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(struct BootVolume) );
592 if ( bvr )
593 {
594 bzero(bvr, sizeof(struct BootVolume));
595
596 bvr->biosdev = biosdev;
597 bvr->part_no = partno;
598 bvr->part_boff = blkoff;
599 bvr->part_type = part->systid;
600 bvr->fs_loadfile = loadFunc;
601 bvr->fs_readfile = readFunc;
602 bvr->fs_getdirentry = getdirFunc;
603 bvr->fs_getfileblock= getBlockFunc;
604 bvr->fs_getuuid = getUUIDFunc;
605 bvr->description = getDescriptionFunc;
606 bvr->type = type;
607 bvr->bv_free = bvFreeFunc;
608
609 if ((part->bootid & FDISK_ACTIVE) && (part->systid == FDISK_HFS))
610 bvr->flags |= kBVFlagPrimary;
611
612 // Probe the filesystem.
613
614 if ( initFunc )
615 {
616 bvr->flags |= kBVFlagNativeBoot;
617
618 if ( probe && initFunc( bvr ) != 0 )
619 {
620 // filesystem probe failed.
621
622 DEBUG_DISK(("%s: failed probe on dev %x part %d\n",
623 __FUNCTION__, biosdev, partno));
624
625 (*bvr->bv_free)(bvr);
626 bvr = NULL;
627 }
628 if ( bvr && readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )
629 {
630 bvr->flags |= kBVFlagBootable;
631 }
632 }
633 else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )
634 {
635 bvr->flags |= kBVFlagForeignBoot;
636 }
637 else
638 {
639 (*bvr->bv_free)(bvr);
640 bvr = NULL;
641 }
642 }
643 if (bvr) bvr->flags |= bvrFlags;
644 return bvr;
645}
646
647#ifdef APPLE_PARTITION_MAP_SUPPORT
648//==========================================================================
649
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(struct BootVolume) );
662 if ( bvr )
663 {
664 bzero(bvr, sizeof(struct BootVolume));
665
666 bvr->biosdev = biosdev;
667 bvr->part_no = partno;
668 bvr->part_boff = blkoff;
669 bvr->fs_loadfile = loadFunc;
670 bvr->fs_readfile = readFunc;
671 bvr->fs_getdirentry = getdirFunc;
672 bvr->fs_getfileblock= getBlockFunc;
673 bvr->fs_getuuid = getUUIDFunc;
674 bvr->description = getDescriptionFunc;
675 bvr->type = type;
676 bvr->bv_free = bvFreeFunc;
677 strlcpy(bvr->name, part->dpme_name, DPISTRLEN);
678 strlcpy(bvr->type_name, part->dpme_type, DPISTRLEN);
679
680 /*
681 if ( part->bootid & FDISK_ACTIVE )
682 bvr->flags |= kBVFlagPrimary;
683 */
684
685 // Probe the filesystem.
686
687 if ( initFunc )
688 {
689 bvr->flags |= kBVFlagNativeBoot | kBVFlagBootable | kBVFlagSystemVolume;
690
691 if ( probe && initFunc( bvr ) != 0 )
692 {
693 // filesystem probe failed.
694
695 DEBUG_DISK(("%s: failed probe on dev %x part %d\n",
696 __FUNCTION__, biosdev, partno));
697
698 (*bvr->bv_free)(bvr);
699 bvr = NULL;
700 }
701 }
702 /*
703 else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )
704 {
705 bvr->flags |= kBVFlagForeignBoot;
706 }
707 */
708 else
709 {
710 (*bvr->bv_free)(bvr);
711 bvr = NULL;
712 }
713 }
714 if (bvr) bvr->flags |= bvrFlags;
715 return bvr;
716}
717#endif
718//==========================================================================
719
720// HFS+ GUID in LE form
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(struct BootVolume) );
743 if ( bvr )
744 {
745 bzero(bvr, sizeof(struct BootVolume));
746
747 bvr->biosdev = biosdev;
748 bvr->part_no = partno;
749 bvr->part_boff = blkoff;
750 bvr->fs_loadfile = loadFunc;
751 bvr->fs_readfile = readFunc;
752 bvr->fs_getdirentry = getdirFunc;
753 bvr->fs_getfileblock= getBlockFunc;
754 bvr->fs_getuuid = getUUIDFunc;
755 bvr->description = getDescriptionFunc;
756 bvr->type = type;
757 bvr->bv_free = bvFreeFunc;
758 // FIXME: UCS-2 -> UTF-8 the name
759 strlcpy(bvr->name, "----", DPISTRLEN);
760 if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)part->ent_type) == 0) ||
761(efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)part->ent_type) == 0) )
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(struct DiskBVMap) );
841 if ( !map )
842 {
843 return NULL;
844 }
845 bzero(map,sizeof(struct DiskBVMap));
846
847 do {
848
849 map->biosdev = biosdev;
850 map->bvr = NULL;
851 map->bvrcnt = 0;
852 map->next = gDiskBVMap;
853 gDiskBVMap = map;
854
855 // Create a record for each partition found on the disk.
856
857 while ( getNextFDiskPartition( biosdev, &partno, &part ) )
858 {
859 DEBUG_DISK(("%s: part %d [%x]\n", __FUNCTION__,
860 partno, part->systid));
861 bvr = 0;
862
863 switch ( part->systid )
864 {
865#ifdef UFS_SUPPORT
866 case FDISK_UFS:
867 bvr = newFDiskBVRef(
868 biosdev, partno,
869 part->relsect + UFS_FRONT_PORCH/BPS,
870 part,
871 UFSInitPartition,
872 UFSLoadFile,
873 UFSReadFile,
874 UFSGetDirEntry,
875 UFSGetFileBlock,
876 UFSGetUUID,
877 UFSGetDescription,
878 UFSFree,
879 0,
880 kBIOSDevTypeHardDrive, 0);
881 break;
882#endif
883
884 case FDISK_HFS:
885 bvr = newFDiskBVRef(
886 biosdev, partno,
887 part->relsect,
888 part,
889 HFSInitPartition,
890 HFSLoadFile,
891 HFSReadFile,
892 HFSGetDirEntry,
893 HFSGetFileBlock,
894 HFSGetUUID,
895 HFSGetDescription,
896 HFSFree,
897 0,
898 kBIOSDevTypeHardDrive, 0);
899 break;
900
901 // turbo - we want the booter type scanned also
902 case FDISK_BOOTER:
903 if (part->bootid & FDISK_ACTIVE) {
904safe_set_env(envgBIOSBootVolume, (uint32_t)newFDiskBVRef(
905 biosdev, partno,
906 part->relsect,
907 part,
908 HFSInitPartition,
909 HFSLoadFile,
910 HFSReadFile,
911 HFSGetDirEntry,
912 HFSGetFileBlock,
913 HFSGetUUID,
914 HFSGetDescription,
915 HFSFree,
916 0,
917 kBIOSDevTypeHardDrive, 0));
918 break;
919 }
920#ifndef UFS_SUPPORT
921 break;
922#else
923
924 //case FDISK_BOOTER:
925 booterUFS = newFDiskBVRef(
926 biosdev, partno,
927 ((part->relsect + spc - 1) / spc) * spc,
928 part,
929 UFSInitPartition,
930 UFSLoadFile,
931 UFSReadFile,
932 UFSGetDirEntry,
933 UFSGetFileBlock,
934 UFSGetUUID,
935 UFSGetDescription,
936 UFSFree,
937 0,
938 kBIOSDevTypeHardDrive, 0);
939 break;
940#endif
941#ifndef NO_WIN_SUPPORT
942 case FDISK_FAT32:
943 case FDISK_DOS12:
944 case FDISK_DOS16S:
945 case FDISK_DOS16B:
946 case FDISK_SMALLFAT32:
947 case FDISK_DOS16SLBA:
948 bvr = newFDiskBVRef(
949 biosdev, partno,
950 part->relsect,
951 part,
952 MSDOSInitPartition,
953 MSDOSLoadFile,
954 MSDOSReadFile,
955 MSDOSGetDirEntry,
956 MSDOSGetFileBlock,
957 MSDOSGetUUID,
958 MSDOSGetDescription,
959 MSDOSFree,
960 0,
961 kBIOSDevTypeHardDrive, 0);
962 break;
963 case FDISK_NTFS:
964 bvr = newFDiskBVRef(
965 biosdev, partno,
966 part->relsect,
967 part,
968 0, 0, 0, 0, 0,
969 NTFSGetUUID,
970 NTFSGetDescription,
971 (BVFree)free,
972 0, kBIOSDevTypeHardDrive, 0);
973 break;
974#endif
975
976#ifndef NO_LINUX_SUPPORT
977
978 case FDISK_LINUX:
979 bvr = newFDiskBVRef(
980 biosdev, partno,
981 part->relsect,
982 part,
983 0, 0, 0, 0, 0, 0,
984 EX2GetDescription,
985 (BVFree)free,
986 0, kBIOSDevTypeHardDrive, 0);
987 break;
988#endif
989#ifndef NO_HAIKU_SUPPORT
990 case FDISK_BEFS:
991 bvr = newFDiskBVRef(
992 biosdev, partno,
993 part->relsect,
994 part,
995 0, 0, 0, 0, 0, 0,
996 BeFSGetDescription,
997 (BVFree)free,
998 0, kBIOSDevTypeHardDrive, 0);
999 break;
1000#endif
1001#ifndef NO_OTHERS_BSD_SUPPORT
1002 case FDISK_FREEBSD:
1003 bvr = newFDiskBVRef(
1004 biosdev, partno,
1005 part->relsect,
1006 part,
1007 0, 0, 0, 0, 0, 0,
1008 FreeBSDGetDescription,
1009 (BVFree)free,
1010 0, kBIOSDevTypeHardDrive, 0);
1011 break;
1012
1013 case FDISK_OPENBSD:
1014 bvr = newFDiskBVRef(
1015 biosdev, partno,
1016 part->relsect,
1017 part,
1018 0, 0, 0, 0, 0, 0,
1019 OpenBSDGetDescription,
1020 (BVFree)free,
1021 0, kBIOSDevTypeHardDrive, 0);
1022 break;
1023#endif
1024 default:
1025#if UNUSED
1026 bvr = newFDiskBVRef(
1027 biosdev, partno,
1028 part->relsect,
1029 part,
1030 0, 0, 0, 0, 0, 0, 0,
1031 (BVFree)free,
1032 0,
1033 kBIOSDevTypeHardDrive, 0);
1034#endif
1035 break;
1036 }
1037
1038 if ( bvr )
1039 {
1040 bvr->next = map->bvr;
1041 map->bvr = bvr;
1042 map->bvrcnt++;
1043 }
1044 }
1045
1046#ifdef UFS_SUPPORT
1047 // Booting from a CD with an UFS filesystem embedded
1048 // in a booter partition.
1049
1050 if ( booterUFS )
1051 {
1052 if ( map->bvrcnt == 0 )
1053 {
1054 map->bvr = booterUFS;
1055 map->bvrcnt++;
1056 }
1057 else free( booterUFS );
1058 }
1059#endif
1060 } while (0);
1061
1062 /*
1063 * If no FDisk partition, then we will check for
1064 * an Apple partition map elsewhere.
1065 */
1066#if UNUSED
1067 if (map->bvrcnt == 0) {
1068static struct fdisk_part cdpart;
1069cdpart.systid = 0xCD;
1070
1071/* Let's try assuming we are on a hybrid HFS/ISO9660 CD. */
1072bvr = newFDiskBVRef(
1073 biosdev, 0,
1074 0,
1075 &cdpart,
1076 HFSInitPartition,
1077 HFSLoadFile,
1078 HFSReadFile,
1079 HFSGetDirEntry,
1080 HFSGetFileBlock,
1081 HFSGetUUID,
1082 HFSGetDescription,
1083 HFSFree,
1084 0,
1085 kBIOSDevTypeHardDrive, 0);
1086bvr->next = map->bvr;
1087map->bvr = bvr;
1088map->bvrcnt++;
1089 }
1090#endif
1091 // Actually this should always be true given the above code
1092 if(map == gDiskBVMap)
1093 {
1094 // Don't leave a null map in the chain
1095 if(map->bvrcnt == 0 && map->bvr == NULL)
1096 {
1097 gDiskBVMap = map->next;
1098 free(map);
1099 map = NULL;
1100 }
1101 }
1102
1103 if (countPtr) *countPtr = map ? map->bvrcnt : 0;
1104
1105 return map ? map->bvr : NULL;
1106}
1107#ifdef APPLE_PARTITION_MAP_SUPPORT
1108//==========================================================================
1109
1110static BVRef diskScanAPMBootVolumes( int biosdev, int * countPtr )
1111{
1112 struct DiskBVMap * map;
1113 struct Block0 *block0_p;
1114 unsigned int blksize;
1115 unsigned int factor;
1116 void *buffer = malloc(BPS);
1117if (!buffer) {
1118 return NULL;
1119 }
1120bzero(buffer,BPS);
1121 /* Check for alternate block size */
1122 if (readBytes( biosdev, 0, 0, BPS, buffer ) != 0) {
1123 return NULL;
1124 }
1125 block0_p = buffer;
1126 if (OSSwapBigToHostInt16(block0_p->sbSig) == BLOCK0_SIGNATURE) {
1127 blksize = OSSwapBigToHostInt16(block0_p->sbBlkSize);
1128 if (blksize != BPS) {
1129 free(buffer);
1130 buffer = malloc(blksize);
1131 if (!buffer) {
1132 return NULL;
1133 }
1134bzero(buffer,BPS);
1135 }
1136 factor = blksize / BPS;
1137 } else {
1138 blksize = BPS;
1139 factor = 1;
1140 }
1141
1142 // Create a new mapping.
1143
1144 map = (struct DiskBVMap *) malloc( sizeof(struct DiskBVMap) );
1145 if ( !map )
1146 {
1147 return NULL;
1148 }
1149bzero(map,sizeof(struct DiskBVMap));
1150
1151 do {
1152
1153 int error;
1154 DPME *dpme_p = (DPME *)buffer;
1155 UInt32 i, npart = UINT_MAX;
1156 BVRef bvr;
1157
1158 map->biosdev = biosdev;
1159 map->bvr = NULL;
1160 map->bvrcnt = 0;
1161 map->next = gDiskBVMap;
1162 gDiskBVMap = map;
1163
1164 for (i=0; i<npart; i++) {
1165 error = readBytes( biosdev, (kAPMSector + i) * factor, 0, blksize, buffer );
1166
1167 if (error || OSSwapBigToHostInt16(dpme_p->dpme_signature) != DPME_SIGNATURE) {
1168 break;
1169 }
1170
1171 if (i==0) {
1172 npart = OSSwapBigToHostInt32(dpme_p->dpme_map_entries);
1173 }
1174 /*
1175 printf("name = %s, %s%s %d -> %d [%d -> %d] {%d}\n",
1176 dpme.dpme_name, dpme.dpme_type, (dpme.dpme_flags & DPME_FLAGS_BOOTABLE) ? "(bootable)" : "",
1177 dpme.dpme_pblock_start, dpme.dpme_pblocks,
1178 dpme.dpme_lblock_start, dpme.dpme_lblocks,
1179 dpme.dpme_boot_block);
1180 */
1181
1182 if (strncmp(dpme_p->dpme_type, "Apple_HFS",sizeof("Apple_HFS")) == 0) {
1183 bvr = newAPMBVRef(biosdev,
1184 i,
1185 OSSwapBigToHostInt32(dpme_p->dpme_pblock_start) * factor,
1186 dpme_p,
1187 HFSInitPartition,
1188 HFSLoadFile,
1189 HFSReadFile,
1190 HFSGetDirEntry,
1191 HFSGetFileBlock,
1192 HFSGetUUID,
1193 HFSGetDescription,
1194 HFSFree,
1195 0,
1196 kBIOSDevTypeHardDrive, 0);
1197 bvr->next = map->bvr;
1198 map->bvr = bvr;
1199 map->bvrcnt++;
1200 }
1201 }
1202 } while (0);
1203
1204 free(buffer);
1205
1206 if (countPtr) *countPtr = map ? map->bvrcnt : 0;
1207
1208 return map ? map->bvr : NULL;
1209}
1210
1211//==========================================================================
1212#endif
1213// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1214
1215/*
1216 * Trying to figure out the filsystem type of a given partition.
1217 */
1218static int probeFileSystem(int biosdev, unsigned int blkoff)
1219{
1220// detected filesystem type;
1221int result = -1;
1222#ifndef NO_WIN_SUPPORT
1223int fatbits;
1224#endif
1225
1226// Allocating buffer for 4 sectors.
1227const void * probeBuffer = calloc(1,PROBEFS_SIZE);
1228if (probeBuffer == NULL)
1229goto exit;
1230
1231// Reading first 4 sectors of current partition
1232int error = readBytes(biosdev, blkoff, 0, PROBEFS_SIZE, (void *)probeBuffer);
1233if (error)
1234goto exit;
1235
1236if (HFSProbe(probeBuffer))
1237result = FDISK_HFS;
1238#ifndef NO_LINUX_SUPPORT
1239else if (EX2Probe(probeBuffer))
1240result = FDISK_LINUX;
1241#endif
1242#ifndef NO_OTHERS_BSD_SUPPORT
1243else if (FreeBSDProbe(probeBuffer))
1244result = FDISK_FREEBSD;
1245else if (OpenBSDProbe(probeBuffer))
1246result = FDISK_OPENBSD;
1247#endif
1248#ifndef NO_HAIKU_SUPPORT
1249else if (BeFSProbe(probeBuffer))
1250result = FDISK_BEFS;
1251#endif
1252#ifndef NO_WIN_SUPPORT
1253else if (NTFSProbe(probeBuffer))
1254result = FDISK_NTFS;
1255else if ((fatbits=MSDOSProbe(probeBuffer)))
1256{
1257switch (fatbits)
1258{
1259case 32:
1260default:
1261result = FDISK_FAT32;
1262break;
1263case 16:
1264result = FDISK_DOS16B;
1265break;
1266case 12:
1267result = FDISK_DOS12;
1268break;
1269}
1270}
1271#endif
1272else
1273// Couldn't detect filesystem type
1274result = 0;
1275
1276exit:
1277if (probeBuffer != NULL) free((void *)probeBuffer);
1278return result;
1279}
1280
1281static bool isPartitionUsed(gpt_ent * partition)
1282{
1283 //
1284 // Ask whether the given partition is used.
1285 //
1286
1287 return efi_guid_is_null((EFI_GUID const*)partition->ent_type) ? false : true;
1288}
1289
1290// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1291
1292static BVRef diskScanGPTBootVolumes( int biosdev, int * countPtr )
1293{
1294if (biosdev >= 0x100 && (execute_hook("isRamDiskRegistred", NULL, NULL, NULL, NULL, NULL, NULL) != EFI_SUCCESS))
1295return NULL;
1296
1297 struct DiskBVMap * map = NULL;
1298 void *buffer = malloc(BPS);
1299 if (!buffer) {
1300 goto scanErr;
1301 }
1302bzero(buffer,BPS);
1303 int error;
1304 if ( (error = readBytes( biosdev, /*secno*/0, 0, BPS, buffer )) != 0) {
1305 DBG("Failed to read boot sector from BIOS device %02xh. Error=%d\n", biosdev, error);
1306 goto scanErr;
1307 }
1308 struct REAL_disk_blk0 *fdiskMap = buffer;
1309 if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE )
1310 {
1311 verbose("Failed to find boot signature on BIOS device %02xh\n", biosdev);
1312 goto scanErr;
1313 }
1314
1315 int fdiskID = 0;
1316 unsigned index;
1317 for ( index = 0; index < FDISK_NPART; index++ )
1318 {
1319 if ( fdiskMap->parts[index].systid )
1320 {
1321 if ( fdiskMap->parts[index].systid == 0xEE )
1322 {
1323 // Fail if two 0xEE partitions are present which
1324 // means the FDISK code will wind up parsing it.
1325 if ( fdiskID ) goto scanErr;
1326
1327 fdiskID = index + 1;
1328 }
1329 }
1330 }
1331
1332 if ( fdiskID == 0 ) goto scanErr;
1333 DBG("Attempting to read GPT\n");
1334
1335 if(readBytes(biosdev, 1, 0, BPS, buffer) != 0)
1336 goto scanErr;
1337
1338 gpt_hdr *headerMap = buffer;
1339
1340 // Determine whether the partition header signature is present.
1341
1342 if ( memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) )
1343 {
1344 goto scanErr;
1345 }
1346
1347 // Determine whether the partition header size is valid.
1348
1349 UInt32 headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self);
1350 UInt32 headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size);
1351
1352 if ( headerSize < offsetof(gpt_hdr, padding) )
1353 {
1354 goto scanErr;
1355 }
1356
1357 if ( headerSize > BPS )
1358 {
1359 goto scanErr;
1360 }
1361
1362 // Determine whether the partition header checksum is valid.
1363
1364 headerMap->hdr_crc_self = 0;
1365
1366 if ( crc32(0, headerMap, headerSize) != headerCheck )
1367 {
1368 goto scanErr;
1369 }
1370
1371 // Determine whether the partition entry size is valid.
1372
1373 UInt64 gptBlock = 0;
1374 //UInt32 gptCheck = 0;
1375 UInt32 gptCount = 0;
1376 UInt32 gptID = 0;
1377 gpt_ent * gptMap = 0;
1378 UInt32 gptSize = 0;
1379
1380 gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table);
1381 //gptCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_table);
1382 gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries);
1383 gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz);
1384
1385 if ( gptSize < sizeof(gpt_ent) )
1386 {
1387 goto scanErr;
1388 }
1389
1390 // Allocate a buffer large enough to hold one map, rounded to a media block.
1391 free(buffer);
1392 buffer = NULL;
1393
1394 UInt32 bufferSize = IORound(gptCount * gptSize, BPS);
1395 if(bufferSize == 0)
1396 goto scanErr;
1397 buffer = malloc(bufferSize);
1398if (!buffer) {
1399 goto scanErr;
1400 }
1401bzero(buffer,bufferSize);
1402
1403 if(readBytes(biosdev, gptBlock, 0, bufferSize, buffer) != 0)
1404 goto scanErr;
1405
1406 DBG("Read GPT\n");
1407
1408 // Allocate a new map for this BIOS device and insert it into the chain
1409 map = (struct DiskBVMap *) malloc(sizeof(struct DiskBVMap));
1410 if (!map) {
1411 goto scanErr;
1412 }
1413bzero(map,sizeof(struct DiskBVMap));
1414
1415 map->biosdev = biosdev;
1416 map->bvr = NULL;
1417 map->bvrcnt = 0;
1418 map->next = gDiskBVMap;
1419 gDiskBVMap = map;
1420
1421 // fdisk like partition type id.
1422 int fsType = 0;
1423
1424 for(gptID = 1; gptID <= gptCount; ++gptID)
1425 {
1426BVRef bvr = NULL;
1427unsigned int bvrFlags = 0;
1428
1429 // size on disk can be larger than sizeof(gpt_ent)
1430 gptMap = (gpt_ent *) ( buffer + ( (gptID - 1) * gptSize) );
1431
1432 // NOTE: EFI_GUID's are in LE and we know we're on an x86.
1433 // The IOGUIDPartitionScheme.cpp code uses byte-based UUIDs, we don't.
1434
1435 if(isPartitionUsed(gptMap))
1436 {
1437 char stringuuid[100];
1438 efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid, sizeof(stringuuid));
1439 verbose("Reading GPT partition %d, type %s\n", gptID, stringuuid);
1440
1441 // Getting fdisk like partition type.
1442 fsType = probeFileSystem(biosdev, gptMap->ent_lba_start);
1443
1444 if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ||
1445(efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )
1446 {
1447#ifdef BOOT_HELPER_SUPPORT
1448 bvrFlags = (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ? kBVFlagBooter : 0;
1449#else
1450if (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0)
1451continue;
1452else
1453bvrFlags = 0;
1454
1455#endif
1456 bvr = newGPTBVRef(biosdev,
1457 gptID,
1458 gptMap->ent_lba_start,
1459 gptMap,
1460 HFSInitPartition,
1461 HFSLoadFile,
1462 HFSReadFile,
1463 HFSGetDirEntry,
1464 HFSGetFileBlock,
1465 HFSGetUUID,
1466 HFSGetDescription,
1467 HFSFree,
1468 0,
1469 kBIOSDevTypeHardDrive, bvrFlags);
1470 }
1471
1472// zef - foreign OS support
1473 if ( (efi_guid_compare(&GPT_BASICDATA_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ||
1474(efi_guid_compare(&GPT_BASICDATA2_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )
1475 {
1476
1477switch (fsType)
1478{
1479#ifndef NO_WIN_SUPPORT
1480
1481case FDISK_NTFS:
1482bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,
1483 0, 0, 0, 0, 0, 0, NTFSGetDescription,
1484 (BVFree)free, 0, kBIOSDevTypeHardDrive, 0);
1485break;
1486#endif
1487default:
1488bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,
1489 0, 0, 0, 0, 0, 0, 0,
1490 (BVFree)free, 0, kBIOSDevTypeHardDrive, 0);
1491break;
1492}
1493
1494 }
1495
1496 // turbo - save our booter partition
1497 // zef - only on original boot device
1498 if ( (efi_guid_compare(&GPT_EFISYS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )
1499 {
1500switch (fsType)
1501{
1502case FDISK_HFS:
1503if (readBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0)
1504{
1505bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,
1506 HFSInitPartition,
1507 HFSLoadFile,
1508 HFSReadFile,
1509 HFSGetDirEntry,
1510 HFSGetFileBlock,
1511 HFSGetUUID,
1512 HFSGetDescription,
1513 HFSFree,
1514 0, kBIOSDevTypeHardDrive, kBVFlagEFISystem);
1515}
1516break;
1517#ifndef NO_WIN_SUPPORT
1518case FDISK_FAT32:
1519if (testFAT32EFIBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0)
1520{
1521bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap,
1522 MSDOSInitPartition,
1523 MSDOSLoadFile,
1524 MSDOSReadFile,
1525 MSDOSGetDirEntry,
1526 MSDOSGetFileBlock,
1527 MSDOSGetUUID,
1528 MSDOSGetDescription,
1529 MSDOSFree,
1530 0, kBIOSDevTypeHardDrive, kBVFlagEFISystem);
1531}
1532break;
1533#endif
1534default:
1535if (biosdev == (int)get_env(envgBIOSDev))
1536safe_set_env(envgBIOSBootVolume, (uint32_t)bvr);
1537break;
1538}
1539 }
1540
1541if (bvr)
1542{
1543// Fixup bvr with the fake fdisk partition type.
1544if (fsType > 0) bvr->part_type = fsType;
1545
1546bvr->next = map->bvr;
1547map->bvr = bvr;
1548++map->bvrcnt;
1549}
1550
1551 }
1552 }
1553
1554scanErr:
1555 if (buffer) free(buffer);
1556
1557 if(map)
1558 {
1559 if(countPtr) *countPtr = map->bvrcnt;
1560 return map->bvr;
1561 }
1562 else
1563 {
1564 if(countPtr) *countPtr = 0;
1565 return NULL;
1566 }
1567}
1568
1569static TagPtr XMLGetElementWithID( TagPtr dict, const char* id )
1570{
1571if(dict->type != kTagTypeArray) return 0;
1572
1573int element = 0;
1574TagPtr tmp = dict->tag;
1575int entry_count = XMLTagCount(dict);
1576
1577while(element < entry_count)
1578{
1579char *Identifier = NULL;
1580Identifier = XMLCastString(XMLGetProperty(tmp, (const char*)"Identifier"));
1581
1582if (Identifier && (strcmp(Identifier, id) == 0))
1583{
1584return tmp;
1585}
1586
1587element++;
1588tmp = tmp->tagNext;
1589}
1590
1591return tmp;
1592}
1593
1594static bool getOSInstallVersion(const char *dirSpec, char *str, config_file_t *systemVersion)
1595{
1596 if (!loadConfigFile(dirSpec, systemVersion))
1597 {
1598 TagPtr pkg_p = XMLCastArray(XMLGetProperty(systemVersion->dictionary, (const char*)"Packages"));
1599
1600 if (pkg_p)
1601 {
1602
1603 char *version = NULL;
1604
1605 version = XMLCastString(XMLGetProperty(
1606 XMLGetElementWithID(pkg_p,
1607 "com.apple.mpkg.OSInstall"),
1608 (const char*)"Version"));
1609
1610if (!version)
1611{
1612version = XMLCastString(XMLGetProperty(
1613 XMLGetElementWithID(pkg_p,
1614 "com.apple.pkg.CompatibilityUpdate"),
1615 (const char*)"Version"));
1616}
1617
1618 if (version && strlen(version) >= 4)
1619 {
1620 *str = '\0';
1621 strncat(str, version, 4);
1622 return true;
1623
1624 }
1625 }
1626 }
1627
1628 return false;
1629}
1630
1631static bool getOSInstallURL(BVRef bvr, const char *dirSpec, config_file_t *config_file)
1632{
1633 if (!loadConfigFile(dirSpec, config_file))
1634 {
1635 char *encoded_url = XMLCastString(XMLGetProperty(config_file->dictionary, (const char*)"Product URL"));
1636
1637if (!encoded_url) {
1638goto out;
1639}
1640
1641DBG("encoded_url %s\n",encoded_url);
1642
1643//char * dev_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // strlen = 36
1644
1645//char * osx_product = "x-osproduct://";// strlen = 14
1646
1647char * val = &encoded_url[(36+14)+1];
1648
1649DBG("val %s\n",val);
1650
1651char * buffer = newStringFromURL(val);
1652
1653if (!buffer)
1654{
1655goto out;
1656}
1657
1658DBG("buffer %s\n",buffer);
1659
1660strlcpy(bvr->OSInstall, buffer, sizeof(bvr->OSInstall));
1661
1662free(buffer);
1663
1664return true;
1665 }
1666out:
1667 return false;
1668}
1669
1670static bool getOSVersion(BVRef bvr, char *str)
1671{
1672bool valid = false;
1673config_file_t config_file;
1674char dirSpec[512];
1675
1676snprintf(dirSpec, sizeof(dirSpec),"hd(%d,%d)/System/Library/CoreServices/SystemVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);
1677
1678if (!loadConfigFile(dirSpec, &config_file))
1679{
1680valid = true;
1681}
1682else
1683{
1684snprintf(dirSpec, sizeof(dirSpec),"hd(%d,%d)/System/Library/CoreServices/ServerVersion.plist", BIOS_DEV_UNIT(bvr), bvr->part_no);
1685
1686if (!loadConfigFile(dirSpec, &config_file))
1687{
1688 bvr->OSisServer = true;
1689valid = true;
1690}
1691else
1692{
1693snprintf(dirSpec, sizeof(dirSpec),"hd(%d,%d)/.IAProductInfo", BIOS_DEV_UNIT(bvr), bvr->part_no);
1694DBG("dirSpec %s\n",dirSpec);
1695
1696if (!loadConfigFile(dirSpec, &config_file))
1697{
1698if (getOSInstallURL(bvr, dirSpec, &config_file))
1699{
1700snprintf(dirSpec, sizeof(dirSpec),"hd(%d,%d)/%s/index.sproduct", BIOS_DEV_UNIT(bvr), bvr->part_no, bvr->OSInstall);
1701
1702DBG("dirSpec %s\n",dirSpec);
1703
1704if (!getOSInstallVersion(dirSpec, str, &config_file))
1705return false;
1706else
1707return true;
1708}
1709}
1710}
1711}
1712
1713if (valid)
1714{
1715const char *val;
1716int len;
1717
1718if (getValueForKey(kProductVersion, &val, &len, &config_file))
1719{
1720// getValueForKey uses const char for val
1721// so copy it and trim
1722*str = '\0';
1723strncat(str, val, MIN(len, 4));
1724}
1725else
1726valid = false;
1727}
1728
1729return valid;
1730}
1731
1732static bool CheckDarwin(BVRef bvr)
1733{
1734 long flags, time, ret = -1;
1735
1736 char dirspec[128];
1737
1738 char *kdirspec[] = {
1739"hd(%d,%d)/mach_kernel",
1740#if UNUSED
1741"hd(%d,%d)/System/Library/CoreServices/mach_kernel"
1742#endif
1743};
1744
1745 bvr->kernelfound = true;
1746
1747 snprintf(dirspec,sizeof(dirspec),kdirspec[0],BIOS_DEV_UNIT(bvr), bvr->part_no);
1748
1749 ret = GetFileInfo(NULL, dirspec, &flags, &time);
1750
1751 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
1752#if UNUSED
1753
1754 snprintf(dirspec,sizeof(dirspec),kdirspec[1],BIOS_DEV_UNIT(bvr), bvr->part_no);
1755
1756 ret = GetFileInfo(NULL, dirspec, &flags, &time);
1757
1758 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
1759#endif
1760 {
1761 bvr->kernelfound = false; // Non fatal, let the booter determine the directory
1762 }
1763
1764 }
1765
1766 if (bvr->kernelfound == true) {
1767 DBG("Kernel found !!, path : %s\n",dirspec);
1768 }
1769
1770
1771 return getOSVersion(bvr,bvr->OSVersion);
1772}
1773
1774//==========================================================================
1775
1776static void scanFSLevelBVRSettings(BVRef chain)
1777{
1778BVRef bvr;
1779#ifdef BOOT_HELPER_SUPPORT
1780 int ret;
1781char label[BVSTRLEN];
1782char dirSpec[256];
1783int fh, fileSize, error;
1784#endif
1785for (bvr = chain; bvr < (BVRef)ULONG_MAX; bvr = bvr->next) {
1786 if (!bvr) {
1787 break;
1788 }
1789#ifdef BOOT_HELPER_SUPPORT
1790error = 0;
1791
1792//
1793// Check for alternate volume label on boot helper partitions.
1794//
1795if (bvr->flags & kBVFlagBooter)
1796{
1797snprintf(dirSpec, sizeof(dirsSpec),"hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no);
1798strlcpy(fileSpec, ".disk_label.contentDetails", sizeof(fileSpec));
1799ret = GetFileInfo(dirSpec, fileSpec, &flags, &time);
1800if (!ret)
1801{
1802strlcat(dirSpec, fileSpec, sizeof(dirSpec));
1803
1804fh = open(dirSpec,0);
1805fileSize = file_size(fh);
1806if (fileSize > 0 && fileSize < BVSTRLEN)
1807{
1808if (read(fh, label, fileSize) != fileSize)
1809error = -1;
1810}
1811else
1812error = -1;
1813
1814close(fh);
1815
1816if (!error)
1817{
1818label[fileSize] = '\0';
1819strlcpy(bvr->altlabel, label, sizeof(bvr->altlabel));
1820}
1821}
1822}
1823#endif
1824//
1825// Check for SystemVersion.plist or ServerVersion.plist
1826// to determine if a volume hosts an installed system.
1827//
1828if (bvr->flags & kBVFlagNativeBoot)
1829{
1830if (CheckDarwin(bvr) == true)
1831{
1832bvr->flags |= kBVFlagSystemVolume;
1833}
1834}
1835
1836}
1837}
1838#ifndef OPTION_ROM
1839void rescanBIOSDevice(int biosdev)
1840{
1841struct DiskBVMap *oldMap = diskResetBootVolumes(biosdev);
1842 if (oldMap == NULL)
1843 {
1844 return;
1845 }
1846CacheReset();
1847diskFreeMap(oldMap);
1848oldMap = NULL;
1849scanBootVolumes(biosdev, 0);
1850}
1851#endif
1852
1853struct DiskBVMap* diskResetBootVolumes(int biosdev)
1854{
1855 struct DiskBVMap * map;
1856 struct DiskBVMap *prevMap = NULL;
1857 for ( map = gDiskBVMap; map; prevMap = map, map = map->next ) {
1858 if ( biosdev == map->biosdev ) {
1859 break;
1860 }
1861 }
1862 if(map != NULL)
1863 {
1864 verbose("Resetting BIOS device %xh\n", biosdev);
1865 // Reset the biosbuf cache
1866 cache_valid = false;
1867 if(map == gDiskBVMap)
1868 gDiskBVMap = map->next;
1869 else if(prevMap != NULL)
1870 prevMap->next = map->next;
1871 else
1872 {
1873 stop("diskResetBootVolumes error\n");
1874 return NULL;
1875 }
1876 }
1877 // Return the old map, either to be freed, or reinserted later
1878 return map;
1879}
1880
1881// Frees a DiskBVMap and all of its BootVolume's
1882void diskFreeMap(struct DiskBVMap *map)
1883{
1884 if(map != NULL)
1885 {
1886 while(map->bvr != NULL)
1887 {
1888 BVRef bvr = map->bvr;
1889 map->bvr = bvr->next;
1890 (*bvr->bv_free)(bvr);
1891 }
1892 free(map);
1893 }
1894}
1895
1896BVRef diskScanBootVolumes( int biosdev, int * countPtr )
1897{
1898 struct DiskBVMap * map;
1899 BVRef bvr;
1900 int count = 0;
1901
1902 // Find an existing mapping for this device.
1903
1904 for ( map = gDiskBVMap; map; map = map->next ) {
1905 if ( biosdev == map->biosdev ) {
1906 count = map->bvrcnt;
1907 break;
1908 }
1909 }
1910
1911 if (map == NULL) {
1912 bvr = diskScanGPTBootVolumes(biosdev, &count);
1913 if (bvr == NULL) {
1914bvr = diskScanFDiskBootVolumes(biosdev, &count);
1915 }
1916#ifdef APPLE_PARTITION_MAP_SUPPORT
1917 if (bvr == NULL) {
1918bvr = diskScanAPMBootVolumes(biosdev, &count);
1919 }
1920#endif
1921 if (bvr)
1922 {
1923scanFSLevelBVRSettings(bvr);
1924 }
1925 } else {
1926 bvr = map->bvr;
1927 }
1928 if (countPtr) *countPtr += count;
1929 return bvr;
1930}
1931
1932BVRef getBVChainForBIOSDev(int biosdev)
1933{
1934BVRef chain = NULL;
1935struct DiskBVMap * map = NULL;
1936
1937for (map = gDiskBVMap; map; map = map->next)
1938{
1939if (map->biosdev == biosdev)
1940{
1941chain = map->bvr;
1942break;
1943}
1944}
1945
1946return chain;
1947}
1948
1949BVRef newFilteredBVChain(int minBIOSDev, int maxBIOSDev, unsigned int allowFlags, unsigned int denyFlags, int *count)
1950{
1951BVRef chain = NULL;
1952BVRef bvr = NULL;
1953BVRef newBVR = NULL;
1954BVRef prevBVR = NULL;
1955
1956struct DiskBVMap * map = NULL;
1957int bvCount = 0;
1958
1959const char *raw = 0;
1960char* val = 0;
1961int len;
1962
1963getValueForKey(kHidePartition, &raw, &len, DEFAULT_BOOT_CONFIG);
1964if(raw)
1965{
1966val = XMLDecode(raw);
1967}
1968
1969/*
1970 * Traverse gDISKBVmap to get references for
1971 * individual bvr chains of each drive.
1972 */
1973for (map = gDiskBVMap; map; map = map->next)
1974{
1975for (bvr = map->bvr; bvr; bvr = bvr->next)
1976{
1977/*
1978 * Save the last bvr.
1979 */
1980if (newBVR) prevBVR = newBVR;
1981
1982/*
1983 * Allocate and copy the matched bvr entry into a new one.
1984 */
1985newBVR = (BVRef) malloc(sizeof(struct BootVolume));
1986 if (!newBVR) {
1987 continue;
1988 }
1989bzero(newBVR,sizeof(struct BootVolume));
1990
1991bcopy(bvr, newBVR, sizeof(struct BootVolume));
1992
1993/*
1994 * Adjust the new bvr's fields.
1995 */
1996newBVR->next = NULL;
1997newBVR->filtered = true;
1998
1999if ( (!allowFlags || newBVR->flags & allowFlags)
2000&& (!denyFlags || !(newBVR->flags & denyFlags) )
2001&& (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev)
2002)
2003newBVR->visible = true;
2004
2005/* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format
2006 * to be able to hide foreign partitions from the boot menu.
2007 */
2008if ( (newBVR->flags & kBVFlagForeignBoot) )
2009{
2010char *start, *next = val;
2011long len = 0;
2012do
2013{
2014start = strbreak(next, &next, &len);
2015if(len && matchVolumeToString(newBVR, start, len) )
2016newBVR->visible = false;
2017}
2018while ( next && *next );
2019}
2020
2021/*
2022 * Use the first bvr entry as the starting chain pointer.
2023 */
2024if (!chain)
2025chain = newBVR;
2026
2027/*
2028 * Update the previous bvr's link pointer to use the new memory area.
2029 */
2030if (prevBVR)
2031prevBVR->next = newBVR;
2032
2033if (newBVR->visible)
2034bvCount++;
2035}
2036}
2037
2038#if DEBUG
2039for (bvr = chain; bvr < (BVRef)ULONG_MAX; bvr = bvr->next) {
2040 if (!bvr) {
2041 break;
2042 }
2043printf(" bvr: %p, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible);
2044}
2045printf("count: %d\n", bvCount);
2046getc();
2047#endif
2048
2049*count = bvCount;
2050
2051free(val);
2052return chain;
2053}
2054
2055int freeFilteredBVChain(const BVRef chain)
2056{
2057int ret = 1;
2058BVRef bvr = chain;
2059BVRef nextBVR = NULL;
2060
2061while (bvr < (BVRef)ULONG_MAX)
2062{
2063 if (!bvr) {
2064 break;
2065 }
2066nextBVR = bvr->next;
2067
2068if (bvr->filtered)
2069{
2070free(bvr);
2071}
2072else
2073{
2074ret = 0;
2075break;
2076}
2077
2078bvr = nextBVR;
2079}
2080
2081return ret;
2082}
2083
2084//==========================================================================
2085
2086static const struct NamedValue fdiskTypes[] =
2087{
2088#ifndef NO_WIN_SUPPORT
2089 { FDISK_NTFS, "Windows NTFS" },
2090{ FDISK_DOS12, "Windows FAT12" },
2091{ FDISK_DOS16B, "Windows FAT16" },
2092{ FDISK_DOS16S, "Windows FAT16" },
2093{ FDISK_DOS16SLBA, "Windows FAT16" },
2094{ FDISK_SMALLFAT32, "Windows FAT32" },
2095{ FDISK_FAT32, "Windows FAT32" },
2096#endif
2097#ifndef NO_OTHERS_BSD_SUPPORT
2098{ FDISK_FREEBSD, "FreeBSD" },
2099 { FDISK_OPENBSD, "OpenBSD" },
2100#endif
2101#ifndef NO_LINUX_SUPPORT
2102 { FDISK_LINUX, "Linux" },
2103#endif
2104#ifdef UFS_SUPPORT
2105 { FDISK_UFS, "Apple UFS" },
2106#endif
2107 { FDISK_HFS, "Apple HFS" },
2108 { FDISK_BOOTER, "Apple Boot/UFS" },
2109#ifndef NO_HAIKU_SUPPORT
2110{ FDISK_BEFS, "Haiku" },
2111#endif
2112 { 0xCD, "CD-ROM" },
2113 { 0x00, 0 } /* must be last */
2114};
2115
2116//==========================================================================
2117
2118bool matchVolumeToString( BVRef bvr, const char* match, long matchLen)
2119{
2120char testStr[128];
2121
2122if ( !bvr || !match || !*match)
2123return 0;
2124
2125if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 )
2126 return 0;
2127
2128 // Try to match hd(x,y) first.
2129 snprintf(testStr, sizeof(testStr),"hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no);
2130 if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2131 return true;
2132
2133 // Try to match volume UUID.
2134 if ( bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr, sizeof(testStr)) == 0)
2135 {
2136 if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2137 return true;
2138 }
2139
2140 // Try to match volume label (always quoted).
2141 if ( bvr->description )
2142 {
2143 bvr->description(bvr, testStr, sizeof(testStr)-1);
2144 if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2145 return true;
2146 }
2147
2148 return false;
2149}
2150
2151/* If Rename Partition has defined an alias, then extract it for description purpose
2152 * The format for the rename string is the following:
2153 * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ...
2154 */
2155
2156static bool getVolumeLabelAlias(BVRef bvr, char* str, long strMaxLen)
2157{
2158 char *aliasList, *entryStart, *entryNext;
2159
2160 if ( !str || strMaxLen <= 0)
2161 return false;
2162
2163 aliasList = XMLDecode(getStringForKey(kRenamePartition, DEFAULT_BOOT_CONFIG));
2164 if ( !aliasList )
2165 return false;
2166
2167 for ( entryStart = entryNext = aliasList;
2168 entryNext && *entryNext;
2169 entryStart = entryNext )
2170 {
2171 char *volStart, *volEnd, *aliasStart;
2172 long volLen, aliasLen;
2173
2174 // Delimit current entry
2175 entryNext = strchr(entryStart, ';');
2176 if ( entryNext )
2177 {
2178 *entryNext = '\0';
2179 entryNext++;
2180 }
2181
2182 volStart = strbreak(entryStart, &volEnd, &volLen);
2183 if(!volLen)
2184 continue;
2185
2186 aliasStart = strbreak(volEnd, 0, &aliasLen);
2187 if(!aliasLen)
2188 continue;
2189
2190 if ( matchVolumeToString(bvr, volStart, volLen) )
2191 {
2192 strncat(str, aliasStart, min(strMaxLen, aliasLen));
2193 free(aliasList);
2194
2195 return true;
2196 }
2197 }
2198
2199 free(aliasList);
2200 return false;
2201}
2202
2203void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription )
2204{
2205 unsigned char type;
2206 char *p = str;
2207
2208 if(!bvr || !p || strMaxLen <= 0)
2209 return;
2210
2211 type = (unsigned char) bvr->part_type;
2212
2213 if (useDeviceDescription)
2214 {
2215 int len = getDeviceDescription(bvr, str, strMaxLen);
2216 if(len >= strMaxLen)
2217 return;
2218
2219 strlcpy(str + len, " ", strMaxLen);
2220 len++;
2221 strMaxLen -= len;
2222 p += len;
2223 }
2224
2225 /* See if a partition rename is preferred */
2226 if(getVolumeLabelAlias(bvr, p, strMaxLen)) {
2227 strncpy(bvr->label, p, strMaxLen);
2228 return; // we're done here no need to seek for real name
2229 }
2230
2231 //
2232 // Get the volume label using filesystem specific functions
2233 // or use the alternate volume label if available.
2234 //
2235if (*bvr->altlabel != '\0')
2236 strncpy(p, bvr->altlabel, strMaxLen);
2237else if (bvr->description)
2238 bvr->description(bvr, p, strMaxLen);
2239
2240 if (*p == '\0') {
2241 const char * name = getNameForValue( fdiskTypes, type );
2242 if (name == NULL) {
2243 name = bvr->type_name;
2244 }
2245 if (name == NULL) {
2246 snprintf(p, strMaxLen, "TYPE %02x", type);
2247 } else {
2248 strncpy(p, name, strMaxLen);
2249 }
2250 }
2251
2252 // Set the devices label
2253 snprintf(bvr->label, sizeof(bvr->label), p);
2254}
2255
2256//==========================================================================
2257int readBootSector( int biosdev, unsigned int secno, void * buffer )
2258{
2259 struct disk_blk0 * bootSector = (struct disk_blk0 *) buffer;
2260 int error;
2261
2262 if ( bootSector == NULL )
2263 {
2264 if ( gBootSector == NULL )
2265 {
2266 gBootSector = (struct disk_blk0 *) malloc(sizeof(struct disk_blk0));
2267 if ( gBootSector == NULL ) return -1;
2268bzero(gBootSector,sizeof(struct disk_blk0));
2269 }
2270
2271 bootSector = gBootSector;
2272 }
2273
2274 error = readBytes( biosdev, secno, 0, BPS, bootSector );
2275 if ( error || bootSector->signature != DISK_SIGNATURE )
2276 return -1;
2277
2278 return 0;
2279}
2280
2281#ifndef NO_WIN_SUPPORT
2282/*
2283 * Format of boot1f32 block.
2284 */
2285
2286#define BOOT1F32_MAGIC "BOOT "
2287#define BOOT1F32_MAGICLEN 11
2288
2289struct disk_boot1f32_blk {
2290 unsigned char init[3];
2291 unsigned char fsheader[87];
2292 unsigned char magic[BOOT1F32_MAGICLEN];
2293 unsigned char bootcode[409];
2294 unsigned short signature;
2295};
2296
2297int testFAT32EFIBootSector( int biosdev, unsigned int secno, void * buffer )
2298{
2299 struct disk_boot1f32_blk * bootSector = (struct disk_boot1f32_blk *) buffer;
2300 int error;
2301
2302 if ( bootSector == NULL )
2303 {
2304 if ( gBootSector == NULL )
2305 {
2306 gBootSector = (struct disk_blk0 *) malloc(sizeof(struct disk_blk0));
2307 if ( gBootSector == NULL ) return -1;
2308bzero(gBootSector,sizeof(struct disk_blk0));
2309 }
2310 bootSector = (struct disk_boot1f32_blk *) gBootSector;
2311 }
2312
2313 error = readBytes( biosdev, secno, 0, BPS, bootSector );
2314 if ( error || bootSector->signature != DISK_SIGNATURE
2315|| strncmp((const char *)bootSector->magic, BOOT1F32_MAGIC, BOOT1F32_MAGICLEN) )
2316return -1;
2317
2318 return 0;
2319}
2320#endif
2321//==========================================================================
2322// Handle seek request from filesystem modules.
2323
2324void diskSeek( BVRef bvr, long long position )
2325{
2326 bvr->fs_boff = position / BPS;
2327 bvr->fs_byteoff = position % BPS;
2328}
2329
2330//==========================================================================
2331// Handle read request from filesystem modules.
2332
2333int diskRead( BVRef bvr, long addr, long length )
2334{
2335 return readBytes( bvr->biosdev,
2336 bvr->fs_boff + bvr->part_boff,
2337 bvr->fs_byteoff,
2338 length,
2339 (void *) addr );
2340}
2341
2342#if UNUSED
2343int rawDiskRead( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
2344{
2345 int secs;
2346 unsigned char *cbuf = (unsigned char *)buffer;
2347 unsigned int copy_len;
2348 int rc;
2349
2350 if ((len & (BPS-1)) != 0) {
2351 printf("raw disk read not sector aligned");
2352 return -1;
2353 }
2354 secno += bvr->part_boff;
2355
2356 cache_valid = false;
2357
2358 while (len > 0) {
2359 secs = len / BPS;
2360 if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
2361 copy_len = secs * BPS;
2362
2363 //printf("rdr: ebiosread(%d, %d, %d)\n", bvr->biosdev, secno, secs);
2364 if ((rc = ebiosread(bvr->biosdev, secno, secs)) != 0) {
2365 /* Ignore corrected ECC errors */
2366 if (rc != ECC_CORRECTED_ERR) {
2367 printf(" EBIOS read error: %s\n", bios_error(rc), rc);
2368 printf(" Block %d Sectors %d\n", secno, secs);
2369 return rc;
2370 }
2371 }
2372 bcopy( trackbuf, cbuf, copy_len );
2373 len -= copy_len;
2374 cbuf += copy_len;
2375 secno += secs;
2376#if TEXT_SPINNER
2377spinActivityIndicator(secs);
2378#endif
2379 }
2380
2381 return 0;
2382}
2383
2384int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
2385{
2386 int secs;
2387 unsigned char *cbuf = (unsigned char *)buffer;
2388 unsigned int copy_len;
2389 int rc;
2390
2391 if ((len & (BPS-1)) != 0) {
2392 printf("raw disk write not sector aligned");
2393 return -1;
2394 }
2395 secno += bvr->part_boff;
2396
2397 cache_valid = false;
2398
2399 while (len > 0) {
2400 secs = len / BPS;
2401 if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
2402 copy_len = secs * BPS;
2403
2404 bcopy( cbuf, trackbuf, copy_len );
2405 //printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs);
2406 if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0) {
2407 printf(" EBIOS write error: %s\n", bios_error(rc), rc);
2408 printf(" Block %d Sectors %d\n", secno, secs);
2409 return rc;
2410 }
2411 len -= copy_len;
2412 cbuf += copy_len;
2413 secno += secs;
2414#if TEXT_SPINNER
2415spinActivityIndicator(secs);
2416#endif
2417 }
2418
2419 return 0;
2420}
2421#endif
2422
2423int diskIsCDROM(BVRef bvr)
2424{
2425 struct driveInfo di;
2426
2427 if (getDriveInfo(bvr->biosdev, &di) == 0 && di.no_emulation) {
2428return 1;
2429 }
2430 return 0;
2431}
2432
2433int biosDevIsCDROM(int biosdev)
2434{
2435 struct driveInfo di;
2436
2437 if (getDriveInfo(biosdev, &di) == 0 && di.no_emulation)
2438 {
2439 return 1;
2440 }
2441 return 0;
2442}
2443

Archive Download this file

Revision: HEAD