From 689c94c815b10a7f464d009b7660a77fcca5466f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 21 Jun 2004 15:57:03 +0000 Subject: [PATCH] Work in progress of the boot loader menu. You can already use the menu, but your options currently don't have any effect. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8094 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/boot/platform/bios_ia32/Jamfile | 1 + .../boot/platform/bios_ia32/console.cpp | 58 +++- src/kernel/boot/platform/bios_ia32/console.h | 27 ++ src/kernel/boot/platform/bios_ia32/menu.cpp | 271 ++++++++++++++++++ src/kernel/boot/platform/bios_ia32/video.cpp | 29 ++ src/kernel/boot/platform/bios_ia32/video.h | 3 + 6 files changed, 376 insertions(+), 13 deletions(-) create mode 100644 src/kernel/boot/platform/bios_ia32/menu.cpp diff --git a/src/kernel/boot/platform/bios_ia32/Jamfile b/src/kernel/boot/platform/bios_ia32/Jamfile index 29b1762958..fdd528d6f1 100644 --- a/src/kernel/boot/platform/bios_ia32/Jamfile +++ b/src/kernel/boot/platform/bios_ia32/Jamfile @@ -13,6 +13,7 @@ KernelMergeObject boot_platform_bios_ia32.o : <$(SOURCE_GRIST)>console.cpp <$(SOURCE_GRIST)>devices.cpp <$(SOURCE_GRIST)>keyboard.cpp + <$(SOURCE_GRIST)>menu.cpp <$(SOURCE_GRIST)>mmu.cpp <$(SOURCE_GRIST)>cpu.cpp <$(SOURCE_GRIST)>smp_boot.c diff --git a/src/kernel/boot/platform/bios_ia32/console.cpp b/src/kernel/boot/platform/bios_ia32/console.cpp index bdd91ec3b2..d932ab5ab9 100644 --- a/src/kernel/boot/platform/bios_ia32/console.cpp +++ b/src/kernel/boot/platform/bios_ia32/console.cpp @@ -24,22 +24,12 @@ static uint16 *sScreenBase = (uint16 *)0xb8000; static uint32 sScreenWidth = 80; static uint32 sScreenHeight = 24; static uint32 sScreenOffset = 0; +static uint16 sColor = 0x0f00; static Console sInput, sOutput; FILE *stdin, *stdout, *stderr; -static void -clear_screen() -{ - if (gKernelArgs.fb.enabled) - return; - - for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++) - sScreenBase[i] = 0xf20; -} - - static void scroll_up() { @@ -82,7 +72,7 @@ Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferS if (string[0] == '\n') sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth); else - sScreenBase[sScreenOffset++] = 0xf00 | string[0]; + sScreenBase[sScreenOffset++] = sColor | string[0]; if (sScreenOffset >= sScreenWidth * sScreenHeight) scroll_up(); @@ -96,12 +86,54 @@ Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferS // #pragma mark - +void +console_clear_screen(void) +{ + if (gKernelArgs.fb.enabled) + return; + + for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++) + sScreenBase[i] = 0xf20; + + // reset cursor position as well + sScreenOffset = 0; +} + + +int32 +console_width(void) +{ + return sScreenWidth; +} + + +int32 +console_height(void) +{ + return sScreenHeight; +} + + +void +console_set_cursor(int32 x, int32 y) +{ + sScreenOffset = x + y * sScreenWidth; +} + + +void +console_set_color(int32 foreground, int32 background) +{ + sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8; +} + + status_t console_init(void) { // ToDo: make screen size changeable via stage2_args - clear_screen(); + console_clear_screen(); // enable stdio functionality stdin = (FILE *)&sInput; diff --git a/src/kernel/boot/platform/bios_ia32/console.h b/src/kernel/boot/platform/bios_ia32/console.h index b1cb894bdf..645b6d3a53 100644 --- a/src/kernel/boot/platform/bios_ia32/console.h +++ b/src/kernel/boot/platform/bios_ia32/console.h @@ -9,10 +9,37 @@ #include #include + +enum console_color { + BLACK, + NAVY, + GREEN, + TEAL, + MAROON, + PURPLE, + OLIVE, + SILVER, + GREY, + BLUE, + LIME, + AQUA, + RED, + FUCHSIA, + YELLOW, + WHITE +}; + + #ifdef __cplusplus extern "C" { #endif +extern void console_clear_screen(void); +extern int32 console_width(void); +extern int32 console_height(void); +extern void console_set_cursor(int32 x, int32 y); +extern void console_set_color(int32 foreground, int32 background); + extern status_t console_init(void); #ifdef __cplusplus diff --git a/src/kernel/boot/platform/bios_ia32/menu.cpp b/src/kernel/boot/platform/bios_ia32/menu.cpp new file mode 100644 index 0000000000..32cf33872d --- /dev/null +++ b/src/kernel/boot/platform/bios_ia32/menu.cpp @@ -0,0 +1,271 @@ +/* +** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include "keyboard.h" +#include "console.h" +#include "bios.h" +#include "video.h" + +#include +#include + +#include + + +// position +static int32 kFirstLine = 8; +static int32 kOffsetX = 10; + +// colors +static console_color kItemColor = SILVER; +static console_color kSelectedItemColor = WHITE; +static console_color kBackgroundColor = BLACK; +static console_color kSelectedBackgroundColor = SILVER; + + +static void +print_spacing(int32 count) +{ + for (int32 i = 0; i < count; i++) + putchar(' '); +} + + +static void +print_item_at(int32 line, MenuItem *item) +{ + bool selected = item->IsSelected(); + + console_color background = selected ? kSelectedBackgroundColor : kBackgroundColor; + console_color foreground = selected ? kSelectedItemColor : kItemColor; + + console_set_cursor(kOffsetX, line + kFirstLine); + console_set_color(foreground, background); + + size_t length = strlen(item->Label()) + 1; + + if (item->Type() == MENU_ITEM_MARKABLE) { + console_set_color(GREY, background); + printf(" ["); + console_set_color(foreground, background); + printf("%c", item->IsMarked() ? 'x' : ' '); + console_set_color(GREY, background); + printf("] "); + console_set_color(foreground, background); + + length += 4; + } else + printf(" "); + + printf(item->Label()); + + if (item->Submenu() && item->Submenu()->Type() == CHOICE_MENU) { + // show the current choice (if any) + Menu *subMenu = item->Submenu(); + MenuItem *subItem = NULL; + + for (int32 i = subMenu->CountItems(); i-- > 0; ) { + subItem = subMenu->ItemAt(i); + if (subItem != NULL && subItem->IsMarked()) + break; + } + + const char *text = " (Current: "; + printf(text); + length += strlen(text); + + text = subItem != NULL ? subItem->Label() : "None"; + length += strlen(text); + + console_set_color(selected ? GREY : WHITE, background); + + printf(text); + + console_set_color(foreground, background); + putchar(')'); + length++; + } + + print_spacing(console_width() - length - 2*kOffsetX); +} + + +static void +draw_menu(Menu *menu) +{ + console_clear_screen(); + + console_set_cursor(console_width()/2 - 7, 1); + console_set_color(WHITE, BLACK); + printf("Welcome To The"); + + console_set_cursor(console_width()/2 - 8, 2); + console_set_color(WHITE, BLACK); + printf("Haiku Boot Loader"); + + console_set_cursor(console_width()/2 - 12, 4); + console_set_color(GREEN, BLACK); + printf("Copyright 2004 Haiku Inc."); + + if (menu->Title()) { + console_set_cursor(kOffsetX, kFirstLine - 2); + console_set_color(WHITE, GREY); + + printf(" %s", menu->Title()); + print_spacing(console_width() - 1 - strlen(menu->Title()) - 2*kOffsetX); + } + + MenuItemIterator iterator = menu->ItemIterator(); + MenuItem *item; + int32 i = 0; + + console_set_cursor(kOffsetX, kFirstLine); + + while ((item = iterator.Next()) != NULL) { + if (item->Type() == MENU_ITEM_SEPARATOR) { + putchar('\n'); + i++; + continue; + } + + print_item_at(i, item); + i++; + } +} + + +static void +run_menu(Menu *menu) +{ + menu->Show(); + + draw_menu(menu); + + // Get selected entry, or select the last one, if there is none + int32 selected; + MenuItem *item = menu->FindSelected(&selected); + if (item == NULL) { + selected = menu->CountItems() - 1; + item = menu->ItemAt(selected); + if (item != NULL) + item->Select(true); + } + + while (true) { + union key key = wait_for_key(); + + item = menu->ItemAt(selected); + + if (key.code.ascii == 0) { + int32 oldSelected = selected; + + switch (key.code.bios) { + case BIOS_KEY_UP: + while ((item = menu->ItemAt(--selected)) != NULL) { + if (item->Type() != MENU_ITEM_SEPARATOR) + break; + } + if (selected < 0) + selected = menu->CountItems() - 1; + break; + case BIOS_KEY_DOWN: + while ((item = menu->ItemAt(++selected)) != NULL) { + if (item->Type() != MENU_ITEM_SEPARATOR) + break; + } + if (selected >= menu->CountItems()) + selected = 0; + break; + case BIOS_KEY_HOME: + selected = 0; + break; + case BIOS_KEY_END: + selected = menu->CountItems() - 1; + break; + } + + // check if selected has changed + if (selected != oldSelected) { + MenuItem *item = menu->ItemAt(selected); + if (item != NULL) + item->Select(true); + } + } else if (key.code.ascii == 0xd || key.code.ascii == ' ') { + // leave the menu + if (item->Submenu() != NULL) { + menu->Hide(); + + run_menu(item->Submenu()); + + menu->Show(); + draw_menu(menu); + // restore current menu + } else if (item->Type() == MENU_ITEM_MARKABLE) { + // toggle state + item->SetMarked(!item->IsMarked()); + print_item_at(selected, item); + } else if (key.code.ascii == 0xd) { + // the space key does not exit the menu + + if (menu->Type() == CHOICE_MENU) + item->SetMarked(true); + break; + } + } else if (key.code.ascii == 0x1b && menu->Type() != MAIN_MENU) + // escape key was hit + break; + } + + menu->Hide(); +} + + +// #pragma mark - + + +void +platform_add_menus(Menu *menu) +{ + MenuItem *item; + + switch (menu->Type()) { + case MAIN_MENU: + menu->AddItem(item = new MenuItem("Select fail-safe video mode", video_mode_menu())); + break; + case SAFE_MODE_MENU: + menu->AddItem(item = new MenuItem("Don't call the BIOS")); + item->SetType(MENU_ITEM_MARKABLE); + break; + default: + break; + } +} + + +void +platform_update_menu_item(Menu *menu, MenuItem *item) +{ + if (menu->IsHidden()) + return; + + int32 index = menu->IndexOf(item); + if (index == -1) + return; + + print_item_at(index, item); +} + + +void +platform_run_menu(Menu *menu) +{ + platform_switch_to_text_mode(); + + run_menu(menu); + + platform_switch_to_logo(); +} + diff --git a/src/kernel/boot/platform/bios_ia32/video.cpp b/src/kernel/boot/platform/bios_ia32/video.cpp index e286b4ab4b..300959c671 100644 --- a/src/kernel/boot/platform/bios_ia32/video.cpp +++ b/src/kernel/boot/platform/bios_ia32/video.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -272,6 +273,34 @@ platform_switch_to_text_mode(void) // #pragma mark - +Menu * +video_mode_menu() +{ + Menu *menu = new Menu(CHOICE_MENU); + MenuItem *item; + + menu->AddItem(item = new MenuItem("Default")); + item->SetMarked(true); + item->Select(true); + + menu->AddItem(new MenuItem("Standard VGA")); + + if (sVesaCompatible) { + // add VESA modes + menu->AddItem(new MenuItem("1024x768 32bit")); + menu->AddItem(new MenuItem("800x600 16bit")); + menu->AddItem(new MenuItem("800x600 15bit")); + menu->AddItem(new MenuItem("800x600 8bit")); + menu->AddItem(new MenuItem("640x480 8bit")); + } + + menu->AddSeparatorItem(); + menu->AddItem(item = new MenuItem("Return to main manu")); + + return menu; +} + + extern "C" status_t video_init(void) { diff --git a/src/kernel/boot/platform/bios_ia32/video.h b/src/kernel/boot/platform/bios_ia32/video.h index 2a0c3838a6..cf7cd8cba9 100644 --- a/src/kernel/boot/platform/bios_ia32/video.h +++ b/src/kernel/boot/platform/bios_ia32/video.h @@ -6,6 +6,9 @@ #ifdef __cplusplus +class Menu; +Menu *video_mode_menu(); + extern "C" #endif status_t video_init(void);