diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2008-04-05 15:51:12 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2008-04-05 15:51:12 -0400 |
commit | e0113c99c083d9b812216e120aff9eb9806de91b (patch) | |
tree | 1b861afb2b61f9cc02580161c15da77af38a3397 /src | |
parent | 567e4e3d349150e252f0d2914d6631e766308490 (diff) | |
download | seabios-hppa-e0113c99c083d9b812216e120aff9eb9806de91b.zip seabios-hppa-e0113c99c083d9b812216e120aff9eb9806de91b.tar.gz seabios-hppa-e0113c99c083d9b812216e120aff9eb9806de91b.tar.bz2 |
Forward port new boot menu features from bochs bios.
Support boot menu during last stage of post.
Improve description of option roms.
Support printf of "%.s" to force printing strings on stack.
Enhance memcpy so that it also works in real-mode.
Diffstat (limited to 'src')
-rw-r--r-- | src/biosvar.h | 1 | ||||
-rw-r--r-- | src/boot.c | 50 | ||||
-rw-r--r-- | src/output.c | 8 | ||||
-rw-r--r-- | src/post.c | 5 | ||||
-rw-r--r-- | src/post_menu.c | 81 | ||||
-rw-r--r-- | src/romlayout.S | 1 | ||||
-rw-r--r-- | src/util.c | 15 | ||||
-rw-r--r-- | src/util.h | 6 |
8 files changed, 149 insertions, 18 deletions
diff --git a/src/biosvar.h b/src/biosvar.h index fe957e5..1c791dc 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -213,6 +213,7 @@ struct ipl_s { struct ipl_entry_s table[8]; u16 count; u16 sequence; + u16 bootfirst; }; #define IPL_TYPE_FLOPPY 0x01 @@ -26,17 +26,36 @@ static const char drivetypes[][10]={ "", "Floppy","Hard Disk","CD-Rom", "Network" }; -static void -print_boot_device(u16 type) +void +printf_bootdev(u16 bootdev) { + u16 type = GET_EBDA(ipl.table[bootdev].type); + /* NIC appears as type 0x80 */ if (type == IPL_TYPE_BEV) type = 0x4; if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); - printf("Booting from %s...\n", drivetypes[type]); + printf("%s", drivetypes[type]); + + /* print product string if BEV */ + void *far_description = (void*)GET_EBDA(ipl.table[bootdev].description); + if (type == 4 && far_description != 0) { + char description[33]; + /* first 32 bytes are significant */ + memcpy(MAKE_FARPTR(GET_SEG(SS), &description), far_description, 32); + /* terminate string */ + description[32] = 0; + printf(" [%.s]", description); + } +} - // XXX - latest cvs has BEV description +static void +print_boot_device(u16 bootdev) +{ + printf("Booting from "); + printf_bootdev(bootdev); + printf("...\n"); } //-------------------------------------------------------------------------- @@ -67,14 +86,20 @@ try_boot(u16 seq_nr) SET_EBDA(ipl.sequence, seq_nr); - u16 bootseg; - u8 bootdrv = 0; - u16 bootdev, bootip; - - bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2); + u16 bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2); bootdev |= ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4); bootdev >>= 4 * seq_nr; bootdev &= 0xf; + + /* Read user selected device */ + u16 bootfirst = GET_EBDA(ipl.bootfirst); + if (bootfirst != 0xFFFF) { + bootdev = bootfirst; + /* Reset boot sequence */ + SET_EBDA(ipl.bootfirst, 0xFFFF); + SET_EBDA(ipl.sequence, 0xFFFF); + } + if (bootdev == 0) BX_PANIC("No bootable device.\n"); @@ -85,12 +110,15 @@ try_boot(u16 seq_nr) BX_INFO("Invalid boot device (0x%x)\n", bootdev); return; } - u16 type = GET_EBDA(ipl.table[bootdev].type); /* Do the loading, and set up vector as a far pointer to the boot * address, and bootdrv as the boot drive */ - print_boot_device(type); + print_boot_device(bootdev); + + u16 type = GET_EBDA(ipl.table[bootdev].type); + u16 bootseg, bootip; + u8 bootdrv = 0; struct bregs cr; switch(type) { case IPL_TYPE_FLOPPY: /* FDD */ diff --git a/src/output.c b/src/output.c index 8983f97..3d53613 100644 --- a/src/output.c +++ b/src/output.c @@ -154,6 +154,14 @@ bvprintf(u16 action, const char *fmt, va_list args) val = va_arg(args, int); putc(action, val); break; + case '.': + // Hack to support "%.s" - meaning string on stack. + if (GET_VAR(CS, *(u8*)(n+1)) != 's') + break; + n++; + sarg = va_arg(args, const char *); + puts(action, sarg); + break; case 's': sarg = va_arg(args, const char *); puts_cs(action, sarg); @@ -289,6 +289,7 @@ init_boot_vectors() ebda->ipl.count = ip - ebda->ipl.table; ebda->ipl.sequence = 0xffff; + ebda->ipl.bootfirst = 0xffff; } static void @@ -340,7 +341,7 @@ rom_scan(u32 start, u32 end) u16 desc = *(u16*)&rom[0x1a+0x10]; if (desc) - ip->description = (FARPTR_TO_SEG(rom) << 16) | desc; + ip->description = (u32)MAKE_FARPTR(FARPTR_TO_SEG(rom), desc); ebda->ipl.count++; } @@ -385,6 +386,8 @@ post() rom_scan(0xc8000, 0xe0000); + interactive_bootmenu(); + // reset the memory (some boot loaders such as syslinux suppose // that the memory is set to zero) memset((void*)0x40000, 0, 0x40000); // XXX - shouldn't use globals diff --git a/src/post_menu.c b/src/post_menu.c new file mode 100644 index 0000000..91b18fe --- /dev/null +++ b/src/post_menu.c @@ -0,0 +1,81 @@ +// Menu presented during final phase of "post". +// +// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "biosvar.h" // GET_EBDA +#include "util.h" // usleep + +static u8 +check_for_keystroke() +{ + struct bregs br; + memset(&br, 0, sizeof(br)); + br.ah = 1; + call16_int(0x16, &br); + return !(br.flags & F_ZF); +} + +static u8 +get_keystroke() +{ + struct bregs br; + memset(&br, 0, sizeof(br)); + call16_int(0x16, &br); + return br.ah; +} + +static void +udelay_and_check_for_keystroke(u32 usec, int count) +{ + int i; + for (i = 1; i <= count; i++) { + usleep(usec); + if (check_for_keystroke()) + break; + } +} + +void +interactive_bootmenu() +{ + while (check_for_keystroke()) + get_keystroke(); + + printf("Press F12 for boot menu.\n\n"); + + udelay_and_check_for_keystroke(500000, 5); + if (! check_for_keystroke()) + return; + u8 scan_code = get_keystroke(); + if (scan_code != 0x58) + /* not F12 */ + return; + + while (check_for_keystroke()) + get_keystroke(); + + printf("Select boot device:\n\n"); + + int count = GET_EBDA(ipl.count); + int i; + for (i = 0; i < count; i++) { + printf("%d. ", i+1); + printf_bootdev(i); + printf("\n"); + } + + for (;;) { + scan_code = get_keystroke(); + if (scan_code == 0x01 || scan_code == 0x58) + /* ESC or F12 */ + break; + if (scan_code <= count + 1) { + SET_EBDA(ipl.bootfirst, scan_code - 1); + break; + } + } + printf("\n"); +} diff --git a/src/romlayout.S b/src/romlayout.S index c5f48eb..baf68f3 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -411,6 +411,7 @@ entry_18: IRQ_TRAMPOLINE 10 IRQ_TRAMPOLINE 13 IRQ_TRAMPOLINE 15 + IRQ_TRAMPOLINE 16 IRQ_TRAMPOLINE 18 IRQ_TRAMPOLINE 19 IRQ_TRAMPOLINE 1c @@ -31,15 +31,18 @@ memset(void *s, int c, size_t n) } void * -memcpy(void *d1, const void *s1, size_t len) +memcpy(void *far_d1, const void *far_s1, size_t len) { - u8 *d = d1; - const u8 *s = s1; + u8 *d = far_d1; + u8 *s = (u8*)far_s1; - while (len--) - *d++ = *s++; + while (len--) { + SET_FARPTR(*d, GET_FARPTR(*s)); + d++; + s++; + } - return d1; + return far_d1; } void @@ -154,4 +154,10 @@ void usleep(u32 count); // rombios32.c void rombios32_init(void); +// boot.c +void printf_bootdev(u16 bootdev); + +// post_menu.c +void interactive_bootmenu(); + #endif // util.h |