add options that allow hiding entries depending of firmware/architecture (#560)
* add settings IF_FW_TYPE and IF_ARCH
IF_FW_TYPE allows to hide menu entries according to the
firmware type (bios/uefi)
if IF_FW_TYPE is present and does not match the firmware
the entry will be hidden
IF_ARCH allows to hide menu entries according to the
processor architecture (x86-64/ia-32/aarch64/...)
if IF_ARCH is present it must contain a space seperated
list of allowed architectures
(ie. IF_ARCH: x86-64 ia-32)
---------
Co-authored-by: PatrickHechler <pat-git@ph.anderemails.de>
Co-authored-by: Kamila Szewczyk <k@iczelia.net>diff --git a/CONFIG.md b/CONFIG.md
index fd86e93b..3b26d2ea 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -207,6 +207,11 @@ Editor control options:
* `cmdline` - The command line string to be passed to the kernel/executable.
Can be omitted.
* `kernel_cmdline` - Alias of `cmdline`.
+* `if_fw_type` - Hide the entry if the firmware does not match. Valid values
+ are: `BIOS`, `UEFI`
+* `if_arch` - Hide the entry if the current CPU architecture is not in the
+ space separated list of permitted architectures
+ * see the `ARCH` macro in [Built-in macros](#built-in-macros) for a list of possible architectures
> **NOTE:** `uefi` and `efi_chainload` are aliases of the `efi` protocol
> option. `bios_chainload` is an alias of the `bios` protocol option.
diff --git a/common/lib/config.c b/common/lib/config.c
index 7070cd3f..b385da1a 100644
--- a/common/lib/config.c
+++ b/common/lib/config.c
@@ -412,36 +412,13 @@ skip_loop:
// Load macros
struct macro *arch_macro = ext_mem_alloc(sizeof(struct macro));
strcpy(arch_macro->name, "ARCH");
-#if defined (__x86_64__)
- strcpy(arch_macro->value, "x86-64");
-#elif defined (__i386__)
- {
- uint32_t eax, ebx, ecx, edx;
- if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
- strcpy(arch_macro->value, "ia-32");
- } else {
- strcpy(arch_macro->value, "x86-64");
- }
- }
-#elif defined (__aarch64__)
- strcpy(arch_macro->value, "aarch64");
-#elif defined (__riscv)
- strcpy(arch_macro->value, "riscv64");
-#elif defined (__loongarch64)
- strcpy(arch_macro->value, "loongarch64");
-#else
-#error "Unspecified architecture"
-#endif
+ strcpy(arch_macro->value, current_arch());
arch_macro->next = macros;
macros = arch_macro;
struct macro *fw_type_macro = ext_mem_alloc(sizeof(struct macro));
strcpy(fw_type_macro->name, "FW_TYPE");
-#if defined (UEFI)
- strcpy(fw_type_macro->value, "UEFI");
-#else
- strcpy(fw_type_macro->value, "BIOS");
-#endif
+ strcpy(fw_type_macro->value, current_firmware());
fw_type_macro->next = macros;
macros = fw_type_macro;
diff --git a/common/lib/misc.h b/common/lib/misc.h
index 60f709ef..00d815b2 100644
--- a/common/lib/misc.h
+++ b/common/lib/misc.h
@@ -150,4 +150,14 @@ struct mem_range {
uint64_t permissions;
};
+static inline const char *current_firmware(void) {
+#if defined (UEFI)
+ return "UEFI";
+#elif defined (BIOS)
+ return "BIOS";
+#else
+#error "Unspecified firmware type"
+#endif
+}
+
#endif
diff --git a/common/menu.c b/common/menu.c
index c98a748c..ad9e9b01 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -173,6 +173,8 @@ static const char *VALID_KEYS[] = {
"IMAGE_PATH",
"DTB_PATH",
"ENTRY",
+ "IF_FW_TYPE",
+ "IF_ARCH",
NULL
};
@@ -617,6 +619,43 @@ static inline bool should_skip_entry(struct menu_entry *entry) {
return true;
}
}
+ char *cur_entry_if_fw_type = config_get_value(entry->body, 0, "IF_FW_TYPE");
+ if (cur_entry_if_fw_type) {
+ if (strcasecmp(cur_entry_if_fw_type, current_firmware()) != 0) {
+ return true;
+ }
+ }
+ char *cur_entry_if_arch = config_get_value(entry->body, 0, "IF_ARCH");
+ if (cur_entry_if_arch) {
+ const char *arch = current_arch();
+ char *cur_arch = cur_entry_if_arch;
+ bool skip = true;
+ while (*cur_arch) {
+ char *cur_arch_end = cur_arch;
+ while (*cur_arch_end && !isspace(*cur_arch_end)) {
+ ++cur_arch_end;
+ }
+ if (cur_arch == cur_arch_end) {
+ ++cur_arch;
+ continue;
+ }
+ char buf[16];
+ if (cur_arch_end - cur_arch >= 16) {
+ cur_arch = cur_arch_end;
+ continue;
+ }
+ memcpy(buf, cur_arch, cur_arch_end - cur_arch);
+ buf[cur_arch_end - cur_arch] = '\0';
+ if (strcasecmp(buf, arch) == 0) {
+ skip = false;
+ break;
+ }
+ cur_arch = cur_arch_end;
+ }
+ if (skip) {
+ return true;
+ }
+ }
return false;
}
diff --git a/common/sys/cpu.h b/common/sys/cpu.h
index e925ddda..a91ed5e2 100644
--- a/common/sys/cpu.h
+++ b/common/sys/cpu.h
@@ -512,4 +512,25 @@ static inline void stall(uint64_t us) {
while (rdtsc() < next_stop);
}
+static inline const char *current_arch(void) {
+#if defined (__x86_64__)
+ return "x86-64";
+#elif defined (__i386__)
+ uint32_t eax, ebx, ecx, edx;
+ if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
+ return "ia-32";
+ } else {
+ return "x86-64";
+ }
+#elif defined (__aarch64__)
+ return "aarch64";
+#elif defined (__riscv)
+ return "riscv64";
+#elif defined (__loongarch64)
+ return "loongarch64";
+#else
+#error "Unspecified architecture"
+#endif
+}
+
#endif
