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.
5 Copyright (C) 2017-2021, Red Hat, Inc.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h> // CpuDeadLoop()
11 #include <Library/DebugLib.h> // DEBUG()
12 #include <Library/MemoryAllocationLib.h> // AllocatePool()
13 #include <Library/QemuFwCfgS3Lib.h> // QemuFwCfgS3ScriptSkipBytes()
15 #include "AcpiPlatform.h"
19 // Condensed structure for capturing the fw_cfg operations -- select, skip,
20 // write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command.
23 UINT16 PointerItem
; // resolved from QEMU_LOADER_WRITE_POINTER.PointerFile
24 UINT8 PointerSize
; // copied as-is from QEMU_LOADER_WRITE_POINTER
25 UINT32 PointerOffset
; // copied as-is from QEMU_LOADER_WRITE_POINTER
26 UINT64 PointerValue
; // resolved from QEMU_LOADER_WRITE_POINTER.PointeeFile
27 // and QEMU_LOADER_WRITE_POINTER.PointeeOffset
28 } CONDENSED_WRITE_POINTER
;
32 // Context structure to accumulate CONDENSED_WRITE_POINTER objects from
33 // QEMU_LOADER_WRITE_POINTER commands.
35 // Any pointers in this structure own the pointed-to objects; that is, when the
36 // context structure is released, all pointed-to objects must be released too.
39 CONDENSED_WRITE_POINTER
*WritePointers
; // one array element per processed
40 // QEMU_LOADER_WRITE_POINTER
42 UINTN Allocated
; // number of elements allocated for
44 UINTN Used
; // number of elements populated in
50 // Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI
51 // S3 Boot Script opcodes to work on.
55 UINT64 PointerValue
; // filled in from CONDENSED_WRITE_POINTER.PointerValue
61 Allocate an S3_CONTEXT object.
63 @param[out] S3Context The allocated S3_CONTEXT object is returned
64 through this parameter.
66 @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to
67 allocate room for. WritePointerCount must be
70 @retval EFI_SUCCESS Allocation successful.
72 @retval EFI_OUT_OF_RESOURCES Out of memory.
74 @retval EFI_INVALID_PARAMETER WritePointerCount is zero.
78 OUT S3_CONTEXT
**S3Context
,
79 IN UINTN WritePointerCount
85 if (WritePointerCount
== 0) {
86 return EFI_INVALID_PARAMETER
;
89 Context
= AllocateZeroPool (sizeof *Context
);
90 if (Context
== NULL
) {
91 return EFI_OUT_OF_RESOURCES
;
94 Context
->WritePointers
= AllocatePool (WritePointerCount
*
95 sizeof *Context
->WritePointers
);
96 if (Context
->WritePointers
== NULL
) {
97 Status
= EFI_OUT_OF_RESOURCES
;
101 Context
->Allocated
= WritePointerCount
;
102 *S3Context
= Context
;
113 Release an S3_CONTEXT object.
115 @param[in] S3Context The object to release.
119 IN S3_CONTEXT
*S3Context
122 FreePool (S3Context
->WritePointers
);
123 FreePool (S3Context
);
128 Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER
129 command during S3 resume, in condensed format.
131 This function is to be called from ProcessCmdWritePointer(), after all the
132 sanity checks have passed, and before the fw_cfg operations are performed.
134 @param[in,out] S3Context The S3_CONTEXT object into which the caller wants
135 to save the information that was derived from
136 QEMU_LOADER_WRITE_POINTER.
138 @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that
139 QEMU_LOADER_WRITE_POINTER.PointerFile was resolved
140 to, expressed as a UINT16 value.
142 @param[in] PointerSize Copied directly from
143 QEMU_LOADER_WRITE_POINTER.PointerSize.
145 @param[in] PointerOffset Copied directly from
146 QEMU_LOADER_WRITE_POINTER.PointerOffset.
148 @param[in] PointerValue The base address of the allocated / downloaded
149 fw_cfg blob that is identified by
150 QEMU_LOADER_WRITE_POINTER.PointeeFile, plus
151 QEMU_LOADER_WRITE_POINTER.PointeeOffset.
153 @retval EFI_SUCCESS The information derived from
154 QEMU_LOADER_WRITE_POINTER has been successfully
155 absorbed into S3Context.
157 @retval EFI_OUT_OF_RESOURCES No room available in S3Context.
160 SaveCondensedWritePointerToS3Context (
161 IN OUT S3_CONTEXT
*S3Context
,
162 IN UINT16 PointerItem
,
163 IN UINT8 PointerSize
,
164 IN UINT32 PointerOffset
,
165 IN UINT64 PointerValue
168 CONDENSED_WRITE_POINTER
*Condensed
;
170 if (S3Context
->Used
== S3Context
->Allocated
) {
171 return EFI_OUT_OF_RESOURCES
;
173 Condensed
= S3Context
->WritePointers
+ S3Context
->Used
;
174 Condensed
->PointerItem
= PointerItem
;
175 Condensed
->PointerSize
= PointerSize
;
176 Condensed
->PointerOffset
= PointerOffset
;
177 Condensed
->PointerValue
= PointerValue
;
178 DEBUG ((DEBUG_VERBOSE
, "%a: 0x%04x/[0x%08x+%d] := 0x%Lx (%Lu)\n",
179 __FUNCTION__
, PointerItem
, PointerOffset
, PointerSize
, PointerValue
,
180 (UINT64
)S3Context
->Used
));
187 FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.
192 AppendFwCfgBootScript (
193 IN OUT VOID
*Context
, OPTIONAL
194 IN OUT VOID
*ExternalScratchBuffer
197 S3_CONTEXT
*S3Context
;
198 SCRATCH_BUFFER
*ScratchBuffer
;
202 ScratchBuffer
= ExternalScratchBuffer
;
204 for (Index
= 0; Index
< S3Context
->Used
; ++Index
) {
205 CONST CONDENSED_WRITE_POINTER
*Condensed
;
206 RETURN_STATUS Status
;
208 Condensed
= &S3Context
->WritePointers
[Index
];
210 Status
= QemuFwCfgS3ScriptSkipBytes (Condensed
->PointerItem
,
211 Condensed
->PointerOffset
);
212 if (RETURN_ERROR (Status
)) {
216 ScratchBuffer
->PointerValue
= Condensed
->PointerValue
;
217 Status
= QemuFwCfgS3ScriptWriteBytes (-1, Condensed
->PointerSize
);
218 if (RETURN_ERROR (Status
)) {
223 DEBUG ((DEBUG_VERBOSE
, "%a: boot script fragment saved\n", __FUNCTION__
));
225 ReleaseS3Context (S3Context
);
235 Translate and append the information from an S3_CONTEXT object to the ACPI S3
238 The effects of a successful call to this function cannot be undone.
240 @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot
241 Script opcodes. If the function returns successfully,
242 the caller must set the S3Context pointer -- originally
243 returned by AllocateS3Context() -- immediately to NULL,
244 because the ownership of S3Context has been transferred.
246 @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script
247 opcodes has been successfully executed or queued. (This
248 includes the case when S3Context was empty on input and
249 no ACPI S3 Boot Script opcodes have been necessary to
252 @return Error codes from underlying functions.
255 TransferS3ContextToBootScript (
256 IN S3_CONTEXT
*S3Context
259 RETURN_STATUS Status
;
261 if (S3Context
->Used
== 0) {
262 ReleaseS3Context (S3Context
);
266 Status
= QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript
,
267 S3Context
, sizeof (SCRATCH_BUFFER
));
268 return (EFI_STATUS
)Status
;