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:
parent
99192aa450
commit
689c94c815
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
271
src/kernel/boot/platform/bios_ia32/menu.cpp
Normal file
271
src/kernel/boot/platform/bios_ia32/menu.cpp
Normal 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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class Menu;
|
||||
Menu *video_mode_menu();
|
||||
|
||||
extern "C"
|
||||
#endif
|
||||
status_t video_init(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user