VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/AcpiPlatformLib/BootScript.c

Last change on this file was 101291, checked in by vboxsync, 19 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette