Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1916