4 * Open Hack'Ware BIOS ISOFS partition type management
6 * Copyright (c) 2004-2005 Jocelyn Mayer
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License V2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* ISO FS partitions handlers */
28 #define ISOFS_BLOCSIZE (2048)
30 /* Generic ISO fs descriptor */
31 typedef struct isofs_desc_t isofs_desc_t;
37 } __attribute__ ((packed));
39 typedef struct iso_primary_desc_t iso_primary_desc_t;
40 struct iso_primary_desc_t {
45 uint8_t system_id[32];
46 uint8_t volume_id[32];
49 } __attribute__ ((packed));
51 /* The only descriptor we're interrested in here
52 * is El-torito boot descriptor
54 typedef struct isofs_bootdesc_t isofs_bootdesc_t;
55 struct isofs_bootdesc_t {
63 } __attribute__ ((packed));
65 #define ISO_BOOTABLE 0x88
80 typedef struct isofs_validdesc_t isofs_validdesc_t;
81 struct isofs_validdesc_t {
88 } __attribute__ ((packed));
90 typedef struct isofs_bootcat_t isofs_bootcat_t;
91 struct isofs_bootcat_t {
100 } __attribute__ ((packed));
102 part_t *isofs_probe_partitions (bloc_device_t *bd)
104 unsigned char name[32];
108 isofs_bootdesc_t bootdesc;
109 iso_primary_desc_t primdesc;
111 isofs_validdesc_t *valid;
112 isofs_bootcat_t *bootcat;
115 uint32_t nsect, bloc, offset, length;
119 buffer = malloc(ISOFS_BLOCSIZE);
123 /* The descriptors start at offset 0x8000 */
124 for (bloc = 0x8000 / ISOFS_BLOCSIZE; end_reached == 0; bloc++) {
125 bd_seek(bd, bloc, 0);
126 if (bd_read(bd, buffer, ISOFS_BLOCSIZE) < 0) {
127 ERROR("%s bloc_read %d failed\n", __func__, bloc);
130 if (strncmp("CD001", desc->desc.ID, 5) != 0) {
131 // MSG("\rNo ISO9660 signature\n");
134 /* We found at least one valid descriptor */
135 switch (desc->desc.type) {
137 /* El-torito descriptor, great ! */
138 DPRINTF("El-torito descriptor: %08x %d\n", desc->bootdesc.catalog,
139 (char *)&desc->bootdesc.catalog - (char *)desc);
140 boot_desc = get_le32(&desc->bootdesc.catalog);
143 /* ISOFS primary descriptor */
144 DPRINTF("ISOFS primary descriptor (%d %d)\n",
145 get_le32(&desc->primdesc.volume_size) * 2048,
146 get_le32(&desc->primdesc.volume_size));
149 /* ISOFS suplementary descriptor */
150 DPRINTF("ISOFS suplementary descriptor\n");
153 /* End of descriptor list */
154 DPRINTF("End of descriptor list\n");
159 if (boot_desc != (uint32_t)(-1)) {
160 /* Find the validation descriptor */
161 bd_seek(bd, boot_desc, 0);
162 for (i = 0; i < (ISOFS_BLOCSIZE / 64); i++) {
163 DPRINTF("ISO catalog...\n");
164 bd_read(bd, buffer, 64);
167 if (valid->ID != 0x01 || get_le16(&valid->key) != 0xAA55) {
168 ERROR("ISO catalog with invalid ID/key: %x %x\n",
169 valid->ID, valid->key);
174 #if defined (__i386__)
175 if (valid->arch != ISOBOOT_IX86) {
176 ERROR("ISO catalog not for x86: %d\n", valid->arch);
179 #elif defined (__powerpc__) || defined (_ARCH_PPC)
180 if (valid->arch != ISOBOOT_PPC && valid->arch != ISOBOOT_MAC) {
181 ERROR("ISO catalog not for PPC: %d\n", valid->arch);
185 ERROR("Unknown host architecture !\n");
189 bootcat = (void *)(valid + 1);
190 if (bootcat->bootable != ISO_BOOTABLE) {
191 ERROR("Non bootable ISO catalog\n");
194 nsect = get_le16(&bootcat->nsect);
195 switch (bootcat->media) {
196 case ISOMEDIA_NOEMUL:
197 length = nsect * ISOFS_BLOCSIZE;
198 dprintf("No emulation\n");
201 length = 1200 * 1024;
202 dprintf("1.2 MB floppy\n");
205 length = 1440 * 1024;
206 dprintf("1.44 MB floppy\n");
209 length = 2880 * 1024;
210 dprintf("2.88 MB floppy\n");
213 length = nsect * ISOFS_BLOCSIZE;
214 dprintf("HD image\n");
217 ERROR("Unknown media type: %d\n", bootcat->media);
220 offset = get_le32(&bootcat->offset);
221 /* Register boot disc */
222 part = malloc(sizeof(part_t));
224 part_set_blocsize(bd, part, ISOFS_BLOCSIZE);
225 part->start = offset;
226 part->size = (length + ISOFS_BLOCSIZE - 1) / ISOFS_BLOCSIZE;
227 part->boot_start.bloc = 0;
228 part->boot_start.offset = 0;
229 part->boot_size.bloc = length / ISOFS_BLOCSIZE;
230 part->boot_size.offset = length % ISOFS_BLOCSIZE;
232 part->boot_entry = 0;
233 if (valid->name[0] == '\0') {
234 strcpy(name, "ISOFS");
236 memcpy(name, valid->name, sizeof(valid->name));
237 name[sizeof(valid->name)] = '\0';
239 printf("Partition '%s': %p st %0x size %0x %d\n",
240 name, part, offset, length, bootcat->media);
241 printf(" boot %0x %0x load %0x entry %0x\n",
242 part->boot_start.bloc, part->boot_size.bloc,
243 part->boot_load, part->boot_entry);
244 part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT;
245 part_register(bd, part, name, i + 1);
246 fs_raw_set_bootfile(part, part->boot_start.bloc,
247 part->boot_start.offset,
248 part->boot_size.bloc,
249 part->boot_size.offset);