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

Archive Download this file

Revision: 2117