Let the right reset entry point jump to the currently wrong entry point
[openhackware.git] / src / libpart / isofs.c
blob6e0adae3e9a5d91c146c843c353139ae58240922
1 /*
2 * <isofs.c>
4 * Open Hack'Ware BIOS ISOFS partition type management
5 *
6 * Copyright (c) 2004-2005 Jocelyn Mayer
7 *
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
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "bios.h"
25 #include "libpart.h"
27 /* ISO FS partitions handlers */
28 #define ISOFS_BLOCSIZE (2048)
30 /* Generic ISO fs descriptor */
31 typedef struct isofs_desc_t isofs_desc_t;
32 struct isofs_desc_t {
33 uint8_t type;
34 uint8_t ID[5];
35 uint8_t version;
36 uint8_t data[2041];
37 } __attribute__ ((packed));
39 typedef struct iso_primary_desc_t iso_primary_desc_t;
40 struct iso_primary_desc_t {
41 uint8_t type;
42 uint8_t ID[5];
43 uint8_t version;
44 uint8_t pad0;
45 uint8_t system_id[32];
46 uint8_t volume_id[32];
47 uint8_t pad1[8];
48 uint32_t volume_size;
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 {
56 uint8_t type;
57 uint8_t ID[5];
58 uint8_t version;
59 uint8_t sys_ID[32];
60 uint8_t pad[32];
61 uint32_t catalog;
62 uint8_t data[1973];
63 } __attribute__ ((packed));
65 #define ISO_BOOTABLE 0x88
66 enum {
67 ISOBOOT_IX86 = 0,
68 ISOBOOT_PPC = 1,
69 ISOBOOT_MAC = 2,
72 enum {
73 ISOMEDIA_NOEMUL = 0,
74 ISOMEDIA_FL12 = 1,
75 ISOMEDIA_FL144 = 2,
76 ISOMEDIA_FL288 = 3,
77 ISOMEDIA_HD = 4,
80 typedef struct isofs_validdesc_t isofs_validdesc_t;
81 struct isofs_validdesc_t {
82 uint8_t ID;
83 uint8_t arch;
84 uint8_t pad[2];
85 uint8_t name[24];
86 uint8_t csum[2];
87 uint16_t key;
88 } __attribute__ ((packed));
90 typedef struct isofs_bootcat_t isofs_bootcat_t;
91 struct isofs_bootcat_t {
92 uint8_t bootable;
93 uint8_t media;
94 uint8_t segment[2];
95 uint8_t sys_type;
96 uint8_t pad;
97 uint16_t nsect;
98 uint32_t offset;
99 uint8_t data[20];
100 } __attribute__ ((packed));
102 part_t *isofs_probe_partitions (bloc_device_t *bd)
104 unsigned char name[32];
105 void *buffer;
106 union {
107 isofs_desc_t desc;
108 isofs_bootdesc_t bootdesc;
109 iso_primary_desc_t primdesc;
110 } *desc;
111 isofs_validdesc_t *valid;
112 isofs_bootcat_t *bootcat;
113 part_t *part;
114 uint32_t boot_desc;
115 uint32_t nsect, bloc, offset, length;
116 int i, end_reached;
118 part = NULL;
119 buffer = malloc(ISOFS_BLOCSIZE);
120 end_reached = 0;
121 desc = buffer;
122 boot_desc = -1;
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);
128 goto error;
130 if (strncmp("CD001", desc->desc.ID, 5) != 0) {
131 // MSG("\rNo ISO9660 signature\n");
132 goto error;
134 /* We found at least one valid descriptor */
135 switch (desc->desc.type) {
136 case 0x00:
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);
141 break;
142 case 0x01:
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));
147 break;
148 case 0x02:
149 /* ISOFS suplementary descriptor */
150 DPRINTF("ISOFS suplementary descriptor\n");
151 break;
152 case 0xFF:
153 /* End of descriptor list */
154 DPRINTF("End of descriptor list\n");
155 end_reached = 1;
156 break;
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);
165 valid = buffer;
166 #if 1
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);
170 continue;
172 #endif
173 #if 0
174 #if defined (__i386__)
175 if (valid->arch != ISOBOOT_IX86) {
176 ERROR("ISO catalog not for x86: %d\n", valid->arch);
177 continue;
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);
182 continue;
184 #else
185 ERROR("Unknown host architecture !\n");
186 continue;
187 #endif
188 #endif
189 bootcat = (void *)(valid + 1);
190 if (bootcat->bootable != ISO_BOOTABLE) {
191 ERROR("Non bootable ISO catalog\n");
192 continue;
194 nsect = get_le16(&bootcat->nsect);
195 switch (bootcat->media) {
196 case ISOMEDIA_NOEMUL:
197 length = nsect * ISOFS_BLOCSIZE;
198 dprintf("No emulation\n");
199 break;
200 case ISOMEDIA_FL12:
201 length = 1200 * 1024;
202 dprintf("1.2 MB floppy\n");
203 break;
204 case ISOMEDIA_FL144:
205 length = 1440 * 1024;
206 dprintf("1.44 MB floppy\n");
207 break;
208 case ISOMEDIA_FL288:
209 length = 2880 * 1024;
210 dprintf("2.88 MB floppy\n");
211 break;
212 case ISOMEDIA_HD:
213 length = nsect * ISOFS_BLOCSIZE;
214 dprintf("HD image\n");
215 break;
216 default:
217 ERROR("Unknown media type: %d\n", bootcat->media);
218 continue;
220 offset = get_le32(&bootcat->offset);
221 /* Register boot disc */
222 part = malloc(sizeof(part_t));
223 part->bd = bd;
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;
231 part->boot_load = 0;
232 part->boot_entry = 0;
233 if (valid->name[0] == '\0') {
234 strcpy(name, "ISOFS");
235 } else {
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);
250 break;
253 error:
254 free(buffer);
256 return part;