1 /* $OpenBSD: file_media.c,v 1.48 2016/01/30 17:21:10 krw Exp $ */ 2 3 /* 4 * file_media.c - 5 * 6 * Written by Eryk Vershen 7 */ 8 9 /* 10 * Copyright 1997,1998 by Apple Computer, Inc. 11 * All Rights Reserved 12 * 13 * Permission to use, copy, modify, and distribute this software and 14 * its documentation for any purpose and without fee is hereby granted, 15 * provided that the above copyright notice appears in all copies and 16 * that both the copyright notice and this permission notice appear in 17 * supporting documentation. 18 * 19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE. 22 * 23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 #include <sys/param.h> /* DEV_BSIZE */ 31 #include <sys/queue.h> 32 33 #include <err.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include "partition_map.h" 40 #include "file_media.h" 41 42 struct ddmap_ondisk { 43 uint8_t ddBlock[4]; 44 uint8_t ddSize[2]; 45 uint8_t ddType[2]; 46 }; 47 48 struct block0_ondisk { 49 uint8_t sbSig[2]; 50 uint8_t sbBlkSize[2]; 51 uint8_t sbBlkCount[4]; 52 uint8_t sbDevType[2]; 53 uint8_t sbDevId[2]; 54 uint8_t sbData[4]; 55 uint8_t sbDrvrCount[2]; 56 uint8_t sbDDMap[64]; /* ddmap_ondisk[8] */ 57 uint8_t reserved[430]; 58 }; 59 60 struct dpme_ondisk { 61 uint8_t dpme_signature[2]; 62 uint8_t dpme_reserved_1[2]; 63 uint8_t dpme_map_entries[4]; 64 uint8_t dpme_pblock_start[4]; 65 uint8_t dpme_pblocks[4]; 66 uint8_t dpme_name[DPISTRLEN]; 67 uint8_t dpme_type[DPISTRLEN]; 68 uint8_t dpme_lblock_start[4]; 69 uint8_t dpme_lblocks[4]; 70 uint8_t dpme_flags[4]; 71 uint8_t dpme_boot_block[4]; 72 uint8_t dpme_boot_bytes[4]; 73 uint8_t dpme_load_addr[4]; 74 uint8_t dpme_reserved_2[4]; 75 uint8_t dpme_goto_addr[4]; 76 uint8_t dpme_reserved_3[4]; 77 uint8_t dpme_checksum[4]; 78 uint8_t dpme_processor_id[16]; 79 uint8_t dpme_reserved_4[376]; 80 }; 81 82 static int read_block(int, uint64_t, void *); 83 static int write_block(int, uint64_t, void *); 84 85 static int 86 read_block(int fd, uint64_t sector, void *address) 87 { 88 ssize_t off; 89 90 off = pread(fd, address, DEV_BSIZE, sector * DEV_BSIZE); 91 if (off == DEV_BSIZE) 92 return 1; 93 94 if (off == 0) 95 fprintf(stderr, "end of file encountered"); 96 else if (off == -1) 97 warn("reading file failed"); 98 else 99 fprintf(stderr, "short read"); 100 101 return 0; 102 } 103 104 static int 105 write_block(int fd, uint64_t sector, void *address) 106 { 107 ssize_t off; 108 109 off = pwrite(fd, address, DEV_BSIZE, sector * DEV_BSIZE); 110 if (off == DEV_BSIZE) 111 return 1; 112 113 warn("writing to file failed"); 114 return 0; 115 } 116 117 int 118 read_block0(int fd, struct partition_map *map) 119 { 120 struct block0_ondisk *block0_ondisk; 121 struct ddmap_ondisk ddmap_ondisk; 122 int i; 123 124 block0_ondisk = malloc(sizeof(struct block0_ondisk)); 125 if (block0_ondisk == NULL) 126 errx(1, "No memory to read block0"); 127 128 if (read_block(fd, 0, block0_ondisk) == 0) 129 return 0; 130 131 memcpy(&map->sbSig, block0_ondisk->sbSig, 132 sizeof(map->sbSig)); 133 map->sbSig = betoh16(map->sbSig); 134 memcpy(&map->sbBlkSize, block0_ondisk->sbBlkSize, 135 sizeof(map->sbBlkSize)); 136 map->sbBlkSize = betoh16(map->sbBlkSize); 137 memcpy(&map->sbBlkCount, block0_ondisk->sbBlkCount, 138 sizeof(map->sbBlkCount)); 139 map->sbBlkCount = betoh32(map->sbBlkCount); 140 memcpy(&map->sbDevType, block0_ondisk->sbDevType, 141 sizeof(map->sbDevType)); 142 map->sbDevType = betoh16(map->sbDevType); 143 memcpy(&map->sbDevId, block0_ondisk->sbDevId, 144 sizeof(map->sbDevId)); 145 map->sbDevId = betoh16(map->sbDevId); 146 memcpy(&map->sbData, block0_ondisk->sbData, 147 sizeof(map->sbData)); 148 map->sbData = betoh32(map->sbData); 149 memcpy(&map->sbDrvrCount, block0_ondisk->sbDrvrCount, 150 sizeof(map->sbDrvrCount)); 151 map->sbDrvrCount = betoh16(map->sbDrvrCount); 152 153 for (i = 0; i < 8; i++) { 154 memcpy(&ddmap_ondisk, 155 map->sbDDMap+i*sizeof(struct ddmap_ondisk), 156 sizeof(ddmap_ondisk)); 157 memcpy(&map->sbDDMap[i].ddBlock, &ddmap_ondisk.ddBlock, 158 sizeof(map->sbDDMap[i].ddBlock)); 159 map->sbDDMap[i].ddBlock = 160 betoh32(map->sbDDMap[i].ddBlock); 161 memcpy(&map->sbDDMap[i].ddSize, &ddmap_ondisk.ddSize, 162 sizeof(map->sbDDMap[i].ddSize)); 163 map->sbDDMap[i].ddSize = betoh16(map->sbDDMap[i].ddSize); 164 memcpy(&map->sbDDMap[i].ddType, &ddmap_ondisk.ddType, 165 sizeof(map->sbDDMap[i].ddType)); 166 map->sbDDMap[i].ddType = betoh32(map->sbDDMap[i].ddType); 167 } 168 169 free(block0_ondisk); 170 return 1; 171 } 172 173 int 174 write_block0(int fd, struct partition_map *map) 175 { 176 struct block0_ondisk *block0_ondisk; 177 struct ddmap_ondisk ddmap_ondisk; 178 int i, rslt; 179 uint32_t tmp32; 180 uint16_t tmp16; 181 182 block0_ondisk = malloc(sizeof(struct block0_ondisk)); 183 if (block0_ondisk == NULL) 184 errx(1, "No memory to write block 0"); 185 186 tmp16 = htobe16(map->sbSig); 187 memcpy(block0_ondisk->sbSig, &tmp16, 188 sizeof(block0_ondisk->sbSig)); 189 tmp16 = htobe16(map->sbBlkSize); 190 memcpy(block0_ondisk->sbBlkSize, &tmp16, 191 sizeof(block0_ondisk->sbBlkSize)); 192 tmp32 = htobe32(map->sbBlkCount); 193 memcpy(block0_ondisk->sbBlkCount, &tmp32, 194 sizeof(block0_ondisk->sbBlkCount)); 195 tmp16 = htobe16(map->sbDevType); 196 memcpy(block0_ondisk->sbDevType, &tmp16, 197 sizeof(block0_ondisk->sbDevType)); 198 tmp16 = htobe16(map->sbDevId); 199 memcpy(block0_ondisk->sbDevId, &tmp16, 200 sizeof(block0_ondisk->sbDevId)); 201 tmp32 = htobe32(map->sbData); 202 memcpy(block0_ondisk->sbData, &tmp32, 203 sizeof(block0_ondisk->sbData)); 204 tmp16 = htobe16(map->sbDrvrCount); 205 memcpy(block0_ondisk->sbDrvrCount, &tmp16, 206 sizeof(block0_ondisk->sbDrvrCount)); 207 208 for (i = 0; i < 8; i++) { 209 tmp32 = htobe32(map->sbDDMap[i].ddBlock); 210 memcpy(ddmap_ondisk.ddBlock, &tmp32, 211 sizeof(ddmap_ondisk.ddBlock)); 212 tmp16 = htobe16(map->sbDDMap[i].ddSize); 213 memcpy(&ddmap_ondisk.ddSize, &tmp16, 214 sizeof(ddmap_ondisk.ddSize)); 215 tmp16 = betoh32(map->sbDDMap[i].ddType); 216 memcpy(&ddmap_ondisk.ddType, &tmp16, 217 sizeof(ddmap_ondisk.ddType)); 218 memcpy(map->sbDDMap+i*sizeof(struct ddmap_ondisk), 219 &ddmap_ondisk, sizeof(ddmap_ondisk)); 220 } 221 222 rslt = write_block(fd, 0, block0_ondisk); 223 free(block0_ondisk); 224 return rslt; 225 } 226 227 int 228 read_dpme(int fd, uint64_t sector, struct entry *entry) 229 { 230 struct dpme_ondisk *dpme_ondisk; 231 232 dpme_ondisk = malloc(sizeof(struct dpme_ondisk)); 233 if (dpme_ondisk == NULL) 234 errx(1, "No memory to read dpme"); 235 236 if (read_block(fd, sector, dpme_ondisk) == 0) 237 return 0; 238 239 memcpy(&entry->dpme_signature, dpme_ondisk->dpme_signature, 240 sizeof(entry->dpme_signature)); 241 memcpy(&entry->dpme_map_entries, dpme_ondisk->dpme_map_entries, 242 sizeof(entry->dpme_map_entries)); 243 memcpy(&entry->dpme_pblock_start, dpme_ondisk->dpme_pblock_start, 244 sizeof(entry->dpme_pblock_start)); 245 memcpy(&entry->dpme_pblocks, dpme_ondisk->dpme_pblocks, 246 sizeof(entry->dpme_pblocks)); 247 memcpy(&entry->dpme_lblock_start, dpme_ondisk->dpme_lblock_start, 248 sizeof(entry->dpme_lblock_start)); 249 memcpy(&entry->dpme_lblocks, dpme_ondisk->dpme_lblocks, 250 sizeof(entry->dpme_lblocks)); 251 memcpy(&entry->dpme_flags, dpme_ondisk->dpme_flags, 252 sizeof(entry->dpme_flags)); 253 memcpy(&entry->dpme_boot_block, dpme_ondisk->dpme_boot_block, 254 sizeof(entry->dpme_boot_block)); 255 memcpy(&entry->dpme_boot_bytes, dpme_ondisk->dpme_boot_bytes, 256 sizeof(entry->dpme_boot_bytes)); 257 memcpy(&entry->dpme_load_addr, dpme_ondisk->dpme_load_addr, 258 sizeof(entry->dpme_load_addr)); 259 memcpy(&entry->dpme_goto_addr, dpme_ondisk->dpme_goto_addr, 260 sizeof(entry->dpme_goto_addr)); 261 memcpy(&entry->dpme_checksum, dpme_ondisk->dpme_checksum, 262 sizeof(entry->dpme_checksum)); 263 264 entry->dpme_signature = betoh16(entry->dpme_signature); 265 entry->dpme_map_entries = betoh32(entry->dpme_map_entries); 266 entry->dpme_pblock_start = betoh32(entry->dpme_pblock_start); 267 entry->dpme_pblocks = betoh32(entry->dpme_pblocks); 268 entry->dpme_lblock_start = betoh32(entry->dpme_lblock_start); 269 entry->dpme_lblocks = betoh32(entry->dpme_lblocks); 270 entry->dpme_flags = betoh32(entry->dpme_flags); 271 entry->dpme_boot_block = betoh32(entry->dpme_boot_block); 272 entry->dpme_boot_bytes = betoh32(entry->dpme_boot_bytes); 273 entry->dpme_load_addr = betoh32(entry->dpme_load_addr); 274 entry->dpme_goto_addr = betoh32(entry->dpme_goto_addr); 275 entry->dpme_checksum = betoh32(entry->dpme_checksum); 276 277 memcpy(entry->dpme_reserved_1, dpme_ondisk->dpme_reserved_1, 278 sizeof(entry->dpme_reserved_1)); 279 memcpy(entry->dpme_reserved_2, dpme_ondisk->dpme_reserved_2, 280 sizeof(entry->dpme_reserved_2)); 281 memcpy(entry->dpme_reserved_3, dpme_ondisk->dpme_reserved_3, 282 sizeof(entry->dpme_reserved_3)); 283 memcpy(entry->dpme_reserved_4, dpme_ondisk->dpme_reserved_4, 284 sizeof(entry->dpme_reserved_4)); 285 286 strlcpy(entry->dpme_name, dpme_ondisk->dpme_name, 287 sizeof(entry->dpme_name)); 288 strlcpy(entry->dpme_type, dpme_ondisk->dpme_type, 289 sizeof(entry->dpme_type)); 290 strlcpy(entry->dpme_processor_id, dpme_ondisk->dpme_processor_id, 291 sizeof(entry->dpme_processor_id)); 292 293 free(dpme_ondisk); 294 return 1; 295 } 296 297 int 298 write_dpme(int fd, uint64_t sector, struct entry *entry) 299 { 300 struct dpme_ondisk *dpme_ondisk; 301 int rslt; 302 uint32_t tmp32; 303 uint16_t tmp16; 304 305 dpme_ondisk = malloc(sizeof(struct dpme_ondisk)); 306 if (dpme_ondisk == NULL) 307 errx(1, "No memory to write dpme"); 308 309 memcpy(dpme_ondisk->dpme_name, entry->dpme_name, 310 sizeof(dpme_ondisk->dpme_name)); 311 memcpy(dpme_ondisk->dpme_type, entry->dpme_type, 312 sizeof(dpme_ondisk->dpme_type)); 313 memcpy(dpme_ondisk->dpme_processor_id, entry->dpme_processor_id, 314 sizeof(dpme_ondisk->dpme_processor_id)); 315 316 memcpy(dpme_ondisk->dpme_reserved_1, entry->dpme_reserved_1, 317 sizeof(dpme_ondisk->dpme_reserved_1)); 318 memcpy(dpme_ondisk->dpme_reserved_2, entry->dpme_reserved_2, 319 sizeof(dpme_ondisk->dpme_reserved_2)); 320 memcpy(dpme_ondisk->dpme_reserved_3, entry->dpme_reserved_3, 321 sizeof(dpme_ondisk->dpme_reserved_3)); 322 memcpy(dpme_ondisk->dpme_reserved_4, entry->dpme_reserved_4, 323 sizeof(dpme_ondisk->dpme_reserved_4)); 324 325 tmp16 = htobe16(entry->dpme_signature); 326 memcpy(dpme_ondisk->dpme_signature, &tmp16, 327 sizeof(dpme_ondisk->dpme_signature)); 328 tmp32 = htobe32(entry->dpme_map_entries); 329 memcpy(dpme_ondisk->dpme_map_entries, &tmp32, 330 sizeof(dpme_ondisk->dpme_map_entries)); 331 tmp32 = htobe32(entry->dpme_pblock_start); 332 memcpy(dpme_ondisk->dpme_pblock_start, &tmp32, 333 sizeof(dpme_ondisk->dpme_pblock_start)); 334 tmp32 = htobe32(entry->dpme_pblocks); 335 memcpy(dpme_ondisk->dpme_pblocks, &tmp32, 336 sizeof(dpme_ondisk->dpme_pblocks)); 337 tmp32 = htobe32(entry->dpme_lblock_start); 338 memcpy(dpme_ondisk->dpme_lblock_start, &tmp32, 339 sizeof(dpme_ondisk->dpme_lblock_start)); 340 tmp32 = betoh32(entry->dpme_lblocks); 341 memcpy(dpme_ondisk->dpme_lblocks, &tmp32, 342 sizeof(dpme_ondisk->dpme_lblocks)); 343 tmp32 = betoh32(entry->dpme_flags); 344 memcpy(dpme_ondisk->dpme_flags, &tmp32, 345 sizeof(dpme_ondisk->dpme_flags)); 346 tmp32 = htobe32(entry->dpme_boot_block); 347 memcpy(dpme_ondisk->dpme_boot_block, &tmp32, 348 sizeof(dpme_ondisk->dpme_boot_block)); 349 tmp32 = htobe32(entry->dpme_boot_bytes); 350 memcpy(dpme_ondisk->dpme_boot_bytes, &tmp32, 351 sizeof(dpme_ondisk->dpme_boot_bytes)); 352 tmp32 = betoh32(entry->dpme_load_addr); 353 memcpy(dpme_ondisk->dpme_load_addr, &tmp32, 354 sizeof(dpme_ondisk->dpme_load_addr)); 355 tmp32 = betoh32(entry->dpme_goto_addr); 356 memcpy(dpme_ondisk->dpme_goto_addr, &tmp32, 357 sizeof(dpme_ondisk->dpme_goto_addr)); 358 tmp32 = betoh32(entry->dpme_checksum); 359 memcpy(dpme_ondisk->dpme_checksum, &tmp32, 360 sizeof(dpme_ondisk->dpme_checksum)); 361 362 rslt = write_block(fd, sector, dpme_ondisk); 363 free(dpme_ondisk); 364 return rslt; 365 } 366