From c9bba52fc7312e8ea9071f9a4b7005954e36e0c1 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 26 May 2021 22:14:14 +0200 Subject: OvmfPkg/XenAcpiPlatformDxe: create from AcpiPlatformDxe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create an almost verbatim copy of the "OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf" driver for the OvmfXen platform. We're going to trim the driver in subsequent patches. Ultimately, the XenAcpiPlatformDxe driver will duplicate a negligible amount of code that is currently present in the QemuFwCfgAcpiPlatformDxe driver. List the new driver in "Maintainers.txt", in the "OvmfPkg: Xen-related modules" section. Switch the OvmfXen platform to the new driver at once. This patch should be reviewed with "git show --find-copies-harder". Cc: Andrew Fish Cc: Anthony Perard Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Julien Grall Cc: Leif Lindholm Cc: Michael D Kinney Cc: Philippe Mathieu-Daudé Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2122 Signed-off-by: Laszlo Ersek Message-Id: <20210526201446.12554-12-lersek@redhat.com> Reviewed-by: Ard Biesheuvel Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Leif Lindholm --- OvmfPkg/XenAcpiPlatformDxe/BootScript.c | 269 ++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 OvmfPkg/XenAcpiPlatformDxe/BootScript.c (limited to 'OvmfPkg/XenAcpiPlatformDxe/BootScript.c') diff --git a/OvmfPkg/XenAcpiPlatformDxe/BootScript.c b/OvmfPkg/XenAcpiPlatformDxe/BootScript.c new file mode 100644 index 0000000000..14d1e68694 --- /dev/null +++ b/OvmfPkg/XenAcpiPlatformDxe/BootScript.c @@ -0,0 +1,269 @@ +/** @file + Append an ACPI S3 Boot Script fragment from the QEMU_LOADER_WRITE_POINTER + commands of QEMU's fully processed table linker/loader script. + + Copyright (C) 2017-2021, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include // CpuDeadLoop() +#include // DEBUG() +#include // AllocatePool() +#include // QemuFwCfgS3ScriptSkipBytes() + +#include "AcpiPlatform.h" + + +// +// Condensed structure for capturing the fw_cfg operations -- select, skip, +// write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command. +// +typedef struct { + UINT16 PointerItem; // resolved from QEMU_LOADER_WRITE_POINTER.PointerFile + UINT8 PointerSize; // copied as-is from QEMU_LOADER_WRITE_POINTER + UINT32 PointerOffset; // copied as-is from QEMU_LOADER_WRITE_POINTER + UINT64 PointerValue; // resolved from QEMU_LOADER_WRITE_POINTER.PointeeFile + // and QEMU_LOADER_WRITE_POINTER.PointeeOffset +} CONDENSED_WRITE_POINTER; + + +// +// Context structure to accumulate CONDENSED_WRITE_POINTER objects from +// QEMU_LOADER_WRITE_POINTER commands. +// +// Any pointers in this structure own the pointed-to objects; that is, when the +// context structure is released, all pointed-to objects must be released too. +// +struct S3_CONTEXT { + CONDENSED_WRITE_POINTER *WritePointers; // one array element per processed + // QEMU_LOADER_WRITE_POINTER + // command + UINTN Allocated; // number of elements allocated for + // WritePointers + UINTN Used; // number of elements populated in + // WritePointers +}; + + +// +// Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI +// S3 Boot Script opcodes to work on. +// +#pragma pack (1) +typedef union { + UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerValue +} SCRATCH_BUFFER; +#pragma pack () + + +/** + Allocate an S3_CONTEXT object. + + @param[out] S3Context The allocated S3_CONTEXT object is returned + through this parameter. + + @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to + allocate room for. WritePointerCount must be + positive. + + @retval EFI_SUCCESS Allocation successful. + + @retval EFI_OUT_OF_RESOURCES Out of memory. + + @retval EFI_INVALID_PARAMETER WritePointerCount is zero. +**/ +EFI_STATUS +AllocateS3Context ( + OUT S3_CONTEXT **S3Context, + IN UINTN WritePointerCount + ) +{ + EFI_STATUS Status; + S3_CONTEXT *Context; + + if (WritePointerCount == 0) { + return EFI_INVALID_PARAMETER; + } + + Context = AllocateZeroPool (sizeof *Context); + if (Context == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Context->WritePointers = AllocatePool (WritePointerCount * + sizeof *Context->WritePointers); + if (Context->WritePointers == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeContext; + } + + Context->Allocated = WritePointerCount; + *S3Context = Context; + return EFI_SUCCESS; + +FreeContext: + FreePool (Context); + + return Status; +} + + +/** + Release an S3_CONTEXT object. + + @param[in] S3Context The object to release. +**/ +VOID +ReleaseS3Context ( + IN S3_CONTEXT *S3Context + ) +{ + FreePool (S3Context->WritePointers); + FreePool (S3Context); +} + + +/** + Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER + command during S3 resume, in condensed format. + + This function is to be called from ProcessCmdWritePointer(), after all the + sanity checks have passed, and before the fw_cfg operations are performed. + + @param[in,out] S3Context The S3_CONTEXT object into which the caller wants + to save the information that was derived from + QEMU_LOADER_WRITE_POINTER. + + @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that + QEMU_LOADER_WRITE_POINTER.PointerFile was resolved + to, expressed as a UINT16 value. + + @param[in] PointerSize Copied directly from + QEMU_LOADER_WRITE_POINTER.PointerSize. + + @param[in] PointerOffset Copied directly from + QEMU_LOADER_WRITE_POINTER.PointerOffset. + + @param[in] PointerValue The base address of the allocated / downloaded + fw_cfg blob that is identified by + QEMU_LOADER_WRITE_POINTER.PointeeFile, plus + QEMU_LOADER_WRITE_POINTER.PointeeOffset. + + @retval EFI_SUCCESS The information derived from + QEMU_LOADER_WRITE_POINTER has been successfully + absorbed into S3Context. + + @retval EFI_OUT_OF_RESOURCES No room available in S3Context. +**/ +EFI_STATUS +SaveCondensedWritePointerToS3Context ( + IN OUT S3_CONTEXT *S3Context, + IN UINT16 PointerItem, + IN UINT8 PointerSize, + IN UINT32 PointerOffset, + IN UINT64 PointerValue + ) +{ + CONDENSED_WRITE_POINTER *Condensed; + + if (S3Context->Used == S3Context->Allocated) { + return EFI_OUT_OF_RESOURCES; + } + Condensed = S3Context->WritePointers + S3Context->Used; + Condensed->PointerItem = PointerItem; + Condensed->PointerSize = PointerSize; + Condensed->PointerOffset = PointerOffset; + Condensed->PointerValue = PointerValue; + DEBUG ((DEBUG_VERBOSE, "%a: 0x%04x/[0x%08x+%d] := 0x%Lx (%Lu)\n", + __FUNCTION__, PointerItem, PointerOffset, PointerSize, PointerValue, + (UINT64)S3Context->Used)); + ++S3Context->Used; + return EFI_SUCCESS; +} + + +/** + FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib. +**/ +STATIC +VOID +EFIAPI +AppendFwCfgBootScript ( + IN OUT VOID *Context, OPTIONAL + IN OUT VOID *ExternalScratchBuffer + ) +{ + S3_CONTEXT *S3Context; + SCRATCH_BUFFER *ScratchBuffer; + UINTN Index; + + S3Context = Context; + ScratchBuffer = ExternalScratchBuffer; + + for (Index = 0; Index < S3Context->Used; ++Index) { + CONST CONDENSED_WRITE_POINTER *Condensed; + RETURN_STATUS Status; + + Condensed = &S3Context->WritePointers[Index]; + + Status = QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem, + Condensed->PointerOffset); + if (RETURN_ERROR (Status)) { + goto FatalError; + } + + ScratchBuffer->PointerValue = Condensed->PointerValue; + Status = QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize); + if (RETURN_ERROR (Status)) { + goto FatalError; + } + } + + DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__)); + + ReleaseS3Context (S3Context); + return; + +FatalError: + ASSERT (FALSE); + CpuDeadLoop (); +} + + +/** + Translate and append the information from an S3_CONTEXT object to the ACPI S3 + Boot Script. + + The effects of a successful call to this function cannot be undone. + + @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot + Script opcodes. If the function returns successfully, + the caller must set the S3Context pointer -- originally + returned by AllocateS3Context() -- immediately to NULL, + because the ownership of S3Context has been transferred. + + @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script + opcodes has been successfully executed or queued. (This + includes the case when S3Context was empty on input and + no ACPI S3 Boot Script opcodes have been necessary to + produce.) + + @return Error codes from underlying functions. +**/ +EFI_STATUS +TransferS3ContextToBootScript ( + IN S3_CONTEXT *S3Context + ) +{ + RETURN_STATUS Status; + + if (S3Context->Used == 0) { + ReleaseS3Context (S3Context); + return EFI_SUCCESS; + } + + Status = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript, + S3Context, sizeof (SCRATCH_BUFFER)); + return (EFI_STATUS)Status; +} -- cgit v1.2.3