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, 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"
18 // Condensed structure for capturing the fw_cfg operations -- select, skip,
19 // write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command.
22 UINT16 PointerItem
; // resolved from QEMU_LOADER_WRITE_POINTER.PointerFile
23 UINT8 PointerSize
; // copied as-is from QEMU_LOADER_WRITE_POINTER
24 UINT32 PointerOffset
; // copied as-is from QEMU_LOADER_WRITE_POINTER
25 UINT64 PointerValue
; // resolved from QEMU_LOADER_WRITE_POINTER.PointeeFile
26 // and QEMU_LOADER_WRITE_POINTER.PointeeOffset
27 } CONDENSED_WRITE_POINTER
;
30 // Context structure to accumulate CONDENSED_WRITE_POINTER objects from
31 // QEMU_LOADER_WRITE_POINTER commands.
33 // Any pointers in this structure own the pointed-to objects; that is, when the
34 // context structure is released, all pointed-to objects must be released too.
37 CONDENSED_WRITE_POINTER
*WritePointers
; // one array element per processed
38 // QEMU_LOADER_WRITE_POINTER
40 UINTN Allocated
; // number of elements allocated for
42 UINTN Used
; // number of elements populated in
47 // Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI
48 // S3 Boot Script opcodes to work on.
52 UINT64 PointerValue
; // filled in from CONDENSED_WRITE_POINTER.PointerValue
57 Allocate an S3_CONTEXT object.
59 @param[out] S3Context The allocated S3_CONTEXT object is returned
60 through this parameter.
62 @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to
63 allocate room for. WritePointerCount must be
66 @retval EFI_SUCCESS Allocation successful.
68 @retval EFI_OUT_OF_RESOURCES Out of memory.
70 @retval EFI_INVALID_PARAMETER WritePointerCount is zero.
74 OUT S3_CONTEXT
**S3Context
,
75 IN UINTN WritePointerCount
81 if (WritePointerCount
== 0) {
82 return EFI_INVALID_PARAMETER
;
85 Context
= AllocateZeroPool (sizeof *Context
);
86 if (Context
== NULL
) {
87 return EFI_OUT_OF_RESOURCES
;
90 Context
->WritePointers
= AllocatePool (
92 sizeof *Context
->WritePointers
94 if (Context
->WritePointers
== NULL
) {
95 Status
= EFI_OUT_OF_RESOURCES
;
99 Context
->Allocated
= WritePointerCount
;
100 *S3Context
= Context
;
110 Release an S3_CONTEXT object.
112 @param[in] S3Context The object to release.
116 IN S3_CONTEXT
*S3Context
119 FreePool (S3Context
->WritePointers
);
120 FreePool (S3Context
);
124 Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER
125 command during S3 resume, in condensed format.
127 This function is to be called from ProcessCmdWritePointer(), after all the
128 sanity checks have passed, and before the fw_cfg operations are performed.
130 @param[in,out] S3Context The S3_CONTEXT object into which the caller wants
131 to save the information that was derived from
132 QEMU_LOADER_WRITE_POINTER.
134 @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that
135 QEMU_LOADER_WRITE_POINTER.PointerFile was resolved
136 to, expressed as a UINT16 value.
138 @param[in] PointerSize Copied directly from
139 QEMU_LOADER_WRITE_POINTER.PointerSize.
141 @param[in] PointerOffset Copied directly from
142 QEMU_LOADER_WRITE_POINTER.PointerOffset.
144 @param[in] PointerValue The base address of the allocated / downloaded
145 fw_cfg blob that is identified by
146 QEMU_LOADER_WRITE_POINTER.PointeeFile, plus
147 QEMU_LOADER_WRITE_POINTER.PointeeOffset.
149 @retval EFI_SUCCESS The information derived from
150 QEMU_LOADER_WRITE_POINTER has been successfully
151 absorbed into S3Context.
153 @retval EFI_OUT_OF_RESOURCES No room available in S3Context.
156 SaveCondensedWritePointerToS3Context (
157 IN OUT S3_CONTEXT
*S3Context
,
158 IN UINT16 PointerItem
,
159 IN UINT8 PointerSize
,
160 IN UINT32 PointerOffset
,
161 IN UINT64 PointerValue
164 CONDENSED_WRITE_POINTER
*Condensed
;
166 if (S3Context
->Used
== S3Context
->Allocated
) {
167 return EFI_OUT_OF_RESOURCES
;
170 Condensed
= S3Context
->WritePointers
+ S3Context
->Used
;
171 Condensed
->PointerItem
= PointerItem
;
172 Condensed
->PointerSize
= PointerSize
;
173 Condensed
->PointerOffset
= PointerOffset
;
174 Condensed
->PointerValue
= PointerValue
;
177 "%a: 0x%04x/[0x%08x+%d] := 0x%Lx (%Lu)\n",
183 (UINT64
)S3Context
->Used
190 FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.
195 AppendFwCfgBootScript (
196 IN OUT VOID
*Context OPTIONAL
,
197 IN OUT VOID
*ExternalScratchBuffer
200 S3_CONTEXT
*S3Context
;
201 SCRATCH_BUFFER
*ScratchBuffer
;
205 ScratchBuffer
= ExternalScratchBuffer
;
207 for (Index
= 0; Index
< S3Context
->Used
; ++Index
) {
208 CONST CONDENSED_WRITE_POINTER
*Condensed
;
209 RETURN_STATUS Status
;
211 Condensed
= &S3Context
->WritePointers
[Index
];
213 Status
= QemuFwCfgS3ScriptSkipBytes (
214 Condensed
->PointerItem
,
215 Condensed
->PointerOffset
217 if (RETURN_ERROR (Status
)) {
221 ScratchBuffer
->PointerValue
= Condensed
->PointerValue
;
222 Status
= QemuFwCfgS3ScriptWriteBytes (-1, Condensed
->PointerSize
);
223 if (RETURN_ERROR (Status
)) {
228 DEBUG ((DEBUG_VERBOSE
, "%a: boot script fragment saved\n", __FUNCTION__
));
230 ReleaseS3Context (S3Context
);
239 Translate and append the information from an S3_CONTEXT object to the ACPI S3
242 The effects of a successful call to this function cannot be undone.
244 @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot
245 Script opcodes. If the function returns successfully,
246 the caller must set the S3Context pointer -- originally
247 returned by AllocateS3Context() -- immediately to NULL,
248 because the ownership of S3Context has been transferred.
250 @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script
251 opcodes has been successfully executed or queued. (This
252 includes the case when S3Context was empty on input and
253 no ACPI S3 Boot Script opcodes have been necessary to
256 @return Error codes from underlying functions.
259 TransferS3ContextToBootScript (
260 IN S3_CONTEXT
*S3Context
263 RETURN_STATUS Status
;
265 if (S3Context
->Used
== 0) {
266 ReleaseS3Context (S3Context
);
270 Status
= QemuFwCfgS3CallWhenBootScriptReady (
271 AppendFwCfgBootScript
,
273 sizeof (SCRATCH_BUFFER
)
275 return (EFI_STATUS
)Status
;