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; bvr = bvr->next)
1699{
1700#ifdef BOOT_HELPER_SUPPORT
1701error = 0;
1702
1703//
1704// Check for alternate volume label on boot helper partitions.
1705//
1706if (bvr->flags & kBVFlagBooter)
1707{
1708sprintf(dirSpec, "hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no);
1709strcpy(fileSpec, ".disk_label.contentDetails");
1710ret = GetFileInfo(dirSpec, fileSpec, &flags, &time);
1711if (!ret)
1712{
1713fh = open(strcat(dirSpec, fileSpec));
1714fileSize = file_size(fh);
1715if (fileSize > 0 && fileSize < BVSTRLEN)
1716{
1717if (read(fh, label, fileSize) != fileSize)
1718error = -1;
1719}
1720else
1721error = -1;
1722
1723close(fh);
1724
1725if (!error)
1726{
1727label[fileSize] = '\0';
1728strcpy(bvr->altlabel, label);
1729}
1730}
1731}
1732#endif
1733//
1734// Check for SystemVersion.plist or ServerVersion.plist
1735// to determine if a volume hosts an installed system.
1736//
1737if (bvr->flags & kBVFlagNativeBoot)
1738{
1739if (CheckDarwin(bvr) == true)
1740{
1741bvr->flags |= kBVFlagSystemVolume;
1742}
1743}
1744
1745}
1746}
1747#ifndef OPTION_ROM
1748void rescanBIOSDevice(int biosdev)
1749{
1750struct DiskBVMap *oldMap = diskResetBootVolumes(biosdev);
1751CacheReset();
1752diskFreeMap(oldMap);
1753oldMap = NULL;
1754scanBootVolumes(biosdev, 0);
1755}
1756#endif
1757
1758struct DiskBVMap* diskResetBootVolumes(int biosdev)
1759{
1760 struct DiskBVMap * map;
1761 struct DiskBVMap *prevMap = NULL;
1762 for ( map = gDiskBVMap; map; prevMap = map, map = map->next ) {
1763 if ( biosdev == map->biosdev ) {
1764 break;
1765 }
1766 }
1767 if(map != NULL)
1768 {
1769 verbose("Resetting BIOS device %xh\n", biosdev);
1770 // Reset the biosbuf cache
1771 cache_valid = false;
1772 if(map == gDiskBVMap)
1773 gDiskBVMap = map->next;
1774 else if(prevMap != NULL)
1775 prevMap->next = map->next;
1776 else
1777 stop("");
1778 }
1779 // Return the old map, either to be freed, or reinserted later
1780 return map;
1781}
1782
1783// Frees a DiskBVMap and all of its BootVolume's
1784void diskFreeMap(struct DiskBVMap *map)
1785{
1786 if(map != NULL)
1787 {
1788 while(map->bvr != NULL)
1789 {
1790 BVRef bvr = map->bvr;
1791 map->bvr = bvr->next;
1792 (*bvr->bv_free)(bvr);
1793 }
1794 free(map);
1795 }
1796}
1797
1798BVRef diskScanBootVolumes( int biosdev, int * countPtr )
1799{
1800 struct DiskBVMap * map;
1801 BVRef bvr;
1802 int count = 0;
1803
1804 // Find an existing mapping for this device.
1805
1806 for ( map = gDiskBVMap; map; map = map->next ) {
1807 if ( biosdev == map->biosdev ) {
1808 count = map->bvrcnt;
1809 break;
1810 }
1811 }
1812
1813 if (map == NULL) {
1814 bvr = diskScanGPTBootVolumes(biosdev, &count);
1815 if (bvr == NULL) {
1816bvr = diskScanFDiskBootVolumes(biosdev, &count);
1817 }
1818#ifdef APPLE_PARTITION_MAP_SUPPORT
1819 if (bvr == NULL) {
1820bvr = diskScanAPMBootVolumes(biosdev, &count);
1821 }
1822#endif
1823 if (bvr)
1824 {
1825scanFSLevelBVRSettings(bvr);
1826 }
1827 } else {
1828 bvr = map->bvr;
1829 }
1830 if (countPtr) *countPtr += count;
1831 return bvr;
1832}
1833
1834BVRef getBVChainForBIOSDev(int biosdev)
1835{
1836BVRef chain = NULL;
1837struct DiskBVMap * map = NULL;
1838
1839for (map = gDiskBVMap; map; map = map->next)
1840{
1841if (map->biosdev == biosdev)
1842{
1843chain = map->bvr;
1844break;
1845}
1846}
1847
1848return chain;
1849}
1850
1851BVRef newFilteredBVChain(int minBIOSDev, int maxBIOSDev, unsigned int allowFlags, unsigned int denyFlags, int *count)
1852{
1853BVRef chain = NULL;
1854BVRef bvr = NULL;
1855BVRef newBVR = NULL;
1856BVRef prevBVR = NULL;
1857
1858struct DiskBVMap * map = NULL;
1859int bvCount = 0;
1860
1861const char *raw = 0;
1862char* val = 0;
1863int len;
1864
1865getValueForKey(kHidePartition, &raw, &len, DEFAULT_BOOT_CONFIG);
1866if(raw)
1867{
1868val = XMLDecode(raw);
1869}
1870
1871/*
1872 * Traverse gDISKBVmap to get references for
1873 * individual bvr chains of each drive.
1874 */
1875for (map = gDiskBVMap; map; map = map->next)
1876{
1877for (bvr = map->bvr; bvr; bvr = bvr->next)
1878{
1879/*
1880 * Save the last bvr.
1881 */
1882if (newBVR) prevBVR = newBVR;
1883
1884/*
1885 * Allocate and copy the matched bvr entry into a new one.
1886 */
1887newBVR = (BVRef) malloc(sizeof(*newBVR));
1888bcopy(bvr, newBVR, sizeof(*newBVR));
1889
1890/*
1891 * Adjust the new bvr's fields.
1892 */
1893newBVR->next = NULL;
1894newBVR->filtered = true;
1895
1896if ( (!allowFlags || newBVR->flags & allowFlags)
1897&& (!denyFlags || !(newBVR->flags & denyFlags) )
1898&& (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev)
1899)
1900newBVR->visible = true;
1901
1902/* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format
1903 * to be able to hide foreign partitions from the boot menu.
1904 */
1905if ( (newBVR->flags & kBVFlagForeignBoot) )
1906{
1907char *start, *next = val;
1908long len = 0;
1909do
1910{
1911start = strbreak(next, &next, &len);
1912if(len && matchVolumeToString(newBVR, start, len) )
1913newBVR->visible = false;
1914}
1915while ( next && *next );
1916}
1917
1918/*
1919 * Use the first bvr entry as the starting chain pointer.
1920 */
1921if (!chain)
1922chain = newBVR;
1923
1924/*
1925 * Update the previous bvr's link pointer to use the new memory area.
1926 */
1927if (prevBVR)
1928prevBVR->next = newBVR;
1929
1930if (newBVR->visible)
1931bvCount++;
1932}
1933}
1934
1935#if DEBUG
1936for (bvr = chain; bvr; bvr = bvr->next)
1937{
1938printf(" bvr: %d, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible);
1939}
1940printf("count: %d\n", bvCount);
1941getc();
1942#endif
1943
1944*count = bvCount;
1945
1946free(val);
1947return chain;
1948}
1949
1950int freeFilteredBVChain(const BVRef chain)
1951{
1952int ret = 1;
1953BVRef bvr = chain;
1954BVRef nextBVR = NULL;
1955
1956while (bvr)
1957{
1958nextBVR = bvr->next;
1959
1960if (bvr->filtered)
1961{
1962free(bvr);
1963}
1964else
1965{
1966ret = 0;
1967break;
1968}
1969
1970bvr = nextBVR;
1971}
1972
1973return ret;
1974}
1975
1976//==========================================================================
1977
1978static const struct NamedValue fdiskTypes[] =
1979{
1980#ifndef NO_WIN_SUPPORT
1981 { FDISK_NTFS, "Windows NTFS" },
1982{ FDISK_DOS12, "Windows FAT12" },
1983{ FDISK_DOS16B, "Windows FAT16" },
1984{ FDISK_DOS16S, "Windows FAT16" },
1985{ FDISK_DOS16SLBA, "Windows FAT16" },
1986{ FDISK_SMALLFAT32, "Windows FAT32" },
1987{ FDISK_FAT32, "Windows FAT32" },
1988#endif
1989#ifndef NO_OTHERS_BSD_SUPPORT
1990{ FDISK_FREEBSD, "FreeBSD" },
1991 { FDISK_OPENBSD, "OpenBSD" },
1992#endif
1993#ifndef NO_LINUX_SUPPORT
1994 { FDISK_LINUX, "Linux" },
1995#endif
1996#ifdef UFS_SUPPORT
1997 { FDISK_UFS, "Apple UFS" },
1998#endif
1999 { FDISK_HFS, "Apple HFS" },
2000 { FDISK_BOOTER, "Apple Boot/UFS" },
2001#ifndef NO_HAIKU_SUPPORT
2002{ FDISK_BEFS, "Haiku" },
2003#endif
2004 { 0xCD, "CD-ROM" },
2005 { 0x00, 0 } /* must be last */
2006};
2007
2008//==========================================================================
2009
2010bool matchVolumeToString( BVRef bvr, const char* match, long matchLen)
2011{
2012char testStr[128];
2013
2014if ( !bvr || !match || !*match)
2015return 0;
2016
2017if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 )
2018 return 0;
2019
2020 // Try to match hd(x,y) first.
2021 sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no);
2022 if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2023 return true;
2024
2025 // Try to match volume UUID.
2026 if ( bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0)
2027 {
2028 if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2029 return true;
2030 }
2031
2032 // Try to match volume label (always quoted).
2033 if ( bvr->description )
2034 {
2035 bvr->description(bvr, testStr, sizeof(testStr)-1);
2036 if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) )
2037 return true;
2038 }
2039
2040 return false;
2041}
2042
2043/* If Rename Partition has defined an alias, then extract it for description purpose
2044 * The format for the rename string is the following:
2045 * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ...
2046 */
2047
2048bool getVolumeLabelAlias(BVRef bvr, char* str, long strMaxLen)
2049{
2050 char *aliasList, *entryStart, *entryNext;
2051
2052 if ( !str || strMaxLen <= 0)
2053 return false;
2054
2055 aliasList = XMLDecode(getStringForKey(kRenamePartition, DEFAULT_BOOT_CONFIG));
2056 if ( !aliasList )
2057 return false;
2058
2059 for ( entryStart = entryNext = aliasList;
2060 entryNext && *entryNext;
2061 entryStart = entryNext )
2062 {
2063 char *volStart, *volEnd, *aliasStart;
2064 long volLen, aliasLen;
2065
2066 // Delimit current entry
2067 entryNext = strchr(entryStart, ';');
2068 if ( entryNext )
2069 {
2070 *entryNext = '\0';
2071 entryNext++;
2072 }
2073
2074 volStart = strbreak(entryStart, &volEnd, &volLen);
2075 if(!volLen)
2076 continue;
2077
2078 aliasStart = strbreak(volEnd, 0, &aliasLen);
2079 if(!aliasLen)
2080 continue;
2081
2082 if ( matchVolumeToString(bvr, volStart, volLen) )
2083 {
2084 strncat(str, aliasStart, min(strMaxLen, aliasLen));
2085 free(aliasList);
2086
2087 return true;
2088 }
2089 }
2090
2091 free(aliasList);
2092 return false;
2093}
2094
2095void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription )
2096{
2097 unsigned char type;
2098 char *p = str;
2099
2100 if(!bvr || !p || strMaxLen <= 0)
2101 return;
2102
2103 type = (unsigned char) bvr->part_type;
2104
2105 if (useDeviceDescription)
2106 {
2107 int len = getDeviceDescription(bvr, str);
2108 if(len >= strMaxLen)
2109 return;
2110
2111 strcpy(str + len, " ");
2112 len++;
2113 strMaxLen -= len;
2114 p += len;
2115 }
2116
2117 /* See if a partition rename is preferred */
2118 if(getVolumeLabelAlias(bvr, p, strMaxLen)) {
2119 strncpy(bvr->label, p, strMaxLen);
2120 return; // we're done here no need to seek for real name
2121 }
2122
2123 //
2124 // Get the volume label using filesystem specific functions
2125 // or use the alternate volume label if available.
2126 //
2127if (*bvr->altlabel != '\0')
2128 strncpy(p, bvr->altlabel, strMaxLen);
2129else if (bvr->description)
2130 bvr->description(bvr, p, strMaxLen);
2131
2132 if (*p == '\0') {
2133 const char * name = getNameForValue( fdiskTypes, type );
2134 if (name == NULL) {
2135 name = bvr->type_name;
2136 }
2137 if (name == NULL) {
2138 sprintf(p, "TYPE %02x", type);
2139 } else {
2140 strncpy(p, name, strMaxLen);
2141 }
2142 }
2143
2144 // Set the devices label
2145 sprintf(bvr->label, p);
2146}
2147
2148//==========================================================================
2149int readBootSector( int biosdev, unsigned int secno, void * buffer )
2150{
2151 struct disk_blk0 * bootSector = (struct disk_blk0 *) buffer;
2152 int error;
2153
2154 if ( bootSector == NULL )
2155 {
2156 if ( gBootSector == NULL )
2157 {
2158 gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector));
2159 if ( gBootSector == NULL ) return -1;
2160 }
2161 bootSector = gBootSector;
2162 }
2163
2164 error = readBytes( biosdev, secno, 0, BPS, bootSector );
2165 if ( error || bootSector->signature != DISK_SIGNATURE )
2166 return -1;
2167
2168 return 0;
2169}
2170
2171#ifndef NO_WIN_SUPPORT
2172/*
2173 * Format of boot1f32 block.
2174 */
2175
2176#define BOOT1F32_MAGIC "BOOT "
2177#define BOOT1F32_MAGICLEN 11
2178
2179struct disk_boot1f32_blk {
2180 unsigned char init[3];
2181 unsigned char fsheader[87];
2182 unsigned char magic[BOOT1F32_MAGICLEN];
2183 unsigned char bootcode[409];
2184 unsigned short signature;
2185};
2186
2187int testFAT32EFIBootSector( int biosdev, unsigned int secno, void * buffer )
2188{
2189 struct disk_boot1f32_blk * bootSector = (struct disk_boot1f32_blk *) buffer;
2190 int error;
2191
2192 if ( bootSector == NULL )
2193 {
2194 if ( gBootSector == NULL )
2195 {
2196 gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector));
2197 if ( gBootSector == NULL ) return -1;
2198 }
2199 bootSector = (struct disk_boot1f32_blk *) gBootSector;
2200 }
2201
2202 error = readBytes( biosdev, secno, 0, BPS, bootSector );
2203 if ( error || bootSector->signature != DISK_SIGNATURE
2204|| strncmp((const char *)bootSector->magic, BOOT1F32_MAGIC, BOOT1F32_MAGICLEN) )
2205return -1;
2206
2207 return 0;
2208}
2209#endif
2210//==========================================================================
2211// Handle seek request from filesystem modules.
2212
2213void diskSeek( BVRef bvr, long long position )
2214{
2215 bvr->fs_boff = position / BPS;
2216 bvr->fs_byteoff = position % BPS;
2217}
2218
2219//==========================================================================
2220// Handle read request from filesystem modules.
2221
2222int diskRead( BVRef bvr, long addr, long length )
2223{
2224 return readBytes( bvr->biosdev,
2225 bvr->fs_boff + bvr->part_boff,
2226 bvr->fs_byteoff,
2227 length,
2228 (void *) addr );
2229}
2230
2231#if UNUSED
2232int rawDiskRead( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
2233{
2234 int secs;
2235 unsigned char *cbuf = (unsigned char *)buffer;
2236 unsigned int copy_len;
2237 int rc;
2238
2239 if ((len & (BPS-1)) != 0) {
2240 printf("raw disk read not sector aligned");
2241 return -1;
2242 }
2243 secno += bvr->part_boff;
2244
2245 cache_valid = false;
2246
2247 while (len > 0) {
2248 secs = len / BPS;
2249 if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
2250 copy_len = secs * BPS;
2251
2252 //printf("rdr: ebiosread(%d, %d, %d)\n", bvr->biosdev, secno, secs);
2253 if ((rc = ebiosread(bvr->biosdev, secno, secs)) != 0) {
2254 /* Ignore corrected ECC errors */
2255 if (rc != ECC_CORRECTED_ERR) {
2256 printf(" EBIOS read error: %s\n", bios_error(rc), rc);
2257 printf(" Block %d Sectors %d\n", secno, secs);
2258 return rc;
2259 }
2260 }
2261 bcopy( trackbuf, cbuf, copy_len );
2262 len -= copy_len;
2263 cbuf += copy_len;
2264 secno += secs;
2265#if TEXT_SPINNER
2266spinActivityIndicator(secs);
2267#endif
2268 }
2269
2270 return 0;
2271}
2272
2273int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len )
2274{
2275 int secs;
2276 unsigned char *cbuf = (unsigned char *)buffer;
2277 unsigned int copy_len;
2278 int rc;
2279
2280 if ((len & (BPS-1)) != 0) {
2281 printf("raw disk write not sector aligned");
2282 return -1;
2283 }
2284 secno += bvr->part_boff;
2285
2286 cache_valid = false;
2287
2288 while (len > 0) {
2289 secs = len / BPS;
2290 if (secs > N_CACHE_SECS) secs = N_CACHE_SECS;
2291 copy_len = secs * BPS;
2292
2293 bcopy( cbuf, trackbuf, copy_len );
2294 //printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs);
2295 if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0) {
2296 printf(" EBIOS write error: %s\n", bios_error(rc), rc);
2297 printf(" Block %d Sectors %d\n", secno, secs);
2298 return rc;
2299 }
2300 len -= copy_len;
2301 cbuf += copy_len;
2302 secno += secs;
2303#if TEXT_SPINNER
2304spinActivityIndicator(secs);
2305#endif
2306 }
2307
2308 return 0;
2309}
2310#endif
2311
2312int diskIsCDROM(BVRef bvr)
2313{
2314 struct driveInfo di;
2315
2316 if (getDriveInfo(bvr->biosdev, &di) == 0 && di.no_emulation) {
2317return 1;
2318 }
2319 return 0;
2320}
2321
2322int biosDevIsCDROM(int biosdev)
2323{
2324 struct driveInfo di;
2325
2326 if (getDriveInfo(biosdev, &di) == 0 && di.no_emulation)
2327 {
2328 return 1;
2329 }
2330 return 0;
2331}
2332

Archive Download this file

Revision: 1913