:: commit b2848fb5800415d08894731ff541addbfdda79ea

Patrick Hechler <gitHub@ph.anderemails.de> — 2026-04-26 18:04

parents: 28d8cc3002

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
tab: 248 wrap: offon