diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-02-08 16:57:22 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-02-08 16:57:22 -0500 |
commit | 71f036d6e31b6281f05a7ea3a9f3105891495c97 (patch) | |
tree | 42dbf59f71cefba0aa8e2a25264091b4335076c2 | |
parent | 9f4e1d9ad54ceb4876c4457907766799ab15f1a3 (diff) | |
download | seabios-hppa-71f036d6e31b6281f05a7ea3a9f3105891495c97.zip seabios-hppa-71f036d6e31b6281f05a7ea3a9f3105891495c97.tar.gz seabios-hppa-71f036d6e31b6281f05a7ea3a9f3105891495c97.tar.bz2 |
Simplify boot code.
Make sure every IPL entry has a description.
Remove output printing helpers - have each caller output what they want.
Add strtcpy function to ensure descriptions don't go over 32 characters.
Breakup code to launch each IPL entry to its own function.
-rw-r--r-- | src/boot.c | 266 | ||||
-rw-r--r-- | src/util.c | 11 | ||||
-rw-r--r-- | src/util.h | 1 |
3 files changed, 119 insertions, 159 deletions
@@ -30,21 +30,24 @@ boot_setup() memset(&IPL, 0, sizeof(IPL)); // Floppy drive - struct ipl_entry_s *ip = &IPL.table[0]; - ip->type = IPL_TYPE_FLOPPY; - ip++; + struct ipl_entry_s *ie = &IPL.table[0]; + ie->type = IPL_TYPE_FLOPPY; + ie->description = "Floppy"; + ie++; // First HDD - ip->type = IPL_TYPE_HARDDISK; - ip++; + ie->type = IPL_TYPE_HARDDISK; + ie->description = "Hard Disk"; + ie++; // CDROM if (CONFIG_CDROM_BOOT) { - ip->type = IPL_TYPE_CDROM; - ip++; + ie->type = IPL_TYPE_CDROM; + ie->description = "CD-Rom"; + ie++; } - IPL.count = ip - IPL.table; + IPL.count = ie - IPL.table; SET_EBDA(boot_sequence, 0xffff); if (CONFIG_COREBOOT) { // XXX - hardcode defaults for coreboot. @@ -72,77 +75,17 @@ add_bev(u16 seg, u16 bev, u16 desc) if (IPL.count >= ARRAY_SIZE(IPL.table)) return; - struct ipl_entry_s *ip = &IPL.table[IPL.count]; - ip->type = IPL_TYPE_BEV; - ip->vector = (seg << 16) | bev; + struct ipl_entry_s *ie = &IPL.table[IPL.count]; + ie->type = IPL_TYPE_BEV; + ie->vector = (seg << 16) | bev; if (desc) - ip->description = MAKE_FLATPTR(seg, desc); + ie->description = MAKE_FLATPTR(seg, desc); IPL.count++; } /**************************************************************** - * Printing helpers - ****************************************************************/ - -static const char drivetypes[][10]={ - "", "Floppy", "Hard Disk", "CD-Rom", "Network" -}; - -// display a device name -static void -printf_bootdev(u16 bootdev) -{ - u16 type = IPL.table[bootdev].type; - - /* NIC appears as type 0x80 */ - if (type == IPL_TYPE_BEV) - type = 0x4; - if (type == 0 || type > 0x4) { - printf("Unknown"); - return; - } - printf("%s", drivetypes[type]); - - /* print product string if BEV */ - char *description_fl = IPL.table[bootdev].description; - if (type == 4 && description_fl != 0) { - char description[33]; - /* first 32 bytes are significant */ - memcpy(description, description_fl, 32); - /* terminate string */ - description[32] = 0; - printf(" [%.s]", description); - } -} - -// display the boot device -static void -print_boot_device(u16 bootdev) -{ - printf("Booting from "); - printf_bootdev(bootdev); - printf("...\n"); -} - -// display the reason why a boot failed -static void -print_boot_failure(u16 type, u8 reason) -{ - printf("Boot failed"); - if (type < 4) { - /* Report the reason too */ - if (reason==0) - printf(": not a bootable disk"); - else - printf(": could not read the boot disk"); - } - printf("\n\n"); -} - - -/**************************************************************** * Boot menu ****************************************************************/ @@ -170,9 +113,10 @@ interactive_bootmenu() int count = IPL.count; int i; for (i = 0; i < count; i++) { - printf("%d. ", i+1); - printf_bootdev(i); - printf("\n"); + struct ipl_entry_s *ie = &IPL.table[i]; + char desc[33]; + printf("%d. %s\n", i+1 + , strtcpy(desc, ie->description, ARRAY_SIZE(desc))); } for (;;) { @@ -197,7 +141,80 @@ interactive_bootmenu() ****************************************************************/ static void -try_boot(u16 seq_nr) +call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv) +{ + dprintf(1, "Booting from %x:%x\n", bootseg, bootip); + + struct bregs br; + memset(&br, 0, sizeof(br)); + br.ip = bootip; + br.cs = bootseg; + // Set the magic number in ax and the boot drive in dl. + br.dl = bootdrv; + br.ax = 0xaa55; + call16(&br); +} + +// Boot from a disk (either floppy or harddrive) +static void +boot_disk(u8 bootdrv, int checksig) +{ + u16 bootseg = 0x07c0; + + // Read sector + struct bregs br; + memset(&br, 0, sizeof(br)); + br.dl = bootdrv; + br.es = bootseg; + br.ah = 2; + br.al = 1; + br.cl = 1; + call16_int(0x13, &br); + + if (br.flags & F_CF) { + printf("Boot failed: could not read the boot disk\n\n"); + return; + } + + if (checksig) { + struct mbr_s *mbr = (void*)0; + if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) { + printf("Boot failed: not a bootable disk\n\n"); + return; + } + } + + /* Canonicalize bootseg:bootip */ + u16 bootip = (bootseg & 0x0fff) << 4; + bootseg &= 0xf000; + + call_boot_entry(bootseg, bootip, bootdrv); +} + +// Boot from a CD-ROM +static void +boot_cdrom() +{ + if (! CONFIG_CDROM_BOOT) + return; + int status = cdrom_boot(); + if (status) { + printf("Boot failed: Could not read from CDROM (code %04x)\n", status); + return; + } + + u16 ebda_seg = get_ebda_seg(); + u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive); + u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment); + /* Canonicalize bootseg:bootip */ + u16 bootip = (bootseg & 0x0fff) << 4; + bootseg &= 0xf000; + + call_boot_entry(bootseg, bootip, bootdrv); +} + +static void +do_boot(u16 seq_nr) { if (! CONFIG_BOOT) BX_PANIC("Boot support not compiled in.\n"); @@ -214,103 +231,34 @@ try_boot(u16 seq_nr) if (bootdev >= IPL.count) { dprintf(1, "Invalid boot device (0x%x)\n", bootdev); - return; + goto fail; } /* Do the loading, and set up vector as a far pointer to the boot * address, and bootdrv as the boot drive */ - print_boot_device(bootdev); + struct ipl_entry_s *ie = &IPL.table[bootdev]; + char desc[33]; + printf("Booting from %s...\n" + , strtcpy(desc, ie->description, ARRAY_SIZE(desc))); - u16 type = IPL.table[bootdev].type; - - u16 bootseg, bootip; - u8 bootdrv = 0; - struct bregs cr; - switch(type) { + switch(ie->type) { case IPL_TYPE_FLOPPY: + boot_disk(0x00, IPL.checkfloppysig); + break; case IPL_TYPE_HARDDISK: - - bootdrv = (type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00; - bootseg = 0x07c0; - - // Read sector - memset(&cr, 0, sizeof(cr)); - cr.dl = bootdrv; - cr.es = bootseg; - cr.ah = 2; - cr.al = 1; - cr.cl = 1; - call16_int(0x13, &cr); - - if (cr.flags & F_CF) { - print_boot_failure(type, 1); - return; - } - - /* Always check the signature on a HDD boot sector; on FDD, - * only do the check if configured for it */ - if (type != IPL_TYPE_FLOPPY || IPL.checkfloppysig) { - struct mbr_s *mbr = (void*)0; - if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) { - print_boot_failure(type, 0); - return; - } - } - - /* Canonicalize bootseg:bootip */ - bootip = (bootseg & 0x0fff) << 4; - bootseg &= 0xf000; + boot_disk(0x80, 1); break; - case IPL_TYPE_CDROM: { - /* CD-ROM */ - if (! CONFIG_CDROM_BOOT) - return; - int status = cdrom_boot(); - if (status) { - printf("CDROM boot failure code : %04x\n", status); - print_boot_failure(type, 1); - return; - } - - u16 ebda_seg = get_ebda_seg(); - bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_drive); - bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment); - /* Canonicalize bootseg:bootip */ - bootip = (bootseg & 0x0fff) << 4; - bootseg &= 0xf000; + case IPL_TYPE_CDROM: + boot_cdrom(); break; - } - case IPL_TYPE_BEV: { - /* Expansion ROM with a Bootstrap Entry Vector (a far - * pointer) */ - u32 vector = IPL.table[bootdev].vector; - bootseg = vector >> 16; - bootip = vector & 0xffff; + case IPL_TYPE_BEV: + call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0); break; } - default: - return; - } - - /* Debugging info */ - dprintf(1, "Booting from %x:%x\n", bootseg, bootip); - - memset(&cr, 0, sizeof(cr)); - cr.ip = bootip; - cr.cs = bootseg; - // Set the magic number in ax and the boot drive in dl. - cr.dl = bootdrv; - cr.ax = 0xaa55; - call16(&cr); -} - -static void -do_boot(u16 seq_nr) -{ - try_boot(seq_nr); // Boot failed: invoke the boot recovery function struct bregs br; +fail: memset(&br, 0, sizeof(br)); call16_int(0x18, &br); } @@ -166,6 +166,17 @@ memmove(void *d, const void *s, size_t len) return d; } +// Copy a string - truncating it if necessary. +char * +strtcpy(char *dest, const char *src, size_t len) +{ + char *d = dest; + while (len-- && *src != '\0') + *d++ = *src++; + *d = '\0'; + return dest; +} + // Wait for 'usec' microseconds with irqs enabled. static void usleep(u32 usec) @@ -74,6 +74,7 @@ void *memcpy(void *d1, const void *s1, size_t len); inline void memcpy_far(u16 d_seg, void *d_far , u16 s_seg, const void *s_far, size_t len); void *memmove(void *d, const void *s, size_t len); +char *strtcpy(char *dest, const char *src, size_t len); struct bregs; inline void call16(struct bregs *callregs); inline void call16big(struct bregs *callregs); |