summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-07-15 00:15:40 +0200
committerKay Sievers <kay@vrfy.org>2012-07-15 02:21:35 +0200
commitfc85a34194b2d623614b1490b456c4e7a70f553e (patch)
tree75f4f9e91e30f351f48d4e2ce80527ef956d556a
parent6d23e5fd047a712102eb946423ec4246d66b2c25 (diff)
add "title-version", "title-machine" to non-unique menu "title"s
-rw-r--r--TODO4
-rw-r--r--gummiboot.c160
-rwxr-xr-xloader-postinst.sh43
3 files changed, 159 insertions, 48 deletions
diff --git a/TODO b/TODO
index d118ce0..137fced 100644
--- 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
diff --git a/gummiboot.c b/gummiboot.c
index a34981c..8e5e35b 100644
--- a/gummiboot.c
+++ b/gummiboot.c
@@ -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);
diff --git a/loader-postinst.sh b/loader-postinst.sh
index a705b2e..091baaf 100755
--- a/loader-postinst.sh
+++ b/loader-postinst.sh
@@ -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