diff options
author | Helge Deller <deller@gmx.de> | 2022-05-14 22:09:22 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2022-05-14 22:19:36 +0200 |
commit | 1314c8b0bfb8d3b3be145936073ed2fec8adf8f9 (patch) | |
tree | 67d6fbdca847f2ba78f784b12f49bece6a822f45 | |
parent | f5c0ce4a292a41aeee7cca238ceffc66ed4b0de6 (diff) | |
download | seabios-hppa-1314c8b0bfb8d3b3be145936073ed2fec8adf8f9.zip seabios-hppa-1314c8b0bfb8d3b3be145936073ed2fec8adf8f9.tar.gz seabios-hppa-1314c8b0bfb8d3b3be145936073ed2fec8adf8f9.tar.bz2 |
parisc: Add full PDC firmware boot menu
Finally add the real boot menu.
If qemu is started with the "-boot menu=on" option, the PDC boot menu is
shown and the user can then boot any of the available SCSI disc/CDs.
Just type "BOOT" (to boot the default device), or "BOOT FWSCSI.4" (to boot
SCSI device #4).
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | src/boot.c | 24 | ||||
-rw-r--r-- | src/output.c | 2 | ||||
-rw-r--r-- | src/parisc/parisc.c | 217 | ||||
-rw-r--r-- | src/parisc/sticore.h | 2 |
4 files changed, 209 insertions, 36 deletions
@@ -795,6 +795,17 @@ interactive_bootmenu(void) } #if CONFIG_PARISC +int parisc_get_scsi_target(struct drive_s **boot_drive, int target) +{ + struct bootentry_s *pos; + hlist_for_each_entry(pos, &BootList, node) { + if (pos->drive->target != target) + continue; + *boot_drive = pos->drive; + return 1; + } + return 0; +} void find_initial_parisc_boot_drives(struct drive_s **harddisc, struct drive_s **cdrom) { @@ -809,15 +820,13 @@ void find_initial_parisc_boot_drives(struct drive_s **harddisc, struct drive_s *select_parisc_boot_drive(char bootdrive) { - printf("Available boot devices:\n"); + printf(" Available boot devices:\n"); // Show menu items - int maxmenu = 0; struct bootentry_s *pos; hlist_for_each_entry(pos, &BootList, node) { char desc[77]; - maxmenu++; - printf("%d. %s\n", maxmenu + printf(" FWSCSI.%d.0 : %s\n", pos->drive->target , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); } @@ -825,15 +834,14 @@ struct drive_s *select_parisc_boot_drive(char bootdrive) hlist_for_each_entry(pos, &BootList, node) { if (((bootdrive == 'd') && (pos->type == IPL_TYPE_CDROM)) || ((bootdrive == 'c') && (pos->type == IPL_TYPE_HARDDISK))) { - printf("\nBooting from %s\n",pos->description); + // printf("\nBooting from %s\n",pos->description); return pos->drive; } /* -boot order=g-m: machine implementation dependent drives */ if ((bootdrive >= 'g') && (bootdrive <= 'm')) { int scsi_index = (int)bootdrive - 'g'; if (pos->drive->target == scsi_index) { - printf("\nBooting from SCSI target %d: %s\n", - scsi_index, pos->description); + // printf("\nBooting from SCSI target %d: %s\n", scsi_index, pos->description); return pos->drive; } } @@ -842,7 +850,7 @@ struct drive_s *select_parisc_boot_drive(char bootdrive) hlist_for_each_entry(pos, &BootList, node) { if ((pos->type == IPL_TYPE_CDROM) || (pos->type == IPL_TYPE_HARDDISK)) { - printf("\nAuto-Booting from %s\n",pos->description); + // printf("\nAuto-Booting from %s\n",pos->description); return pos->drive; } } diff --git a/src/output.c b/src/output.c index fcbc3f9..b940480 100644 --- a/src/output.c +++ b/src/output.c @@ -90,7 +90,7 @@ screenc(char c) br.bl = 0x07; call16_int(0x10, &br); #else - parisc_screenc(c); + parisc_putchar(c); #endif } diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c index 54616c2..55e8e49 100644 --- a/src/parisc/parisc.c +++ b/src/parisc/parisc.c @@ -120,6 +120,10 @@ int pdc_console; int sti_font; +/* Want PDC boot menu? Enable via qemu "-boot menu=on" option. */ +unsigned int show_boot_menu; +unsigned int interact_ipl; + unsigned long PORT_QEMU_CFG_CTL; unsigned int tlb_entries = 256; unsigned int btlb_entries = 8; @@ -348,6 +352,14 @@ int HPA_is_graphics_device(unsigned long hpa) (hpa == 0xf8000000) || (hpa == 0xfa000000); } +static const char *hpa_device_name(unsigned long hpa, int output) +{ + return HPA_is_graphics_device(hpa) ? "GRAPHICS(1)" : + HPA_is_keyboard_device(hpa) ? "PS2" : + (PARISC_SERIAL_CONSOLE == PORT_SERIAL1) ? + "SERIAL_1.9600.8.none" : "SERIAL_2.9600.8.none"; +} + static unsigned long keep_list[] = { PARISC_KEEP_LIST }; static void remove_from_keep_list(unsigned long hpa) @@ -533,7 +545,7 @@ static void parisc_serial_out(char c) } } -void parisc_screenc(char c) +static void parisc_putchar_internal(char c) { if (HPA_is_graphics_device(PAGE0->mem_cons.hpa)) sti_putc(c); @@ -541,6 +553,29 @@ void parisc_screenc(char c) parisc_serial_out(c); } +/* print char to default PDC output device */ +void parisc_putchar(char c) +{ + if (c == '\n') + parisc_putchar_internal('\r'); + parisc_putchar_internal(c); +} + +/* read char from default PDC input device (serial port / ps2-kbd) */ +static char parisc_getchar(void) +{ + int count; + char c; + + if (HPA_is_serial_device(PAGE0->mem_kbd.hpa)) + count = parisc_serial_in(&c, sizeof(c)); + else + count = lasips2_kbd_in(&c, sizeof(c)); + if (count == 0) + c = 0; + return c; +} + void iodc_log_call(unsigned int *arg, const char *func) { if (pdc_debug & DEBUG_IODC) { @@ -1708,6 +1743,145 @@ extern void find_initial_parisc_boot_drives( struct drive_s **harddisc, struct drive_s **cdrom); extern struct drive_s *select_parisc_boot_drive(char bootdrive); +extern int parisc_get_scsi_target(struct drive_s **boot_drive, int target); + +static void print_menu(void) +{ + printf("\n------- Main Menu -------------------------------------------------------------\n\n" + " Command Description\n" + " ------- -----------\n" + " BOot [PRI|ALT|<path>] Boot from specified path\n" +#if 0 + " PAth [PRI|ALT|CON|KEY] [<path>] Display or modify a path\n" + " SEArch [DIsplay|IPL] [<path>] Search for boot devices\n\n" + " COnfiguration [<command>] Access Configuration menu/commands\n" + " INformation [<command>] Access Information menu/commands\n" + " SERvice [<command>] Access Service menu/commands\n\n" + " DIsplay Redisplay the current menu\n" +#endif + " HElp [<menu>|<command>] Display help for menu or command\n" + " RESET Restart the system\n" + "-------\n"); +} + +/* Copyright (C) 1999 Jason L. Eckhardt (jle@cygnus.com) - taken from palo */ +static char *enter_text(char *txt, int maxchars) +{ + char c; + int pos; + for (pos = 0; txt[pos]; pos++); /* calculate no. of chars */ + if (pos > maxchars) /* if input too long, shorten it */ + { + pos = maxchars; + txt[pos] = '\0'; + } + printf(txt); /* print initial text */ + do + { + c = parisc_getchar(); + if (c == 13) + { /* CR -> finish! */ + if (pos <= maxchars) + txt[pos] = 0; + else + txt[maxchars] = '\0'; + return txt; + }; + if (c == '\b' || c == 127 ) + { /* BS -> delete prev. char */ + if (pos) + { + pos--; + c='\b'; + parisc_putchar(c); + parisc_putchar(' '); + parisc_putchar(c); + } + } else if (c == 21) + { /* CTRL-U */ + while (pos) + { + pos--; + c='\b'; + parisc_putchar(c); + parisc_putchar(' '); + parisc_putchar(c); + } + txt[0] = 0; + } else if ((pos < maxchars) && c >= ' ') + { + txt[pos] = c; + pos++; + parisc_putchar(c); + } + } + while (c != 13); + return txt; +} + +static void menu_loop(void) +{ + int scsi_boot_target; + char input[24]; + char *c; + + // snprintf(input, sizeof(input), "BOOT FWSCSI.%d.0", boot_drive->target); +again: + print_menu(); + +again2: + input[0] = '\0'; + printf("Main Menu: Enter command > "); + /* ask user for boot menu command */ + enter_text(input, sizeof(input)-1); + parisc_putchar('\n'); + + /* convert to uppercase */ + c = input; + while (*c) { + if ((*c >= 'a') && (*c <= 'z')) + *c += 'A'-'a'; + c++; + } + + if (input[0] == 'R' && input[1] == 'E') // RESET? + reset(); + if (input[0] == 'H' && input[1] == 'E') // HELP? + goto again; + if (input[0] != 'B' || input[1] != 'O') { // BOOT? + printf("Unknown command, please try again.\n\n"); + goto again2; + } + // from here on we handle "BOOT PRI/ALT/FWSCSI.x" + c = input; + while (*c && (*c != ' ')) c++; // search space + // preset with default boot target (this is same as "BOOT PRI" + scsi_boot_target = boot_drive->target; + if (c[0] == 'A' && c[1] == 'L' && c[2] == 'T') + scsi_boot_target = parisc_boot_cdrom->target; + while (*c) { + if (*c >= '0' && *c <= '9') { + scsi_boot_target = *c - '0'; + break; + } + c++; + } + + if (!parisc_get_scsi_target(&boot_drive, scsi_boot_target)) { + printf("No FWSCSI.%d.0 device available for boot. Please try again.\n\n", + scsi_boot_target); + goto again2; + } + + printf("Interact with IPL (Y, N, or Cancel)?> "); + input[0] = '\0'; + enter_text(input, 1); + parisc_putchar('\n'); + if (input[0] == 'C' || input[0] == 'c') + goto again2; + if (input[0] == 'Y' || input[0] == 'y') + interact_ipl = 1; +} static int parisc_boot_menu(unsigned long *iplstart, unsigned long *iplend, char bootdrive) @@ -1722,12 +1896,21 @@ static int parisc_boot_menu(unsigned long *iplstart, unsigned long *iplend, }; boot_drive = select_parisc_boot_drive(bootdrive); + + /* enter main menu if booted with "boot menu=on" */ + if (show_boot_menu) + menu_loop(); + else + interact_ipl = 0; + disk_op.drive_fl = boot_drive; if (boot_drive == NULL) { printf("SeaBIOS: No boot device.\n"); return 0; } + printf("\nBooting from FWSCSI.%d.0 ...\n", boot_drive->target); + /* seek to beginning of disc/CD */ disk_op.drive_fl = boot_drive; ret = process_op(&disk_op); @@ -1911,8 +2094,8 @@ void __VISIBLE start_parisc_firmware(void) unsigned long iplstart, iplend; char *str; - unsigned long interactive = (linux_kernel_entry == 1) ? 1:0; char bootdrive = (char)cmdline; // c = hdd, d = CD/DVD + show_boot_menu = (linux_kernel_entry == 1); if (smp_cpus > HPPA_MAX_CPUS) smp_cpus = HPPA_MAX_CPUS; @@ -2069,10 +2252,9 @@ void __VISIBLE start_parisc_firmware(void) printf("SeaBIOS PA-RISC Firmware Version %d\n" "\n" "Duplex Console IO Dependent Code (IODC) revision 1\n" - "\n" - "Memory Test/Initialization Completed\n\n", SEABIOS_HPPA_VERSION); + "\n", SEABIOS_HPPA_VERSION); printf("------------------------------------------------------------------------------\n" - " (c) Copyright 2017-2021 Helge Deller <deller@gmx.de> and SeaBIOS developers.\n" + " (c) Copyright 2017-2022 Helge Deller <deller@gmx.de> and SeaBIOS developers.\n" "------------------------------------------------------------------------------\n\n"); printf( " Processor Speed State Coprocessor State Cache Size\n" " --------- -------- --------------------- ----------------- ----------\n"); @@ -2091,11 +2273,11 @@ void __VISIBLE start_parisc_firmware(void) printf(" Primary boot path: FWSCSI.%d.%d\n" " Alternate boot path: FWSCSI.%d.%d\n" " Console path: %s\n" - " Keyboard path: PS2\n\n", + " Keyboard path: %s\n\n", parisc_boot_harddisc->target, parisc_boot_harddisc->lun, parisc_boot_cdrom->target, parisc_boot_cdrom->lun, - HPA_is_graphics_device(PAGE0->mem_cons.hpa) ? "GRAPHICS(1)" : - ((PARISC_SERIAL_CONSOLE == PORT_SERIAL1) ? "SERIAL_1.9600.8.none" : "SERIAL_2.9600.8.none")); + hpa_device_name(PAGE0->mem_cons.hpa, 1), + hpa_device_name(PAGE0->mem_kbd.hpa, 0)); if (bootdrive == 'c') boot_drive = parisc_boot_harddisc; @@ -2137,23 +2319,6 @@ void __VISIBLE start_parisc_firmware(void) hlt(); /* this ends the emulator */ } -#if 0 - printf("------- Main Menu -------------------------------------------------------------\n\n" - " Command Description\n" - " ------- -----------\n" - " BOot [PRI|ALT|<path>] Boot from specified path\n" - " PAth [PRI|ALT|CON|KEY] [<path>] Display or modify a path\n" - " SEArch [DIsplay|IPL] [<path>] Search for boot devices\n\n" - " COnfiguration [<command>] Access Configuration menu/commands\n" - " INformation [<command>] Access Information menu/commands\n" - " SERvice [<command>] Access Service menu/commands\n\n" - " DIsplay Redisplay the current menu\n" - " HElp [<menu>|<command>] Display help for menu or command\n" - " RESET Restart the system\n" - "-------\n" - "Main Menu: Enter command > "); -#endif - /* check for bootable drives, and load and start IPL bootloader if possible */ if (parisc_boot_menu(&iplstart, &iplend, bootdrive)) { void (*start_ipl)(long interactive, long iplend); @@ -2165,7 +2330,7 @@ void __VISIBLE start_parisc_firmware(void) "Boot IO Dependent Code (IODC) revision 153\n\n" "%s Booted.\n", PAGE0->imm_soft_boot ? "SOFT":"HARD"); start_ipl = (void *) iplstart; - start_ipl(interactive, iplend); + start_ipl(interact_ipl, iplend); } hlt(); /* this ends the emulator */ diff --git a/src/parisc/sticore.h b/src/parisc/sticore.h index 658714b..fff7d15 100644 --- a/src/parisc/sticore.h +++ b/src/parisc/sticore.h @@ -321,6 +321,6 @@ void sti_putc(const char c); extern struct sti_rom sti_proc_rom; extern char _sti_rom_end[]; extern char _sti_rom_start[]; -extern void parisc_screenc(char c); +extern void parisc_putchar(char c); #endif /* STICORE_H */ |