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