//
// This file may be distributed under the terms of the GNU LGPLv3 license.
-#include "util.h" // irq_enable
+#include "util.h" // dprintf
#include "biosvar.h" // GET_EBDA
#include "config.h" // CONFIG_*
#include "disk.h" // cdrom_boot
#include "bregs.h" // struct bregs
#include "boot.h" // struct ipl_s
#include "cmos.h" // inb_cmos
+#include "paravirt.h"
struct ipl_s IPL;
****************************************************************/
void
-boot_setup()
+boot_setup(void)
{
if (! CONFIG_BOOT)
return;
return;
struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
- ie->type = IPL_TYPE_BEV;
+ ie->type = BCV_TYPE_EXTERNAL;
ie->vector = (seg << 16) | ip;
const char *d = "Legacy option rom";
if (desc)
ie->description = d;
}
-// Add a bcv entry for an ata harddrive
+// Add a bcv entry for an internal harddrive
void
-add_bcv_hd(int driveid, const char *desc)
+add_bcv_internal(struct drive_s *drive_g)
{
if (! CONFIG_BOOT)
return;
return;
struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
- ie->type = IPL_TYPE_HARDDISK;
- ie->vector = driveid;
- ie->description = desc;
+ if (CONFIG_THREADS) {
+ // Add to bcv list with assured drive order.
+ struct ipl_entry_s *end = ie;
+ for (;;) {
+ struct ipl_entry_s *prev = ie - 1;
+ if (prev < IPL.bcv || prev->type != BCV_TYPE_INTERNAL)
+ break;
+ struct drive_s *prevdrive = (void*)prev->vector;
+ if (prevdrive->type < drive_g->type
+ || (prevdrive->type == drive_g->type
+ && prevdrive->cntl_id < drive_g->cntl_id))
+ break;
+ ie--;
+ }
+ if (ie != end)
+ memmove(ie+1, ie, (void*)end-(void*)ie);
+ }
+ ie->type = BCV_TYPE_INTERNAL;
+ ie->vector = (u32)drive_g;
+ ie->description = "";
}
static int
menu_show_floppy(struct ipl_entry_s *ie, int menupos)
{
- if (!FloppyCount)
- return 0;
- return menu_show_default(ie, menupos);
+ int i;
+ for (i = 0; i < Drives.floppycount; i++) {
+ struct drive_s *drive_g = getDrive(EXTTYPE_FLOPPY, i);
+ printf("%d. Floppy [%s]\n", menupos + i, drive_g->desc);
+ }
+ return Drives.floppycount;
}
// Show menu items from BCV list.
int i;
for (i = 0; i < IPL.bcvcount; i++) {
struct ipl_entry_s *ie = &IPL.bcv[i];
+ struct drive_s *drive_g = (void*)ie->vector;
switch (ie->type) {
- case IPL_TYPE_HARDDISK:
- printf("%d. ata%d-%d %s\n", menupos + i
- , ie->vector / 2, ie->vector % 2, ie->description);
+ case BCV_TYPE_INTERNAL:
+ printf("%d. %s\n", menupos + i, drive_g->desc);
break;
default:
menu_show_default(ie, menupos+i);
menu_show_cdrom(struct ipl_entry_s *ie, int menupos)
{
int i;
- for (i = 0; i < ATA.cdcount; i++) {
- int driveid = ATA.idmap[1][i];
- printf("%d. CD-Rom [ata%d-%d %s]\n", menupos + i
- , driveid / 2, driveid % 2, ATA.devices[driveid].model);
+ for (i = 0; i < Drives.cdcount; i++) {
+ struct drive_s *drive_g = getDrive(EXTTYPE_CD, i);
+ printf("%d. CD-Rom [%s]\n", menupos + i, drive_g->desc);
}
- return ATA.cdcount;
+ return Drives.cdcount;
}
// Show coreboot-fs menu item.
menu_show_cbfs(struct ipl_entry_s *ie, int menupos)
{
int count = 0;
+ struct cbfs_file *file = NULL;
for (;;) {
- const char *filename = cbfs_findNprefix("img/", count);
- if (!filename)
+ file = cbfs_findprefix("img/", file);
+ if (!file)
break;
+ const char *filename = cbfs_filename(file);
printf("%d. Payload [%s]\n", menupos + count, &filename[4]);
count++;
if (count > 8)
// Show IPL option menu.
static void
-interactive_bootmenu()
+interactive_bootmenu(void)
{
- if (! CONFIG_BOOTMENU)
+ if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu())
return;
while (get_keystroke(0) >= 0)
int i;
for (i = 0; i < IPL.bevcount; i++) {
struct ipl_entry_s *ie = &IPL.bev[i];
- int sc = 1;
+ int sc;
switch (ie->type) {
case IPL_TYPE_FLOPPY:
sc = menu_show_floppy(ie, menupos);
run_bcv(struct ipl_entry_s *ie)
{
switch (ie->type) {
- case IPL_TYPE_HARDDISK:
- map_drive(ie->vector);
+ case BCV_TYPE_INTERNAL:
+ map_hd_drive((void*)ie->vector);
break;
- case IPL_TYPE_BEV:
+ case BCV_TYPE_EXTERNAL:
call_bcv(ie->vector >> 16, ie->vector & 0xffff);
break;
}
// Prepare for boot - show menu and run bcvs.
void
-boot_prep()
+boot_prep(void)
{
if (! CONFIG_BOOT)
return;
+ // XXX - show available drives?
+
// Allow user to modify BCV/IPL order.
interactive_bootmenu();
+ // Setup floppy boot order
+ int override = IPL.bev[0].subchoice;
+ struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
+ Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override];
+ Drives.idmap[EXTTYPE_FLOPPY][override] = tmp;
+
// Run BCVs
- int override = IPL.bev[1].subchoice;
+ override = IPL.bev[1].subchoice;
if (override < IPL.bcvcount)
run_bcv(&IPL.bcv[override]);
int i;
static void
call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
{
- dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
+ dprintf(1, "Booting from %04x:%04x\n", bootseg, bootip);
struct bregs br;
memset(&br, 0, sizeof(br));
- br.ip = bootip;
- br.cs = bootseg;
+ br.flags = F_IF;
+ br.code = SEGOFF(bootseg, bootip);
// Set the magic number in ax and the boot drive in dl.
br.dl = bootdrv;
br.ax = 0xaa55;
// Read sector
struct bregs br;
memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
br.dl = bootdrv;
br.es = bootseg;
br.ah = 2;
}
u16 ebda_seg = get_ebda_seg();
- u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
+ u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
/* Canonicalize bootseg:bootip */
u16 bootip = (bootseg & 0x0fff) << 4;
call_boot_entry(bootseg, bootip, bootdrv);
}
-// Boot from a CD-ROM
+// Boot from a CBFS payload
static void
boot_cbfs(struct ipl_entry_s *ie)
{
if (! CONFIG_COREBOOT_FLASH)
return;
- const char *filename = cbfs_findNprefix("img/", ie->subchoice);
- if (! filename)
- return;
- cbfs_run_payload(filename);
+ int count = ie->subchoice;
+ struct cbfs_file *file = NULL;
+ for (;;) {
+ file = cbfs_findprefix("img/", file);
+ if (!file)
+ return;
+ if (count--)
+ continue;
+ cbfs_run_payload(file);
+ }
}
static void
printf("No bootable device.\n");
// Loop with irqs enabled - this allows ctrl+alt+delete to work.
for (;;)
- usleep(1000000);
+ biosusleep(1000000);
}
/* Do the loading, and set up vector as a far pointer to the boot
// Boot failed: invoke the boot recovery function
struct bregs br;
memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
call16_int(0x18, &br);
}
// Boot Failure recovery: try the next device.
-void VISIBLE32
-handle_18()
+void VISIBLE32FLAT
+handle_18(void)
{
debug_serial_setup();
debug_enter(NULL, DEBUG_HDL_18);
}
// INT 19h Boot Load Service Entry Point
-void VISIBLE32
-handle_19()
+void VISIBLE32FLAT
+handle_19(void)
{
debug_serial_setup();
debug_enter(NULL, DEBUG_HDL_19);
SET_EBDA(boot_sequence, 0);
do_boot(0);
}
-
-// Ughh - some older gcc compilers have a bug which causes VISIBLE32
-// functions to not be exported as global variables.
-asm(".global handle_18, handle_19");