|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.