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