memset(&IPL, 0, sizeof(IPL));
// Floppy drive
- struct ipl_entry_s *ip = &IPL.table[0];
- ip->type = IPL_TYPE_FLOPPY;
- ip++;
+ struct ipl_entry_s *ie = &IPL.table[0];
+ ie->type = IPL_TYPE_FLOPPY;
+ ie->description = "Floppy";
+ ie++;
// First HDD
- ip->type = IPL_TYPE_HARDDISK;
- ip++;
+ ie->type = IPL_TYPE_HARDDISK;
+ ie->description = "Hard Disk";
+ ie++;
// CDROM
if (CONFIG_CDROM_BOOT) {
- ip->type = IPL_TYPE_CDROM;
- ip++;
+ ie->type = IPL_TYPE_CDROM;
+ ie->description = "CD-Rom";
+ ie++;
}
- IPL.count = ip - IPL.table;
+ IPL.count = ie - IPL.table;
SET_EBDA(boot_sequence, 0xffff);
if (CONFIG_COREBOOT) {
// XXX - hardcode defaults for coreboot.
if (IPL.count >= ARRAY_SIZE(IPL.table))
return;
- struct ipl_entry_s *ip = &IPL.table[IPL.count];
- ip->type = IPL_TYPE_BEV;
- ip->vector = (seg << 16) | bev;
+ struct ipl_entry_s *ie = &IPL.table[IPL.count];
+ ie->type = IPL_TYPE_BEV;
+ ie->vector = (seg << 16) | bev;
if (desc)
- ip->description = MAKE_FLATPTR(seg, desc);
+ ie->description = MAKE_FLATPTR(seg, desc);
IPL.count++;
}
-/****************************************************************
- * Printing helpers
- ****************************************************************/
-
-static const char drivetypes[][10]={
- "", "Floppy", "Hard Disk", "CD-Rom", "Network"
-};
-
-// display a device name
-static void
-printf_bootdev(u16 bootdev)
-{
- u16 type = IPL.table[bootdev].type;
-
- /* NIC appears as type 0x80 */
- if (type == IPL_TYPE_BEV)
- type = 0x4;
- if (type == 0 || type > 0x4) {
- printf("Unknown");
- return;
- }
- printf("%s", drivetypes[type]);
-
- /* print product string if BEV */
- char *description_fl = IPL.table[bootdev].description;
- if (type == 4 && description_fl != 0) {
- char description[33];
- /* first 32 bytes are significant */
- memcpy(description, description_fl, 32);
- /* terminate string */
- description[32] = 0;
- printf(" [%.s]", description);
- }
-}
-
-// display the boot device
-static void
-print_boot_device(u16 bootdev)
-{
- printf("Booting from ");
- printf_bootdev(bootdev);
- printf("...\n");
-}
-
-// display the reason why a boot failed
-static void
-print_boot_failure(u16 type, u8 reason)
-{
- printf("Boot failed");
- if (type < 4) {
- /* Report the reason too */
- if (reason==0)
- printf(": not a bootable disk");
- else
- printf(": could not read the boot disk");
- }
- printf("\n\n");
-}
-
-
/****************************************************************
* Boot menu
****************************************************************/
int count = IPL.count;
int i;
for (i = 0; i < count; i++) {
- printf("%d. ", i+1);
- printf_bootdev(i);
- printf("\n");
+ struct ipl_entry_s *ie = &IPL.table[i];
+ char desc[33];
+ printf("%d. %s\n", i+1
+ , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
}
for (;;) {
****************************************************************/
static void
-try_boot(u16 seq_nr)
+call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
+{
+ dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
+
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.ip = bootip;
+ br.cs = bootseg;
+ // Set the magic number in ax and the boot drive in dl.
+ br.dl = bootdrv;
+ br.ax = 0xaa55;
+ call16(&br);
+}
+
+// Boot from a disk (either floppy or harddrive)
+static void
+boot_disk(u8 bootdrv, int checksig)
+{
+ u16 bootseg = 0x07c0;
+
+ // Read sector
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.dl = bootdrv;
+ br.es = bootseg;
+ br.ah = 2;
+ br.al = 1;
+ br.cl = 1;
+ call16_int(0x13, &br);
+
+ if (br.flags & F_CF) {
+ printf("Boot failed: could not read the boot disk\n\n");
+ return;
+ }
+
+ if (checksig) {
+ struct mbr_s *mbr = (void*)0;
+ if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
+ printf("Boot failed: not a bootable disk\n\n");
+ return;
+ }
+ }
+
+ /* Canonicalize bootseg:bootip */
+ u16 bootip = (bootseg & 0x0fff) << 4;
+ bootseg &= 0xf000;
+
+ call_boot_entry(bootseg, bootip, bootdrv);
+}
+
+// Boot from a CD-ROM
+static void
+boot_cdrom()
+{
+ if (! CONFIG_CDROM_BOOT)
+ return;
+ int status = cdrom_boot();
+ if (status) {
+ printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
+ return;
+ }
+
+ u16 ebda_seg = get_ebda_seg();
+ u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
+ u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
+ /* Canonicalize bootseg:bootip */
+ u16 bootip = (bootseg & 0x0fff) << 4;
+ bootseg &= 0xf000;
+
+ call_boot_entry(bootseg, bootip, bootdrv);
+}
+
+static void
+do_boot(u16 seq_nr)
{
if (! CONFIG_BOOT)
BX_PANIC("Boot support not compiled in.\n");
if (bootdev >= IPL.count) {
dprintf(1, "Invalid boot device (0x%x)\n", bootdev);
- return;
+ goto fail;
}
/* Do the loading, and set up vector as a far pointer to the boot
* address, and bootdrv as the boot drive */
- print_boot_device(bootdev);
+ struct ipl_entry_s *ie = &IPL.table[bootdev];
+ char desc[33];
+ printf("Booting from %s...\n"
+ , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
- u16 type = IPL.table[bootdev].type;
-
- u16 bootseg, bootip;
- u8 bootdrv = 0;
- struct bregs cr;
- switch(type) {
+ switch(ie->type) {
case IPL_TYPE_FLOPPY:
+ boot_disk(0x00, IPL.checkfloppysig);
+ break;
case IPL_TYPE_HARDDISK:
-
- bootdrv = (type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
- bootseg = 0x07c0;
-
- // Read sector
- memset(&cr, 0, sizeof(cr));
- cr.dl = bootdrv;
- cr.es = bootseg;
- cr.ah = 2;
- cr.al = 1;
- cr.cl = 1;
- call16_int(0x13, &cr);
-
- if (cr.flags & F_CF) {
- print_boot_failure(type, 1);
- return;
- }
-
- /* Always check the signature on a HDD boot sector; on FDD,
- * only do the check if configured for it */
- if (type != IPL_TYPE_FLOPPY || IPL.checkfloppysig) {
- struct mbr_s *mbr = (void*)0;
- if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
- print_boot_failure(type, 0);
- return;
- }
- }
-
- /* Canonicalize bootseg:bootip */
- bootip = (bootseg & 0x0fff) << 4;
- bootseg &= 0xf000;
+ boot_disk(0x80, 1);
break;
- case IPL_TYPE_CDROM: {
- /* CD-ROM */
- if (! CONFIG_CDROM_BOOT)
- return;
- int status = cdrom_boot();
- if (status) {
- printf("CDROM boot failure code : %04x\n", status);
- print_boot_failure(type, 1);
- return;
- }
-
- u16 ebda_seg = get_ebda_seg();
- bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
- bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
- /* Canonicalize bootseg:bootip */
- bootip = (bootseg & 0x0fff) << 4;
- bootseg &= 0xf000;
+ case IPL_TYPE_CDROM:
+ boot_cdrom();
break;
- }
- case IPL_TYPE_BEV: {
- /* Expansion ROM with a Bootstrap Entry Vector (a far
- * pointer) */
- u32 vector = IPL.table[bootdev].vector;
- bootseg = vector >> 16;
- bootip = vector & 0xffff;
+ case IPL_TYPE_BEV:
+ call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0);
break;
}
- default:
- return;
- }
-
- /* Debugging info */
- dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
-
- memset(&cr, 0, sizeof(cr));
- cr.ip = bootip;
- cr.cs = bootseg;
- // Set the magic number in ax and the boot drive in dl.
- cr.dl = bootdrv;
- cr.ax = 0xaa55;
- call16(&cr);
-}
-
-static void
-do_boot(u16 seq_nr)
-{
- try_boot(seq_nr);
// Boot failed: invoke the boot recovery function
struct bregs br;
+fail:
memset(&br, 0, sizeof(br));
call16_int(0x18, &br);
}