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