* All rights reserved.
*/
-#define DRIVER_PRIVATE
-
-#include "sys/types.h"
-#include "legacy/disk.h"
-#include "legacy/fdisk.h"
#include "libsaio.h"
-#include "memory.h"
-
-/*
- * Type and constant definitions.
- */
-typedef struct disk_blk0 boot_sector;
-#define BOOT_SIGNATURE DISK_SIGNATURE
-#define PART_TYPE_EXT 0x05
-#define PART_TYPE_APPLE 0xa8
-#define UFS_FRONT_PORCH 0
-
-#if DEBUG
-#define DPRINT(x) { printf x; }
-#define DSPRINT(x) { printf x; sleep(1); }
-#else
-#define DPRINT(x)
-#define DSPRINT(x)
-#endif
-
-/*
- * Function prototypes.
- */
-extern void spinActivityIndicator();
-static void diskActivityHook();
-static int Biosread(int biosdev, int secno);
-static struct fdisk_part * find_partition(u_int8_t type,
- u_int8_t biosdev,
- BOOL mba);
+#include "fdisk.h"
/*
* diskinfo unpacking.
*/
-#define SPT(di) ((di) & 0xff)
-#define HEADS(di) ((((di)>>8) & 0xff) + 1)
-#define SPC(di) (SPT(di) * HEADS(di))
-#define BPS 512 /* sector size of the device */
-#define N_CACHE_SECS (BIOS_LEN / BPS)
+#define SPT(di) ((di) & 0xff)
+#define HEADS(di) ((((di)>>8) & 0xff) + 1)
+#define SPC(di) (SPT(di) * HEADS(di))
-/*
- * Stores the geometry of the disk in order to
- * perform LBA to CHS translation for non EBIOS calls.
- */
-static struct diskinfo {
- int spt; /* sectors per track */
- int spc; /* sectors per cylinder */
-} diskinfo;
-
-/*
- * Globals variables.
- */
-int label_secsize = BPS;
-char * b[NBUFS];
-daddr_t blknos[NBUFS];
-struct iob iob[NFILES];
+#define BPS 512 /* sector size of the device */
+#define N_CACHE_SECS (BIOS_LEN / BPS)
+#define UFS_FRONT_PORCH 0
/*
- * intbuf points to the start of the sector cache. BIOS calls will
- * store the sectors read into this memory area. If cache_valid
- * is TRUE, then intbuf contents are valid. Otherwise, ignore the
- * cache and read from disk.
+ * trackbuf points to the start of the track cache. Biosread()
+ * will store the sectors read from disk to this memory area.
*
- * biosbuf points to a sector within the sector cache.
+ * biosbuf points to a sector within the track cache, and is
+ * updated by Biosread().
*/
-static char * const intbuf = (char *)ptov(BIOS_ADDR);
-static BOOL cache_valid = FALSE;
-static char * biosbuf;
+static const char * const trackbuf = (char *) ptov(BIOS_ADDR);
+static const char * biosbuf;
-/*==========================================================================
- *
+/*
+ * Map a disk drive to bootable volumes contained within.
*/
-void
-devopen(char * name, struct iob * io)
-{
- static int last_biosdev = -1;
- static daddr_t last_offset = 0;
+struct DiskBVMap {
+ int biosdev; // BIOS device number (unique)
+ BVRef bvr; // chain of boot volumes on the disk
+ int bvrcnt; // number of boot volumes
+ struct DiskBVMap * next; // linkage to next mapping
+};
- struct fdisk_part * part;
- long di;
+static struct DiskBVMap * gDiskBVMap = NULL;
+static struct disk_blk0 * gBootSector = NULL;
- io->i_error = 0;
- io->dirbuf_blkno = -1;
+extern long HFSInitPartition(CICell ih);
+extern long HFSLoadFile(CICell ih, char * filePath);
+extern long HFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time);
- // Use cached values if possible.
- //
- if (io->biosdev == last_biosdev) {
- io->i_boff = last_offset;
- return;
- }
+extern long UFSInitPartition(CICell ih);
+extern long UFSLoadFile(CICell ih, char * filePath);
+extern long UFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
+ char ** name, long * flags, long * time);
- // initialize disk parameters -- spt and spc
- // must do this before doing reads from the device.
+extern void spinActivityIndicator();
- di = get_diskinfo(io->biosdev);
- if (di == 0) {
- io->i_error = ENXIO;
- return;
- }
+static void getVolumeDescription(BVRef bvr, char * str, long strMaxLen);
- diskinfo.spt = SPT(di);
- diskinfo.spc = diskinfo.spt * HEADS(di);
-
- // FIXME - io->partition is ignored. Doesn't make sense anymore.
- // we also don't overwrite the 'name' argument.
- // Whats special about "$LBL" ?
-
- part = find_partition(PART_TYPE_APPLE, io->biosdev, FALSE);
- if (part == NULL) {
- io->i_error = EIO;
- DSPRINT(("Unable to find partition: IO error\n"));
- } else {
- last_offset = io->i_boff = part->relsect + UFS_FRONT_PORCH/BPS;
- last_biosdev = io->biosdev;
- DSPRINT(("partition offset: %x\n", io->i_boff));
- }
-}
+//==========================================================================
-/*==========================================================================
- *
- */
-void devflush()
+static int getDiskGeometry( int biosdev, int * spt, int * spc )
{
- cache_valid = FALSE; // invalidate the sector cache (intbuf)
-}
-
-/*==========================================================================
- *
- */
-int devread(struct iob * io)
-{
- long sector;
- int offset;
-// int dev;
-
- io->i_flgs |= F_RDDATA;
+ static int cached_biosdev = -1;
+ static int cached_spt = 0;
+ static int cached_spc = 0;
+
+ if ( biosdev != cached_biosdev )
+ {
+ long di = get_diskinfo(biosdev);
+ if (di == 0) return (-1); // BIOS call error
- io->i_error = 0; // assume the best
+ cached_spt = SPT(di);
+ cached_spc = cached_spt * HEADS(di);
-// dev = io->i_ino.i_dev;
+ DEBUG_DISK(("%s: %d sectors, %d heads\n",
+ __FUNCTION__, cached_spt, (int)HEADS(di)));
+ }
- sector = io->i_bn * (label_secsize/BPS);
+ *spt = cached_spt;
+ *spc = cached_spc;
- for (offset = 0; offset < io->i_cc; offset += BPS) {
+ return 0;
+}
- io->i_error = Biosread(io->biosdev, sector);
- if (io->i_error)
- return (-1);
+//==========================================================================
+// Maps (E)BIOS return codes to message strings.
- /* copy 1 sector from the internal buffer biosbuf into buf */
- bcopy(biosbuf, &io->i_ma[offset], BPS);
+struct NamedValue {
+ unsigned char value;
+ const char * name;
+};
- sector++;
- }
+static const char * getNameForValue( const struct NamedValue * nameTable,
+ unsigned char value )
+{
+ const struct NamedValue * np;
- io->i_flgs &= ~F_TYPEMASK;
+ for ( np = nameTable; np->value; np++)
+ if (np->value == value)
+ return np->name;
- return (io->i_cc);
+ return NULL;
}
-/*==========================================================================
- * Maps (E)BIOS return codes to message strings.
- */
-struct bios_error_info {
- int errno;
- const char * string;
-};
-
#define ECC_CORRECTED_ERR 0x11
-static struct bios_error_info bios_errors[] = {
- {0x10, "Media error"},
- {0x11, "Corrected ECC error"},
- {0x20, "Controller or device error"},
- {0x40, "Seek failed"},
- {0x80, "Device timeout"},
- {0xAA, "Drive not ready"},
- {0x00, 0}
+static const struct NamedValue bios_errors[] = {
+ { 0x10, "Media error" },
+ { 0x11, "Corrected ECC error" },
+ { 0x20, "Controller or device error" },
+ { 0x40, "Seek failed" },
+ { 0x80, "Device timeout" },
+ { 0xAA, "Drive not ready" },
+ { 0x00, 0 }
};
-static const char *
-bios_error(int errno)
+static const char * bios_error(int errnum)
{
- struct bios_error_info * bp;
-
- for (bp = bios_errors; bp->errno; bp++) {
- if (bp->errno == errno)
- return bp->string;
- }
- return "Error 0x%02x"; // No string, print error code only
+ static char errorstr[] = "Error 0x00";
+ const char * errname;
+
+ errname = getNameForValue( bios_errors, errnum );
+ if ( errname ) return errname;
+
+ sprintf(errorstr, "Error 0x%02x", errnum);
+ return errorstr; // No string, print error code only
}
-/*==========================================================================
- * Use BIOS INT13 calls to read the sector specified. This function will
- * also perform read-ahead to cache a few subsequent sector to the sector
- * cache.
- *
- * The fields in diskinfo structure must be filled in before calling this
- * function.
- *
- * Return:
- * Return code from INT13/F2 or INT13/F42 call. If operation was
- * successful, 0 is returned.
- *
- */
-static int
-Biosread(int biosdev, int secno)
+//==========================================================================
+// Use BIOS INT13 calls to read the sector specified. This function will
+// also perform read-ahead to cache a few subsequent sector to the sector
+// cache.
+//
+// Return:
+// 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call.
+
+static int Biosread( int biosdev, unsigned int secno )
{
- static int xbiosdev, xcyl, xhead, xsec, xnsecs;
-
- extern unsigned char uses_ebios[];
+ static int xbiosdev, xcyl, xhead;
+ static unsigned int xsec, xnsecs;
+ static BOOL cache_valid = FALSE;
- int rc;
+ int rc = -1;
int cyl, head, sec;
int spt, spc;
int tries = 0;
- DSPRINT(("Biosread %d \n", secno));
+ // DEBUG_DISK(("Biosread dev %x sec %d \n", biosdev, secno));
// To read the disk sectors, use EBIOS if we can. Otherwise,
// revert to the standard BIOS calls.
- //
- if ((biosdev >= BIOS_DEV_HD) && uses_ebios[biosdev - BIOS_DEV_HD]) {
+
+ if ((biosdev >= kBIOSDevTypeHardDrive) &&
+ (uses_ebios[biosdev - kBIOSDevTypeHardDrive] & EBIOS_FIXED_DISK_ACCESS))
+ {
if (cache_valid &&
(biosdev == xbiosdev) &&
(secno >= xsec) &&
(secno < (xsec + xnsecs)))
{
- biosbuf = intbuf + (BPS * (secno - xsec));
+ biosbuf = trackbuf + (BPS * (secno - xsec));
return 0;
}
xnsecs = N_CACHE_SECS;
xsec = secno;
+ cache_valid = FALSE;
while ((rc = ebiosread(biosdev, secno, xnsecs)) && (++tries < 5))
{
if (rc == ECC_CORRECTED_ERR) {
/* Ignore corrected ECC errors */
+ rc = 0;
break;
}
error(" EBIOS read error: %s\n", bios_error(rc), rc);
sleep(1);
}
}
- else {
- spt = diskinfo.spt; // From previous INT13/F8 call.
- spc = diskinfo.spc;
-
+ else if ( getDiskGeometry(biosdev, &spt, &spc) == 0 )
+ {
cyl = secno / spc;
head = (secno % spc) / spt;
sec = secno % spt;
(sec >= xsec) &&
(sec < (xsec + xnsecs)))
{
- // this sector is in intbuf cache
- biosbuf = intbuf + (BPS * (sec - xsec));
+ // this sector is in trackbuf cache
+ biosbuf = trackbuf + (BPS * (sec - xsec));
return 0;
}
// Cache up to a track worth of sectors, but do not cross a
// track boundary.
- //
+
xcyl = cyl;
xhead = head;
xsec = sec;
xnsecs = ((sec + N_CACHE_SECS) > spt) ? (spt - sec) : N_CACHE_SECS;
+ cache_valid = FALSE;
while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) &&
(++tries < 5))
{
if (rc == ECC_CORRECTED_ERR) {
/* Ignore corrected ECC errors */
+ rc = 0;
break;
}
error(" BIOS read error: %s\n", bios_error(rc), rc);
}
// If the BIOS reported success, mark the sector cache as valid.
- //
+
if (rc == 0) {
cache_valid = TRUE;
}
- biosbuf = intbuf;
+ biosbuf = trackbuf;
xbiosdev = biosdev;
- diskActivityHook();
+ spinActivityIndicator();
return rc;
}
-/*==========================================================================
- * Replace this function if you want to change
- * the way disk activity is indicated to the user.
- */
-void
-diskActivityHook(void)
+//==========================================================================
+
+static int readBytes( int biosdev, unsigned int blkno,
+ unsigned int byteCount, void * buffer )
{
- spinActivityIndicator();
+
+ char * cbuf = (char *) buffer;
+ int error;
+ int copy_len;
+
+ DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__,
+ biosdev, blkno, byteCount, (unsigned)cbuf));
+
+ for ( ; byteCount; cbuf += BPS, blkno++ )
+ {
+ error = Biosread( biosdev, blkno );
+ if ( error )
+ {
+ DEBUG_DISK(("error\n"));
+ return (-1);
+ }
+
+ copy_len = (byteCount > BPS) ? BPS : byteCount;
+ bcopy( biosbuf, cbuf, copy_len );
+ byteCount -= copy_len;
+ }
+
+ DEBUG_DISK(("done\n"));
+
+ return 0;
}
-/*==========================================================================
- * Returns YES if the partition type specified is an extended fdisk
- * partition.
- */
-static BOOL
-isExtendedPartition(u_int8_t type)
+//==========================================================================
+
+static int isExtendedFDiskPartition( const struct fdisk_part * part )
{
- int i;
-
- u_int8_t extended_partitions[] = {
- 0x05, /* Extended */
- 0x0f, /* Win95 extended */
- 0x85, /* Linux extended */
- };
-
- for (i = 0;
- i < sizeof(extended_partitions)/sizeof(extended_partitions[0]);
- i++)
- {
- if (extended_partitions[i] == type)
- return YES;
- }
- return NO;
+ static unsigned char extParts[] =
+ {
+ 0x05, /* Extended */
+ 0x0f, /* Win95 extended */
+ 0x85, /* Linux extended */
+ };
+
+ int i;
+
+ for (i = 0; i < sizeof(extParts)/sizeof(extParts[0]); i++)
+ {
+ if (extParts[i] == part->systid) return 1;
+ }
+ return 0;
}
-/*==========================================================================
- * Traverse the fdisk partition tables on disk until a partition is found
- * that matches the specified type.
- *
- * Arguments:
- * type - Partition type to search for (e.g. 0xa7 for NeXTSTEP).
- * biosdev - BIOS device unit. 0x80 and up for hard-drive.
- * mba - If true, the partition found must be marked active.
- *
- * Return:
- * A pointer to the matching partition entry in biosbuf memory.
- * Note that the starting LBA field in the partition entry is
- * modified to contain the absolute sector address, rather than
- * the relative address.
- * A NULL is returned if a match is not found.
- *
- * There are certain fdisk rules that allows us to simplify the search.
- *
- * - There can be 0-1 extended partition entry in any partition table.
- * - In the MBR, there can be 0-4 primary partitions entries.
- * - In the extended partition, there can be 0-1 logical partition entry.
- *
- */
-struct fdisk_part *
-find_partition(u_int8_t type, u_int8_t biosdev, BOOL mba)
+//==========================================================================
+
+static int getNextFDiskPartition( int biosdev, int * partno,
+ const struct fdisk_part ** outPart )
{
-#define MAX_ITERATIONS 128
+ static int sBiosdev = -1;
+ static int sNextPartNo;
+ static unsigned int sExtBase;
+ static unsigned int sExtDepth;
+ static struct fdisk_part * sExtPart;
+ struct fdisk_part * part;
+
+ if ( sBiosdev != biosdev || *partno < 0 )
+ {
+ // Fetch MBR.
+ if ( readBootSector( biosdev, DISK_BLK0, 0 ) ) return 0;
+
+ sBiosdev = biosdev;
+ sNextPartNo = 0;
+ sExtBase = 0;
+ sExtDepth = 0;
+ sExtPart = NULL;
+ }
- static u_int32_t iter = 0;
- static u_int32_t offset_root;
- static u_int32_t offset;
+ while (1)
+ {
+ part = NULL;
- int n;
- int rc;
- boot_sector * bootsect;
- struct fdisk_part * match = 0;
- struct fdisk_part * parts;
+ if ( sNextPartNo < FDISK_NPART )
+ {
+ part = (struct fdisk_part *) gBootSector->parts[sNextPartNo];
+ }
+ else if ( sExtPart )
+ {
+ unsigned int blkno = sExtPart->relsect + sExtBase;
- if (iter == 0) {
- if (rc = Biosread(biosdev, 0)) // Read MBR at sector zero.
- return 0;
- offset = 0;
+ // Save the block offset of the first extended partition.
+
+ if ( sExtDepth == 0 ) sExtBase = sExtPart->relsect;
+
+ // Load extended partition table.
+
+ if ( readBootSector( biosdev, blkno, 0 ) == 0 )
+ {
+ sNextPartNo = 0;
+ sExtDepth++;
+ sExtPart = NULL;
+ continue;
+ }
+ }
+
+ if ( part == NULL ) break; // Reached end of partition chain.
+
+ // Advance to next partition number.
+
+ sNextPartNo++;
+
+ // Assume at most one extended partition per table.
+
+ if ( isExtendedFDiskPartition(part) )
+ {
+ sExtPart = part;
+ continue;
+ }
+
+ // Skip empty slots.
+
+ if ( part->systid == 0x00 )
+ {
+ continue;
+ }
+
+ // Change relative offset to an absolute offset.
+
+ part->relsect += sExtBase;
+
+ *outPart = part;
+ *partno = sExtDepth ? (sExtDepth + 4) : sNextPartNo;
+
+ break;
}
- bootsect = (boot_sector *) biosbuf;
- if (bootsect->signature != BOOT_SIGNATURE)
- return 0;
+ return (part != NULL);
+}
+
+//==========================================================================
- // Find a primary or a logical partition that matches the partition
- // type specified.
- //
- for (n = 0, parts = (struct fdisk_part *) bootsect->parts;
- n < 4;
- n++, parts++)
+static BVRef newFDiskBVRef( int biosdev, int partno, unsigned int blkoff,
+ const struct fdisk_part * part,
+ FSInit initFunc, FSLoadFile loadFunc,
+ FSGetDirEntry getdirFunc, int probe )
+{
+ BVRef bvr = (BVRef) malloc( sizeof(*bvr) );
+ if ( bvr )
{
- DSPRINT(("fdisk: [%d] %02x\n", iter, parts->systid));
+ bzero(bvr, sizeof(*bvr));
- if (mba && ((parts->bootid & 0x80) == 0))
- continue;
+ bvr->biosdev = biosdev;
+ bvr->part_no = partno;
+ bvr->part_boff = blkoff;
+ bvr->part_type = part->systid;
+ bvr->fs_loadfile = loadFunc;
+ bvr->fs_getdirentry = getdirFunc;
+ bvr->description = getVolumeDescription;
+
+ if ( part->bootid & FDISK_ACTIVE )
+ bvr->flags |= kBVFlagPrimary;
+
+ // Probe the filesystem.
+
+ if ( initFunc )
+ {
+ bvr->flags |= kBVFlagNativeBoot;
- if (parts->systid == type) {
- //
- // Found it!!!
- // Make the relsect field (LBA starting sector) absolute by
- // adding in the offset.
- //
- parts->relsect += offset;
+ if ( probe && initFunc( bvr ) != 0 )
+ {
+ // filesystem probe failed.
- DSPRINT(("Found: %x (%d)\n", parts->relsect, parts->numsect));
+ DEBUG_DISK(("%s: failed probe on dev %x part %d\n",
+ __FUNCTION__, biosdev, partno));
- return parts;
+ free(bvr);
+ bvr = NULL;
+ }
+ }
+ else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 )
+ {
+ bvr->flags |= kBVFlagForeignBoot;
+ }
+ else
+ {
+ free(bvr);
+ bvr = NULL;
}
}
+ return bvr;
+}
- // Find if there is an extended partition entry that points to
- // an extended partition table. Note that we only allow up to
- // one extended partition per partition table.
- //
- for (n = 0, parts = (struct fdisk_part *) bootsect->parts;
- n < 4;
- n++, parts++)
- {
- DSPRINT(("fdisk: [E%d] %02x\n", iter, parts->systid));
+//==========================================================================
+
+BVRef diskScanBootVolumes( int biosdev, int * countPtr )
+{
+ const struct fdisk_part * part;
+ struct DiskBVMap * map;
+ int partno = -1;
+ BVRef bvr;
+ BVRef booterUFS = NULL;
+ int spc, spt;
- if (isExtendedPartition(parts->systid))
+ do {
+ // Find an existing mapping for this device.
+
+ for ( map = gDiskBVMap; map; map = map->next )
{
- if (iter > MAX_ITERATIONS) // limit recursion depth
- return 0;
+ if ( biosdev == map->biosdev ) break;
+ }
+ if ( map ) break;
- if (iter == 0)
- offset = offset_root = parts->relsect;
- else
- offset = parts->relsect + offset_root;
+ // Create a new mapping.
- iter++;
+ map = (struct DiskBVMap *) malloc( sizeof(*map) );
+ if ( map )
+ {
+ map->biosdev = biosdev;
+ map->bvr = NULL;
+ map->bvrcnt = 0;
+ map->next = gDiskBVMap;
+ gDiskBVMap = map;
- // Load extended partition table.
- //
- if (((rc = Biosread(biosdev, offset)) == 0) &&
- (bootsect->signature == BOOT_SIGNATURE))
+ // Create a record for each partition found on the disk.
+
+ while ( getNextFDiskPartition( biosdev, &partno, &part ) )
{
- match = find_partition(type, biosdev, mba);
+ DEBUG_DISK(("%s: part %d [%x]\n", __FUNCTION__,
+ partno, part->systid));
+
+ bvr = 0;
+
+ switch ( part->systid )
+ {
+ case FDISK_UFS:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect + UFS_FRONT_PORCH/BPS,
+ part,
+ UFSInitPartition,
+ UFSLoadFile,
+ UFSGetDirEntry,
+ 0 );
+ break;
+
+ case FDISK_HFS:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect,
+ part,
+ HFSInitPartition,
+ HFSLoadFile,
+ HFSGetDirEntry,
+ 0 );
+ break;
+
+ case FDISK_BOOTER:
+ if (getDiskGeometry(biosdev, &spt, &spc) != 0)
+ break;
+
+ booterUFS = newFDiskBVRef(
+ biosdev, partno,
+ ((part->relsect + spc - 1) / spc) * spc,
+ part,
+ UFSInitPartition,
+ UFSLoadFile,
+ UFSGetDirEntry,
+ 0 );
+ break;
+
+ default:
+ bvr = newFDiskBVRef(
+ biosdev, partno,
+ part->relsect,
+ part,
+ 0, 0, 0, 0 );
+ break;
+ }
+
+ if ( bvr )
+ {
+ bvr->next = map->bvr;
+ map->bvr = bvr;
+ map->bvrcnt++;
+ }
}
-
- iter--;
- break;
+ // Booting from a CD with an UFS filesystem embedded
+ // in a booter partition.
+
+ if ( booterUFS )
+ {
+ if ( map->bvrcnt == 0 )
+ {
+ map->bvr = booterUFS;
+ map->bvrcnt++;
+ }
+ else free( booterUFS );
+ }
+ }
+ } while (0);
+
+ if (countPtr) *countPtr = map ? map->bvrcnt : 0;
+
+ return map ? map->bvr : NULL;
+}
+
+//==========================================================================
+
+static const struct NamedValue fdiskTypes[] =
+{
+ { 0x07, "Windows NTFS" },
+ { 0x0c, "Windows FAT32" },
+ { 0x83, "Linux" },
+ { FDISK_UFS, "Apple UFS" },
+ { FDISK_HFS, "Apple HFS" },
+ { FDISK_BOOTER, "Apple Boot/UFS" },
+ { 0x00, 0 } /* must be last */
+};
+
+static void getVolumeDescription( BVRef bvr, char * str, long strMaxLen )
+{
+ unsigned char type = (unsigned char) bvr->part_type;
+ const char * name = getNameForValue( fdiskTypes, type );
+
+ if ( name )
+ sprintf( str, "hd(%d,%d) %s",
+ BIOS_DEV_UNIT(bvr->biosdev), bvr->part_no, name );
+ else
+ sprintf( str, "hd(%d,%d) TYPE %02x",
+ BIOS_DEV_UNIT(bvr->biosdev), bvr->part_no, type );
+}
+
+//==========================================================================
+
+int readBootSector( int biosdev, unsigned int secno, void * buffer )
+{
+ struct disk_blk0 * bootSector = (struct disk_blk0 *) buffer;
+ int error;
+
+ if ( bootSector == NULL )
+ {
+ if ( gBootSector == NULL )
+ {
+ gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector));
+ if ( gBootSector == NULL ) return -1;
}
+ bootSector = gBootSector;
}
-
- return match;
+
+ error = readBytes( biosdev, secno, BPS, bootSector );
+ if ( error || bootSector->signature != DISK_SIGNATURE )
+ return -1;
+
+ return 0;
+}
+
+//==========================================================================
+// Handle seek request from filesystem modules.
+
+void diskSeek( BVRef bvr, long long position )
+{
+ bvr->fs_boff = position / BPS;
+}
+
+//==========================================================================
+// Handle read request from filesystem modules.
+
+int diskRead( BVRef bvr, long addr, long length )
+{
+ return readBytes( bvr->biosdev,
+ bvr->fs_boff + bvr->part_boff,
+ length,
+ (void *) addr );
}