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

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

unix.superglobalmegacorp.com

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