From 49ae5bc2f89058bb781e4ce6421deeced75202b5 Mon Sep 17 00:00:00 2001 From: PMheart <17109513+PMheart@users.noreply.github.com> Date: Mon, 1 Feb 2021 06:49:07 +0800 Subject: [PATCH] ocvalidate: Add NVRAM key/value sanitising support (#178) --- Utilities/ocvalidate/KextInfo.h | 24 +- Utilities/ocvalidate/Makefile | 13 +- Utilities/ocvalidate/NvramKeyInfo.c | 188 +++++++++ Utilities/ocvalidate/NvramKeyInfo.h | 51 +++ Utilities/ocvalidate/OcValidateLib.c | 43 +- Utilities/ocvalidate/OcValidateLib.h | 45 ++- Utilities/ocvalidate/README.md | 18 +- Utilities/ocvalidate/ValidateAcpi.c | 8 +- Utilities/ocvalidate/ValidateBooter.c | 24 +- .../ocvalidate/ValidateDeviceProperties.c | 19 +- Utilities/ocvalidate/ValidateKernel.c | 21 +- Utilities/ocvalidate/ValidateMisc.c | 53 ++- Utilities/ocvalidate/ValidateNVRAM.c | 324 --------------- Utilities/ocvalidate/ValidateNvram.c | 379 ++++++++++++++++++ Utilities/ocvalidate/ValidatePlatformInfo.c | 16 +- Utilities/ocvalidate/ValidateUEFI.c | 14 +- Utilities/ocvalidate/ocvalidate.c | 37 +- Utilities/ocvalidate/ocvalidate.h | 22 +- 18 files changed, 850 insertions(+), 449 deletions(-) create mode 100644 Utilities/ocvalidate/NvramKeyInfo.c create mode 100644 Utilities/ocvalidate/NvramKeyInfo.h delete mode 100644 Utilities/ocvalidate/ValidateNVRAM.c create mode 100644 Utilities/ocvalidate/ValidateNvram.c diff --git a/Utilities/ocvalidate/KextInfo.h b/Utilities/ocvalidate/KextInfo.h index 3cf89773..910a941f 100644 --- a/Utilities/ocvalidate/KextInfo.h +++ b/Utilities/ocvalidate/KextInfo.h @@ -19,32 +19,32 @@ #define INDEX_KEXT_LILU 0U #define INDEX_KEXT_VSMC 1U -// -// Child kext must be put after Parent kext in OpenCore config->Kernel->Add. -// This means that the index of Child kext must be greater than that of Parent kext. -// +/** + Child kext must be put after Parent kext in OpenCore config->Kernel->Add. + This means that the index of Child must succeed that of Parent. +**/ typedef struct KEXT_PRECEDENCE_ { CONST CHAR8 *Child; CONST CHAR8 *Parent; } KEXT_PRECEDENCE; -// -// Sanitiser for known kext info. Mainly those from Acidanthera. -// +/** + Known information of kexts. Mainly those from Acidanthera. +**/ typedef struct KEXT_INFO_ { CONST CHAR8 *KextBundlePath; CONST CHAR8 *KextExecutablePath; CONST CHAR8 *KextPlistPath; } KEXT_INFO; -extern KEXT_PRECEDENCE mKextPrecedence[]; -extern UINTN mKextPrecedenceSize; +extern KEXT_PRECEDENCE mKextPrecedence[]; +extern UINTN mKextPrecedenceSize; -extern KEXT_INFO mKextInfo[]; -extern UINTN mKextInfoSize; +extern KEXT_INFO mKextInfo[]; +extern UINTN mKextInfoSize; /** - ASSERT() on mismatched kext info. + ASSERT() on incorrect placed kext info, where a set of rules must be followed. **/ VOID ValidateKextInfo ( diff --git a/Utilities/ocvalidate/Makefile b/Utilities/ocvalidate/Makefile index 13419e44..15ee8e0b 100644 --- a/Utilities/ocvalidate/Makefile +++ b/Utilities/ocvalidate/Makefile @@ -5,7 +5,18 @@ PROJECT = ocvalidate PRODUCT = $(PROJECT)$(SUFFIX) -OBJS = $(PROJECT).o OcValidateLib.o KextInfo.o ValidateAcpi.o ValidateBooter.o ValidateDeviceProperties.o ValidateKernel.o ValidateMisc.o ValidateNVRAM.o ValidatePlatformInfo.o ValidateUEFI.o +OBJS = $(PROJECT).o \ + OcValidateLib.o \ + KextInfo.o \ + NvramKeyInfo.o \ + ValidateAcpi.o \ + ValidateBooter.o \ + ValidateDeviceProperties.o \ + ValidateKernel.o \ + ValidateMisc.o \ + ValidateNvram.o \ + ValidatePlatformInfo.o \ + ValidateUEFI.o # # OcConfigurationLib targets. # diff --git a/Utilities/ocvalidate/NvramKeyInfo.c b/Utilities/ocvalidate/NvramKeyInfo.c new file mode 100644 index 00000000..b0f291b5 --- /dev/null +++ b/Utilities/ocvalidate/NvramKeyInfo.c @@ -0,0 +1,188 @@ +/** @file + Copyright (C) 2018, vit9696. All rights reserved. + Copyright (C) 2020, PMheart. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "NvramKeyInfo.h" + +STATIC +BOOLEAN +ValidateNvramKeySize8 ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + (VOID) Value; + + return ValueSize == sizeof (UINT8); +} + +STATIC +BOOLEAN +ValidateNvramKeySize32 ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + (VOID) Value; + + return ValueSize == sizeof (UINT32); +} + +STATIC +BOOLEAN +ValidateNvramKeySize64 ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + (VOID) Value; + + return ValueSize == sizeof (UINT64); +} + +STATIC +BOOLEAN +ValidateUIScale ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + UINTN Index; + CONST UINT8 *UIScaleValue; + STATIC CONST UINT8 AllowedUIScaleValue[] = { + 0x01, + 0x02 ///< HiDPI + }; + + UIScaleValue = (CONST UINT8 *) Value; + + if (!ValidateNvramKeySize8 (NULL, ValueSize)) { + return FALSE; + } + + for (Index = 0; Index < ARRAY_SIZE (AllowedUIScaleValue); ++Index) { + if (*UIScaleValue == AllowedUIScaleValue[Index]) { + return TRUE; + } + } + + return FALSE; +} + +STATIC +BOOLEAN +ValidateNvdaDrv ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + UINTN Index; + CONST UINT8 *NvdaDrvValue; + STATIC CONST UINT8 AllowedNvdaDrvValue[] = { + 0x30, ///< "0" - WebDriver off + 0x31 ///< "1" - WebDriver on + }; + + NvdaDrvValue = (CONST UINT8 *) Value; + + if (!ValidateNvramKeySize8 (NULL, ValueSize)) { + return FALSE; + } + + for (Index = 0; Index < ARRAY_SIZE (AllowedNvdaDrvValue); ++Index) { + if (*NvdaDrvValue == AllowedNvdaDrvValue[Index]) { + return TRUE; + } + } + + return FALSE; +} + +STATIC +BOOLEAN +ValidateBootArgs ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + CONST CHAR8 *BootArgsValue; + + BootArgsValue = (CONST CHAR8 *) Value; + + return OcAsciiStringNPrintable (BootArgsValue, ValueSize); +} + +STATIC +BOOLEAN +ValidateBooterCfg ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + // + // bootercfg is similar to boot-args. + // + return ValidateBootArgs (Value, ValueSize); +} + +STATIC +BOOLEAN +ValidateDefaultBackgroundColor ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ) +{ + // + // Cast Value to UINT8 * to ensure alignment. + // + CONST UINT8 *DefaultBackgroundColorValue; + + DefaultBackgroundColorValue = (CONST UINT8 *) Value; + + // + // Even if casted to UINT8 *, DefaultBackgroundColor is still 32-bit. + // + if (!ValidateNvramKeySize32 (NULL, ValueSize)) { + return FALSE; + } + + // + // The last byte must be zero. + // + return DefaultBackgroundColorValue[3] == 0U; +} + +STATIC NVRAM_KEY_MAP mAppleBootVariableGuidKeyMaps[] = { + { "nvda_drv", ValidateNvdaDrv }, + { "boot-args", ValidateBootArgs }, + { "bootercfg", ValidateBooterCfg }, + { "csr-active-config", ValidateNvramKeySize32 }, + { "StartupMute", ValidateNvramKeySize8 }, + { "SystemAudioVolume", ValidateNvramKeySize8 }, +}; + +STATIC NVRAM_KEY_MAP mAppleVendorVariableGuidKeyMaps[] = { + { "UIScale", ValidateUIScale }, + { "FirmwareFeatures", ValidateNvramKeySize32 }, + { "ExtendedFirmwareFeatures", ValidateNvramKeySize64 }, + { "FirmwareFeaturesMask", ValidateNvramKeySize32 }, + { "ExtendedFirmwareFeatures", ValidateNvramKeySize64 }, + { "DefaultBackgroundColor", ValidateDefaultBackgroundColor }, +}; + +NVRAM_GUID_MAP mGUIDMaps[] = { + { &gAppleBootVariableGuid, &mAppleBootVariableGuidKeyMaps[0], ARRAY_SIZE (mAppleBootVariableGuidKeyMaps) }, + { &gAppleVendorVariableGuid, &mAppleVendorVariableGuidKeyMaps[0], ARRAY_SIZE (mAppleVendorVariableGuidKeyMaps) }, +}; +UINTN mGUIDMapsCount = ARRAY_SIZE (mGUIDMaps); diff --git a/Utilities/ocvalidate/NvramKeyInfo.h b/Utilities/ocvalidate/NvramKeyInfo.h new file mode 100644 index 00000000..f7366e17 --- /dev/null +++ b/Utilities/ocvalidate/NvramKeyInfo.h @@ -0,0 +1,51 @@ +/** @file + Copyright (C) 2018, vit9696. All rights reserved. + Copyright (C) 2020, PMheart. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef OC_USER_UTILITIES_OCVALIDATE_NVRAM_KEY_INFO_H +#define OC_USER_UTILITIES_OCVALIDATE_NVRAM_KEY_INFO_H + +#include + +/** + Check whether one NVRAM key has accepted value. +**/ +typedef +BOOLEAN +(*NVRAM_KEY_CHECK) ( + IN CONST VOID *Value, + IN UINT32 ValueSize + ); + +/** + Structure holding NVRAM key maps. +**/ +typedef struct NVRAM_KEY_MAP_ { + CONST CHAR8 *KeyName; + NVRAM_KEY_CHECK KeyChecker; +} NVRAM_KEY_MAP; + +/** + Structure holding NVRAM GUID maps. +**/ +typedef struct NVRAM_GUID_MAP_ { + CONST EFI_GUID *Guid; + CONST NVRAM_KEY_MAP *NvramKeyMaps; + UINTN NvramKeyMapsCount; +} NVRAM_GUID_MAP; + +extern NVRAM_GUID_MAP mGUIDMaps[]; +extern UINTN mGUIDMapsCount; + +#endif // OC_USER_UTILITIES_OCVALIDATE_NVRAM_KEY_INFO_H diff --git a/Utilities/ocvalidate/OcValidateLib.c b/Utilities/ocvalidate/OcValidateLib.c index c04f1bcb..146cdc76 100644 --- a/Utilities/ocvalidate/OcValidateLib.c +++ b/Utilities/ocvalidate/OcValidateLib.c @@ -275,7 +275,7 @@ AsciiDevicePathIsLegal ( if (OcStriCmp (UnicodeDevicePath, TextualDevicePath) != 0) { DEBUG (( DEBUG_WARN, - "Original path: %s\nPath after internal conversion: %s\n\n", + "Original path: %s\nPath after internal conversion: %s\n", UnicodeDevicePath, TextualDevicePath )); @@ -304,6 +304,9 @@ AsciiGuidIsLegal ( Status = AsciiStrToGuid (AsciiGuid, &Guid); + // + // AsciiStrToGuid should never return errors on valid GUID. + // return !EFI_ERROR (Status); } @@ -322,6 +325,9 @@ DataHasProperMasking ( ByteMask = Mask; for (Index = 0; Index < Size; ++Index) { + // + // Mask should only be set when corresponding bits on Data are inactive. + // if ((ByteData[Index] & ~ByteMask[Index]) != 0) { return FALSE; } @@ -349,6 +355,9 @@ ValidatePatch ( ErrorCount = 0; + // + // If size of Find cannot be zero and it is different from that of Replace, then error. + // if (!FindSizeCanBeZero && FindSize != ReplaceSize) { DEBUG (( DEBUG_WARN, @@ -362,6 +371,9 @@ ValidatePatch ( } if (MaskSize > 0) { + // + // If Mask is set, but its size is different from that of Find, then error. + // if (MaskSize != FindSize) { DEBUG (( DEBUG_WARN, @@ -373,6 +385,9 @@ ValidatePatch ( )); ++ErrorCount; } else if (!DataHasProperMasking (Find, Mask, FindSize)) { + // + // If Mask is set without corresponding bits being active for Find, then error. + // DEBUG (( DEBUG_WARN, "%a[%u]->Find requires Mask to be active for corresponding bits!\n", @@ -382,8 +397,11 @@ ValidatePatch ( ++ErrorCount; } } - + if (ReplaceMaskSize > 0) { + // + // If ReplaceMask is set, but its size is different from that of Replace, then error. + // if (ReplaceMaskSize != ReplaceSize) { DEBUG (( DEBUG_WARN, @@ -395,6 +413,9 @@ ValidatePatch ( )); ++ErrorCount; } else if (!DataHasProperMasking (Replace, ReplaceMask, ReplaceSize)) { + // + // If ReplaceMask is set without corresponding bits being active for Replace, then error. + // DEBUG (( DEBUG_WARN, "%a[%u]->Replace requires ReplaceMask to be active for corresponding bits!\n", @@ -448,23 +469,19 @@ FindArrayDuplication ( BOOLEAN StringIsDuplicated ( IN CONST CHAR8 *EntrySection, - IN CONST CHAR8 *PrimaryEntry, - IN CONST CHAR8 *SecondaryEntry + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString ) { - BOOLEAN HasDup; - - HasDup = FALSE; - - if (AsciiStrCmp (PrimaryEntry, SecondaryEntry) == 0) { + if (AsciiStrCmp (FirstString, SecondString) == 0) { // - // Print duplicated entries. Index will be printed in the parent function (FindArrayDuplication). + // Print duplicated entries whose index will be printed in the parent function (FindArrayDuplication). // - DEBUG ((DEBUG_WARN, "%a: %a is duplicated ", EntrySection, PrimaryEntry[0] != '\0' ? PrimaryEntry : "")); - HasDup = TRUE; + DEBUG ((DEBUG_WARN, "%a: %a is duplicated ", EntrySection, FirstString[0] != '\0' ? FirstString : "")); + return TRUE; } - return HasDup; + return FALSE; } UINT32 diff --git a/Utilities/ocvalidate/OcValidateLib.h b/Utilities/ocvalidate/OcValidateLib.h index e79fe3f9..471b2538 100644 --- a/Utilities/ocvalidate/OcValidateLib.h +++ b/Utilities/ocvalidate/OcValidateLib.h @@ -73,7 +73,7 @@ AsciiIdentifierIsLegal ( Check if an OpenCore Configuration Arch matches specific conventions. @param[in] Arch Arch to be checked. - @param[in] IsKernelArch Whether to perform special checks for Kernel->Scheme->KernelArch. + @param[in] IsKernelArch TRUE to perform special checks for Kernel->Scheme->KernelArch. @retval TRUE If Arch matches conventions. **/ @@ -84,7 +84,8 @@ AsciiArchIsLegal ( ); /** - Check if an OpenCore Configuration Property contains only ASCII printable characters. Mainly used in device properties and NVRAM properties. + Check if an OpenCore Configuration Property contains only ASCII printable characters. + This is mainly used in Device Properties and NVRAM Properties. @param[in] Property Property to be checked. @@ -122,7 +123,7 @@ AsciiDevicePathIsLegal ( /** Check if a GUID in ASCII is valid. - @param[in] AsciiGuid GUID to be checked. + @param[in] AsciiGuid GUID in ASCII format to be checked. @retval TRUE If AsciiGuid has valid GUID format. **/ @@ -137,7 +138,7 @@ AsciiGuidIsLegal ( This function assumes identical sizes of Data and Mask, which must be ensured before calling. @param[in] Data Data to be checked. - @param[in] Mask Mask to be paired with Data. + @param[in] Mask Mask to be applied to Data. @param[in] Size Size of Data and Mask. @retval TRUE If corresponding bits of Mask to Data are active (set to non-zero). @@ -152,23 +153,23 @@ DataHasProperMasking ( /** Check if an OpenCore binary patch is valid. - If size of Find pattern cannot be zero, and size of Find pattern is different from that of Replace pattern, it is an error. - If Mask/ReplaceMask is used, but its size is different from that of Find/Replace, it is an error. - If Mask/ReplaceMask is used without corresponding bits being active for Find/Replace pattern, it is an error. + If size of Find cannot be zero and it is different from that of Replace, then error. + If Mask/ReplaceMask is set, but its size is different from that of Find/Replace, then error. + If Mask/ReplaceMask is set without corresponding bits being active for Find/Replace, then error. @param[in] PatchSection Patch section to which the patch to be checked belongs. @param[in] PatchIndex Index of the patch to be checked. - @param[in] FindSizeCanBeZero Whether size of Find pattern can be zero. Set to TRUE only when Kernel->Patch->Base is used and Find is empty. + @param[in] FindSizeCanBeZero Whether size of Find can be zero. This should be set to TRUE only when Kernel->Patch->Base is used and Find is empty. @param[in] Find Find pattern to be checked. - @param[in] FindSize Size of Find pattern to be checked. + @param[in] FindSize Size of Find pattern above. @param[in] Replace Replace pattern to be checked. - @param[in] ReplaceSize Size of Replace pattern to be checked. + @param[in] ReplaceSize Size of Replace pattern above. @param[in] Mask Mask pattern to be checked. - @param[in] MaskSize Size of Mask pattern to be checked. + @param[in] MaskSize Size of Mask pattern above. @param[in] ReplaceMask ReplaceMask pattern to be checked. - @param[in] ReplaceMaskSize Size of ReplaceMask pattern to be checked. + @param[in] ReplaceMaskSize Size of ReplaceMask pattern above. - @return Number of errors detected, which are treated as errors to be cumulated to the whole number of errors found in a single checker. + @return Number of errors detected, which are counted to the total number of errors discovered. **/ UINT32 ValidatePatch ( @@ -203,7 +204,7 @@ BOOLEAN @param[in] Size Size in bytes of each element in the array. @param[in] DupChecker Pointer to a comparator function which returns TRUE if duplication is found. See DUPLICATION_CHECK for function prototype. - @return Number of duplications detected, which are treated as errors to be cumulated to the whole number of errors found in a single checker. + @return Number of duplications detected, which are counted to the total number of errors discovered. **/ UINT32 FindArrayDuplication ( @@ -216,23 +217,23 @@ FindArrayDuplication ( /** Check if two strings are duplicated to each other. Used as a wrapper of AsciiStrCmp to print duplicated entries. - @param[in] EntrySection Section of strings to which they belong. - @param[in] PrimaryEntry Primary entry in string format. - @param[in] SecondaryEntry Secondary entry in string format. + @param[in] EntrySection Section of strings to which they belong throughout OpenCore Configuration. + @param[in] FirstString Primary entry in string format. + @param[in] SecondString Secondary entry in string format. - @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated to each other. + @retval TRUE If FirstString and SecondString are duplicated. **/ BOOLEAN StringIsDuplicated ( IN CONST CHAR8 *EntrySection, - IN CONST CHAR8 *PrimaryEntry, - IN CONST CHAR8 *SecondaryEntry + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString ); /** - Report status of errors in the end of each checker functions. + Report status of errors in the end of each checker function. - @param[in] FuncName Checker function name. (__func__) + @param[in] FuncName Checker function name. (__func__ in most cases) @param[in] ErrorCount Number of errors to be returned. @return Number of errors detected in one checker. diff --git a/Utilities/ocvalidate/README.md b/Utilities/ocvalidate/README.md index d1ba64c3..b9a73249 100644 --- a/Utilities/ocvalidate/README.md +++ b/Utilities/ocvalidate/README.md @@ -61,6 +61,8 @@ Utility to validate whether a `config.plist` matches requirements and convention - KernelCache: Only `Auto`, `Cacheless`, `Mkext`, or `Prelinked` are accepted. ### Misc +#### BlessOverride +- Entries cannot be `\EFI\Microsoft\Boot\bootmgfw.efi` or `\System\Library\CoreServices\boot.efi` since OpenCore knows these paths. #### Boot - HibernateMode: Only `None`, `Auto`, `RTC`, or `NVRAM` are accepted. - PickerMode: Only `Builtin`, `External`, or `Apple` are accepted. @@ -72,7 +74,21 @@ Utility to validate whether a `config.plist` matches requirements and convention - SecureBootModel: Only `Default`, `Disabled`, `j137`, `j680`, `j132`, `j174`, `j140k`, `j780`, `j213`, `j140a`, `j152f`, `j160`, `j230k`, `j214k`, `j223`, `j215`, `j185`, `j185f`, or `x86legacy` are accepted. ### NVRAM -- Requirements here all follow Global Rules. +- Requirements here all follow Global Rules. In addition, the following keys and values are checked: +#### gAppleBootVariableGuid (`7C436110-AB2A-4BBB-A880-FE41995C9F82`) +- `nvda_drv` must have type `Plist Data` with the value of `0x30` or `0x31`. +- `boot-args` must be an ASCII string (thus `Plist String`) without trailing `\0`. +- `bootercfg` must be an ASCII string (thus `Plist String`) without trailing `\0`. +- `csr-active-config` must have type `Plist Data` and have length of 4 bytes. +- `StartupMute` must have type `Plist Data` and have length of 1 byte. +- `SystemAudioVolume` must have type `Plist Data` and have length of 1 byte. +#### gAppleVendorVariableGuid (`4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14`) +- `UIScale` must have type `Plist Data` with the value of `0x01` or `0x02`. +- `FirmwareFeatures` must have type `Plist Data` and have length of 4 bytes. +- `ExtendedFirmwareFeatures` must have type `Plist Data` and have length of 8 bytes. +- `FirmwareFeaturesMask` must have type `Plist Data` and have length of 4 bytes. +- `ExtendedFirmwareFeatures` must have type `Plist Data` and have length of 8 bytes. +- `DefaultBackgroundColor` must have type `Plist Data` and have length of 4 bytes. Also, its last byte must be `0x00`. ### PlatformInfo - UpdateSMBIOSMode: Only `TryOverwrite`, `Create`, `Overwrite`, or `Custom` are accepted. diff --git a/Utilities/ocvalidate/ValidateAcpi.c b/Utilities/ocvalidate/ValidateAcpi.c index 554f467f..a694641f 100644 --- a/Utilities/ocvalidate/ValidateAcpi.c +++ b/Utilities/ocvalidate/ValidateAcpi.c @@ -17,7 +17,7 @@ #include "OcValidateLib.h" /** - Callback funtion to verify whether Path is duplicated in ACPI->Add. + Callback function to verify whether Path is duplicated in ACPI->Add. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -205,9 +205,9 @@ CheckACPI ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK ACPICheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK ACPICheckers[] = { &CheckACPIAdd, &CheckACPIDelete, &CheckACPIPatch diff --git a/Utilities/ocvalidate/ValidateBooter.c b/Utilities/ocvalidate/ValidateBooter.c index 87807c6e..efef777d 100644 --- a/Utilities/ocvalidate/ValidateBooter.c +++ b/Utilities/ocvalidate/ValidateBooter.c @@ -30,15 +30,19 @@ CheckBooterMmioWhitelist ( BOOLEAN ShouldEnableDevirtualiseMmio; BOOLEAN IsDevirtualiseMmioEnabled; - ErrorCount = 0; - UserBooter = &Config->Booter; - IsMmioWhitelistEnabled = FALSE; - ShouldEnableDevirtualiseMmio = FALSE; - IsDevirtualiseMmioEnabled = UserBooter->Quirks.DevirtualiseMmio; + ErrorCount = 0; + UserBooter = &Config->Booter; + IsDevirtualiseMmioEnabled = UserBooter->Quirks.DevirtualiseMmio; + IsMmioWhitelistEnabled = FALSE; + ShouldEnableDevirtualiseMmio = FALSE; for (Index = 0; Index < UserBooter->MmioWhitelist.Count; ++Index) { Comment = OC_BLOB_GET (&UserBooter->MmioWhitelist.Values[Index]->Comment); IsMmioWhitelistEnabled = UserBooter->MmioWhitelist.Values[Index]->Enabled; + // + // DevirtualiseMmio should be enabled if at least one entry is enabled. + // + ShouldEnableDevirtualiseMmio = IsMmioWhitelistEnabled; // // Sanitise strings. @@ -47,10 +51,6 @@ CheckBooterMmioWhitelist ( DEBUG ((DEBUG_WARN, "Booter->MmioWhitelist[%u]->Comment contains illegal character!\n", Index)); ++ErrorCount; } - - if (IsMmioWhitelistEnabled) { - ShouldEnableDevirtualiseMmio = TRUE; - } } if (ShouldEnableDevirtualiseMmio && !IsDevirtualiseMmioEnabled) { @@ -214,9 +214,9 @@ CheckBooter ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK BooterCheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK BooterCheckers[] = { &CheckBooterMmioWhitelist, &CheckBooterPatch, &CheckBooterQuirks diff --git a/Utilities/ocvalidate/ValidateDeviceProperties.c b/Utilities/ocvalidate/ValidateDeviceProperties.c index f25cda81..47bf9387 100644 --- a/Utilities/ocvalidate/ValidateDeviceProperties.c +++ b/Utilities/ocvalidate/ValidateDeviceProperties.c @@ -17,7 +17,7 @@ #include "OcValidateLib.h" /** - Callback funtion to verify whether one entry is duplicated in DeviceProperties->Add. + Callback function to verify whether one entry is duplicated in DeviceProperties->Add. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -45,7 +45,7 @@ DevPropsAddHasDuplication ( } /** - Callback funtion to verify whether one entry is duplicated in DeviceProperties->Delete. + Callback function to verify whether one entry is duplicated in DeviceProperties->Delete. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -90,15 +90,14 @@ CheckDevicePropertiesAdd ( UserDevProp = &Config->DeviceProperties; for (DeviceIndex = 0; DeviceIndex < UserDevProp->Add.Count; ++DeviceIndex) { - AsciiDevicePath = OC_BLOB_GET (UserDevProp->Add.Keys[DeviceIndex]); + AsciiDevicePath = OC_BLOB_GET (UserDevProp->Add.Keys[DeviceIndex]); if (!AsciiDevicePathIsLegal (AsciiDevicePath)) { DEBUG ((DEBUG_WARN, "DeviceProperties->Add[%u]->DevicePath is borked! Please check the information above!\n", DeviceIndex)); ++ErrorCount; } - PropertyMap = UserDevProp->Add.Values[DeviceIndex]; - + PropertyMap = UserDevProp->Add.Values[DeviceIndex]; for (PropertyIndex = 0; PropertyIndex < PropertyMap->Count; ++PropertyIndex) { AsciiProperty = OC_BLOB_GET (PropertyMap->Keys[PropertyIndex]); @@ -153,11 +152,11 @@ CheckDevicePropertiesDelete ( CONST CHAR8 *AsciiDevicePath; CONST CHAR8 *AsciiProperty; - ErrorCount = 0; + ErrorCount = 0; UserDevProp = &Config->DeviceProperties; for (DeviceIndex = 0; DeviceIndex < UserDevProp->Delete.Count; ++DeviceIndex) { - AsciiDevicePath = OC_BLOB_GET (UserDevProp->Delete.Keys[DeviceIndex]); + AsciiDevicePath = OC_BLOB_GET (UserDevProp->Delete.Keys[DeviceIndex]); if (!AsciiDevicePathIsLegal (AsciiDevicePath)) { DEBUG ((DEBUG_WARN, "DeviceProperties->Delete[%u]->DevicePath is borked! Please check the information above!\n", DeviceIndex)); @@ -210,9 +209,9 @@ CheckDeviceProperties ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK DevicePropertiesCheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK DevicePropertiesCheckers[] = { &CheckDevicePropertiesAdd, &CheckDevicePropertiesDelete }; diff --git a/Utilities/ocvalidate/ValidateKernel.c b/Utilities/ocvalidate/ValidateKernel.c index 776dd5c6..11d50852 100644 --- a/Utilities/ocvalidate/ValidateKernel.c +++ b/Utilities/ocvalidate/ValidateKernel.c @@ -20,7 +20,7 @@ #include /** - Callback funtion to verify whether BundlePath is duplicated in Kernel->Add. + Callback function to verify whether BundlePath is duplicated in Kernel->Add. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -52,7 +52,7 @@ KernelAddHasDuplication ( } /** - Callback funtion to verify whether Identifier is duplicated in Kernel->Block. + Callback function to verify whether Identifier is duplicated in Kernel->Block. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -84,7 +84,7 @@ KernelBlockHasDuplication ( } /** - Callback funtion to verify whether BundlePath is duplicated in Kernel->Force. + Callback function to verify whether BundlePath is duplicated in Kernel->Force. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -355,6 +355,7 @@ CheckKernelEmulate ( OC_KERNEL_CONFIG *UserKernel; CONST CHAR8 *MaxKernel; CONST CHAR8 *MinKernel; + BOOLEAN Result; ErrorCount = 0; UserKernel = &Config->Kernel; @@ -373,7 +374,13 @@ CheckKernelEmulate ( ++ErrorCount; } - if (!DataHasProperMasking (UserKernel->Emulate.Cpuid1Data, UserKernel->Emulate.Cpuid1Mask, sizeof (UserKernel->Emulate.Cpuid1Data))) { + Result = DataHasProperMasking ( + UserKernel->Emulate.Cpuid1Data, + UserKernel->Emulate.Cpuid1Mask, + sizeof (UserKernel->Emulate.Cpuid1Data) + ); + + if (!Result) { DEBUG ((DEBUG_WARN, "Kernel->Emulate->Cpuid1Data requires Cpuid1Mask to be active for replaced bits!\n")); ++ErrorCount; } @@ -644,9 +651,9 @@ CheckKernel ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK KernelCheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK KernelCheckers[] = { &CheckKernelAdd, &CheckKernelBlock, &CheckKernelEmulate, diff --git a/Utilities/ocvalidate/ValidateMisc.c b/Utilities/ocvalidate/ValidateMisc.c index 769b40c6..ca98cf97 100644 --- a/Utilities/ocvalidate/ValidateMisc.c +++ b/Utilities/ocvalidate/ValidateMisc.c @@ -23,7 +23,7 @@ #include /** - Callback funtion to verify whether Arguments and Path are duplicated in Misc->Entries. + Callback function to verify whether Arguments and Path are duplicated in Misc->Entries. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -68,7 +68,7 @@ MiscEntriesHasDuplication ( } /** - Callback funtion to verify whether Arguments and Path are duplicated in Misc->Tools. + Callback function to verify whether Arguments and Path are duplicated in Misc->Tools. @param[in] PrimaryEntry Primary entry to be checked. @param[in] SecondaryEntry Secondary entry to be checked. @@ -122,8 +122,8 @@ ValidateSecureBootModel ( IN CONST CHAR8 *SecureBootModel ) { - UINTN Index; - CONST CHAR8 *AllowedSecureBootModel[] = { + UINTN Index; + STATIC CONST CHAR8 *AllowedSecureBootModel[] = { "Default", "Disabled", "j137", "j680", "j132", "j174", "j140k", "j780", "j213", "j140a", "j152f", "j160", @@ -140,6 +140,44 @@ ValidateSecureBootModel ( return FALSE; } +STATIC +UINT32 +CheckBlessOverride ( + IN OC_GLOBAL_CONFIG *Config + ) +{ + UINT32 ErrorCount; + UINT32 Index; + UINTN Index2; + OC_MISC_CONFIG *UserMisc; + CONST CHAR8 *BlessOverrideEntry; + STATIC CONST CHAR8 *DisallowedBlessOverrideValues[] = { + "\\EFI\\Microsoft\\Boot\\bootmgfw.efi", + "\\System\\Library\\CoreServices\\boot.efi", + }; + + ErrorCount = 0; + UserMisc = &Config->Misc; + + for (Index = 0; Index < UserMisc->BlessOverride.Count; ++Index) { + BlessOverrideEntry = OC_BLOB_GET (UserMisc->BlessOverride.Values[Index]); + + // + // &DisallowedBlessOverrideValues[][1] means no first '\\'. + // + for (Index2 = 0; Index2 < ARRAY_SIZE (DisallowedBlessOverrideValues); ++Index2) { + if (AsciiStrCmp (BlessOverrideEntry, DisallowedBlessOverrideValues[Index2]) == 0 + || AsciiStrCmp (BlessOverrideEntry, &DisallowedBlessOverrideValues[Index2][1]) == 0) { + DEBUG ((DEBUG_WARN, "Misc->BlessOverride: %a is redundant!\n", BlessOverrideEntry)); + ++ErrorCount; + } + } + + } + + return ErrorCount; +} + STATIC UINT32 CheckMiscBoot ( @@ -500,9 +538,10 @@ CheckMisc ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK MiscCheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK MiscCheckers[] = { + &CheckBlessOverride, &CheckMiscBoot, &CheckMiscDebug, &CheckMiscEntries, diff --git a/Utilities/ocvalidate/ValidateNVRAM.c b/Utilities/ocvalidate/ValidateNVRAM.c deleted file mode 100644 index d4a63ce5..00000000 --- a/Utilities/ocvalidate/ValidateNVRAM.c +++ /dev/null @@ -1,324 +0,0 @@ -/** @file - Copyright (C) 2018, vit9696. All rights reserved. - Copyright (C) 2020, PMheart. All rights reserved. - - All rights reserved. - - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -**/ - -#include "ocvalidate.h" -#include "OcValidateLib.h" - -/** - Callback funtion to verify whether one entry is duplicated in NVRAM->Add. - - @param[in] PrimaryEntry Primary entry to be checked. - @param[in] SecondaryEntry Secondary entry to be checked. - - @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. -**/ -STATIC -BOOLEAN -NVRAMAddHasDuplication ( - IN CONST VOID *PrimaryEntry, - IN CONST VOID *SecondaryEntry - ) -{ - CONST OC_STRING *NVRAMAddPrimaryEntry; - CONST OC_STRING *NVRAMAddSecondaryEntry; - CONST CHAR8 *NVRAMAddPrimaryGUIDString; - CONST CHAR8 *NVRAMAddSecondaryGUIDString; - - NVRAMAddPrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; - NVRAMAddSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; - NVRAMAddPrimaryGUIDString = OC_BLOB_GET (NVRAMAddPrimaryEntry); - NVRAMAddSecondaryGUIDString = OC_BLOB_GET (NVRAMAddSecondaryEntry); - - return StringIsDuplicated ("NVRAM->Add", NVRAMAddPrimaryGUIDString, NVRAMAddSecondaryGUIDString); -} - -/** - Callback funtion to verify whether one entry is duplicated in NVRAM->Delete. - - @param[in] PrimaryEntry Primary entry to be checked. - @param[in] SecondaryEntry Secondary entry to be checked. - - @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. -**/ -STATIC -BOOLEAN -NVRAMDeleteHasDuplication ( - IN CONST VOID *PrimaryEntry, - IN CONST VOID *SecondaryEntry - ) -{ - CONST OC_STRING *NVRAMDeletePrimaryEntry; - CONST OC_STRING *NVRAMDeleteSecondaryEntry; - CONST CHAR8 *NVRAMDeletePrimaryGUIDString; - CONST CHAR8 *NVRAMDeleteSecondaryGUIDString; - - NVRAMDeletePrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; - NVRAMDeleteSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; - NVRAMDeletePrimaryGUIDString = OC_BLOB_GET (NVRAMDeletePrimaryEntry); - NVRAMDeleteSecondaryGUIDString = OC_BLOB_GET (NVRAMDeleteSecondaryEntry); - - return StringIsDuplicated ("NVRAM->Delete", NVRAMDeletePrimaryGUIDString, NVRAMDeleteSecondaryGUIDString); -} - -/** - Callback funtion to verify whether one entry is duplicated in NVRAM->LegacySchema. - - @param[in] PrimaryEntry Primary entry to be checked. - @param[in] SecondaryEntry Secondary entry to be checked. - - @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. -**/ -STATIC -BOOLEAN -NVRAMLegacySchemaHasDuplication ( - IN CONST VOID *PrimaryEntry, - IN CONST VOID *SecondaryEntry - ) -{ - CONST OC_STRING *NVRAMLegacySchemaPrimaryEntry; - CONST OC_STRING *NVRAMLegacySchemaSecondaryEntry; - CONST CHAR8 *NVRAMLegacySchemaPrimaryGUIDString; - CONST CHAR8 *NVRAMLegacySchemaSecondaryGUIDString; - - NVRAMLegacySchemaPrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; - NVRAMLegacySchemaSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; - NVRAMLegacySchemaPrimaryGUIDString = OC_BLOB_GET (NVRAMLegacySchemaPrimaryEntry); - NVRAMLegacySchemaSecondaryGUIDString = OC_BLOB_GET (NVRAMLegacySchemaSecondaryEntry); - - return StringIsDuplicated ("NVRAM->LegacySchema", NVRAMLegacySchemaPrimaryGUIDString, NVRAMLegacySchemaSecondaryGUIDString); -} - -STATIC -UINT32 -CheckNVRAMAdd ( - IN OC_GLOBAL_CONFIG *Config - ) -{ - UINT32 ErrorCount; - UINT32 GuidIndex; - UINT32 VariableIndex; - OC_NVRAM_CONFIG *UserNVRAM; - CONST CHAR8 *AsciiGuid; - CONST CHAR8 *AsciiNVRAMKey; - OC_ASSOC *VariableMap; - - ErrorCount = 0; - UserNVRAM = &Config->Nvram; - - for (GuidIndex = 0; GuidIndex < UserNVRAM->Add.Count; ++GuidIndex) { - AsciiGuid = OC_BLOB_GET (UserNVRAM->Add.Keys[GuidIndex]); - - if (!AsciiGuidIsLegal (AsciiGuid)) { - DEBUG ((DEBUG_WARN, "NVRAM->Add[%u] has borked GUID!\n", GuidIndex)); - ++ErrorCount; - } - - VariableMap = UserNVRAM->Add.Values[GuidIndex]; - - for (VariableIndex = 0; VariableIndex < VariableMap->Count; ++VariableIndex) { - AsciiNVRAMKey = OC_BLOB_GET (VariableMap->Keys[VariableIndex]); - - // - // Sanitise strings. - // - if (!AsciiPropertyIsLegal (AsciiNVRAMKey)) { - DEBUG (( - DEBUG_WARN, - "NVRAM->Add[%u]->Key[%u] contains illegal character!\n", - GuidIndex, - VariableIndex - )); - ++ErrorCount; - } - } - - // - // Check duplicated properties in NVRAM->Add. - // - ErrorCount += FindArrayDuplication ( - VariableMap->Keys, - VariableMap->Count, - sizeof (VariableMap->Keys[0]), - NVRAMAddHasDuplication - ); - } - - // - // Check duplicated entries in NVRAM->Add. - // - ErrorCount += FindArrayDuplication ( - UserNVRAM->Add.Keys, - UserNVRAM->Add.Count, - sizeof (UserNVRAM->Add.Keys[0]), - NVRAMAddHasDuplication - ); - - return ErrorCount; -} - -STATIC -UINT32 -CheckNVRAMDelete ( - IN OC_GLOBAL_CONFIG *Config - ) -{ - UINT32 ErrorCount; - UINT32 GuidIndex; - UINT32 VariableIndex; - OC_NVRAM_CONFIG *UserNVRAM; - CONST CHAR8 *AsciiGuid; - CONST CHAR8 *AsciiNVRAMKey; - - ErrorCount = 0; - UserNVRAM = &Config->Nvram; - - for (GuidIndex = 0; GuidIndex < UserNVRAM->Delete.Count; ++GuidIndex) { - AsciiGuid = OC_BLOB_GET (UserNVRAM->Delete.Keys[GuidIndex]); - - if (!AsciiGuidIsLegal (AsciiGuid)) { - DEBUG ((DEBUG_WARN, "NVRAM->Delete[%u] has borked GUID!\n", GuidIndex)); - ++ErrorCount; - } - - for (VariableIndex = 0; VariableIndex < UserNVRAM->Delete.Values[GuidIndex]->Count; ++VariableIndex) { - AsciiNVRAMKey = OC_BLOB_GET (UserNVRAM->Delete.Values[GuidIndex]->Values[VariableIndex]); - - // - // Sanitise strings. - // - if (!AsciiPropertyIsLegal (AsciiNVRAMKey)) { - DEBUG (( - DEBUG_WARN, - "NVRAM->Delete[%u]->Key[%u] contains illegal character!\n", - GuidIndex, - VariableIndex - )); - ++ErrorCount; - } - } - - // - // Check duplicated properties in NVRAM->Delete. - // - ErrorCount += FindArrayDuplication ( - UserNVRAM->Delete.Values[GuidIndex]->Values, - UserNVRAM->Delete.Values[GuidIndex]->Count, - sizeof (UserNVRAM->Delete.Values[GuidIndex]->Values[0]), - NVRAMDeleteHasDuplication - ); - } - - // - // Check duplicated entries in NVRAM->Delete. - // - ErrorCount += FindArrayDuplication ( - UserNVRAM->Delete.Keys, - UserNVRAM->Delete.Count, - sizeof (UserNVRAM->Delete.Keys[0]), - NVRAMDeleteHasDuplication - ); - - return ErrorCount; -} - -STATIC -UINT32 -CheckNVRAMSchema ( - IN OC_GLOBAL_CONFIG *Config - ) -{ - UINT32 ErrorCount; - UINT32 GuidIndex; - UINT32 VariableIndex; - OC_NVRAM_CONFIG *UserNVRAM; - CONST CHAR8 *AsciiGuid; - CONST CHAR8 *AsciiNVRAMKey; - - ErrorCount = 0; - UserNVRAM = &Config->Nvram; - - for (GuidIndex = 0; GuidIndex < UserNVRAM->Legacy.Count; ++GuidIndex) { - AsciiGuid = OC_BLOB_GET (UserNVRAM->Legacy.Keys[GuidIndex]); - - if (!AsciiGuidIsLegal (AsciiGuid)) { - DEBUG ((DEBUG_WARN, "NVRAM->LegacySchema[%u] has borked GUID!\n", GuidIndex)); - ++ErrorCount; - } - - for (VariableIndex = 0; VariableIndex < UserNVRAM->Legacy.Values[GuidIndex]->Count; ++VariableIndex) { - AsciiNVRAMKey = OC_BLOB_GET (UserNVRAM->Legacy.Values[GuidIndex]->Values[VariableIndex]); - - // - // Sanitise strings. - // - if (!AsciiPropertyIsLegal (AsciiNVRAMKey)) { - DEBUG (( - DEBUG_WARN, - "NVRAM->LegacySchema[%u]->Key[%u] contains illegal character!\n", - GuidIndex, - VariableIndex - )); - ++ErrorCount; - } - } - - // - // Check duplicated properties in NVRAM->LegacySchema. - // - ErrorCount += FindArrayDuplication ( - UserNVRAM->Legacy.Values[GuidIndex]->Values, - UserNVRAM->Legacy.Values[GuidIndex]->Count, - sizeof (UserNVRAM->Legacy.Values[GuidIndex]->Values[0]), - NVRAMLegacySchemaHasDuplication - ); - } - - // - // Check duplicated entries in NVRAM->LegacySchema. - // - ErrorCount += FindArrayDuplication ( - UserNVRAM->Legacy.Keys, - UserNVRAM->Legacy.Count, - sizeof (UserNVRAM->Legacy.Keys[0]), - NVRAMLegacySchemaHasDuplication - ); - - return ErrorCount; -} - - -UINT32 -CheckNVRAM ( - IN OC_GLOBAL_CONFIG *Config - ) -{ - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK NVRAMCheckers[] = { - &CheckNVRAMAdd, - &CheckNVRAMDelete, - &CheckNVRAMSchema - }; - - DEBUG ((DEBUG_VERBOSE, "config loaded into %a!\n", __func__)); - - ErrorCount = 0; - - for (Index = 0; Index < ARRAY_SIZE (NVRAMCheckers); ++Index) { - ErrorCount += NVRAMCheckers[Index] (Config); - } - - return ReportError (__func__, ErrorCount); -} diff --git a/Utilities/ocvalidate/ValidateNvram.c b/Utilities/ocvalidate/ValidateNvram.c new file mode 100644 index 00000000..6989a8c3 --- /dev/null +++ b/Utilities/ocvalidate/ValidateNvram.c @@ -0,0 +1,379 @@ +/** @file + Copyright (C) 2018, vit9696. All rights reserved. + Copyright (C) 2020, PMheart. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "ocvalidate.h" +#include "OcValidateLib.h" +#include "NvramKeyInfo.h" + +/** + Callback function to verify whether one entry is duplicated in NVRAM->Add. + + @param[in] PrimaryEntry Primary entry to be checked. + @param[in] SecondaryEntry Secondary entry to be checked. + + @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. +**/ +STATIC +BOOLEAN +NvramAddHasDuplication ( + IN CONST VOID *PrimaryEntry, + IN CONST VOID *SecondaryEntry + ) +{ + CONST OC_STRING *NvramAddPrimaryEntry; + CONST OC_STRING *NvramAddSecondaryEntry; + CONST CHAR8 *NvramAddPrimaryGUIDString; + CONST CHAR8 *NvramAddSecondaryGUIDString; + + NvramAddPrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; + NvramAddSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; + NvramAddPrimaryGUIDString = OC_BLOB_GET (NvramAddPrimaryEntry); + NvramAddSecondaryGUIDString = OC_BLOB_GET (NvramAddSecondaryEntry); + + return StringIsDuplicated ("NVRAM->Add", NvramAddPrimaryGUIDString, NvramAddSecondaryGUIDString); +} + +/** + Callback function to verify whether one entry is duplicated in NVRAM->Delete. + + @param[in] PrimaryEntry Primary entry to be checked. + @param[in] SecondaryEntry Secondary entry to be checked. + + @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. +**/ +STATIC +BOOLEAN +NvramDeleteHasDuplication ( + IN CONST VOID *PrimaryEntry, + IN CONST VOID *SecondaryEntry + ) +{ + CONST OC_STRING *NvramDeletePrimaryEntry; + CONST OC_STRING *NvramDeleteSecondaryEntry; + CONST CHAR8 *NvramDeletePrimaryGUIDString; + CONST CHAR8 *NvramDeleteSecondaryGUIDString; + + NvramDeletePrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; + NvramDeleteSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; + NvramDeletePrimaryGUIDString = OC_BLOB_GET (NvramDeletePrimaryEntry); + NvramDeleteSecondaryGUIDString = OC_BLOB_GET (NvramDeleteSecondaryEntry); + + return StringIsDuplicated ("NVRAM->Delete", NvramDeletePrimaryGUIDString, NvramDeleteSecondaryGUIDString); +} + +/** + Callback function to verify whether one entry is duplicated in NVRAM->LegacySchema. + + @param[in] PrimaryEntry Primary entry to be checked. + @param[in] SecondaryEntry Secondary entry to be checked. + + @retval TRUE If PrimaryEntry and SecondaryEntry are duplicated. +**/ +STATIC +BOOLEAN +NvramLegacySchemaHasDuplication ( + IN CONST VOID *PrimaryEntry, + IN CONST VOID *SecondaryEntry + ) +{ + CONST OC_STRING *NvramLegacySchemaPrimaryEntry; + CONST OC_STRING *NvramLegacySchemaSecondaryEntry; + CONST CHAR8 *NvramLegacySchemaPrimaryGUIDString; + CONST CHAR8 *NvramLegacySchemaSecondaryGUIDString; + + NvramLegacySchemaPrimaryEntry = *(CONST OC_STRING **) PrimaryEntry; + NvramLegacySchemaSecondaryEntry = *(CONST OC_STRING **) SecondaryEntry; + NvramLegacySchemaPrimaryGUIDString = OC_BLOB_GET (NvramLegacySchemaPrimaryEntry); + NvramLegacySchemaSecondaryGUIDString = OC_BLOB_GET (NvramLegacySchemaSecondaryEntry); + + return StringIsDuplicated ("NVRAM->LegacySchema", NvramLegacySchemaPrimaryGUIDString, NvramLegacySchemaSecondaryGUIDString); +} + +STATIC +UINT32 +ValidateNvramKeyByGuid ( + IN CONST CHAR8 *AsciiGuid, + IN CONST OC_ASSOC *VariableMap + ) +{ + UINT32 ErrorCount; + EFI_STATUS Status; + GUID Guid; + UINT32 VariableIndex; + UINTN Index; + UINTN Index2; + + ErrorCount = 0; + + Status = AsciiStrToGuid (AsciiGuid, &Guid); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "NVRAM->Add: Unable to check %a due to borked GUID format!\n", AsciiGuid)); + ++ErrorCount; + return ErrorCount; + } + + for (Index = 0; Index < mGUIDMapsCount; ++Index) { + if (CompareGuid (&Guid, mGUIDMaps[Index].Guid)) { + for (VariableIndex = 0; VariableIndex < VariableMap->Count; ++VariableIndex) { + for (Index2 = 0; Index2 < mGUIDMaps[Index].NvramKeyMapsCount; ++Index2) { + if (AsciiStrCmp (mGUIDMaps[Index].NvramKeyMaps[Index2].KeyName, OC_BLOB_GET (VariableMap->Keys[VariableIndex])) == 0) { + if (!mGUIDMaps[Index].NvramKeyMaps[Index2].KeyChecker ( + OC_BLOB_GET (VariableMap->Values[VariableIndex]), + VariableMap->Values[VariableIndex]->Size + )) { + DEBUG (( + DEBUG_WARN, + "NVRAM->Add->%g->%a has illegal value!\n", + &Guid, + OC_BLOB_GET (VariableMap->Keys[VariableIndex]) + )); + ++ErrorCount; + } + } + } + } + } + } + + return ErrorCount; +} + +STATIC +UINT32 +CheckNvramAdd ( + IN OC_GLOBAL_CONFIG *Config + ) +{ + UINT32 ErrorCount; + UINT32 GuidIndex; + UINT32 VariableIndex; + OC_NVRAM_CONFIG *UserNvram; + CONST CHAR8 *AsciiGuid; + CONST CHAR8 *AsciiNvramKey; + OC_ASSOC *VariableMap; + + ErrorCount = 0; + UserNvram = &Config->Nvram; + + for (GuidIndex = 0; GuidIndex < UserNvram->Add.Count; ++GuidIndex) { + AsciiGuid = OC_BLOB_GET (UserNvram->Add.Keys[GuidIndex]); + + if (!AsciiGuidIsLegal (AsciiGuid)) { + DEBUG ((DEBUG_WARN, "NVRAM->Add[%u] has borked GUID!\n", GuidIndex)); + ++ErrorCount; + } + + VariableMap = UserNvram->Add.Values[GuidIndex]; + + for (VariableIndex = 0; VariableIndex < VariableMap->Count; ++VariableIndex) { + AsciiNvramKey = OC_BLOB_GET (VariableMap->Keys[VariableIndex]); + + // + // Sanitise strings. + // + if (!AsciiPropertyIsLegal (AsciiNvramKey)) { + DEBUG (( + DEBUG_WARN, + "NVRAM->Add[%u]->Key[%u] contains illegal character!\n", + GuidIndex, + VariableIndex + )); + ++ErrorCount; + } + } + + // + // Check duplicated properties in NVRAM->Add. + // + ErrorCount += FindArrayDuplication ( + VariableMap->Keys, + VariableMap->Count, + sizeof (VariableMap->Keys[0]), + NvramAddHasDuplication + ); + + // + // Check for accepted values for NVRAM keys. + // + ErrorCount += ValidateNvramKeyByGuid (AsciiGuid, VariableMap); + } + + // + // Check duplicated entries in NVRAM->Add. + // + ErrorCount += FindArrayDuplication ( + UserNvram->Add.Keys, + UserNvram->Add.Count, + sizeof (UserNvram->Add.Keys[0]), + NvramAddHasDuplication + ); + + return ErrorCount; +} + +STATIC +UINT32 +CheckNvramDelete ( + IN OC_GLOBAL_CONFIG *Config + ) +{ + UINT32 ErrorCount; + UINT32 GuidIndex; + UINT32 VariableIndex; + OC_NVRAM_CONFIG *UserNvram; + CONST CHAR8 *AsciiGuid; + CONST CHAR8 *AsciiNvramKey; + + ErrorCount = 0; + UserNvram = &Config->Nvram; + + for (GuidIndex = 0; GuidIndex < UserNvram->Delete.Count; ++GuidIndex) { + AsciiGuid = OC_BLOB_GET (UserNvram->Delete.Keys[GuidIndex]); + + if (!AsciiGuidIsLegal (AsciiGuid)) { + DEBUG ((DEBUG_WARN, "NVRAM->Delete[%u] has borked GUID!\n", GuidIndex)); + ++ErrorCount; + } + + for (VariableIndex = 0; VariableIndex < UserNvram->Delete.Values[GuidIndex]->Count; ++VariableIndex) { + AsciiNvramKey = OC_BLOB_GET (UserNvram->Delete.Values[GuidIndex]->Values[VariableIndex]); + + // + // Sanitise strings. + // + if (!AsciiPropertyIsLegal (AsciiNvramKey)) { + DEBUG (( + DEBUG_WARN, + "NVRAM->Delete[%u]->Key[%u] contains illegal character!\n", + GuidIndex, + VariableIndex + )); + ++ErrorCount; + } + } + + // + // Check duplicated properties in NVRAM->Delete. + // + ErrorCount += FindArrayDuplication ( + UserNvram->Delete.Values[GuidIndex]->Values, + UserNvram->Delete.Values[GuidIndex]->Count, + sizeof (UserNvram->Delete.Values[GuidIndex]->Values[0]), + NvramDeleteHasDuplication + ); + } + + // + // Check duplicated entries in NVRAM->Delete. + // + ErrorCount += FindArrayDuplication ( + UserNvram->Delete.Keys, + UserNvram->Delete.Count, + sizeof (UserNvram->Delete.Keys[0]), + NvramDeleteHasDuplication + ); + + return ErrorCount; +} + +STATIC +UINT32 +CheckNvramSchema ( + IN OC_GLOBAL_CONFIG *Config + ) +{ + UINT32 ErrorCount; + UINT32 GuidIndex; + UINT32 VariableIndex; + OC_NVRAM_CONFIG *UserNvram; + CONST CHAR8 *AsciiGuid; + CONST CHAR8 *AsciiNvramKey; + + ErrorCount = 0; + UserNvram = &Config->Nvram; + + for (GuidIndex = 0; GuidIndex < UserNvram->Legacy.Count; ++GuidIndex) { + AsciiGuid = OC_BLOB_GET (UserNvram->Legacy.Keys[GuidIndex]); + + if (!AsciiGuidIsLegal (AsciiGuid)) { + DEBUG ((DEBUG_WARN, "NVRAM->LegacySchema[%u] has borked GUID!\n", GuidIndex)); + ++ErrorCount; + } + + for (VariableIndex = 0; VariableIndex < UserNvram->Legacy.Values[GuidIndex]->Count; ++VariableIndex) { + AsciiNvramKey = OC_BLOB_GET (UserNvram->Legacy.Values[GuidIndex]->Values[VariableIndex]); + + // + // Sanitise strings. + // + if (!AsciiPropertyIsLegal (AsciiNvramKey)) { + DEBUG (( + DEBUG_WARN, + "NVRAM->LegacySchema[%u]->Key[%u] contains illegal character!\n", + GuidIndex, + VariableIndex + )); + ++ErrorCount; + } + } + + // + // Check duplicated properties in NVRAM->LegacySchema. + // + ErrorCount += FindArrayDuplication ( + UserNvram->Legacy.Values[GuidIndex]->Values, + UserNvram->Legacy.Values[GuidIndex]->Count, + sizeof (UserNvram->Legacy.Values[GuidIndex]->Values[0]), + NvramLegacySchemaHasDuplication + ); + } + + // + // Check duplicated entries in NVRAM->LegacySchema. + // + ErrorCount += FindArrayDuplication ( + UserNvram->Legacy.Keys, + UserNvram->Legacy.Count, + sizeof (UserNvram->Legacy.Keys[0]), + NvramLegacySchemaHasDuplication + ); + + return ErrorCount; +} + + +UINT32 +CheckNvram ( + IN OC_GLOBAL_CONFIG *Config + ) +{ + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK NvramCheckers[] = { + &CheckNvramAdd, + &CheckNvramDelete, + &CheckNvramSchema + }; + + DEBUG ((DEBUG_VERBOSE, "config loaded into %a!\n", __func__)); + + ErrorCount = 0; + + for (Index = 0; Index < ARRAY_SIZE (NvramCheckers); ++Index) { + ErrorCount += NvramCheckers[Index] (Config); + } + + return ReportError (__func__, ErrorCount); +} diff --git a/Utilities/ocvalidate/ValidatePlatformInfo.c b/Utilities/ocvalidate/ValidatePlatformInfo.c index 58720bb4..73ccc4df 100644 --- a/Utilities/ocvalidate/ValidatePlatformInfo.c +++ b/Utilities/ocvalidate/ValidatePlatformInfo.c @@ -25,8 +25,8 @@ ValidateProcessorType ( IN UINT16 ProcessorType ) { - UINTN Index; - UINT8 AllowedProcessorType[] = { + UINTN Index; + STATIC CONST UINT8 AllowedProcessorType[] = { AppleProcessorMajorCore, AppleProcessorMajorCore2, AppleProcessorMajorXeonPenryn, @@ -117,12 +117,12 @@ CheckPlatformInfo ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - OC_PLATFORM_CONFIG *UserPlatformInfo; - BOOLEAN IsAutomaticEnabled; - CONST CHAR8 *UpdateSMBIOSMode; - UINTN Index; - STATIC CONFIG_CHECK PlatformInfoCheckers[] = { + UINT32 ErrorCount; + OC_PLATFORM_CONFIG *UserPlatformInfo; + BOOLEAN IsAutomaticEnabled; + CONST CHAR8 *UpdateSMBIOSMode; + UINTN Index; + STATIC CONFIG_CHECK PlatformInfoCheckers[] = { &CheckPlatformInfoGeneric }; diff --git a/Utilities/ocvalidate/ValidateUEFI.c b/Utilities/ocvalidate/ValidateUEFI.c index 6a1090c7..6a693528 100644 --- a/Utilities/ocvalidate/ValidateUEFI.c +++ b/Utilities/ocvalidate/ValidateUEFI.c @@ -19,7 +19,7 @@ #include /** - Callback funtion to verify whether one UEFI driver is duplicated in UEFI->Drivers. + Callback function to verify whether one UEFI driver is duplicated in UEFI->Drivers. @param[in] PrimaryDriver Primary driver to be checked. @param[in] SecondaryDriver Secondary driver to be checked. @@ -47,7 +47,7 @@ UEFIDriverHasDuplication ( } /** - Callback funtion to verify whether one UEFI ReservedMemory entry overlaps the other, + Callback function to verify whether one UEFI ReservedMemory entry overlaps the other, in terms of Address and Size. @param[in] PrimaryEntry Primary entry to be checked. @@ -95,8 +95,8 @@ ValidateReservedMemoryType ( IN CONST CHAR8 *Type ) { - UINTN Index; - CONST CHAR8 *AllowedType[] = { + UINTN Index; + STATIC CONST CHAR8 *AllowedType[] = { "Reserved", "LoaderCode", "LoaderData", "BootServiceCode", "BootServiceData", "RuntimeCode", "RuntimeData", "Available", "Persistent", "UnusableMemory", "ACPIReclaimMemory", "ACPIMemoryNVS", "MemoryMappedIO", "MemoryMappedIOPortSpace", "PalCode" @@ -528,9 +528,9 @@ CheckUEFI ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK UEFICheckers[] = { + UINT32 ErrorCount; + UINTN Index; + STATIC CONFIG_CHECK UEFICheckers[] = { &CheckUEFIAPFS, &CheckUEFIAudio, &CheckUEFIDrivers, diff --git a/Utilities/ocvalidate/ocvalidate.c b/Utilities/ocvalidate/ocvalidate.c index 7de22675..f8636802 100644 --- a/Utilities/ocvalidate/ocvalidate.c +++ b/Utilities/ocvalidate/ocvalidate.c @@ -25,26 +25,36 @@ CheckConfig ( IN OC_GLOBAL_CONFIG *Config ) { - UINT32 ErrorCount; - UINTN Index; - STATIC CONFIG_CHECK ConfigCheckers[] = { + UINT32 ErrorCount; + UINT32 CurrErrorCount; + UINTN Index; + STATIC CONFIG_CHECK ConfigCheckers[] = { &CheckACPI, &CheckBooter, &CheckDeviceProperties, &CheckKernel, &CheckMisc, - &CheckNVRAM, + &CheckNvram, &CheckPlatformInfo, &CheckUEFI }; - ErrorCount = 0; + ErrorCount = 0; + CurrErrorCount = 0; // // Pass config structure to all checkers. // for (Index = 0; Index < ARRAY_SIZE (ConfigCheckers); ++Index) { - ErrorCount += ConfigCheckers[Index] (Config); + CurrErrorCount = ConfigCheckers[Index] (Config); + + if (CurrErrorCount != 0) { + // + // Print an extra newline on error. + // + DEBUG ((DEBUG_WARN, "\n")); + ErrorCount += CurrErrorCount; + } } return ErrorCount; @@ -99,6 +109,10 @@ int ENTRY_POINT(int argc, const char *argv[]) { return -1; } + // + // Print a newline that splits errors between OcConfigurationInit and config checkers. + // + DEBUG ((DEBUG_ERROR, "\n")); ErrorCount = CheckConfig (&Config); if (ErrorCount == 0) { DEBUG (( @@ -119,19 +133,22 @@ int ENTRY_POINT(int argc, const char *argv[]) { } OcConfigurationFree (&Config); - free (ConfigFileBuffer); + FreePool (ConfigFileBuffer); return 0; } INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) { - VOID *NewData = AllocatePool (Size); - if (NewData) { + VOID *NewData; + OC_GLOBAL_CONFIG Config; + + NewData = AllocatePool (Size); + if (NewData != NULL) { CopyMem (NewData, Data, Size); - OC_GLOBAL_CONFIG Config; OcConfigurationInit (&Config, NewData, Size); OcConfigurationFree (&Config); FreePool (NewData); } + return 0; } diff --git a/Utilities/ocvalidate/ocvalidate.h b/Utilities/ocvalidate/ocvalidate.h index eef9e3f6..6725b89b 100644 --- a/Utilities/ocvalidate/ocvalidate.h +++ b/Utilities/ocvalidate/ocvalidate.h @@ -19,7 +19,7 @@ #include /** - Validate OpenCore Configuration. + OpenCore Configuration checker. **/ typedef UINT32 @@ -32,7 +32,7 @@ UINT32 @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in ACPI Section. **/ UINT32 CheckACPI ( @@ -44,7 +44,7 @@ CheckACPI ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in Booter Section. **/ UINT32 CheckBooter ( @@ -56,7 +56,7 @@ CheckBooter ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in DeviceProperties. **/ UINT32 CheckDeviceProperties ( @@ -68,7 +68,7 @@ CheckDeviceProperties ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in Kernel Section. **/ UINT32 CheckKernel ( @@ -80,7 +80,7 @@ CheckKernel ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in Misc Section. **/ UINT32 CheckMisc ( @@ -92,10 +92,10 @@ CheckMisc ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in NVRAM Section. **/ UINT32 -CheckNVRAM ( +CheckNvram ( IN OC_GLOBAL_CONFIG *Config ); @@ -104,7 +104,7 @@ CheckNVRAM ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in PlatformInfo Section. **/ UINT32 CheckPlatformInfo ( @@ -116,7 +116,7 @@ CheckPlatformInfo ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected in UEFI Section. **/ UINT32 CheckUEFI ( @@ -128,7 +128,7 @@ CheckUEFI ( @param[in] Config Configuration structure. - @return Number of errors detected. + @return Number of errors detected overall. **/ UINT32 CheckConfig (