[haiku-commits] haiku: hrev46394 - src/system/boot/loader src/add-ons/kernel/file_systems/packagefs/volume headers/private/kernel/boot src/system/boot/loader/file_systems/packagefs

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 20 Nov 2013 16:06:11 +0100 (CET)

hrev46394 adds 5 changesets to branch 'master'
old head: 658491b8984a4e31607c9cebeaca0fdec77d50e2
new head: c04f3a625afa73d870e755e27e1ebdf9ea6c8038
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=c04f3a6+%5E658491b

----------------------------------------------------------------------------

7e7f482: SinglyLinkedList: Missing include

435fb01: DoublyLinkedList: Add Sort()

6c7abe9: boot loader: Menu[Item] API improvements
  
  * Make Menu and MenuItem polymorphic.
  * MenuItem:
    - Make SetMarked() virtual, so it can be overridden.
    - Add SetSubmenu() and Supermenu().
    - Delete the submenu in the destructor.
  * Menu:
    - Add Entered()/Exited() hooks. They frame the time the user navigates
      the menu or any of its submenus. The hooks allow for subclasses
      populating their item list dynamically.
    - Add SortItems().
  * Update boot loader menu copyright text to include 2013, now that it is
    over soon. :-)

f2620e4: boot loader: add_safe_mode_settings(): Make parameter const

c04f3a6: boot loader: Add safe mode blacklist submenu
  
  It's a browser for the system package content, where entries can be
  selected to blacklist them. The selected entries are removed from the
  packagefs instance in the boot loader, so that e.g. selected drivers
  won't be picked up. The paths are also added to the safe mode driver
  settings and will be interpreted when the system packagefs instance is
  mounted by the kernel.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

16 files changed, 865 insertions(+), 71 deletions(-)
headers/private/kernel/boot/PathBlacklist.h      |  72 +++
headers/private/kernel/boot/menu.h               |  16 +-
headers/private/kernel/util/DoublyLinkedList.h   |  29 ++
headers/private/kernel/util/SinglyLinkedList.h   |   3 +
.../packagefs/volume/PackageSettings.cpp         |  60 ++-
.../packagefs/volume/PackageSettings.h           |  18 +-
src/system/boot/loader/Jamfile                   |   1 +
src/system/boot/loader/PathBlacklist.cpp         | 180 ++++++++
.../loader/file_systems/packagefs/packagefs.cpp  |  67 ++-
.../loader/file_systems/packagefs/packagefs.h    |   4 +
src/system/boot/loader/load_driver_settings.cpp  |   2 +-
src/system/boot/loader/load_driver_settings.h    |   2 +-
src/system/boot/loader/main.cpp                  |  14 +-
src/system/boot/loader/menu.cpp                  | 458 +++++++++++++++++--
src/system/boot/loader/menu.h                    |   6 +-
src/system/boot/platform/generic/text_menu.cpp   |   4 +-

############################################################################

Commit:      7e7f482590f37ee66831cb69f993eb42719e7b1c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=7e7f482
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Wed Nov 20 13:06:32 2013 UTC

SinglyLinkedList: Missing include

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/util/SinglyLinkedList.h 
b/headers/private/kernel/util/SinglyLinkedList.h
index ed13417..9598a83 100644
--- a/headers/private/kernel/util/SinglyLinkedList.h
+++ b/headers/private/kernel/util/SinglyLinkedList.h
@@ -8,6 +8,9 @@
 #define KERNEL_UTIL_SINGLY_LINKED_LIST_H
 
 
+#include <SupportDefs.h>
+
+
 #ifdef __cplusplus
 
 // SinglyLinkedListLink

############################################################################

Commit:      435fb01509b257991ebedf9eae099e35b8be48f6
URL:         http://cgit.haiku-os.org/haiku/commit/?id=435fb01
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Wed Nov 20 14:38:20 2013 UTC

DoublyLinkedList: Add Sort()

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/util/DoublyLinkedList.h 
b/headers/private/kernel/util/DoublyLinkedList.h
index 2321689..f796bfa 100644
--- a/headers/private/kernel/util/DoublyLinkedList.h
+++ b/headers/private/kernel/util/DoublyLinkedList.h
@@ -365,6 +365,10 @@ public:
        inline int32 Count() const;
                // O(n)!
 
+       template<typename Less>
+       void Sort(const Less& less);
+               // O(n^2)
+
        inline Iterator GetIterator()                           { return 
Iterator(this); }
        inline ConstIterator GetIterator() const        { return 
ConstIterator(this); }
 
@@ -645,6 +649,31 @@ DOUBLY_LINKED_LIST_CLASS_NAME::Count() const
        return count;
 }
 
+
+DOUBLY_LINKED_LIST_TEMPLATE_LIST
+template<typename Less>
+void
+DOUBLY_LINKED_LIST_CLASS_NAME::Sort(const Less& less)
+{
+       // selection sort
+       Element* tail = Head();
+       while (tail != NULL) {
+               Element* leastElement = tail;
+               Element* element = tail;
+               while ((element = GetNext(element)) != NULL) {
+                       if (less(element, leastElement))
+                               leastElement = element;
+               }
+
+               if (leastElement != tail) {
+                       Remove(leastElement);
+                       InsertBefore(tail, leastElement);
+               } else
+                       tail = GetNext(tail);
+       }
+}
+
+
 // sGetLink
 DOUBLY_LINKED_LIST_TEMPLATE_LIST
 GetLink DOUBLY_LINKED_LIST_CLASS_NAME::sGetLink;

############################################################################

Commit:      6c7abe982939eb2f37df772014db96ad8b5f440a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=6c7abe9
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Wed Nov 20 14:48:35 2013 UTC

boot loader: Menu[Item] API improvements

* Make Menu and MenuItem polymorphic.
* MenuItem:
  - Make SetMarked() virtual, so it can be overridden.
  - Add SetSubmenu() and Supermenu().
  - Delete the submenu in the destructor.
* Menu:
  - Add Entered()/Exited() hooks. They frame the time the user navigates
    the menu or any of its submenus. The hooks allow for subclasses
    populating their item list dynamically.
  - Add SortItems().
* Update boot loader menu copyright text to include 2013, now that it is
  over soon. :-)

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/boot/menu.h 
b/headers/private/kernel/boot/menu.h
index 6b7beb3..dc07cb3 100644
--- a/headers/private/kernel/boot/menu.h
+++ b/headers/private/kernel/boot/menu.h
@@ -30,12 +30,12 @@ class MenuItem : public DoublyLinkedListLinkImpl<MenuItem> {
 public:
                                                                MenuItem(const 
char* label = NULL,
                                                                        Menu* 
subMenu = NULL);
-                                                               ~MenuItem();
+       virtual                                         ~MenuItem();
 
                        void                            
SetTarget(menu_item_hook target);
                        menu_item_hook          Target() const { return 
fTarget; }
 
-                       void                            SetMarked(bool marked);
+       virtual void                            SetMarked(bool marked);
                        bool                            IsMarked() const { 
return fIsMarked; }
 
                        void                            Select(bool selected);
@@ -57,7 +57,11 @@ public:
                        char                            Shortcut() const { 
return fShortcut; }
 
                        const char*                     Label() const { return 
fLabel; }
+
                        Menu*                           Submenu() const { 
return fSubMenu; }
+                       void                            SetSubmenu(Menu* 
subMenu);
+
+                       Menu*                           Supermenu() const { 
return fMenu; }
 
 private:
                        friend class Menu;
@@ -93,10 +97,13 @@ enum menu_type {
 class Menu {
 public:
                                                                Menu(menu_type 
type, const char* title = NULL);
-                                                               ~Menu();
+       virtual                                         ~Menu();
 
                        menu_type                       Type() const { return 
fType; }
 
+       virtual void                            Entered();
+       virtual void                            Exited();
+
                        void                            Hide() { fIsHidden = 
true; }
                        void                            Show() { fIsHidden = 
false; }
                        bool                            IsHidden() const { 
return fIsHidden; }
@@ -131,6 +138,9 @@ public:
                        shortcut_hook           FindShortcut(char key) const;
                        MenuItem*                       FindItemByShortcut(char 
key);
 
+                       void                            SortItems(bool 
(*less)(const MenuItem*,
+                                                                       const 
MenuItem*));
+
                        void                            Run();
 
 private:
diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp
index 38241b6..58e2170 100644
--- a/src/system/boot/loader/menu.cpp
+++ b/src/system/boot/loader/menu.cpp
@@ -51,21 +51,18 @@ MenuItem::MenuItem(const char *label, Menu *subMenu)
        fIsEnabled(true),
        fType(MENU_ITEM_STANDARD),
        fMenu(NULL),
-       fSubMenu(subMenu),
+       fSubMenu(NULL),
        fData(NULL),
        fHelpText(NULL),
        fShortcut(0)
 {
-       if (subMenu != NULL)
-               subMenu->fSuperItem = this;
+       SetSubmenu(subMenu);
 }
 
 
 MenuItem::~MenuItem()
 {
-       if (fSubMenu != NULL)
-               fSubMenu->fSuperItem = NULL;
-
+       delete fSubMenu;
        free(const_cast<char *>(fLabel));
 }
 
@@ -176,6 +173,16 @@ MenuItem::SetShortcut(char key)
 
 
 void
+MenuItem::SetSubmenu(Menu* subMenu)
+{
+       fSubMenu = subMenu;
+
+       if (fSubMenu != NULL)
+               fSubMenu->fSuperItem = this;
+}
+
+
+void
 MenuItem::SetMenu(Menu* menu)
 {
        fMenu = menu;
@@ -210,6 +217,18 @@ Menu::~Menu()
 }
 
 
+void
+Menu::Entered()
+{
+}
+
+
+void
+Menu::Exited()
+{
+}
+
+
 MenuItem*
 Menu::ItemAt(int32 index)
 {
@@ -398,6 +417,13 @@ Menu::FindItemByShortcut(char key)
 
 
 void
+Menu::SortItems(bool (*less)(const MenuItem*, const MenuItem*))
+{
+       fItems.Sort(less);
+}
+
+
+void
 Menu::Run()
 {
        platform_run_menu(this);
diff --git a/src/system/boot/platform/generic/text_menu.cpp 
b/src/system/boot/platform/generic/text_menu.cpp
index 502db27..605f8da 100644
--- a/src/system/boot/platform/generic/text_menu.cpp
+++ b/src/system/boot/platform/generic/text_menu.cpp
@@ -209,7 +209,7 @@ draw_menu(Menu *menu)
        print_centered(2, "Haiku Boot Loader");
 
        console_set_color(kCopyrightColor, kBackgroundColor);
-       print_centered(4, "Copyright 2004-2012 Haiku Inc.");
+       print_centered(4, "Copyright 2004-2013 Haiku, Inc.");
 
        if (menu->Title()) {
                console_set_cursor(kOffsetX, kFirstLine - 2);
@@ -390,6 +390,7 @@ static void
 run_menu(Menu* menu)
 {
        sMenuOffset = 0;
+       menu->Entered();
        menu->Show();
 
        draw_menu(menu);
@@ -481,6 +482,7 @@ run_menu(Menu* menu)
        }
 
        menu->Hide();
+       menu->Exited();
 }
 
 

############################################################################

Commit:      f2620e47140215edf4100aeab02e99688744cf26
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f2620e4
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Wed Nov 20 14:49:04 2013 UTC

boot loader: add_safe_mode_settings(): Make parameter const

----------------------------------------------------------------------------

diff --git a/src/system/boot/loader/load_driver_settings.cpp 
b/src/system/boot/loader/load_driver_settings.cpp
index cec73ca..65aca1d 100644
--- a/src/system/boot/loader/load_driver_settings.cpp
+++ b/src/system/boot/loader/load_driver_settings.cpp
@@ -125,7 +125,7 @@ add_stage2_driver_settings(stage2_args* args)
 
 
 status_t
-add_safe_mode_settings(char* settings)
+add_safe_mode_settings(const char* settings)
 {
        if (settings == NULL || settings[0] == '\0')
                return B_OK;
diff --git a/src/system/boot/loader/load_driver_settings.h 
b/src/system/boot/loader/load_driver_settings.h
index a5ad2f8..02ae17c 100644
--- a/src/system/boot/loader/load_driver_settings.h
+++ b/src/system/boot/loader/load_driver_settings.h
@@ -9,7 +9,7 @@
 #include <boot/vfs.h>
 
 
-extern status_t add_safe_mode_settings(char *buffer);
+extern status_t add_safe_mode_settings(const char *buffer);
 extern status_t add_stage2_driver_settings(stage2_args *args);
 extern status_t load_driver_settings(stage2_args *args, Directory *volume);
 

############################################################################

Revision:    hrev46394
Commit:      c04f3a625afa73d870e755e27e1ebdf9ea6c8038
URL:         http://cgit.haiku-os.org/haiku/commit/?id=c04f3a6
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Wed Nov 20 14:59:46 2013 UTC

boot loader: Add safe mode blacklist submenu

It's a browser for the system package content, where entries can be
selected to blacklist them. The selected entries are removed from the
packagefs instance in the boot loader, so that e.g. selected drivers
won't be picked up. The paths are also added to the safe mode driver
settings and will be interpreted when the system packagefs instance is
mounted by the kernel.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/boot/PathBlacklist.h 
b/headers/private/kernel/boot/PathBlacklist.h
new file mode 100644
index 0000000..851a785
--- /dev/null
+++ b/headers/private/kernel/boot/PathBlacklist.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef KERNEL_BOOT_PATH_BLACKLIST_H
+#define KERNEL_BOOT_PATH_BLACKLIST_H
+
+
+#include <string.h>
+
+#include <util/SinglyLinkedList.h>
+
+
+class BlacklistedPath : public SinglyLinkedListLinkImpl<BlacklistedPath> {
+public:
+                                                               
BlacklistedPath();
+                                                               
~BlacklistedPath();
+
+                       bool                            SetTo(const char* path);
+
+                       bool                            Append(const char* 
component);
+
+                       const char*                     Path() const
+                                                                       { 
return fPath != NULL ? fPath : ""; }
+
+                       size_t                          Length() const
+                                                                       { 
return fLength; }
+
+                       bool                            operator==(const char* 
path) const
+                                                                       { 
return strcmp(Path(), path) == 0; }
+
+private:
+                       bool                            _Resize(size_t length, 
bool keepData);
+
+private:
+                       char*                           fPath;
+                       size_t                          fLength;
+                       size_t                          fCapacity;
+};
+
+
+class PathBlacklist {
+public:
+                       typedef SinglyLinkedList<BlacklistedPath>::Iterator 
Iterator;
+
+public:
+                                                               PathBlacklist();
+                                                               
~PathBlacklist();
+
+                       bool                            Add(const char* path);
+                       void                            Remove(const char* 
path);
+                       bool                            Contains(const char* 
path) const;
+                       void                            MakeEmpty();
+
+                       bool                            IsEmpty() const
+                                                                       { 
return fPaths.IsEmpty(); }
+
+                       Iterator                        GetIterator() const
+                                                                       { 
return fPaths.GetIterator(); }
+
+private:
+                       BlacklistedPath*        _FindPath(const char* path) 
const;
+
+private:
+                       typedef SinglyLinkedList<BlacklistedPath> PathList;
+
+private:
+                       PathList                        fPaths;
+};
+
+
+#endif // KERNEL_BOOT_PATH_BLACKLIST_H
diff --git 
a/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.cpp 
b/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.cpp
index 1868b7b..54b2984 100644
--- a/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.cpp
+++ b/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.cpp
@@ -16,6 +16,9 @@
 #include "DebugSupport.h"
 
 
+static const char* const kEntryBlacklistParameterName = "EntryBlacklist";
+
+
 // #pragma mark - PackageSettingsItem
 
 
@@ -39,14 +42,21 @@ PackageSettingsItem::~PackageSettingsItem()
 
 
 status_t
-PackageSettingsItem::Init(const driver_parameter& parameter)
+PackageSettingsItem::Init(const char* name)
 {
-       if (!fName.SetTo(parameter.values[0]) || fEntries.Init() != B_OK)
+       if (!fName.SetTo(name) || fEntries.Init() != B_OK)
                RETURN_ERROR(B_NO_MEMORY);
+       return B_OK;
+}
 
-       for (int i = 0; i < parameter.parameter_count; i++) {
-               const driver_parameter& subParameter = parameter.parameters[i];
-               if (strcmp(subParameter.name, "EntryBlacklist") != 0)
+
+status_t
+PackageSettingsItem::ApplySettings(const driver_parameter* parameters,
+       int parameterCount)
+{
+       for (int i = 0; i < parameterCount; i++) {
+               const driver_parameter& subParameter = parameters[i];
+               if (strcmp(subParameter.name, kEntryBlacklistParameterName) != 
0)
                        continue;
 
                status_t error = _AddBlackListedEntries(subParameter);
@@ -165,6 +175,22 @@ PackageSettings::Load(dev_t mountPointDeviceID, ino_t 
mountPointNodeID,
        if (error != B_OK)
                RETURN_ERROR(error);
 
+       // First get the safe mode options. Those apply to the system package.
+       if (mountType == PACKAGE_FS_MOUNT_TYPE_SYSTEM) {
+               void* settingsHandle = 
load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
+               if (settingsHandle != NULL) {
+                       if (const driver_settings* settings
+                                       = get_driver_settings(settingsHandle)) {
+                               error = _AddPackageSettingsItem("haiku", 
settings->parameters,
+                                       settings->parameter_count);
+                               // abort only in case of serious issues (memory 
shortage)
+                               if (error == B_NO_MEMORY)
+                                       return error;
+                       }
+                       unload_driver_settings(settingsHandle);
+               }
+       }
+
        // get the mount point relative settings file path
        const char* settingsFilePath = mountType == PACKAGE_FS_MOUNT_TYPE_HOME
                ? kUserSettingsGlobalDirectory "/packages"
@@ -201,7 +227,8 @@ PackageSettings::Load(dev_t mountPointDeviceID, ino_t 
mountPointNodeID,
                        continue;
                }
 
-               error = _AddPackageSettingsItem(parameter);
+               error = _AddPackageSettingsItem(parameter.values[0],
+                       parameter.parameters, parameter.parameter_count);
                // abort only in case of serious issues (memory shortage)
                if (error == B_NO_MEMORY)
                        return error;
@@ -219,14 +246,21 @@ PackageSettings::PackageItemFor(const String& name) const
 
 
 status_t
-PackageSettings::_AddPackageSettingsItem(const driver_parameter& parameter)
+PackageSettings::_AddPackageSettingsItem(const char* name,
+       const driver_parameter* parameters, int parameterCount)
 {
-       PackageSettingsItem* packageItem = new(std::nothrow) 
PackageSettingsItem;
-       if (packageItem == NULL || packageItem->Init(parameter) != B_OK) {
-               delete packageItem;
-               RETURN_ERROR(B_NO_MEMORY);
+       // get/create the package item
+       PackageSettingsItem* packageItem = 
fPackageItems.Lookup(StringKey(name));
+       if (packageItem == NULL) {
+               packageItem = new(std::nothrow) PackageSettingsItem;
+               if (packageItem == NULL || packageItem->Init(name) != B_OK) {
+                       delete packageItem;
+                       RETURN_ERROR(B_NO_MEMORY);
+               }
+
+               fPackageItems.Insert(packageItem);
        }
 
-       fPackageItems.Insert(packageItem);
-       return B_OK;
+       // apply the settings
+       return packageItem->ApplySettings(parameters, parameterCount);
 }
diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.h 
b/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.h
index a1654e6..eea56e1 100644
--- a/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.h
+++ b/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.h
@@ -9,7 +9,7 @@
 #include <packagefs.h>
 #include <util/OpenHashTable.h>
 
-#include "String.h"
+#include "StringKey.h"
 
 
 struct driver_parameter;
@@ -102,7 +102,10 @@ public:
                                                                
PackageSettingsItem();
                                                                
~PackageSettingsItem();
 
-                       status_t                        Init(const 
driver_parameter& parameter);
+                       status_t                        Init(const char* name);
+                       status_t                        ApplySettings(
+                                                                       const 
driver_parameter* parameters,
+                                                                       int 
parameterCount);
 
                        const String&           Name() const
                                                                        { 
return fName; }
@@ -158,10 +161,10 @@ private:
 
 
 struct PackageSettingsItemHashDefinition {
-       typedef String                          KeyType;
+       typedef StringKey                       KeyType;
        typedef PackageSettingsItem     ValueType;
 
-       size_t HashKey(const String& key) const
+       size_t HashKey(const StringKey& key) const
        {
                return key.Hash();
        }
@@ -171,7 +174,7 @@ struct PackageSettingsItemHashDefinition {
                return HashKey(value->Name());
        }
 
-       bool Compare(const String& key, const PackageSettingsItem* value) const
+       bool Compare(const StringKey& key, const PackageSettingsItem* value) 
const
        {
                return key == value->Name();
        }
@@ -199,8 +202,9 @@ private:
                                PackageItemTable;
 
 private:
-                       status_t                        _AddPackageSettingsItem(
-                                                                       const 
driver_parameter& parameter);
+                       status_t                        
_AddPackageSettingsItem(const char* name,
+                                                                       const 
driver_parameter* parameters,
+                                                                       int 
parameterCount);
 
 private:
                        PackageItemTable        fPackageItems;
diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile
index 1b24a2e..1f2b0bd 100644
--- a/src/system/boot/loader/Jamfile
+++ b/src/system/boot/loader/Jamfile
@@ -56,6 +56,7 @@ UsePrivateHeaders shared storage ;
 
 
 BootStaticLibrary boot_loader :
+       PathBlacklist.cpp
        elf.cpp
        heap.cpp
        kernel_args.cpp
diff --git a/src/system/boot/loader/PathBlacklist.cpp 
b/src/system/boot/loader/PathBlacklist.cpp
new file mode 100644
index 0000000..82822cc
--- /dev/null
+++ b/src/system/boot/loader/PathBlacklist.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <boot/PathBlacklist.h>
+
+#include <stdlib.h>
+
+#include <algorithm>
+
+
+// #pragma mark - BlacklistedPath
+
+
+BlacklistedPath::BlacklistedPath()
+       :
+       fPath(NULL),
+       fLength(0),
+       fCapacity(0)
+{
+}
+
+
+BlacklistedPath::~BlacklistedPath()
+{
+       free(fPath);
+}
+
+
+bool
+BlacklistedPath::SetTo(const char* path)
+{
+       size_t length = strlen(path);
+       if (length > 0 && path[length - 1] == '/')
+               length--;
+
+       if (!_Resize(length, false))
+               return false;
+
+       if (length > 0) {
+               memcpy(fPath, path, length);
+               fPath[length] = '\0';
+       }
+
+       return true;
+}
+
+
+bool
+BlacklistedPath::Append(const char* component)
+{
+       size_t componentLength = strlen(component);
+       if (componentLength > 0 && component[componentLength - 1] == '/')
+               componentLength--;
+       if (componentLength == 0)
+               return true;
+
+       size_t oldLength = fLength;
+       size_t length = (fLength > 0 ? fLength + 1 : 0) + componentLength;
+       if (!_Resize(length, true))
+               return false;
+
+       if (oldLength > 0)
+               fPath[oldLength++] = '/';
+       memcpy(fPath + oldLength, component, componentLength);
+       return true;
+}
+
+
+bool
+BlacklistedPath::_Resize(size_t length, bool keepData)
+{
+       if (length == 0) {
+               free(fPath);
+               fPath = NULL;
+               fLength = 0;
+               fCapacity = 0;
+               return true;
+       }
+
+       if (length < fCapacity) {
+               fPath[length] = '\0';
+               fLength = length;
+               return true;
+       }
+
+       size_t capacity = std::max(length + 1, 2 * fCapacity);
+       capacity = std::max(capacity, size_t(32));
+
+       char* path;
+       if (fLength > 0 && keepData) {
+               path = (char*)realloc(fPath, capacity);
+               if (path == NULL)
+                       return false;
+       } else {
+               path = (char*)malloc(capacity);
+               if (path == NULL)
+                       return false;
+               free(fPath);
+       }
+
+       fPath = path;
+       fPath[length] = '\0';
+       fLength = length;
+       fCapacity = capacity;
+       return true;
+}
+
+
+// #pragma mark - PathBlacklist
+
+
+PathBlacklist::PathBlacklist()
+{
+}
+
+
+PathBlacklist::~PathBlacklist()
+{
+       MakeEmpty();
+}
+
+
+bool
+PathBlacklist::Add(const char* path)
+{
+       BlacklistedPath* blacklistedPath = _FindPath(path);
+       if (blacklistedPath != NULL)
+               return true;
+
+       blacklistedPath = new(std::nothrow) BlacklistedPath;
+       if (blacklistedPath == NULL || !blacklistedPath->SetTo(path)) {
+               delete blacklistedPath;
+               return false;
+       }
+
+       fPaths.Add(blacklistedPath);
+       return true;
+}
+
+
+void
+PathBlacklist::Remove(const char* path)
+{
+       BlacklistedPath* blacklistedPath = _FindPath(path);
+       if (blacklistedPath != NULL) {
+               fPaths.Remove(blacklistedPath);
+               delete blacklistedPath;
+       }
+}
+
+
+bool
+PathBlacklist::Contains(const char* path) const
+{
+       return _FindPath(path) != NULL;
+}
+
+
+void
+PathBlacklist::MakeEmpty()
+{
+       while (BlacklistedPath* blacklistedPath = fPaths.RemoveHead())
+               delete blacklistedPath;
+}
+
+
+BlacklistedPath*
+PathBlacklist::_FindPath(const char* path) const
+{
+       for (PathList::Iterator it = fPaths.GetIterator(); it.HasNext();) {
+               BlacklistedPath* blacklistedPath = it.Next();
+               if (*blacklistedPath == path)
+                       return blacklistedPath;
+       }
+
+       return NULL;
+}
diff --git a/src/system/boot/loader/file_systems/packagefs/packagefs.cpp 
b/src/system/boot/loader/file_systems/packagefs/packagefs.cpp
index 53d75ad..5223662 100644
--- a/src/system/boot/loader/file_systems/packagefs/packagefs.cpp
+++ b/src/system/boot/loader/file_systems/packagefs/packagefs.cpp
@@ -23,6 +23,7 @@
 
 #include <Referenceable.h>
 
+#include <boot/PathBlacklist.h>
 #include <boot/platform.h>
 
 #include "PackageSettingsItem.h"
@@ -46,10 +47,10 @@ using namespace BPackageKit::BHPKG;
 using BPackageKit::BHPKG::BPrivate::PackageFileHeapReader;
 using BPackageKit::BHPKG::BPrivate::PackageReaderImpl;
 
-using PackageFS::PackageSettingsItem;
+using namespace PackageFS;
 
 
-namespace {
+namespace PackageFS {
 
 
 struct PackageDirectory;
@@ -120,6 +121,10 @@ struct PackageNode : DoublyLinkedListLinkImpl<PackageNode> 
{
                return fModifiedTime;
        }
 
+       virtual void RemoveEntry(const char* path)
+       {
+       }
+
 protected:
        PackageVolume*          fVolume;
        PackageDirectory*       fParentDirectory;
@@ -226,19 +231,47 @@ struct PackageDirectory : PackageNode {
                if (strcmp(name, "..") == 0)
                        return fParentDirectory;
 
+               return _LookupChild(name, strlen(name));
+       }
+
+       virtual void RemoveEntry(const char* path)
+       {
+               const char* componentEnd = strchr(path, '/');
+               if (componentEnd == NULL)
+                       componentEnd = path + strlen(path);
+
+               PackageNode* child = _LookupChild(path, componentEnd - path);
+               if (child == NULL)
+                       return;
+
+               if (*componentEnd == '\0') {
+                       // last path component -- delete the child
+                       fEntries.Remove(child);
+                       delete child;
+               } else {
+                       // must be a directory component -- continue resolving 
the path
+                       child->RemoveEntry(componentEnd + 1);
+               }
+       }
+
+private:
+       typedef DoublyLinkedList<PackageNode>   NodeList;
+
+private:
+       PackageNode* _LookupChild(const char* name, size_t nameLength)
+       {
                for (NodeList::Iterator it = fEntries.GetIterator();
                                PackageNode* child = it.Next();) {
-                       if (strcmp(child->Name(), name) == 0)
+                       if (strncmp(child->Name(), name, nameLength) == 0
+                               && child->Name()[nameLength] == '\0') {
                                return child;
+                       }
                }
 
                return NULL;
        }
 
 private:
-       typedef DoublyLinkedList<PackageNode>   NodeList;
-
-private:
        NodeList        fEntries;
 };
 
@@ -641,6 +674,11 @@ struct Directory : ::Directory {
                fDirectory->Volume()->ReleaseReference();
        }
 
+       void RemoveEntry(const char* path)
+       {
+               fDirectory->RemoveEntry(path);
+       }
+
        virtual ssize_t ReadAt(void* cookie, off_t pos, void* buffer,
                size_t bufferSize)
        {
@@ -789,7 +827,7 @@ create_node(PackageNode* packageNode, ::Node*& _node)
 }
 
 
-}      // unnamed namespace
+}      // namespace PackageFS
 
 
 status_t
@@ -836,3 +874,18 @@ packagefs_mount_file(int fd, ::Directory* systemDirectory,
        _mountedDirectory = static_cast< ::Directory*>(rootNode);
        return B_OK;
 }
+
+
+void
+packagefs_apply_path_blacklist(::Directory* systemDirectory,
+       const PathBlacklist& pathBlacklist)
+{
+       PackageFS::Directory* directory
+               = static_cast<PackageFS::Directory*>(systemDirectory);
+
+       for (PathBlacklist::Iterator it = pathBlacklist.GetIterator();
+               BlacklistedPath* path = it.Next();) {
+               directory->RemoveEntry(path->Path());
+       }
+}
+
diff --git a/src/system/boot/loader/file_systems/packagefs/packagefs.h 
b/src/system/boot/loader/file_systems/packagefs/packagefs.h
index 6c31dbd..be51060 100644
--- a/src/system/boot/loader/file_systems/packagefs/packagefs.h
+++ b/src/system/boot/loader/file_systems/packagefs/packagefs.h
@@ -11,6 +11,7 @@
 #include <SupportDefs.h>
 
 
+class PathBlacklist;
 class Directory;
 class Node;
 
@@ -18,5 +19,8 @@ class Node;
 status_t packagefs_mount_file(int fd, Directory* systemDirectory,
        Directory*& _mountedDirectory);
 
+void packagefs_apply_path_blacklist(Directory* systemDirectory,
+       const PathBlacklist& pathBlacklist);
+
 
 #endif // BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_H
diff --git a/src/system/boot/loader/main.cpp b/src/system/boot/loader/main.cpp
index 004c576..c0b8f31 100644
--- a/src/system/boot/loader/main.cpp
+++ b/src/system/boot/loader/main.cpp
@@ -12,8 +12,11 @@
 #include <boot/vfs.h>
 #include <boot/platform.h>
 #include <boot/heap.h>
+#include <boot/PathBlacklist.h>
 #include <boot/stdio.h>
 
+#include "file_systems/packagefs/packagefs.h"
+
 
 //#define TRACE_MAIN
 #ifdef TRACE_MAIN
@@ -53,6 +56,7 @@ main(stage2_args *args)
        bool mountedAllVolumes = false;
 
        BootVolume bootVolume;
+       PathBlacklist pathBlacklist;
 
        if (get_boot_file_system(args, bootVolume) != B_OK
                || (platform_boot_options() & BOOT_OPTION_MENU) != 0) {
@@ -69,7 +73,7 @@ main(stage2_args *args)
 
                mountedAllVolumes = true;
 
-               if (user_menu(bootVolume) < B_OK) {
+               if (user_menu(bootVolume, pathBlacklist) < B_OK) {
                        // user requested to quit the loader
                        goto out;
                }
@@ -91,7 +95,8 @@ main(stage2_args *args)
                                mountedAllVolumes = true;
                        }
 
-                       if (user_menu(bootVolume) < B_OK || 
!bootVolume.IsValid()) {
+                       if (user_menu(bootVolume, pathBlacklist) != B_OK
+                               || !bootVolume.IsValid()) {
                                // user requested to quit the loader
                                goto out;
                        }
@@ -101,6 +106,11 @@ main(stage2_args *args)
                // is already loaded at this point and we definitely
                // know our boot volume, too
                if (status == B_OK) {
+                       if (bootVolume.IsPackaged()) {
+                               
packagefs_apply_path_blacklist(bootVolume.SystemDirectory(),
+                                       pathBlacklist);
+                       }
+
                        register_boot_file_system(bootVolume);
 
                        if ((platform_boot_options() & 
BOOT_OPTION_DEBUG_OUTPUT) == 0)
diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp
index 58e2170..5b55168 100644
--- a/src/system/boot/loader/menu.cpp
+++ b/src/system/boot/loader/menu.cpp
@@ -1,6 +1,7 @@
 /*
  * Copyright 2003-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -14,7 +15,9 @@
 
 #include <OS.h>
 
+#include <AutoDeleter.h>
 #include <boot/menu.h>
+#include <boot/PathBlacklist.h>
 #include <boot/stage2.h>
 #include <boot/vfs.h>
 #include <boot/platform.h>
@@ -22,6 +25,7 @@
 #include <boot/stdio.h>
 #include <safemode.h>
 #include <util/ring_buffer.h>
+#include <util/SinglyLinkedList.h>
 
 #include "kernel_debug_config.h"
 
@@ -31,7 +35,7 @@
 #include "RootFileSystem.h"
 
 
-#define TRACE_MENU
+//#define TRACE_MENU
 #ifdef TRACE_MENU
 #      define TRACE(x) dprintf x
 #else
@@ -39,7 +43,11 @@
 #endif
 
 
-static char sSafeModeOptionsBuffer[2048];
+// only set while in user_menu()
+static Menu* sMainMenu = NULL;
+static Menu* sBlacklistRootMenu = NULL;
+static BootVolume* sBootVolume = NULL;
+static PathBlacklist* sPathBlacklist;
 
 
 MenuItem::MenuItem(const char *label, Menu *subMenu)
@@ -489,22 +497,340 @@ size_to_string(off_t size, char* buffer, size_t 
bufferSize)
 }
 
 
+// #pragma mark - blacklist menu
+
+
+class BlacklistMenuItem : public MenuItem {
+public:
+       BlacklistMenuItem(char* label, Node* node, Menu* subMenu)
+               :
+               MenuItem(label, subMenu),
+               fNode(node),
+               fSubMenu(subMenu)
+       {
+               fNode->Acquire();
+               SetType(MENU_ITEM_MARKABLE);
+       }
+
+       ~BlacklistMenuItem()
+       {
+               fNode->Release();
+
+               // make sure the submenu is destroyed
+               SetSubmenu(fSubMenu);
+       }
+
+       bool IsDirectoryItem() const
+       {
+               return fNode->Type() == S_IFDIR;
+       }
+
+       bool GetPath(BlacklistedPath& _path) const
+       {
+               Menu* menu = Supermenu();
+               if (menu != NULL && menu != sBlacklistRootMenu
+                       && menu->Superitem() != NULL) {
+                       return 
static_cast<BlacklistMenuItem*>(menu->Superitem())
+                                       ->GetPath(_path)
+                          && _path.Append(Label());
+               }
+
+               return _path.SetTo(Label());
+       }
+
+       void UpdateBlacklisted()
+       {
+               BlacklistedPath path;
+               if (GetPath(path))
+                       _SetMarked(sPathBlacklist->Contains(path.Path()), 
false);
+       }
+
+       virtual void SetMarked(bool marked)
+       {
+               _SetMarked(marked, true);
+       }
+
+       static bool Less(const MenuItem* a, const MenuItem* b)
+       {
+               const BlacklistMenuItem* item1
+                       = static_cast<const BlacklistMenuItem*>(a);
+               const BlacklistMenuItem* item2
+                       = static_cast<const BlacklistMenuItem*>(b);
+
+               // directories come first
+               if (item1->IsDirectoryItem() != item2->IsDirectoryItem())
+                       return item1->IsDirectoryItem();
+
+               // compare the labels
+               return strcasecmp(item1->Label(), item2->Label()) < 0;
+       }
+
+private:
+       void _SetMarked(bool marked, bool updateBlacklist)
+       {
+               if (marked == IsMarked())
+                       return;
+
+               // For directories toggle the availability of the submenu.
+               if (IsDirectoryItem())
+                       SetSubmenu(marked ? NULL : fSubMenu);
+
+               if (updateBlacklist) {
+                       BlacklistedPath path;
+                       if (GetPath(path)) {
+                               if (marked)
+                                       sPathBlacklist->Add(path.Path());
+                               else
+                                       sPathBlacklist->Remove(path.Path());
+                       }
+               }
+
+               MenuItem::SetMarked(marked);
+       }
+
+private:
+       Node*   fNode;
+       Menu*   fSubMenu;
+};
+
+
+class BlacklistMenu : public Menu {
+public:
+       BlacklistMenu()
+               :
+               Menu(STANDARD_MENU, "Mark the entries to blacklist"),
+               fDirectory(NULL)
+       {
+       }
+
+       ~BlacklistMenu()
+       {
+               SetDirectory(NULL);
+       }
+
+       virtual void Entered()
+       {
+               _DeleteItems();
+
+               if (fDirectory == NULL)
+                       return;
+
+               void* cookie;
+               if (fDirectory->Open(&cookie, O_RDONLY) == B_OK) {
+                       Node* node;
+                       while (fDirectory->GetNextNode(cookie, &node) == B_OK) {
+                               BlacklistMenuItem* item = _CreateItem(node);
+                               node->Release();
+                               if (item == NULL)
+                                       break;
+
+                               AddItem(item);
+
+                               item->UpdateBlacklisted();
+                       }
+                       fDirectory->Close(cookie);
+               }
+
+               SortItems(&BlacklistMenuItem::Less);
+       }
+
+       virtual void Exited()
+       {
+               _DeleteItems();
+       }
+
+protected:
+       void SetDirectory(Directory* directory)
+       {
+               if (fDirectory != NULL)
+                       fDirectory->Release();
+
+               fDirectory = directory;
+
+               if (fDirectory != NULL)
+                       fDirectory->Acquire();
+       }
+
+private:
+       static BlacklistMenuItem* _CreateItem(Node* node)
+       {
+               // Get the node name and duplicate it, so we can use it as a 
label.
+               char name[B_FILE_NAME_LENGTH];
+               if (node->GetName(name, sizeof(name)) != B_OK)
+                       return NULL;
+
+               // append '/' to directory labels
+               bool isDirectory = node->Type() == S_IFDIR;
+               if (isDirectory)
+                       strlcat(name, "/", sizeof(name));
+
+               // If this is a directory, create the submenu.
+               BlacklistMenu* subMenu = NULL;
+               if (isDirectory) {
+                       subMenu = new(std::nothrow) BlacklistMenu;
+                       if (subMenu != NULL)
+                               
subMenu->SetDirectory(static_cast<Directory*>(node));
+
+               }
+               ObjectDeleter<BlacklistMenu> subMenuDeleter(subMenu);
+
+               // create the menu item
+               BlacklistMenuItem* item = new(std::nothrow) 
BlacklistMenuItem(name,
+                       node, subMenu);
+               if (item == NULL)
+                       return NULL;
+
+               subMenuDeleter.Detach();
+               return item;
+       }
+
+       void _DeleteItems()
+       {
+               int32 count = CountItems();
+               for (int32 i = 0; i < count; i++)
+                       delete RemoveItemAt(0);
+       }
+
+private:
+       Directory*      fDirectory;
+};
+
+
+class BlacklistRootMenu : public BlacklistMenu {
+public:
+       BlacklistRootMenu()
+               :
+               BlacklistMenu()
+       {
+       }
+
+       virtual void Entered()
+       {
+               // Get the system directory, but only if this is a packaged 
Haiku.
+               // Otherwise blacklisting isn't supported.
+               if (sBootVolume != NULL && sBootVolume->IsValid()
+                       && sBootVolume->IsPackaged()) {
+                       SetDirectory(sBootVolume->SystemDirectory());
+               } else
+                       SetDirectory(NULL);
+
+               BlacklistMenu::Entered();
+       }
+
+       virtual void Exited()
+       {
+               BlacklistMenu::Exited();
+               SetDirectory(NULL);
+       }
+};
+
+
+// #pragma mark -
+
+
+class StringBuffer {
+public:
+       StringBuffer()
+               :
+               fBuffer(NULL),
+               fLength(0),
+               fCapacity(0)
+       {
+       }
+
+       ~StringBuffer()
+       {
+               free(fBuffer);
+       }
+
+       const char* String() const
+       {
+               return fBuffer != NULL ? fBuffer : "";
+       }
+
+       size_t Length() const
+       {
+               return fLength;
+       }
+
+       bool Append(const char* toAppend)
+       {
+               return Append(toAppend, strlen(toAppend));
+       }
+
+       bool Append(const char* toAppend, size_t length)
+       {
+               size_t oldLength = fLength;
+               if (!_Resize(fLength + length))
+                       return false;
+
+               memcpy(fBuffer + oldLength, toAppend, length);
+               return true;
+       }
+
+private:
+       bool _Resize(size_t newLength)
+       {
+               if (newLength >= fCapacity) {
+                       size_t newCapacity = std::max(fCapacity, size_t(32));
+                       while (newLength >= newCapacity)
+                               newCapacity *= 2;
+
+                       char* buffer = (char*)realloc(fBuffer, newCapacity);
+                       if (buffer == NULL)
+                               return false;
+
+                       fBuffer = buffer;
+                       fCapacity = newCapacity;
+               }
+
+               fBuffer[newLength] = '\0';
+               fLength = newLength;
+               return true;
+       }
+
+private:
+       char*   fBuffer;
+       size_t  fLength;
+       size_t  fCapacity;
+};
+
+
 // #pragma mark -
 
 
+static StringBuffer sSafeModeOptionsBuffer;
+
+
+static MenuItem*
+get_continue_booting_menu_item()
+{
+       // It's the last item in the main menu.
+       if (sMainMenu == NULL || sMainMenu->CountItems() == 0)
+               return NULL;
+       return sMainMenu->ItemAt(sMainMenu->CountItems() - 1);
+}
+
+
 static bool
 user_menu_boot_volume(Menu* menu, MenuItem* item)
 {
-       Menu* super = menu->Supermenu();
-       if (super == NULL) {
+       MenuItem* bootItem = get_continue_booting_menu_item();
+       if (bootItem == NULL) {
                // huh?
                return true;
        }
 
-       MenuItem *bootItem = super->ItemAt(super->CountItems() - 1);
-       bootItem->SetEnabled(true);
-       bootItem->Select(true);
-       bootItem->SetData(item->Data());
+       if (sBootVolume->IsValid() && sBootVolume->RootDirectory() == 
item->Data())
+               return true;
+
+       sPathBlacklist->MakeEmpty();
+
+       bool valid = sBootVolume->SetTo((Directory*)item->Data()) == B_OK;
+
+       bootItem->SetEnabled(valid);
+       if (valid)
+               bootItem->Select(true);
 
        gBootVolume.SetBool(BOOT_VOLUME_USER_SELECTED, true);
        return true;
@@ -653,10 +979,10 @@ debug_menu_add_advanced_option(Menu* menu, MenuItem* item)
 
        if (size > 0) {
                buffer[size] = '\n';
-               size_t pos = strlen(sSafeModeOptionsBuffer);
-               if (pos + size + 1 < sizeof(sSafeModeOptionsBuffer))
-                       strlcat(sSafeModeOptionsBuffer, buffer,
-                               sizeof(sSafeModeOptionsBuffer));
+               if (!sSafeModeOptionsBuffer.Append(buffer)) {
+                       dprintf("debug_menu_add_advanced_option(): failed to 
append option "
+                               "to buffer\n");
+               }
        }
 
        return true;
@@ -699,7 +1025,7 @@ add_boot_volume_menu(Directory* bootVolume)
                Directory* volume;
                while (gRoot->GetNextNode(cookie, (Node**)&volume) == B_OK) {
                        // only list bootable volumes
-                       if (!is_bootable(volume))
+                       if (volume != bootVolume && !is_bootable(volume))
                                continue;
 
                        char name[B_FILE_NAME_LENGTH];
@@ -794,6 +1120,13 @@ add_safe_mode_menu()
        platform_add_menus(safeMenu);
 
        safeMenu->AddSeparatorItem();
+       sBlacklistRootMenu = new(std::nothrow) BlacklistRootMenu;
+       safeMenu->AddItem(item = new(std::nothrow) MenuItem("Blacklist entries",
+               sBlacklistRootMenu));
+       item->SetHelpText("Allows to select system files that shall be ignored. 
"
+               "Useful e.g. to disable drivers temporarily.");
+
+       safeMenu->AddSeparatorItem();
        safeMenu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
 
        return safeMenu;
@@ -962,18 +1295,43 @@ add_debug_menu()
 static void
 apply_safe_mode_options(Menu* menu)
 {
-       int32 pos = strlen(sSafeModeOptionsBuffer);
-       size_t bufferSize = sizeof(sSafeModeOptionsBuffer);
-
        MenuItemIterator iterator = menu->ItemIterator();
        while (MenuItem* item = iterator.Next()) {
                if (item->Type() == MENU_ITEM_SEPARATOR || !item->IsMarked()
-                       || item->Data() == NULL || (uint32)pos >= bufferSize)
+                       || item->Data() == NULL) {
                        continue;
+               }
 
-               size_t totalBytes = snprintf(sSafeModeOptionsBuffer + pos,
-                       bufferSize - pos, "%s true\n", (const 
char*)item->Data());
-               pos += std::min(totalBytes, bufferSize - pos - 1);
+               char buffer[256];
+               if (snprintf(buffer, sizeof(buffer), "%s true\n",
+                               (const char*)item->Data()) >= 
(int)sizeof(buffer)
+                       || !sSafeModeOptionsBuffer.Append(buffer)) {
+                       dprintf("apply_safe_mode_options(): failed to append 
option to "
+                               "buffer\n");
+               }
+       }
+}
+
+
+static void
+apply_safe_mode_path_blacklist()
+{
+       if (sPathBlacklist->IsEmpty())
+               return;
+
+       bool success = sSafeModeOptionsBuffer.Append("EntryBlacklist {\n");
+
+       for (PathBlacklist::Iterator it = sPathBlacklist->GetIterator();
+               BlacklistedPath* path = it.Next();) {
+               success &= sSafeModeOptionsBuffer.Append(path->Path());
+               success &= sSafeModeOptionsBuffer.Append("\n", 1);
+       }
+
+       success &= sSafeModeOptionsBuffer.Append("}\n");
+
+       if (!success) {
+               dprintf("apply_safe_mode_options(): failed to append path "
+                       "blacklist to buffer\n");
        }
 }
 
@@ -987,17 +1345,21 @@ user_menu_reboot(Menu* menu, MenuItem* item)
 
 
 status_t
-user_menu(BootVolume& _bootVolume)
+user_menu(BootVolume& _bootVolume, PathBlacklist& _pathBlacklist)
 {
+
        Menu* menu = new(std::nothrow) Menu(MAIN_MENU);
+
+       sMainMenu = menu;
+       sBootVolume = &_bootVolume;
+       sPathBlacklist = &_pathBlacklist;
+
        Menu* safeModeMenu = NULL;
        Menu* debugMenu = NULL;
        MenuItem* item;
 
        TRACE(("user_menu: enter\n"));
 
-       memset(sSafeModeOptionsBuffer, 0, sizeof(sSafeModeOptionsBuffer));
-
        // Add boot volume
        menu->AddItem(item = new(std::nothrow) MenuItem("Select boot volume",
                add_boot_volume_menu(_bootVolume.RootDirectory())));
@@ -1028,18 +1390,18 @@ user_menu(BootVolume& _bootVolume)
 
        menu->Run();
 
-       // See if a new boot device has been selected, and propagate that back
-       if (item->Data() != NULL)
-               _bootVolume.SetTo((Directory*)item->Data());
-
        apply_safe_mode_options(safeModeMenu);
        apply_safe_mode_options(debugMenu);
-       add_safe_mode_settings(sSafeModeOptionsBuffer);
+       apply_safe_mode_path_blacklist();
+       add_safe_mode_settings(sSafeModeOptionsBuffer.String());
        delete menu;
 
 
        TRACE(("user_menu: leave\n"));
 
+       sMainMenu = NULL;
+       sBlacklistRootMenu = NULL;
+       sBootVolume = NULL;
+       sPathBlacklist = NULL;
        return B_OK;
 }
-
diff --git a/src/system/boot/loader/menu.h b/src/system/boot/loader/menu.h
index a400952..c10cf61 100644
--- a/src/system/boot/loader/menu.h
+++ b/src/system/boot/loader/menu.h
@@ -9,7 +9,11 @@
 #include <boot/vfs.h>
 
 
-extern status_t user_menu(BootVolume& _bootVolume);
+class PathBlacklist;
+
+
+extern status_t user_menu(BootVolume& _bootVolume,
+       PathBlacklist& _pathBlacklist);
 
 
 #endif /* MENU_H */


Other related posts:

  • » [haiku-commits] haiku: hrev46394 - src/system/boot/loader src/add-ons/kernel/file_systems/packagefs/volume headers/private/kernel/boot src/system/boot/loader/file_systems/packagefs - ingo_weinhold