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