1 | /*␊ |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
7 | * Reserved. This file contains Original Code and/or Modifications of␊ |
8 | * Original Code as defined in and that are subject to the Apple Public␊ |
9 | * Source License Version 2.0 (the "License"). You may not use this file␊ |
10 | * except in compliance with the License. Please obtain a copy of the␊ |
11 | * License at http://www.apple.com/publicsource and read it before using␊ |
12 | * this file.␊ |
13 | * ␊ |
14 | * The Original Code and all software distributed under the License are␊ |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the␊ |
19 | * License for the specific language governing rights and limitations␊ |
20 | * under the License.␊ |
21 | * ␊ |
22 | * @APPLE_LICENSE_HEADER_END@␊ |
23 | *␊ |
24 | *␊ |
25 | * Mach Operating System␊ |
26 | * Copyright (c) 1990 Carnegie-Mellon University␊ |
27 | * Copyright (c) 1989 Carnegie-Mellon University␊ |
28 | * All rights reserved. The CMU software License Agreement specifies␊ |
29 | * the terms and conditions for use and redistribution.␊ |
30 | *␊ |
31 | *␊ |
32 | * INTEL CORPORATION PROPRIETARY INFORMATION␊ |
33 | *␊ |
34 | * This software is supplied under the terms of a license agreement or ␊ |
35 | * nondisclosure agreement with Intel Corporation and may not be copied ␊ |
36 | * nor disclosed except in accordance with the terms of that agreement.␊ |
37 | *␊ |
38 | * Copyright 1988, 1989 Intel Corporation␊ |
39 | *␊ |
40 | *␊ |
41 | * Copyright 1993 NeXT Computer, Inc.␊ |
42 | * All rights reserved.␊ |
43 | *␊ |
44 | *␊ |
45 | * Copyright 2007 VMware Inc.␊ |
46 | * "Preboot" ramdisk support added by David Elliott␊ |
47 | * GPT support added by David Elliott. Based on IOGUIDPartitionScheme.cpp.␊ |
48 | */␊ |
49 | ␊ |
50 | //Azi: style the rest later...␊ |
51 | ␊ |
52 | // Allow UFS_SUPPORT to be overridden with preprocessor option.␊ |
53 | #ifndef UFS_SUPPORT␊ |
54 | // zef: Disabled UFS support␊ |
55 | #define UFS_SUPPORT 0␊ |
56 | #endif␊ |
57 | ␊ |
58 | #if UFS_SUPPORT␊ |
59 | #include "ufs.h"␊ |
60 | #endif␊ |
61 | #include <limits.h>␊ |
62 | #include <IOKit/storage/IOApplePartitionScheme.h>␊ |
63 | #include <IOKit/storage/IOGUIDPartitionScheme.h>␊ |
64 | #include "libsaio.h"␊ |
65 | #include "boot.h"␊ |
66 | #include "bootstruct.h"␊ |
67 | #include "memory.h"␊ |
68 | #include "fdisk.h"␊ |
69 | #include "hfs.h"␊ |
70 | #include "ntfs.h"␊ |
71 | #include "exfat.h"␊ |
72 | #include "msdos.h"␊ |
73 | #include "ext2fs.h"␊ |
74 | #include "befs.h"␊ |
75 | #include "freebsd.h"␊ |
76 | #include "openbsd.h"␊ |
77 | #include "xml.h"␊ |
78 | #include "disk.h"␊ |
79 | // For EFI_GUID␊ |
80 | #include "efi.h"␊ |
81 | #include "efi_tables.h"␊ |
82 | ␊ |
83 | typedef struct gpt_hdr gpt_hdr;␊ |
84 | typedef struct gpt_ent gpt_ent;␊ |
85 | ␊ |
86 | #define PROBEFS_SIZE BPS * 4 /* buffer size for filesystem probe */␊ |
87 | #define CD_BPS 2048 /* CD-ROM block size */␊ |
88 | #define N_CACHE_SECS (BIOS_LEN / BPS) /* Must be a multiple of 4 for CD-ROMs */␊ |
89 | #define UFS_FRONT_PORCH 0␊ |
90 | #define kAPMSector 2 /* Sector number of Apple partition map */␊ |
91 | #define kAPMCDSector 8 /* Translated sector of Apple partition map on a CD */␊ |
92 | #define ECC_CORRECTED_ERR 0x11␊ |
93 | ␊ |
94 | /*␊ |
95 | * IORound and IOTrunc convenience functions, in the spirit␊ |
96 | * of vm's round_page() and trunc_page().␊ |
97 | */␊ |
98 | #define IORound(value,multiple) \␊ |
99 | ((((value) + (multiple) - 1) / (multiple)) * (multiple))␊ |
100 | ␊ |
101 | #define IOTrunc(value,multiple) \␊ |
102 | (((value) / (multiple)) * (multiple));␊ |
103 | ␊ |
104 | //==========================================================================␊ |
105 | // Maps (E)BIOS return codes to message strings.␊ |
106 | struct NamedValue {␊ |
107 | ␉unsigned char value;␊ |
108 | ␉const char *name;␊ |
109 | };␊ |
110 | ␊ |
111 | // =========================================================================␊ |
112 | /*␊ |
113 | * Map a disk drive to bootable volumes contained within.␊ |
114 | */␊ |
115 | struct DiskBVMap {␊ |
116 | int biosdev;␉␉// BIOS device number (unique)␊ |
117 | BVRef bvr;␉␉// chain of boot volumes on the disk␊ |
118 | int bvrcnt;␉␉// number of boot volumes␊ |
119 | struct DiskBVMap *next;␉␉// linkage to next mapping␊ |
120 | };␊ |
121 | ␊ |
122 | /*␊ |
123 | * trackbuf points to the start of the track cache. Biosread()␊ |
124 | * will store the sectors read from disk to this memory area.␊ |
125 | *␊ |
126 | * biosbuf points to a sector within the track cache, and is␊ |
127 | * updated by Biosread().␊ |
128 | */␊ |
129 | static char *const trackbuf = (char *) ptov(BIOS_ADDR);␊ |
130 | static char *biosbuf;␊ |
131 | ␊ |
132 | static struct DiskBVMap *gDiskBVMap = NULL;␊ |
133 | static struct disk_blk0 *gBootSector = NULL;␊ |
134 | ␊ |
135 | // Function pointers to be filled in if ramdisks are available:␊ |
136 | int (*p_ramdiskReadBytes)( int biosdev, unsigned int blkno,␊ |
137 | unsigned int byteoff,␊ |
138 | unsigned int byteCount, void * buffer ) = NULL;␊ |
139 | int (*p_get_ramdisk_info)(int biosdev, struct driveInfo *dip) = NULL;␊ |
140 | ␊ |
141 | static bool getOSVersion(BVRef bvr, char *str);␊ |
142 | static bool cache_valid = false;␊ |
143 | ␊ |
144 | // =============================================================================␊ |
145 | static const struct NamedValue bios_errors[] =␊ |
146 | {␊ |
147 | ␉{ 0x10, "Media error" },␊ |
148 | ␉{ 0x11, "Corrected ECC error" },␊ |
149 | ␉{ 0x20, "Controller or device error" },␊ |
150 | ␉{ 0x40, "Seek failed" },␊ |
151 | ␉{ 0x80, "Device timeout" },␊ |
152 | ␉{ 0xAA, "Drive not ready" },␊ |
153 | ␉{ 0x00, NULL }␊ |
154 | };␊ |
155 | ␊ |
156 | // =============================================================================␊ |
157 | static const struct NamedValue fdiskTypes[] =␊ |
158 | {␊ |
159 | ␉{ FDISK_DOS12,␉␉"DOS_FAT_12" }, // 0x01␊ |
160 | ␉{ FDISK_DOS16S,␉␉"DOS_FAT_16_S" }, // 0x04␊ |
161 | ␉{ FDISK_DOS16B,␉␉"DOS_FAT_16" }, // 0x06␊ |
162 | ␉{ FDISK_NTFS,␉␉"Windows NTFS" }, // 0x07␊ |
163 | ␉{ FDISK_SMALLFAT32,␉"DOS_FAT_32" }, // 0x0B␊ |
164 | ␉{ FDISK_FAT32,␉␉"Windows FAT_32" }, // 0x0C␊ |
165 | ␉{ FDISK_DOS16SLBA,␉"Windows FAT_16" }, // 0x0E␊ |
166 | ␉{ FDISK_WIN_LDM, "Windows_LDM" }, // 0x42␊ |
167 | ␉{ FDISK_LINUX_SWAP, "Linux_Swap" }, // 0x82␊ |
168 | ␉{ FDISK_LINUX,␉␉"Linux" }, // 0x83␊ |
169 | ␉{ FDISK_LINUX_LVM, "Linux_LVM" }, // 0x8E␊ |
170 | ␉{ FDISK_FREEBSD,␉"FreeBSD" }, // 0xA5␊ |
171 | ␉{ FDISK_OPENBSD,␉"OpenBSD" }, // 0xA6␊ |
172 | ␉{ FDISK_NEXTNAME, "Apple_Rhapsody_UFS" }, // 0xA7␊ |
173 | ␉{ FDISK_UFS,␉␉"Apple UFS" }, // 0xA8␊ |
174 | ␉{ FDISK_NETBSD, "NetBSD" }, // 0xA9␊ |
175 | ␉{ FDISK_BOOTER,␉␉"Apple_Boot" }, // 0xAB␊ |
176 | ␉{ FDISK_ENCRYPTED, "Apple_Encrypted" }, // 0xAE␊ |
177 | ␉{ FDISK_HFS,␉␉"Apple HFS" }, // 0xAF␊ |
178 | ␉{ 0xCD,␉␉␉"CD-ROM" }, // 0xCD␊ |
179 | ␉{ FDISK_BEFS, "Haiku" }, // 0xEB␊ |
180 | ␉{ FDISK_LINUX_RAID, "Linux_RAID" }, // 0xFD␊ |
181 | ␉{ 0x00,␉␉␉NULL } /* must be last */␊ |
182 | };␊ |
183 | ␊ |
184 | //==============================================================================␊ |
185 | extern void spinActivityIndicator(int sectors);␊ |
186 | ␊ |
187 | //==============================================================================␊ |
188 | static int getDriveInfo( int biosdev, struct driveInfo *dip )␊ |
189 | {␊ |
190 | ␉static struct driveInfo cached_di;␊ |
191 | ␉int cc;␊ |
192 | ␊ |
193 | ␉// Real BIOS devices are 8-bit, so anything above that is for internal use.␊ |
194 | ␉// Don't cache ramdisk drive info since it doesn't require several BIOS␊ |
195 | ␉// calls and is thus not worth it.␊ |
196 | ␉if (biosdev >= 0x100)␊ |
197 | ␉{␊ |
198 | ␉␉if (p_get_ramdisk_info != NULL)␊ |
199 | ␉␉{␊ |
200 | ␉␉␉cc = (*p_get_ramdisk_info)(biosdev, dip);␊ |
201 | ␉␉}␊ |
202 | ␉␉else␊ |
203 | ␉␉{␊ |
204 | ␉␉␉cc = -1;␊ |
205 | ␉␉}␊ |
206 | ␉␉if (cc < 0)␊ |
207 | ␉␉{␊ |
208 | ␉␉␉dip->valid = 0;␊ |
209 | ␉␉␉return -1;␊ |
210 | ␉␉}␊ |
211 | ␉␉else␊ |
212 | ␉␉{␊ |
213 | ␉␉␉return 0;␊ |
214 | ␉␉}␊ |
215 | ␉}␊ |
216 | ␊ |
217 | ␉if (!cached_di.valid || biosdev != cached_di.biosdev)␊ |
218 | ␉{␊ |
219 | ␉␉cc = get_drive_info(biosdev, &cached_di);␊ |
220 | ␊ |
221 | ␉␉if (cc < 0)␊ |
222 | ␉␉{␊ |
223 | ␉␉␉cached_di.valid = 0;␊ |
224 | ␉␉␉DEBUG_DISK(("get_drive_info returned error\n"));␊ |
225 | ␉␉␉return (-1); // BIOS call error␊ |
226 | ␉␉}␊ |
227 | ␉}␊ |
228 | ␊ |
229 | ␉bcopy(&cached_di, dip, sizeof(cached_di));␊ |
230 | ␊ |
231 | ␉return 0;␊ |
232 | }␊ |
233 | ␊ |
234 | //==============================================================================␊ |
235 | static const char *getNameForValue( const struct NamedValue *nameTable, unsigned char value )␊ |
236 | {␊ |
237 | ␉const struct NamedValue *np;␊ |
238 | ␊ |
239 | ␉for ( np = nameTable; np->value; np++)␊ |
240 | ␉{␊ |
241 | ␉␉if (np->value == value)␊ |
242 | ␉␉{␊ |
243 | ␉␉␉return np->name;␊ |
244 | ␉␉}␊ |
245 | ␉}␊ |
246 | ␊ |
247 | ␉return NULL;␊ |
248 | }␊ |
249 | ␊ |
250 | //==============================================================================␊ |
251 | static const char *bios_error(int errnum)␊ |
252 | {␊ |
253 | ␉static char errorstr[] = "Error 0x00";␊ |
254 | ␉const char * errname;␊ |
255 | ␊ |
256 | ␉errname = getNameForValue(bios_errors, errnum);␊ |
257 | ␊ |
258 | ␉if (errname)␊ |
259 | ␉{␊ |
260 | ␉␉return errname;␊ |
261 | ␉}␊ |
262 | ␊ |
263 | ␉snprintf(errorstr, sizeof(errorstr), "Error 0x%02x", errnum);␊ |
264 | ␉return errorstr; // No string, print error code only␊ |
265 | }␊ |
266 | ␊ |
267 | //==========================================================================␊ |
268 | // Use BIOS INT13 calls to read the sector specified. This function will␊ |
269 | // also perform read-ahead to cache a few subsequent sector to the sector␊ |
270 | // cache.␊ |
271 | // ␊ |
272 | // Return:␊ |
273 | // 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call.␊ |
274 | ␊ |
275 | static int Biosread( int biosdev, unsigned long long secno )␊ |
276 | {␊ |
277 | ␉static int xbiosdev, xcyl, xhead;␊ |
278 | ␉static unsigned int xsec, xnsecs;␊ |
279 | ␉struct driveInfo di;␊ |
280 | ␊ |
281 | ␉int rc = -1;␊ |
282 | ␉int cyl, head, sec;␊ |
283 | ␉int tries = 0;␊ |
284 | ␉int bps, divisor;␊ |
285 | ␊ |
286 | ␉if (getDriveInfo(biosdev, &di) < 0)␊ |
287 | ␉{␊ |
288 | ␉␉return -1;␊ |
289 | ␉}␊ |
290 | ␊ |
291 | ␉if (di.no_emulation)␊ |
292 | ␉{␊ |
293 | ␉␉bps = 2048; /* Always assume 2K block size since the BIOS may lie about the geometry */␊ |
294 | ␉}␊ |
295 | ␉else␊ |
296 | ␉{␊ |
297 | ␉␉bps = di.di.params.phys_nbps;␊ |
298 | ␊ |
299 | ␉␉if (bps == 0)␊ |
300 | ␉␉{␊ |
301 | ␉␉␉return -1;␊ |
302 | ␉␉}␊ |
303 | ␉}␊ |
304 | ␊ |
305 | ␉divisor = bps / BPS;␊ |
306 | ␊ |
307 | ␉DEBUG_DISK(("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps));␊ |
308 | ␊ |
309 | ␉// To read the disk sectors, use EBIOS if we can. Otherwise,␊ |
310 | ␉// revert to the standard BIOS calls.␊ |
311 | ␊ |
312 | ␉if ((biosdev >= kBIOSDevTypeHardDrive) && (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS))␊ |
313 | ␉{␊ |
314 | ␉␉if (cache_valid && (biosdev == xbiosdev) && (secno >= xsec) && ((unsigned int)secno < (xsec + xnsecs)))␊ |
315 | ␉␉{␊ |
316 | ␉␉␉biosbuf = trackbuf + (BPS * (secno - xsec));␊ |
317 | ␉␉␉return 0;␊ |
318 | ␉␉}␊ |
319 | ␊ |
320 | ␉␉xnsecs = N_CACHE_SECS;␊ |
321 | ␉␉xsec = (secno / divisor) * divisor;␊ |
322 | ␉␉cache_valid = false;␊ |
323 | ␊ |
324 | ␉␉while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5))␊ |
325 | ␉␉{␊ |
326 | ␉␉␉if (rc == ECC_CORRECTED_ERR)␊ |
327 | ␉␉␉{␊ |
328 | ␉␉␉␉rc = 0; // Ignore corrected ECC errors␊ |
329 | ␉␉␉␉break;␊ |
330 | ␉␉␉}␊ |
331 | ␊ |
332 | ␉␉␉error(" EBIOS read error: %s\n", bios_error(rc), rc);␊ |
333 | ␉␉␉error(" Block 0x%x Sectors %d\n", secno, xnsecs);␊ |
334 | ␉␉␉sleep(1);␊ |
335 | ␉␉}␊ |
336 | ␉}␊ |
337 | ␊ |
338 | ␉else␊ |
339 | ␉{␊ |
340 | ␉␉/* spc = spt * heads */␊ |
341 | ␉␉int spc = (di.di.params.phys_spt * di.di.params.phys_heads);␊ |
342 | ␉␉cyl = secno / spc;␊ |
343 | ␉␉head = (secno % spc) / di.di.params.phys_spt;␊ |
344 | ␉␉sec = secno % di.di.params.phys_spt;␊ |
345 | ␊ |
346 | ␉␉if (cache_valid && (biosdev == xbiosdev) && (cyl == xcyl) &&␊ |
347 | ␉␉␉(head == xhead) && ((unsigned int)sec >= xsec) && ((unsigned int)sec < (xsec + xnsecs)))␊ |
348 | ␊ |
349 | ␉␉{␊ |
350 | ␉␉␉// this sector is in trackbuf cache␊ |
351 | ␉␉␉biosbuf = trackbuf + (BPS * (sec - xsec));␊ |
352 | ␉␉␉return 0;␊ |
353 | ␉␉}␊ |
354 | ␊ |
355 | ␉␉// Cache up to a track worth of sectors, but do not cross a track boundary.␊ |
356 | ␊ |
357 | ␉␉xcyl = cyl;␊ |
358 | ␉␉xhead = head;␊ |
359 | ␉␉xsec = sec;␊ |
360 | ␉␉xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS;␊ |
361 | ␊ |
362 | ␉␉cache_valid = false;␊ |
363 | ␊ |
364 | ␉␉while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && (++tries < 5))␊ |
365 | ␉␉{␊ |
366 | ␉␉␉if (rc == ECC_CORRECTED_ERR)␊ |
367 | ␉␉␉{␊ |
368 | ␉␉␉␉rc = 0; // Ignore corrected ECC errors␊ |
369 | ␉␉␉␉break;␊ |
370 | ␉␉␉}␊ |
371 | ␊ |
372 | ␉␉␉error(" BIOS read error: %s\n", bios_error(rc), rc);␊ |
373 | ␉␉␉error(" Block %d, Cyl %d Head %d Sector %d\n", secno, cyl, head, sec);␊ |
374 | ␉␉␉sleep(1);␊ |
375 | ␉␉}␊ |
376 | ␉}␊ |
377 | ␊ |
378 | ␉// If the BIOS reported success, mark the sector cache as valid.␊ |
379 | ␊ |
380 | ␉if (rc == 0)␊ |
381 | ␉{␊ |
382 | ␉␉cache_valid = true;␊ |
383 | ␉}␊ |
384 | ␊ |
385 | ␉biosbuf = trackbuf + (secno % divisor) * BPS;␊ |
386 | ␉xbiosdev = biosdev;␊ |
387 | ␊ |
388 | ␉spinActivityIndicator(xnsecs);␊ |
389 | ␊ |
390 | ␉return rc;␊ |
391 | }␊ |
392 | ␊ |
393 | //==============================================================================␊ |
394 | int testBiosread(int biosdev, unsigned long long secno)␊ |
395 | {␊ |
396 | ␉return Biosread(biosdev, secno);␊ |
397 | }␊ |
398 | ␊ |
399 | //==============================================================================␊ |
400 | static int readBytes(int biosdev, unsigned long long blkno, unsigned int byteoff, unsigned int byteCount, void *buffer)␊ |
401 | {␊ |
402 | ␉// ramdisks require completely different code for reading.␊ |
403 | ␉if(p_ramdiskReadBytes != NULL && biosdev >= 0x100)␊ |
404 | ␉{␊ |
405 | ␉␉return (*p_ramdiskReadBytes)(biosdev, blkno, byteoff, byteCount, buffer);␊ |
406 | ␉}␊ |
407 | ␊ |
408 | ␉char * cbuf = (char *) buffer;␊ |
409 | ␉int error;␊ |
410 | ␉int copy_len;␊ |
411 | ␊ |
412 | ␉DEBUG_DISK(("%s: dev %X block %X [%d] -> 0x%X...", __FUNCTION__, biosdev, blkno, byteCount, (unsigned)cbuf));␊ |
413 | ␊ |
414 | ␉for (; byteCount; cbuf += copy_len, blkno++)␊ |
415 | ␉{␊ |
416 | ␉␉error = Biosread(biosdev, blkno);␊ |
417 | ␊ |
418 | ␉␉if (error)␊ |
419 | ␉␉{␊ |
420 | ␉␉␉DEBUG_DISK(("error\n"));␊ |
421 | ␊ |
422 | ␉␉␉return (-1);␊ |
423 | ␉␉}␊ |
424 | ␊ |
425 | ␉␉copy_len = ((byteCount + byteoff) > BPS) ? (BPS - byteoff) : byteCount;␊ |
426 | ␉␉bcopy( biosbuf + byteoff, cbuf, copy_len );␊ |
427 | ␉␉byteCount -= copy_len;␊ |
428 | ␉␉byteoff = 0;␊ |
429 | ␉}␊ |
430 | ␊ |
431 | ␉DEBUG_DISK(("done\n"));␊ |
432 | ␊ |
433 | ␉return 0; ␊ |
434 | }␊ |
435 | ␊ |
436 | //==============================================================================␊ |
437 | static int isExtendedFDiskPartition( const struct fdisk_part *part )␊ |
438 | {␊ |
439 | ␉static unsigned char extParts[] =␊ |
440 | ␉{␊ |
441 | ␉␉0x05, /* Extended */␊ |
442 | ␉␉0x0f, /* Win95 extended */␊ |
443 | ␉␉0x85, /* Linux extended */␊ |
444 | ␉};␊ |
445 | ␊ |
446 | ␉unsigned int i;␊ |
447 | ␊ |
448 | ␉for (i = 0; i < sizeof(extParts)/sizeof(extParts[0]); i++)␊ |
449 | ␉{␊ |
450 | ␉␉if (extParts[i] == part->systid)␊ |
451 | ␉␉{␊ |
452 | ␉␉␉return 1;␊ |
453 | ␉␉}␊ |
454 | ␉}␊ |
455 | ␉return 0;␊ |
456 | }␊ |
457 | ␊ |
458 | //==============================================================================␊ |
459 | static int getNextFDiskPartition( int biosdev, int *partno, const struct fdisk_part **outPart )␊ |
460 | {␊ |
461 | ␉static int sBiosdev = -1;␊ |
462 | ␉static int sNextPartNo;␊ |
463 | ␉static unsigned int sFirstBase;␊ |
464 | ␉static unsigned int sExtBase;␊ |
465 | ␉static unsigned int sExtDepth;␊ |
466 | ␉static struct fdisk_part *sExtPart;␊ |
467 | ␉struct fdisk_part *part;␊ |
468 | ␊ |
469 | ␉if ( sBiosdev != biosdev || *partno < 0 )␊ |
470 | ␉{␊ |
471 | ␉␉// Fetch MBR.␊ |
472 | ␉␉if ( readBootSector( biosdev, DISK_BLK0, 0 ) )␊ |
473 | ␉␉{␊ |
474 | ␉␉␉return 0;␊ |
475 | ␉␉}␊ |
476 | ␊ |
477 | ␉␉sBiosdev = biosdev;␊ |
478 | ␉␉sNextPartNo = 0;␊ |
479 | ␉␉sFirstBase = 0;␊ |
480 | ␉␉sExtBase = 0;␊ |
481 | ␉␉sExtDepth = 0;␊ |
482 | ␉␉sExtPart = NULL;␊ |
483 | ␉}␊ |
484 | ␊ |
485 | ␉while (1)␊ |
486 | ␉{␊ |
487 | ␉␉part = NULL;␊ |
488 | ␊ |
489 | ␉␉if ( sNextPartNo < FDISK_NPART )␊ |
490 | ␉␉{␊ |
491 | ␉␉␉part = (struct fdisk_part *) gBootSector->parts[sNextPartNo];␊ |
492 | ␉␉}␊ |
493 | ␉␉else if ( sExtPart )␊ |
494 | ␉␉{␊ |
495 | ␉␉␉unsigned int blkno = sExtPart->relsect + sFirstBase;␊ |
496 | ␊ |
497 | ␉␉␉// Save the block offset of the first extended partition.␊ |
498 | ␊ |
499 | ␉␉␉if (sExtDepth == 0)␊ |
500 | ␉␉␉{␊ |
501 | ␉␉␉␉sFirstBase = blkno;␊ |
502 | ␉␉␉}␊ |
503 | ␉␉␉sExtBase = blkno;␊ |
504 | ␊ |
505 | ␉␉␉// Load extended partition table.␊ |
506 | ␊ |
507 | ␉␉␉if ( readBootSector( biosdev, blkno, 0 ) == 0 )␊ |
508 | ␉␉␉{␊ |
509 | ␉␉␉␉sNextPartNo = 0;␊ |
510 | ␉␉␉␉sExtDepth++;␊ |
511 | ␉␉␉␉sExtPart = NULL;␊ |
512 | ␉␉␉␉continue;␊ |
513 | ␉␉␉}␊ |
514 | ␉␉␉// Fall through to part == NULL␊ |
515 | ␉␉}␊ |
516 | ␊ |
517 | ␉␉if ( part == NULL ) break; // Reached end of partition chain.␊ |
518 | ␊ |
519 | ␉␉// Advance to next partition number.␊ |
520 | ␊ |
521 | ␉␉sNextPartNo++;␊ |
522 | ␊ |
523 | ␉␉if ( isExtendedFDiskPartition(part) )␊ |
524 | ␉␉{␊ |
525 | ␉␉␉sExtPart = part;␊ |
526 | ␉␉␉continue;␊ |
527 | ␉␉}␊ |
528 | ␊ |
529 | ␉␉// Skip empty slots.␊ |
530 | ␊ |
531 | ␉␉if ( part->systid == 0x00 )␊ |
532 | ␉␉{␊ |
533 | ␉␉␉continue;␊ |
534 | ␉␉}␊ |
535 | ␊ |
536 | ␉␉// Change relative offset to an absolute offset.␊ |
537 | ␉␉part->relsect += sExtBase;␊ |
538 | ␊ |
539 | ␉␉*outPart = part;␊ |
540 | ␉␉*partno = sExtDepth ? (int)(sExtDepth + FDISK_NPART) : sNextPartNo;␊ |
541 | ␊ |
542 | ␉␉break;␊ |
543 | ␉}␊ |
544 | ␊ |
545 | ␉return (part != NULL);␊ |
546 | }␊ |
547 | ␊ |
548 | //==============================================================================␊ |
549 | /*␊ |
550 | * Trying to figure out the filsystem type of a given partition.␊ |
551 | * X = fdisk partition type␊ |
552 | * 0 = Unknown/Unused␊ |
553 | * -1 = error␊ |
554 | */␊ |
555 | static int probeFileSystem(int biosdev, unsigned int blkoff)␊ |
556 | {␊ |
557 | ␉// detected filesystem type;␊ |
558 | ␉int result = -1;␊ |
559 | ␉int fatbits = 0;␊ |
560 | ␊ |
561 | ␉// Allocating buffer for 4 sectors.␊ |
562 | ␉const void *probeBuffer = malloc(PROBEFS_SIZE);␊ |
563 | ␉if (probeBuffer == NULL)␊ |
564 | ␉{␊ |
565 | ␉␉verbose("\t[probeFileSystem] Error: can't alloc memory for probe buffer.\n");␊ |
566 | ␉␉goto exit;␊ |
567 | ␉}␊ |
568 | ␊ |
569 | ␉// Reading first 4 sectors of current partition␊ |
570 | ␉int error = readBytes(biosdev, blkoff, 0, PROBEFS_SIZE, (void *)probeBuffer);␊ |
571 | ␊ |
572 | ␉if (error)␊ |
573 | ␉{␊ |
574 | ␉␉verbose("\t[probeFileSystem] Error: can't read from device=%02Xh.\n", biosdev);␊ |
575 | ␉␉goto exit;␊ |
576 | ␉}␊ |
577 | ␊ |
578 | ␉if (HFSProbe(probeBuffer))␊ |
579 | ␉{␊ |
580 | ␉␉result = FDISK_HFS;␊ |
581 | ␉}␊ |
582 | ␉else if (EX2Probe(probeBuffer))␊ |
583 | ␉{␊ |
584 | ␉␉result = FDISK_LINUX;␊ |
585 | ␉}␊ |
586 | ␉else if (FreeBSDProbe(probeBuffer))␊ |
587 | ␉{␊ |
588 | ␉␉result = FDISK_FREEBSD;␊ |
589 | ␉}␊ |
590 | ␉else if (OpenBSDProbe(probeBuffer))␊ |
591 | ␉{␊ |
592 | ␉␉result = FDISK_OPENBSD;␊ |
593 | ␉}␊ |
594 | ␉else if (BeFSProbe(probeBuffer))␊ |
595 | ␉{␊ |
596 | ␉␉result = FDISK_BEFS;␊ |
597 | ␉}␊ |
598 | ␉else if (NTFSProbe(probeBuffer))␊ |
599 | ␉{␊ |
600 | ␉␉result = FDISK_NTFS;␊ |
601 | ␉}␊ |
602 | ␊ |
603 | ␉else if (EXFATProbe(probeBuffer))␊ |
604 | ␉{␊ |
605 | ␉␉result = FDISK_PSEUDO_EXFAT;␊ |
606 | ␉}␊ |
607 | ␊ |
608 | ␉else if ((fatbits = MSDOSProbe(probeBuffer)))␊ |
609 | ␉{␊ |
610 | ␉␉switch (fatbits)␊ |
611 | ␉␉{␊ |
612 | ␉␉␉case 12:␊ |
613 | ␉␉␉␉result = FDISK_DOS12;␊ |
614 | ␉␉␉␉break;␊ |
615 | ␊ |
616 | ␉␉␉case 16:␊ |
617 | ␉␉␉␉result = FDISK_DOS16B;␊ |
618 | ␉␉␉␉break;␊ |
619 | ␊ |
620 | ␉␉␉case 32:␊ |
621 | ␉␉␉default:␊ |
622 | ␉␉␉␉result = FDISK_FAT32;␊ |
623 | ␉␉␉␉break;␊ |
624 | ␉␉}␊ |
625 | ␉}␊ |
626 | ␉else␊ |
627 | ␉{␊ |
628 | ␉␉// Couldn't detect filesystem type␊ |
629 | ␉␉result = 0;␊ |
630 | ␉}␊ |
631 | ␊ |
632 | exit:␊ |
633 | ␉if (probeBuffer)␊ |
634 | ␉{␊ |
635 | ␉␉free((void *)probeBuffer);␊ |
636 | ␉}␊ |
637 | ␊ |
638 | ␉return result;␊ |
639 | }␊ |
640 | ␊ |
641 | //==============================================================================␊ |
642 | static BVRef newFDiskBVRef( int biosdev,␊ |
643 | int partno,␊ |
644 | unsigned int blkoff,␊ |
645 | const struct fdisk_part *part,␊ |
646 | FSInit initFunc,␊ |
647 | FSLoadFile loadFunc,␊ |
648 | FSReadFile readFunc,␊ |
649 | FSGetDirEntry getdirFunc,␊ |
650 | FSGetFileBlock getBlockFunc,␊ |
651 | FSGetUUID getUUIDFunc,␊ |
652 | BVGetDescription getDescriptionFunc,␊ |
653 | BVFree bvFreeFunc,␊ |
654 | int probe, int type, unsigned int bvrFlags )␊ |
655 | {␊ |
656 | ␉BVRef bvr = (BVRef)malloc(sizeof(*bvr));␊ |
657 | ␉if ( bvr )␊ |
658 | ␉{␊ |
659 | ␉␉bzero(bvr, sizeof(*bvr));␊ |
660 | ␊ |
661 | ␉␉bvr->biosdev = biosdev;␊ |
662 | ␉␉bvr->part_no = partno;␊ |
663 | ␉␉bvr->part_boff = blkoff;␊ |
664 | ␉␉bvr->part_type = part->systid;␊ |
665 | ␉␉bvr->fs_loadfile = loadFunc;␊ |
666 | ␉␉bvr->fs_readfile = readFunc;␊ |
667 | ␉␉bvr->fs_getdirentry = getdirFunc;␊ |
668 | ␉␉bvr->fs_getfileblock= getBlockFunc;␊ |
669 | ␉␉bvr->fs_getuuid = getUUIDFunc;␊ |
670 | ␉␉bvr->description = getDescriptionFunc;␊ |
671 | ␉␉bvr->type = type;␊ |
672 | ␉␉bvr->bv_free = bvFreeFunc;␊ |
673 | ␊ |
674 | ␉␉if ((part->bootid & FDISK_ACTIVE) && (part->systid == FDISK_HFS))␊ |
675 | ␉␉{␊ |
676 | ␉␉␉bvr->flags |= kBVFlagPrimary;␊ |
677 | ␉␉}␊ |
678 | ␊ |
679 | ␉␉// Probe the filesystem.␊ |
680 | ␊ |
681 | ␉␉if ( initFunc )␊ |
682 | ␉␉{␊ |
683 | ␉␉␉bvr->flags |= kBVFlagNativeBoot;␊ |
684 | ␊ |
685 | ␉␉␉if ( probe && initFunc( bvr ) != 0 )␊ |
686 | ␉␉␉{␊ |
687 | ␉␉␉␉// filesystem probe failed.␊ |
688 | ␊ |
689 | ␉␉␉␉DEBUG_DISK(("%s: failed probe on dev %X part %d\n", __FUNCTION__, biosdev, partno));␊ |
690 | ␊ |
691 | ␉␉␉␉(*bvr->bv_free)(bvr);␊ |
692 | ␉␉␉␉bvr = NULL;␊ |
693 | ␉␉␉}␊ |
694 | ␊ |
695 | ␉␉␉if ( bvr && readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )␊ |
696 | ␉␉␉{␊ |
697 | ␉␉␉␉bvr->flags |= kBVFlagBootable;␊ |
698 | ␉␉␉}␊ |
699 | ␉␉}␊ |
700 | ␉␉else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )␊ |
701 | ␉␉{␊ |
702 | ␉␉␉/*␊ |
703 | ␉␉␉ * This is an ugly place to check for exfat/FDisk, but it reads␊ |
704 | ␉␉␉ * the partition boot sector only once.␊ |
705 | ␉␉␉ */␊ |
706 | ␉␉␉if (bvr->part_type == FDISK_NTFS && EXFATProbe((void const *)0x7e00))␊ |
707 | ␉␉␉{␊ |
708 | ␉␉␉␉bvr->flags |= kBVFlagNativeBoot | kBVFlagBootable;␊ |
709 | ␉␉␉␉bvr->fs_loadfile = EXFATLoadFile;␊ |
710 | ␉␉␉␉bvr->fs_readfile = EXFATReadFile;␊ |
711 | ␉␉␉␉bvr->fs_getdirentry = EXFATGetDirEntry;␊ |
712 | ␉␉␉␉bvr->fs_getfileblock= EXFATGetFileBlock;␊ |
713 | ␉␉␉␉bvr->fs_getuuid = EXFATGetUUID;␊ |
714 | ␉␉␉␉bvr->description = EXFATGetDescription;␊ |
715 | ␉␉␉␉bvr->bv_free = EXFATFree;␊ |
716 | ␉␉␉}␊ |
717 | ␉␉␉else␊ |
718 | ␉␉␉{␊ |
719 | ␉␉␉␉bvr->flags |= kBVFlagForeignBoot;␊ |
720 | ␉␉␉}␊ |
721 | ␉␉}␊ |
722 | ␉␉else␊ |
723 | ␉␉{␊ |
724 | ␉␉␉(*bvr->bv_free)(bvr);␊ |
725 | ␉␉␉bvr = NULL;␊ |
726 | ␉␉}␊ |
727 | ␉}␊ |
728 | ␊ |
729 | ␉if ( bvr )␊ |
730 | ␉{␊ |
731 | ␉␉bvr->flags |= bvrFlags;␊ |
732 | ␉}␊ |
733 | ␊ |
734 | ␉return bvr;␊ |
735 | }␊ |
736 | ␊ |
737 | //==============================================================================␊ |
738 | static BVRef newAPMBVRef( int biosdev, int partno, unsigned int blkoff,␊ |
739 | const DPME * part,␊ |
740 | FSInit initFunc, FSLoadFile loadFunc,␊ |
741 | FSReadFile readFunc,␊ |
742 | FSGetDirEntry getdirFunc,␊ |
743 | FSGetFileBlock getBlockFunc,␊ |
744 | FSGetUUID getUUIDFunc,␊ |
745 | BVGetDescription getDescriptionFunc,␊ |
746 | BVFree bvFreeFunc,␊ |
747 | int probe, int type, unsigned int bvrFlags )␊ |
748 | {␊ |
749 | ␉BVRef bvr = (BVRef)malloc(sizeof(*bvr));␊ |
750 | ␉if ( bvr )␊ |
751 | ␉{␊ |
752 | ␉␉bzero(bvr, sizeof(*bvr));␊ |
753 | ␊ |
754 | ␉␉bvr->biosdev = biosdev;␊ |
755 | ␉␉bvr->part_no = partno;␊ |
756 | ␉␉bvr->part_boff = blkoff;␊ |
757 | ␉␉bvr->fs_loadfile = loadFunc;␊ |
758 | ␉␉bvr->fs_readfile = readFunc;␊ |
759 | ␉␉bvr->fs_getdirentry = getdirFunc;␊ |
760 | ␉␉bvr->fs_getfileblock= getBlockFunc;␊ |
761 | ␉␉bvr->fs_getuuid = getUUIDFunc;␊ |
762 | ␉␉bvr->description = getDescriptionFunc;␊ |
763 | ␉␉bvr->type = type;␊ |
764 | ␉␉bvr->bv_free = bvFreeFunc;␊ |
765 | ␉␉strlcpy(bvr->name, part->dpme_name, DPISTRLEN);␊ |
766 | ␉␉strlcpy(bvr->type_name, part->dpme_type, DPISTRLEN);␊ |
767 | ␊ |
768 | ␉␉/*␊ |
769 | ␉␉if ( part->bootid & FDISK_ACTIVE )␊ |
770 | ␉␉{␊ |
771 | ␉␉␉bvr->flags |= kBVFlagPrimary;␊ |
772 | ␉␉}␊ |
773 | ␉␉*/␊ |
774 | ␊ |
775 | ␉␉// Probe the filesystem.␊ |
776 | ␊ |
777 | ␉␉if ( initFunc )␊ |
778 | ␉␉{␊ |
779 | ␉␉␉bvr->flags |= kBVFlagNativeBoot | kBVFlagBootable | kBVFlagSystemVolume;␊ |
780 | ␊ |
781 | ␉␉␉if ( probe && initFunc( bvr ) != 0 )␊ |
782 | ␉␉␉{␊ |
783 | ␉␉␉␉// filesystem probe failed.␊ |
784 | ␊ |
785 | ␉␉␉␉DEBUG_DISK(("%s: failed probe on dev %X part %d\n", __FUNCTION__, biosdev, partno));␊ |
786 | ␊ |
787 | ␉␉␉␉(*bvr->bv_free)(bvr);␊ |
788 | ␉␉␉␉bvr = NULL;␊ |
789 | ␉␉␉}␊ |
790 | ␉␉}␊ |
791 | ␉␉/*␊ |
792 | ␉␉else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )␊ |
793 | ␉␉{␊ |
794 | ␉␉␉bvr->flags |= kBVFlagForeignBoot;␊ |
795 | ␉␉}␊ |
796 | ␉␉*/␊ |
797 | ␉␉else␊ |
798 | ␉␉{␊ |
799 | ␉␉␉(*bvr->bv_free)(bvr);␊ |
800 | ␉␉␉bvr = NULL;␊ |
801 | ␉␉}␊ |
802 | ␉}␊ |
803 | ␊ |
804 | ␉if ( bvr )␊ |
805 | ␉{␊ |
806 | ␉␉bvr->flags |= bvrFlags;␊ |
807 | ␉}␊ |
808 | ␊ |
809 | ␉return bvr;␊ |
810 | }␊ |
811 | ␊ |
812 | //==============================================================================␊ |
813 | ␊ |
814 | // GUID's in LE form:␊ |
815 | // HFS+ partition - 48465300-0000-11AA-AA11-00306543ECAC␊ |
816 | EFI_GUID const GPT_HFS_GUID␉␉= { 0x48465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF00 "Apple HFS/HFS+"␊ |
817 | ␊ |
818 | // turbo - Apple Boot Partition - 426F6F74-0000-11AA-AA11-00306543ECAC␊ |
819 | EFI_GUID const GPT_BOOT_GUID␉␉= { 0x426F6F74, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAB00 "Apple boot"␊ |
820 | ␊ |
821 | // turbo - or an EFI System Partition - C12A7328-F81F-11D2-BA4B-00A0C93EC93B␊ |
822 | EFI_GUID const GPT_EFISYS_GUID␉␉= { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B } }; // 0xEF00 "EFI System"␊ |
823 | ␊ |
824 | // zef - Basic Data Partition - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 for foreign OS support␊ |
825 | EFI_GUID const GPT_BASICDATA_GUID␉= { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } }; // 0x0100 "Microsoft basic data"␊ |
826 | ␊ |
827 | // Microsoft Reserved Partition - E3C9E316-0B5C-4DB8-817DF92DF00215AE␊ |
828 | EFI_GUID const GPT_BASICDATA2_GUID␉= { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE } }; // 0x0C01 "Microsoft reserved"␊ |
829 | ␊ |
830 | // Apple OSX␊ |
831 | //EFI_GUID const GPT_UFS_GUID␉␉= { 0x55465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xA800 "Apple UFS"␊ |
832 | //EFI_GUID const GPT_RAID_GUID␉␉= { 0x52414944, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF01 "Apple RAID"␊ |
833 | //EFI_GUID const GPT_RAID_OFFLINE_GUID␉= { 0x52414944, 0x5f4f, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF02 "Apple RAID offline"␊ |
834 | //EFI_GUID const GPT_LABEL_GUID␉␉= { 0x4C616265, 0x6C00, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF03 "Apple label"␊ |
835 | //EFI_GUID const GPT_APPLETV_GUID␉= { 0x5265636F, 0x7665, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF04 "Apple TV recovery"␊ |
836 | EFI_GUID const GPT_CORESTORAGE_GUID␉= { 0x53746F72, 0x6167, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; // 0xAF05 "Apple Core storage"␊ |
837 | // same as Apple ZFS␊ |
838 | //EFI_GUID const GPT_ZFS_GUID␉␉= { 0x6A898CC3, 0x1DD2, 0x11B2, { 0x99, 0xA6, 0x08, 0x00, 0x20, 0x73, 0x66, 0x31 } }; // 0xBF01 "Solaris /usr & Apple ZFS␊ |
839 | ␊ |
840 | static BVRef newGPTBVRef( int biosdev,␊ |
841 | int partno,␊ |
842 | unsigned int blkoff,␊ |
843 | const gpt_ent *part,␊ |
844 | FSInit initFunc,␊ |
845 | FSLoadFile loadFunc,␊ |
846 | FSReadFile readFunc,␊ |
847 | FSGetDirEntry getdirFunc,␊ |
848 | FSGetFileBlock getBlockFunc,␊ |
849 | FSGetUUID getUUIDFunc,␊ |
850 | BVGetDescription getDescriptionFunc,␊ |
851 | BVFree bvFreeFunc,␊ |
852 | int probe,␊ |
853 | int type,␊ |
854 | unsigned int bvrFlags )␊ |
855 | {␊ |
856 | ␉BVRef bvr = (BVRef)malloc(sizeof(*bvr));␊ |
857 | ␉if ( bvr )␊ |
858 | ␉{␊ |
859 | ␉␉bzero(bvr, sizeof(*bvr));␊ |
860 | ␊ |
861 | ␉␉bvr->biosdev = biosdev;␊ |
862 | ␉␉bvr->part_no = partno;␊ |
863 | ␉␉bvr->part_boff = blkoff;␊ |
864 | ␉␉bvr->fs_loadfile = loadFunc;␊ |
865 | ␉␉bvr->fs_readfile = readFunc;␊ |
866 | ␉␉bvr->fs_getdirentry = getdirFunc;␊ |
867 | ␉␉bvr->fs_getfileblock = getBlockFunc;␊ |
868 | ␉␉bvr->fs_getuuid = getUUIDFunc;␊ |
869 | ␉␉bvr->description = getDescriptionFunc;␊ |
870 | ␉␉bvr->type = type;␊ |
871 | ␉␉bvr->bv_free = bvFreeFunc;␊ |
872 | ␉␉// FIXME: UCS-2 -> UTF-8 the name␊ |
873 | ␉␉strlcpy(bvr->name, "----", DPISTRLEN);␊ |
874 | ␉␉if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)part->ent_type) == 0) || (efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)part->ent_type) == 0) )␊ |
875 | ␉␉{␊ |
876 | ␉␉␉strlcpy(bvr->type_name, "GPT HFS+", DPISTRLEN);␊ |
877 | ␉␉}␊ |
878 | ␉␉else␊ |
879 | ␉␉{␊ |
880 | ␉␉␉strlcpy(bvr->type_name, "GPT Unknown", DPISTRLEN);␊ |
881 | ␉␉}␊ |
882 | ␊ |
883 | ␉␉/*␊ |
884 | ␉␉if ( part->bootid & FDISK_ACTIVE )␊ |
885 | ␉␉{␊ |
886 | ␉␉␉bvr->flags |= kBVFlagPrimary;␊ |
887 | ␉␉}␊ |
888 | ␉␉*/␊ |
889 | ␊ |
890 | ␉␉// Probe the filesystem.␊ |
891 | ␊ |
892 | ␉␉if ( initFunc )␊ |
893 | ␉␉{␊ |
894 | ␉␉␉bvr->flags |= kBVFlagNativeBoot;␊ |
895 | ␊ |
896 | ␉␉␉if ( probe && initFunc( bvr ) != 0 )␊ |
897 | ␉␉␉{␊ |
898 | ␉␉␉␉// filesystem probe failed.␊ |
899 | ␊ |
900 | ␉␉␉␉DEBUG_DISK(("%s: failed probe on dev %x part %d\n", __FUNCTION__, biosdev, partno));␊ |
901 | ␊ |
902 | ␉␉␉␉(*bvr->bv_free)(bvr);␊ |
903 | ␉␉␉␉bvr = NULL;␊ |
904 | ␉␉␉}␊ |
905 | ␉␉␉else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )␊ |
906 | ␉␉␉{␊ |
907 | ␉␉␉␉bvr->flags |= kBVFlagBootable;␊ |
908 | ␉␉␉}␊ |
909 | ␉␉}␊ |
910 | ␉␉else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )␊ |
911 | ␉␉{␊ |
912 | ␉␉␉bvr->flags |= kBVFlagForeignBoot;␊ |
913 | ␉␉}␊ |
914 | ␉␉else␊ |
915 | ␉␉{␊ |
916 | ␉␉␉(*bvr->bv_free)(bvr);␊ |
917 | ␉␉␉bvr = NULL;␊ |
918 | ␉␉}␊ |
919 | ␉}␊ |
920 | ␊ |
921 | ␉if ( bvr )␊ |
922 | ␉{␊ |
923 | ␉␉bvr->flags |= bvrFlags;␊ |
924 | ␉}␊ |
925 | ␊ |
926 | ␉return bvr;␊ |
927 | }␊ |
928 | ␊ |
929 | //==============================================================================␊ |
930 | ␊ |
931 | /* A note on partition numbers:␊ |
932 | * IOKit makes the primary partitions numbers 1-4, and then␊ |
933 | * extended partitions are numbered consecutively 5 and up.␊ |
934 | * So, for example, if you have two primary partitions and␊ |
935 | * one extended partition they will be numbered 1, 2, 5.␊ |
936 | */␊ |
937 | static BVRef diskScanFDiskBootVolumes( int biosdev, int *countPtr )␊ |
938 | {␊ |
939 | const struct fdisk_part␉*part;␊ |
940 | struct DiskBVMap␉␉*map;␊ |
941 | int␉␉␉␉partno = -1;␊ |
942 | BVRef␉␉␉bvr;␊ |
943 | #if UFS_SUPPORT␊ |
944 | BVRef␉␉␉booterUFS = NULL;␊ |
945 | #endif␊ |
946 | int␉␉␉␉spc;␊ |
947 | struct driveInfo␉␉di;␊ |
948 | boot_drive_info_t␉␉*dp;␊ |
949 | ␊ |
950 | ␉verbose("\tAttempting to scan FDISK boot volumes [biosdev=%02Xh]:\n", biosdev);␊ |
951 | ␊ |
952 | ␉/* Initialize disk info */␊ |
953 | ␊ |
954 | ␉if (getDriveInfo(biosdev, &di) != 0)␊ |
955 | ␉{␊ |
956 | ␉␉return NULL;␊ |
957 | ␉}␊ |
958 | ␊ |
959 | ␉dp = &di.di;␊ |
960 | ␉spc = (dp->params.phys_spt * dp->params.phys_heads);␊ |
961 | ␊ |
962 | ␉if (spc == 0)␊ |
963 | ␉{␊ |
964 | ␉␉/* This is probably a CD-ROM; punt on the geometry. */␊ |
965 | ␉␉spc = 1;␊ |
966 | ␉}␊ |
967 | ␊ |
968 | ␉do␊ |
969 | ␉{␊ |
970 | ␉// Create a new mapping.␊ |
971 | ␊ |
972 | ␉map = (struct DiskBVMap *) malloc(sizeof(*map));␊ |
973 | ␊ |
974 | ␉if ( !map )␊ |
975 | ␉{␊ |
976 | ␉␉return NULL;␊ |
977 | ␉}␊ |
978 | ␊ |
979 | ␉if ( map )␊ |
980 | {␊ |
981 | ␉␉map->biosdev = biosdev;␊ |
982 | ␉␉map->bvr = NULL;␊ |
983 | ␉␉map->bvrcnt = 0;␊ |
984 | ␉␉map->next = gDiskBVMap;␊ |
985 | ␉␉gDiskBVMap = map;␊ |
986 | ␊ |
987 | ␉␉// Create a record for each partition found on the disk.␊ |
988 | ␊ |
989 | ␉␉while ( getNextFDiskPartition( biosdev, &partno, &part ) )␊ |
990 | ␉␉{␊ |
991 | ␉␉␉DEBUG_DISK(("%s: part %d [%X]\n", __FUNCTION__, partno, part->systid));␊ |
992 | ␉␉␉bvr = 0;␊ |
993 | ␊ |
994 | ␉␉␉switch ( part->systid )␊ |
995 | ␉␉␉{␊ |
996 | #if UFS_SUPPORT␊ |
997 | ␉␉␉␉case FDISK_UFS:␊ |
998 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
999 | ␉␉␉␉␉␉biosdev, partno,␊ |
1000 | ␉␉␉␉␉␉part->relsect + UFS_FRONT_PORCH/BPS,␊ |
1001 | ␉␉␉␉␉␉part,␊ |
1002 | ␉␉␉␉␉␉UFSInitPartition,␊ |
1003 | ␉␉␉␉␉␉UFSLoadFile,␊ |
1004 | ␉␉␉␉␉␉UFSReadFile,␊ |
1005 | ␉␉␉␉␉␉UFSGetDirEntry,␊ |
1006 | ␉␉␉␉␉␉UFSGetFileBlock,␊ |
1007 | ␉␉␉␉␉␉UFSGetUUID,␊ |
1008 | ␉␉␉␉␉␉UFSGetDescription,␊ |
1009 | ␉␉␉␉␉␉UFSFree,␊ |
1010 | ␉␉␉␉␉␉0,␊ |
1011 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1012 | ␉␉␉␉␉break;␊ |
1013 | #endif␊ |
1014 | ␊ |
1015 | ␉␉␉␉case FDISK_HFS:␊ |
1016 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1017 | ␉␉␉␉␉␉biosdev, partno,␊ |
1018 | ␉␉␉␉␉␉part->relsect,␊ |
1019 | ␉␉␉␉␉␉part,␊ |
1020 | ␉␉␉␉␉␉HFSInitPartition,␊ |
1021 | ␉␉␉␉␉␉HFSLoadFile,␊ |
1022 | ␉␉␉␉␉␉HFSReadFile,␊ |
1023 | ␉␉␉␉␉␉HFSGetDirEntry,␊ |
1024 | ␉␉␉␉␉␉HFSGetFileBlock,␊ |
1025 | ␉␉␉␉␉␉HFSGetUUID,␊ |
1026 | ␉␉␉␉␉␉HFSGetDescription,␊ |
1027 | ␉␉␉␉␉␉HFSFree,␊ |
1028 | ␉␉␉␉␉␉0,␊ |
1029 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1030 | ␉␉␉␉␉break;␊ |
1031 | ␊ |
1032 | ␉␉␉␉// turbo - we want the booter type scanned also␊ |
1033 | ␉␉␉␉case FDISK_BOOTER:␊ |
1034 | ␉␉␉␉␉if (part->bootid & FDISK_ACTIVE)␊ |
1035 | ␉␉␉␉␉{␊ |
1036 | ␉␉␉␉␉␉gBIOSBootVolume = newFDiskBVRef(␊ |
1037 | ␉␉␉␉␉␉␉biosdev, partno,␊ |
1038 | ␉␉␉␉␉␉␉part->relsect,␊ |
1039 | ␉␉␉␉␉␉␉part,␊ |
1040 | ␉␉␉␉␉␉␉HFSInitPartition,␊ |
1041 | ␉␉␉␉␉␉␉HFSLoadFile,␊ |
1042 | ␉␉␉␉␉␉␉HFSReadFile,␊ |
1043 | ␉␉␉␉␉␉␉HFSGetDirEntry,␊ |
1044 | ␉␉␉␉␉␉␉HFSGetFileBlock,␊ |
1045 | ␉␉␉␉␉␉␉HFSGetUUID,␊ |
1046 | ␉␉␉␉␉␉␉HFSGetDescription,␊ |
1047 | ␉␉␉␉␉␉␉HFSFree,␊ |
1048 | ␉␉␉␉␉␉␉0,␊ |
1049 | ␉␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1050 | ␉␉␉␉␉}␊ |
1051 | ␉␉␉␉␉break;␊ |
1052 | ␊ |
1053 | #if UFS_SUPPORT␊ |
1054 | ␉␉␉␉case FDISK_BOOTER:␊ |
1055 | ␉␉␉␉␉booterUFS = newFDiskBVRef(␊ |
1056 | ␉␉␉␉␉␉biosdev, partno,␊ |
1057 | ␉␉␉␉␉␉((part->relsect + spc - 1) / spc) * spc,␊ |
1058 | ␉␉␉␉␉␉part,␊ |
1059 | ␉␉␉␉␉␉UFSInitPartition,␊ |
1060 | ␉␉␉␉␉␉UFSLoadFile,␊ |
1061 | ␉␉␉␉␉␉UFSReadFile,␊ |
1062 | ␉␉␉␉␉␉UFSGetDirEntry,␊ |
1063 | ␉␉␉␉␉␉UFSGetFileBlock,␊ |
1064 | ␉␉␉␉␉␉UFSGetUUID,␊ |
1065 | ␉␉␉␉␉␉UFSGetDescription,␊ |
1066 | ␉␉␉␉␉␉UFSFree,␊ |
1067 | ␉␉␉␉␉␉0,␊ |
1068 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1069 | ␉␉␉␉␉break;␊ |
1070 | #endif␊ |
1071 | ␊ |
1072 | ␉␉␉␉case FDISK_FAT32:␊ |
1073 | ␉␉␉␉case FDISK_DOS12:␊ |
1074 | ␉␉␉␉case FDISK_DOS16S:␊ |
1075 | ␉␉␉␉case FDISK_DOS16B:␊ |
1076 | ␉␉␉␉case FDISK_SMALLFAT32:␊ |
1077 | ␉␉␉␉case FDISK_DOS16SLBA:␊ |
1078 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1079 | ␉␉␉␉␉␉biosdev, partno,␊ |
1080 | ␉␉␉␉␉␉part->relsect,␊ |
1081 | ␉␉␉␉␉␉part,␊ |
1082 | ␉␉␉␉␉␉MSDOSInitPartition,␊ |
1083 | ␉␉␉␉␉␉MSDOSLoadFile,␊ |
1084 | ␉␉␉␉␉␉MSDOSReadFile,␊ |
1085 | ␉␉␉␉␉␉MSDOSGetDirEntry,␊ |
1086 | ␉␉␉␉␉␉MSDOSGetFileBlock,␊ |
1087 | ␉␉␉␉␉␉MSDOSGetUUID,␊ |
1088 | ␉␉␉␉␉␉MSDOSGetDescription,␊ |
1089 | ␉␉␉␉␉␉MSDOSFree,␊ |
1090 | ␉␉␉␉␉␉0,␊ |
1091 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1092 | ␉␉␉␉␉break;␊ |
1093 | ␊ |
1094 | ␉␉␉␉case FDISK_NTFS:␊ |
1095 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1096 | ␉␉␉␉␉␉biosdev, partno,␊ |
1097 | ␉␉␉␉␉␉part->relsect,␊ |
1098 | ␉␉␉␉␉␉part,␊ |
1099 | ␉␉␉␉␉␉0, 0, 0, 0, 0,␊ |
1100 | ␉␉␉␉␉␉NTFSGetUUID,␊ |
1101 | ␉␉␉␉␉␉NTFSGetDescription,␊ |
1102 | ␉␉␉␉␉␉(BVFree)free,␊ |
1103 | ␉␉␉␉␉␉0,␊ |
1104 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1105 | ␉␉␉␉␉break;␊ |
1106 | ␊ |
1107 | ␉␉␉␉case FDISK_LINUX:␊ |
1108 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1109 | ␉␉␉␉␉␉biosdev, partno,␊ |
1110 | ␉␉␉␉␉␉part->relsect,␊ |
1111 | ␉␉␉␉␉␉part,␊ |
1112 | ␉␉␉␉␉␉0, 0, 0, 0, 0,␊ |
1113 | ␉␉␉␉␉␉EX2GetUUID,␊ |
1114 | ␉␉␉␉␉␉EX2GetDescription,␊ |
1115 | ␉␉␉␉␉␉(BVFree)free,␊ |
1116 | ␉␉␉␉␉␉0,␊ |
1117 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1118 | ␉␉␉␉␉break;␊ |
1119 | ␊ |
1120 | ␉␉␉␉case FDISK_BEFS:␊ |
1121 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1122 | ␉␉␉␉␉␉biosdev, partno,␊ |
1123 | ␉␉␉␉␉␉part->relsect,␊ |
1124 | ␉␉␉␉␉␉part,␊ |
1125 | ␉␉␉␉␉␉0, 0, 0, 0, 0, 0,␊ |
1126 | ␉␉␉␉␉␉BeFSGetDescription,␊ |
1127 | ␉␉␉␉␉␉(BVFree)free,␊ |
1128 | ␉␉␉␉␉␉0,␊ |
1129 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1130 | ␉␉␉␉␉break;␊ |
1131 | ␊ |
1132 | ␉␉␉␉case FDISK_FREEBSD:␊ |
1133 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1134 | ␉␉␉␉␉␉biosdev, partno,␊ |
1135 | ␉␉␉␉␉␉part->relsect,␊ |
1136 | ␉␉␉␉␉␉part,␊ |
1137 | ␉␉␉␉␉␉0, 0, 0, 0, 0, 0,␊ |
1138 | ␉␉␉␉␉␉FreeBSDGetDescription,␊ |
1139 | ␉␉␉␉␉␉(BVFree)free,␊ |
1140 | ␉␉␉␉␉␉0,␊ |
1141 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1142 | ␉␉␉␉␉break;␊ |
1143 | ␊ |
1144 | ␉␉␉␉case FDISK_OPENBSD:␊ |
1145 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1146 | ␉␉␉␉␉␉biosdev, partno,␊ |
1147 | ␉␉␉␉␉␉part->relsect,␊ |
1148 | ␉␉␉␉␉␉part,␊ |
1149 | ␉␉␉␉␉␉0, 0, 0, 0, 0, 0,␊ |
1150 | ␉␉␉␉␉␉OpenBSDGetDescription,␊ |
1151 | ␉␉␉␉␉␉(BVFree)free,␊ |
1152 | ␉␉␉␉␉␉0,␊ |
1153 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1154 | ␉␉␉␉␉break;␊ |
1155 | ␊ |
1156 | ␉␉␉␉default:␊ |
1157 | ␉␉␉␉␉bvr = newFDiskBVRef(␊ |
1158 | ␉␉␉␉␉␉biosdev, partno,␊ |
1159 | ␉␉␉␉␉␉part->relsect,␊ |
1160 | ␉␉␉␉␉␉part,␊ |
1161 | ␉␉␉␉␉␉0, 0, 0, 0, 0, 0, 0,␊ |
1162 | ␉␉␉␉␉␉(BVFree)free,␊ |
1163 | ␉␉␉␉␉␉0,␊ |
1164 | ␉␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1165 | ␉␉␉␉␉break;␊ |
1166 | ␉␉␉}␊ |
1167 | ␊ |
1168 | ␉␉␉if ( bvr )␊ |
1169 | ␉␉␉{␊ |
1170 | ␉␉␉␉bvr->next = map->bvr;␊ |
1171 | ␉␉␉␉map->bvr = bvr;␊ |
1172 | ␉␉␉␉map->bvrcnt++;␊ |
1173 | ␉␉␉}␊ |
1174 | ␉␉}␊ |
1175 | ␊ |
1176 | #if UFS_SUPPORT␊ |
1177 | ␉␉// Booting from a CD with an UFS filesystem embedded␊ |
1178 | ␉␉// in a booter partition.␊ |
1179 | ␊ |
1180 | ␉␉␉if ( booterUFS )␊ |
1181 | ␉␉␉{␊ |
1182 | ␉␉␉␉if ( map->bvrcnt == 0 )␊ |
1183 | ␉␉␉␉{␊ |
1184 | ␉␉␉␉␉map->bvr = booterUFS;␊ |
1185 | ␉␉␉␉␉map->bvrcnt++;␊ |
1186 | ␉␉␉␉}␊ |
1187 | ␉␉␉␉else␊ |
1188 | ␉␉␉␉{␊ |
1189 | ␉␉␉␉␉free( booterUFS );␊ |
1190 | ␉␉␉␉}␊ |
1191 | ␉␉␉}␊ |
1192 | #endif␊ |
1193 | ␉␉}␊ |
1194 | ␉} while (0);␊ |
1195 | ␊ |
1196 | #if UNUSED␊ |
1197 | ␉/*␊ |
1198 | ␉ * If no FDisk partition, then we will check for␊ |
1199 | ␉ * an Apple partition map elsewhere.␊ |
1200 | ␉ */␊ |
1201 | ␉if (map && map->bvrcnt == 0)␊ |
1202 | ␉{␊ |
1203 | ␉␉static struct fdisk_part cdpart;␊ |
1204 | ␉␉cdpart.systid = 0xCD;␊ |
1205 | ␊ |
1206 | ␉␉/* Let's try assuming we are on a hybrid HFS/ISO9660 CD. */␊ |
1207 | ␉␉bvr = newFDiskBVRef(␊ |
1208 | ␉␉␉biosdev, 0,␊ |
1209 | ␉␉␉0,␊ |
1210 | ␉␉␉&cdpart,␊ |
1211 | ␉␉␉HFSInitPartition,␊ |
1212 | ␉␉␉HFSLoadFile,␊ |
1213 | ␉␉␉HFSReadFile,␊ |
1214 | ␉␉␉HFSGetDirEntry,␊ |
1215 | ␉␉␉HFSGetFileBlock,␊ |
1216 | ␉␉␉HFSGetUUID,␊ |
1217 | ␉␉␉HFSGetDescription,␊ |
1218 | ␉␉␉HFSFree,␊ |
1219 | ␉␉␉0,␊ |
1220 | ␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1221 | ␉␉bvr->next = map->bvr;␊ |
1222 | ␉␉map->bvr = bvr;␊ |
1223 | ␉␉map->bvrcnt++;␊ |
1224 | ␉}␊ |
1225 | #endif␊ |
1226 | ␉// Actually this should always be true given the above code␊ |
1227 | ␉// (unless malloc failed above)␊ |
1228 | ␉if(map && (map == gDiskBVMap))␊ |
1229 | ␉{␊ |
1230 | ␉␉// Don't leave a null map in the chain␊ |
1231 | ␉␉if((map->bvrcnt == 0) && (map->bvr == NULL))␊ |
1232 | ␉␉{␊ |
1233 | ␉␉␉gDiskBVMap = map->next;␊ |
1234 | ␉␉␉free(map);␊ |
1235 | ␉␉␉map = NULL;␊ |
1236 | ␉␉}␊ |
1237 | ␉}␊ |
1238 | ␊ |
1239 | ␉if (countPtr) *countPtr = map ? map->bvrcnt : 0;␊ |
1240 | ␊ |
1241 | ␉return map ? map->bvr : NULL;␊ |
1242 | }␊ |
1243 | ␊ |
1244 | //==============================================================================␊ |
1245 | static BVRef diskScanAPMBootVolumes( int biosdev, int *countPtr )␊ |
1246 | {␊ |
1247 | ␉struct DiskBVMap␉*map;␊ |
1248 | ␉struct Block0␉␉*block0_p;␊ |
1249 | ␉unsigned int␉␉blksize;␊ |
1250 | ␉unsigned int␉␉factor;␊ |
1251 | ␊ |
1252 | ␉verbose("\tAttempting to scan APM boot volumes [biosdev=%02Xh]:\n", biosdev);␊ |
1253 | ␊ |
1254 | ␉void␉*buffer = malloc(BPS);␊ |
1255 | ␊ |
1256 | ␉if (!buffer)␊ |
1257 | ␉{␊ |
1258 | ␉␉return NULL;␊ |
1259 | ␉}␊ |
1260 | ␊ |
1261 | ␉bzero(buffer,BPS);␊ |
1262 | ␊ |
1263 | ␉/* Check for alternate block size */␊ |
1264 | ␉if (readBytes( biosdev, 0, 0, BPS, buffer ) != 0)␊ |
1265 | ␉{␊ |
1266 | ␉␉return NULL;␊ |
1267 | ␉}␊ |
1268 | ␊ |
1269 | ␉block0_p = buffer;␊ |
1270 | ␉if (OSSwapBigToHostInt16(block0_p->sbSig) == BLOCK0_SIGNATURE)␊ |
1271 | ␉{␊ |
1272 | ␉␉blksize = OSSwapBigToHostInt16(block0_p->sbBlkSize);␊ |
1273 | ␉␉if (blksize != BPS)␊ |
1274 | ␉␉{␊ |
1275 | ␉␉␉free(buffer);␊ |
1276 | ␉␉␉buffer = malloc(blksize);␊ |
1277 | ␉␉␉if (!buffer)␊ |
1278 | ␉␉␉{␊ |
1279 | ␉␉␉␉return NULL;␊ |
1280 | ␉␉␉}␊ |
1281 | ␉␉␉bzero(buffer,BPS);␊ |
1282 | ␉␉}␊ |
1283 | ␉␉factor = blksize / BPS;␊ |
1284 | ␉}␊ |
1285 | ␉else␊ |
1286 | ␉{␊ |
1287 | ␉␉blksize = BPS;␊ |
1288 | ␉␉factor = 1;␊ |
1289 | ␉}␊ |
1290 | ␊ |
1291 | ␉do␊ |
1292 | ␉{␊ |
1293 | ␉␉// Create a new mapping.␊ |
1294 | ␊ |
1295 | ␉␉map = (struct DiskBVMap *) malloc( sizeof(*map) );␊ |
1296 | ␉␉if ( map )␊ |
1297 | ␉␉{␊ |
1298 | ␉␉␉int error;␊ |
1299 | ␉␉␉DPME *dpme_p = (DPME *)buffer;␊ |
1300 | ␉␉␉UInt32 i, npart = UINT_MAX;␊ |
1301 | ␉␉␉BVRef bvr;␊ |
1302 | ␊ |
1303 | ␉␉␉map->biosdev = biosdev;␊ |
1304 | ␉␉␉map->bvr = NULL;␊ |
1305 | ␉␉␉map->bvrcnt = 0;␊ |
1306 | ␉␉␉map->next = gDiskBVMap;␊ |
1307 | ␉␉␉gDiskBVMap = map;␊ |
1308 | ␊ |
1309 | ␉␉␉for (i = 0; i < npart; i++)␊ |
1310 | ␉␉␉{␊ |
1311 | ␉␉␉␉error = readBytes( biosdev, (kAPMSector + i) * factor, 0, blksize, buffer );␊ |
1312 | ␊ |
1313 | ␉␉␉␉if (error || OSSwapBigToHostInt16(dpme_p->dpme_signature) != DPME_SIGNATURE)␊ |
1314 | ␉␉␉␉{␊ |
1315 | ␉␉␉␉␉break;␊ |
1316 | ␉␉␉␉}␊ |
1317 | ␊ |
1318 | ␉␉␉␉if (i == 0)␊ |
1319 | ␉␉␉␉{␊ |
1320 | ␉␉␉␉␉npart = OSSwapBigToHostInt32(dpme_p->dpme_map_entries);␊ |
1321 | ␉␉␉␉}␊ |
1322 | ␉␉␉␉/*␊ |
1323 | ␉␉␉␉printf("name = %s, %s%s %d -> %d [%d -> %d] {%d}\n",␊ |
1324 | ␉␉␉␉dpme.dpme_name, dpme.dpme_type, (dpme.dpme_flags & DPME_FLAGS_BOOTABLE) ? "(bootable)" : "",␊ |
1325 | ␉␉␉␉dpme.dpme_pblock_start, dpme.dpme_pblocks,␊ |
1326 | ␉␉␉␉dpme.dpme_lblock_start, dpme.dpme_lblocks,␊ |
1327 | ␉␉␉␉dpme.dpme_boot_block);␊ |
1328 | ␉␉␉␉*/␊ |
1329 | ␊ |
1330 | ␉␉␉␉if (strncmp(dpme_p->dpme_type, "Apple_HFS", sizeof("Apple_HFS")) == 0)␊ |
1331 | ␉␉␉␉{␊ |
1332 | ␉␉␉␉␉bvr = newAPMBVRef(biosdev,␊ |
1333 | ␉␉␉␉␉i,␊ |
1334 | ␉␉␉␉␉OSSwapBigToHostInt32(dpme_p->dpme_pblock_start) * factor,␊ |
1335 | ␉␉␉␉␉dpme_p,␊ |
1336 | ␉␉␉␉␉HFSInitPartition,␊ |
1337 | ␉␉␉␉␉HFSLoadFile,␊ |
1338 | ␉␉␉␉␉HFSReadFile,␊ |
1339 | ␉␉␉␉␉HFSGetDirEntry,␊ |
1340 | ␉␉␉␉␉HFSGetFileBlock,␊ |
1341 | ␉␉␉␉␉HFSGetUUID,␊ |
1342 | ␉␉␉␉␉HFSGetDescription,␊ |
1343 | ␉␉␉␉␉HFSFree,␊ |
1344 | ␉␉␉␉␉0,␊ |
1345 | ␉␉␉␉␉kBIOSDevTypeHardDrive, 0);␊ |
1346 | ␉␉␉␉␉bvr->next = map->bvr;␊ |
1347 | ␉␉␉␉␉map->bvr = bvr;␊ |
1348 | ␉␉␉␉␉map->bvrcnt++;␊ |
1349 | ␉␉␉␉}␊ |
1350 | ␉␉␉}␊ |
1351 | ␉␉}␊ |
1352 | ␉} while (0);␊ |
1353 | ␊ |
1354 | ␉if (buffer)␊ |
1355 | ␉{␊ |
1356 | ␉␉free(buffer);␊ |
1357 | ␉}␊ |
1358 | ␊ |
1359 | ␉if (countPtr)␊ |
1360 | ␉{␊ |
1361 | ␉␉*countPtr = map ? map->bvrcnt : 0;␊ |
1362 | ␉}␊ |
1363 | ␊ |
1364 | ␉return map ? map->bvr : NULL;␊ |
1365 | }␊ |
1366 | ␊ |
1367 | //==============================================================================␊ |
1368 | static bool isPartitionUsed(gpt_ent * partition)␊ |
1369 | {␊ |
1370 | ␊ |
1371 | ␉// Ask whether the given partition is used.␊ |
1372 | ␊ |
1373 | ␉return efi_guid_is_null((EFI_GUID const*)partition->ent_type) ? false : true;␊ |
1374 | }␊ |
1375 | ␊ |
1376 | //==============================================================================␊ |
1377 | static BVRef diskScanGPTBootVolumes(int biosdev, int *countPtr)␊ |
1378 | {␊ |
1379 | ␉verbose("\tAttempting to scan GPT boot volumes [biosdev=%02Xh]:\n", biosdev);␊ |
1380 | ␊ |
1381 | ␉struct DiskBVMap *map = NULL;␊ |
1382 | ␊ |
1383 | ␉void *buffer = malloc(BPS);␊ |
1384 | ␊ |
1385 | ␉int error;␊ |
1386 | ␊ |
1387 | ␉if ((error = readBytes( biosdev, /*secno*/0, 0, BPS, buffer )) != 0)␊ |
1388 | ␉{␊ |
1389 | ␉␉verbose("Failed to read boot sector from BIOS device %02xh. Error=%d\n", biosdev, error);␊ |
1390 | ␉␉goto scanErr;␊ |
1391 | ␉}␊ |
1392 | ␉struct REAL_disk_blk0 *fdiskMap = buffer;␊ |
1393 | ␉if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE )␊ |
1394 | ␉{␊ |
1395 | ␉␉verbose("Failed to find boot signature on BIOS device %02xh\n", biosdev);␊ |
1396 | ␉␉goto scanErr;␊ |
1397 | ␉}␊ |
1398 | ␊ |
1399 | ␉int fdiskID = 0;␊ |
1400 | ␉unsigned index;␊ |
1401 | ␉for ( index = 0; index < FDISK_NPART; index++ )␊ |
1402 | ␉{␊ |
1403 | ␉␉if ( fdiskMap->parts[index].systid )␊ |
1404 | ␉␉{␊ |
1405 | ␉␉␉if ( fdiskMap->parts[index].systid == 0xEE )␊ |
1406 | ␉␉␉{␊ |
1407 | ␉␉␉␉// Fail if two 0xEE partitions are present which␊ |
1408 | ␉␉␉␉// means the FDISK code will wind up parsing it.␊ |
1409 | ␉␉␉␉if ( fdiskID )␊ |
1410 | ␉␉␉␉{␊ |
1411 | ␉␉␉␉␉verbose("\t[diskScanGPTBootVolumes] Error! Two GPT protective MBR (fdisk=0xEE) partitions found on same device, skipping.\n");␊ |
1412 | ␉␉␉␉␉goto scanErr;␊ |
1413 | ␉␉␉␉}␊ |
1414 | ␊ |
1415 | ␉␉␉␉fdiskID = index + 1;␊ |
1416 | ␉␉␉}␊ |
1417 | ␉␉}␊ |
1418 | ␉}␊ |
1419 | ␊ |
1420 | ␉if ( fdiskID == 0 )␊ |
1421 | ␉{␊ |
1422 | ␉␉goto scanErr;␊ |
1423 | ␉}␊ |
1424 | ␊ |
1425 | ␉verbose("Attempting to read GPT\n");␊ |
1426 | ␊ |
1427 | ␉if(readBytes(biosdev, 1, 0, BPS, buffer) != 0)␊ |
1428 | ␉{␊ |
1429 | ␉␉goto scanErr;␊ |
1430 | ␉}␊ |
1431 | ␊ |
1432 | ␉gpt_hdr *headerMap = buffer;␊ |
1433 | ␊ |
1434 | ␉// Determine whether the partition header signature is present.␊ |
1435 | ␊ |
1436 | ␉if ( memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) )␊ |
1437 | ␉{␊ |
1438 | ␉␉goto scanErr;␊ |
1439 | ␉}␊ |
1440 | ␊ |
1441 | ␉// Determine whether the partition header size is valid.␊ |
1442 | ␊ |
1443 | ␉UInt32 headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self);␊ |
1444 | ␉UInt32 headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size);␊ |
1445 | ␊ |
1446 | ␉if (headerSize < offsetof(gpt_hdr, padding))␊ |
1447 | ␉{␊ |
1448 | ␉␉goto scanErr;␊ |
1449 | ␉}␊ |
1450 | ␊ |
1451 | ␉if ( headerSize > BPS )␊ |
1452 | ␉{␊ |
1453 | ␉␉goto scanErr;␊ |
1454 | ␉}␊ |
1455 | ␊ |
1456 | ␉// Determine whether the partition header checksum is valid.␊ |
1457 | ␊ |
1458 | ␉headerMap->hdr_crc_self = 0;␊ |
1459 | ␊ |
1460 | ␉if ( crc32(0, headerMap, headerSize) != headerCheck )␊ |
1461 | ␉{␊ |
1462 | ␉␉goto scanErr;␊ |
1463 | ␉}␊ |
1464 | ␊ |
1465 | ␉// Determine whether the partition entry size is valid.␊ |
1466 | ␊ |
1467 | ␉UInt64␉␉gptBlock␉= 0;␊ |
1468 | ␉UInt32␉␉gptCheck␉= 0;␊ |
1469 | ␉UInt32␉␉gptCount␉= 0;␊ |
1470 | ␉UInt32␉␉gptID␉␉= 0;␊ |
1471 | ␉gpt_ent␉␉*gptMap␉␉= NULL;␊ |
1472 | ␉UInt32␉␉gptSize␉␉= 0;␊ |
1473 | ␊ |
1474 | ␉gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table);␊ |
1475 | ␉gptCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_table);␊ |
1476 | ␉gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries);␊ |
1477 | ␉gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz);␊ |
1478 | ␊ |
1479 | ␉if ( gptSize < sizeof(gpt_ent) )␊ |
1480 | ␉{␊ |
1481 | ␉␉goto scanErr;␊ |
1482 | ␉}␊ |
1483 | ␊ |
1484 | ␉// Allocate a buffer large enough to hold one map, rounded to a media block.␊ |
1485 | ␉free(buffer);␊ |
1486 | ␉buffer = NULL;␊ |
1487 | ␊ |
1488 | ␉UInt32 bufferSize = IORound(gptCount * gptSize, BPS);␊ |
1489 | ␉if (bufferSize == 0)␊ |
1490 | ␉{␊ |
1491 | ␉␉goto scanErr;␊ |
1492 | ␉}␊ |
1493 | ␉buffer = malloc(bufferSize);␊ |
1494 | ␉if (!buffer)␊ |
1495 | ␉{␊ |
1496 | ␉goto scanErr;␊ |
1497 | ␉}␊ |
1498 | ␊ |
1499 | ␉bzero(buffer,bufferSize);␊ |
1500 | ␊ |
1501 | ␉if (readBytes(biosdev, gptBlock, 0, bufferSize, buffer) != 0)␊ |
1502 | ␉{␊ |
1503 | ␉␉goto scanErr;␊ |
1504 | ␉}␊ |
1505 | ␉verbose("Read GPT\n");␊ |
1506 | ␊ |
1507 | ␉// Allocate a new map for this BIOS device and insert it into the chain␊ |
1508 | ␉map = malloc(sizeof(*map));␊ |
1509 | ␉if (!map)␊ |
1510 | ␉{␊ |
1511 | ␉␉goto scanErr;␊ |
1512 | ␉}␊ |
1513 | ␉map->biosdev = biosdev;␊ |
1514 | ␉map->bvr = NULL;␊ |
1515 | ␉map->bvrcnt = 0;␊ |
1516 | ␉map->next = gDiskBVMap;␊ |
1517 | ␉gDiskBVMap = map;␊ |
1518 | ␊ |
1519 | ␉// fdisk like partition type id.␊ |
1520 | ␉int fsType = 0;␊ |
1521 | ␊ |
1522 | ␉for(gptID = 1; gptID <= gptCount; ++gptID)␊ |
1523 | ␉{␊ |
1524 | ␉␉BVRef bvr = NULL;␊ |
1525 | ␉␉unsigned int bvrFlags = 0;␊ |
1526 | ␊ |
1527 | ␉␉// size on disk can be larger than sizeof(gpt_ent)␊ |
1528 | ␉␉gptMap = (gpt_ent *)(buffer + ((gptID - 1) * gptSize));␊ |
1529 | ␊ |
1530 | ␉␉// NOTE: EFI_GUID's are in LE and we know we're on an x86.␊ |
1531 | ␉␉// The IOGUIDPartitionScheme.cpp code uses byte-based UUIDs, we don't.␊ |
1532 | ␊ |
1533 | ␉␉if (isPartitionUsed(gptMap))␊ |
1534 | ␉␉{␊ |
1535 | ␉␉␉char stringuuid[100];␊ |
1536 | ␉␉␉efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid);␊ |
1537 | ␉␉␉verbose("Reading GPT partition %d, type %s\n", (unsigned) gptID, stringuuid);␊ |
1538 | ␊ |
1539 | ␉␉␉// Getting fdisk like partition type.␊ |
1540 | ␉␉␉fsType = probeFileSystem(biosdev, gptMap->ent_lba_start);␊ |
1541 | ␊ |
1542 | ␉␉␉if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) || (efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )␊ |
1543 | ␉␉␉{␊ |
1544 | ␉␉␉␉bvrFlags = (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ? kBVFlagBooter : 0;␊ |
1545 | ␉␉␉␉bvr = newGPTBVRef(biosdev,␊ |
1546 | ␉␉␉␉gptID,␊ |
1547 | ␉␉␉␉gptMap->ent_lba_start,␊ |
1548 | ␉␉␉␉gptMap,␊ |
1549 | ␉␉␉␉HFSInitPartition,␊ |
1550 | ␉␉␉␉HFSLoadFile,␊ |
1551 | ␉␉␉␉HFSReadFile,␊ |
1552 | ␉␉␉␉HFSGetDirEntry,␊ |
1553 | ␉␉␉␉HFSGetFileBlock,␊ |
1554 | ␉␉␉␉HFSGetUUID,␊ |
1555 | ␉␉␉␉HFSGetDescription,␊ |
1556 | ␉␉␉␉HFSFree,␊ |
1557 | ␉␉␉␉0,␊ |
1558 | ␉␉␉␉kBIOSDevTypeHardDrive, bvrFlags);␊ |
1559 | ␉␉␉}␊ |
1560 | ␊ |
1561 | ␉␉␉// zef - foreign OS support␊ |
1562 | ␉␉␉if ((efi_guid_compare(&GPT_BASICDATA_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ||␊ |
1563 | ␉␉␉␉(efi_guid_compare(&GPT_BASICDATA2_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )␊ |
1564 | ␉␉␉{␊ |
1565 | ␉␉␉␉switch (fsType)␊ |
1566 | ␉␉␉␉{␊ |
1567 | ␉␉␉␉␉case FDISK_NTFS:␊ |
1568 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1569 | ␉␉␉␉␉␉0, 0, 0, 0, 0, NTFSGetUUID, NTFSGetDescription,␊ |
1570 | ␉␉␉␉␉␉(BVFree)free, 0, kBIOSDevTypeHardDrive, 0);␊ |
1571 | ␉␉␉␉␉␉break;␊ |
1572 | ␊ |
1573 | ␉␉␉␉␉case FDISK_LINUX:␊ |
1574 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1575 | ␉␉␉␉␉␉0, 0, 0, 0, 0, EX2GetUUID, EX2GetDescription,␊ |
1576 | ␉␉␉␉␉␉(BVFree)free, 0, kBIOSDevTypeHardDrive, 0);␊ |
1577 | ␉␉␉␉␉␉break;␊ |
1578 | ␊ |
1579 | ␉␉␉␉␉case FDISK_FAT32:␊ |
1580 | ␉␉␉␉␉case FDISK_DOS12:␊ |
1581 | ␉␉␉␉␉case FDISK_DOS16B:␊ |
1582 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1583 | ␉␉␉␉␉␉␉␉MSDOSInitPartition,␊ |
1584 | ␉␉␉␉␉␉␉␉MSDOSLoadFile,␊ |
1585 | ␉␉␉␉␉␉␉␉MSDOSReadFile,␊ |
1586 | ␉␉␉␉␉␉␉␉MSDOSGetDirEntry,␊ |
1587 | ␉␉␉␉␉␉␉␉MSDOSGetFileBlock,␊ |
1588 | ␉␉␉␉␉␉␉␉MSDOSGetUUID,␊ |
1589 | ␉␉␉␉␉␉␉␉MSDOSGetDescription,␊ |
1590 | ␉␉␉␉␉␉␉␉MSDOSFree,␊ |
1591 | ␉␉␉␉␉␉␉␉0, kBIOSDevTypeHardDrive, 0);␊ |
1592 | ␉␉␉␉␉␉break;␊ |
1593 | ␊ |
1594 | ␉␉␉␉␉case FDISK_PSEUDO_EXFAT:␊ |
1595 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1596 | ␉␉␉␉␉␉␉␉␉␉ EXFATInitPartition,␊ |
1597 | ␉␉␉␉␉␉␉␉␉␉ EXFATLoadFile,␊ |
1598 | ␉␉␉␉␉␉␉␉␉␉ EXFATReadFile,␊ |
1599 | ␉␉␉␉␉␉␉␉␉␉ EXFATGetDirEntry,␊ |
1600 | ␉␉␉␉␉␉␉␉␉␉ EXFATGetFileBlock,␊ |
1601 | ␉␉␉␉␉␉␉␉␉␉ EXFATGetUUID,␊ |
1602 | ␉␉␉␉␉␉␉␉␉␉ EXFATGetDescription,␊ |
1603 | ␉␉␉␉␉␉␉␉␉␉ EXFATFree,␊ |
1604 | ␉␉␉␉␉␉␉␉␉␉ 0, kBIOSDevTypeHardDrive, 0);␊ |
1605 | ␉␉␉␉␉␉break;␊ |
1606 | ␊ |
1607 | ␉␉␉␉␉default:␊ |
1608 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1609 | ␉␉␉␉␉␉0, 0, 0, 0, 0, 0, 0,␊ |
1610 | ␉␉␉␉␉␉(BVFree)free, 0, kBIOSDevTypeHardDrive, 0);␊ |
1611 | ␉␉␉␉␉␉break;␊ |
1612 | ␉␉␉␉}␊ |
1613 | ␊ |
1614 | ␉␉␉}␊ |
1615 | ␊ |
1616 | ␉␉␉// turbo - save our booter partition␊ |
1617 | ␉␉␉// zef - only on original boot device␊ |
1618 | ␉␉␉if ( (efi_guid_compare(&GPT_EFISYS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ) {␊ |
1619 | ␉␉␉␉switch (fsType) {␊ |
1620 | ␉␉␉␉␉case FDISK_HFS:␊ |
1621 | ␉␉␉␉␉if (readBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0) {␊ |
1622 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1623 | ␉␉␉␉␉␉HFSInitPartition,␊ |
1624 | ␉␉␉␉␉␉HFSLoadFile,␊ |
1625 | ␉␉␉␉␉␉HFSReadFile,␊ |
1626 | ␉␉␉␉␉␉HFSGetDirEntry,␊ |
1627 | ␉␉␉␉␉␉HFSGetFileBlock,␊ |
1628 | ␉␉␉␉␉␉HFSGetUUID,␊ |
1629 | ␉␉␉␉␉␉HFSGetDescription,␊ |
1630 | ␉␉␉␉␉␉HFSFree,␊ |
1631 | ␉␉␉␉␉␉0, kBIOSDevTypeHardDrive, kBVFlagEFISystem);␊ |
1632 | ␉␉␉␉␉}␊ |
1633 | ␉␉␉␉␉break;␊ |
1634 | ␊ |
1635 | ␉␉␉␉␉case FDISK_FAT32:␊ |
1636 | ␉␉␉␉␉if (testFAT32EFIBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0) {␊ |
1637 | ␉␉␉␉␉␉bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,␊ |
1638 | ␉␉␉␉␉␉MSDOSInitPartition,␊ |
1639 | ␉␉␉␉␉␉MSDOSLoadFile,␊ |
1640 | ␉␉␉␉␉␉MSDOSReadFile,␊ |
1641 | ␉␉␉␉␉␉MSDOSGetDirEntry,␊ |
1642 | ␉␉␉␉␉␉MSDOSGetFileBlock,␊ |
1643 | ␉␉␉␉␉␉MSDOSGetUUID,␊ |
1644 | ␉␉␉␉␉␉MSDOSGetDescription,␊ |
1645 | ␉␉␉␉␉␉MSDOSFree,␊ |
1646 | ␉␉␉␉␉␉0, kBIOSDevTypeHardDrive, kBVFlagEFISystem);␊ |
1647 | ␉␉␉␉␉}␊ |
1648 | ␉␉␉␉␉break;␊ |
1649 | ␊ |
1650 | ␉␉␉␉␉default:␊ |
1651 | ␉␉␉␉␉if (biosdev == gBIOSDev)␊ |
1652 | ␉␉␉␉␉{␊ |
1653 | ␉␉␉␉␉␉gBIOSBootVolume = bvr;␊ |
1654 | ␉␉␉␉␉}␊ |
1655 | ␉␉␉␉␉break;␊ |
1656 | ␉␉␉␉}␊ |
1657 | ␉␉␉}␊ |
1658 | ␊ |
1659 | ␉␉␉if (bvr)␊ |
1660 | ␉␉␉{␊ |
1661 | ␉␉␉␉// Fixup bvr with the fake fdisk partition type.␊ |
1662 | ␉␉␉␉if (fsType > 0) {␊ |
1663 | ␉␉␉␉␉bvr->part_type = fsType;␊ |
1664 | ␉␉␉␉}␊ |
1665 | ␊ |
1666 | ␉␉␉␉bvr->next = map->bvr;␊ |
1667 | ␉␉␉␉map->bvr = bvr;␊ |
1668 | ␉␉␉␉++map->bvrcnt;␊ |
1669 | ␉␉␉}␊ |
1670 | ␊ |
1671 | ␉␉}␊ |
1672 | ␉}␊ |
1673 | ␊ |
1674 | ␉scanErr:␊ |
1675 | ␉if (buffer)␊ |
1676 | ␉{␊ |
1677 | ␉␉free(buffer);␊ |
1678 | ␉}␊ |
1679 | ␊ |
1680 | ␉if(map)␊ |
1681 | ␉{␊ |
1682 | ␉␉if(countPtr) *countPtr = map->bvrcnt;␊ |
1683 | ␉␉{␊ |
1684 | ␉␉␉return map->bvr;␊ |
1685 | ␉␉}␊ |
1686 | ␊ |
1687 | ␉}␊ |
1688 | ␉else␊ |
1689 | ␉{␊ |
1690 | ␉␉if(countPtr) *countPtr = 0;␊ |
1691 | ␉␉{␊ |
1692 | ␉␉␉return NULL;␊ |
1693 | ␉␉}␊ |
1694 | ␉}␊ |
1695 | }␊ |
1696 | ␊ |
1697 | //==============================================================================␊ |
1698 | static bool getOSVersion(BVRef bvr, char *str)␊ |
1699 | {␊ |
1700 | ␉bool valid = false;␊ |
1701 | ␉config_file_t configFile;␊ |
1702 | ␉char dirSpec[512];␊ |
1703 | ␉const char *val; int len;␊ |
1704 | ␊ |
1705 | ␉const char *fakeOSVersion;␊ |
1706 | ␉int fakeOSVersionInt;␊ |
1707 | ␉// our pattern: avoiding to use full path. this help if the app is named as Beta or DP..␊ |
1708 | ␉char *LionPattern = "Install%20Mac%20OS%20X%20Lion";␊ |
1709 | ␉char *MLPattern = "Install%20OS%20X%20Mountain%20Lion";␊ |
1710 | ␉char *MavPattern = "Install%20OS%20X%20Mavericks";␊ |
1711 | ␉char *YosPattern = "Install%20OS%20X%20Yosemite";␊ |
1712 | ␉char *ECPattern = "Install%20OS%20X%20El%20Capitan";␊ |
1713 | ␉char *SierraPattern = "Install%20macOS%20Sierra";␊ |
1714 | ␉char *HSierraPattern = "Install%20macOS%20High%20Sierra";␊ |
1715 | ␉char *HSierraPatternB = "Install%20macOS%2010.13";␊ |
1716 | ␊ |
1717 | ␉/*␊ |
1718 | ␉ * Only look for OS Version on HFS+␊ |
1719 | ␉ */␊ |
1720 | ␉if (bvr->fs_readfile != HFSReadFile)␊ |
1721 | ␉{␊ |
1722 | ␉␉return valid;␊ |
1723 | ␉}␊ |
1724 | ␊ |
1725 | ␉/*␊ |
1726 | ␉ * Micky1979, let it search for the right Version *.plist␊ |
1727 | ␉ *␊ |
1728 | ␉ * NOTE:␊ |
1729 | ␉ * order is important because vanilla installer (createinstallermedia method 10.9 +) has both /.IABootFilesSystemVersion.plist and␊ |
1730 | ␉ * /System/Library/CoreServices/SystemVersion.plist otherwise fail to recognize it as Installer!␊ |
1731 | ␉ *␊ |
1732 | ␉ * OS X Installer made by the Vanilla app for Lion and newer.␊ |
1733 | ␉ * This kind of Installer can be a guest in a already working System, and produces some temporary files:␊ |
1734 | ␉ * 1) ".IABootFiles" folder is created in the root of the same partition where the app reside.␊ |
1735 | ␉ * 2) "Mac OS X Install Data" or "OS X Install Data" in the target partition␊ |
1736 | ␉ * 3) The presence of ".IABootFilesSystemVersion.plist" file if present or not, distinguishes this installer ␊ |
1737 | ␉ * by the one create with "createinstallmedia" method (is present), so we know what kind of installer is.␊ |
1738 | ␉ */␊ |
1739 | ␊ |
1740 | ␉// is an installer or a system to Upgrade OSX?␊ |
1741 | ␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/.IAProductInfo", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1742 | ␊ |
1743 | ␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1744 | ␉{␊ |
1745 | ␉␉valid = true;␊ |
1746 | ␉}␊ |
1747 | ␊ |
1748 | ␉if (valid)␊ |
1749 | ␉{␊ |
1750 | ␉␉// is createinstallmedia?␊ |
1751 | ␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/.IABootFilesSystemVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1752 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1753 | ␉␉{␊ |
1754 | ␉␉␉valid = false;␊ |
1755 | ␉␉}␊ |
1756 | ␉␉else␊ |
1757 | ␉␉{␊ |
1758 | ␉␉␉// if not exist probably is a vanilla installer made w/o createinstallermedia method␊ |
1759 | ␉␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/.IABootFiles/com.apple.Boot.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1760 | ␉␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1761 | ␉␉␉{␊ |
1762 | ␉␉␉␉valid = true;␊ |
1763 | ␉␉␉}␊ |
1764 | ␉␉␉else␊ |
1765 | ␉␉␉{␊ |
1766 | ␉␉␉␉valid = false;␊ |
1767 | ␉␉␉}␊ |
1768 | ␉␉}␊ |
1769 | ␉}␊ |
1770 | ␊ |
1771 | ␉if (valid)␊ |
1772 | ␉{␊ |
1773 | ␉␉/*␊ |
1774 | ␉␉ * we don't know the real OS version, but "Kernel Flags" key contain the URL path to the app..␊ |
1775 | ␉␉ * and we try to see if contain a match for our patterns ("Install%20OS%20X%20El%20Capitan" = 10.11)␊ |
1776 | ␉␉ */␊ |
1777 | ␉␉if (getValueForKey("Kernel Flags", &val, &len, &configFile))␊ |
1778 | ␉␉{␊ |
1779 | ␉␉␉if(strstr(val, LionPattern))␊ |
1780 | ␉␉␉{␊ |
1781 | ␉␉␉␉fakeOSVersion = "10.7";␊ |
1782 | ␉␉␉␉fakeOSVersionInt = 7;␊ |
1783 | ␉␉␉␉valid = true;␊ |
1784 | ␉␉␉}␊ |
1785 | ␉␉␉else if(strstr(val, MLPattern))␊ |
1786 | ␉␉␉{␊ |
1787 | ␉␉␉␉fakeOSVersion = "10.8";␊ |
1788 | ␉␉␉␉fakeOSVersionInt = 8;␊ |
1789 | ␉␉␉␉valid = true;␊ |
1790 | ␉␉␉}␊ |
1791 | ␉␉␉else if(strstr(val, MavPattern))␊ |
1792 | ␉␉␉{␊ |
1793 | ␉␉␉␉fakeOSVersion = "10.9";␊ |
1794 | ␉␉␉␉fakeOSVersionInt = 9;␊ |
1795 | ␉␉␉␉valid = true;␊ |
1796 | ␉␉␉}␊ |
1797 | ␉␉␉else if(strstr(val, YosPattern))␊ |
1798 | ␉␉␉{␊ |
1799 | ␉␉␉␉fakeOSVersion = "10.10";␊ |
1800 | ␉␉␉␉fakeOSVersionInt = 10;␊ |
1801 | ␉␉␉␉valid = true;␊ |
1802 | ␉␉␉}␊ |
1803 | ␉␉␉else if(strstr(val, ECPattern))␊ |
1804 | ␉␉␉{␊ |
1805 | ␉␉␉␉fakeOSVersion = "10.11";␊ |
1806 | ␉␉␉␉fakeOSVersionInt = 11;␊ |
1807 | ␉␉␉␉valid = true;␊ |
1808 | ␉␉␉}␊ |
1809 | ␉␉␉else if(strstr(val, SierraPattern))␊ |
1810 | ␉␉␉{␊ |
1811 | ␉␉␉␉fakeOSVersion = "10.12";␊ |
1812 | ␉␉␉␉fakeOSVersionInt = 12;␊ |
1813 | ␉␉␉␉valid = true;␊ |
1814 | ␉␉␉}␊ |
1815 | ␉␉␉else if(strstr(val, HSierraPattern))␊ |
1816 | ␉␉␉{␊ |
1817 | ␉␉␉␉fakeOSVersion = "10.13";␊ |
1818 | ␉␉␉␉fakeOSVersionInt = 13;␊ |
1819 | ␉␉␉␉valid = true;␊ |
1820 | ␉␉␉}␊ |
1821 | ␉␉␉else if(strstr(val, HSierraPatternB))␊ |
1822 | ␉␉␉{␊ |
1823 | ␉␉␉␉fakeOSVersion = "10.13";␊ |
1824 | ␉␉␉␉fakeOSVersionInt = 13;␊ |
1825 | ␉␉␉␉valid = true;␊ |
1826 | ␉␉␉}␊ |
1827 | ␉␉␉else␊ |
1828 | ␉␉␉{␊ |
1829 | ␉␉␉␉valid = false;␊ |
1830 | ␉␉␉}␊ |
1831 | ␉␉}␊ |
1832 | ␉␉else␊ |
1833 | ␉␉{␊ |
1834 | ␉␉␉valid = false;␊ |
1835 | ␉␉}␊ |
1836 | ␉}␊ |
1837 | ␊ |
1838 | ␉if (valid)␊ |
1839 | ␉{␊ |
1840 | ␉␉/* ␊ |
1841 | ␉␉ * if we are here that is an createinstallmedia Installer!␊ |
1842 | ␉␉ * fake the OS version so we can find the right path to the kernelcache/prelinked!␊ |
1843 | ␉␉ * To patch the kernelcache we aquire the "Darwin versionn" later..␊ |
1844 | ␉␉ */␊ |
1845 | ␉␉strncpy( bvr->OSFullVer, fakeOSVersion, strlen(fakeOSVersion) );␊ |
1846 | ␉␉bvr->OSisInstaller = true;␊ |
1847 | ␉␉// no SystemVersion.plist ...so no build...␊ |
1848 | ␉␉strncpy( bvr->OSBuildVer, "INSTALLER", strlen("INSTALLER") );␊ |
1849 | ␉␉return true;␊ |
1850 | ␉}␊ |
1851 | ␊ |
1852 | ␉/*␊ |
1853 | ␉ * Not valid? But we have the "/.IAProductInfo" in the root so this is not a conventional installer␊ |
1854 | ␉ * and probably this is an Upgrade made by the "Install OS X app"␊ |
1855 | ␉ */␊ |
1856 | ␉if (!valid)␊ |
1857 | ␉{␊ |
1858 | ␉␉len = 0; val = 0;␊ |
1859 | ␉␉// 10.9 and later use "/OS X Install Data" folder␊ |
1860 | ␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/OS X Install Data/com.apple.Boot.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1861 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1862 | ␉␉{␊ |
1863 | ␉␉␉/*␊ |
1864 | ␉␉␉ * bad is that we can't find what is the exactly Major OS version..␊ |
1865 | ␉␉␉ * but what we need is the right path to the kernel cache:␊ |
1866 | ␉␉␉ * kernelcache = 10.9 and 10.10␊ |
1867 | ␉␉␉ * prelinkedkernel = 10.11 and later␊ |
1868 | ␊ |
1869 | ␉␉␉ * so we fake the OS version just to find the correct path!␊ |
1870 | ␉␉␉ * .. later the right "Darwin Version" will use to patch the kernel cache!␊ |
1871 | ␉␉␉ */␊ |
1872 | ␊ |
1873 | ␉␉␉if (getValueForKey("Kernel Cache", &val, &len, &configFile))␊ |
1874 | ␉␉␉{␊ |
1875 | ␉␉␉␉if(strstr(val, "prelinkedkernel")) // /OS X Install Data/prelinkedkernel␊ |
1876 | ␉␉␉␉{␊ |
1877 | ␉␉␉␉␉fakeOSVersion = "10.11"; // fake OS to find prelinkedkernel on newer OSes␊ |
1878 | ␊ |
1879 | ␉␉␉␉␉switch (fakeOSVersionInt)␊ |
1880 | ␉␉␉␉␉{␊ |
1881 | ␉␉␉␉␉␉case 11:␊ |
1882 | ␉␉␉␉␉␉␉fakeOSVersion = "10.11";␊ |
1883 | ␉␉␉␉␉␉␉break;␊ |
1884 | ␉␉␉␉␉␉case 12:␊ |
1885 | ␉␉␉␉␉␉␉fakeOSVersion = "10.12";␊ |
1886 | ␉␉␉␉␉␉␉break;␊ |
1887 | ␉␉␉␉␉␉case 13:␊ |
1888 | ␉␉␉␉␉␉␉fakeOSVersion = "10.13";␊ |
1889 | ␉␉␉␉␉␉␉break;␊ |
1890 | ␉␉␉␉␉␉default:␊ |
1891 | ␉␉␉␉␉␉␉fakeOSVersion = "10.13";␊ |
1892 | ␉␉␉␉␉␉␉break;␊ |
1893 | ␉␉␉␉␉}␊ |
1894 | ␊ |
1895 | ␉␉␉␉␉valid = true;␊ |
1896 | ␉␉␉␉}␊ |
1897 | ␉␉␉␉else if(strstr(val, "kernelcache")) // /OS X Install Data/kernelcache␊ |
1898 | ␉␉␉␉{␊ |
1899 | ␉␉␉␉␉fakeOSVersion = "10.10"; // fake OS to find prelinkedkernel on 10.9 and 10.10␊ |
1900 | ␉␉␉␉␉valid = true;␊ |
1901 | ␉␉␉␉}␊ |
1902 | ␉␉␉␉else␊ |
1903 | ␉␉␉␉{␊ |
1904 | ␉␉␉␉␉valid = false;␊ |
1905 | ␉␉␉␉}␊ |
1906 | ␊ |
1907 | ␉␉␉␉if (valid)␊ |
1908 | ␉␉␉␉{␊ |
1909 | ␉␉␉␉␉strncpy( bvr->OSFullVer, fakeOSVersion, strlen(fakeOSVersion) );␊ |
1910 | ␉␉␉␉␉bvr->OSisOSXUpgrade = true;␊ |
1911 | ␉␉␉␉␉strncpy( bvr->OSBuildVer, "UPGRADE", strlen("UPGRADE") );␊ |
1912 | ␉␉␉␉␉return true;␊ |
1913 | ␉␉␉␉}␊ |
1914 | ␉␉␉}␊ |
1915 | ␉␉␉else␊ |
1916 | ␉␉␉{␊ |
1917 | ␉␉␉␉valid = false;␊ |
1918 | ␉␉␉}␊ |
1919 | ␊ |
1920 | ␉␉}␊ |
1921 | ␉␉else␊ |
1922 | ␉␉{␊ |
1923 | ␉␉␉valid = false;␊ |
1924 | ␉␉}␊ |
1925 | ␉}␊ |
1926 | ␊ |
1927 | ␉if (!valid)␊ |
1928 | ␉{␊ |
1929 | ␉␉/*␊ |
1930 | ␉␉ * Not valid? 10.8 and older use "/Mac OS X Install Data" folder..␊ |
1931 | ␉␉ */␊ |
1932 | ␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/Mac OS X Install Data/com.apple.Boot.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1933 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1934 | ␉␉{␊ |
1935 | ␉␉␉fakeOSVersion = "10.8"; // fake the OS version using 10.8.. just to find the kernelcache path for 10.7 and 10.8..␊ |
1936 | ␉␉␉strncpy( bvr->OSFullVer, fakeOSVersion, strlen(fakeOSVersion) );␊ |
1937 | ␉␉␉bvr->OSisMacOSXUpgrade = true;␊ |
1938 | ␉␉␉// again no SystemVersion.plist, so no build version.. but is usefull to know that is a System upgrade..␊ |
1939 | ␉␉␉strncpy( bvr->OSBuildVer, "UPGRADE", strlen("UPGRADE") );␊ |
1940 | ␉␉␉return true;␊ |
1941 | ␉␉}␊ |
1942 | ␉}␊ |
1943 | ␊ |
1944 | ␉if (!valid)␊ |
1945 | ␉{␊ |
1946 | ␉␉len = 0; val = 0;␊ |
1947 | ␉␉/*␊ |
1948 | ␉␉ * Not valid? 10.13 and newer use "/macOS Install Data" folder..␊ |
1949 | ␉␉ * and we have /macOS Install Data/Locked Files/Boot Files/SystemVersion.plist... thanks Apple!␊ |
1950 | ␉␉ * NOTE: the stage 2 of this installation is already bootable (aug 13 2017)␊ |
1951 | ␉␉ */␊ |
1952 | ␉␉snprintf(dirSpec, sizeof(dirSpec),␊ |
1953 | ␉␉␉"hd(%d,%d)/macOS Install Data/Locked Files/Boot Files/SystemVersion.plist",␊ |
1954 | ␉␉BIOS_DEV_UNIT(bvr),␊ |
1955 | ␉␉bvr->part_no);␊ |
1956 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1957 | ␉␉{␊ |
1958 | ␉␉␉if (getValueForKey(kProductVersion, &val, &len, &configFile))␊ |
1959 | ␉␉␉{␊ |
1960 | ␉␉␉␉// Copy the complete value into OSFullVer␊ |
1961 | ␉␉␉␉strncpy( bvr->OSFullVer, val, len );␊ |
1962 | ␉␉␉␉bvr->OSFullVer[len] = '\0'; /* null character manually added */␊ |
1963 | ␊ |
1964 | ␉␉␉␉bvr->OSisOSXUpgrade = true;␊ |
1965 | ␉␉␉␉strncpy( bvr->OSBuildVer, "UPGRADE", strlen("UPGRADE") );␊ |
1966 | ␉␉␉␉return true;␊ |
1967 | ␉␉␉}␊ |
1968 | ␉␉}␊ |
1969 | ␉}␊ |
1970 | ␊ |
1971 | ␉len = 0; val = 0;␊ |
1972 | ␊ |
1973 | ␉// OS X Installer createinstallermedia method for 10.9 and newer.␊ |
1974 | ␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/.IABootFilesSystemVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1975 | ␊ |
1976 | ␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1977 | ␉{␊ |
1978 | ␉␉bvr->OSisInstaller = true;␊ |
1979 | ␉␉valid = true;␊ |
1980 | ␉}␊ |
1981 | ␊ |
1982 | ␉// OS X Standard␊ |
1983 | ␉if (!valid)␊ |
1984 | ␉{␊ |
1985 | ␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/System/Library/CoreServices/SystemVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1986 | ␊ |
1987 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1988 | ␉␉{␊ |
1989 | ␉␉␉valid = true;␊ |
1990 | ␉␉}␊ |
1991 | ␉␉else␊ |
1992 | ␉␉{␊ |
1993 | ␉␉␉// OS X Server␊ |
1994 | ␉␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/System/Library/CoreServices/ServerVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
1995 | ␊ |
1996 | ␉␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
1997 | ␉␉␉{␊ |
1998 | ␉␉␉␉bvr->OSisServer = true;␊ |
1999 | ␉␉␉␉valid = true;␊ |
2000 | ␉␉␉}␊ |
2001 | ␉␉}␊ |
2002 | ␉}␊ |
2003 | ␊ |
2004 | ␉if (!valid)␊ |
2005 | ␉{␊ |
2006 | ␉␉// OS X Recovery␊ |
2007 | ␉␉sprintf(dirSpec, "hd(%d,%d)/com.apple.recovery.boot/SystemVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
2008 | ␊ |
2009 | ␉␉if (!loadConfigFile(dirSpec, &configFile))␊ |
2010 | ␉␉{␊ |
2011 | ␉␉␉bvr->OSisRecovery = true;␊ |
2012 | ␉␉␉valid = true;␊ |
2013 | ␉␉}␊ |
2014 | ␉}␊ |
2015 | ␊ |
2016 | ␉if (valid)␊ |
2017 | ␉{␊ |
2018 | ␊ |
2019 | ␉␉// ProductVersion␊ |
2020 | ␉␉if (getValueForKey(kProductVersion, &val, &len, &configFile))␊ |
2021 | ␉␉{␊ |
2022 | ␉␉␉// Copy the complete value into OSFullVer␊ |
2023 | ␉␉␉strncpy( bvr->OSFullVer, val, len );␊ |
2024 | ␉␉␉bvr->OSFullVer[len] = '\0'; /* null character manually added */␊ |
2025 | ␊ |
2026 | ␉␉␉// getValueForKey uses const char for val␊ |
2027 | ␉␉␉// so copy it and trim␊ |
2028 | ␉␉␉*str = '\0';␊ |
2029 | ␉␉␉strncat(str, val, MIN(len, 5));␊ |
2030 | ␉␉␉if(str[4] == '.')␊ |
2031 | ␉␉␉{␊ |
2032 | ␉␉␉␉str[4] = '\0';␊ |
2033 | ␉␉␉}␊ |
2034 | ␊ |
2035 | ␉␉␉// ProductBuildVersion␊ |
2036 | ␉␉␉if (getValueForKey(kProductBuildVersion, &val, &len, &configFile))␊ |
2037 | ␉␉␉{␊ |
2038 | ␉␉␉␉strncpy( bvr->OSBuildVer, val, len );␊ |
2039 | ␉␉␉␉bvr->OSBuildVer[len] = '\0'; /* null character manually added */␊ |
2040 | ␉␉␉}␊ |
2041 | ␊ |
2042 | ␉␉}␊ |
2043 | ␉␉else␊ |
2044 | ␉␉{␊ |
2045 | ␉␉␉valid = false;␊ |
2046 | ␉␉}␊ |
2047 | ␉}␊ |
2048 | ␊ |
2049 | ␉return valid;␊ |
2050 | }␊ |
2051 | ␊ |
2052 | //==============================================================================␊ |
2053 | static void scanFSLevelBVRSettings(BVRef chain)␊ |
2054 | {␊ |
2055 | ␉BVRef bvr;␊ |
2056 | ␉char dirSpec[512], fileSpec[512];␊ |
2057 | ␉char label[BVSTRLEN];␊ |
2058 | ␉int ret;␊ |
2059 | ␉long flags;␊ |
2060 | ␉u_int32_t time;␊ |
2061 | ␉int fh, fileSize, error;␊ |
2062 | ␊ |
2063 | ␉for (bvr = chain; bvr; bvr = bvr->next)␊ |
2064 | ␉{␊ |
2065 | ␉␉ret = -1;␊ |
2066 | ␉␉error = 0;␊ |
2067 | ␊ |
2068 | ␉␉//␊ |
2069 | ␉␉// Check for alternate volume label on boot helper partitions.␊ |
2070 | ␉␉//␊ |
2071 | ␉␉if (bvr->flags & kBVFlagBooter)␊ |
2072 | ␉␉{␊ |
2073 | ␉␉␉snprintf(dirSpec, sizeof(dirSpec), "hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
2074 | ␉␉␉strlcpy(fileSpec, ".disk_label.contentDetails", sizeof(fileSpec));␊ |
2075 | ␉␉␉ret = GetFileInfo(dirSpec, fileSpec, &flags, &time);␊ |
2076 | ␉␉␉if (!ret)␊ |
2077 | ␉␉␉{␊ |
2078 | ␉␉␉␉strlcat(dirSpec, fileSpec, sizeof(dirSpec));␊ |
2079 | ␉␉␉␉fh = open(dirSpec,0);␊ |
2080 | ␊ |
2081 | ␉␉␉␉fileSize = file_size(fh);␊ |
2082 | ␉␉␉␉if (fileSize > 0 && fileSize < BVSTRLEN)␊ |
2083 | ␉␉␉␉{␊ |
2084 | ␉␉␉␉␉if (read(fh, label, fileSize) != fileSize)␊ |
2085 | ␉␉␉␉␉{␊ |
2086 | ␉␉␉␉␉␉error = -1;␊ |
2087 | ␉␉␉␉␉}␊ |
2088 | ␉␉␉␉}␊ |
2089 | ␉␉␉␉else␊ |
2090 | ␉␉␉␉{␊ |
2091 | ␉␉␉␉␉error = -1;␊ |
2092 | ␉␉␉␉}␊ |
2093 | ␊ |
2094 | ␉␉␉␉close(fh);␊ |
2095 | ␊ |
2096 | ␉␉␉␉if (!error)␊ |
2097 | ␉␉␉␉{␊ |
2098 | ␉␉␉␉␉label[fileSize] = '\0';␊ |
2099 | ␉␉␉␉␉strlcpy(bvr->altlabel, label, sizeof(bvr->altlabel));␊ |
2100 | ␉␉␉␉}␊ |
2101 | ␉␉␉}␊ |
2102 | ␉␉}␊ |
2103 | ␊ |
2104 | ␉␉// Check for SystemVersion.plist or ServerVersion.plist or com.apple.boot.plist to determine if a volume hosts an installed system.␊ |
2105 | ␊ |
2106 | ␉␉if (bvr->flags & kBVFlagNativeBoot)␊ |
2107 | ␉␉{␊ |
2108 | ␉␉␉if (getOSVersion(bvr, bvr->OSVersion) == true)␊ |
2109 | ␉␉␉{␊ |
2110 | ␉␉␉␉bvr->flags |= kBVFlagSystemVolume;␊ |
2111 | ␉␉␉}␊ |
2112 | ␉␉}␊ |
2113 | ␊ |
2114 | ␉}␊ |
2115 | }␊ |
2116 | ␊ |
2117 | //==============================================================================␊ |
2118 | void rescanBIOSDevice(int biosdev)␊ |
2119 | {␊ |
2120 | ␉struct DiskBVMap *oldMap = diskResetBootVolumes(biosdev);␊ |
2121 | ␉if (oldMap == NULL)␊ |
2122 | ␉{␊ |
2123 | ␉␉return;␊ |
2124 | ␉}␊ |
2125 | ␊ |
2126 | ␉CacheReset();␊ |
2127 | ␉diskFreeMap(oldMap);␊ |
2128 | ␉oldMap = NULL;␊ |
2129 | ␉scanBootVolumes(biosdev, 0);␊ |
2130 | }␊ |
2131 | ␊ |
2132 | //==============================================================================␊ |
2133 | struct DiskBVMap* diskResetBootVolumes(int biosdev)␊ |
2134 | {␊ |
2135 | ␉struct DiskBVMap * map;␊ |
2136 | ␉struct DiskBVMap *prevMap = NULL;␊ |
2137 | ␉for ( map = gDiskBVMap; map; prevMap = map, map = map->next ) {␊ |
2138 | ␉␉if ( biosdev == map->biosdev ) {␊ |
2139 | ␉␉␉break;␊ |
2140 | ␉␉}␊ |
2141 | ␉}␊ |
2142 | ␊ |
2143 | ␉if(map != NULL) {␊ |
2144 | ␉␉verbose("Resetting BIOS device %xh\n", biosdev);␊ |
2145 | ␉␉// Reset the biosbuf cache␊ |
2146 | ␉␉cache_valid = false;␊ |
2147 | ␉␉if(map == gDiskBVMap)␊ |
2148 | ␉␉{␊ |
2149 | ␉␉␉gDiskBVMap = map->next;␊ |
2150 | ␉␉}␊ |
2151 | ␉␉else if(prevMap != NULL)␊ |
2152 | ␉␉{␊ |
2153 | ␉␉␉prevMap->next = map->next;␊ |
2154 | ␉␉}␊ |
2155 | ␉␉else␊ |
2156 | ␉␉{␊ |
2157 | ␉␉␉stop("diskResetBootVolumes error\n");␊ |
2158 | ␉␉␉return NULL;␊ |
2159 | ␉␉}␊ |
2160 | ␉}␊ |
2161 | ␉// Return the old map, either to be freed, or reinserted later␊ |
2162 | ␉return map;␊ |
2163 | }␊ |
2164 | ␊ |
2165 | //==============================================================================␊ |
2166 | // Frees a DiskBVMap and all of its BootVolume's␊ |
2167 | void diskFreeMap(struct DiskBVMap *map)␊ |
2168 | {␊ |
2169 | ␉if(map != NULL)␊ |
2170 | ␉{␊ |
2171 | ␉␉while(map->bvr != NULL)␊ |
2172 | ␉␉{␊ |
2173 | ␉␉␉BVRef bvr = map->bvr;␊ |
2174 | ␉␉␉map->bvr = bvr->next;␊ |
2175 | ␉␉␉(*bvr->bv_free)(bvr);␊ |
2176 | ␉␉}␊ |
2177 | ␊ |
2178 | ␉␉free(map);␊ |
2179 | ␉}␊ |
2180 | }␊ |
2181 | ␊ |
2182 | //==============================================================================␊ |
2183 | BVRef diskScanBootVolumes(int biosdev, int *countPtr)␊ |
2184 | {␊ |
2185 | ␉struct DiskBVMap *map;␊ |
2186 | ␉BVRef bvr;␊ |
2187 | ␉int count = 0;␊ |
2188 | ␊ |
2189 | ␉// Find an existing mapping for this device.␊ |
2190 | ␊ |
2191 | ␉for (map = gDiskBVMap; map; map = map->next)␊ |
2192 | ␉{␊ |
2193 | ␉␉if (biosdev == map->biosdev)␊ |
2194 | ␉␉{␊ |
2195 | ␉␉␉count = map->bvrcnt;␊ |
2196 | ␉␉␉break;␊ |
2197 | ␉␉}␊ |
2198 | ␉}␊ |
2199 | ␊ |
2200 | ␉if (map == NULL)␊ |
2201 | ␉{␊ |
2202 | ␉␉bvr = diskScanGPTBootVolumes(biosdev, &count);␊ |
2203 | ␉␉if (bvr == NULL)␊ |
2204 | ␉␉{␊ |
2205 | ␉␉␉bvr = diskScanFDiskBootVolumes(biosdev, &count);␊ |
2206 | ␉␉}␊ |
2207 | ␊ |
2208 | ␉␉if (bvr == NULL)␊ |
2209 | ␉␉{␊ |
2210 | ␉␉␉bvr = diskScanAPMBootVolumes(biosdev, &count);␊ |
2211 | ␉␉}␊ |
2212 | ␊ |
2213 | ␉␉if (bvr)␊ |
2214 | ␉␉{␊ |
2215 | ␉␉␉scanFSLevelBVRSettings(bvr);␊ |
2216 | ␉␉}␊ |
2217 | ␉}␊ |
2218 | ␉else␊ |
2219 | ␉{␊ |
2220 | ␉␉bvr = map->bvr;␊ |
2221 | ␉}␊ |
2222 | ␊ |
2223 | ␉if (countPtr)␊ |
2224 | ␉{␊ |
2225 | ␉␉*countPtr += count;␊ |
2226 | ␉}␊ |
2227 | ␊ |
2228 | ␉return bvr;␊ |
2229 | }␊ |
2230 | ␊ |
2231 | //==============================================================================␊ |
2232 | BVRef getBVChainForBIOSDev(int biosdev)␊ |
2233 | {␊ |
2234 | ␉BVRef chain = NULL;␊ |
2235 | ␉struct DiskBVMap * map = NULL;␊ |
2236 | ␊ |
2237 | ␉for (map = gDiskBVMap; map; map = map->next)␊ |
2238 | ␉{␊ |
2239 | ␉␉if (map->biosdev == biosdev)␊ |
2240 | ␉␉{␊ |
2241 | ␉␉␉chain = map->bvr;␊ |
2242 | ␉␉␉break;␊ |
2243 | ␉␉}␊ |
2244 | ␉}␊ |
2245 | ␊ |
2246 | ␉return chain;␊ |
2247 | }␊ |
2248 | ␊ |
2249 | //==============================================================================␊ |
2250 | BVRef newFilteredBVChain(int minBIOSDev, int maxBIOSDev, unsigned int allowFlags, unsigned int denyFlags, int *count)␊ |
2251 | {␊ |
2252 | ␉BVRef chain = NULL;␊ |
2253 | ␉BVRef bvr = NULL;␊ |
2254 | ␉BVRef newBVR = NULL;␊ |
2255 | ␉BVRef prevBVR = NULL;␊ |
2256 | ␊ |
2257 | ␉struct DiskBVMap * map = NULL;␊ |
2258 | ␉int bvCount = 0;␊ |
2259 | ␊ |
2260 | ␉const char *raw = 0;␊ |
2261 | ␉char* val = 0;␊ |
2262 | ␉int len;␊ |
2263 | ␊ |
2264 | ␉getValueForKey(kHidePartition, &raw, &len, &bootInfo->chameleonConfig);␊ |
2265 | ␉if(raw)␊ |
2266 | ␉{␊ |
2267 | ␉␉val = XMLDecode(raw); ␊ |
2268 | ␉}␊ |
2269 | ␊ |
2270 | ␉// Traverse gDISKBVmap to get references for␊ |
2271 | ␉// individual bvr chains of each drive.␊ |
2272 | ␉for (map = gDiskBVMap; map; map = map->next)␊ |
2273 | ␉{␊ |
2274 | ␉␉for (bvr = map->bvr; bvr; bvr = bvr->next)␊ |
2275 | ␉␉{␊ |
2276 | ␉␉␉// Save the last bvr.␊ |
2277 | ␉␉␉if (newBVR)␊ |
2278 | ␉␉␉{␊ |
2279 | ␉␉␉␉prevBVR = newBVR;␊ |
2280 | ␉␉␉}␊ |
2281 | ␊ |
2282 | ␉␉␉// Allocate and copy the matched bvr entry into a new one.␊ |
2283 | ␉␉␉newBVR = (BVRef) malloc(sizeof(*newBVR));␊ |
2284 | ␉␉␉if (!newBVR)␊ |
2285 | ␉␉␉{␊ |
2286 | ␉␉␉␉continue;␊ |
2287 | ␉␉␉}␊ |
2288 | ␉␉␉bzero(newBVR,sizeof(*newBVR));␊ |
2289 | ␊ |
2290 | ␉␉␉bcopy(bvr, newBVR, sizeof(*newBVR));␊ |
2291 | ␊ |
2292 | ␉␉␉// Adjust the new bvr's fields.␊ |
2293 | ␉␉␉newBVR->next = NULL;␊ |
2294 | ␉␉␉newBVR->filtered = true;␊ |
2295 | ␊ |
2296 | ␉␉␉if ( (!allowFlags || newBVR->flags & allowFlags)␊ |
2297 | ␉␉␉␉&& (!denyFlags || !(newBVR->flags & denyFlags) )␊ |
2298 | ␉␉␉␉&& (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev)␊ |
2299 | ␉␉␉␉)␊ |
2300 | ␉␉␉{␊ |
2301 | ␉␉␉␉newBVR->visible = true;␊ |
2302 | ␉␉␉}␊ |
2303 | ␊ |
2304 | ␉␉␉// Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format,␊ |
2305 | ␉␉␉// to be able to hide foreign partitions from the boot menu.␊ |
2306 | ␊ |
2307 | ␉␉␉if ( (newBVR->flags & kBVFlagForeignBoot) )␊ |
2308 | ␉␉␉{␊ |
2309 | ␉␉␉␉char *start, *next = val;␊ |
2310 | ␉␉␉␉long len = 0; ␊ |
2311 | ␉␉␉␉do␊ |
2312 | ␉␉␉␉{␊ |
2313 | ␉␉␉␉␉start = strbreak(next, &next, &len);␊ |
2314 | ␉␉␉␉␉if(len && matchVolumeToString(newBVR, start, len) )␊ |
2315 | ␉␉␉␉␉{␊ |
2316 | ␉␉␉␉␉␉newBVR->visible = false;␊ |
2317 | ␉␉␉␉␉}␊ |
2318 | ␉␉␉␉}␊ |
2319 | ␉␉␉␉while ( next && *next );␊ |
2320 | ␉␉␉}␊ |
2321 | ␊ |
2322 | ␉␉␉// Use the first bvr entry as the starting chain pointer.␊ |
2323 | ␉␉␉if (!chain)␊ |
2324 | ␉␉␉{␊ |
2325 | ␉␉␉␉chain = newBVR;␊ |
2326 | ␉␉␉}␊ |
2327 | ␊ |
2328 | ␉␉␉// Update the previous bvr's link pointer to use the new memory area.␊ |
2329 | ␉␉␉if (prevBVR)␊ |
2330 | ␉␉␉{␊ |
2331 | ␉␉␉␉prevBVR->next = newBVR;␊ |
2332 | ␉␉␉}␊ |
2333 | ␊ |
2334 | ␉␉␉if (newBVR->visible)␊ |
2335 | ␉␉␉{␊ |
2336 | ␉␉␉␉bvCount++;␊ |
2337 | ␉␉␉}␊ |
2338 | ␉␉}␊ |
2339 | ␉}␊ |
2340 | ␊ |
2341 | #if DEBUG //Azi: warning - too big for boot-log.. far too big.. i mean HUGE!! :P␊ |
2342 | ␉for (bvr = chain; bvr; bvr = bvr->next)␊ |
2343 | ␉{␊ |
2344 | ␉␉if (!bvr)␊ |
2345 | ␉␉{␊ |
2346 | ␉␉␉break;␊ |
2347 | ␉␉}␊ |
2348 | ␉␉printf(" bvr: %d, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible);␊ |
2349 | ␉}␊ |
2350 | ␉printf("count: %d\n", bvCount);␊ |
2351 | ␉getchar();␊ |
2352 | #endif␊ |
2353 | ␊ |
2354 | ␉*count = bvCount;␊ |
2355 | ␊ |
2356 | ␉free(val); ␊ |
2357 | ␉return chain;␊ |
2358 | }␊ |
2359 | ␊ |
2360 | //==============================================================================␊ |
2361 | int freeFilteredBVChain(const BVRef chain)␊ |
2362 | {␊ |
2363 | ␉int ret = 1;␊ |
2364 | ␉BVRef bvr = chain;␊ |
2365 | ␉BVRef nextBVR = NULL;␊ |
2366 | ␊ |
2367 | ␉while (bvr)␊ |
2368 | ␉{␊ |
2369 | ␉␉if (!bvr)␊ |
2370 | ␉␉{␊ |
2371 | ␉␉␉break;␊ |
2372 | ␉␉}␊ |
2373 | ␊ |
2374 | ␉␉nextBVR = bvr->next;␊ |
2375 | ␊ |
2376 | ␉␉if (bvr->filtered)␊ |
2377 | ␉␉{␊ |
2378 | ␉␉␉free(bvr);␊ |
2379 | ␉␉}␊ |
2380 | ␉␉else␊ |
2381 | ␉␉{␊ |
2382 | ␉␉␉ret = 0;␊ |
2383 | ␉␉␉break;␊ |
2384 | ␉␉}␊ |
2385 | ␊ |
2386 | ␉␉bvr = nextBVR;␊ |
2387 | ␉}␊ |
2388 | ␊ |
2389 | ␉return ret;␊ |
2390 | }␊ |
2391 | ␊ |
2392 | //==============================================================================␊ |
2393 | bool matchVolumeToString( BVRef bvr, const char *match, long matchLen)␊ |
2394 | {␊ |
2395 | ␉char testStr[128];␊ |
2396 | ␊ |
2397 | ␉if ( !bvr || !match || !*match)␊ |
2398 | ␉{␊ |
2399 | ␉␉return 0;␊ |
2400 | ␉}␊ |
2401 | ␊ |
2402 | ␉if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 )␊ |
2403 | ␉{␊ |
2404 | return 0;␊ |
2405 | ␉}␊ |
2406 | ␊ |
2407 | ␉// Try to match hd(x,y) first.␊ |
2408 | ␉snprintf(testStr, sizeof(testStr), "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
2409 | ␉if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )␊ |
2410 | ␉{␊ |
2411 | ␉␉return true;␊ |
2412 | ␉}␊ |
2413 | ␊ |
2414 | ␉// Try to match volume UUID.␊ |
2415 | ␉if ( bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0)␊ |
2416 | ␉{␊ |
2417 | ␉␉if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )␊ |
2418 | ␉␉{␊ |
2419 | ␉␉␉return true;␊ |
2420 | ␉␉}␊ |
2421 | ␉}␊ |
2422 | ␊ |
2423 | ␉// Try to match volume label (always quoted).␊ |
2424 | ␉if ( bvr->description )␊ |
2425 | ␉{␊ |
2426 | ␉␉bvr->description(bvr, testStr, sizeof(testStr)-1);␊ |
2427 | ␉␉if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )␊ |
2428 | ␉␉{␊ |
2429 | ␉␉␉return true;␊ |
2430 | ␉␉}␊ |
2431 | ␉}␊ |
2432 | ␊ |
2433 | ␉return false;␊ |
2434 | }␊ |
2435 | ␊ |
2436 | //==============================================================================␊ |
2437 | /* If Rename Partition has defined an alias, then extract it for description purpose.␊ |
2438 | * The format for the rename string is the following:␊ |
2439 | * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" "alias"; etc...␊ |
2440 | */␊ |
2441 | static bool getVolumeLabelAlias(BVRef bvr, char *str, long strMaxLen)␊ |
2442 | {␊ |
2443 | ␉char *aliasList, *entryStart, *entryNext;␊ |
2444 | ␊ |
2445 | ␉if ( !str || strMaxLen <= 0)␊ |
2446 | ␉{␊ |
2447 | ␉␉return false;␊ |
2448 | ␉}␊ |
2449 | ␊ |
2450 | ␉aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->chameleonConfig));␊ |
2451 | ␉if ( !aliasList )␊ |
2452 | ␉{␊ |
2453 | ␉␉return false;␊ |
2454 | ␉}␊ |
2455 | ␊ |
2456 | ␉for ( entryStart = entryNext = aliasList; entryNext && *entryNext; entryStart = entryNext )␊ |
2457 | ␉{␊ |
2458 | ␉␉char *volStart, *volEnd, *aliasStart;␊ |
2459 | ␉␉long volLen, aliasLen;␊ |
2460 | ␊ |
2461 | ␉␉// Delimit current entry␊ |
2462 | ␉␉entryNext = strchr(entryStart, ';');␊ |
2463 | ␉␉if ( entryNext )␊ |
2464 | ␉␉{␊ |
2465 | ␉␉␉*entryNext = '\0';␊ |
2466 | ␉␉␉entryNext++;␊ |
2467 | ␉␉}␊ |
2468 | ␊ |
2469 | ␉␉volStart = strbreak(entryStart, &volEnd, &volLen);␊ |
2470 | ␉␉if(!volLen)␊ |
2471 | ␉␉{␊ |
2472 | ␉␉␉continue;␊ |
2473 | ␉␉}␊ |
2474 | ␊ |
2475 | ␉␉aliasStart = strbreak(volEnd, 0, &aliasLen);␊ |
2476 | ␉␉if(!aliasLen)␊ |
2477 | ␉␉{␊ |
2478 | ␉␉␉continue;␊ |
2479 | ␉␉}␊ |
2480 | ␊ |
2481 | ␉␉if ( matchVolumeToString(bvr, volStart, volLen) )␊ |
2482 | ␉␉{␊ |
2483 | ␉␉␉strncat(str, aliasStart, MIN(strMaxLen, aliasLen));␊ |
2484 | ␉␉␉free(aliasList);␊ |
2485 | ␊ |
2486 | ␉␉␉return true;␊ |
2487 | ␉␉}␊ |
2488 | ␉}␊ |
2489 | ␊ |
2490 | ␉free(aliasList);␊ |
2491 | ␉return false;␊ |
2492 | }␊ |
2493 | ␊ |
2494 | //==============================================================================␊ |
2495 | void getBootVolumeDescription( BVRef bvr, char *str, long strMaxLen, bool useDeviceDescription )␊ |
2496 | {␊ |
2497 | ␉unsigned char type;␊ |
2498 | ␉char *p = str;␊ |
2499 | ␊ |
2500 | ␉if(!bvr || !p || strMaxLen <= 0)␊ |
2501 | ␉{␊ |
2502 | ␉␉return;␊ |
2503 | ␉}␊ |
2504 | ␊ |
2505 | ␉type = (unsigned char) bvr->part_type;␊ |
2506 | ␊ |
2507 | ␉if (useDeviceDescription)␊ |
2508 | ␉{␊ |
2509 | ␉␉int len = getDeviceDescription(bvr, str);␊ |
2510 | ␉␉if(len >= strMaxLen)␊ |
2511 | ␉␉{␊ |
2512 | ␉␉␉return;␊ |
2513 | ␉␉}␊ |
2514 | ␊ |
2515 | ␉␉strcpy(str + len, bvr->OSisInstaller ? " (Installer " : " (");␊ |
2516 | ␉␉len += bvr->OSisInstaller ? 12 : 2;␊ |
2517 | ␉␉strcpy(str + len, bvr->OSVersion);␊ |
2518 | ␉␉len += strlen(bvr->OSVersion);␊ |
2519 | ␉␉strcpy(str + len, ") ");␊ |
2520 | ␉␉len += 2;␊ |
2521 | ␊ |
2522 | ␉␉strMaxLen -= len;␊ |
2523 | ␉␉p += len;␊ |
2524 | ␉}␊ |
2525 | ␊ |
2526 | ␉/* See if a partition rename is preferred */␊ |
2527 | ␉if (getVolumeLabelAlias(bvr, p, strMaxLen))␊ |
2528 | ␉{␊ |
2529 | ␉␉strncpy(bvr->label, p, strMaxLen); ␊ |
2530 | ␉␉return; // we're done here no need to seek for real name␊ |
2531 | ␉}␊ |
2532 | ␊ |
2533 | ␉// Get the volume label using filesystem specific functions or use the alternate volume label if available.␊ |
2534 | ␊ |
2535 | ␉if (*bvr->altlabel != '\0')␊ |
2536 | ␉{␊ |
2537 | ␉␉strncpy(p, bvr->altlabel, strMaxLen);␊ |
2538 | ␉}␊ |
2539 | ␉else if (bvr->description)␊ |
2540 | ␉{␊ |
2541 | ␉␉bvr->description(bvr, p, strMaxLen);␊ |
2542 | ␉}␊ |
2543 | ␊ |
2544 | ␉if (*p == '\0')␊ |
2545 | ␉{␊ |
2546 | ␉␉const char * name = getNameForValue( fdiskTypes, type );␊ |
2547 | ␊ |
2548 | ␉␉if (name == NULL)␊ |
2549 | ␉␉{␊ |
2550 | ␉␉␉name = bvr->type_name;␊ |
2551 | ␉␉}␊ |
2552 | ␊ |
2553 | ␉␉if (name == NULL)␊ |
2554 | ␉␉{␊ |
2555 | ␉␉␉snprintf(p, strMaxLen, "TYPE %02X", type);␊ |
2556 | ␉␉}␊ |
2557 | ␉␉else␊ |
2558 | ␉␉{␊ |
2559 | ␉␉␉strncpy(p, name, strMaxLen);␊ |
2560 | ␉␉}␊ |
2561 | ␉}␊ |
2562 | ␊ |
2563 | ␉// Set the devices label␊ |
2564 | ␉strncpy(bvr->label, p, sizeof(bvr->label) );␊ |
2565 | }␊ |
2566 | ␊ |
2567 | //==============================================================================␊ |
2568 | int readBootSector(int biosdev, unsigned int secno, void *buffer)␊ |
2569 | {␊ |
2570 | ␉int error;␊ |
2571 | ␉struct disk_blk0 * bootSector = (struct disk_blk0 *)buffer;␊ |
2572 | ␊ |
2573 | ␉if (bootSector == NULL)␊ |
2574 | ␉{␊ |
2575 | ␉␉if (gBootSector == NULL)␊ |
2576 | ␉␉{␊ |
2577 | ␉␉␉gBootSector = (struct disk_blk0 *)malloc(sizeof(*gBootSector));␊ |
2578 | ␊ |
2579 | ␉␉␉if (gBootSector == NULL)␊ |
2580 | ␉␉␉{␊ |
2581 | ␉␉␉␉return -1;␊ |
2582 | ␉␉␉}␊ |
2583 | ␉␉}␊ |
2584 | ␊ |
2585 | ␉␉bootSector = gBootSector;␊ |
2586 | ␉}␊ |
2587 | ␊ |
2588 | ␉error = readBytes(biosdev, secno, 0, BPS, bootSector);␊ |
2589 | ␊ |
2590 | ␉if (error || bootSector->signature != DISK_SIGNATURE)␊ |
2591 | ␉{␊ |
2592 | ␉␉return -1;␊ |
2593 | ␉}␊ |
2594 | ␉return 0;␊ |
2595 | }␊ |
2596 | ␊ |
2597 | //==============================================================================␊ |
2598 | /*␊ |
2599 | * Format of boot1f32 block.␊ |
2600 | */␊ |
2601 | #define BOOT1F32_MAGIC "BOOT "␊ |
2602 | #define BOOT1F32_MAGICLEN 11␊ |
2603 | ␊ |
2604 | struct disk_boot1f32_blk␊ |
2605 | {␊ |
2606 | ␉unsigned char init[3];␊ |
2607 | ␉unsigned char fsheader[87];␊ |
2608 | ␉unsigned char magic[BOOT1F32_MAGICLEN];␊ |
2609 | ␉unsigned char bootcode[409];␊ |
2610 | ␉unsigned short signature;␊ |
2611 | };␊ |
2612 | ␊ |
2613 | //==============================================================================␊ |
2614 | ␊ |
2615 | int testFAT32EFIBootSector(int biosdev, unsigned int secno, void *buffer)␊ |
2616 | {␊ |
2617 | ␉struct disk_boot1f32_blk *bootSector = (struct disk_boot1f32_blk *)buffer;␊ |
2618 | ␉int error;␊ |
2619 | ␊ |
2620 | ␉if (bootSector == NULL)␊ |
2621 | ␉{␊ |
2622 | ␉␉if (gBootSector == NULL)␊ |
2623 | ␉␉{␊ |
2624 | ␉␉␉gBootSector = (struct disk_blk0 *)malloc(sizeof(*gBootSector));␊ |
2625 | ␉␉␉if ( gBootSector == NULL )␊ |
2626 | ␉␉␉{␊ |
2627 | ␉␉␉␉return -1;␊ |
2628 | ␉␉␉}␊ |
2629 | ␉␉}␊ |
2630 | ␉␉bootSector = (struct disk_boot1f32_blk *)gBootSector;␊ |
2631 | ␉}␊ |
2632 | ␊ |
2633 | ␉error = readBytes(biosdev, secno, 0, BPS, bootSector);␊ |
2634 | ␉if (error || bootSector->signature != DISK_SIGNATURE || strncmp((const char *)bootSector->magic, BOOT1F32_MAGIC, BOOT1F32_MAGICLEN) )␊ |
2635 | ␉{␊ |
2636 | ␉␉return -1;␊ |
2637 | ␉}␊ |
2638 | ␉return 0;␊ |
2639 | }␊ |
2640 | ␊ |
2641 | //==============================================================================␊ |
2642 | // Handle seek request from filesystem modules.␊ |
2643 | void diskSeek(BVRef bvr, long long position)␊ |
2644 | {␊ |
2645 | ␉bvr->fs_boff = position / BPS;␊ |
2646 | ␉bvr->fs_byteoff = position % BPS;␊ |
2647 | }␊ |
2648 | ␊ |
2649 | //==============================================================================␊ |
2650 | // Handle read request from filesystem modules.␊ |
2651 | int diskRead(BVRef bvr, long addr, long length)␊ |
2652 | {␊ |
2653 | ␉return readBytes(bvr->biosdev, bvr->fs_boff + bvr->part_boff, bvr->fs_byteoff, length, (void *) addr);␊ |
2654 | }␊ |
2655 | ␊ |
2656 | //==============================================================================␊ |
2657 | int rawDiskRead( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )␊ |
2658 | {␊ |
2659 | ␉int secs;␊ |
2660 | ␉unsigned char *cbuf = (unsigned char *)buffer;␊ |
2661 | ␉unsigned int copy_len;␊ |
2662 | ␉int rc;␊ |
2663 | ␊ |
2664 | ␉if ((len & (BPS-1)) != 0)␊ |
2665 | ␉{␊ |
2666 | ␉␉error("raw disk read not sector aligned");␊ |
2667 | ␉␉return -1;␊ |
2668 | ␉}␊ |
2669 | ␉secno += bvr->part_boff;␊ |
2670 | ␊ |
2671 | ␉cache_valid = false;␊ |
2672 | ␊ |
2673 | ␉while (len > 0)␊ |
2674 | ␉{␊ |
2675 | ␉␉secs = len / BPS;␊ |
2676 | ␉␉if (secs > N_CACHE_SECS)␊ |
2677 | ␉␉{␊ |
2678 | ␉␉␉secs = N_CACHE_SECS;␊ |
2679 | ␉␉}␊ |
2680 | ␉␉copy_len = secs * BPS;␊ |
2681 | ␊ |
2682 | ␉␉//printf("rdr: ebiosread(%d, %d, %d)\n", bvr->biosdev, secno, secs);␊ |
2683 | ␉␉if ((rc = ebiosread(bvr->biosdev, secno, secs)) != 0)␊ |
2684 | ␉␉{␊ |
2685 | ␉␉␉/* Ignore corrected ECC errors */␊ |
2686 | ␉␉␉if (rc != ECC_CORRECTED_ERR)␊ |
2687 | ␉␉␉{␊ |
2688 | ␉␉␉␉error(" EBIOS read error: %s\n", bios_error(rc), rc);␊ |
2689 | ␉␉␉␉error(" Block %d Sectors %d\n", secno, secs);␊ |
2690 | ␉␉␉␉return rc;␊ |
2691 | ␉␉␉}␊ |
2692 | ␉␉}␊ |
2693 | ␉␉bcopy( trackbuf, cbuf, copy_len );␊ |
2694 | ␉␉len -= copy_len;␊ |
2695 | ␉␉cbuf += copy_len;␊ |
2696 | ␉␉secno += secs;␊ |
2697 | ␉␉spinActivityIndicator(secs);␊ |
2698 | ␉}␊ |
2699 | ␊ |
2700 | ␉return 0;␊ |
2701 | }␊ |
2702 | ␊ |
2703 | //==============================================================================␊ |
2704 | int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )␊ |
2705 | {␊ |
2706 | int secs;␊ |
2707 | unsigned char *cbuf = (unsigned char *)buffer;␊ |
2708 | unsigned int copy_len;␊ |
2709 | int rc;␊ |
2710 | ␊ |
2711 | ␉if ((len & (BPS-1)) != 0)␊ |
2712 | ␉{␊ |
2713 | ␉␉error("raw disk write not sector aligned");␊ |
2714 | ␉␉return -1;␊ |
2715 | ␉}␊ |
2716 | ␉secno += bvr->part_boff;␊ |
2717 | ␊ |
2718 | ␉cache_valid = false;␊ |
2719 | ␊ |
2720 | ␉while (len > 0)␊ |
2721 | ␉{␊ |
2722 | ␉␉secs = len / BPS;␊ |
2723 | ␉␉if (secs > N_CACHE_SECS)␊ |
2724 | ␉␉{␊ |
2725 | ␉␉␉secs = N_CACHE_SECS;␊ |
2726 | ␉␉}␊ |
2727 | ␉␉copy_len = secs * BPS;␊ |
2728 | ␊ |
2729 | ␉␉bcopy( cbuf, trackbuf, copy_len );␊ |
2730 | ␉␉//printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs);␊ |
2731 | ␉␉if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0)␊ |
2732 | ␉␉{␊ |
2733 | ␉␉␉error(" EBIOS write error: %s\n", bios_error(rc), rc);␊ |
2734 | ␉␉␉error(" Block %d Sectors %d\n", secno, secs);␊ |
2735 | ␉␉␉return rc;␊ |
2736 | ␉␉}␊ |
2737 | ␊ |
2738 | ␉␉len -= copy_len;␊ |
2739 | ␉␉cbuf += copy_len;␊ |
2740 | ␉␉secno += secs;␊ |
2741 | ␉␉spinActivityIndicator(secs);␊ |
2742 | ␉}␊ |
2743 | ␊ |
2744 | ␉return 0;␊ |
2745 | }␊ |
2746 | ␊ |
2747 | //==============================================================================␊ |
2748 | int diskIsCDROM(BVRef bvr)␊ |
2749 | {␊ |
2750 | ␉struct driveInfo di;␊ |
2751 | ␊ |
2752 | ␉if (getDriveInfo(bvr->biosdev, &di) == 0 && di.no_emulation)␊ |
2753 | ␉{␊ |
2754 | ␉␉return 1;␊ |
2755 | ␉}␊ |
2756 | ␉return 0;␊ |
2757 | }␊ |
2758 | ␊ |
2759 | //==============================================================================␊ |
2760 | int biosDevIsCDROM(int biosdev)␊ |
2761 | {␊ |
2762 | ␉struct driveInfo di;␊ |
2763 | ␊ |
2764 | ␉if (getDriveInfo(biosdev, &di) == 0 && di.no_emulation)␊ |
2765 | ␉{␊ |
2766 | ␉␉return 1;␊ |
2767 | ␉}␊ |
2768 | ␉return 0;␊ |
2769 | }␊ |
2770 | |