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

Archive Download this file

Revision: 1899