X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=seabios.git;a=blobdiff_plain;f=src%2Fboot.c;h=9dd37fd57478d7522fb5251f85f64db88f9b479e;hp=5ae418ca56ed26674bbeabc2da4158a842e17d53;hb=refs%2Fheads%2Fcoreboot;hpb=7bb1584a2657815b1ca5b62d8919bc726dcca092 diff --git a/src/boot.c b/src/boot.c index 5ae418c..9dd37fd 100644 --- a/src/boot.c +++ b/src/boot.c @@ -10,75 +10,191 @@ #include "config.h" // CONFIG_* #include "disk.h" // cdrom_boot #include "bregs.h" // struct bregs -#include "boot.h" // struct ipl_s +#include "boot.h" // func defs #include "cmos.h" // inb_cmos -#include "paravirt.h" - -struct ipl_s IPL; +#include "paravirt.h" // romfile_loadfile +#include "pci.h" //pci_bdf_to_* /**************************************************************** * Boot priority ordering ****************************************************************/ +static char **Bootorder; +static int BootorderCount; + static void loadBootOrder(void) { + if (!CONFIG_BOOTORDER) + return; + char *f = romfile_loadfile("bootorder", NULL); if (!f) return; - int i; - IPL.fw_bootorder_count = 1; + int i = 0; + BootorderCount = 1; while (f[i]) { if (f[i] == '\n') - IPL.fw_bootorder_count++; + BootorderCount++; i++; } - IPL.fw_bootorder = malloc_tmphigh(IPL.fw_bootorder_count*sizeof(char*)); - if (!IPL.fw_bootorder) { + Bootorder = malloc_tmphigh(BootorderCount*sizeof(char*)); + if (!Bootorder) { warn_noalloc(); free(f); + BootorderCount = 0; return; } dprintf(3, "boot order:\n"); i = 0; do { - IPL.fw_bootorder[i] = f; + Bootorder[i] = f; f = strchr(f, '\n'); - if (f) { - *f = '\0'; - f++; - dprintf(3, "%d: %s\n", i, IPL.fw_bootorder[i]); - i++; + if (f) + *(f++) = '\0'; + nullTrailingSpace(Bootorder[i]); + dprintf(3, "%d: %s\n", i+1, Bootorder[i]); + i++; + } while (f); +} + +// See if 'str' starts with 'glob' - if glob contains an '*' character +// it will match any number of characters in str that aren't a '/' or +// the next glob character. +static char * +glob_prefix(const char *glob, const char *str) +{ + for (;;) { + if (!*glob && (!*str || *str == '/')) + return (char*)str; + if (*glob == '*') { + if (!*str || *str == '/' || *str == glob[1]) + glob++; + else + str++; + continue; } - } while(f); + if (*glob != *str) + return NULL; + glob++; + str++; + } } -int bootprio_find_pci_device(int bdf) +// Search the bootorder list for the given glob pattern. +static int +find_prio(const char *glob) { + dprintf(1, "Searching bootorder for: %s\n", glob); + int i; + for (i = 0; i < BootorderCount; i++) + if (glob_prefix(glob, Bootorder[i])) + return i+1; return -1; } -int bootprio_find_ata_device(int bdf, int chanid, int slave) +#define FW_PCI_DOMAIN "/pci@i0cf8" + +static char * +build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) { - return -1; + // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2 + char *p = buf; + if (pci->parent) { + p = build_pci_path(p, max, "pci-bridge", pci->parent); + } else { + if (pci->rootbus) + p += snprintf(p, max, "/pci-root@%x", pci->rootbus); + p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN); + } + + int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf); + p += snprintf(p, buf+max-p, "/%s@%x", devname, dev); + if (fn) + p += snprintf(p, buf+max-p, ",%x", fn); + return p; } -int bootprio_find_fdc_device(int bfd, int port, int fdid) +int bootprio_find_pci_device(struct pci_device *pci) { - return -1; + if (!CONFIG_BOOTORDER) + return -1; + // Find pci device - for example: /pci@i0cf8/ethernet@5 + char desc[256]; + build_pci_path(desc, sizeof(desc), "*", pci); + return find_prio(desc); } -int bootprio_find_pci_rom(int bdf, int instance) +int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave) { - return -1; + if (!CONFIG_BOOTORDER) + return -1; + if (!pci) + // support only pci machine for now + return -1; + // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave); + return find_prio(desc); +} + +int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid) +{ + if (!CONFIG_BOOTORDER) + return -1; + if (!pci) + // support only pci machine for now + return -1; + // Find floppy - for example: /pci@i0cf8/isa@1/fdc@03f1/floppy@0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "isa", pci); + snprintf(p, desc+sizeof(desc)-p, "/fdc@%04x/floppy@%x", port, fdid); + return find_prio(desc); +} + +int bootprio_find_pci_rom(struct pci_device *pci, int instance) +{ + if (!CONFIG_BOOTORDER) + return -1; + // Find pci rom - for example: /pci@i0cf8/scsi@3:rom2 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + if (instance) + snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance); + return find_prio(desc); } int bootprio_find_named_rom(const char *name, int instance) { - return -1; + if (!CONFIG_BOOTORDER) + return -1; + // Find named rom - for example: /rom@genroms/linuxboot.bin + char desc[256], *p; + p = desc + snprintf(desc, sizeof(desc), "/rom@%s", name); + if (instance) + snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance); + return find_prio(desc); +} + +int bootprio_find_usb(struct pci_device *pci, u64 path) +{ + if (!CONFIG_BOOTORDER) + return -1; + // Find usb - for example: /pci@i0cf8/usb@1,2/hub@1/network@0/ethernet@0 + int i; + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "usb", pci); + for (i=56; i>0; i-=8) { + int port = (path >> i) & 0xff; + if (port != 0xff) + p += snprintf(p, desc+sizeof(desc)-p, "/hub@%x", port+1); + } + snprintf(p, desc+sizeof(desc)-p, "/*@%x", (u32)(path & 0xff)+1); + return find_prio(desc); } @@ -165,7 +281,9 @@ bootentry_add(int type, int prio, u32 data, const char *desc) be->type = type; be->priority = prio; be->data = data; - be->description = desc; + be->description = desc ?: "?"; + dprintf(3, "Registering bootable: %s (type:%d prio:%d data:%x)\n" + , be->description, type, prio, data); // Add entry in sorted order. struct bootentry_s **pprev; @@ -208,30 +326,30 @@ boot_add_bev(u16 seg, u16 bev, u16 desc, int prio) void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio) { - bootentry_add(IPL_TYPE_BCV, defPrio(prio, DEFAULT_PRIO) + bootentry_add(IPL_TYPE_BCV, defPrio(prio, DefaultHDPrio) , SEGOFF(seg, ip).segoff , desc ? MAKE_FLATPTR(seg, desc) : "Legacy option rom"); } void -boot_add_floppy(struct drive_s *drive_g, int prio) +boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio) { bootentry_add(IPL_TYPE_FLOPPY, defPrio(prio, DefaultFloppyPrio) - , (u32)drive_g, drive_g->desc); + , (u32)drive_g, desc); } void -boot_add_hd(struct drive_s *drive_g, int prio) +boot_add_hd(struct drive_s *drive_g, const char *desc, int prio) { bootentry_add(IPL_TYPE_HARDDISK, defPrio(prio, DefaultHDPrio) - , (u32)drive_g, drive_g->desc); + , (u32)drive_g, desc); } void -boot_add_cd(struct drive_s *drive_g, int prio) +boot_add_cd(struct drive_s *drive_g, const char *desc, int prio) { bootentry_add(IPL_TYPE_CDROM, defPrio(prio, DefaultCDPrio) - , (u32)drive_g, drive_g->desc); + , (u32)drive_g, desc); } // Add a CBFS payload entry @@ -246,6 +364,8 @@ boot_add_cbfs(void *data, const char *desc, int prio) * Boot menu and BCV execution ****************************************************************/ +#define DEFAULT_BOOTMENU_WAIT 2500 + // Show IPL option menu. static void interactive_bootmenu(void) @@ -258,8 +378,12 @@ interactive_bootmenu(void) printf("Press F12 for boot menu.\n\n"); + u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT); enable_bootsplash(); - int scan_code = get_keystroke(CONFIG_BOOTMENU_WAIT); + if (1 == 1) { + return; + } + int scan_code = get_keystroke(menutime); disable_bootsplash(); if (scan_code != 0x86) /* not F12 */ @@ -305,6 +429,7 @@ interactive_bootmenu(void) pos->priority = 0; } +// BEV (Boot Execution Vector) list struct bev_s { int type; u32 vector; @@ -339,11 +464,14 @@ boot_prep(void) // XXX - show available drives? // Allow user to modify BCV/IPL order. + dprintf(3, "[wurm] bp1\n"); interactive_bootmenu(); + dprintf(3, "[wurm] bp2\n"); wait_threads(); // Map drives and populate BEV list struct bootentry_s *pos = BootList; + dprintf(3, "[wurm] bp3\n"); while (pos) { switch (pos->type) { case IPL_TYPE_BCV: @@ -367,10 +495,12 @@ boot_prep(void) } pos = pos->next; } + dprintf(3, "[wurm] bp4\n"); // If nothing added a floppy/hd boot - add it manually. add_bev(IPL_TYPE_FLOPPY, 0); add_bev(IPL_TYPE_HARDDISK, 0); + dprintf(3, "[wurm] bp5\n"); } @@ -380,13 +510,13 @@ boot_prep(void) // Jump to a bootup entry point. static void -call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv) +call_boot_entry(struct segoff_s bootsegip, u8 bootdrv) { - dprintf(1, "Booting from %04x:%04x\n", bootseg, bootip); + dprintf(1, "Booting from %04x:%04x\n", bootsegip.seg, bootsegip.offset); struct bregs br; memset(&br, 0, sizeof(br)); br.flags = F_IF; - br.code = SEGOFF(bootseg, bootip); + br.code = bootsegip; // Set the magic number in ax and the boot drive in dl. br.dl = bootdrv; br.ax = 0xaa55; @@ -427,21 +557,17 @@ boot_disk(u8 bootdrv, int checksig) u16 bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; - call_boot_entry(bootseg, bootip, bootdrv); + call_boot_entry(SEGOFF(bootseg, bootip), bootdrv); } // Boot from a CD-ROM static void -boot_cdrom(struct bev_s *ie) +boot_cdrom(struct drive_s *drive_g) { if (! CONFIG_CDROM_BOOT) return; - - if (!ie->vector) - return; printf("Booting from DVD/CD...\n"); - struct drive_s *drive_g = (void*)ie->vector; int status = cdrom_boot(drive_g); if (status) { printf("Boot failed: Could not read from CDROM (code %04x)\n", status); @@ -455,19 +581,30 @@ boot_cdrom(struct bev_s *ie) u16 bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; - call_boot_entry(bootseg, bootip, bootdrv); + call_boot_entry(SEGOFF(bootseg, bootip), bootdrv); } // Boot from a CBFS payload static void -boot_cbfs(struct bev_s *ie) +boot_cbfs(struct cbfs_file *file) { if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) return; printf("Booting from CBFS...\n"); - cbfs_run_payload((void*)ie->vector); + cbfs_run_payload(file); +} + +// Boot from a BEV entry on an optionrom. +static void +boot_rom(u32 vector) +{ + printf("Booting from ROM...\n"); + struct segoff_s so; + so.segoff = vector; + call_boot_entry(so, 0); } +// Determine next boot method and attempt a boot using it. static void do_boot(u16 seq_nr) { @@ -493,14 +630,13 @@ do_boot(u16 seq_nr) boot_disk(0x80, 1); break; case IPL_TYPE_CDROM: - boot_cdrom(ie); + boot_cdrom((void*)ie->vector); break; case IPL_TYPE_CBFS: - boot_cbfs(ie); + boot_cbfs((void*)ie->vector); break; case IPL_TYPE_BEV: - printf("Booting from ROM...\n"); - call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0); + boot_rom(ie->vector); break; }