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.
254 @return Error codes from underlying functions.
257 TransferS3ContextToBootScript (
258 IN S3_CONTEXT
*S3Context
261 RETURN_STATUS Status
;
263 Status
= QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript
,
264 S3Context
, sizeof (SCRATCH_BUFFER
));
265 return (EFI_STATUS
)Status
;