File: | src/usr.sbin/makefs/cd9660/cd9660_eltorito.c |
Warning: | line 139, column 3 Value stored to 'mode_msg' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: cd9660_eltorito.c,v 1.15 2021/07/12 15:09:21 beck Exp $ */ |
2 | /* $NetBSD: cd9660_eltorito.c,v 1.20 2013/01/28 21:03:28 christos Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan |
6 | * Perez-Rathke and Ram Vedam. All rights reserved. |
7 | * |
8 | * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys, |
9 | * Alan Perez-Rathke and Ram Vedam. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or |
12 | * without modification, are permitted provided that the following |
13 | * conditions are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above |
17 | * copyright notice, this list of conditions and the following |
18 | * disclaimer in the documentation and/or other materials provided |
19 | * with the distribution. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN |
22 | * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
25 | * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN |
26 | * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT, |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
29 | * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
31 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
33 | * OF SUCH DAMAGE. |
34 | */ |
35 | |
36 | |
37 | #include "cd9660.h" |
38 | #include "cd9660_eltorito.h" |
39 | #include <inttypes.h> |
40 | |
41 | /* |
42 | * Partition Status Information from Apple Tech Note 1189 |
43 | */ |
44 | #define APPLE_PS_VALID0x00000001 0x00000001 /* Entry is valid */ |
45 | #define APPLE_PS_ALLOCATED0x00000002 0x00000002 /* Entry is allocated */ |
46 | #define APPLE_PS_READABLE0x00000010 0x00000010 /* Entry is readable */ |
47 | #define APPLE_PS_WRITABLE0x00000020 0x00000020 /* Entry is writable */ |
48 | |
49 | #ifdef DEBUG |
50 | #define ELTORITO_DPRINTF(__x) printf __x |
51 | #else |
52 | #define ELTORITO_DPRINTF(__x) |
53 | #endif |
54 | |
55 | static struct boot_catalog_entry *cd9660_init_boot_catalog_entry(void); |
56 | static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char); |
57 | static struct boot_catalog_entry *cd9660_boot_setup_default_entry( |
58 | struct cd9660_boot_image *); |
59 | static struct boot_catalog_entry *cd9660_boot_setup_section_head(char); |
60 | static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char); |
61 | #if 0 |
62 | static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *); |
63 | #endif |
64 | |
65 | int |
66 | cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info) |
67 | { |
68 | struct stat stbuf; |
69 | const char *mode_msg; |
70 | char *temp; |
71 | char *sysname; |
72 | char *filename; |
73 | struct cd9660_boot_image *new_image, *tmp_image; |
74 | |
75 | assert(boot_info != NULL)((boot_info != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660/cd9660_eltorito.c" , 75, __func__, "boot_info != NULL")); |
76 | |
77 | if (*boot_info == '\0') { |
78 | warnx("Error: Boot disk information must be in the " |
79 | "format 'system;filename'"); |
80 | return 0; |
81 | } |
82 | |
83 | /* First decode the boot information */ |
84 | temp = estrdup(boot_info); |
85 | |
86 | sysname = temp; |
87 | filename = strchr(sysname, ';'); |
88 | if (filename == NULL((void *)0)) { |
89 | warnx("supply boot disk information in the format " |
90 | "'system;filename'"); |
91 | free(temp); |
92 | return 0; |
93 | } |
94 | |
95 | *filename++ = '\0'; |
96 | |
97 | new_image = ecalloc(1, sizeof(*new_image)); |
98 | new_image->loadSegment = 0; /* default for now */ |
99 | |
100 | /* Decode System */ |
101 | if (strcmp(sysname, "i386") == 0) |
102 | new_image->system = ET_SYS_X860; |
103 | else if (strcmp(sysname, "powerpc") == 0) |
104 | new_image->system = ET_SYS_PPC1; |
105 | else if (strcmp(sysname, "macppc") == 0) |
106 | new_image->system = ET_SYS_MAC2; |
107 | else if (strcmp(sysname, "efi") == 0) |
108 | new_image->system = ET_SYS_EFI0xef; |
109 | else { |
110 | warnx("boot disk system must be " |
111 | "i386, macppc, powerpc, or efi"); |
112 | free(temp); |
113 | free(new_image); |
114 | return 0; |
115 | } |
116 | |
117 | |
118 | new_image->filename = estrdup(filename); |
119 | |
120 | free(temp); |
121 | |
122 | if (unveil(new_image->filename, "r") == -1) |
123 | err(1, "unveil %s", new_image->filename); |
124 | /* Get information about the file */ |
125 | if (lstat(new_image->filename, &stbuf) == -1) |
126 | err(1, "%s: lstat(\"%s\")", __func__, new_image->filename); |
127 | |
128 | switch (stbuf.st_size) { |
129 | case 1440 * 1024: |
130 | new_image->targetMode = ET_MEDIA_144FDD2; |
131 | mode_msg = "Assigned boot image to 1.44 emulation mode"; |
132 | break; |
133 | case 1200 * 1024: |
134 | new_image->targetMode = ET_MEDIA_12FDD1; |
135 | mode_msg = "Assigned boot image to 1.2 emulation mode"; |
136 | break; |
137 | case 2880 * 1024: |
138 | new_image->targetMode = ET_MEDIA_288FDD3; |
139 | mode_msg = "Assigned boot image to 2.88 emulation mode"; |
Value stored to 'mode_msg' is never read | |
140 | break; |
141 | default: |
142 | new_image->targetMode = ET_MEDIA_NOEM0; |
143 | mode_msg = "Assigned boot image to no emulation mode"; |
144 | break; |
145 | } |
146 | |
147 | new_image->size = stbuf.st_size; |
148 | new_image->num_sectors = |
149 | howmany(new_image->size, diskStructure->sectorSize)(((new_image->size) + ((diskStructure->sectorSize) - 1) ) / (diskStructure->sectorSize)) * |
150 | howmany(diskStructure->sectorSize, 512)(((diskStructure->sectorSize) + ((512) - 1)) / (512)); |
151 | new_image->sector = -1; |
152 | /* Bootable by default */ |
153 | new_image->bootable = ET_BOOTABLE0x88; |
154 | /* Add boot disk */ |
155 | |
156 | /* Group images for the same platform together. */ |
157 | TAILQ_FOREACH(tmp_image, &diskStructure->boot_images, image_list)for((tmp_image) = ((&diskStructure->boot_images)->tqh_first ); (tmp_image) != ((void *)0); (tmp_image) = ((tmp_image)-> image_list.tqe_next)) { |
158 | if (tmp_image->system != new_image->system) |
159 | break; |
160 | } |
161 | |
162 | if (tmp_image == NULL((void *)0)) |
163 | TAILQ_INSERT_HEAD(&diskStructure->boot_images, new_image,do { if (((new_image)->image_list.tqe_next = (&diskStructure ->boot_images)->tqh_first) != ((void *)0)) (&diskStructure ->boot_images)->tqh_first->image_list.tqe_prev = & (new_image)->image_list.tqe_next; else (&diskStructure ->boot_images)->tqh_last = &(new_image)->image_list .tqe_next; (&diskStructure->boot_images)->tqh_first = (new_image); (new_image)->image_list.tqe_prev = &(& diskStructure->boot_images)->tqh_first; } while (0) |
164 | image_list)do { if (((new_image)->image_list.tqe_next = (&diskStructure ->boot_images)->tqh_first) != ((void *)0)) (&diskStructure ->boot_images)->tqh_first->image_list.tqe_prev = & (new_image)->image_list.tqe_next; else (&diskStructure ->boot_images)->tqh_last = &(new_image)->image_list .tqe_next; (&diskStructure->boot_images)->tqh_first = (new_image); (new_image)->image_list.tqe_prev = &(& diskStructure->boot_images)->tqh_first; } while (0); |
165 | else |
166 | TAILQ_INSERT_AFTER(&diskStructure->boot_images, tmp_image,do { if (((new_image)->image_list.tqe_next = (tmp_image)-> image_list.tqe_next) != ((void *)0)) (new_image)->image_list .tqe_next->image_list.tqe_prev = &(new_image)->image_list .tqe_next; else (&diskStructure->boot_images)->tqh_last = &(new_image)->image_list.tqe_next; (tmp_image)-> image_list.tqe_next = (new_image); (new_image)->image_list .tqe_prev = &(tmp_image)->image_list.tqe_next; } while (0) |
167 | new_image, image_list)do { if (((new_image)->image_list.tqe_next = (tmp_image)-> image_list.tqe_next) != ((void *)0)) (new_image)->image_list .tqe_next->image_list.tqe_prev = &(new_image)->image_list .tqe_next; else (&diskStructure->boot_images)->tqh_last = &(new_image)->image_list.tqe_next; (tmp_image)-> image_list.tqe_next = (new_image); (new_image)->image_list .tqe_prev = &(tmp_image)->image_list.tqe_next; } while (0); |
168 | |
169 | new_image->serialno = diskStructure->image_serialno++; |
170 | |
171 | /* TODO : Need to do anything about the boot image in the tree? */ |
172 | diskStructure->is_bootable = 1; |
173 | |
174 | return 1; |
175 | } |
176 | |
177 | int |
178 | cd9660_eltorito_add_boot_option(iso9660_disk *diskStructure, |
179 | const char *option_string, const char *value) |
180 | { |
181 | char *eptr; |
182 | struct cd9660_boot_image *image; |
183 | |
184 | assert(option_string != NULL)((option_string != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660/cd9660_eltorito.c" , 184, __func__, "option_string != NULL")); |
185 | |
186 | /* Find the last image added */ |
187 | TAILQ_FOREACH(image, &diskStructure->boot_images, image_list)for((image) = ((&diskStructure->boot_images)->tqh_first ); (image) != ((void *)0); (image) = ((image)->image_list. tqe_next)) { |
188 | if (image->serialno + 1 == diskStructure->image_serialno) |
189 | break; |
190 | } |
191 | if (image == NULL((void *)0)) |
192 | errx(1, "Attempted to add boot option, " |
193 | "but no boot images have been specified"); |
194 | |
195 | if (strcmp(option_string, "no-emul-boot") == 0) { |
196 | image->targetMode = ET_MEDIA_NOEM0; |
197 | } else if (strcmp(option_string, "no-boot") == 0) { |
198 | image->bootable = ET_NOT_BOOTABLE0; |
199 | } else if (strcmp(option_string, "hard-disk-boot") == 0) { |
200 | image->targetMode = ET_MEDIA_HDD4; |
201 | } else if (strcmp(option_string, "boot-load-segment") == 0) { |
202 | image->loadSegment = strtoul(value, &eptr, 16); |
203 | if (eptr == value || *eptr != '\0' || errno(*__errno()) != ERANGE34) { |
204 | warn("%s: strtoul", __func__); |
205 | return 0; |
206 | } |
207 | } else { |
208 | return 0; |
209 | } |
210 | return 1; |
211 | } |
212 | |
213 | static struct boot_catalog_entry * |
214 | cd9660_init_boot_catalog_entry(void) |
215 | { |
216 | return ecalloc(1, sizeof(struct boot_catalog_entry)); |
217 | } |
218 | |
219 | static struct boot_catalog_entry * |
220 | cd9660_boot_setup_validation_entry(char sys) |
221 | { |
222 | struct boot_catalog_entry *entry; |
223 | boot_catalog_validation_entry *ve; |
224 | int16_t checksum; |
225 | unsigned char *csptr; |
226 | size_t i; |
227 | entry = cd9660_init_boot_catalog_entry(); |
228 | |
229 | entry->entry_type = ET_ENTRY_VE1; |
230 | ve = &entry->entry_data.VE; |
231 | |
232 | ve->header_id[0] = 1; |
233 | ve->platform_id[0] = sys; |
234 | ve->key[0] = 0x55; |
235 | ve->key[1] = 0xAA; |
236 | |
237 | /* Calculate checksum */ |
238 | checksum = 0; |
239 | cd9660_721(0, ve->checksum); |
240 | csptr = (unsigned char*)ve; |
241 | for (i = 0; i < sizeof(*ve); i += 2) { |
242 | checksum += (int16_t)csptr[i]; |
243 | checksum += 256 * (int16_t)csptr[i + 1]; |
244 | } |
245 | checksum = -checksum; |
246 | cd9660_721(checksum, ve->checksum); |
247 | |
248 | ELTORITO_DPRINTF(("%s: header_id %d, platform_id %d, key[0] %d, key[1] %d, " |
249 | "checksum %04x\n", __func__, ve->header_id[0], ve->platform_id[0], |
250 | ve->key[0], ve->key[1], checksum)); |
251 | return entry; |
252 | } |
253 | |
254 | static struct boot_catalog_entry * |
255 | cd9660_boot_setup_default_entry(struct cd9660_boot_image *disk) |
256 | { |
257 | struct boot_catalog_entry *default_entry; |
258 | boot_catalog_initial_entry *ie; |
259 | |
260 | default_entry = cd9660_init_boot_catalog_entry(); |
261 | if (default_entry == NULL((void *)0)) |
262 | return NULL((void *)0); |
263 | |
264 | default_entry->entry_type = ET_ENTRY_IE2; |
265 | ie = &default_entry->entry_data.IE; |
266 | |
267 | ie->boot_indicator[0] = disk->bootable; |
268 | ie->media_type[0] = disk->targetMode; |
269 | cd9660_721(disk->loadSegment, ie->load_segment); |
270 | ie->system_type[0] = disk->system; |
271 | cd9660_721(disk->num_sectors, ie->sector_count); |
272 | cd9660_731(disk->sector, ie->load_rba); |
273 | |
274 | ELTORITO_DPRINTF(("%s: boot indicator %d, media type %d, " |
275 | "load segment %04x, system type %d, sector count %d, " |
276 | "load rba %d\n", __func__, ie->boot_indicator[0], |
277 | ie->media_type[0], disk->loadSegment, ie->system_type[0], |
278 | disk->num_sectors, disk->sector)); |
279 | return default_entry; |
280 | } |
281 | |
282 | static struct boot_catalog_entry * |
283 | cd9660_boot_setup_section_head(char platform) |
284 | { |
285 | struct boot_catalog_entry *entry; |
286 | boot_catalog_section_header *sh; |
287 | |
288 | entry = cd9660_init_boot_catalog_entry(); |
289 | if (entry == NULL((void *)0)) |
290 | return NULL((void *)0); |
291 | |
292 | entry->entry_type = ET_ENTRY_SH3; |
293 | sh = &entry->entry_data.SH; |
294 | /* More by default. The last one will manually be set to 0x91 */ |
295 | sh->header_indicator[0] = ET_SECTION_HEADER_MORE0x90; |
296 | sh->platform_id[0] = platform; |
297 | sh->num_section_entries[0] = 0; |
298 | return entry; |
299 | } |
300 | |
301 | static struct boot_catalog_entry * |
302 | cd9660_boot_setup_section_entry(struct cd9660_boot_image *disk) |
303 | { |
304 | struct boot_catalog_entry *entry; |
305 | boot_catalog_section_entry *se; |
306 | if ((entry = cd9660_init_boot_catalog_entry()) == NULL((void *)0)) |
307 | return NULL((void *)0); |
308 | |
309 | entry->entry_type = ET_ENTRY_SE4; |
310 | se = &entry->entry_data.SE; |
311 | |
312 | se->boot_indicator[0] = ET_BOOTABLE0x88; |
313 | se->media_type[0] = disk->targetMode; |
314 | cd9660_721(disk->loadSegment, se->load_segment); |
315 | cd9660_721(disk->num_sectors, se->sector_count); |
316 | cd9660_731(disk->sector, se->load_rba); |
317 | return entry; |
318 | } |
319 | |
320 | #if 0 |
321 | static u_char |
322 | cd9660_boot_get_system_type(struct cd9660_boot_image *disk) |
323 | { |
324 | /* |
325 | For hard drive booting, we need to examine the MBR to figure |
326 | out what the partition type is |
327 | */ |
328 | return 0; |
329 | } |
330 | #endif |
331 | |
332 | /* |
333 | * Set up the BVD, Boot catalog, and the boot entries, but do no writing |
334 | */ |
335 | int |
336 | cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) |
337 | { |
338 | int sector; |
339 | int used_sectors; |
340 | int num_entries = 0; |
341 | int catalog_sectors; |
342 | struct boot_catalog_entry *x86_head, *mac_head, *ppc_head, *efi_head, |
343 | *valid_entry, *default_entry, *temp, *head, **headp, *next; |
344 | struct cd9660_boot_image *tmp_disk; |
345 | |
346 | headp = NULL((void *)0); |
347 | x86_head = mac_head = ppc_head = efi_head = NULL((void *)0); |
348 | |
349 | /* If there are no boot disks, don't bother building boot information */ |
350 | if (TAILQ_EMPTY(&diskStructure->boot_images)(((&diskStructure->boot_images)->tqh_first) == ((void *)0))) |
351 | return 0; |
352 | |
353 | /* Point to catalog: For now assume it consumes one sector */ |
354 | ELTORITO_DPRINTF(("Boot catalog will go in sector %d\n", first_sector)); |
355 | diskStructure->boot_catalog_sector = first_sector; |
356 | cd9660_bothendian_dword(first_sector, |
357 | diskStructure->boot_descriptor->boot_catalog_pointer); |
358 | |
359 | /* Step 1: Generate boot catalog */ |
360 | /* Step 1a: Validation entry */ |
361 | valid_entry = cd9660_boot_setup_validation_entry(ET_SYS_X860); |
362 | if (valid_entry == NULL((void *)0)) |
363 | return -1; |
364 | |
365 | /* |
366 | * Count how many boot images there are, |
367 | * and how many sectors they consume. |
368 | */ |
369 | num_entries = 1; |
370 | used_sectors = 0; |
371 | |
372 | TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list)for((tmp_disk) = ((&diskStructure->boot_images)->tqh_first ); (tmp_disk) != ((void *)0); (tmp_disk) = ((tmp_disk)->image_list .tqe_next)) { |
373 | used_sectors += tmp_disk->num_sectors; |
374 | |
375 | /* One default entry per image */ |
376 | num_entries++; |
377 | } |
378 | catalog_sectors = howmany(num_entries * 0x20, diskStructure->sectorSize)(((num_entries * 0x20) + ((diskStructure->sectorSize) - 1) ) / (diskStructure->sectorSize)); |
379 | used_sectors += catalog_sectors; |
380 | |
381 | /* Populate sector numbers */ |
382 | sector = first_sector + catalog_sectors; |
383 | TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list)for((tmp_disk) = ((&diskStructure->boot_images)->tqh_first ); (tmp_disk) != ((void *)0); (tmp_disk) = ((tmp_disk)->image_list .tqe_next)) { |
384 | tmp_disk->sector = sector; |
385 | sector += tmp_disk->num_sectors; |
386 | } |
387 | |
388 | LIST_INSERT_HEAD(&diskStructure->boot_entries, valid_entry, ll_struct)do { if (((valid_entry)->ll_struct.le_next = (&diskStructure ->boot_entries)->lh_first) != ((void *)0)) (&diskStructure ->boot_entries)->lh_first->ll_struct.le_prev = & (valid_entry)->ll_struct.le_next; (&diskStructure-> boot_entries)->lh_first = (valid_entry); (valid_entry)-> ll_struct.le_prev = &(&diskStructure->boot_entries )->lh_first; } while (0); |
389 | |
390 | /* Step 1b: Initial/default entry */ |
391 | /* TODO : PARAM */ |
392 | tmp_disk = TAILQ_FIRST(&diskStructure->boot_images)((&diskStructure->boot_images)->tqh_first); |
393 | default_entry = cd9660_boot_setup_default_entry(tmp_disk); |
394 | if (default_entry == NULL((void *)0)) { |
395 | warnx("Error: memory allocation failed in cd9660_setup_boot"); |
396 | return -1; |
397 | } |
398 | |
399 | LIST_INSERT_AFTER(valid_entry, default_entry, ll_struct)do { if (((default_entry)->ll_struct.le_next = (valid_entry )->ll_struct.le_next) != ((void *)0)) (valid_entry)->ll_struct .le_next->ll_struct.le_prev = &(default_entry)->ll_struct .le_next; (valid_entry)->ll_struct.le_next = (default_entry ); (default_entry)->ll_struct.le_prev = &(valid_entry) ->ll_struct.le_next; } while (0); |
400 | |
401 | /* Todo: multiple default entries? */ |
402 | |
403 | tmp_disk = TAILQ_NEXT(tmp_disk, image_list)((tmp_disk)->image_list.tqe_next); |
404 | |
405 | temp = default_entry; |
406 | |
407 | /* If multiple boot images are given : */ |
408 | while (tmp_disk != NULL((void *)0)) { |
409 | /* Step 2: Section header */ |
410 | switch (tmp_disk->system) { |
411 | case ET_SYS_X860: |
412 | headp = &x86_head; |
413 | break; |
414 | case ET_SYS_PPC1: |
415 | headp = &ppc_head; |
416 | break; |
417 | case ET_SYS_MAC2: |
418 | headp = &mac_head; |
419 | break; |
420 | case ET_SYS_EFI0xef: |
421 | headp = &efi_head; |
422 | break; |
423 | default: |
424 | warnx("%s: internal error: unknown system type", |
425 | __func__); |
426 | return -1; |
427 | } |
428 | |
429 | if (*headp == NULL((void *)0)) { |
430 | head = |
431 | cd9660_boot_setup_section_head(tmp_disk->system); |
432 | if (head == NULL((void *)0)) { |
433 | warnx("Error: memory allocation failed in " |
434 | "cd9660_setup_boot"); |
435 | return -1; |
436 | } |
437 | LIST_INSERT_AFTER(default_entry, head, ll_struct)do { if (((head)->ll_struct.le_next = (default_entry)-> ll_struct.le_next) != ((void *)0)) (default_entry)->ll_struct .le_next->ll_struct.le_prev = &(head)->ll_struct.le_next ; (default_entry)->ll_struct.le_next = (head); (head)-> ll_struct.le_prev = &(default_entry)->ll_struct.le_next ; } while (0); |
438 | *headp = head; |
439 | } else |
440 | head = *headp; |
441 | |
442 | head->entry_data.SH.num_section_entries[0]++; |
443 | |
444 | /* Step 2a: Section entry and extensions */ |
445 | temp = cd9660_boot_setup_section_entry(tmp_disk); |
446 | if (temp == NULL((void *)0)) { |
447 | warn("%s: cd9660_boot_setup_section_entry", __func__); |
448 | return -1; |
449 | } |
450 | |
451 | while ((next = LIST_NEXT(head, ll_struct)((head)->ll_struct.le_next)) != NULL((void *)0) && |
452 | next->entry_type == ET_ENTRY_SE4) |
453 | head = next; |
454 | |
455 | LIST_INSERT_AFTER(head, temp, ll_struct)do { if (((temp)->ll_struct.le_next = (head)->ll_struct .le_next) != ((void *)0)) (head)->ll_struct.le_next->ll_struct .le_prev = &(temp)->ll_struct.le_next; (head)->ll_struct .le_next = (temp); (temp)->ll_struct.le_prev = &(head) ->ll_struct.le_next; } while (0); |
456 | tmp_disk = TAILQ_NEXT(tmp_disk, image_list)((tmp_disk)->image_list.tqe_next); |
457 | } |
458 | |
459 | /* TODO: Remaining boot disks when implemented */ |
460 | |
461 | return first_sector + used_sectors; |
462 | } |
463 | |
464 | int |
465 | cd9660_setup_boot_volume_descriptor(iso9660_disk *diskStructure, |
466 | volume_descriptor *bvd) |
467 | { |
468 | boot_volume_descriptor *bvdData = |
469 | (boot_volume_descriptor*)bvd->volumeDescriptorData; |
470 | |
471 | bvdData->boot_record_indicator[0] = ISO_VOLUME_DESCRIPTOR_BOOT0; |
472 | memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID"CD001", 5); |
473 | bvdData->version[0] = 1; |
474 | memcpy(bvdData->boot_system_identifier, ET_ID"EL TORITO SPECIFICATION", 23); |
475 | memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID"CD001", 5); |
476 | diskStructure->boot_descriptor = |
477 | (boot_volume_descriptor*) bvd->volumeDescriptorData; |
478 | return 1; |
479 | } |
480 | |
481 | static int |
482 | cd9660_write_mbr_partition_entry(FILE *fd, int idx, off_t sector_start, |
483 | off_t nsectors, int type) |
484 | { |
485 | uint8_t val; |
486 | uint32_t lba; |
487 | |
488 | if (fseeko(fd, (off_t)(idx) * 16 + 0x1be, SEEK_SET0) == -1) |
489 | err(1, "fseeko"); |
490 | |
491 | val = 0x80; /* Bootable */ |
492 | fwrite(&val, sizeof(val), 1, fd); |
493 | |
494 | val = 0xff; /* CHS begin */ |
495 | fwrite(&val, sizeof(val), 1, fd); |
496 | fwrite(&val, sizeof(val), 1, fd); |
497 | fwrite(&val, sizeof(val), 1, fd); |
498 | |
499 | val = type; /* Part type */ |
500 | fwrite(&val, sizeof(val), 1, fd); |
501 | |
502 | val = 0xff; /* CHS end */ |
503 | fwrite(&val, sizeof(val), 1, fd); |
504 | fwrite(&val, sizeof(val), 1, fd); |
505 | fwrite(&val, sizeof(val), 1, fd); |
506 | |
507 | /* LBA extent */ |
508 | lba = htole32(sector_start)((__uint32_t)(sector_start)); |
509 | fwrite(&lba, sizeof(lba), 1, fd); |
510 | lba = htole32(nsectors)((__uint32_t)(nsectors)); |
511 | fwrite(&lba, sizeof(lba), 1, fd); |
512 | |
513 | return 0; |
514 | } |
515 | |
516 | static int |
517 | cd9660_write_apm_partition_entry(FILE *fd, int idx, int total_partitions, |
518 | off_t sector_start, off_t nsectors, off_t sector_size, |
519 | const char *part_name, const char *part_type) |
520 | { |
521 | uint32_t apm32, part_status; |
522 | uint16_t apm16; |
523 | |
524 | part_status = APPLE_PS_VALID0x00000001 | APPLE_PS_ALLOCATED0x00000002 | APPLE_PS_READABLE0x00000010 | |
525 | APPLE_PS_WRITABLE0x00000020; |
526 | |
527 | if (fseeko(fd, (off_t)(idx + 1) * sector_size, SEEK_SET0) == -1) |
528 | err(1, "fseeko"); |
529 | |
530 | /* Signature */ |
531 | apm16 = htobe16(0x504d)(__uint16_t)(__builtin_constant_p(0x504d) ? (__uint16_t)(((__uint16_t )(0x504d) & 0xffU) << 8 | ((__uint16_t)(0x504d) & 0xff00U) >> 8) : __swap16md(0x504d)); |
532 | fwrite(&apm16, sizeof(apm16), 1, fd); |
533 | apm16 = 0; |
534 | fwrite(&apm16, sizeof(apm16), 1, fd); |
535 | |
536 | /* Total number of partitions */ |
537 | apm32 = htobe32(total_partitions)(__uint32_t)(__builtin_constant_p(total_partitions) ? (__uint32_t )(((__uint32_t)(total_partitions) & 0xff) << 24 | ( (__uint32_t)(total_partitions) & 0xff00) << 8 | ((__uint32_t )(total_partitions) & 0xff0000) >> 8 | ((__uint32_t )(total_partitions) & 0xff000000) >> 24) : __swap32md (total_partitions)); |
538 | fwrite(&apm32, sizeof(apm32), 1, fd); |
539 | /* Bounds */ |
540 | apm32 = htobe32(sector_start)(__uint32_t)(__builtin_constant_p(sector_start) ? (__uint32_t )(((__uint32_t)(sector_start) & 0xff) << 24 | ((__uint32_t )(sector_start) & 0xff00) << 8 | ((__uint32_t)(sector_start ) & 0xff0000) >> 8 | ((__uint32_t)(sector_start) & 0xff000000) >> 24) : __swap32md(sector_start)); |
541 | fwrite(&apm32, sizeof(apm32), 1, fd); |
542 | apm32 = htobe32(nsectors)(__uint32_t)(__builtin_constant_p(nsectors) ? (__uint32_t)((( __uint32_t)(nsectors) & 0xff) << 24 | ((__uint32_t) (nsectors) & 0xff00) << 8 | ((__uint32_t)(nsectors) & 0xff0000) >> 8 | ((__uint32_t)(nsectors) & 0xff000000 ) >> 24) : __swap32md(nsectors)); |
543 | fwrite(&apm32, sizeof(apm32), 1, fd); |
544 | |
545 | fwrite(part_name, strlen(part_name) + 1, 1, fd); |
546 | fseek(fd, 32 - strlen(part_name) - 1, SEEK_CUR1); |
547 | fwrite(part_type, strlen(part_type) + 1, 1, fd); |
548 | fseek(fd, 32 - strlen(part_type) - 1, SEEK_CUR1); |
549 | |
550 | apm32 = 0; |
551 | /* pmLgDataStart */ |
552 | fwrite(&apm32, sizeof(apm32), 1, fd); |
553 | /* pmDataCnt */ |
554 | apm32 = htobe32(nsectors)(__uint32_t)(__builtin_constant_p(nsectors) ? (__uint32_t)((( __uint32_t)(nsectors) & 0xff) << 24 | ((__uint32_t) (nsectors) & 0xff00) << 8 | ((__uint32_t)(nsectors) & 0xff0000) >> 8 | ((__uint32_t)(nsectors) & 0xff000000 ) >> 24) : __swap32md(nsectors)); |
555 | fwrite(&apm32, sizeof(apm32), 1, fd); |
556 | /* pmPartStatus */ |
557 | apm32 = htobe32(part_status)(__uint32_t)(__builtin_constant_p(part_status) ? (__uint32_t) (((__uint32_t)(part_status) & 0xff) << 24 | ((__uint32_t )(part_status) & 0xff00) << 8 | ((__uint32_t)(part_status ) & 0xff0000) >> 8 | ((__uint32_t)(part_status) & 0xff000000) >> 24) : __swap32md(part_status)); |
558 | fwrite(&apm32, sizeof(apm32), 1, fd); |
559 | |
560 | return 0; |
561 | } |
562 | |
563 | int |
564 | cd9660_write_boot(iso9660_disk *diskStructure, FILE *fd) |
565 | { |
566 | struct boot_catalog_entry *e; |
567 | struct cd9660_boot_image *t; |
568 | int apm_partitions = 0; |
569 | int mbr_partitions = 0; |
570 | |
571 | /* write boot catalog */ |
572 | if (fseeko(fd, (off_t)diskStructure->boot_catalog_sector * |
573 | diskStructure->sectorSize, SEEK_SET0) == -1) |
574 | err(1, "fseeko"); |
575 | |
576 | LIST_FOREACH(e, &diskStructure->boot_entries, ll_struct)for((e) = ((&diskStructure->boot_entries)->lh_first ); (e)!= ((void *)0); (e) = ((e)->ll_struct.le_next)) { |
577 | /* |
578 | * It doesnt matter which one gets written |
579 | * since they are the same size |
580 | */ |
581 | fwrite(&(e->entry_data.VE), 1, 32, fd); |
582 | } |
583 | |
584 | /* copy boot images */ |
585 | TAILQ_FOREACH(t, &diskStructure->boot_images, image_list)for((t) = ((&diskStructure->boot_images)->tqh_first ); (t) != ((void *)0); (t) = ((t)->image_list.tqe_next)) { |
586 | cd9660_copy_file(diskStructure, fd, t->sector, t->filename); |
587 | |
588 | if (t->system == ET_SYS_MAC2) |
589 | apm_partitions++; |
590 | if (t->system == ET_SYS_PPC1) |
591 | mbr_partitions++; |
592 | } |
593 | |
594 | /* some systems need partition tables as well */ |
595 | if (mbr_partitions > 0) { |
596 | uint16_t sig; |
597 | |
598 | fseek(fd, 0x1fe, SEEK_SET0); |
599 | sig = htole16(0xaa55)((__uint16_t)(0xaa55)); |
600 | fwrite(&sig, sizeof(sig), 1, fd); |
601 | |
602 | mbr_partitions = 0; |
603 | |
604 | /* Write all partition entries */ |
605 | TAILQ_FOREACH(t, &diskStructure->boot_images, image_list)for((t) = ((&diskStructure->boot_images)->tqh_first ); (t) != ((void *)0); (t) = ((t)->image_list.tqe_next)) { |
606 | if (t->system != ET_SYS_PPC1) |
607 | continue; |
608 | cd9660_write_mbr_partition_entry(fd, mbr_partitions++, |
609 | t->sector * (diskStructure->sectorSize / 512), |
610 | t->num_sectors * (diskStructure->sectorSize / 512), |
611 | 0x41 /* PReP Boot */); |
612 | } |
613 | } |
614 | |
615 | if (apm_partitions > 0) { |
616 | /* Write DDR and global APM info */ |
617 | uint32_t apm32; |
618 | uint16_t apm16; |
619 | int total_parts; |
620 | |
621 | fseek(fd, 0, SEEK_SET0); |
622 | apm16 = htobe16(0x4552)(__uint16_t)(__builtin_constant_p(0x4552) ? (__uint16_t)(((__uint16_t )(0x4552) & 0xffU) << 8 | ((__uint16_t)(0x4552) & 0xff00U) >> 8) : __swap16md(0x4552)); |
623 | fwrite(&apm16, sizeof(apm16), 1, fd); |
624 | /* Device block size */ |
625 | apm16 = htobe16(512)(__uint16_t)(__builtin_constant_p(512) ? (__uint16_t)(((__uint16_t )(512) & 0xffU) << 8 | ((__uint16_t)(512) & 0xff00U ) >> 8) : __swap16md(512)); |
626 | fwrite(&apm16, sizeof(apm16), 1, fd); |
627 | /* Device block count */ |
628 | apm32 = htobe32(diskStructure->totalSectors *(__uint32_t)(__builtin_constant_p(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) ? (__uint32_t)(((__uint32_t )(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) & 0xff) << 24 | ((__uint32_t)(diskStructure ->totalSectors * (diskStructure->sectorSize / 512)) & 0xff00) << 8 | ((__uint32_t)(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) & 0xff0000) >> 8 | ((__uint32_t)(diskStructure->totalSectors * (diskStructure ->sectorSize / 512)) & 0xff000000) >> 24) : __swap32md (diskStructure->totalSectors * (diskStructure->sectorSize / 512))) |
629 | (diskStructure->sectorSize / 512))(__uint32_t)(__builtin_constant_p(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) ? (__uint32_t)(((__uint32_t )(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) & 0xff) << 24 | ((__uint32_t)(diskStructure ->totalSectors * (diskStructure->sectorSize / 512)) & 0xff00) << 8 | ((__uint32_t)(diskStructure->totalSectors * (diskStructure->sectorSize / 512)) & 0xff0000) >> 8 | ((__uint32_t)(diskStructure->totalSectors * (diskStructure ->sectorSize / 512)) & 0xff000000) >> 24) : __swap32md (diskStructure->totalSectors * (diskStructure->sectorSize / 512))); |
630 | fwrite(&apm32, sizeof(apm32), 1, fd); |
631 | /* Device type/id */ |
632 | apm16 = htobe16(1)(__uint16_t)(__builtin_constant_p(1) ? (__uint16_t)(((__uint16_t )(1) & 0xffU) << 8 | ((__uint16_t)(1) & 0xff00U ) >> 8) : __swap16md(1)); |
633 | fwrite(&apm16, sizeof(apm16), 1, fd); |
634 | fwrite(&apm16, sizeof(apm16), 1, fd); |
635 | |
636 | /* Count total needed entries */ |
637 | total_parts = 2 + apm_partitions; /* Self + ISO9660 */ |
638 | |
639 | /* Write self-descriptor */ |
640 | cd9660_write_apm_partition_entry(fd, 0, total_parts, 1, |
641 | total_parts, 512, "Apple", "Apple_partition_map"); |
642 | |
643 | /* Write all partition entries */ |
644 | apm_partitions = 0; |
645 | TAILQ_FOREACH(t, &diskStructure->boot_images, image_list)for((t) = ((&diskStructure->boot_images)->tqh_first ); (t) != ((void *)0); (t) = ((t)->image_list.tqe_next)) { |
646 | if (t->system != ET_SYS_MAC2) |
647 | continue; |
648 | |
649 | cd9660_write_apm_partition_entry(fd, |
650 | 1 + apm_partitions++, total_parts, |
651 | t->sector * (diskStructure->sectorSize / 512), |
652 | t->num_sectors * (diskStructure->sectorSize / 512), |
653 | 512, "CD Boot", "Apple_Bootstrap"); |
654 | } |
655 | |
656 | /* Write ISO9660 descriptor, enclosing the whole disk */ |
657 | cd9660_write_apm_partition_entry(fd, 2 + apm_partitions, |
658 | total_parts, 0, diskStructure->totalSectors * |
659 | (diskStructure->sectorSize / 512), 512, "ISO9660", |
660 | "CD_ROM_Mode_1"); |
661 | } |
662 | |
663 | return 0; |
664 | } |