]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformDxe/PlatformConfig.c
OvmfPkg: PlatformDxe: utility functions for saving / loading configuration
[mirror_edk2.git] / OvmfPkg / PlatformDxe / PlatformConfig.c
diff --git a/OvmfPkg/PlatformDxe/PlatformConfig.c b/OvmfPkg/PlatformDxe/PlatformConfig.c
new file mode 100644 (file)
index 0000000..3468f88
--- /dev/null
@@ -0,0 +1,131 @@
+/** @file\r
+\r
+  Utility functions for serializing (persistently storing) and deserializing\r
+  OVMF's platform configuration.\r
+\r
+  Copyright (C) 2014, Red Hat, Inc.\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Guid/OvmfPlatformConfig.h>\r
+\r
+#include "PlatformConfig.h"\r
+\r
+//\r
+// Name of the UEFI variable that we use for persistent storage.\r
+//\r
+STATIC CHAR16 mVariableName[] = L"PlatformConfig";\r
+\r
+\r
+/**\r
+  Serialize and persistently save platform configuration.\r
+\r
+  @param[in] PlatformConfig  The platform configuration to serialize and save.\r
+\r
+  @return  Status codes returned by gRT->SetVariable().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformConfigSave (\r
+  IN PLATFORM_CONFIG *PlatformConfig\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // We could implement any kind of translation here, as part of serialization.\r
+  // For example, we could expose the platform configuration in separate\r
+  // variables with human-readable contents, allowing other tools to access\r
+  // them more easily. For now, just save a binary dump.\r
+  //\r
+  Status = gRT->SetVariable (mVariableName, &gOvmfPlatformConfigGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
+                    EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof *PlatformConfig, PlatformConfig);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Load and deserialize platform configuration.\r
+\r
+  When the function fails, output parameters are indeterminate.\r
+\r
+  @param[out] PlatformConfig    The platform configuration to receive the\r
+                                loaded data.\r
+\r
+  @param[out] OptionalElements  This bitmap describes the presence of optional\r
+                                configuration elements that have been loaded.\r
+                                PLATFORM_CONFIG_F_DOWNGRADE means that some\r
+                                unknown elements, present in the wire format,\r
+                                have been ignored.\r
+\r
+  @retval  EFI_SUCCESS         Loading & deserialization successful.\r
+  @return                      Error codes returned by GetVariable2().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformConfigLoad (\r
+  OUT PLATFORM_CONFIG *PlatformConfig,\r
+  OUT UINT64          *OptionalElements\r
+  )\r
+{\r
+  VOID       *Data;\r
+  UINTN      DataSize;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // Any translation done in PlatformConfigSave() would have to be mirrored\r
+  // here. For now, just load the binary dump.\r
+  //\r
+  // Versioning of the binary wire format is implemented based on size\r
+  // (only incremental changes, ie. new fields), and on GUID.\r
+  // (Incompatible changes require a GUID change.)\r
+  //\r
+  Status = GetVariable2 (mVariableName, &gOvmfPlatformConfigGuid, &Data,\r
+             &DataSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *OptionalElements = 0;\r
+  if (DataSize > sizeof *PlatformConfig) {\r
+    //\r
+    // Handle firmware downgrade -- keep only leading part.\r
+    //\r
+    CopyMem (PlatformConfig, Data, sizeof *PlatformConfig);\r
+    *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE;\r
+  } else {\r
+    CopyMem (PlatformConfig, Data, DataSize);\r
+\r
+    //\r
+    // Handle firmware upgrade -- zero out missing fields.\r
+    //\r
+    ZeroMem ((UINT8 *)PlatformConfig + DataSize,\r
+      sizeof *PlatformConfig - DataSize);\r
+  }\r
+\r
+  //\r
+  // Based on DataSize, report the optional features that we recognize.\r
+  //\r
+  if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) +\r
+                   sizeof PlatformConfig->VerticalResolution)) {\r
+    *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION;\r
+  }\r
+\r
+  FreePool (Data);\r
+  return EFI_SUCCESS;\r
+}\r