Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/disk.c

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

Archive Download this file

Revision: 1972