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

Archive Download this file

Revision: 1977