aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2008-04-05 15:51:12 -0400
committerKevin O'Connor <kevin@koconnor.net>2008-04-05 15:51:12 -0400
commite0113c99c083d9b812216e120aff9eb9806de91b (patch)
tree1b861afb2b61f9cc02580161c15da77af38a3397
parent567e4e3d349150e252f0d2914d6631e766308490 (diff)
downloadseabios-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.
-rw-r--r--Makefile2
-rw-r--r--src/biosvar.h1
-rw-r--r--src/boot.c50
-rw-r--r--src/output.c8
-rw-r--r--src/post.c5
-rw-r--r--src/post_menu.c81
-rw-r--r--src/romlayout.S1
-rw-r--r--src/util.c15
-rw-r--r--src/util.h6
9 files changed, 150 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index cb1cdd0..3808086 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ OUT=out/
# Source files
SRC16=floppy.c disk.c system.c clock.c serial.c kbd.c mouse.c output.c \
boot.c ata.c cdrom.c apm.c util.c pcibios.c pci.c
-SRC32=post.c output.c rombios32.c util.c ata.c kbd.c pci.c
+SRC32=post.c output.c rombios32.c util.c ata.c kbd.c pci.c boot.c post_menu.c
TABLESRC=font.c cbt.c floppy_dbt.c
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
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
diff --git a/src/boot.c b/src/boot.c
index c1f8846..53577ec 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -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);
diff --git a/src/post.c b/src/post.c
index 5ba9a29..4734991 100644
--- a/src/post.c
+++ b/src/post.c
@@ -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
diff --git a/src/util.c b/src/util.c
index 438bf75..845609b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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
diff --git a/src/util.h b/src/util.h
index 1566adf..dff1a11 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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