Annotation of qemu/roms/seabios/src/boot.c, revision 1.1.1.6

1.1       root        1: // Code to load disk image and start system boot.
                      2: //
1.1.1.4   root        3: // Copyright (C) 2008-2010  Kevin O'Connor <[email protected]>
1.1       root        4: // Copyright (C) 2002  MandrakeSoft S.A.
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
                      8: #include "util.h" // dprintf
                      9: #include "biosvar.h" // GET_EBDA
                     10: #include "config.h" // CONFIG_*
                     11: #include "disk.h" // cdrom_boot
                     12: #include "bregs.h" // struct bregs
1.1.1.5   root       13: #include "boot.h" // func defs
1.1       root       14: #include "cmos.h" // inb_cmos
1.1.1.5   root       15: #include "paravirt.h" // romfile_loadfile
                     16: #include "pci.h" //pci_bdf_to_*
1.1       root       17: 
                     18: 
                     19: /****************************************************************
1.1.1.5   root       20:  * Boot priority ordering
1.1       root       21:  ****************************************************************/
                     22: 
1.1.1.5   root       23: static char **Bootorder;
                     24: static int BootorderCount;
                     25: 
                     26: static void
                     27: loadBootOrder(void)
1.1       root       28: {
1.1.1.6 ! root       29:     if (!CONFIG_BOOTORDER)
        !            30:         return;
        !            31: 
1.1.1.5   root       32:     char *f = romfile_loadfile("bootorder", NULL);
                     33:     if (!f)
1.1       root       34:         return;
                     35: 
1.1.1.5   root       36:     int i = 0;
                     37:     BootorderCount = 1;
                     38:     while (f[i]) {
                     39:         if (f[i] == '\n')
                     40:             BootorderCount++;
                     41:         i++;
                     42:     }
                     43:     Bootorder = malloc_tmphigh(BootorderCount*sizeof(char*));
                     44:     if (!Bootorder) {
                     45:         warn_noalloc();
                     46:         free(f);
                     47:         BootorderCount = 0;
                     48:         return;
1.1       root       49:     }
                     50: 
1.1.1.5   root       51:     dprintf(3, "boot order:\n");
                     52:     i = 0;
                     53:     do {
                     54:         Bootorder[i] = f;
                     55:         f = strchr(f, '\n');
                     56:         if (f)
                     57:             *(f++) = '\0';
                     58:         nullTrailingSpace(Bootorder[i]);
                     59:         dprintf(3, "%d: %s\n", i+1, Bootorder[i]);
                     60:         i++;
                     61:     } while (f);
                     62: }
                     63: 
                     64: // See if 'str' starts with 'glob' - if glob contains an '*' character
                     65: // it will match any number of characters in str that aren't a '/' or
                     66: // the next glob character.
                     67: static char *
                     68: glob_prefix(const char *glob, const char *str)
                     69: {
                     70:     for (;;) {
                     71:         if (!*glob && (!*str || *str == '/'))
                     72:             return (char*)str;
                     73:         if (*glob == '*') {
                     74:             if (!*str || *str == '/' || *str == glob[1])
                     75:                 glob++;
                     76:             else
                     77:                 str++;
                     78:             continue;
                     79:         }
                     80:         if (*glob != *str)
                     81:             return NULL;
                     82:         glob++;
                     83:         str++;
1.1       root       84:     }
1.1.1.5   root       85: }
1.1       root       86: 
1.1.1.5   root       87: // Search the bootorder list for the given glob pattern.
                     88: static int
                     89: find_prio(const char *glob)
                     90: {
                     91:     dprintf(1, "Searching bootorder for: %s\n", glob);
                     92:     int i;
                     93:     for (i = 0; i < BootorderCount; i++)
                     94:         if (glob_prefix(glob, Bootorder[i]))
                     95:             return i+1;
                     96:     return -1;
                     97: }
                     98: 
                     99: #define FW_PCI_DOMAIN "/pci@i0cf8"
                    100: 
                    101: static char *
1.1.1.6 ! root      102: build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
1.1.1.5   root      103: {
                    104:     // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2
                    105:     char *p = buf;
1.1.1.6 ! root      106:     if (pci->parent) {
        !           107:         p = build_pci_path(p, max, "pci-bridge", pci->parent);
1.1       root      108:     } else {
1.1.1.6 ! root      109:         if (pci->rootbus)
        !           110:             p += snprintf(p, max, "/pci-root@%x", pci->rootbus);
1.1.1.5   root      111:         p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
1.1       root      112:     }
1.1.1.5   root      113: 
1.1.1.6 ! root      114:     int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf);
1.1.1.5   root      115:     p += snprintf(p, buf+max-p, "/%s@%x", devname, dev);
                    116:     if (fn)
                    117:         p += snprintf(p, buf+max-p, ",%x", fn);
                    118:     return p;
1.1       root      119: }
                    120: 
1.1.1.6 ! root      121: int bootprio_find_pci_device(struct pci_device *pci)
1.1       root      122: {
1.1.1.6 ! root      123:     if (!CONFIG_BOOTORDER)
        !           124:         return -1;
1.1.1.5   root      125:     // Find pci device - for example: /pci@i0cf8/ethernet@5
                    126:     char desc[256];
1.1.1.6 ! root      127:     build_pci_path(desc, sizeof(desc), "*", pci);
1.1.1.5   root      128:     return find_prio(desc);
                    129: }
1.1       root      130: 
1.1.1.6 ! root      131: int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
1.1.1.5   root      132: {
1.1.1.6 ! root      133:     if (!CONFIG_BOOTORDER)
        !           134:         return -1;
        !           135:     if (!pci)
1.1.1.5   root      136:         // support only pci machine for now
                    137:         return -1;
                    138:     // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0
                    139:     char desc[256], *p;
1.1.1.6 ! root      140:     p = build_pci_path(desc, sizeof(desc), "*", pci);
1.1.1.5   root      141:     snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave);
                    142:     return find_prio(desc);
1.1       root      143: }
                    144: 
1.1.1.6 ! root      145: int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid)
1.1       root      146: {
1.1.1.6 ! root      147:     if (!CONFIG_BOOTORDER)
        !           148:         return -1;
        !           149:     if (!pci)
1.1.1.5   root      150:         // support only pci machine for now
                    151:         return -1;
                    152:     // Find floppy - for example: /pci@i0cf8/isa@1/fdc@03f1/floppy@0
                    153:     char desc[256], *p;
1.1.1.6 ! root      154:     p = build_pci_path(desc, sizeof(desc), "isa", pci);
1.1.1.5   root      155:     snprintf(p, desc+sizeof(desc)-p, "/fdc@%04x/floppy@%x", port, fdid);
                    156:     return find_prio(desc);
                    157: }
                    158: 
1.1.1.6 ! root      159: int bootprio_find_pci_rom(struct pci_device *pci, int instance)
1.1.1.5   root      160: {
1.1.1.6 ! root      161:     if (!CONFIG_BOOTORDER)
        !           162:         return -1;
1.1.1.5   root      163:     // Find pci rom - for example: /pci@i0cf8/scsi@3:rom2
                    164:     char desc[256], *p;
1.1.1.6 ! root      165:     p = build_pci_path(desc, sizeof(desc), "*", pci);
1.1.1.5   root      166:     if (instance)
                    167:         snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
                    168:     return find_prio(desc);
                    169: }
                    170: 
                    171: int bootprio_find_named_rom(const char *name, int instance)
                    172: {
1.1.1.6 ! root      173:     if (!CONFIG_BOOTORDER)
        !           174:         return -1;
1.1.1.5   root      175:     // Find named rom - for example: /rom@genroms/linuxboot.bin
                    176:     char desc[256], *p;
                    177:     p = desc + snprintf(desc, sizeof(desc), "/rom@%s", name);
                    178:     if (instance)
                    179:         snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
                    180:     return find_prio(desc);
                    181: }
1.1       root      182: 
1.1.1.6 ! root      183: int bootprio_find_usb(struct pci_device *pci, u64 path)
1.1.1.5   root      184: {
1.1.1.6 ! root      185:     if (!CONFIG_BOOTORDER)
        !           186:         return -1;
1.1.1.5   root      187:     // Find usb - for example: /pci@i0cf8/usb@1,2/hub@1/network@0/ethernet@0
                    188:     int i;
                    189:     char desc[256], *p;
1.1.1.6 ! root      190:     p = build_pci_path(desc, sizeof(desc), "usb", pci);
1.1.1.5   root      191:     for (i=56; i>0; i-=8) {
                    192:         int port = (path >> i) & 0xff;
                    193:         if (port != 0xff)
                    194:             p += snprintf(p, desc+sizeof(desc)-p, "/hub@%x", port);
                    195:     }
                    196:     snprintf(p, desc+sizeof(desc)-p, "/*@%x", (u32)(path & 0xff));
                    197:     return find_prio(desc);
1.1       root      198: }
                    199: 
1.1.1.5   root      200: 
                    201: /****************************************************************
                    202:  * Boot setup
                    203:  ****************************************************************/
                    204: 
                    205: static int CheckFloppySig = 1;
                    206: 
                    207: #define DEFAULT_PRIO           9999
                    208: 
                    209: static int DefaultFloppyPrio = 101;
                    210: static int DefaultCDPrio     = 102;
                    211: static int DefaultHDPrio     = 103;
                    212: static int DefaultBEVPrio    = 104;
                    213: 
1.1       root      214: void
1.1.1.5   root      215: boot_setup(void)
1.1       root      216: {
                    217:     if (! CONFIG_BOOT)
                    218:         return;
                    219: 
1.1.1.5   root      220:     SET_EBDA(boot_sequence, 0xffff);
                    221: 
                    222:     if (!CONFIG_COREBOOT) {
                    223:         // On emulators, get boot order from nvram.
                    224:         if (inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1)
                    225:             CheckFloppySig = 0;
                    226:         u32 bootorder = (inb_cmos(CMOS_BIOS_BOOTFLAG2)
                    227:                          | ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4));
                    228:         DefaultFloppyPrio = DefaultCDPrio = DefaultHDPrio
                    229:             = DefaultBEVPrio = DEFAULT_PRIO;
                    230:         int i;
                    231:         for (i=101; i<104; i++) {
                    232:             u32 val = bootorder & 0x0f;
                    233:             bootorder >>= 4;
                    234:             switch (val) {
                    235:             case 1: DefaultFloppyPrio = i; break;
                    236:             case 2: DefaultHDPrio = i;     break;
                    237:             case 3: DefaultCDPrio = i;     break;
                    238:             case 4: DefaultBEVPrio = i;    break;
                    239:             }
1.1       root      240:         }
                    241:     }
1.1.1.5   root      242: 
                    243:     loadBootOrder();
1.1       root      244: }
                    245: 
                    246: 
                    247: /****************************************************************
1.1.1.5   root      248:  * BootList handling
1.1       root      249:  ****************************************************************/
                    250: 
1.1.1.5   root      251: struct bootentry_s {
                    252:     int type;
                    253:     union {
                    254:         u32 data;
                    255:         struct segoff_s vector;
                    256:         struct drive_s *drive;
                    257:     };
                    258:     int priority;
                    259:     const char *description;
                    260:     struct bootentry_s *next;
                    261: };
                    262: static struct bootentry_s *BootList;
                    263: 
                    264: #define IPL_TYPE_FLOPPY      0x01
                    265: #define IPL_TYPE_HARDDISK    0x02
                    266: #define IPL_TYPE_CDROM       0x03
                    267: #define IPL_TYPE_CBFS        0x20
                    268: #define IPL_TYPE_BEV         0x80
                    269: #define IPL_TYPE_BCV         0x81
                    270: 
                    271: static void
                    272: bootentry_add(int type, int prio, u32 data, const char *desc)
1.1       root      273: {
1.1.1.5   root      274:     if (! CONFIG_BOOT)
                    275:         return;
                    276:     struct bootentry_s *be = malloc_tmp(sizeof(*be));
                    277:     if (!be) {
                    278:         warn_noalloc();
                    279:         return;
                    280:     }
                    281:     be->type = type;
                    282:     be->priority = prio;
                    283:     be->data = data;
                    284:     be->description = desc ?: "?";
                    285:     dprintf(3, "Registering bootable: %s (type:%d prio:%d data:%x)\n"
                    286:             , be->description, type, prio, data);
                    287: 
                    288:     // Add entry in sorted order.
                    289:     struct bootentry_s **pprev;
                    290:     for (pprev = &BootList; *pprev; pprev = &(*pprev)->next) {
                    291:         struct bootentry_s *pos = *pprev;
                    292:         if (be->priority < pos->priority)
                    293:             break;
                    294:         if (be->priority > pos->priority)
                    295:             continue;
                    296:         if (be->type < pos->type)
                    297:             break;
                    298:         if (be->type > pos->type)
                    299:             continue;
                    300:         if (be->type <= IPL_TYPE_CDROM
                    301:             && (be->drive->type < pos->drive->type
                    302:                 || (be->drive->type == pos->drive->type
                    303:                     && be->drive->cntl_id < pos->drive->cntl_id)))
                    304:             break;
                    305:     }
                    306:     be->next = *pprev;
                    307:     *pprev = be;
1.1       root      308: }
                    309: 
1.1.1.5   root      310: // Return the given priority if it's set - defaultprio otherwise.
                    311: static inline int defPrio(int priority, int defaultprio) {
                    312:     return (priority < 0) ? defaultprio : priority;
                    313: }
                    314: 
                    315: // Add a BEV vector for a given pnp compatible option rom.
                    316: void
                    317: boot_add_bev(u16 seg, u16 bev, u16 desc, int prio)
1.1       root      318: {
1.1.1.5   root      319:     bootentry_add(IPL_TYPE_BEV, defPrio(prio, DefaultBEVPrio)
                    320:                   , SEGOFF(seg, bev).segoff
                    321:                   , desc ? MAKE_FLATPTR(seg, desc) : "Unknown");
                    322:     DefaultBEVPrio = DEFAULT_PRIO;
1.1       root      323: }
                    324: 
1.1.1.5   root      325: // Add a bcv entry for an expansion card harddrive or legacy option rom
                    326: void
                    327: boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio)
1.1       root      328: {
1.1.1.5   root      329:     bootentry_add(IPL_TYPE_BCV, defPrio(prio, DEFAULT_PRIO)
                    330:                   , SEGOFF(seg, ip).segoff
                    331:                   , desc ? MAKE_FLATPTR(seg, desc) : "Legacy option rom");
1.1       root      332: }
                    333: 
1.1.1.5   root      334: void
                    335: boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio)
1.1       root      336: {
1.1.1.5   root      337:     bootentry_add(IPL_TYPE_FLOPPY, defPrio(prio, DefaultFloppyPrio)
                    338:                   , (u32)drive_g, desc);
1.1       root      339: }
                    340: 
1.1.1.5   root      341: void
                    342: boot_add_hd(struct drive_s *drive_g, const char *desc, int prio)
1.1       root      343: {
1.1.1.5   root      344:     bootentry_add(IPL_TYPE_HARDDISK, defPrio(prio, DefaultHDPrio)
                    345:                   , (u32)drive_g, desc);
                    346: }
                    347: 
                    348: void
                    349: boot_add_cd(struct drive_s *drive_g, const char *desc, int prio)
                    350: {
                    351:     bootentry_add(IPL_TYPE_CDROM, defPrio(prio, DefaultCDPrio)
                    352:                   , (u32)drive_g, desc);
1.1       root      353: }
                    354: 
1.1.1.5   root      355: // Add a CBFS payload entry
                    356: void
                    357: boot_add_cbfs(void *data, const char *desc, int prio)
                    358: {
                    359:     bootentry_add(IPL_TYPE_CBFS, defPrio(prio, DEFAULT_PRIO), (u32)data, desc);
                    360: }
                    361: 
                    362: 
                    363: /****************************************************************
                    364:  * Boot menu and BCV execution
                    365:  ****************************************************************/
                    366: 
1.1.1.6 ! root      367: #define DEFAULT_BOOTMENU_WAIT 2500
        !           368: 
1.1       root      369: // Show IPL option menu.
                    370: static void
1.1.1.2   root      371: interactive_bootmenu(void)
1.1       root      372: {
                    373:     if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu())
                    374:         return;
                    375: 
                    376:     while (get_keystroke(0) >= 0)
                    377:         ;
                    378: 
                    379:     printf("Press F12 for boot menu.\n\n");
                    380: 
1.1.1.6 ! root      381:     u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
1.1.1.4   root      382:     enable_bootsplash();
1.1.1.6 ! root      383:     int scan_code = get_keystroke(menutime);
1.1.1.4   root      384:     disable_bootsplash();
1.1       root      385:     if (scan_code != 0x86)
                    386:         /* not F12 */
                    387:         return;
                    388: 
                    389:     while (get_keystroke(0) >= 0)
                    390:         ;
                    391: 
                    392:     printf("Select boot device:\n\n");
1.1.1.3   root      393:     wait_threads();
1.1       root      394: 
1.1.1.5   root      395:     // Show menu items
                    396:     struct bootentry_s *pos = BootList;
                    397:     int maxmenu = 0;
                    398:     while (pos) {
                    399:         char desc[60];
                    400:         maxmenu++;
                    401:         printf("%d. %s\n", maxmenu
                    402:                , strtcpy(desc, pos->description, ARRAY_SIZE(desc)));
                    403:         pos = pos->next;
1.1       root      404:     }
                    405: 
1.1.1.5   root      406:     // Get key press
1.1       root      407:     for (;;) {
                    408:         scan_code = get_keystroke(1000);
1.1.1.5   root      409:         if (scan_code >= 1 && scan_code <= maxmenu+1)
1.1       root      410:             break;
                    411:     }
                    412:     printf("\n");
1.1.1.5   root      413:     if (scan_code == 0x01)
                    414:         // ESC
                    415:         return;
                    416: 
                    417:     // Find entry and make top priority.
                    418:     int choice = scan_code - 1;
                    419:     struct bootentry_s **pprev = &BootList;
                    420:     while (--choice)
                    421:         pprev = &(*pprev)->next;
                    422:     pos = *pprev;
                    423:     *pprev = pos->next;
                    424:     pos->next = BootList;
                    425:     BootList = pos;
                    426:     pos->priority = 0;
                    427: }
                    428: 
                    429: // BEV (Boot Execution Vector) list
                    430: struct bev_s {
                    431:     int type;
                    432:     u32 vector;
                    433: };
                    434: static struct bev_s BEV[20];
                    435: static int BEVCount;
                    436: static int HaveHDBoot, HaveFDBoot;
1.1       root      437: 
                    438: static void
1.1.1.5   root      439: add_bev(int type, u32 vector)
1.1       root      440: {
1.1.1.5   root      441:     if (type == IPL_TYPE_HARDDISK && HaveHDBoot++)
                    442:         return;
                    443:     if (type == IPL_TYPE_FLOPPY && HaveFDBoot++)
                    444:         return;
                    445:     if (BEVCount >= ARRAY_SIZE(BEV))
                    446:         return;
                    447:     struct bev_s *bev = &BEV[BEVCount++];
                    448:     bev->type = type;
                    449:     bev->vector = vector;
1.1       root      450: }
                    451: 
                    452: // Prepare for boot - show menu and run bcvs.
                    453: void
1.1.1.2   root      454: boot_prep(void)
1.1       root      455: {
1.1.1.3   root      456:     if (! CONFIG_BOOT) {
                    457:         wait_threads();
1.1       root      458:         return;
1.1.1.3   root      459:     }
1.1       root      460: 
                    461:     // XXX - show available drives?
                    462: 
                    463:     // Allow user to modify BCV/IPL order.
                    464:     interactive_bootmenu();
1.1.1.3   root      465:     wait_threads();
1.1       root      466: 
1.1.1.5   root      467:     // Map drives and populate BEV list
                    468:     struct bootentry_s *pos = BootList;
                    469:     while (pos) {
                    470:         switch (pos->type) {
                    471:         case IPL_TYPE_BCV:
                    472:             call_bcv(pos->vector.seg, pos->vector.offset);
                    473:             add_bev(IPL_TYPE_HARDDISK, 0);
                    474:             break;
                    475:         case IPL_TYPE_FLOPPY:
                    476:             map_floppy_drive(pos->drive);
                    477:             add_bev(IPL_TYPE_FLOPPY, 0);
                    478:             break;
                    479:         case IPL_TYPE_HARDDISK:
                    480:             map_hd_drive(pos->drive);
                    481:             add_bev(IPL_TYPE_HARDDISK, 0);
                    482:             break;
                    483:         case IPL_TYPE_CDROM:
                    484:             map_cd_drive(pos->drive);
                    485:             // NO BREAK
                    486:         default:
                    487:             add_bev(pos->type, pos->data);
                    488:             break;
                    489:         }
                    490:         pos = pos->next;
                    491:     }
                    492: 
                    493:     // If nothing added a floppy/hd boot - add it manually.
                    494:     add_bev(IPL_TYPE_FLOPPY, 0);
                    495:     add_bev(IPL_TYPE_HARDDISK, 0);
1.1       root      496: }
                    497: 
                    498: 
                    499: /****************************************************************
                    500:  * Boot code (int 18/19)
                    501:  ****************************************************************/
                    502: 
                    503: // Jump to a bootup entry point.
                    504: static void
1.1.1.5   root      505: call_boot_entry(struct segoff_s bootsegip, u8 bootdrv)
1.1       root      506: {
1.1.1.5   root      507:     dprintf(1, "Booting from %04x:%04x\n", bootsegip.seg, bootsegip.offset);
1.1       root      508:     struct bregs br;
                    509:     memset(&br, 0, sizeof(br));
                    510:     br.flags = F_IF;
1.1.1.5   root      511:     br.code = bootsegip;
1.1       root      512:     // Set the magic number in ax and the boot drive in dl.
                    513:     br.dl = bootdrv;
                    514:     br.ax = 0xaa55;
                    515:     call16(&br);
                    516: }
                    517: 
                    518: // Boot from a disk (either floppy or harddrive)
                    519: static void
                    520: boot_disk(u8 bootdrv, int checksig)
                    521: {
                    522:     u16 bootseg = 0x07c0;
                    523: 
                    524:     // Read sector
                    525:     struct bregs br;
                    526:     memset(&br, 0, sizeof(br));
                    527:     br.flags = F_IF;
                    528:     br.dl = bootdrv;
                    529:     br.es = bootseg;
                    530:     br.ah = 2;
                    531:     br.al = 1;
                    532:     br.cl = 1;
                    533:     call16_int(0x13, &br);
                    534: 
                    535:     if (br.flags & F_CF) {
                    536:         printf("Boot failed: could not read the boot disk\n\n");
                    537:         return;
                    538:     }
                    539: 
                    540:     if (checksig) {
                    541:         struct mbr_s *mbr = (void*)0;
                    542:         if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
                    543:             printf("Boot failed: not a bootable disk\n\n");
                    544:             return;
                    545:         }
                    546:     }
                    547: 
                    548:     /* Canonicalize bootseg:bootip */
                    549:     u16 bootip = (bootseg & 0x0fff) << 4;
                    550:     bootseg &= 0xf000;
                    551: 
1.1.1.5   root      552:     call_boot_entry(SEGOFF(bootseg, bootip), bootdrv);
1.1       root      553: }
                    554: 
                    555: // Boot from a CD-ROM
                    556: static void
1.1.1.5   root      557: boot_cdrom(struct drive_s *drive_g)
1.1       root      558: {
                    559:     if (! CONFIG_CDROM_BOOT)
                    560:         return;
1.1.1.5   root      561:     printf("Booting from DVD/CD...\n");
                    562: 
                    563:     int status = cdrom_boot(drive_g);
1.1       root      564:     if (status) {
                    565:         printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
                    566:         return;
                    567:     }
                    568: 
                    569:     u16 ebda_seg = get_ebda_seg();
                    570:     u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
                    571:     u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
                    572:     /* Canonicalize bootseg:bootip */
                    573:     u16 bootip = (bootseg & 0x0fff) << 4;
                    574:     bootseg &= 0xf000;
                    575: 
1.1.1.5   root      576:     call_boot_entry(SEGOFF(bootseg, bootip), bootdrv);
1.1       root      577: }
                    578: 
                    579: // Boot from a CBFS payload
                    580: static void
1.1.1.5   root      581: boot_cbfs(struct cbfs_file *file)
1.1       root      582: {
1.1.1.3   root      583:     if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH)
1.1       root      584:         return;
1.1.1.5   root      585:     printf("Booting from CBFS...\n");
                    586:     cbfs_run_payload(file);
1.1       root      587: }
                    588: 
1.1.1.5   root      589: // Boot from a BEV entry on an optionrom.
                    590: static void
                    591: boot_rom(u32 vector)
                    592: {
                    593:     printf("Booting from ROM...\n");
                    594:     struct segoff_s so;
                    595:     so.segoff = vector;
                    596:     call_boot_entry(so, 0);
                    597: }
                    598: 
                    599: // Determine next boot method and attempt a boot using it.
1.1       root      600: static void
                    601: do_boot(u16 seq_nr)
                    602: {
                    603:     if (! CONFIG_BOOT)
                    604:         panic("Boot support not compiled in.\n");
                    605: 
1.1.1.5   root      606:     if (seq_nr >= BEVCount) {
1.1       root      607:         printf("No bootable device.\n");
                    608:         // Loop with irqs enabled - this allows ctrl+alt+delete to work.
                    609:         for (;;)
1.1.1.3   root      610:             wait_irq();
1.1       root      611:     }
                    612: 
1.1.1.5   root      613:     // Boot the given BEV type.
                    614:     struct bev_s *ie = &BEV[seq_nr];
1.1.1.4   root      615:     switch (ie->type) {
1.1       root      616:     case IPL_TYPE_FLOPPY:
1.1.1.5   root      617:         printf("Booting from Floppy...\n");
                    618:         boot_disk(0x00, CheckFloppySig);
1.1       root      619:         break;
                    620:     case IPL_TYPE_HARDDISK:
1.1.1.5   root      621:         printf("Booting from Hard Disk...\n");
1.1       root      622:         boot_disk(0x80, 1);
                    623:         break;
                    624:     case IPL_TYPE_CDROM:
1.1.1.5   root      625:         boot_cdrom((void*)ie->vector);
1.1       root      626:         break;
                    627:     case IPL_TYPE_CBFS:
1.1.1.5   root      628:         boot_cbfs((void*)ie->vector);
1.1       root      629:         break;
                    630:     case IPL_TYPE_BEV:
1.1.1.5   root      631:         boot_rom(ie->vector);
1.1       root      632:         break;
                    633:     }
                    634: 
                    635:     // Boot failed: invoke the boot recovery function
                    636:     struct bregs br;
                    637:     memset(&br, 0, sizeof(br));
                    638:     br.flags = F_IF;
                    639:     call16_int(0x18, &br);
                    640: }
                    641: 
                    642: // Boot Failure recovery: try the next device.
1.1.1.2   root      643: void VISIBLE32FLAT
                    644: handle_18(void)
1.1       root      645: {
                    646:     debug_serial_setup();
                    647:     debug_enter(NULL, DEBUG_HDL_18);
                    648:     u16 ebda_seg = get_ebda_seg();
                    649:     u16 seq = GET_EBDA2(ebda_seg, boot_sequence) + 1;
                    650:     SET_EBDA2(ebda_seg, boot_sequence, seq);
                    651:     do_boot(seq);
                    652: }
                    653: 
                    654: // INT 19h Boot Load Service Entry Point
1.1.1.2   root      655: void VISIBLE32FLAT
                    656: handle_19(void)
1.1       root      657: {
                    658:     debug_serial_setup();
                    659:     debug_enter(NULL, DEBUG_HDL_19);
                    660:     SET_EBDA(boot_sequence, 0);
                    661:     do_boot(0);
                    662: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.