Work in progress of the boot loader menu.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8095 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+311
-12
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
|
** Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the OpenBeOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,18 +10,273 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <util/kernel_cpp.h>
|
||||||
|
#include <boot/menu.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
#include <boot/vfs.h>
|
#include <boot/vfs.h>
|
||||||
#include <boot/platform.h>
|
#include <boot/platform.h>
|
||||||
#include <boot/stdio.h>
|
#include <boot/stdio.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem::MenuItem(const char *label, Menu *subMenu)
|
||||||
|
:
|
||||||
|
fLabel(strdup(label)),
|
||||||
|
fTarget(NULL),
|
||||||
|
fIsMarked(false),
|
||||||
|
fIsSelected(false),
|
||||||
|
fType(MENU_ITEM_STANDARD),
|
||||||
|
fMenu(NULL),
|
||||||
|
fSubMenu(subMenu)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem::~MenuItem()
|
||||||
|
{
|
||||||
|
free(const_cast<char *>(fLabel));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MenuItem::SetTarget(menu_item_hook target)
|
||||||
|
{
|
||||||
|
fTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MenuItem::SetMarked(bool marked)
|
||||||
|
{
|
||||||
|
if (fIsMarked == marked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (marked && fMenu != NULL && fMenu->Type() == CHOICE_MENU) {
|
||||||
|
// unmark previous item
|
||||||
|
MenuItem *markedItem = fMenu->FindMarked();
|
||||||
|
if (markedItem != NULL)
|
||||||
|
markedItem->SetMarked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fIsMarked = marked;
|
||||||
|
|
||||||
|
if (fMenu != NULL)
|
||||||
|
fMenu->Draw(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MenuItem::Select(bool selected)
|
||||||
|
{
|
||||||
|
if (fIsSelected == selected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (selected && fMenu != NULL) {
|
||||||
|
// unselect previous item
|
||||||
|
MenuItem *selectedItem = fMenu->FindSelected();
|
||||||
|
if (selectedItem != NULL)
|
||||||
|
selectedItem->Select(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fIsSelected = selected;
|
||||||
|
|
||||||
|
if (fMenu != NULL)
|
||||||
|
fMenu->Draw(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MenuItem::SetType(menu_item_type type)
|
||||||
|
{
|
||||||
|
fType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MenuItem::SetMenu(Menu *menu)
|
||||||
|
{
|
||||||
|
fMenu = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
Menu::Menu(menu_type type, const char *title)
|
||||||
|
:
|
||||||
|
fTitle(title),
|
||||||
|
fCount(0),
|
||||||
|
fIsHidden(true),
|
||||||
|
fType(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Menu::~Menu()
|
||||||
|
{
|
||||||
|
// take all remaining items with us
|
||||||
|
|
||||||
|
MenuItem *item;
|
||||||
|
while ((item = fItems.RemoveHead()) != NULL) {
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem *
|
||||||
|
Menu::ItemAt(int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= fCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
MenuItemIterator iterator = ItemIterator();
|
||||||
|
MenuItem *item;
|
||||||
|
|
||||||
|
while ((item = iterator.Next()) != NULL) {
|
||||||
|
if (index-- == 0)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
Menu::IndexOf(MenuItem *searchedItem)
|
||||||
|
{
|
||||||
|
MenuItemIterator iterator = ItemIterator();
|
||||||
|
MenuItem *item;
|
||||||
|
int32 index = 0;
|
||||||
|
|
||||||
|
while ((item = iterator.Next()) != NULL) {
|
||||||
|
if (item == searchedItem)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
Menu::CountItems() const
|
||||||
|
{
|
||||||
|
return fCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem *
|
||||||
|
Menu::FindMarked()
|
||||||
|
{
|
||||||
|
MenuItemIterator iterator = ItemIterator();
|
||||||
|
MenuItem *item;
|
||||||
|
|
||||||
|
while ((item = iterator.Next()) != NULL) {
|
||||||
|
if (item->IsMarked())
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem *
|
||||||
|
Menu::FindSelected(int32 *_index)
|
||||||
|
{
|
||||||
|
MenuItemIterator iterator = ItemIterator();
|
||||||
|
MenuItem *item;
|
||||||
|
int32 index = 0;
|
||||||
|
|
||||||
|
while ((item = iterator.Next()) != NULL) {
|
||||||
|
if (item->IsSelected()) {
|
||||||
|
if (_index != NULL)
|
||||||
|
*_index = index;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Menu::AddItem(MenuItem *item)
|
||||||
|
{
|
||||||
|
item->fMenu = this;
|
||||||
|
fItems.Add(item);
|
||||||
|
fCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
user_menu(Directory **_bootVolume)
|
Menu::AddSeparatorItem()
|
||||||
{
|
{
|
||||||
platform_switch_to_text_mode();
|
MenuItem *item = new MenuItem();
|
||||||
|
if (item == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
int32 index = 1;
|
item->SetType(MENU_ITEM_SEPARATOR);
|
||||||
|
|
||||||
|
AddItem(item);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MenuItem *
|
||||||
|
Menu::RemoveItemAt(int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= fCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
MenuItemIterator iterator = ItemIterator();
|
||||||
|
MenuItem *item;
|
||||||
|
|
||||||
|
while ((item = iterator.Next()) != NULL) {
|
||||||
|
if (index-- == 0) {
|
||||||
|
RemoveItem(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Menu::RemoveItem(MenuItem *item)
|
||||||
|
{
|
||||||
|
item->fMenu = NULL;
|
||||||
|
fItems.Remove(item);
|
||||||
|
fCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Menu::Draw(MenuItem *item)
|
||||||
|
{
|
||||||
|
if (!IsHidden())
|
||||||
|
platform_update_menu_item(this, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Menu::Run()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static Menu *
|
||||||
|
add_boot_volume_menu(Directory *bootVolume)
|
||||||
|
{
|
||||||
|
Menu *menu = new Menu(CHOICE_MENU, "Select Boot Volume");
|
||||||
|
MenuItem *item;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
|
|
||||||
if (gRoot->Open(&cookie, O_RDONLY) == B_OK) {
|
if (gRoot->Open(&cookie, O_RDONLY) == B_OK) {
|
||||||
@@ -32,18 +287,62 @@ user_menu(Directory **_bootVolume)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
char name[B_FILE_NAME_LENGTH];
|
char name[B_FILE_NAME_LENGTH];
|
||||||
if (volume->GetName(name, sizeof(name)) == B_OK)
|
if (volume->GetName(name, sizeof(name)) == B_OK) {
|
||||||
printf("%ld) /%s\n", index++, name);
|
menu->AddItem(item = new MenuItem(name));
|
||||||
|
if (volume == bootVolume) {
|
||||||
// ToDo: for now, just choose the first volume as boot volume
|
item->SetMarked(true);
|
||||||
if (*_bootVolume == NULL)
|
item->Select(true);
|
||||||
*_bootVolume = volume;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gRoot->Close(cookie);
|
gRoot->Close(cookie);
|
||||||
}
|
}
|
||||||
puts("(it always tries to boot from the first for now...)");
|
|
||||||
|
|
||||||
platform_switch_to_logo();
|
menu->AddSeparatorItem();
|
||||||
|
menu->AddItem(item = new MenuItem("Rescan volumes"));
|
||||||
|
menu->AddItem(item = new MenuItem("Return to main manu"));
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Menu *
|
||||||
|
add_safe_mode_menu()
|
||||||
|
{
|
||||||
|
Menu *safeMenu = new Menu(SAFE_MODE_MENU, "Safe Mode Options");
|
||||||
|
MenuItem *item;
|
||||||
|
|
||||||
|
safeMenu->AddItem(item = new MenuItem("Disable user add-ons"));
|
||||||
|
item->SetType(MENU_ITEM_MARKABLE);
|
||||||
|
|
||||||
|
platform_add_menus(safeMenu);
|
||||||
|
|
||||||
|
safeMenu->AddSeparatorItem();
|
||||||
|
safeMenu->AddItem(item = new MenuItem("Return to main menu"));
|
||||||
|
|
||||||
|
return safeMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
user_menu(Directory **_bootVolume)
|
||||||
|
{
|
||||||
|
Menu *menu = new Menu(MAIN_MENU);
|
||||||
|
MenuItem *item;
|
||||||
|
|
||||||
|
// Add boot volume
|
||||||
|
menu->AddItem(item = new MenuItem("Select boot volume", add_boot_volume_menu(*_bootVolume)));
|
||||||
|
|
||||||
|
// Add safe mode
|
||||||
|
menu->AddItem(item = new MenuItem("Select safe mode options", add_safe_mode_menu()));
|
||||||
|
|
||||||
|
// Add platform dependent menus
|
||||||
|
platform_add_menus(menu);
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
menu->AddItem(item = new MenuItem("Continue booting"));
|
||||||
|
|
||||||
|
platform_run_menu(menu);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user