add "title-version", "title-machine" to non-unique menu "title"s
authorKay Sievers <kay@vrfy.org>
Sat, 14 Jul 2012 22:15:40 +0000 (00:15 +0200)
committerKay Sievers <kay@vrfy.org>
Sun, 15 Jul 2012 00:21:35 +0000 (02:21 +0200)
TODO
gummiboot.c
loader-postinst.sh

diff --git a/TODO b/TODO
index d118ce0..137fced 100644 (file)
--- a/TODO
+++ b/TODO
@@ -11,9 +11,5 @@
   and which supports: create/update/delete conf fragment, update/cleanup
   all fragments belonging to this machine.
 
-* add "title-details" (carrying the machine-id / the root device name) support
-  to the fragment file. Display the details along with the "title" if we have
-  non-unique titles -> pretty looking menu without silly numbers if not needed
-
 * properly document the config file format, directory layout and EFI variable
   in the wiki; make it more look like a spec -> easier to adapt other loaders
index a34981c..8e5e35b 100644 (file)
@@ -41,11 +41,15 @@ enum loader_type {
 
 typedef struct {
         CHAR16 *file;
+        CHAR16 *title_show;
         CHAR16 *title;
+        CHAR16 *title_version;
+        CHAR16 *title_machine;
         enum loader_type type;
         CHAR16 *loader;
         CHAR16 *options;
         BOOLEAN no_autoselect;
+        BOOLEAN non_unique;
 } ConfigEntry;
 
 typedef struct {
@@ -361,7 +365,13 @@ static VOID dump_status(Config *config) {
                 entry = config->entries[i];
                 Print(L"config entry:           %d/%d\n", i+1, config->entry_count);
                 Print(L"file                    '%s'\n", entry->file);
-                Print(L"title                   '%s'\n", entry->title);
+                Print(L"title show              '%s'\n", entry->title_show);
+                if (entry->title)
+                        Print(L"title                   '%s'\n", entry->title);
+                if (entry->title_version)
+                        Print(L"title version           '%s'\n", entry->title_version);
+                if (entry->title_machine)
+                        Print(L"title machine           '%s'\n", entry->title_machine);
                 Print(L"loader                  '%s'\n", entry->loader);
                 if (entry->options)
                         Print(L"options                 '%s'\n", entry->options);
@@ -433,7 +443,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry) {
         for (i = 0; i < config->entry_count; i++) {
                 UINTN entry_len;
 
-                entry_len = StrLen(config->entries[i]->title);
+                entry_len = StrLen(config->entries[i]->title_show);
                 if (line_width < entry_len)
                         line_width = entry_len;
         }
@@ -443,7 +453,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry) {
         /* menu entries title lines */
         lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
         for (i = 0; i < config->entry_count; i++)
-                lines[i] = PoolPrint(L"  %-.*s ", line_width, config->entries[i]->title);
+                lines[i] = PoolPrint(L"  %-.*s  ", line_width, config->entries[i]->title_show);
 
         status = NULL;
         clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
@@ -689,7 +699,9 @@ static VOID config_add_entry(Config *config, ConfigEntry *entry) {
 }
 
 static VOID config_entry_free(ConfigEntry *entry) {
+        FreePool(entry->title_show);
         FreePool(entry->title);
+        FreePool(entry->title_machine);
         FreePool(entry->loader);
         FreePool(entry->options);
 }
@@ -971,6 +983,18 @@ static VOID config_entry_add_from_file(Config *config, CHAR16 *file, CHAR8 *cont
                         continue;
                 }
 
+                if (strcmpa((CHAR8 *)"title-version", key) == 0) {
+                        FreePool(entry->title_version);
+                        entry->title_version = stra_to_str(value);
+                        continue;
+                }
+
+                if (strcmpa((CHAR8 *)"title-machine", key) == 0) {
+                        FreePool(entry->title_machine);
+                        entry->title_machine = stra_to_str(value);
+                        continue;
+                }
+
                 if (strcmpa((CHAR8 *)"linux", key) == 0) {
                         FreePool(entry->loader);
                         entry->type = LOADER_LINUX;
@@ -1055,9 +1079,6 @@ static VOID config_entry_add_from_file(Config *config, CHAR16 *file, CHAR8 *cont
                 entry->file[len - 5] = '\0';
         StrLwr(entry->file);
 
-        if (!entry->title)
-                entry->title = StrDuplicate(entry->loader);
-
         config_add_entry(config, entry);
 }
 
@@ -1145,17 +1166,17 @@ static VOID config_load(Config *config, EFI_FILE *root_dir, CHAR16 *loaded_image
         /* sort entries after version number */
         for (i = 1; i < config->entry_count; i++) {
                 BOOLEAN more;
-                UINTN j;
+                UINTN k;
 
                 more = FALSE;
-                for (j = 0; j < config->entry_count - i; j++) {
+                for (k = 0; k < config->entry_count - i; k++) {
                         ConfigEntry *entry;
 
-                        if (str_verscmp(config->entries[j]->file, config->entries[j+1]->file) <= 0)
+                        if (str_verscmp(config->entries[k]->file, config->entries[k+1]->file) <= 0)
                                 continue;
-                        entry = config->entries[j];
-                        config->entries[j] = config->entries[j+1];
-                        config->entries[j+1] = entry;
+                        entry = config->entries[k];
+                        config->entries[k] = config->entries[k+1];
+                        config->entries[k+1] = entry;
                         more = TRUE;
                 }
                 if (!more)
@@ -1242,6 +1263,113 @@ static VOID config_default_entry_select(Config *config) {
                 config->idx_default = config->entry_count-1;
 }
 
+/* generate a unique title, avoiding non-distinguishable menu entries */
+static VOID config_title_generate(Config *config) {
+        UINTN i, k;
+        BOOLEAN unique;
+
+        /* set title */
+        for (i = 0; i < config->entry_count; i++) {
+                CHAR16 *title;
+
+                FreePool(config->entries[i]->title_show);
+                title = config->entries[i]->title;
+                if (!title)
+                        title = config->entries[i]->file;
+                config->entries[i]->title_show = StrDuplicate(title);
+        }
+
+        unique = TRUE;
+        for (i = 0; i < config->entry_count; i++) {
+                for (k = 0; k < config->entry_count; k++) {
+                        if (i == k)
+                                continue;
+                        if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
+                                continue;
+
+                        unique = FALSE;
+                        config->entries[i]->non_unique = TRUE;
+                        config->entries[k]->non_unique = TRUE;
+                }
+        }
+        if (unique)
+                return;
+
+        /* add version to non-unique titles */
+        for (i = 0; i < config->entry_count; i++) {
+                CHAR16 *s;
+
+                if (!config->entries[i]->non_unique)
+                        continue;
+                if (!config->entries[i]->title_version)
+                        continue;
+
+                s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->title_version);
+                FreePool(config->entries[i]->title_show);
+                config->entries[i]->title_show = s;
+                config->entries[i]->non_unique = FALSE;
+        }
+
+        unique = TRUE;
+        for (i = 0; i < config->entry_count; i++) {
+                for (k = 0; k < config->entry_count; k++) {
+                        if (i == k)
+                                continue;
+                        if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
+                                continue;
+
+                        unique = FALSE;
+                        config->entries[i]->non_unique = TRUE;
+                        config->entries[k]->non_unique = TRUE;
+                }
+        }
+        if (unique)
+                return;
+
+        /* add machine-id to non-unique titles */
+        for (i = 0; i < config->entry_count; i++) {
+                CHAR16 *s;
+
+                if (!config->entries[i]->non_unique)
+                        continue;
+                if (!config->entries[i]->title_machine)
+                        continue;
+
+                s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->title_machine);
+                FreePool(config->entries[i]->title_show);
+                config->entries[i]->title_show = s;
+                config->entries[i]->non_unique = FALSE;
+        }
+
+        unique = TRUE;
+        for (i = 0; i < config->entry_count; i++) {
+                for (k = 0; k < config->entry_count; k++) {
+                        if (i == k)
+                                continue;
+                        if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
+                                continue;
+
+                        unique = FALSE;
+                        config->entries[i]->non_unique = TRUE;
+                        config->entries[k]->non_unique = TRUE;
+                }
+        }
+        if (unique)
+                return;
+
+        /* add file name to non-unique titles */
+        for (i = 0; i < config->entry_count; i++) {
+                CHAR16 *s;
+
+                if (!config->entries[i]->non_unique)
+                        continue;
+                s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->file);
+                FreePool(config->entries[i]->title_show);
+                config->entries[i]->title_show = s;
+                config->entries[i]->non_unique = FALSE;
+        }
+}
+
 static VOID config_entry_add_loader(Config *config, EFI_FILE *root_dir, CHAR16 *loaded_image_path,
                                     CHAR16 *file, CHAR16 *title, CHAR16 *loader) {
         EFI_FILE_HANDLE handle;
@@ -1370,13 +1498,15 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
 
         /* if we find some well-known loaders, add them to the end of the list */
         config_entry_add_loader(&config, root_dir, loaded_image_path,
-                                L"loader-bootmgfw", L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
+                                L"builtin-bootmgfw", L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
         config_entry_add_loader(&config, root_dir, loaded_image_path,
-                                L"loader-shellx64", L"EFI Shell", L"\\shellx64.efi");
+                                L"builtin-shellx64", L"EFI Shell", L"\\shellx64.efi");
         config_entry_add_loader(&config, root_dir, loaded_image_path,
-                                L"loader-bootx64", L"EFI Default Loader", L"\\EFI\\BOOT\\BOOTX64.EFI");
+                                L"builtin-bootx64", L"EFI Default Loader", L"\\EFI\\BOOT\\BOOTX64.EFI");
         FreePool(loaded_image_path);
 
+        config_title_generate(&config);
+
         /* select entry by configured pattern or EFI LoaderDefaultEntry= variable*/
         config_default_entry_select(&config);
 
index a705b2e..091baaf 100755 (executable)
@@ -31,14 +31,14 @@ fi
 
 if [[ -d /boot/loader/entries ]]; then
         EFI_DIR="/boot"
-elif [[ -f /boot/efi/loader/entries ]]; then
+elif [[ -d /boot/efi/loader/entries ]]; then
         EFI_DIR="/boot/efi"
 fi
 
 if ! [[ $EFI_DIR ]] ; then
-        echo "Can't install new kernel for loader: no directory 'loader/entries found!" >&2
-        echo "Please create the directory 'loader/entries' in your EFI partition." >&2
-        exit 1
+        echo "Did not install new kernel and loader entry." >&2
+        echo "Please create the directory 'loader/entries/' in your EFI system partition." >&2
+        exit 0
 fi
 
 if [[ -f ${KERNEL_IMAGE/vmlinuz/initrd} ]]; then
@@ -55,57 +55,42 @@ if [[ -f /etc/kernel/cmdline ]]; then
         done < /etc/kernel/cmdline
 fi
 if ! [[ $BOOT_OPTIONS ]]; then
-        echo "Can't load default kernel command line parameters from /etc/kernel/cmdline!" >&2
+        echo "Can't determine the kernel command line parameters." >&2
         echo "Please specify the kernel command line in /etc/kernel/cmdline!" >&2
         exit 1
 fi
 
 [[ -f /etc/os-release ]] && . /etc/os-release
 if ! [[ $ID ]]; then
-        echo "Can't determine the ID of your distribution. Please populate /etc/os-release!" >&2
+        echo "Can't determine the name of your distribution. Please create /etc/os-release." >&2
         echo "See http://www.freedesktop.org/software/systemd/man/os-release.html" >&2
         exit 1
 fi
 
 [[ -f /etc/machine-id ]] && read MACHINE_ID < /etc/machine-id
 if ! [[ $MACHINE_ID ]]; then
-        echo "Can't determine your machine id. Please populate /etc/machine-id!" >&2
+        echo "Can't determine your machine id. Please create /etc/machine-id!" >&2
         echo "See http://www.freedesktop.org/software/systemd/man/machine-id.html" >&2
         exit 1
 fi
 
-ROOT_DEV=$(while read a a a a mp a a a dev a; do
-        if [[ $mp = "/" ]]; then
-                echo $dev
-                break
-        fi
-done < /proc/self/mountinfo)
-
-if [[ $ROOT_DEV ]]; then
-        ROOT_LABEL=$(blkid -p -o udev -u filesystem $ROOT_DEV |
-            while read line; do
-                if [[ $line == ID_FS_LABEL* ]]; then
-                    echo ${line##ID_FS_LABEL=}
-                    break
-                fi
-                done)
-fi
-
 mkdir -p "${EFI_DIR}/${ID}/${MACHINE_ID}"
 
 cp --preserve "$KERNEL_IMAGE" "${EFI_DIR}/${ID}/${MACHINE_ID}/"
 [[ $INITRD_IMAGE ]] && cp --preserve "$INITRD_IMAGE" "${EFI_DIR}/${ID}/${MACHINE_ID}/"
 
 {
-        echo "title $NAME $VERSION_ID ($KERNEL_VERSION) $ROOT_LABEL ${ROOT_DEV##/dev/} ${MACHINE_ID:0:8}"
-        echo "options $BOOT_OPTIONS"
-        echo "linux /$ID/$MACHINE_ID/${KERNEL_IMAGE##*/}"
-        [[ $INITRD_IMAGE ]] && echo "initrd /${ID}/${MACHINE_ID}/${INITRD_IMAGE##*/}"
+        echo "title         $PRETTY_NAME"
+        echo "title-version $KERNEL_VERSION"
+        echo "title-machine ${MACHINE_ID:0:8}"
+        echo "options       $BOOT_OPTIONS"
+        echo "linux         /$ID/$MACHINE_ID/${KERNEL_IMAGE##*/}"
+        [[ $INITRD_IMAGE ]] && echo "initrd        /${ID}/${MACHINE_ID}/${INITRD_IMAGE##*/}"
 } > "${EFI_DIR}/loader/entries/${ID}-${KERNEL_VERSION}-${MACHINE_ID}.conf"
 
 if ! [[ -f ${EFI_DIR}/loader/loader.conf ]]; then
         {
-                echo "default $ID-"
+                echo "default $ID-*"
         } > "${EFI_DIR}/loader/loader.conf"
 fi