diff --git a/OvmfPkg/PlatformDxe/Platform.inf b/OvmfPkg/PlatformDxe/Platform.inf index 42a104c5b5..47ed25b5c7 100644 --- a/OvmfPkg/PlatformDxe/Platform.inf +++ b/OvmfPkg/PlatformDxe/Platform.inf @@ -26,6 +26,7 @@ [Sources] Platform.c + PlatformConfig.c [Packages] MdePkg/MdePkg.dec @@ -33,9 +34,17 @@ OvmfPkg/OvmfPkg.dec [LibraryClasses] + BaseMemoryLib DebugLib + MemoryAllocationLib UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib UefiDriverEntryPoint +[Guids] + gOvmfPlatformConfigGuid + [Depex] - TRUE + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/OvmfPkg/PlatformDxe/PlatformConfig.c b/OvmfPkg/PlatformDxe/PlatformConfig.c new file mode 100644 index 0000000000..3468f88150 --- /dev/null +++ b/OvmfPkg/PlatformDxe/PlatformConfig.c @@ -0,0 +1,131 @@ +/** @file + + Utility functions for serializing (persistently storing) and deserializing + OVMF's platform configuration. + + Copyright (C) 2014, Red Hat, Inc. + + 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 +#include +#include +#include +#include +#include + +#include "PlatformConfig.h" + +// +// Name of the UEFI variable that we use for persistent storage. +// +STATIC CHAR16 mVariableName[] = L"PlatformConfig"; + + +/** + Serialize and persistently save platform configuration. + + @param[in] PlatformConfig The platform configuration to serialize and save. + + @return Status codes returned by gRT->SetVariable(). +**/ +EFI_STATUS +EFIAPI +PlatformConfigSave ( + IN PLATFORM_CONFIG *PlatformConfig + ) +{ + EFI_STATUS Status; + + // + // We could implement any kind of translation here, as part of serialization. + // For example, we could expose the platform configuration in separate + // variables with human-readable contents, allowing other tools to access + // them more easily. For now, just save a binary dump. + // + Status = gRT->SetVariable (mVariableName, &gOvmfPlatformConfigGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof *PlatformConfig, PlatformConfig); + return Status; +} + + +/** + Load and deserialize platform configuration. + + When the function fails, output parameters are indeterminate. + + @param[out] PlatformConfig The platform configuration to receive the + loaded data. + + @param[out] OptionalElements This bitmap describes the presence of optional + configuration elements that have been loaded. + PLATFORM_CONFIG_F_DOWNGRADE means that some + unknown elements, present in the wire format, + have been ignored. + + @retval EFI_SUCCESS Loading & deserialization successful. + @return Error codes returned by GetVariable2(). +**/ +EFI_STATUS +EFIAPI +PlatformConfigLoad ( + OUT PLATFORM_CONFIG *PlatformConfig, + OUT UINT64 *OptionalElements + ) +{ + VOID *Data; + UINTN DataSize; + EFI_STATUS Status; + + // + // Any translation done in PlatformConfigSave() would have to be mirrored + // here. For now, just load the binary dump. + // + // Versioning of the binary wire format is implemented based on size + // (only incremental changes, ie. new fields), and on GUID. + // (Incompatible changes require a GUID change.) + // + Status = GetVariable2 (mVariableName, &gOvmfPlatformConfigGuid, &Data, + &DataSize); + if (EFI_ERROR (Status)) { + return Status; + } + + *OptionalElements = 0; + if (DataSize > sizeof *PlatformConfig) { + // + // Handle firmware downgrade -- keep only leading part. + // + CopyMem (PlatformConfig, Data, sizeof *PlatformConfig); + *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE; + } else { + CopyMem (PlatformConfig, Data, DataSize); + + // + // Handle firmware upgrade -- zero out missing fields. + // + ZeroMem ((UINT8 *)PlatformConfig + DataSize, + sizeof *PlatformConfig - DataSize); + } + + // + // Based on DataSize, report the optional features that we recognize. + // + if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) + + sizeof PlatformConfig->VerticalResolution)) { + *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION; + } + + FreePool (Data); + return EFI_SUCCESS; +} diff --git a/OvmfPkg/PlatformDxe/PlatformConfig.h b/OvmfPkg/PlatformDxe/PlatformConfig.h new file mode 100644 index 0000000000..3fd6982566 --- /dev/null +++ b/OvmfPkg/PlatformDxe/PlatformConfig.h @@ -0,0 +1,59 @@ +/** @file + + Utility functions for serializing (persistently storing) and deserializing + OVMF's platform configuration. + + Copyright (C) 2014, Red Hat, Inc. + + 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 _PLATFORM_CONFIG_H_ +#define _PLATFORM_CONFIG_H_ + +#include + +// +// This structure participates in driver configuration. It does not +// (necessarily) reflect the wire format in the persistent store. +// +#pragma pack(1) +typedef struct { + // + // preferred graphics console resolution when booting + // + UINT32 HorizontalResolution; + UINT32 VerticalResolution; +} PLATFORM_CONFIG; +#pragma pack() + +// +// Please see the API documentation near the function definitions. +// +EFI_STATUS +EFIAPI +PlatformConfigSave ( + IN PLATFORM_CONFIG *PlatformConfig + ); + +EFI_STATUS +EFIAPI +PlatformConfigLoad ( + OUT PLATFORM_CONFIG *PlatformConfig, + OUT UINT64 *OptionalElements + ); + +// +// Feature flags for OptionalElements. +// +#define PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION BIT0 +#define PLATFORM_CONFIG_F_DOWNGRADE BIT63 + +#endif // _PLATFORM_CONFIG_H_