|
@@ -0,0 +1,528 @@
|
|
|
+/** @file
|
|
|
+ Acpi Debug driver code.
|
|
|
+
|
|
|
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
|
+This program and the accompanying materials are licensed and made available under
|
|
|
+the terms and conditions of the BSD License that accompanies this distribution.
|
|
|
+The full text of the license may be found at
|
|
|
+http://opensource.org/licenses/bsd-license.php.
|
|
|
+
|
|
|
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
+
|
|
|
+**/
|
|
|
+
|
|
|
+
|
|
|
+#include <Uefi.h>
|
|
|
+#include <Library/BaseLib.h>
|
|
|
+#include <Library/BaseMemoryLib.h>
|
|
|
+#include <Library/UefiBootServicesTableLib.h>
|
|
|
+#include <Library/DebugLib.h>
|
|
|
+#include <Library/PcdLib.h>
|
|
|
+#include <Library/DxeServicesLib.h>
|
|
|
+#include <Protocol/AcpiTable.h>
|
|
|
+#include <IndustryStandard/Acpi.h>
|
|
|
+
|
|
|
+#include <Protocol/SmmBase2.h>
|
|
|
+#include <Protocol/SmmEndOfDxe.h>
|
|
|
+#include <Protocol/SmmSwDispatch2.h>
|
|
|
+
|
|
|
+#define ACPI_DEBUG_STR "INTEL ACPI DEBUG"
|
|
|
+
|
|
|
+//
|
|
|
+// ASL NAME structure
|
|
|
+//
|
|
|
+#pragma pack(1)
|
|
|
+typedef struct {
|
|
|
+ UINT8 NameOp; // Byte [0]=0x08:NameOp.
|
|
|
+ UINT32 NameString; // Byte [4:1]=Name of object.
|
|
|
+ UINT8 DWordPrefix; // Byte [5]=0x0C:DWord Prefix.
|
|
|
+ UINT32 Value; // 0 ; Value of named object.
|
|
|
+} NAME_LAYOUT;
|
|
|
+#pragma pack()
|
|
|
+
|
|
|
+#pragma pack(1)
|
|
|
+typedef struct {
|
|
|
+ UINT8 Signature[16]; // "INTEL ACPI DEBUG"
|
|
|
+ UINT32 BufferSize; // Total size of Acpi Debug buffer including header structure
|
|
|
+ UINT32 Head; // Current buffer pointer for SMM to print out
|
|
|
+ UINT32 Tail; // Current buffer pointer for ASL to input
|
|
|
+ UINT8 SmiTrigger; // Value to trigger the SMI via B2 port
|
|
|
+ UINT8 Wrap; // If current Tail < Head
|
|
|
+ UINT8 SmmVersion; // If SMM version
|
|
|
+ UINT8 Truncate; // If the input from ASL > MAX_BUFFER_SIZE
|
|
|
+} ACPI_DEBUG_HEAD;
|
|
|
+#pragma pack()
|
|
|
+
|
|
|
+#define AD_SIZE sizeof (ACPI_DEBUG_HEAD) // This is 0x20
|
|
|
+
|
|
|
+#define MAX_BUFFER_SIZE 32
|
|
|
+
|
|
|
+UINT32 mBufferEnd = 0;
|
|
|
+ACPI_DEBUG_HEAD *mAcpiDebug = NULL;
|
|
|
+
|
|
|
+EFI_SMM_SYSTEM_TABLE2 *mSmst = NULL;
|
|
|
+
|
|
|
+/**
|
|
|
+ Patch and load ACPI table.
|
|
|
+
|
|
|
+ @param[in] AcpiDebugAddress Address of Acpi debug memory buffer.
|
|
|
+ @param[in] BufferIndex Index that starts after the Acpi Debug head.
|
|
|
+ @param[in] BufferEnd End of Acpi debug memory buffer.
|
|
|
+
|
|
|
+**/
|
|
|
+VOID
|
|
|
+PatchAndLoadAcpiTable (
|
|
|
+ IN ACPI_DEBUG_HEAD *AcpiDebugAddress,
|
|
|
+ IN UINT32 BufferIndex,
|
|
|
+ IN UINT32 BufferEnd
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
|
|
|
+ UINTN Size;
|
|
|
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
|
|
|
+ UINTN TableKey;
|
|
|
+ UINT8 *CurrPtr;
|
|
|
+ UINT32 *Signature;
|
|
|
+ NAME_LAYOUT *NamePtr;
|
|
|
+ UINT8 UpdateCounter;
|
|
|
+
|
|
|
+ Status = GetSectionFromFv (
|
|
|
+ &gEfiCallerIdGuid,
|
|
|
+ EFI_SECTION_RAW,
|
|
|
+ 0,
|
|
|
+ (VOID **) &TableHeader,
|
|
|
+ &Size
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // This is Acpi Debug SSDT. Acpi Debug should be enabled if we reach here so load the table.
|
|
|
+ //
|
|
|
+ ASSERT (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId == SIGNATURE_64 ('A', 'D', 'e', 'b', 'T', 'a', 'b', 'l'));
|
|
|
+
|
|
|
+ //
|
|
|
+ // Patch some pointers for the ASL code before loading the SSDT.
|
|
|
+ //
|
|
|
+
|
|
|
+ //
|
|
|
+ // Count pointer updates, so we can stop after all three pointers are patched.
|
|
|
+ //
|
|
|
+ UpdateCounter = 1;
|
|
|
+ for (CurrPtr = (UINT8 *) TableHeader; CurrPtr <= ((UINT8 *) TableHeader + TableHeader->Length) && UpdateCounter < 4; CurrPtr++) {
|
|
|
+ Signature = (UINT32 *) (CurrPtr + 1);
|
|
|
+ //
|
|
|
+ // patch DPTR (address of Acpi debug memory buffer)
|
|
|
+ //
|
|
|
+ if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('D', 'P', 'T', 'R')) {
|
|
|
+ NamePtr = (NAME_LAYOUT *) CurrPtr;
|
|
|
+ NamePtr->Value = (UINT32) (UINTN) AcpiDebugAddress;
|
|
|
+ UpdateCounter++;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // patch EPTR (end of Acpi debug memory buffer)
|
|
|
+ //
|
|
|
+ if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('E', 'P', 'T', 'R')) {
|
|
|
+ NamePtr = (NAME_LAYOUT *) CurrPtr;
|
|
|
+ NamePtr->Value = BufferEnd;
|
|
|
+ UpdateCounter++;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // patch CPTR (used as an index that starts after the Acpi Debug head)
|
|
|
+ //
|
|
|
+ if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('C', 'P', 'T', 'R')) {
|
|
|
+ NamePtr = (NAME_LAYOUT *) CurrPtr;
|
|
|
+ NamePtr->Value = BufferIndex;
|
|
|
+ UpdateCounter++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Add the table
|
|
|
+ //
|
|
|
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ goto Done;
|
|
|
+ }
|
|
|
+
|
|
|
+ TableKey = 0;
|
|
|
+ Status = AcpiTable->InstallAcpiTable (
|
|
|
+ AcpiTable,
|
|
|
+ TableHeader,
|
|
|
+ Size,
|
|
|
+ &TableKey
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ goto Done;
|
|
|
+ }
|
|
|
+
|
|
|
+Done:
|
|
|
+ gBS->FreePool (TableHeader);
|
|
|
+ return ;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Allocate Acpi Debug memory.
|
|
|
+
|
|
|
+ @param[out] BufferSize Pointer to Acpi debug memory buffer size.
|
|
|
+
|
|
|
+ @return Address of Acpi debug memory buffer. 0 if PcdAcpiDebugEnable is FALSE.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_PHYSICAL_ADDRESS
|
|
|
+AllocateAcpiDebugMemory (
|
|
|
+ OUT UINT32 *BufferSize
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_PHYSICAL_ADDRESS AcpiDebugAddress;
|
|
|
+ UINTN PagesNum;
|
|
|
+
|
|
|
+ AcpiDebugAddress = 0;
|
|
|
+ *BufferSize = 0;
|
|
|
+
|
|
|
+ if (PcdGetBool (PcdAcpiDebugEnable)) {
|
|
|
+ //
|
|
|
+ // Reserve memory to store Acpi Debug data.
|
|
|
+ //
|
|
|
+ AcpiDebugAddress = 0xFFFFFFFF;
|
|
|
+ PagesNum = EFI_SIZE_TO_PAGES (PcdGet32 (PcdAcpiDebugBufferSize));
|
|
|
+ Status = gBS->AllocatePages (
|
|
|
+ AllocateMaxAddress,
|
|
|
+ EfiReservedMemoryType,
|
|
|
+ PagesNum,
|
|
|
+ &AcpiDebugAddress
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "AcpiDebugAddress - 0x%08x\n", AcpiDebugAddress));
|
|
|
+
|
|
|
+ Status = PcdSet32S (PcdAcpiDebugAddress, (UINT32) AcpiDebugAddress);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
if (EFI_ERROR (Status)) {
|
|
|
+ gBS->FreePages (AcpiDebugAddress, PagesNum);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *BufferSize = PcdGet32 (PcdAcpiDebugBufferSize);
|
|
|
+ }
|
|
|
+
|
|
|
+ return AcpiDebugAddress;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Acpi Debug EndOfDxe notification.
|
|
|
+
|
|
|
+ @param[in] Event Event whose notification function is being invoked.
|
|
|
+ @param[in] Context Pointer to the notification function's context.
|
|
|
+
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EFIAPI
|
|
|
+AcpiDebugEndOfDxeNotification (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINT32 BufferSize;
|
|
|
+ UINT32 BufferIndex;
|
|
|
+
|
|
|
+ mAcpiDebug = (ACPI_DEBUG_HEAD *) (UINTN) AllocateAcpiDebugMemory (&BufferSize);
|
|
|
+ if (mAcpiDebug != NULL) {
|
|
|
+ //
|
|
|
+ // Init ACPI DEBUG buffer to lower case 'x'.
|
|
|
+ //
|
|
|
+ SetMem ((VOID *) mAcpiDebug, BufferSize, 0x78);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Clear header of AD_SIZE bytes.
|
|
|
+ //
|
|
|
+ ZeroMem ((VOID *) mAcpiDebug, AD_SIZE);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Write a signature to the first line of the buffer, "INTEL ACPI DEBUG".
|
|
|
+ //
|
|
|
+ CopyMem ((VOID *) mAcpiDebug, ACPI_DEBUG_STR, sizeof (ACPI_DEBUG_STR) - 1);
|
|
|
+
|
|
|
+ BufferIndex = (UINT32) (UINTN) mAcpiDebug;
|
|
|
+ mBufferEnd = BufferIndex + BufferSize;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Leave the Index after the Acpi Debug head.
|
|
|
+ //
|
|
|
+ BufferIndex += AD_SIZE;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Patch and Load the SSDT ACPI Tables.
|
|
|
+ //
|
|
|
+ PatchAndLoadAcpiTable (mAcpiDebug, BufferIndex, mBufferEnd);
|
|
|
+
|
|
|
+ mAcpiDebug->Head = BufferIndex;
|
|
|
+ mAcpiDebug->Tail = BufferIndex;
|
|
|
+ mAcpiDebug->BufferSize = BufferSize;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Close event, so it will not be invoked again.
|
|
|
+ //
|
|
|
+ gBS->CloseEvent (Event);
|
|
|
+
|
|
|
+ return ;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Initialize ACPI Debug.
|
|
|
+
|
|
|
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
|
|
+ @param[in] SystemTable A pointer to the EFI System Table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The driver initializes correctly.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+InitializeAcpiDebugDxe (
|
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_EVENT EndOfDxeEvent;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Register EndOfDxe notification
|
|
|
+ // that point could ensure the Acpi Debug related PCDs initialized.
|
|
|
+ //
|
|
|
+ Status = gBS->CreateEventEx (
|
|
|
+ EVT_NOTIFY_SIGNAL,
|
|
|
+ TPL_CALLBACK,
|
|
|
+ AcpiDebugEndOfDxeNotification,
|
|
|
+ NULL,
|
|
|
+ &gEfiEndOfDxeEventGroupGuid,
|
|
|
+ &EndOfDxeEvent
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Software SMI callback for ACPI Debug which is called from ACPI method.
|
|
|
+
|
|
|
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
|
|
+ @param[in] Context Points to an optional handler context which was specified when the
|
|
|
+ handler was registered.
|
|
|
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
|
|
|
+ be conveyed from a non-SMM environment into an SMM environment.
|
|
|
+ @param[in, out] CommBufferSize The size of the CommBuffer.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The interrupt was handled successfully.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+AcpiDebugSmmCallback (
|
|
|
+ IN EFI_HANDLE DispatchHandle,
|
|
|
+ IN CONST VOID *Context,
|
|
|
+ IN OUT VOID *CommBuffer,
|
|
|
+ IN OUT UINTN *CommBufferSize
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINT8 Buffer[MAX_BUFFER_SIZE];
|
|
|
+
|
|
|
+ //
|
|
|
+ // Validate the fields in mAcpiDebug to ensure there is no harm to SMI handler.
|
|
|
+ // mAcpiDebug is below 4GB and the start address of whole buffer.
|
|
|
+ //
|
|
|
+ if ((mAcpiDebug->BufferSize != (mBufferEnd - (UINT32) (UINTN) mAcpiDebug)) ||
|
|
|
+ (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + AD_SIZE)) ||
|
|
|
+ (mAcpiDebug->Head > mBufferEnd) ||
|
|
|
+ (mAcpiDebug->Tail < (UINT32) ((UINTN) mAcpiDebug + AD_SIZE)) ||
|
|
|
+ (mAcpiDebug->Tail > mBufferEnd)) {
|
|
|
+ //
|
|
|
+ // If some fields in mAcpiDebug are invaid, return directly.
|
|
|
+ //
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(BOOLEAN)mAcpiDebug->Wrap && ((mAcpiDebug->Head >= (UINT32) ((UINTN) mAcpiDebug + AD_SIZE))
|
|
|
+ && (mAcpiDebug->Head < mAcpiDebug->Tail))){
|
|
|
+ //
|
|
|
+ // If curent ----- buffer + 020
|
|
|
+ // ...
|
|
|
+ // ... Head
|
|
|
+ // ... Data for SMM print
|
|
|
+ // ... Tail
|
|
|
+ // ... Vacant for ASL input
|
|
|
+ // ----- buffer end
|
|
|
+ //
|
|
|
+ // skip NULL block
|
|
|
+ //
|
|
|
+ while ((*(CHAR8 *) (UINTN) mAcpiDebug->Head == '\0') && (mAcpiDebug->Head < mAcpiDebug->Tail)) {
|
|
|
+ mAcpiDebug->Head ++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mAcpiDebug->Head < mAcpiDebug->Tail) {
|
|
|
+ ZeroMem (Buffer, MAX_BUFFER_SIZE);
|
|
|
+ AsciiStrnCpyS ((CHAR8 *) Buffer, MAX_BUFFER_SIZE, (CHAR8 *) (UINTN) mAcpiDebug->Head, MAX_BUFFER_SIZE - 1);
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO | DEBUG_ERROR, "%a%a\n", Buffer, (BOOLEAN) mAcpiDebug->Truncate ? "..." : ""));
|
|
|
+ mAcpiDebug->Head += MAX_BUFFER_SIZE;
|
|
|
+
|
|
|
+ if (mAcpiDebug->Head >= (mAcpiDebug->Tail)) {
|
|
|
+ //
|
|
|
+ // When head == tail, we do nothing in handler.
|
|
|
+ //
|
|
|
+ mAcpiDebug->Head = mAcpiDebug->Tail;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if ((BOOLEAN) mAcpiDebug->Wrap && ((mAcpiDebug->Head > mAcpiDebug->Tail)
|
|
|
+ && (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)))){
|
|
|
+ //
|
|
|
+ // If curent ----- buffer + 020
|
|
|
+ // ... Tail
|
|
|
+ // ... Vacant for ASL input
|
|
|
+ // ... Head
|
|
|
+ // ... Data for SMM print
|
|
|
+ // ----- buffer end
|
|
|
+ //
|
|
|
+ while ((*(CHAR8 *) (UINTN) mAcpiDebug->Head == '\0') && (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize))) {
|
|
|
+ mAcpiDebug->Head ++;
|
|
|
+ }
|
|
|
+ if (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)){
|
|
|
+ ZeroMem (Buffer, MAX_BUFFER_SIZE);
|
|
|
+ AsciiStrnCpyS ((CHAR8 *) Buffer, MAX_BUFFER_SIZE, (CHAR8 *) (UINTN) mAcpiDebug->Head, MAX_BUFFER_SIZE - 1);
|
|
|
+ DEBUG ((DEBUG_INFO | DEBUG_ERROR, "%a%a\n", Buffer, (BOOLEAN) mAcpiDebug->Truncate ? "..." : ""));
|
|
|
+ mAcpiDebug->Head += MAX_BUFFER_SIZE;
|
|
|
+
|
|
|
+ if (mAcpiDebug->Head >= (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)) {
|
|
|
+ //
|
|
|
+ // We met end of buffer.
|
|
|
+ //
|
|
|
+ mAcpiDebug->Wrap = 0;
|
|
|
+ mAcpiDebug->Head = (UINT32) ((UINTN) mAcpiDebug + AD_SIZE);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Acpi Debug SmmEndOfDxe notification.
|
|
|
+
|
|
|
+ @param[in] Protocol Points to the protocol's unique identifier.
|
|
|
+ @param[in] Interface Points to the interface instance.
|
|
|
+ @param[in] Handle The handle on which the interface was installed.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Notification runs successfully.
|
|
|
+
|
|
|
+ **/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+AcpiDebugSmmEndOfDxeNotification (
|
|
|
+ IN CONST EFI_GUID *Protocol,
|
|
|
+ IN VOID *Interface,
|
|
|
+ IN EFI_HANDLE Handle
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
|
|
|
+ EFI_SMM_SW_REGISTER_CONTEXT SwContext;
|
|
|
+ EFI_HANDLE SwHandle;
|
|
|
+
|
|
|
+ AcpiDebugEndOfDxeNotification (NULL, NULL);
|
|
|
+
|
|
|
+ if (mAcpiDebug != NULL) {
|
|
|
+ //
|
|
|
+ // Get the Sw dispatch protocol and register SMI callback function.
|
|
|
+ //
|
|
|
+ SwDispatch = NULL;
|
|
|
+ Status = mSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **) &SwDispatch);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ SwContext.SwSmiInputValue = (UINTN) -1;
|
|
|
+ Status = SwDispatch->Register (SwDispatch, AcpiDebugSmmCallback, &SwContext, &SwHandle);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ mAcpiDebug->SmiTrigger = (UINT8) SwContext.SwSmiInputValue;
|
|
|
+ mAcpiDebug->SmmVersion = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Initialize ACPI Debug.
|
|
|
+
|
|
|
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
|
|
+ @param[in] SystemTable A pointer to the EFI System Table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The driver initializes correctly.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+InitializeAcpiDebugSmm (
|
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ VOID *Registration;
|
|
|
+ EFI_SMM_BASE2_PROTOCOL *SmmBase2;
|
|
|
+ BOOLEAN InSmm;
|
|
|
+
|
|
|
+ Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **) &SmmBase2);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = SmmBase2->InSmm (SmmBase2, &InSmm);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ ASSERT (InSmm);
|
|
|
+ if (!InSmm) {
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = SmmBase2->GetSmstLocation (SmmBase2, &mSmst);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Register SmmEndOfDxe notification
|
|
|
+ // that point could ensure the Acpi Debug related PCDs initialized.
|
|
|
+ //
|
|
|
+ Registration = NULL;
|
|
|
+ Status = mSmst->SmmRegisterProtocolNotify (
|
|
|
+ &gEfiSmmEndOfDxeProtocolGuid,
|
|
|
+ AcpiDebugSmmEndOfDxeNotification,
|
|
|
+ &Registration
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|