Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2517