From 3d2deacfbbb3583359060e7429a09283584e28fa Mon Sep 17 00:00:00 2001 From: vit9696 Date: Wed, 7 Aug 2019 18:11:54 +0300 Subject: [PATCH] FwRuntimeServices: Rework to support read-only NVRAM --- Application/CleanNvram/CleanNvram.c | 13 +-- .../FwRuntimeServices/FwRuntimeServices.c | 94 +++++++------------ .../FwRuntimeServices/FwRuntimeServices.inf | 1 - .../FwRuntimeServicesPrivate.h | 29 +++--- .../FwRuntimeServices/UefiRuntimeServices.c | 74 +++++---------- 5 files changed, 82 insertions(+), 129 deletions(-) diff --git a/Application/CleanNvram/CleanNvram.c b/Application/CleanNvram/CleanNvram.c index 352ec59..6d451e7 100644 --- a/Application/CleanNvram/CleanNvram.c +++ b/Application/CleanNvram/CleanNvram.c @@ -209,7 +209,7 @@ UefiMain ( { EFI_STATUS Status; OC_FIRMWARE_RUNTIME_PROTOCOL *FwRuntime; - BOOLEAN Redirect; + OC_FWRT_CONFIG Config; Print (L"NVRAM cleanup %s\n", APPLE_SUPPORT_VERSION); @@ -220,18 +220,19 @@ UefiMain ( ); if (!EFI_ERROR (Status) && FwRuntime->Revision >= OC_FIRMWARE_RUNTIME_REVISION) { - Redirect = FwRuntime->SetNvram (FALSE); - Print (L"Found AMF NVRAM, full access %d\n", Redirect); + ZeroMem (&Config, sizeof (Config)); + FwRuntime->SetOverride (&Config); + Print (L"Found AMF NVRAM, full access %d\n", Config.BootVariableRedirect); } else { - Redirect = FALSE; + FwRuntime = NULL; Print (L"Missing AMF NVRAM\n"); } DeleteVariables (); - if (Redirect) { + if (FwRuntime != NULL) { Print (L"Restoring AMF NVRAM...\n"); - FwRuntime->SetNvram (TRUE); + FwRuntime->SetOverride (NULL); } Print (L"NVRAM cleanup completed, please reboot!\n"); diff --git a/Platform/FwRuntimeServices/FwRuntimeServices.c b/Platform/FwRuntimeServices/FwRuntimeServices.c index 4713439..2b8a88a 100644 --- a/Platform/FwRuntimeServices/FwRuntimeServices.c +++ b/Platform/FwRuntimeServices/FwRuntimeServices.c @@ -14,6 +14,7 @@ #include "FwRuntimeServicesPrivate.h" +#include #include #include #include @@ -22,73 +23,49 @@ #include #include -STATIC EFI_IMAGE_START mStoredStartImage; - -STATIC UINTN mNestedCount; - -EFI_STATUS +STATIC +VOID EFIAPI -WrapStartImage ( - IN EFI_HANDLE ImageHandle, - OUT UINTN *ExitDataSize, - OUT CHAR16 **ExitData OPTIONAL +FwGetCurrent ( + OUT OC_FWRT_CONFIG *Config ) { - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL *AppleLoadedImage; - - AppleLoadedImage = OcGetAppleBootLoadedImage (ImageHandle); - - // - // Nest count checking is used to protect from situations like - // Start BootLoader → { Start App, App Finished, Start Kernel } - // - ++mNestedCount; + CopyMem (Config, gCurrentConfig, sizeof (*Config)); +} - if (mNestedCount == 1) { - // - // Request boot variable redirection if enabled. - // - SetBootVariableRedirect (TRUE); - - if (AppleLoadedImage) { - // - // Latest Windows brings Virtualization-based security and monitors - // CR0 by launching itself under a hypevisor. Since we need WP disable - // on macOS to let NVRAM work, and for the time being no other OS - // requires it, here we decide to use it for macOS exclusively. - // - SetWriteUnprotectorMode (TRUE); - } - - Status = mStoredStartImage (ImageHandle, ExitDataSize, ExitData); - - if (AppleLoadedImage) { - // - // We failed but other operating systems should be loadable. - // - SetWriteUnprotectorMode (FALSE); - } +STATIC +VOID +EFIAPI +FwSetMain ( + IN CONST OC_FWRT_CONFIG *Config + ) +{ + CopyMem (&gMainConfig, Config, sizeof (gMainConfig)); +} - // - // Disable redirect on failure, this is cleaner design-wise. - // - SetBootVariableRedirect (FALSE); +STATIC +VOID +EFIAPI +FwSetOverride ( + IN CONST OC_FWRT_CONFIG *Config + ) +{ + if (Config != NULL) { + CopyMem (&gOverrideConfig, Config, sizeof (gOverrideConfig)); + gCurrentConfig = &gOverrideConfig; } else { - Status = mStoredStartImage (ImageHandle, ExitDataSize, ExitData); + gCurrentConfig = &gMainConfig; } - - --mNestedCount; - - return Status; } STATIC OC_FIRMWARE_RUNTIME_PROTOCOL mOcFirmwareRuntimeProtocol = { OC_FIRMWARE_RUNTIME_REVISION, - SetBootVariableRedirect, - SetCustomGetVariableHandler + FwGetCurrent, + FwSetMain, + FwSetOverride, + FwOnGetVariable }; EFI_STATUS @@ -115,11 +92,10 @@ UefiEntrypoint ( return EFI_ALREADY_STARTED; } - mStoredStartImage = gBS->StartImage; - gBS->StartImage = WrapStartImage; - - gBS->Hdr.CRC32 = 0; - gBS->CalculateCrc32 (gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32); + // + // Activate main configuration. + // + gCurrentConfig = &gMainConfig; RedirectRuntimeServices (); diff --git a/Platform/FwRuntimeServices/FwRuntimeServices.inf b/Platform/FwRuntimeServices/FwRuntimeServices.inf index 2aa95eb..d5c2cd0 100755 --- a/Platform/FwRuntimeServices/FwRuntimeServices.inf +++ b/Platform/FwRuntimeServices/FwRuntimeServices.inf @@ -51,7 +51,6 @@ gAppleBootVariableGuid ## SOMETIMES_CONSUMES [Protocols] - gEfiLoadedImageProtocolGuid ## CONSUMES gOcFirmwareRuntimeProtocolGuid ## SOMETIMES_PRODUCES [Depex] diff --git a/Platform/FwRuntimeServices/FwRuntimeServicesPrivate.h b/Platform/FwRuntimeServices/FwRuntimeServicesPrivate.h index 4e7d7cc..cd5e591 100644 --- a/Platform/FwRuntimeServices/FwRuntimeServicesPrivate.h +++ b/Platform/FwRuntimeServices/FwRuntimeServicesPrivate.h @@ -16,26 +16,31 @@ #define FIRMWARE_RUNTIME_SERVICES_PRIVATE_H #include +#include + +/** + Main runtime services configuration. +**/ +extern OC_FWRT_CONFIG gMainConfig; + +/** + Override runtime services configuration. +**/ +extern OC_FWRT_CONFIG gOverrideConfig; + +/** + Current active runtime services configuration (main or override). +**/ +extern OC_FWRT_CONFIG *gCurrentConfig; VOID RedirectRuntimeServices ( VOID ); -VOID -SetWriteUnprotectorMode ( - IN BOOLEAN Enable - ); - -BOOLEAN -EFIAPI -SetBootVariableRedirect ( - IN BOOLEAN Enable - ); - EFI_STATUS EFIAPI -SetCustomGetVariableHandler ( +FwOnGetVariable ( IN EFI_GET_VARIABLE GetVariable, OUT EFI_GET_VARIABLE *OrgGetVariable OPTIONAL ); diff --git a/Platform/FwRuntimeServices/UefiRuntimeServices.c b/Platform/FwRuntimeServices/UefiRuntimeServices.c index 663e7cd..e3e712b 100644 --- a/Platform/FwRuntimeServices/UefiRuntimeServices.c +++ b/Platform/FwRuntimeServices/UefiRuntimeServices.c @@ -37,9 +37,12 @@ STATIC EFI_SET_VARIABLE mStoredSetVariable; STATIC EFI_GET_NEXT_HIGH_MONO_COUNT mStoredGetNextHighMonotonicCount; STATIC EFI_RESET_SYSTEM mStoredResetSystem; -STATIC BOOLEAN mBootVariableRedirect; -STATIC BOOLEAN mWriteUnprotector; -STATIC BOOLEAN mRestrictedPermissions; +/** + Configurations to use. +**/ +OC_FWRT_CONFIG gMainConfig; +OC_FWRT_CONFIG gOverrideConfig; +OC_FWRT_CONFIG *gCurrentConfig; /** Boot phase accessible variables. @@ -56,7 +59,7 @@ WriteUnprotectorPrologue ( { IA32_CR0 Cr0; - if (mWriteUnprotector) { + if (gCurrentConfig->WriteUnprotector) { *Ints = SaveAndDisableInterrupts (); Cr0.UintN = AsmReadCr0 (); if (Cr0.Bits.WP == 1) { @@ -81,7 +84,7 @@ WriteUnprotectorEpilogue ( { IA32_CR0 Cr0; - if (mWriteUnprotector) { + if (gCurrentConfig->WriteUnprotector) { if (Wp) { Cr0.UintN = AsmReadCr0 (); Cr0.Bits.WP = 1; @@ -268,7 +271,7 @@ WrapGetVariable ( // // Abort access to write-only variables. // - if (mRestrictedPermissions + if (gCurrentConfig->RestrictedVariables && CompareGuid (VendorGuid, &gOcWriteOnlyVariableGuid)) { return EFI_SECURITY_VIOLATION; } @@ -276,7 +279,7 @@ WrapGetVariable ( // // Redirect Boot-prefixed variables to our own GUID. // - if (mBootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) { + if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) { VendorGuid = &gOcVendorVariableGuid; Routed = TRUE; } else { @@ -348,7 +351,7 @@ WrapGetNextVariableName ( // // In case we do not redirect, simply do nothing. // - if (!mBootVariableRedirect) { + if (!gCurrentConfig->BootVariableRedirect) { Status = mStoredGetNextVariableName (VariableNameSize, VariableName, VendorGuid); WriteUnprotectorEpilogue (Ints, Wp); return Status; @@ -518,10 +521,17 @@ WrapSetVariable ( BOOLEAN Ints; BOOLEAN Wp; + // + // Abort access when running with read-only NVRAM. + // + if (gCurrentConfig->WriteProtection) { + return EFI_SECURITY_VIOLATION; + } + // // Abort access to read-only variables. // - if (mRestrictedPermissions + if (gCurrentConfig->RestrictedVariables && CompareGuid (VendorGuid, &gOcReadOnlyVariableGuid)) { return EFI_SECURITY_VIOLATION; } @@ -529,7 +539,7 @@ WrapSetVariable ( // // Redirect Boot-prefixed variables to our own GUID. // - if (mBootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) { + if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) { VendorGuid = &gOcVendorVariableGuid; } @@ -595,47 +605,9 @@ WrapResetSystem ( WriteUnprotectorEpilogue (Ints, Wp); } -VOID -SetWriteUnprotectorMode ( - IN BOOLEAN Enable - ) -{ - mWriteUnprotector = Enable; -} - -BOOLEAN -EFIAPI -SetBootVariableRedirect ( - IN BOOLEAN Enable - ) -{ - UINTN DataSize; - EFI_STATUS Status; - BOOLEAN Previous; - - if (Enable) { - DataSize = sizeof (Enable); - Status = mStoredGetVariable ( - OC_BOOT_REDIRECT_VARIABLE_NAME, - &gOcVendorVariableGuid, - NULL, - &DataSize, - &Enable - ); - - if (EFI_ERROR (Status)) { - Enable = FALSE; - } - } - - Previous = mBootVariableRedirect; - mBootVariableRedirect = Enable; - return Previous; -} - EFI_STATUS EFIAPI -SetCustomGetVariableHandler ( +FwOnGetVariable ( IN EFI_GET_VARIABLE GetVariable, OUT EFI_GET_VARIABLE *OrgGetVariable OPTIONAL ) @@ -671,8 +643,8 @@ TranslateAddressesHandler ( gRT->ConvertPointer (0, (VOID **) &mStoredGetNextHighMonotonicCount); gRT->ConvertPointer (0, (VOID **) &mStoredResetSystem); - mCustomGetVariable = NULL; - mRestrictedPermissions = TRUE; + gRT->ConvertPointer (0, (VOID **) &gCurrentConfig); + mCustomGetVariable = NULL; } VOID