Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2538