130 lines
4.0 KiB
Python
Executable File
130 lines
4.0 KiB
Python
Executable File
#!/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()
|