]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/AcpiPlatformDxe/BootScript.c
OvmfPkg/MemEncryptSevLib: find pages of initial SMRAM save state map
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / BootScript.c
... / ...
CommitLineData
1/** @file\r
2 Append an ACPI S3 Boot Script fragment from the QEMU_LOADER_WRITE_POINTER\r
3 commands of QEMU's fully processed table linker/loader script.\r
4\r
5 Copyright (C) 2017, Red Hat, Inc.\r
6\r
7 This program and the accompanying materials are licensed and made available\r
8 under the terms and conditions of the BSD License which accompanies this\r
9 distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14**/\r
15\r
16#include <Library/MemoryAllocationLib.h>\r
17#include <Library/QemuFwCfgLib.h>\r
18#include <Library/QemuFwCfgS3Lib.h>\r
19\r
20#include "AcpiPlatform.h"\r
21\r
22\r
23//\r
24// Condensed structure for capturing the fw_cfg operations -- select, skip,\r
25// write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command.\r
26//\r
27typedef struct {\r
28 UINT16 PointerItem; // resolved from QEMU_LOADER_WRITE_POINTER.PointerFile\r
29 UINT8 PointerSize; // copied as-is from QEMU_LOADER_WRITE_POINTER\r
30 UINT32 PointerOffset; // copied as-is from QEMU_LOADER_WRITE_POINTER\r
31 UINT64 PointerValue; // resolved from QEMU_LOADER_WRITE_POINTER.PointeeFile\r
32 // and QEMU_LOADER_WRITE_POINTER.PointeeOffset\r
33} CONDENSED_WRITE_POINTER;\r
34\r
35\r
36//\r
37// Context structure to accumulate CONDENSED_WRITE_POINTER objects from\r
38// QEMU_LOADER_WRITE_POINTER commands.\r
39//\r
40// Any pointers in this structure own the pointed-to objects; that is, when the\r
41// context structure is released, all pointed-to objects must be released too.\r
42//\r
43struct S3_CONTEXT {\r
44 CONDENSED_WRITE_POINTER *WritePointers; // one array element per processed\r
45 // QEMU_LOADER_WRITE_POINTER\r
46 // command\r
47 UINTN Allocated; // number of elements allocated for\r
48 // WritePointers\r
49 UINTN Used; // number of elements populated in\r
50 // WritePointers\r
51};\r
52\r
53\r
54//\r
55// Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI\r
56// S3 Boot Script opcodes to work on.\r
57//\r
58#pragma pack (1)\r
59typedef union {\r
60 UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerValue\r
61} SCRATCH_BUFFER;\r
62#pragma pack ()\r
63\r
64\r
65/**\r
66 Allocate an S3_CONTEXT object.\r
67\r
68 @param[out] S3Context The allocated S3_CONTEXT object is returned\r
69 through this parameter.\r
70\r
71 @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to\r
72 allocate room for. WritePointerCount must be\r
73 positive.\r
74\r
75 @retval EFI_SUCCESS Allocation successful.\r
76\r
77 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
78\r
79 @retval EFI_INVALID_PARAMETER WritePointerCount is zero.\r
80**/\r
81EFI_STATUS\r
82AllocateS3Context (\r
83 OUT S3_CONTEXT **S3Context,\r
84 IN UINTN WritePointerCount\r
85 )\r
86{\r
87 EFI_STATUS Status;\r
88 S3_CONTEXT *Context;\r
89\r
90 if (WritePointerCount == 0) {\r
91 return EFI_INVALID_PARAMETER;\r
92 }\r
93\r
94 Context = AllocateZeroPool (sizeof *Context);\r
95 if (Context == NULL) {\r
96 return EFI_OUT_OF_RESOURCES;\r
97 }\r
98\r
99 Context->WritePointers = AllocatePool (WritePointerCount *\r
100 sizeof *Context->WritePointers);\r
101 if (Context->WritePointers == NULL) {\r
102 Status = EFI_OUT_OF_RESOURCES;\r
103 goto FreeContext;\r
104 }\r
105\r
106 Context->Allocated = WritePointerCount;\r
107 *S3Context = Context;\r
108 return EFI_SUCCESS;\r
109\r
110FreeContext:\r
111 FreePool (Context);\r
112\r
113 return Status;\r
114}\r
115\r
116\r
117/**\r
118 Release an S3_CONTEXT object.\r
119\r
120 @param[in] S3Context The object to release.\r
121**/\r
122VOID\r
123ReleaseS3Context (\r
124 IN S3_CONTEXT *S3Context\r
125 )\r
126{\r
127 FreePool (S3Context->WritePointers);\r
128 FreePool (S3Context);\r
129}\r
130\r
131\r
132/**\r
133 Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER\r
134 command during S3 resume, in condensed format.\r
135\r
136 This function is to be called from ProcessCmdWritePointer(), after all the\r
137 sanity checks have passed, and before the fw_cfg operations are performed.\r
138\r
139 @param[in,out] S3Context The S3_CONTEXT object into which the caller wants\r
140 to save the information that was derived from\r
141 QEMU_LOADER_WRITE_POINTER.\r
142\r
143 @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that\r
144 QEMU_LOADER_WRITE_POINTER.PointerFile was resolved\r
145 to, expressed as a UINT16 value.\r
146\r
147 @param[in] PointerSize Copied directly from\r
148 QEMU_LOADER_WRITE_POINTER.PointerSize.\r
149\r
150 @param[in] PointerOffset Copied directly from\r
151 QEMU_LOADER_WRITE_POINTER.PointerOffset.\r
152\r
153 @param[in] PointerValue The base address of the allocated / downloaded\r
154 fw_cfg blob that is identified by\r
155 QEMU_LOADER_WRITE_POINTER.PointeeFile, plus\r
156 QEMU_LOADER_WRITE_POINTER.PointeeOffset.\r
157\r
158 @retval EFI_SUCCESS The information derived from\r
159 QEMU_LOADER_WRITE_POINTER has been successfully\r
160 absorbed into S3Context.\r
161\r
162 @retval EFI_OUT_OF_RESOURCES No room available in S3Context.\r
163**/\r
164EFI_STATUS\r
165SaveCondensedWritePointerToS3Context (\r
166 IN OUT S3_CONTEXT *S3Context,\r
167 IN UINT16 PointerItem,\r
168 IN UINT8 PointerSize,\r
169 IN UINT32 PointerOffset,\r
170 IN UINT64 PointerValue\r
171 )\r
172{\r
173 CONDENSED_WRITE_POINTER *Condensed;\r
174\r
175 if (S3Context->Used == S3Context->Allocated) {\r
176 return EFI_OUT_OF_RESOURCES;\r
177 }\r
178 Condensed = S3Context->WritePointers + S3Context->Used;\r
179 Condensed->PointerItem = PointerItem;\r
180 Condensed->PointerSize = PointerSize;\r
181 Condensed->PointerOffset = PointerOffset;\r
182 Condensed->PointerValue = PointerValue;\r
183 DEBUG ((DEBUG_VERBOSE, "%a: 0x%04x/[0x%08x+%d] := 0x%Lx (%Lu)\n",\r
184 __FUNCTION__, PointerItem, PointerOffset, PointerSize, PointerValue,\r
185 (UINT64)S3Context->Used));\r
186 ++S3Context->Used;\r
187 return EFI_SUCCESS;\r
188}\r
189\r
190\r
191/**\r
192 FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.\r
193**/\r
194STATIC\r
195VOID\r
196EFIAPI\r
197AppendFwCfgBootScript (\r
198 IN OUT VOID *Context, OPTIONAL\r
199 IN OUT VOID *ExternalScratchBuffer\r
200 )\r
201{\r
202 S3_CONTEXT *S3Context;\r
203 SCRATCH_BUFFER *ScratchBuffer;\r
204 UINTN Index;\r
205\r
206 S3Context = Context;\r
207 ScratchBuffer = ExternalScratchBuffer;\r
208\r
209 for (Index = 0; Index < S3Context->Used; ++Index) {\r
210 CONST CONDENSED_WRITE_POINTER *Condensed;\r
211 RETURN_STATUS Status;\r
212\r
213 Condensed = &S3Context->WritePointers[Index];\r
214\r
215 Status = QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem,\r
216 Condensed->PointerOffset);\r
217 if (RETURN_ERROR (Status)) {\r
218 goto FatalError;\r
219 }\r
220\r
221 ScratchBuffer->PointerValue = Condensed->PointerValue;\r
222 Status = QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize);\r
223 if (RETURN_ERROR (Status)) {\r
224 goto FatalError;\r
225 }\r
226 }\r
227\r
228 DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));\r
229\r
230 ReleaseS3Context (S3Context);\r
231 return;\r
232\r
233FatalError:\r
234 ASSERT (FALSE);\r
235 CpuDeadLoop ();\r
236}\r
237\r
238\r
239/**\r
240 Translate and append the information from an S3_CONTEXT object to the ACPI S3\r
241 Boot Script.\r
242\r
243 The effects of a successful call to this function cannot be undone.\r
244\r
245 @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot\r
246 Script opcodes. If the function returns successfully,\r
247 the caller must set the S3Context pointer -- originally\r
248 returned by AllocateS3Context() -- immediately to NULL,\r
249 because the ownership of S3Context has been transfered.\r
250\r
251 @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script\r
252 opcodes has been successfully executed or queued. (This\r
253 includes the case when S3Context was empty on input and\r
254 no ACPI S3 Boot Script opcodes have been necessary to\r
255 produce.)\r
256\r
257 @return Error codes from underlying functions.\r
258**/\r
259EFI_STATUS\r
260TransferS3ContextToBootScript (\r
261 IN S3_CONTEXT *S3Context\r
262 )\r
263{\r
264 RETURN_STATUS Status;\r
265\r
266 if (S3Context->Used == 0) {\r
267 ReleaseS3Context (S3Context);\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
271 Status = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript,\r
272 S3Context, sizeof (SCRATCH_BUFFER));\r
273 return (EFI_STATUS)Status;\r
274}\r