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
This commit is contained in:
Axel Dörfler 2004-06-21 15:57:03 +00:00
parent 99192aa450
commit 689c94c815
6 changed files with 376 additions and 13 deletions

View File

@ -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

View File

@ -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;

View File

@ -9,10 +9,37 @@
#include <boot/vfs.h>
#include <boot/stdio.h>
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

View File

@ -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 <boot/platform.h>
#include <boot/menu.h>
#include <string.h>
// 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();
}

View File

@ -13,6 +13,7 @@
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/menu.h>
#include <boot/kernel_args.h>
#include <string.h>
@ -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)
{

View File

@ -6,6 +6,9 @@
#ifdef __cplusplus
class Menu;
Menu *video_mode_menu();
extern "C"
#endif
status_t video_init(void);