4 * Open Hack'Ware BIOS Apple 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 /* Apple partitions handler */
28 #define HFS_BLOCSIZE (512)
30 typedef struct Mac_head_t Mac_head_t;
44 uint8_t part_table[0x40];
48 } __attribute__ ((packed));
50 typedef struct Mac_driver_entry_t Mac_driver_entry_t;
51 struct Mac_driver_entry_t {
55 } __attribute__ ((packed));
57 typedef enum Mac_partflags_t Mac_partflags_t;
58 enum Mac_partflags_t {
59 MACPART_SPEC2 = 0x0100,
60 MACPART_SPEC1 = 0x0080,
62 MACPART_WRITABLE = 0x0020,
63 MACPART_READABLE = 0x0010,
64 MACPART_BOOTABLE = 0x0008,
65 MACPART_INUSE = 0x0004,
66 MACPART_ALLOCATED = 0x0002,
67 MACPART_VALID = 0x0001,
70 #define MAC_BOOTABLE_PART (MACPART_VALID | MACPART_INUSE | MACPART_BOOTABLE)
72 typedef struct Mac_partmap_t Mac_partmap_t;
73 struct Mac_partmap_t {
103 uint8_t boot_args[0x80];
114 } __attribute__ ((packed));
116 int fs_raw_set_bootfile (part_t *part,
117 uint32_t start_bloc, uint32_t start_offset,
118 uint32_t size_bloc, uint32_t size_offset);
120 part_t *Apple_probe_partitions (bloc_device_t *bd)
122 unsigned char tmp[33], *name;
124 Mac_partmap_t *partmap;
125 part_t *part, *boot_part;
128 uint32_t pos, bloc, start, count;
129 uint32_t bloc_size, flags;
130 int map_count, i, n, len;
135 buffer = malloc(HFS_BLOCSIZE);
136 /* Read first sector */
138 if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) {
139 ERROR("Unable to read boot sector from boot device. Aborting...\n");
142 head = (Mac_head_t *)buffer;
143 if (head->signature[0] != 'E' || head->signature[1] != 'R') {
144 // MSG("\rNo Apple boot bloc signature...\n");
147 MSG("\rFound Apple partition map...\n");
149 bloc_size = bd_seclen(bd);
152 if (head->magic[0] == 0x55 && head->magic[1] == 0xAA) {
153 /* PREP boot image ! Must parse it as MS-DOS boot bloc */
154 ERROR("%s PREP head magic\n", __func__);
158 /* Partition table starts in sector 1 */
159 for (i = 1; i < (map_count + 1); i++) {
160 bloc = (i * HFS_BLOCSIZE) / bloc_size;
161 pos = (i * HFS_BLOCSIZE) % bloc_size;
162 DPRINTF("Check part %d of %d (%d %d %d)\n",
163 i, map_count, bloc, pos, bloc_size);
164 bd_seek(bd, bloc, pos);
165 if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) {
166 ERROR("%s sector_read failed (%d)\n", __func__, i);
169 partmap = (Mac_partmap_t *)buffer;
170 if (partmap->signature[0] != 'P' || partmap->signature[1] != 'M' ) {
171 ERROR("%s bad partition signature (%c %c)\n",
172 __func__, partmap->signature[0], partmap->signature[1]);
175 /* We found at least one Apple partition map,
176 * so we won't have to try to parse with other partition mappings.
178 for (type = partmap->type; (type - partmap->type) < 32; type++) {
182 if (partmap->name[0] == '\0') {
183 sprintf(tmp, "part%d", i);
186 name = partmap->name;
188 /* Regular Apple partition */
189 part = malloc(sizeof(part_t));
191 ERROR("%s: can't allocate partition\n", __func__);
194 memset(part, 0, sizeof(part_t));
195 part->start = partmap->start_bloc;
196 part->size = partmap->bloc_cnt;
197 part_set_blocsize(bd, part, HFS_BLOCSIZE);
198 len = 32 - (type - partmap->type);
200 /* Place holder. Skip it */
201 DPRINTF("%s placeholder part\t%d\n", __func__, i);
202 part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
203 part_register(bd, part, name, i);
204 } else if (strncmp("Apple_Void", type, 32) == 0) {
205 /* Void partition. Skip it */
206 DPRINTF("%s Void part\t%d [%s]\n", __func__, i, type);
207 part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
208 part_register(bd, part, name, i);
209 } else if (strncmp("Apple_Free", type, 32) == 0) {
210 /* Free space. Skip it */
211 DPRINTF("%s Free part (%d)\n", __func__, i);
212 part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
213 part_register(bd, part, name, i);
214 } else if (strncmp("Apple_partition_map", type, 32) == 0 ||
215 strncmp("Apple_Partition_Map", type, 32) == 0
216 #if 0 // Is this really used or is it just a mistake ?
217 || strncmp("Apple_patition_map", type, 32) == 0
220 DPRINTF("%s Partition map\t%d [%s]\n", __func__, i, type);
221 /* We are in the partition map descriptor */
223 /* Get the real map blocs count */
224 map_count = partmap->map_cnt;
225 DPRINTF("%s: map_count: %d\n", __func__, map_count);
227 /* Don't about about secondary partition map
228 * Seems to be used, at least on CDROMs, to describe
229 * the same partition map with bloc_size = 2048
232 part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
233 part_register(bd, part, name, i);
234 } else if (strncmp("Apple_Driver", type, 32) == 0 ||
235 strncmp("Apple_Driver43", type, 32) == 0 ||
236 strncmp("Apple_Driver43_CD", type, 32) == 0 ||
237 strncmp("Apple_Driver_ATA", type, 32) == 0 ||
238 strncmp("Apple_Driver_ATAPI", type, 32) == 0 ||
239 strncmp("Apple_FWDriver", type, 32) == 0 ||
240 strncmp("Apple_Driver_IOKit", type, 32) == 0) {
241 /* Drivers. don't care for now */
242 DPRINTF("%s Drivers part\t%d [%s]\n", __func__, i, type);
243 part->flags = PART_TYPE_APPLE | PART_FLAG_DRIVER;
244 part_register(bd, part, name, i);
245 } else if (strncmp("Apple_Patches", type, 32) == 0) {
246 /* Patches: don't care for now */
247 part->flags = PART_TYPE_APPLE | PART_FLAG_PATCH;
248 part_register(bd, part, name, i);
249 DPRINTF("%s Patches part\t%d [%s]\n", __func__, i, type);
250 } else if (strncmp("Apple_HFS", type, 32) == 0 ||
251 strncmp("Apple_MFS", type, 32) == 0 ||
252 strncmp("Apple_UFS", type, 32) == 0 ||
253 strncmp("Apple_PRODOS", type, 32) == 0 ||
254 strncmp("Apple_UNIX_SVR2", type, 32) == 0 ||
255 strncmp("Linux", type, 32) == 0 ||
256 strncmp("NetBSD/macppc", type, 32) == 0 ||
257 strncmp("Apple_boot", type, 32) == 0 ||
258 strncmp("Apple_bootstrap", type, 32) == 0 ||
259 strncmp("Apple_Bootstrap", type, 32) == 0) {
260 DPRINTF("%s Fs part\t%d [%s]\n", __func__, i, type);
261 /* Filesystems / boot partitions */
262 flags = partmap->flags;
263 start = partmap->start_bloc * HFS_BLOCSIZE;
264 count = partmap->bloc_cnt * HFS_BLOCSIZE;
265 if (partmap->boot_size == 0 || partmap->boot_load == 0) {
266 printf("Not a bootable partition %d %d (%p %p)\n",
267 partmap->boot_size, partmap->boot_load,
269 part->flags = PART_TYPE_APPLE | PART_FLAG_FS;
271 part->boot_start.bloc = partmap->boot_start;
272 part->boot_start.offset = 0;
273 part->boot_size.bloc = partmap->boot_size / HFS_BLOCSIZE;
275 printf("%0x %0x %0x\n", partmap->boot_size, HFS_BLOCSIZE,
276 part->boot_size.bloc);
278 part->boot_size.offset = (partmap->boot_size) % HFS_BLOCSIZE;
279 part->boot_load = partmap->boot_load;
280 part->boot_entry = partmap->boot_entry;
281 fs_raw_set_bootfile(part, part->boot_start.bloc,
282 part->boot_start.offset,
283 part->boot_size.bloc,
284 part->boot_size.offset);
286 part->flags = PART_TYPE_APPLE | PART_FLAG_FS | PART_FLAG_BOOT;
288 printf("Partition: %d '%s' '%s' st %0x size %0x",
289 i, name, type, partmap->start_bloc, partmap->bloc_cnt);
293 DPRINTF(" - %0x %0x %p %p\n",
294 partmap->boot_start, partmap->boot_size, part, part->fs);
295 DPRINTF(" boot %0x %0x load %0x entry %0x\n",
296 part->boot_start.bloc, part->boot_size.bloc,
297 part->boot_load, part->boot_entry);
298 DPRINTF(" load %0x entry %0x %0x\n",
299 partmap->boot_load2, partmap->boot_entry2, HFS_BLOCSIZE);
300 part_register(bd, part, name, i);
302 memcpy(tmp, type, 32);
304 ERROR("Unknown partition type [%s]\n", tmp);
305 part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
306 part_register(bd, part, name, i);