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