-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Linux Variable Writing Script (#353)
## Description This adds a Python script to write UEFI variables to and from config bins from Linux. The current support is only for Windows. For each item, place an "x" in between `[` and `]` if true. Example: `[x]`. _(you can also check items in the GitHub UI)_ - [ ] Impacts functionality? - **Functionality** - Does the change ultimately impact how firmware functions? - Examples: Add a new library, publish a new PPI, update an algorithm, ... - [ ] Impacts security? - **Security** - Does the change have a direct security impact on an application, flow, or firmware? - Examples: Crypto algorithm change, buffer overflow fix, parameter validation improvement, ... - [ ] Breaking change? - **Breaking change** - Will anyone consuming this change experience a break in build or boot behavior? - Examples: Add a new library class, move a module to a different repo, call a function in a new library class in a pre-existing module, ... - [ ] Includes tests? - **Tests** - Does the change include any explicit test code? - Examples: Unit tests, integration tests, robot tests, ... - [ ] Includes documentation? - **Documentation** - Does the change contain explicit documentation additions outside direct code modifications (and comments)? - Examples: Update readme file, add feature readme file, link to documentation on an a separate Web page, ... ## How This Was Tested Tested in Ubuntu 24.04 with the QemuQ35 virtual platform using mu_feature_config as well as on physical platforms using it. ## Integration Instructions Run the same flows as for the Windows script, the scripts will automatically detect that this is run from Linux and choose the right script. It needs to be run as sudo. --------- Co-authored-by: kuqin12 <42554914+kuqin12@users.noreply.github.com> Co-authored-by: Aaron <105021049+apop5@users.noreply.github.com>
- Loading branch information
1 parent
319a618
commit 2fffa56
Showing
6 changed files
with
183 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,6 +125,9 @@ | |
"profilenames", | ||
"profileid", | ||
"profileids", | ||
"prettyname" | ||
"prettyname", | ||
"efivars", | ||
"efivarfs", | ||
"chattr" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLinuxLib.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# @file | ||
# | ||
# Python lib to support Reading and writing UEFI variables from Linux | ||
# | ||
# | ||
# Copyright (c), Microsoft Corporation | ||
# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
# | ||
# GetUefiAllVarNames is based on information from | ||
# https://github.com/awslabs/python-uefivars/blob/main/pyuefivars/efivarfs.py | ||
# | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: MIT | ||
|
||
import os | ||
import uuid | ||
import struct | ||
|
||
from ctypes import ( | ||
create_string_buffer | ||
) | ||
|
||
EFI_VAR_MAX_BUFFER_SIZE = 1024 * 1024 | ||
|
||
|
||
class UefiVariable(object): | ||
ERROR_ENVVAR_NOT_FOUND = 0xcb | ||
|
||
def __init__(self): | ||
pass | ||
|
||
# | ||
# Function to get variable | ||
# return a tuple of error code and variable data as string | ||
# | ||
def GetUefiVar(self, name, guid): | ||
# success | ||
err = 0 | ||
# the variable name is VariableName-Guid | ||
path = '/sys/firmware/efi/efivars/' + name + '-%s' % guid | ||
|
||
if not os.path.exists(path): | ||
err = UefiVariable.ERROR_ENVVAR_NOT_FOUND | ||
return (err, None) | ||
|
||
efi_var = create_string_buffer(EFI_VAR_MAX_BUFFER_SIZE) | ||
with open(path, 'rb') as fd: | ||
efi_var = fd.read() | ||
|
||
return (err, efi_var) | ||
|
||
# | ||
# Function to get all variable names | ||
# return a tuple of error code and variable names byte array formatted as: | ||
# | ||
# typedef struct _VARIABLE_NAME { | ||
# ULONG NextEntryOffset; | ||
# GUID VendorGuid; | ||
# WCHAR Name[ANYSIZE_ARRAY]; | ||
# } VARIABLE_NAME, *PVARIABLE_NAME; | ||
# | ||
def GetUefiAllVarNames(self): | ||
# success | ||
status = 0 | ||
|
||
# implementation borrowed from https://github.com/awslabs/python-uefivars/blob/main/pyuefivars/efivarfs.py | ||
path = '/sys/firmware/efi/efivars' | ||
if not os.path.exists(path): | ||
status = UefiVariable.ERROR_ENVVAR_NOT_FOUND | ||
return (status, None) | ||
|
||
vars = os.listdir(path) | ||
|
||
# get the total buffer length, converting to unicode | ||
length = 0 | ||
offset = 0 | ||
for var in vars: | ||
split_string = var.split('-') | ||
name = '-'.join(split_string[:-5]) | ||
name = name.encode('utf-16-le') | ||
name_len = len(name) | ||
length += (4 + 16 + name_len) | ||
|
||
efi_var_names = create_string_buffer(length) | ||
|
||
for var in vars: | ||
# efivarfs stores vars as NAME-GUID | ||
split_string = var.split('-') | ||
try: | ||
# GUID is last 5 elements of split_string | ||
guid = uuid.UUID('-'.join(split_string[-5:])).bytes_le | ||
except ValueError: | ||
raise Exception(f'Could not parse "{var}"') | ||
|
||
# the other part is the name | ||
name = '-'.join(split_string[:-5]) | ||
name = name.encode('utf-16-le') | ||
name_len = len(name) | ||
|
||
# NextEntryOffset | ||
struct.pack_into('<I', efi_var_names, offset, 4 + 16 + name_len) | ||
offset += 4 | ||
|
||
# VendorGuid | ||
struct.pack_into('=16s', efi_var_names, offset, guid) | ||
offset += 16 | ||
|
||
# Name | ||
struct.pack_into(f'={name_len}s', efi_var_names, offset, name) | ||
offset += name_len | ||
|
||
return (status, efi_var_names) | ||
|
||
# | ||
# Function to set variable | ||
# return a tuple of boolean status, error_code, error_string (None if not error) | ||
# | ||
def SetUefiVar(self, name, guid, var=None, attrs=None): | ||
success = 0 # Fail | ||
|
||
# There is a null terminator at the end of the name | ||
path = '/sys/firmware/efi/efivars/' + name[:-1] + '-' + str(guid) | ||
if var is None: | ||
# we are deleting the variable | ||
if (os.path.exists(path)): | ||
os.remove(path) | ||
success = 1 # expect non-zero success | ||
return success | ||
|
||
if attrs is None: | ||
attrs = 0x7 | ||
|
||
# if the file exists, remove the immutable flag | ||
if (os.path.exists(path)): | ||
os.system('sudo chattr -i ' + path) | ||
|
||
with open(path, 'wb') as fd: | ||
# var data is attribute (UINT32) followed by data | ||
packed = struct.pack('=I', attrs) | ||
packed += var | ||
fd.write(packed) | ||
|
||
return 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters