1 /** @file
2
3 Utility functions for serializing (persistently storing) and deserializing
4 OVMF's platform configuration.
5
6 Copyright (C) 2014, Red Hat, Inc.
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiLib.h>
22 #include <Library/UefiRuntimeServicesTableLib.h>
23 #include <Guid/OvmfPlatformConfig.h>
24
25 #include "PlatformConfig.h"
26
27 //
28 // Name of the UEFI variable that we use for persistent storage.
29 //
30 STATIC CHAR16 mVariableName[] = L"PlatformConfig";
31
32
33 /**
34 Serialize and persistently save platform configuration.
35
36 @param[in] PlatformConfig The platform configuration to serialize and save.
37
38 @return Status codes returned by gRT->SetVariable().
39 **/
40 EFI_STATUS
41 EFIAPI
PlatformConfigSave(IN PLATFORM_CONFIG * PlatformConfig)42 PlatformConfigSave (
43 IN PLATFORM_CONFIG *PlatformConfig
44 )
45 {
46 EFI_STATUS Status;
47
48 //
49 // We could implement any kind of translation here, as part of serialization.
50 // For example, we could expose the platform configuration in separate
51 // variables with human-readable contents, allowing other tools to access
52 // them more easily. For now, just save a binary dump.
53 //
54 Status = gRT->SetVariable (mVariableName, &gOvmfPlatformConfigGuid,
55 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
56 EFI_VARIABLE_RUNTIME_ACCESS,
57 sizeof *PlatformConfig, PlatformConfig);
58 return Status;
59 }
60
61
62 /**
63 Load and deserialize platform configuration.
64
65 When the function fails, output parameters are indeterminate.
66
67 @param[out] PlatformConfig The platform configuration to receive the
68 loaded data.
69
70 @param[out] OptionalElements This bitmap describes the presence of optional
71 configuration elements that have been loaded.
72 PLATFORM_CONFIG_F_DOWNGRADE means that some
73 unknown elements, present in the wire format,
74 have been ignored.
75
76 @retval EFI_SUCCESS Loading & deserialization successful.
77 @return Error codes returned by GetVariable2().
78 **/
79 EFI_STATUS
80 EFIAPI
PlatformConfigLoad(OUT PLATFORM_CONFIG * PlatformConfig,OUT UINT64 * OptionalElements)81 PlatformConfigLoad (
82 OUT PLATFORM_CONFIG *PlatformConfig,
83 OUT UINT64 *OptionalElements
84 )
85 {
86 VOID *Data;
87 UINTN DataSize;
88 EFI_STATUS Status;
89
90 //
91 // Any translation done in PlatformConfigSave() would have to be mirrored
92 // here. For now, just load the binary dump.
93 //
94 // Versioning of the binary wire format is implemented based on size
95 // (only incremental changes, ie. new fields), and on GUID.
96 // (Incompatible changes require a GUID change.)
97 //
98 Status = GetVariable2 (mVariableName, &gOvmfPlatformConfigGuid, &Data,
99 &DataSize);
100 if (EFI_ERROR (Status)) {
101 return Status;
102 }
103
104 *OptionalElements = 0;
105 if (DataSize > sizeof *PlatformConfig) {
106 //
107 // Handle firmware downgrade -- keep only leading part.
108 //
109 CopyMem (PlatformConfig, Data, sizeof *PlatformConfig);
110 *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE;
111 } else {
112 CopyMem (PlatformConfig, Data, DataSize);
113
114 //
115 // Handle firmware upgrade -- zero out missing fields.
116 //
117 ZeroMem ((UINT8 *)PlatformConfig + DataSize,
118 sizeof *PlatformConfig - DataSize);
119 }
120
121 //
122 // Based on DataSize, report the optional features that we recognize.
123 //
124 if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) +
125 sizeof PlatformConfig->VerticalResolution)) {
126 *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION;
127 }
128
129 FreePool (Data);
130 return EFI_SUCCESS;
131 }
132