diff --git a/.azurepipelines/MuDevOpsWrapper.yml b/.azurepipelines/MuDevOpsWrapper.yml index 5950bd93..e8382838 100644 --- a/.azurepipelines/MuDevOpsWrapper.yml +++ b/.azurepipelines/MuDevOpsWrapper.yml @@ -19,7 +19,7 @@ resources: type: github endpoint: microsoft name: microsoft/mu_devops - ref: refs/tags/v9.1.9 + ref: refs/tags/v10.0.0 parameters: - name: do_ci_build diff --git a/.cspell.json b/.cspell.json index 4da8b900..269caea8 100644 --- a/.cspell.json +++ b/.cspell.json @@ -126,6 +126,9 @@ "profileid", "profileids", "prettyname", + "efivars", + "efivarfs", + "chattr", "typesonly", "nochange", "headerRef" diff --git a/.github/workflows/auto-approve.yml b/.github/workflows/auto-approve.yml index 4d8c5ec1..23b9389f 100644 --- a/.github/workflows/auto-approve.yml +++ b/.github/workflows/auto-approve.yml @@ -29,5 +29,5 @@ jobs: if: | github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'uefibot' - uses: microsoft/mu_devops/.github/workflows/AutoApprover.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/AutoApprover.yml@v10.0.0 secrets: inherit diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 84cf27a1..4f37dd5f 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -32,5 +32,5 @@ jobs: if: | github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'uefibot' - uses: microsoft/mu_devops/.github/workflows/AutoMerger.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/AutoMerger.yml@v10.0.0 secrets: inherit diff --git a/.github/workflows/issue-assignment.yml b/.github/workflows/issue-assignment.yml index 94735ebc..79196ea3 100644 --- a/.github/workflows/issue-assignment.yml +++ b/.github/workflows/issue-assignment.yml @@ -23,4 +23,4 @@ jobs: contents: read issues: write - uses: microsoft/mu_devops/.github/workflows/IssueAssignment.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/IssueAssignment.yml@v10.0.0 diff --git a/.github/workflows/label-issues.yml b/.github/workflows/label-issues.yml index dd78cb86..ffad0ec0 100644 --- a/.github/workflows/label-issues.yml +++ b/.github/workflows/label-issues.yml @@ -36,4 +36,4 @@ jobs: contents: read pull-requests: write - uses: microsoft/mu_devops/.github/workflows/Labeler.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/Labeler.yml@v10.0.0 diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml index c8b8f2a4..c4274642 100644 --- a/.github/workflows/label-sync.yml +++ b/.github/workflows/label-sync.yml @@ -28,4 +28,4 @@ jobs: permissions: issues: write - uses: microsoft/mu_devops/.github/workflows/LabelSyncer.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/LabelSyncer.yml@v10.0.0 diff --git a/.github/workflows/release-draft.yml b/.github/workflows/release-draft.yml index 71f1b2fe..6c60a1de 100644 --- a/.github/workflows/release-draft.yml +++ b/.github/workflows/release-draft.yml @@ -32,5 +32,5 @@ jobs: contents: write pull-requests: write - uses: microsoft/mu_devops/.github/workflows/ReleaseDrafter.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/ReleaseDrafter.yml@v10.0.0 secrets: inherit diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index fc34d6bf..5b94e822 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -29,4 +29,4 @@ jobs: issues: write pull-requests: write - uses: microsoft/mu_devops/.github/workflows/Stale.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/Stale.yml@v10.0.0 diff --git a/.github/workflows/triage-issues.yml b/.github/workflows/triage-issues.yml index 3c68005d..49780aae 100644 --- a/.github/workflows/triage-issues.yml +++ b/.github/workflows/triage-issues.yml @@ -23,4 +23,4 @@ jobs: permissions: issues: write - uses: microsoft/mu_devops/.github/workflows/IssueTriager.yml@v9.1.9 + uses: microsoft/mu_devops/.github/workflows/IssueTriager.yml@v10.0.0 diff --git a/.pytool/CISettings.py b/.pytool/CISettings.py index e6a2002c..173cc6d9 100644 --- a/.pytool/CISettings.py +++ b/.pytool/CISettings.py @@ -190,17 +190,17 @@ def GetDependencies(self): { "Path": "MU_BASECORE", "Url": "https://github.com/microsoft/mu_basecore.git", - "Branch": "release/202302" + "Branch": "release/202311" }, { "Path": "Common/MU_PLUS", "Url": "https://github.com/microsoft/mu_plus.git", - "Branch": "release/202302" + "Branch": "release/202311" }, { "Path": "Common/MU_TIANO_PLUS", "Url": "https://github.com/microsoft/mu_tiano_plus.git", - "Branch": "release/202302" + "Branch": "release/202311" } ] return [] diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/GoogleTest/ConfigKnobShimDxeLibGoogleTest.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/GoogleTest/ConfigKnobShimDxeLibGoogleTest.inf index d3b69a67..25913bc6 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/GoogleTest/ConfigKnobShimDxeLibGoogleTest.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/GoogleTest/ConfigKnobShimDxeLibGoogleTest.inf @@ -20,7 +20,6 @@ [Sources] ConfigKnobShimDxeLibGoogleTest.cpp - ../../ConfigKnobShimLibCommon.c [Packages] MdePkg/MdePkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/UnitTest/ConfigKnobShimDxeLibUnitTest.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/UnitTest/ConfigKnobShimDxeLibUnitTest.inf index 4a2a822a..61c274f0 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/UnitTest/ConfigKnobShimDxeLibUnitTest.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/UnitTest/ConfigKnobShimDxeLibUnitTest.inf @@ -21,7 +21,6 @@ [Sources] ../../UnitTest/ConfigKnobShimLibUnitTestCommon.c ../ConfigKnobShimDxeLib.c - ../../ConfigKnobShimLibCommon.c [Packages] MdePkg/MdePkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/ConfigKnobShimMmLib.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/ConfigKnobShimMmLib.inf index ef798bd1..3de16fea 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/ConfigKnobShimMmLib.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/ConfigKnobShimMmLib.inf @@ -25,7 +25,6 @@ [Sources] ConfigKnobShimMmLib.c ../ConfigKnobShimLibCommon.c - ../ConfigKnobShimLibCommon.h [Packages] MdePkg/MdePkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/UnitTest/ConfigKnobShimMmLibUnitTest.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/UnitTest/ConfigKnobShimMmLibUnitTest.inf index 12cb4421..f3de30fb 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/UnitTest/ConfigKnobShimMmLibUnitTest.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimMmLib/UnitTest/ConfigKnobShimMmLibUnitTest.inf @@ -21,7 +21,6 @@ [Sources] ../../UnitTest/ConfigKnobShimLibUnitTestCommon.c ../ConfigKnobShimMmLib.c - ../../ConfigKnobShimLibCommon.c [Packages] MdePkg/MdePkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/ConfigKnobShimPeiLib.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/ConfigKnobShimPeiLib.inf index b44510c9..df7a4be2 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/ConfigKnobShimPeiLib.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/ConfigKnobShimPeiLib.inf @@ -25,7 +25,7 @@ ConfigKnobShimPeiLib.c ../ConfigKnobShimLibCommon.c ../ConfigKnobShimLibCommon.h - + [Packages] MdePkg/MdePkg.dec SetupDataPkg/SetupDataPkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/GoogleTest/ConfigKnobShimPeiLibGoogleTest.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/GoogleTest/ConfigKnobShimPeiLibGoogleTest.inf index 163696ee..4ba4af6b 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/GoogleTest/ConfigKnobShimPeiLibGoogleTest.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/GoogleTest/ConfigKnobShimPeiLibGoogleTest.inf @@ -20,7 +20,6 @@ [Sources] ConfigKnobShimPeiLibGoogleTest.cpp - ../../ConfigKnobShimLibCommon.c MdePkg/Test/Mock/Library/GoogleTest/Ppi/MockReadOnlyVariable2.cpp [Packages] diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/UnitTest/ConfigKnobShimPeiLibUnitTest.inf b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/UnitTest/ConfigKnobShimPeiLibUnitTest.inf index 28281dd6..aed6c540 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/UnitTest/ConfigKnobShimPeiLibUnitTest.inf +++ b/SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimPeiLib/UnitTest/ConfigKnobShimPeiLibUnitTest.inf @@ -21,7 +21,6 @@ [Sources] ../../UnitTest/ConfigKnobShimLibUnitTestCommon.c ../ConfigKnobShimPeiLib.c - ../../ConfigKnobShimLibCommon.c [Packages] MdePkg/MdePkg.dec diff --git a/SetupDataPkg/Library/ConfigKnobShimLib/UnitTest/ConfigKnobShimLibUnitTestCommon.c b/SetupDataPkg/Library/ConfigKnobShimLib/UnitTest/ConfigKnobShimLibUnitTestCommon.c index e25e463a..6ed82614 100644 --- a/SetupDataPkg/Library/ConfigKnobShimLib/UnitTest/ConfigKnobShimLibUnitTestCommon.c +++ b/SetupDataPkg/Library/ConfigKnobShimLib/UnitTest/ConfigKnobShimLibUnitTestCommon.c @@ -25,7 +25,7 @@ #include // include the c file to be able to unit test static function -#include "ConfigKnobShimLibCommon.c" +#include "../ConfigKnobShimLibCommon.c" #define UNIT_TEST_APP_NAME "Config Knob Shim Common Lib Unit Tests" #define UNIT_TEST_APP_VERSION "1.0" diff --git a/SetupDataPkg/SetupDataPkg.ci.yaml b/SetupDataPkg/SetupDataPkg.ci.yaml index d5e058d0..1cbcc0fc 100644 --- a/SetupDataPkg/SetupDataPkg.ci.yaml +++ b/SetupDataPkg/SetupDataPkg.ci.yaml @@ -91,7 +91,10 @@ "dmpstore", "mschange", "DDTHH", - "prettyname" + "prettyname", + "efivars", + "efivarfs", + "chattr" ], # words to extend to the dictionary for this package "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported) diff --git a/SetupDataPkg/Tools/ReadUefiVarsToConfVarList.py b/SetupDataPkg/Tools/ReadUefiVarsToConfVarList.py index 395806ea..92a12234 100644 --- a/SetupDataPkg/Tools/ReadUefiVarsToConfVarList.py +++ b/SetupDataPkg/Tools/ReadUefiVarsToConfVarList.py @@ -12,7 +12,10 @@ import struct import uuid import ctypes -from SettingSupport.UefiVariablesSupportLib import UefiVariable +if os.name == 'nt': + from SettingSupport.UefiVariablesSupportLib import UefiVariable +else: + from SettingSupport.UefiVariablesSupportLinuxLib import UefiVariable from VariableList import Schema, UEFIVariable, create_vlist_buffer @@ -53,7 +56,7 @@ def option_parser(): # array # def read_variable_into_variable_list(uefi_var, name, namespace): - (rc, var, _) = uefi_var.GetUefiVar(name, namespace) + (rc, var) = uefi_var.GetUefiVar(name, namespace) if rc != 0: if rc != UefiVariable.ERROR_ENVVAR_NOT_FOUND: # only log the errors other than EFI_NOT_FOUND, because not found is normal in this case... @@ -78,7 +81,7 @@ def main(): ret = b'' if arguments.configuration_file is None: # Read all the variables - (rc, efi_var_names, error_string) = UefiVar.GetUefiAllVarNames() + (rc, efi_var_names) = UefiVar.GetUefiAllVarNames() if rc != 0: logging.error(f"Error returned from GetUefiAllVarNames: {rc}") @@ -117,9 +120,14 @@ def main(): console.setLevel(logging.CRITICAL) # check the privilege level and report error - if not ctypes.windll.shell32.IsUserAnAdmin(): - print("Administrator privilege required. Please launch from an Administrator privilege level.") - sys.exit(1) + if os.name == 'nt': + if not ctypes.windll.shell32.IsUserAnAdmin(): + print("Administrator privilege required. Please launch from an Administrator privilege level.") + sys.exit(1) + else: + if os.geteuid() != 0: + print("Root permission required, please run script with sudo.") + sys.exit(1) # call main worker function retcode = main() diff --git a/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLib.py b/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLib.py index 3db0dc82..7a6c1e32 100644 --- a/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLib.py +++ b/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLib.py @@ -10,7 +10,6 @@ c_wchar_p, c_void_p, c_int, - c_char, create_string_buffer, WinError, pointer @@ -90,27 +89,6 @@ def __init__(self): ) pass - # - # Helper function to create buffer for var read/write - # - def CreateBuffer(self, init, size=None): - """CreateBuffer(aString) -> character array - CreateBuffer(anInteger) -> character array - CreateBuffer(aString, anInteger) -> character array - """ - if isinstance(init, str): - if size is None: - size = len(init) + 1 - buftype = c_char * size - buf = buftype() - buf.value = init - return buf - elif isinstance(init, int): - buftype = c_char * init - buf = buftype() - return buf - raise TypeError(init) - # # Function to get variable # return a tuple of error code and variable data as string @@ -135,8 +113,8 @@ def GetUefiVar(self, name, guid): ) logging.error(WinError()) if efi_var is None: - return (err, None, WinError(err)) - return (err, efi_var[:length], WinError(err)) + return (err, None) + return (err, efi_var[:length]) # # Function to get all variable names @@ -176,8 +154,8 @@ def GetUefiAllVarNames(self): logging.error( "EnumerateFirmwareEnvironmentVariable failed (GetLastError = 0x%x)" % status ) - return (status, None, WinError(status)) - return (status, efi_var_names, None) + return (status, None) + return (status, efi_var_names) # # Function to set variable @@ -186,7 +164,6 @@ def GetUefiAllVarNames(self): def SetUefiVar(self, name, guid, var=None, attrs=None): var_len = 0 err = 0 - error_string = None if var is None: var = bytes(0) else: @@ -221,5 +198,4 @@ def SetUefiVar(self, name, guid, var=None, attrs=None): "SetFirmwareEnvironmentVariable failed (GetLastError = 0x%x)" % err ) logging.error(WinError()) - error_string = WinError(err) - return (success, err, error_string) + return success diff --git a/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLinuxLib.py b/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLinuxLib.py new file mode 100644 index 00000000..0558b6cd --- /dev/null +++ b/SetupDataPkg/Tools/SettingSupport/UefiVariablesSupportLinuxLib.py @@ -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('