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