mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
722 lines
22 KiB
C
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);
|
|
}
|