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 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
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.
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/QemuFwCfgLib.h>
18 #include <Library/QemuFwCfgS3Lib.h>
20 #include "AcpiPlatform.h"
24 // Condensed structure for capturing the fw_cfg operations -- select, skip,
25 // write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command.
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
;
37 // Context structure to accumulate CONDENSED_WRITE_POINTER objects from
38 // QEMU_LOADER_WRITE_POINTER commands.
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.
44 CONDENSED_WRITE_POINTER
*WritePointers
; // one array element per processed
45 // QEMU_LOADER_WRITE_POINTER
47 UINTN Allocated
; // number of elements allocated for
49 UINTN Used
; // number of elements populated in
55 // Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI
56 // S3 Boot Script opcodes to work on.
60 UINT64 PointerValue
; // filled in from CONDENSED_WRITE_POINTER.PointerValue
66 Allocate an S3_CONTEXT object.
68 @param[out] S3Context The allocated S3_CONTEXT object is returned
69 through this parameter.
71 @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to
72 allocate room for. WritePointerCount must be
75 @retval EFI_SUCCESS Allocation successful.
77 @retval EFI_OUT_OF_RESOURCES Out of memory.
79 @retval EFI_INVALID_PARAMETER WritePointerCount is zero.
83 OUT S3_CONTEXT
**S3Context
,
84 IN UINTN WritePointerCount
90 if (WritePointerCount
== 0) {
91 return EFI_INVALID_PARAMETER
;
94 Context
= AllocateZeroPool (sizeof *Context
);
95 if (Context
== NULL
) {
96 return EFI_OUT_OF_RESOURCES
;
99 Context
->WritePointers
= AllocatePool (WritePointerCount
*
100 sizeof *Context
->WritePointers
);
101 if (Context
->WritePointers
== NULL
) {
102 Status
= EFI_OUT_OF_RESOURCES
;
106 Context
->Allocated
= WritePointerCount
;
107 *S3Context
= Context
;
118 Release an S3_CONTEXT object.
120 @param[in] S3Context The object to release.
124 IN S3_CONTEXT
*S3Context
127 FreePool (S3Context
->WritePointers
);
128 FreePool (S3Context
);
133 Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER
134 command during S3 resume, in condensed format.
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.
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.
143 @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that
144 QEMU_LOADER_WRITE_POINTER.PointerFile was resolved
145 to, expressed as a UINT16 value.
147 @param[in] PointerSize Copied directly from
148 QEMU_LOADER_WRITE_POINTER.PointerSize.
150 @param[in] PointerOffset Copied directly from
151 QEMU_LOADER_WRITE_POINTER.PointerOffset.
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.
158 @retval EFI_SUCCESS The information derived from
159 QEMU_LOADER_WRITE_POINTER has been successfully
160 absorbed into S3Context.
162 @retval EFI_OUT_OF_RESOURCES No room available in S3Context.
165 SaveCondensedWritePointerToS3Context (
166 IN OUT S3_CONTEXT
*S3Context
,
167 IN UINT16 PointerItem
,
168 IN UINT8 PointerSize
,
169 IN UINT32 PointerOffset
,
170 IN UINT64 PointerValue
173 CONDENSED_WRITE_POINTER
*Condensed
;
175 if (S3Context
->Used
== S3Context
->Allocated
) {
176 return EFI_OUT_OF_RESOURCES
;
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
));
192 FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.
197 AppendFwCfgBootScript (
198 IN OUT VOID
*Context
, OPTIONAL
199 IN OUT VOID
*ExternalScratchBuffer
202 S3_CONTEXT
*S3Context
;
203 SCRATCH_BUFFER
*ScratchBuffer
;
207 ScratchBuffer
= ExternalScratchBuffer
;
209 for (Index
= 0; Index
< S3Context
->Used
; ++Index
) {
210 CONST CONDENSED_WRITE_POINTER
*Condensed
;
211 RETURN_STATUS Status
;
213 Condensed
= &S3Context
->WritePointers
[Index
];
215 Status
= QemuFwCfgS3ScriptSkipBytes (Condensed
->PointerItem
,
216 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
);
240 Translate and append the information from an S3_CONTEXT object to the ACPI S3
243 The effects of a successful call to this function cannot be undone.
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.
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
257 @return Error codes from underlying functions.
260 TransferS3ContextToBootScript (
261 IN S3_CONTEXT
*S3Context
264 RETURN_STATUS Status
;
266 if (S3Context
->Used
== 0) {
267 ReleaseS3Context (S3Context
);
271 Status
= QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript
,
272 S3Context
, sizeof (SCRATCH_BUFFER
));
273 return (EFI_STATUS
)Status
;