2022-07-28 23:53:15 +03:00

722 lines
22 KiB
C

/** @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"
#include "ocvalidate.h"
#include "OcValidateLib.h"
#include <Library/BaseLib.h>
#include <Library/OcConsoleLib.h>
/**
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.
@retval TRUE If PrimaryDriver and SecondaryDriver are duplicated.
**/
STATIC
BOOLEAN
UefiDriverHasDuplication (
IN CONST VOID *PrimaryDriver,
IN CONST VOID *SecondaryDriver
)
{
CONST OC_UEFI_DRIVER_ENTRY *UefiPrimaryDriver;
CONST OC_UEFI_DRIVER_ENTRY *UefiSecondaryDriver;
CONST CHAR8 *UefiDriverPrimaryString;
CONST CHAR8 *UefiDriverSecondaryString;
UefiPrimaryDriver = *(CONST OC_UEFI_DRIVER_ENTRY **)PrimaryDriver;
UefiSecondaryDriver = *(CONST OC_UEFI_DRIVER_ENTRY **)SecondaryDriver;
UefiDriverPrimaryString = OC_BLOB_GET (&UefiPrimaryDriver->Path);
UefiDriverSecondaryString = OC_BLOB_GET (&UefiSecondaryDriver->Path);
return StringIsDuplicated ("UEFI->Drivers", UefiDriverPrimaryString, UefiDriverSecondaryString);
}
/**
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.
@param[in] SecondaryEntry Secondary entry to be checked.
@retval TRUE If PrimaryEntry and SecondaryEntry have overlapped Address and Size.
**/
STATIC
BOOLEAN
UefiReservedMemoryHasOverlap (
IN CONST VOID *PrimaryEntry,
IN CONST VOID *SecondaryEntry
)
{
CONST OC_UEFI_RSVD_ENTRY *UefiReservedMemoryPrimaryEntry;
CONST OC_UEFI_RSVD_ENTRY *UefiReservedMemorySecondaryEntry;
UINT64 UefiReservedMemoryPrimaryAddress;
UINT64 UefiReservedMemoryPrimarySize;
UINT64 UefiReservedMemorySecondaryAddress;
UINT64 UefiReservedMemorySecondarySize;
UefiReservedMemoryPrimaryEntry = *(CONST OC_UEFI_RSVD_ENTRY **)PrimaryEntry;
UefiReservedMemorySecondaryEntry = *(CONST OC_UEFI_RSVD_ENTRY **)SecondaryEntry;
UefiReservedMemoryPrimaryAddress = UefiReservedMemoryPrimaryEntry->Address;
UefiReservedMemoryPrimarySize = UefiReservedMemoryPrimaryEntry->Size;
UefiReservedMemorySecondaryAddress = UefiReservedMemorySecondaryEntry->Address;
UefiReservedMemorySecondarySize = UefiReservedMemorySecondaryEntry->Size;
if (!UefiReservedMemoryPrimaryEntry->Enabled || !UefiReservedMemorySecondaryEntry->Enabled) {
return FALSE;
}
if ( (UefiReservedMemoryPrimaryAddress < UefiReservedMemorySecondaryAddress + UefiReservedMemorySecondarySize)
&& (UefiReservedMemorySecondaryAddress < UefiReservedMemoryPrimaryAddress + UefiReservedMemoryPrimarySize))
{
DEBUG ((DEBUG_WARN, "UEFI->ReservedMemory: Entries have overlapped Address and Size "));
return TRUE;
}
return FALSE;
}
STATIC
BOOLEAN
ValidateReservedMemoryType (
IN CONST CHAR8 *Type
)
{
UINTN Index;
STATIC CONST CHAR8 *AllowedType[] = {
"Reserved", "LoaderCode", "LoaderData", "BootServiceCode", "BootServiceData",
"RuntimeCode", "RuntimeData", "Available", "Persistent", "UnusableMemory",
"ACPIReclaimMemory", "ACPIMemoryNVS", "MemoryMappedIO", "MemoryMappedIOPortSpace", "PalCode"
};
for (Index = 0; Index < ARRAY_SIZE (AllowedType); ++Index) {
if (AsciiStrCmp (Type, AllowedType[Index]) == 0) {
return TRUE;
}
}
return FALSE;
}
STATIC
UINT32
CheckUefiAPFS (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
BOOLEAN IsEnableJumpstartEnabled;
UINT32 ScanPolicy;
ErrorCount = 0;
//
// If FS restrictions is enabled but APFS FS scanning is disabled, it is an error.
//
IsEnableJumpstartEnabled = Config->Uefi.Apfs.EnableJumpstart;
ScanPolicy = Config->Misc.Security.ScanPolicy;
if ( IsEnableJumpstartEnabled
&& ((ScanPolicy & OC_SCAN_FILE_SYSTEM_LOCK) != 0)
&& ((ScanPolicy & OC_SCAN_ALLOW_FS_APFS) == 0))
{
DEBUG ((DEBUG_WARN, "UEFI->APFS->EnableJumpstart is enabled, but Misc->Security->ScanPolicy does not allow APFS scanning!\n"));
++ErrorCount;
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiAppleInput (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
CONST CHAR8 *AppleEvent;
ErrorCount = 0;
AppleEvent = OC_BLOB_GET (&Config->Uefi.AppleInput.AppleEvent);
if ( (AsciiStrCmp (AppleEvent, "Auto") != 0)
&& (AsciiStrCmp (AppleEvent, "Builtin") != 0)
&& (AsciiStrCmp (AppleEvent, "OEM") != 0))
{
DEBUG ((DEBUG_WARN, "UEFI->AppleInput->AppleEvent is illegal (Can only be Auto, Builtin, OEM)!\n"));
++ErrorCount;
}
if (Config->Uefi.Input.KeySupport && Config->Uefi.AppleInput.CustomDelays) {
if ( (Config->Uefi.AppleInput.KeyInitialDelay != 0)
&& (Config->Uefi.AppleInput.KeyInitialDelay < Config->Uefi.Input.KeyForgetThreshold))
{
DEBUG ((DEBUG_WARN, "KeyInitialDelay is enabled in KeySupport mode, is non-zero and is less than the KeyForgetThreshold value (will result in uncontrolled key repeats)!\n"));
++ErrorCount;
}
if (Config->Uefi.AppleInput.KeySubsequentDelay < Config->Uefi.Input.KeyForgetThreshold) {
DEBUG ((DEBUG_WARN, "KeySubsequentDelay is enabled in KeySupport mode and is less than the KeyForgetThreshold value (will result in uncontrolled key repeats)!\n"));
++ErrorCount;
}
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiGain (
INT8 Gain,
CHAR8 *GainName,
INT8 GainAbove, OPTIONAL
CHAR8 *GainAboveName OPTIONAL
)
{
UINT32 ErrorCount;
ErrorCount = 0;
//
// Cannot check these as they are already truncated to INT8 before we can validate them.
// TODO: (?) Add check during DEBUG parsing that specified values fit into what they will be cast to.
//
#if 0
if (Gain < -128) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be greater than or equal to -128!\n", GainName));
++ErrorCount;
} else if (Gain > 127) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be less than or equal to 127!\n", GainName));
++ErrorCount;
}
#endif
if ((GainAboveName != NULL) && (Gain > GainAbove)) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be less than or equal to UEFI->Audio->%a!\n", GainName, GainAboveName));
++ErrorCount;
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiAudio (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
BOOLEAN IsAudioSupportEnabled;
UINT64 AudioOutMask;
CONST CHAR8 *AsciiAudioDevicePath;
CONST CHAR8 *AsciiPlayChime;
ErrorCount = 0;
IsAudioSupportEnabled = Config->Uefi.Audio.AudioSupport;
AudioOutMask = Config->Uefi.Audio.AudioOutMask;
AsciiAudioDevicePath = OC_BLOB_GET (&Config->Uefi.Audio.AudioDevice);
AsciiPlayChime = OC_BLOB_GET (&Config->Uefi.Audio.PlayChime);
if (IsAudioSupportEnabled) {
if (AudioOutMask == 0) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->AudioOutMask is zero when AudioSupport is enabled, no sound will play!\n"));
++ErrorCount;
}
ErrorCount += CheckUefiGain (
Config->Uefi.Audio.MaximumGain,
"MaximumGain",
0,
NULL
);
// No operational reason for MinimumAssistGain <= MaximumGain, but is safer to ensure non-deafening sound levels.
ErrorCount += CheckUefiGain (
Config->Uefi.Audio.MinimumAssistGain,
"MinimumAssistGain",
Config->Uefi.Audio.MaximumGain,
"MaximumGain"
);
ErrorCount += CheckUefiGain (
Config->Uefi.Audio.MinimumAudibleGain,
"MinimumAudibleGain",
Config->Uefi.Audio.MinimumAssistGain,
"MinimumAssistGain"
);
ErrorCount += CheckUefiGain (
Config->Uefi.Audio.MinimumAudibleGain,
"MinimumAudibleGain",
Config->Uefi.Audio.MaximumGain,
"MaximumGain"
);
if (!AsciiDevicePathIsLegal (AsciiAudioDevicePath)) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->AudioDevice is borked! Please check the information above!\n"));
++ErrorCount;
}
if (AsciiPlayChime[0] == '\0') {
DEBUG ((DEBUG_WARN, "UEFI->Audio->PlayChime cannot be empty when AudioSupport is enabled!\n"));
++ErrorCount;
} else if ( (AsciiStrCmp (AsciiPlayChime, "Auto") != 0)
&& (AsciiStrCmp (AsciiPlayChime, "Enabled") != 0)
&& (AsciiStrCmp (AsciiPlayChime, "Disabled") != 0))
{
DEBUG ((DEBUG_WARN, "UEFI->Audio->PlayChime is borked (Can only be Auto, Enabled, or Disabled)!\n"));
++ErrorCount;
}
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiDrivers (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
UINT32 Index;
OC_UEFI_DRIVER_ENTRY *DriverEntry;
CONST CHAR8 *Comment;
CONST CHAR8 *Driver;
UINTN DriverSumSize;
BOOLEAN HasOpenRuntimeEfiDriver;
BOOLEAN HasOpenUsbKbDxeEfiDriver;
UINT32 IndexOpenUsbKbDxeEfiDriver;
BOOLEAN HasPs2KeyboardDxeEfiDriver;
BOOLEAN IndexPs2KeyboardDxeEfiDriver;
BOOLEAN HasHfsEfiDriver;
UINT32 IndexHfsEfiDriver;
BOOLEAN HasAudioDxeEfiDriver;
UINT32 IndexAudioDxeEfiDriver;
BOOLEAN IsRequestBootVarRoutingEnabled;
BOOLEAN IsKeySupportEnabled;
BOOLEAN IsConnectDriversEnabled;
ErrorCount = 0;
HasOpenRuntimeEfiDriver = FALSE;
HasOpenUsbKbDxeEfiDriver = FALSE;
IndexOpenUsbKbDxeEfiDriver = 0;
HasPs2KeyboardDxeEfiDriver = FALSE;
IndexPs2KeyboardDxeEfiDriver = 0;
HasHfsEfiDriver = FALSE;
IndexHfsEfiDriver = 0;
HasAudioDxeEfiDriver = FALSE;
IndexAudioDxeEfiDriver = 0;
for (Index = 0; Index < Config->Uefi.Drivers.Count; ++Index) {
DriverEntry = Config->Uefi.Drivers.Values[Index];
Comment = OC_BLOB_GET (&DriverEntry->Comment);
Driver = OC_BLOB_GET (&DriverEntry->Path);
//
// Check the length of path relative to OC directory.
//
DriverSumSize = L_STR_LEN (OPEN_CORE_UEFI_DRIVER_PATH) + AsciiStrSize (Driver);
if (DriverSumSize > OC_STORAGE_SAFE_PATH_MAX) {
DEBUG ((
DEBUG_WARN,
"UEFI->Drivers[%u] (length %u) is too long (should not exceed %u)!\n",
Index,
AsciiStrLen (Driver),
OC_STORAGE_SAFE_PATH_MAX - L_STR_LEN (OPEN_CORE_UEFI_DRIVER_PATH)
));
++ErrorCount;
}
//
// Sanitise strings.
//
if (!AsciiCommentIsLegal (Comment)) {
DEBUG ((DEBUG_WARN, "UEFI->Drivers[%u]->Comment contains illegal character!\n", Index));
++ErrorCount;
}
if (!AsciiUefiDriverIsLegal (Driver, Index)) {
++ErrorCount;
continue;
}
if (!DriverEntry->Enabled) {
continue;
}
if (AsciiStrCmp (Driver, "OpenRuntime.efi") == 0) {
HasOpenRuntimeEfiDriver = TRUE;
}
if (AsciiStrCmp (Driver, "OpenUsbKbDxe.efi") == 0) {
HasOpenUsbKbDxeEfiDriver = TRUE;
IndexOpenUsbKbDxeEfiDriver = Index;
}
if (AsciiStrCmp (Driver, "Ps2KeyboardDxe.efi") == 0) {
HasPs2KeyboardDxeEfiDriver = TRUE;
IndexPs2KeyboardDxeEfiDriver = Index;
}
//
// There are several HFS Plus drivers, including HfsPlus, VboxHfs, etc.
// Here only "hfs" (case-insensitive) is matched.
//
if (OcAsciiStriStr (Driver, "hfs") != NULL) {
HasHfsEfiDriver = TRUE;
IndexHfsEfiDriver = Index;
}
if (AsciiStrCmp (Driver, "AudioDxe.efi") == 0) {
HasAudioDxeEfiDriver = TRUE;
IndexAudioDxeEfiDriver = Index;
}
}
//
// Check duplicated Drivers.
//
ErrorCount += FindArrayDuplication (
Config->Uefi.Drivers.Values,
Config->Uefi.Drivers.Count,
sizeof (Config->Uefi.Drivers.Values[0]),
UefiDriverHasDuplication
);
IsRequestBootVarRoutingEnabled = Config->Uefi.Quirks.RequestBootVarRouting;
if (IsRequestBootVarRoutingEnabled) {
if (!HasOpenRuntimeEfiDriver) {
DEBUG ((DEBUG_WARN, "UEFI->Quirks->RequestBootVarRouting is enabled, but OpenRuntime.efi is not loaded at UEFI->Drivers!\n"));
++ErrorCount;
}
}
IsKeySupportEnabled = Config->Uefi.Input.KeySupport;
if (IsKeySupportEnabled) {
if (HasOpenUsbKbDxeEfiDriver) {
DEBUG ((DEBUG_WARN, "OpenUsbKbDxe.efi at UEFI->Drivers[%u] should NEVER be used together with UEFI->Input->KeySupport!\n", IndexOpenUsbKbDxeEfiDriver));
++ErrorCount;
}
} else {
if (HasPs2KeyboardDxeEfiDriver) {
DEBUG ((DEBUG_WARN, "UEFI->Input->KeySupport should be enabled when Ps2KeyboardDxe.efi is in use!\n"));
++ErrorCount;
}
}
if (HasOpenUsbKbDxeEfiDriver && HasPs2KeyboardDxeEfiDriver) {
DEBUG ((
DEBUG_WARN,
"OpenUsbKbDxe.efi at UEFI->Drivers[%u], and Ps2KeyboardDxe.efi at UEFI->Drivers[%u], should NEVER co-exist!\n",
IndexOpenUsbKbDxeEfiDriver,
IndexPs2KeyboardDxeEfiDriver
));
++ErrorCount;
}
IsConnectDriversEnabled = Config->Uefi.ConnectDrivers;
if (!IsConnectDriversEnabled) {
if (HasHfsEfiDriver) {
DEBUG ((DEBUG_WARN, "HFS+ filesystem driver is loaded at UEFI->Drivers[%u], but UEFI->ConnectDrivers is not enabled!\n", IndexHfsEfiDriver));
++ErrorCount;
}
if (HasAudioDxeEfiDriver) {
DEBUG ((DEBUG_WARN, "AudioDevice.efi is loaded at UEFI->Drivers[%u], but UEFI->ConnectDrivers is not enabled!\n", IndexAudioDxeEfiDriver));
++ErrorCount;
}
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiInput (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
BOOLEAN IsPointerSupportEnabled;
CONST CHAR8 *PointerSupportMode;
CONST CHAR8 *KeySupportMode;
ErrorCount = 0;
IsPointerSupportEnabled = Config->Uefi.Input.PointerSupport;
PointerSupportMode = OC_BLOB_GET (&Config->Uefi.Input.PointerSupportMode);
if (IsPointerSupportEnabled && (AsciiStrCmp (PointerSupportMode, "ASUS") != 0)) {
DEBUG ((DEBUG_WARN, "UEFI->Input->PointerSupport is enabled, but PointerSupportMode is not ASUS!\n"));
++ErrorCount;
}
KeySupportMode = OC_BLOB_GET (&Config->Uefi.Input.KeySupportMode);
if ( (AsciiStrCmp (KeySupportMode, "Auto") != 0)
&& (AsciiStrCmp (KeySupportMode, "V1") != 0)
&& (AsciiStrCmp (KeySupportMode, "V2") != 0)
&& (AsciiStrCmp (KeySupportMode, "AMI") != 0))
{
DEBUG ((DEBUG_WARN, "UEFI->Input->KeySupportMode is illegal (Can only be Auto, V1, V2, AMI)!\n"));
++ErrorCount;
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiOutput (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
CONST CHAR8 *TextRenderer;
CONST CHAR8 *GopPassThrough;
BOOLEAN IsTextRendererSystem;
BOOLEAN IsClearScreenOnModeSwitchEnabled;
BOOLEAN IsIgnoreTextInGraphicsEnabled;
BOOLEAN IsReplaceTabWithSpaceEnabled;
BOOLEAN IsSanitiseClearScreenEnabled;
CONST CHAR8 *ConsoleMode;
CONST CHAR8 *Resolution;
UINT32 UserWidth;
UINT32 UserHeight;
UINT32 UserBpp;
BOOLEAN UserSetMax;
INT8 UIScale;
BOOLEAN HasUefiOutputUIScale;
ErrorCount = 0;
IsTextRendererSystem = FALSE;
HasUefiOutputUIScale = FALSE;
//
// Sanitise strings.
//
TextRenderer = OC_BLOB_GET (&Config->Uefi.Output.TextRenderer);
if ( (AsciiStrCmp (TextRenderer, "BuiltinGraphics") != 0)
&& (AsciiStrCmp (TextRenderer, "BuiltinText") != 0)
&& (AsciiStrCmp (TextRenderer, "SystemGraphics") != 0)
&& (AsciiStrCmp (TextRenderer, "SystemText") != 0)
&& (AsciiStrCmp (TextRenderer, "SystemGeneric") != 0))
{
DEBUG ((DEBUG_WARN, "UEFI->Output->TextRenderer is illegal (Can only be BuiltinGraphics, BuiltinText, SystemGraphics, SystemText, or SystemGeneric)!\n"));
++ErrorCount;
} else if (AsciiStrnCmp (TextRenderer, "System", L_STR_LEN ("System")) == 0) {
//
// Check whether TextRenderer has System prefix.
//
IsTextRendererSystem = TRUE;
}
if (!IsTextRendererSystem) {
IsClearScreenOnModeSwitchEnabled = Config->Uefi.Output.ClearScreenOnModeSwitch;
if (IsClearScreenOnModeSwitchEnabled) {
DEBUG ((DEBUG_WARN, "UEFI->Output->ClearScreenOnModeSwitch is enabled on non-System TextRenderer (currently %a)!\n", TextRenderer));
++ErrorCount;
}
IsIgnoreTextInGraphicsEnabled = Config->Uefi.Output.IgnoreTextInGraphics;
if (IsIgnoreTextInGraphicsEnabled) {
DEBUG ((DEBUG_WARN, "UEFI->Output->IgnoreTextInGraphics is enabled on non-System TextRenderer (currently %a)!\n", TextRenderer));
++ErrorCount;
}
IsReplaceTabWithSpaceEnabled = Config->Uefi.Output.ReplaceTabWithSpace;
if (IsReplaceTabWithSpaceEnabled) {
DEBUG ((DEBUG_WARN, "UEFI->Output->ReplaceTabWithSpace is enabled on non-System TextRenderer (currently %a)!\n", TextRenderer));
++ErrorCount;
}
IsSanitiseClearScreenEnabled = Config->Uefi.Output.SanitiseClearScreen;
if (IsSanitiseClearScreenEnabled) {
DEBUG ((DEBUG_WARN, "UEFI->Output->SanitiseClearScreen is enabled on non-System TextRenderer (currently %a)!\n", TextRenderer));
++ErrorCount;
}
}
GopPassThrough = OC_BLOB_GET (&Config->Uefi.Output.GopPassThrough);
if ( (AsciiStrCmp (GopPassThrough, "Enabled") != 0)
&& (AsciiStrCmp (GopPassThrough, "Disabled") != 0)
&& (AsciiStrCmp (GopPassThrough, "Apple") != 0))
{
DEBUG ((DEBUG_WARN, "UEFI->Output->GopPassThrough is illegal (Can only be Enabled, Disabled, Apple)!\n"));
++ErrorCount;
}
//
// Parse Output->ConsoleMode by calling OpenCore libraries.
//
ConsoleMode = OC_BLOB_GET (&Config->Uefi.Output.ConsoleMode);
OcParseConsoleMode (
ConsoleMode,
&UserWidth,
&UserHeight,
&UserSetMax
);
if ( (ConsoleMode[0] != '\0')
&& !UserSetMax
&& ((UserWidth == 0) || (UserHeight == 0)))
{
DEBUG ((DEBUG_WARN, "UEFI->Output->ConsoleMode is borked, please check Configurations.pdf!\n"));
++ErrorCount;
}
//
// Parse Output->Resolution by calling OpenCore libraries.
//
Resolution = OC_BLOB_GET (&Config->Uefi.Output.Resolution);
OcParseScreenResolution (
Resolution,
&UserWidth,
&UserHeight,
&UserBpp,
&UserSetMax
);
if ( (Resolution[0] != '\0')
&& !UserSetMax
&& ((UserWidth == 0) || (UserHeight == 0)))
{
DEBUG ((DEBUG_WARN, "UEFI->Output->Resolution is borked, please check Configurations.pdf!\n"));
++ErrorCount;
}
UIScale = Config->Uefi.Output.UIScale;
if ((UIScale < -1) || (UIScale > 2)) {
DEBUG ((DEBUG_WARN, "UEFI->Output->UIScale is borked (Can only be between -1 and 2)!\n"));
++ErrorCount;
} else if (UIScale != -1) {
HasUefiOutputUIScale = TRUE;
}
if (HasUefiOutputUIScale && mHasNvramUIScale) {
DEBUG ((DEBUG_WARN, "UIScale is set under both NVRAM and UEFI->Output!\n"));
++ErrorCount;
}
return ErrorCount;
}
//
// FIXME: Just in case this can be of use...
//
STATIC
UINT32
CheckUefiQuirks (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
INT8 ResizeGpuBars;
ErrorCount = 0;
ResizeGpuBars = Config->Uefi.Quirks.ResizeGpuBars;
if ((ResizeGpuBars < -1) || (ResizeGpuBars > 19)) {
DEBUG ((DEBUG_WARN, "UEFI->Quirks->ResizeGpuBars is borked (Can only be between -1 and 19)!\n"));
++ErrorCount;
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiReservedMemory (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
UINT32 Index;
CONST CHAR8 *AsciiReservedMemoryType;
UINT64 ReservedMemoryAddress;
UINT64 ReservedMemorySize;
ErrorCount = 0;
//
// Validate ReservedMemory[N].
//
for (Index = 0; Index < Config->Uefi.ReservedMemory.Count; ++Index) {
AsciiReservedMemoryType = OC_BLOB_GET (&Config->Uefi.ReservedMemory.Values[Index]->Type);
ReservedMemoryAddress = Config->Uefi.ReservedMemory.Values[Index]->Address;
ReservedMemorySize = Config->Uefi.ReservedMemory.Values[Index]->Size;
if (!ValidateReservedMemoryType (AsciiReservedMemoryType)) {
DEBUG ((DEBUG_WARN, "UEFI->ReservedMemory[%u]->Type is borked!\n", Index));
++ErrorCount;
}
if (ReservedMemoryAddress % EFI_PAGE_SIZE != 0) {
DEBUG ((DEBUG_WARN, "UEFI->ReservedMemory[%u]->Address (%Lu) cannot be divided by page size!\n", Index, ReservedMemoryAddress));
++ErrorCount;
}
if (ReservedMemorySize == 0ULL) {
DEBUG ((DEBUG_WARN, "UEFI->ReservedMemory[%u]->Size cannot be zero!\n", Index));
++ErrorCount;
} else if (ReservedMemorySize % EFI_PAGE_SIZE != 0) {
DEBUG ((DEBUG_WARN, "UEFI->ReservedMemory[%u]->Size (%Lu) cannot be divided by page size!\n", Index, ReservedMemorySize));
++ErrorCount;
}
}
//
// Now overlapping check amongst Address and Size.
//
ErrorCount += FindArrayDuplication (
Config->Uefi.ReservedMemory.Values,
Config->Uefi.ReservedMemory.Count,
sizeof (Config->Uefi.ReservedMemory.Values[0]),
UefiReservedMemoryHasOverlap
);
return ErrorCount;
}
UINT32
CheckUefi (
IN OC_GLOBAL_CONFIG *Config
)
{
UINT32 ErrorCount;
UINTN Index;
STATIC CONFIG_CHECK UefiCheckers[] = {
&CheckUefiAPFS,
&CheckUefiAppleInput,
&CheckUefiAudio,
&CheckUefiDrivers,
&CheckUefiInput,
&CheckUefiOutput,
&CheckUefiQuirks,
&CheckUefiReservedMemory
};
DEBUG ((DEBUG_VERBOSE, "config loaded into %a!\n", __func__));
ErrorCount = 0;
for (Index = 0; Index < ARRAY_SIZE (UefiCheckers); ++Index) {
ErrorCount += UefiCheckers[Index](Config);
}
return ReportError (__func__, ErrorCount);
}