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

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

unix.superglobalmegacorp.com

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