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