#!/usr/bin/python3 -I """ What: efivars Description: List EFI variables made available in RAM from the UEFI NV-RAM The list of variables is divided into two sections, the first being the UEFI defined variables as described in the UEFI Specification v2.11 (https://uefi.org/sites/default/files/resources/UEFI_Spec_Final_2.11.pdf), and the second section contains all vendor specific variables defined by the vendors UEFI firmware. Author: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu> Date: Mar 22 2025 """ import os import re import sys # Global variables UEFI_GLOBAL_VARIABLE_GUID = "8be4df61-93ca-11d2-aa0d-00e098032b8c" SYSFS_EFIVARSFS = "/sys/firmware/efi/efivars" # Technically speaking UEFI variables stored in the NV-RAM are not # directly accessible from the OS level. They are rather made residents # of RAM by the UEFI firmware at boot time for exposure to the 'efivarfs' # interface driver which will make them available in /sys/firmware/efi/efivars # hence why we will enumerate all files in the latter. def enum_efi_vars(efivarsfs_path: str = SYSFS_EFIVARSFS) -> list: """ Enumerates UEFI variables exposed in SYSFS_EFIVARSFS. Args: efivarsfs_path (str): Absolute filesystem path to efivarsfs ,default (SYSFS_EFIVARSFS) Returns: list: All found variables in SYSFS_EFIVARSFS """ efi_vars = [] for (dirpath, dirnames, filenames) in os.walk(efivarsfs_path): efi_vars.extend(filenames) break return efi_vars # Here we will sort the enumerated EFI variables into two distinct lists. def sort_efi_vars(efi_vars_list: list, uefi_global_vars_guid: str) -> tuple: """ Sorts the enumerated EFI variables into two different lists. 'uefi_spec_vars' will contain variables defined by the UEFI Specification and 'vendor_spec_vars' will be vendor defined variables Args: list (efi_vars_list): An unsorted list of EFI variables str (uefi_global_vars_guid): UEFI global variables guid for the regex pattern Returns: tuple (uefi_spec_vars, vendor_spec_vars): List of UEFI and vendor specific variables, respectively """ uefi_spec_vars = [] vendor_spec_vars = [] # As defined in UEFI Specification v2.11 8.2.3 # variables have to be minimum 1 char long uefi_vars_regex_pattern = re.compile(f"^.+-{uefi_global_vars_guid}$") for var in efi_vars_list: if not uefi_vars_regex_pattern.match(var): vendor_spec_vars.append(var) else: uefi_spec_vars.append(var) return uefi_spec_vars, vendor_spec_vars # Pretty print a list def print_list(var_l: list, l_name: str) -> None: l_size = len(var_l) print("{} {}\n".format(l_size, l_name)) for e in var_l: print(e) # Entrypoint def main() -> None: # Testing if the 'efivarfs' at /sys/firmware/efi/efivars has been created try: os.stat(SYSFS_EFIVARSFS) except Exception as e: print(""" {}\n EFI variables can not be listed on your system Please make sure your kernel isn't booted with the 'noefi' parameter and is configured with 'CONFIG_EFI=y', otherwise run the command below as root and try again. mount -t efivarfs efivarfs /sys/firmware/efi/efivars""".format(e)) sys.exit(2) all_efi_vars = enum_efi_vars(SYSFS_EFIVARSFS) if not all_efi_vars: print("Something seems wrong, no EFI variables found!") sys.exit(3) uefi_spec_vars, vendor_spec_vars = sort_efi_vars( all_efi_vars, UEFI_GLOBAL_VARIABLE_GUID ) print_list( uefi_spec_vars, "[UEFI Specification v2.11 defined EFI variables]" ) print("") print_list(vendor_spec_vars, "[Vendor defined EFI variables]") # Enter the entrypoint only if this script is ran directly if __name__ == '__main__': main()