From 5454291680b11e0580906f4deacfee7e15bedcd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 31 Mar 2005 11:03:44 +0000 Subject: [PATCH] Implemented a simple boot menu to play with (this can be taken over by other boot menu implementations for a start). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12181 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/boot/loader/platform_devices.cpp | 7 +- .../kernel/boot/loader/platform_menu.cpp | 173 ++++++++++++++++-- .../kernel/boot/loader/platform_misc.cpp | 11 +- 3 files changed, 169 insertions(+), 22 deletions(-) diff --git a/src/tests/kernel/boot/loader/platform_devices.cpp b/src/tests/kernel/boot/loader/platform_devices.cpp index 167594e8ba..fea7b0c6e0 100644 --- a/src/tests/kernel/boot/loader/platform_devices.cpp +++ b/src/tests/kernel/boot/loader/platform_devices.cpp @@ -22,6 +22,8 @@ extern int __libc_argc; extern char **__libc_argv; extern const char *__progname; +extern bool gShowMenu; + static status_t get_device(const char *path, Node **_device) @@ -179,11 +181,14 @@ platform_add_block_devices(struct stage2_args *args, NodeList *list) addDevices = false; else if (!strcmp(option, "--no-scsi")) scsi = false; + else if (!strcmp(option, "--menu")) + gShowMenu = true; else { fprintf(stderr, "usage: %s [OPTIONS] [image ...]\n" " --no-devices\tDon't add real devices from /dev/disk\n" " --no-scsi\tDon't add SCSI devices (might be problematic with some\n" - "\t\tUSB mass storage drivers)\n", __progname); + "\t\tUSB mass storage drivers)\n" + " --menu\tShow boot menu\n", __progname); exit(0); } } diff --git a/src/tests/kernel/boot/loader/platform_menu.cpp b/src/tests/kernel/boot/loader/platform_menu.cpp index 4c3192df4c..3b7616586e 100644 --- a/src/tests/kernel/boot/loader/platform_menu.cpp +++ b/src/tests/kernel/boot/loader/platform_menu.cpp @@ -14,12 +14,129 @@ #include +const char *kNormalColor = "\33[0m"; +const char *kDisabledColor = "\33[31m"; // red +const char *kTitleColor = "\33[34m"; // blue + + extern RootFileSystem *gRoot; +bool gShowMenu = false; + + +static void +print_item_at(int32 line, MenuItem *item, bool clearHelp = true) +{ + if (!item->IsEnabled()) + printf("%s ", kDisabledColor); + else + printf("%2ld. ", line); + + if (item->Type() == MENU_ITEM_MARKABLE) { + printf(" ["); + printf("%c", item->IsMarked() ? 'x' : ' '); + printf("] "); + } 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; + } + + printf(" (Current: "); + printf(subItem != NULL ? subItem->Label() : "None"); + putchar(')'); + } + + if (!item->IsEnabled()) + printf(kNormalColor); + putchar('\n'); +} + + +static void +draw_menu(Menu *menu) +{ + printf("\n %s--- ", kTitleColor); + if (menu->Title()) + printf("%s", menu->Title()); + else + printf("Welcome To The Haiku Bootloader"); + printf(" ---%s\n\n", kNormalColor); + + MenuItemIterator iterator = menu->ItemIterator(); + MenuItem *item; + int32 i = 0, selected = -1; + + while ((item = iterator.Next()) != NULL) { + if (item->Type() == MENU_ITEM_SEPARATOR) { + putchar('\n'); + i++; + continue; + } + + if (item->IsSelected()) + selected = i; + + print_item_at(i++, item, false); + } + + printf("\n[%ld]? ", selected); +} + + +bool +dump_devices_hook(Menu *menu, MenuItem *item) +{ + puts("List of known root directories:"); + + void *cookie; + if (gRoot->Open(&cookie, O_RDONLY) == B_OK) { + Directory *directory; + while (gRoot->GetNextNode(cookie, (Node **)&directory) == B_OK) { + char name[256]; + if (directory->GetName(name, sizeof(name)) == B_OK) + printf("%s:: %s (%p)%s\n", kTitleColor, name, directory, kNormalColor); + + void *subCookie; + if (directory->Open(&subCookie, O_RDONLY) == B_OK) { + while (directory->GetNextEntry(subCookie, name, sizeof(name)) == B_OK) { + printf("\t%s\n", name); + } + directory->Close(subCookie); + } + } + gRoot->Close(cookie); + } + + return false; +} + + +// #pragma mark - void platform_add_menus(Menu *menu) { + MenuItem *item; + + switch (menu->Type()) { + case MAIN_MENU: + menu->AddItem(item = new MenuItem("Dump all recognized volumes")); + item->SetTarget(dump_devices_hook); + break; + default: + break; + } } @@ -32,25 +149,47 @@ platform_update_menu_item(Menu *menu, MenuItem *item) void platform_run_menu(Menu *menu) { - puts("List of known root directories:"); + // 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); + } - void *cookie; - if (gRoot->Open(&cookie, O_RDONLY) == B_OK) { - Directory *directory; - while (gRoot->GetNextNode(cookie, (Node **)&directory) == B_OK) { - char name[256]; - if (directory->GetName(name, sizeof(name)) == B_OK) - printf(":: %s (%p)\n", name, directory); + while (true) { + draw_menu(menu); - void *subCookie; - if (directory->Open(&subCookie, O_RDONLY) == B_OK) { - while (directory->GetNextEntry(subCookie, name, sizeof(name)) == B_OK) { - printf("\t%s\n", name); - } - directory->Close(subCookie); - } - } - gRoot->Close(cookie); + char buffer[32]; + if (fgets(buffer, sizeof(buffer), stdin) == NULL) + return; + + if (buffer[0] != '\n') + selected = atoi(buffer); + + item = menu->ItemAt(selected); + + // leave the menu + if (item->Submenu() != NULL) { + menu->Hide(); + + platform_run_menu(item->Submenu()); + if (item->Target() != NULL) + (*item->Target())(menu, item); + + // restore current menu + menu->FindSelected(&selected); + menu->Show(); + } else if (item->Type() == MENU_ITEM_MARKABLE) { + // toggle state + item->SetMarked(!item->IsMarked()); + + if (item->Target() != NULL) + (*item->Target())(menu, item); + } else if (item->Target() == NULL || (*item->Target())(menu, item)) + break; } } diff --git a/src/tests/kernel/boot/loader/platform_misc.cpp b/src/tests/kernel/boot/loader/platform_misc.cpp index 2c5464d233..4e47cafb09 100644 --- a/src/tests/kernel/boot/loader/platform_misc.cpp +++ b/src/tests/kernel/boot/loader/platform_misc.cpp @@ -1,16 +1,19 @@ /* -** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the Haiku License. -*/ + * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ #include +extern bool gShowMenu; + + uint32 platform_boot_options(void) { - return 0; + return gShowMenu ? BOOT_OPTION_MENU: 0; }