366 lines
12 KiB
C
366 lines
12 KiB
C
/* $OpenBSD: file_media.c,v 1.48 2016/01/30 17:21:10 krw Exp $ */
|
|
|
|
/*
|
|
* file_media.c -
|
|
*
|
|
* Written by Eryk Vershen
|
|
*/
|
|
|
|
/*
|
|
* Copyright 1997,1998 by Apple Computer, Inc.
|
|
* All Rights Reserved
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and
|
|
* its documentation for any purpose and without fee is hereby granted,
|
|
* provided that the above copyright notice appears in all copies and
|
|
* that both the copyright notice and this permission notice appear in
|
|
* supporting documentation.
|
|
*
|
|
* APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
|
|
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <sys/param.h> /* DEV_BSIZE */
|
|
#include <sys/queue.h>
|
|
|
|
#include <err.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "partition_map.h"
|
|
#include "file_media.h"
|
|
|
|
struct ddmap_ondisk {
|
|
uint8_t ddBlock[4];
|
|
uint8_t ddSize[2];
|
|
uint8_t ddType[2];
|
|
};
|
|
|
|
struct block0_ondisk {
|
|
uint8_t sbSig[2];
|
|
uint8_t sbBlkSize[2];
|
|
uint8_t sbBlkCount[4];
|
|
uint8_t sbDevType[2];
|
|
uint8_t sbDevId[2];
|
|
uint8_t sbData[4];
|
|
uint8_t sbDrvrCount[2];
|
|
uint8_t sbDDMap[64]; /* ddmap_ondisk[8] */
|
|
uint8_t reserved[430];
|
|
};
|
|
|
|
struct dpme_ondisk {
|
|
uint8_t dpme_signature[2];
|
|
uint8_t dpme_reserved_1[2];
|
|
uint8_t dpme_map_entries[4];
|
|
uint8_t dpme_pblock_start[4];
|
|
uint8_t dpme_pblocks[4];
|
|
uint8_t dpme_name[DPISTRLEN];
|
|
uint8_t dpme_type[DPISTRLEN];
|
|
uint8_t dpme_lblock_start[4];
|
|
uint8_t dpme_lblocks[4];
|
|
uint8_t dpme_flags[4];
|
|
uint8_t dpme_boot_block[4];
|
|
uint8_t dpme_boot_bytes[4];
|
|
uint8_t dpme_load_addr[4];
|
|
uint8_t dpme_reserved_2[4];
|
|
uint8_t dpme_goto_addr[4];
|
|
uint8_t dpme_reserved_3[4];
|
|
uint8_t dpme_checksum[4];
|
|
uint8_t dpme_processor_id[16];
|
|
uint8_t dpme_reserved_4[376];
|
|
};
|
|
|
|
static int read_block(int, uint64_t, void *);
|
|
static int write_block(int, uint64_t, void *);
|
|
|
|
static int
|
|
read_block(int fd, uint64_t sector, void *address)
|
|
{
|
|
ssize_t off;
|
|
|
|
off = pread(fd, address, DEV_BSIZE, sector * DEV_BSIZE);
|
|
if (off == DEV_BSIZE)
|
|
return 1;
|
|
|
|
if (off == 0)
|
|
fprintf(stderr, "end of file encountered");
|
|
else if (off == -1)
|
|
warn("reading file failed");
|
|
else
|
|
fprintf(stderr, "short read");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
write_block(int fd, uint64_t sector, void *address)
|
|
{
|
|
ssize_t off;
|
|
|
|
off = pwrite(fd, address, DEV_BSIZE, sector * DEV_BSIZE);
|
|
if (off == DEV_BSIZE)
|
|
return 1;
|
|
|
|
warn("writing to file failed");
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
read_block0(int fd, struct partition_map *map)
|
|
{
|
|
struct block0_ondisk *block0_ondisk;
|
|
struct ddmap_ondisk ddmap_ondisk;
|
|
int i;
|
|
|
|
block0_ondisk = malloc(sizeof(struct block0_ondisk));
|
|
if (block0_ondisk == NULL)
|
|
errx(1, "No memory to read block0");
|
|
|
|
if (read_block(fd, 0, block0_ondisk) == 0)
|
|
return 0;
|
|
|
|
memcpy(&map->sbSig, block0_ondisk->sbSig,
|
|
sizeof(map->sbSig));
|
|
map->sbSig = betoh16(map->sbSig);
|
|
memcpy(&map->sbBlkSize, block0_ondisk->sbBlkSize,
|
|
sizeof(map->sbBlkSize));
|
|
map->sbBlkSize = betoh16(map->sbBlkSize);
|
|
memcpy(&map->sbBlkCount, block0_ondisk->sbBlkCount,
|
|
sizeof(map->sbBlkCount));
|
|
map->sbBlkCount = betoh32(map->sbBlkCount);
|
|
memcpy(&map->sbDevType, block0_ondisk->sbDevType,
|
|
sizeof(map->sbDevType));
|
|
map->sbDevType = betoh16(map->sbDevType);
|
|
memcpy(&map->sbDevId, block0_ondisk->sbDevId,
|
|
sizeof(map->sbDevId));
|
|
map->sbDevId = betoh16(map->sbDevId);
|
|
memcpy(&map->sbData, block0_ondisk->sbData,
|
|
sizeof(map->sbData));
|
|
map->sbData = betoh32(map->sbData);
|
|
memcpy(&map->sbDrvrCount, block0_ondisk->sbDrvrCount,
|
|
sizeof(map->sbDrvrCount));
|
|
map->sbDrvrCount = betoh16(map->sbDrvrCount);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
memcpy(&ddmap_ondisk,
|
|
map->sbDDMap+i*sizeof(struct ddmap_ondisk),
|
|
sizeof(ddmap_ondisk));
|
|
memcpy(&map->sbDDMap[i].ddBlock, &ddmap_ondisk.ddBlock,
|
|
sizeof(map->sbDDMap[i].ddBlock));
|
|
map->sbDDMap[i].ddBlock =
|
|
betoh32(map->sbDDMap[i].ddBlock);
|
|
memcpy(&map->sbDDMap[i].ddSize, &ddmap_ondisk.ddSize,
|
|
sizeof(map->sbDDMap[i].ddSize));
|
|
map->sbDDMap[i].ddSize = betoh16(map->sbDDMap[i].ddSize);
|
|
memcpy(&map->sbDDMap[i].ddType, &ddmap_ondisk.ddType,
|
|
sizeof(map->sbDDMap[i].ddType));
|
|
map->sbDDMap[i].ddType = betoh32(map->sbDDMap[i].ddType);
|
|
}
|
|
|
|
free(block0_ondisk);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
write_block0(int fd, struct partition_map *map)
|
|
{
|
|
struct block0_ondisk *block0_ondisk;
|
|
struct ddmap_ondisk ddmap_ondisk;
|
|
int i, rslt;
|
|
uint32_t tmp32;
|
|
uint16_t tmp16;
|
|
|
|
block0_ondisk = malloc(sizeof(struct block0_ondisk));
|
|
if (block0_ondisk == NULL)
|
|
errx(1, "No memory to write block 0");
|
|
|
|
tmp16 = htobe16(map->sbSig);
|
|
memcpy(block0_ondisk->sbSig, &tmp16,
|
|
sizeof(block0_ondisk->sbSig));
|
|
tmp16 = htobe16(map->sbBlkSize);
|
|
memcpy(block0_ondisk->sbBlkSize, &tmp16,
|
|
sizeof(block0_ondisk->sbBlkSize));
|
|
tmp32 = htobe32(map->sbBlkCount);
|
|
memcpy(block0_ondisk->sbBlkCount, &tmp32,
|
|
sizeof(block0_ondisk->sbBlkCount));
|
|
tmp16 = htobe16(map->sbDevType);
|
|
memcpy(block0_ondisk->sbDevType, &tmp16,
|
|
sizeof(block0_ondisk->sbDevType));
|
|
tmp16 = htobe16(map->sbDevId);
|
|
memcpy(block0_ondisk->sbDevId, &tmp16,
|
|
sizeof(block0_ondisk->sbDevId));
|
|
tmp32 = htobe32(map->sbData);
|
|
memcpy(block0_ondisk->sbData, &tmp32,
|
|
sizeof(block0_ondisk->sbData));
|
|
tmp16 = htobe16(map->sbDrvrCount);
|
|
memcpy(block0_ondisk->sbDrvrCount, &tmp16,
|
|
sizeof(block0_ondisk->sbDrvrCount));
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
tmp32 = htobe32(map->sbDDMap[i].ddBlock);
|
|
memcpy(ddmap_ondisk.ddBlock, &tmp32,
|
|
sizeof(ddmap_ondisk.ddBlock));
|
|
tmp16 = htobe16(map->sbDDMap[i].ddSize);
|
|
memcpy(&ddmap_ondisk.ddSize, &tmp16,
|
|
sizeof(ddmap_ondisk.ddSize));
|
|
tmp16 = betoh32(map->sbDDMap[i].ddType);
|
|
memcpy(&ddmap_ondisk.ddType, &tmp16,
|
|
sizeof(ddmap_ondisk.ddType));
|
|
memcpy(map->sbDDMap+i*sizeof(struct ddmap_ondisk),
|
|
&ddmap_ondisk, sizeof(ddmap_ondisk));
|
|
}
|
|
|
|
rslt = write_block(fd, 0, block0_ondisk);
|
|
free(block0_ondisk);
|
|
return rslt;
|
|
}
|
|
|
|
int
|
|
read_dpme(int fd, uint64_t sector, struct entry *entry)
|
|
{
|
|
struct dpme_ondisk *dpme_ondisk;
|
|
|
|
dpme_ondisk = malloc(sizeof(struct dpme_ondisk));
|
|
if (dpme_ondisk == NULL)
|
|
errx(1, "No memory to read dpme");
|
|
|
|
if (read_block(fd, sector, dpme_ondisk) == 0)
|
|
return 0;
|
|
|
|
memcpy(&entry->dpme_signature, dpme_ondisk->dpme_signature,
|
|
sizeof(entry->dpme_signature));
|
|
memcpy(&entry->dpme_map_entries, dpme_ondisk->dpme_map_entries,
|
|
sizeof(entry->dpme_map_entries));
|
|
memcpy(&entry->dpme_pblock_start, dpme_ondisk->dpme_pblock_start,
|
|
sizeof(entry->dpme_pblock_start));
|
|
memcpy(&entry->dpme_pblocks, dpme_ondisk->dpme_pblocks,
|
|
sizeof(entry->dpme_pblocks));
|
|
memcpy(&entry->dpme_lblock_start, dpme_ondisk->dpme_lblock_start,
|
|
sizeof(entry->dpme_lblock_start));
|
|
memcpy(&entry->dpme_lblocks, dpme_ondisk->dpme_lblocks,
|
|
sizeof(entry->dpme_lblocks));
|
|
memcpy(&entry->dpme_flags, dpme_ondisk->dpme_flags,
|
|
sizeof(entry->dpme_flags));
|
|
memcpy(&entry->dpme_boot_block, dpme_ondisk->dpme_boot_block,
|
|
sizeof(entry->dpme_boot_block));
|
|
memcpy(&entry->dpme_boot_bytes, dpme_ondisk->dpme_boot_bytes,
|
|
sizeof(entry->dpme_boot_bytes));
|
|
memcpy(&entry->dpme_load_addr, dpme_ondisk->dpme_load_addr,
|
|
sizeof(entry->dpme_load_addr));
|
|
memcpy(&entry->dpme_goto_addr, dpme_ondisk->dpme_goto_addr,
|
|
sizeof(entry->dpme_goto_addr));
|
|
memcpy(&entry->dpme_checksum, dpme_ondisk->dpme_checksum,
|
|
sizeof(entry->dpme_checksum));
|
|
|
|
entry->dpme_signature = betoh16(entry->dpme_signature);
|
|
entry->dpme_map_entries = betoh32(entry->dpme_map_entries);
|
|
entry->dpme_pblock_start = betoh32(entry->dpme_pblock_start);
|
|
entry->dpme_pblocks = betoh32(entry->dpme_pblocks);
|
|
entry->dpme_lblock_start = betoh32(entry->dpme_lblock_start);
|
|
entry->dpme_lblocks = betoh32(entry->dpme_lblocks);
|
|
entry->dpme_flags = betoh32(entry->dpme_flags);
|
|
entry->dpme_boot_block = betoh32(entry->dpme_boot_block);
|
|
entry->dpme_boot_bytes = betoh32(entry->dpme_boot_bytes);
|
|
entry->dpme_load_addr = betoh32(entry->dpme_load_addr);
|
|
entry->dpme_goto_addr = betoh32(entry->dpme_goto_addr);
|
|
entry->dpme_checksum = betoh32(entry->dpme_checksum);
|
|
|
|
memcpy(entry->dpme_reserved_1, dpme_ondisk->dpme_reserved_1,
|
|
sizeof(entry->dpme_reserved_1));
|
|
memcpy(entry->dpme_reserved_2, dpme_ondisk->dpme_reserved_2,
|
|
sizeof(entry->dpme_reserved_2));
|
|
memcpy(entry->dpme_reserved_3, dpme_ondisk->dpme_reserved_3,
|
|
sizeof(entry->dpme_reserved_3));
|
|
memcpy(entry->dpme_reserved_4, dpme_ondisk->dpme_reserved_4,
|
|
sizeof(entry->dpme_reserved_4));
|
|
|
|
strlcpy(entry->dpme_name, dpme_ondisk->dpme_name,
|
|
sizeof(entry->dpme_name));
|
|
strlcpy(entry->dpme_type, dpme_ondisk->dpme_type,
|
|
sizeof(entry->dpme_type));
|
|
strlcpy(entry->dpme_processor_id, dpme_ondisk->dpme_processor_id,
|
|
sizeof(entry->dpme_processor_id));
|
|
|
|
free(dpme_ondisk);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
write_dpme(int fd, uint64_t sector, struct entry *entry)
|
|
{
|
|
struct dpme_ondisk *dpme_ondisk;
|
|
int rslt;
|
|
uint32_t tmp32;
|
|
uint16_t tmp16;
|
|
|
|
dpme_ondisk = malloc(sizeof(struct dpme_ondisk));
|
|
if (dpme_ondisk == NULL)
|
|
errx(1, "No memory to write dpme");
|
|
|
|
memcpy(dpme_ondisk->dpme_name, entry->dpme_name,
|
|
sizeof(dpme_ondisk->dpme_name));
|
|
memcpy(dpme_ondisk->dpme_type, entry->dpme_type,
|
|
sizeof(dpme_ondisk->dpme_type));
|
|
memcpy(dpme_ondisk->dpme_processor_id, entry->dpme_processor_id,
|
|
sizeof(dpme_ondisk->dpme_processor_id));
|
|
|
|
memcpy(dpme_ondisk->dpme_reserved_1, entry->dpme_reserved_1,
|
|
sizeof(dpme_ondisk->dpme_reserved_1));
|
|
memcpy(dpme_ondisk->dpme_reserved_2, entry->dpme_reserved_2,
|
|
sizeof(dpme_ondisk->dpme_reserved_2));
|
|
memcpy(dpme_ondisk->dpme_reserved_3, entry->dpme_reserved_3,
|
|
sizeof(dpme_ondisk->dpme_reserved_3));
|
|
memcpy(dpme_ondisk->dpme_reserved_4, entry->dpme_reserved_4,
|
|
sizeof(dpme_ondisk->dpme_reserved_4));
|
|
|
|
tmp16 = htobe16(entry->dpme_signature);
|
|
memcpy(dpme_ondisk->dpme_signature, &tmp16,
|
|
sizeof(dpme_ondisk->dpme_signature));
|
|
tmp32 = htobe32(entry->dpme_map_entries);
|
|
memcpy(dpme_ondisk->dpme_map_entries, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_map_entries));
|
|
tmp32 = htobe32(entry->dpme_pblock_start);
|
|
memcpy(dpme_ondisk->dpme_pblock_start, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_pblock_start));
|
|
tmp32 = htobe32(entry->dpme_pblocks);
|
|
memcpy(dpme_ondisk->dpme_pblocks, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_pblocks));
|
|
tmp32 = htobe32(entry->dpme_lblock_start);
|
|
memcpy(dpme_ondisk->dpme_lblock_start, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_lblock_start));
|
|
tmp32 = betoh32(entry->dpme_lblocks);
|
|
memcpy(dpme_ondisk->dpme_lblocks, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_lblocks));
|
|
tmp32 = betoh32(entry->dpme_flags);
|
|
memcpy(dpme_ondisk->dpme_flags, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_flags));
|
|
tmp32 = htobe32(entry->dpme_boot_block);
|
|
memcpy(dpme_ondisk->dpme_boot_block, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_boot_block));
|
|
tmp32 = htobe32(entry->dpme_boot_bytes);
|
|
memcpy(dpme_ondisk->dpme_boot_bytes, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_boot_bytes));
|
|
tmp32 = betoh32(entry->dpme_load_addr);
|
|
memcpy(dpme_ondisk->dpme_load_addr, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_load_addr));
|
|
tmp32 = betoh32(entry->dpme_goto_addr);
|
|
memcpy(dpme_ondisk->dpme_goto_addr, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_goto_addr));
|
|
tmp32 = betoh32(entry->dpme_checksum);
|
|
memcpy(dpme_ondisk->dpme_checksum, &tmp32,
|
|
sizeof(dpme_ondisk->dpme_checksum));
|
|
|
|
rslt = write_block(fd, sector, dpme_ondisk);
|
|
free(dpme_ondisk);
|
|
return rslt;
|
|
}
|