mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
OpenRuntime: Store Boot options with different prefix
This commit is contained in:
parent
558f0a7385
commit
814b3d81b8
@ -17,6 +17,7 @@ OpenCore Changelog
|
||||
- Fixed `DisableSingleUser` quirk when Apple Secure Boot is enabled
|
||||
- Added `BootstrapShort` to workaround buggy Insyde firmwares
|
||||
- Changed `Bootstrap(Short)` to choose dynamic entry (requires NVRAM reset)
|
||||
- Avoided `Boot` prefix in `RequestBootVarRouting` to workaround AMI issues
|
||||
|
||||
#### v0.6.3
|
||||
- Added support for xml comments in plist files
|
||||
|
||||
@ -33,7 +33,7 @@ extern OC_FWRT_CONFIG gOverrideConfig;
|
||||
**/
|
||||
extern OC_FWRT_CONFIG *gCurrentConfig;
|
||||
|
||||
#define OC_GL_BOOT_OPTION_START 0xF000
|
||||
#define OC_VARIABLE_NAME_SIZE 256
|
||||
|
||||
VOID
|
||||
RedirectRuntimeServices (
|
||||
|
||||
@ -56,6 +56,9 @@ OC_FWRT_CONFIG *gCurrentConfig;
|
||||
STATIC EFI_EVENT mTranslateEvent;
|
||||
STATIC EFI_GET_VARIABLE mCustomGetVariable;
|
||||
STATIC BOOLEAN mKernelStarted;
|
||||
#ifdef OC_DEBUG_VAR_SERVICE ///< For file logging disable TPL checking in OcLogAddEntry.
|
||||
STATIC BOOLEAN mInsideVarService;
|
||||
#endif
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
@ -108,9 +111,12 @@ STATIC
|
||||
BOOLEAN
|
||||
IsEfiBootVar (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT CHAR16 *NewVariableName OPTIONAL
|
||||
)
|
||||
{
|
||||
UINTN Size;
|
||||
|
||||
if (!CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
|
||||
return FALSE;
|
||||
}
|
||||
@ -119,24 +125,85 @@ IsEfiBootVar (
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Return OC option path if requested.
|
||||
//
|
||||
// Many modern AMI BIOSes (e.g. ASUS ROG STRIX Z370-F GAMING)
|
||||
// have bugs in AMI Post Manager protocol implementation in AMI TSE.
|
||||
//
|
||||
// The handshake function, responsible for obtaining firmware
|
||||
// boot option list, calls gRT->GetNextVariableName and then matches
|
||||
// every Boot#### variable as a potential boot option regardless
|
||||
// of the GUID namespace it is in.
|
||||
//
|
||||
// The correct way to do it is to only check Boot#### variables in
|
||||
// gEfiGlobalVariableGuid VendorGuid. However, since they made a mistake,
|
||||
// most ASUS firmwares (and perhaps other vendors) get corrupted boot option
|
||||
// list (with e.g. duplicated options) if Boot#### variables are present
|
||||
// outside of gEfiGlobalVariableGuid.
|
||||
//
|
||||
// This is the case with OpenCore as we store macOS-specific boot options
|
||||
// in a separate GUID (gOcVendorVariableGuid). To workaround the issue
|
||||
// we store Boot options with a different prefix - OCBt. This way
|
||||
// Boot0001 becomes OCBt0001 and Bootorder becomes OCBtOrder.
|
||||
//
|
||||
// One of the ways to reproduce the issue is to enable Fast Boot
|
||||
// and let an ExitBootServices handler try to update BootOrder.
|
||||
// It can be easily noticed by BootFlow GetVariable with an uninitialised
|
||||
// size argument.
|
||||
//
|
||||
if (NewVariableName != NULL) {
|
||||
Size = StrSize (VariableName);
|
||||
if (Size > OC_VARIABLE_NAME_SIZE * sizeof (CHAR16)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (&NewVariableName[0], L"OCBt", L_STR_SIZE_NT (L"OCBt"));
|
||||
CopyMem (
|
||||
&NewVariableName[L_STR_LEN (L"OCBt")],
|
||||
&VariableName[L_STR_LEN (L"OCBt")],
|
||||
Size - L_STR_SIZE_NT (L"OCBt")
|
||||
);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsOcBootVar (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT CHAR16 *NewVariableName OPTIONAL
|
||||
)
|
||||
{
|
||||
UINTN Size;
|
||||
|
||||
if (!CompareGuid (VendorGuid, &gOcVendorVariableGuid)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (StrnCmp (L"Boot", VariableName, L_STR_LEN (L"Boot")) != 0) {
|
||||
if (StrnCmp (L"OCBt", VariableName, L_STR_LEN (L"OCBt")) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Return boot option if requested.
|
||||
//
|
||||
if (NewVariableName != NULL) {
|
||||
Size = StrSize (VariableName);
|
||||
if (Size > OC_VARIABLE_NAME_SIZE * sizeof (CHAR16)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (NewVariableName, L"Boot", L_STR_SIZE_NT (L"Boot"));
|
||||
CopyMem (
|
||||
&NewVariableName[L_STR_LEN (L"Boot")],
|
||||
&VariableName[L_STR_LEN (L"Boot")],
|
||||
Size - L_STR_SIZE_NT (L"Boot")
|
||||
);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -261,6 +328,7 @@ WrapGetVariable (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 TempName[OC_VARIABLE_NAME_SIZE];
|
||||
BOOLEAN Ints;
|
||||
BOOLEAN Wp;
|
||||
|
||||
@ -274,6 +342,14 @@ WrapGetVariable (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
#ifdef OC_DEBUG_VAR_SERVICE
|
||||
if (!mInsideVarService && StrCmp (VariableName, L"EfiTime") != 0) {
|
||||
mInsideVarService = TRUE;
|
||||
DEBUG ((DEBUG_INFO, "GETVAR %g:%s (%u)\n", VendorGuid, VariableName, (UINT32) *DataSize));
|
||||
mInsideVarService = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Abort access to write-only variables.
|
||||
//
|
||||
@ -286,7 +362,8 @@ WrapGetVariable (
|
||||
//
|
||||
// Redirect Boot-prefixed variables to our own GUID.
|
||||
//
|
||||
if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) {
|
||||
if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid, TempName)) {
|
||||
VariableName = TempName;
|
||||
VendorGuid = &gOcVendorVariableGuid;
|
||||
}
|
||||
|
||||
@ -317,12 +394,20 @@ WrapGetNextVariableName (
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINTN Size;
|
||||
CHAR16 TempName[256];
|
||||
CHAR16 TempName[OC_VARIABLE_NAME_SIZE];
|
||||
EFI_GUID TempGuid;
|
||||
BOOLEAN StartBootVar;
|
||||
BOOLEAN Ints;
|
||||
BOOLEAN Wp;
|
||||
|
||||
#ifdef OC_DEBUG_VAR_SERVICE
|
||||
if (!mInsideVarService) {
|
||||
mInsideVarService = TRUE;
|
||||
DEBUG ((DEBUG_INFO, "NEXVAR %g:%s (%u/%u)\n", VendorGuid, VariableName, (UINT32) *VariableNameSize));
|
||||
mInsideVarService = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Perform initial checks as per spec. Last check is part of:
|
||||
// Null-terminator is not found in the first VariableNameSize
|
||||
@ -374,7 +459,7 @@ WrapGetNextVariableName (
|
||||
// then go through the whole variable list and return
|
||||
// variables except EfiBoot.
|
||||
//
|
||||
if (!IsEfiBootVar (TempName, &TempGuid)) {
|
||||
if (!IsEfiBootVar (TempName, &TempGuid, TempName)) {
|
||||
while (TRUE) {
|
||||
//
|
||||
// Request for variables.
|
||||
@ -383,7 +468,7 @@ WrapGetNextVariableName (
|
||||
Status = mStoredGetNextVariableName (&Size, TempName, &TempGuid);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (!IsEfiBootVar (TempName, &TempGuid)) {
|
||||
if (!IsEfiBootVar (TempName, &TempGuid, NULL)) {
|
||||
Size = StrSize (TempName); ///< Not guaranteed to be updated with EFI_SUCCESS.
|
||||
|
||||
if (*VariableNameSize >= Size) {
|
||||
@ -456,6 +541,7 @@ WrapGetNextVariableName (
|
||||
} else {
|
||||
//
|
||||
// Switch to real GUID as stored in variable storage.
|
||||
// TempName is already updated with the new name.
|
||||
//
|
||||
CopyGuid (&TempGuid, &gOcVendorVariableGuid);
|
||||
}
|
||||
@ -468,7 +554,7 @@ WrapGetNextVariableName (
|
||||
Status = mStoredGetNextVariableName (&Size, TempName, &TempGuid);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (IsOcBootVar (TempName, &TempGuid)) {
|
||||
if (IsOcBootVar (TempName, &TempGuid, TempName)) {
|
||||
Size = StrSize (TempName); ///< Not guaranteed to be updated with EFI_SUCCESS.
|
||||
|
||||
if (*VariableNameSize >= Size) {
|
||||
@ -522,9 +608,18 @@ WrapSetVariable (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 TempName[OC_VARIABLE_NAME_SIZE];
|
||||
BOOLEAN Ints;
|
||||
BOOLEAN Wp;
|
||||
|
||||
#ifdef OC_DEBUG_VAR_SERVICE
|
||||
if (!mInsideVarService) {
|
||||
mInsideVarService = TRUE;
|
||||
DEBUG ((DEBUG_INFO, "SETVAR %g:%s (%u/%u)\n", VendorGuid, VariableName, (UINT32) DataSize, Attributes));
|
||||
mInsideVarService = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Abort access when running with read-only NVRAM.
|
||||
//
|
||||
@ -569,7 +664,8 @@ WrapSetVariable (
|
||||
// Redirect Boot-prefixed variables to our own GUID.
|
||||
//
|
||||
if (gCurrentConfig->BootVariableRedirect
|
||||
&& IsEfiBootVar (VariableName, VendorGuid)) {
|
||||
&& IsEfiBootVar (VariableName, VendorGuid, TempName)) {
|
||||
VariableName = TempName;
|
||||
VendorGuid = &gOcVendorVariableGuid;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user