Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15695 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1117 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1117 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  ACPI Sdt Protocol Driver
 | 
						|
 | 
						|
  Copyright (c) 2010 - 2014, 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
 | 
						|
  which 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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
//
 | 
						|
// Includes
 | 
						|
//
 | 
						|
#include "AcpiTable.h"
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED
 | 
						|
EFI_ACPI_SDT_PROTOCOL  mAcpiSdtProtocolTemplate = {
 | 
						|
  EFI_ACPI_TABLE_VERSION_NONE | EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 | EFI_ACPI_TABLE_VERSION_4_0,
 | 
						|
  GetAcpiTable2,
 | 
						|
  RegisterNotify,
 | 
						|
  Open,
 | 
						|
  OpenSdt,
 | 
						|
  Close,
 | 
						|
  GetChild,
 | 
						|
  GetOption,
 | 
						|
  SetOption,
 | 
						|
  FindPath
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  This function returns ACPI Table instance.
 | 
						|
 | 
						|
  @return AcpiTableInstance
 | 
						|
**/
 | 
						|
EFI_ACPI_TABLE_INSTANCE *
 | 
						|
SdtGetAcpiTableInstance (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mPrivateData;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function finds the table specified by the buffer.
 | 
						|
 | 
						|
  @param[in]  Buffer      Table buffer to find.
 | 
						|
 | 
						|
  @return ACPI table list.
 | 
						|
**/
 | 
						|
EFI_ACPI_TABLE_LIST *
 | 
						|
FindTableByBuffer (
 | 
						|
  IN VOID  *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
 | 
						|
  LIST_ENTRY                *CurrentLink;
 | 
						|
  EFI_ACPI_TABLE_LIST       *CurrentTableList;
 | 
						|
  LIST_ENTRY                *StartLink;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the instance of the ACPI Table
 | 
						|
  //
 | 
						|
  AcpiTableInstance = SdtGetAcpiTableInstance ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the notify
 | 
						|
  //
 | 
						|
  StartLink   = &AcpiTableInstance->TableList;
 | 
						|
  CurrentLink = StartLink->ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink != StartLink) {
 | 
						|
    CurrentTableList = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
 | 
						|
    if (((UINTN)CurrentTableList->PageAddress <= (UINTN)Buffer) &&
 | 
						|
        ((UINTN)CurrentTableList->PageAddress + EFI_PAGES_TO_SIZE(CurrentTableList->NumberOfPages) > (UINTN)Buffer)) {
 | 
						|
      //
 | 
						|
      // Good! Found Table.
 | 
						|
      //
 | 
						|
      return CurrentTableList;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function updates AML table checksum.
 | 
						|
  It will search the ACPI table installed by ACPI_TABLE protocol.
 | 
						|
 | 
						|
  @param[in]  Buffer        A piece of AML code buffer pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The table holds the AML buffer is found, and checksum is updated.
 | 
						|
  @retval EFI_NOT_FOUND     The table holds the AML buffer is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtUpdateAmlChecksum (
 | 
						|
  IN VOID  *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_LIST       *CurrentTableList;
 | 
						|
 | 
						|
  CurrentTableList = FindTableByBuffer (Buffer);
 | 
						|
  if (CurrentTableList == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  AcpiPlatformChecksum (
 | 
						|
    (VOID *)CurrentTableList->Table,
 | 
						|
    CurrentTableList->Table->Length,
 | 
						|
    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum)
 | 
						|
    );
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function finds MAX AML buffer size.
 | 
						|
  It will search the ACPI table installed by ACPI_TABLE protocol.
 | 
						|
 | 
						|
  @param[in]  Buffer        A piece of AML code buffer pointer.
 | 
						|
  @param[out] MaxSize       On return it holds the MAX size of buffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The table holds the AML buffer is found, and MAX size if returned.
 | 
						|
  @retval EFI_NOT_FOUND     The table holds the AML buffer is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtGetMaxAmlBufferSize (
 | 
						|
  IN  VOID  *Buffer,
 | 
						|
  OUT UINTN *MaxSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_LIST       *CurrentTableList;
 | 
						|
 | 
						|
  CurrentTableList = FindTableByBuffer (Buffer);
 | 
						|
  if (CurrentTableList == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *MaxSize = (UINTN)CurrentTableList->Table + CurrentTableList->Table->Length - (UINTN)Buffer;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function invokes ACPI notification.
 | 
						|
 | 
						|
  @param[in]  AcpiTableInstance          Instance to AcpiTable
 | 
						|
  @param[in]  Version                    Version(s) to set.
 | 
						|
  @param[in]  Handle                     Handle of the table.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SdtNotifyAcpiList (
 | 
						|
  IN EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance,
 | 
						|
  IN EFI_ACPI_TABLE_VERSION    Version,
 | 
						|
  IN UINTN                     Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_NOTIFY_LIST      *CurrentNotifyList;
 | 
						|
  LIST_ENTRY                *CurrentLink;
 | 
						|
  LIST_ENTRY                *StartLink;
 | 
						|
  EFI_ACPI_TABLE_LIST       *Table;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // We should not use Table buffer, because it is user input buffer.
 | 
						|
  //
 | 
						|
  Status = FindTableByHandle (
 | 
						|
             Handle,
 | 
						|
             &AcpiTableInstance->TableList,
 | 
						|
             &Table
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the notify
 | 
						|
  //
 | 
						|
  StartLink   = &AcpiTableInstance->NotifyList;
 | 
						|
  CurrentLink = StartLink->ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink != StartLink) {
 | 
						|
    CurrentNotifyList = EFI_ACPI_NOTIFY_LIST_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    //
 | 
						|
    // Inovke notification
 | 
						|
    //
 | 
						|
    CurrentNotifyList->Notification ((EFI_ACPI_SDT_HEADER *)Table->Table, Version, Handle);
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns a requested ACPI table.
 | 
						|
  
 | 
						|
  The GetAcpiTable() function returns a pointer to a buffer containing the ACPI table associated
 | 
						|
  with the Index that was input. The following structures are not considered elements in the list of
 | 
						|
  ACPI tables:
 | 
						|
  - Root System Description Pointer (RSD_PTR)
 | 
						|
  - Root System Description Table (RSDT)
 | 
						|
  - Extended System Description Table (XSDT)
 | 
						|
  Version is updated with a bit map containing all the versions of ACPI of which the table is a
 | 
						|
  member.
 | 
						|
  
 | 
						|
  @param[in]    Index       The zero-based index of the table to retrieve.
 | 
						|
  @param[out]   Table       Pointer for returning the table buffer.
 | 
						|
  @param[out]   Version     On return, updated with the ACPI versions to which this table belongs. Type
 | 
						|
                            EFI_ACPI_TABLE_VERSION is defined in "Related Definitions" in the
 | 
						|
                            EFI_ACPI_SDT_PROTOCOL.    
 | 
						|
  @param[out]   TableKey    On return, points to the table key for the specified ACPI system definition table. This
 | 
						|
                            is identical to the table key used in the EFI_ACPI_TABLE_PROTOCOL.  
 | 
						|
                            
 | 
						|
  @retval EFI_SUCCESS       The function completed successfully.
 | 
						|
  @retval EFI_NOT_FOUND     The requested index is too large and a table was not found.                                  
 | 
						|
**/  
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetAcpiTable2 (
 | 
						|
  IN  UINTN                               Index,
 | 
						|
  OUT EFI_ACPI_SDT_HEADER                 **Table,
 | 
						|
  OUT EFI_ACPI_TABLE_VERSION              *Version,
 | 
						|
  OUT UINTN                               *TableKey
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
 | 
						|
  UINTN                     TableIndex;
 | 
						|
  LIST_ENTRY                *CurrentLink;
 | 
						|
  LIST_ENTRY                *StartLink;
 | 
						|
  EFI_ACPI_TABLE_LIST       *CurrentTable;
 | 
						|
 | 
						|
  ASSERT (Table != NULL);
 | 
						|
  ASSERT (Version != NULL);
 | 
						|
  ASSERT (TableKey != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the instance of the ACPI Table
 | 
						|
  //
 | 
						|
  AcpiTableInstance = SdtGetAcpiTableInstance ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the table
 | 
						|
  //
 | 
						|
  StartLink   = &AcpiTableInstance->TableList;
 | 
						|
  CurrentLink = StartLink->ForwardLink;
 | 
						|
  TableIndex = 0;
 | 
						|
 | 
						|
  while (CurrentLink != StartLink) {
 | 
						|
    if (TableIndex == Index) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Next one
 | 
						|
    //
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
    TableIndex ++;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((TableIndex != Index) || (CurrentLink == StartLink)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get handle and version
 | 
						|
  //
 | 
						|
  CurrentTable  = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
 | 
						|
  *TableKey     = CurrentTable->Handle;
 | 
						|
  *Version      = CurrentTable->Version;
 | 
						|
  *Table        = (EFI_ACPI_SDT_HEADER *)CurrentTable->Table;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register a callback when an ACPI table is installed.
 | 
						|
  
 | 
						|
  This function registers a function which will be called whenever a new ACPI table is installed.
 | 
						|
  
 | 
						|
  @param[in]  Notification               Points to the callback function to be registered
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SdtRegisterNotify (
 | 
						|
  IN EFI_ACPI_NOTIFICATION_FN   Notification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
 | 
						|
  EFI_ACPI_NOTIFY_LIST      *CurrentNotifyList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the instance of the ACPI Table
 | 
						|
  //
 | 
						|
  AcpiTableInstance = SdtGetAcpiTableInstance ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a new list entry
 | 
						|
  //
 | 
						|
  CurrentNotifyList = AllocatePool (sizeof (EFI_ACPI_NOTIFY_LIST));
 | 
						|
  ASSERT (CurrentNotifyList != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the table contents
 | 
						|
  //
 | 
						|
  CurrentNotifyList->Signature    = EFI_ACPI_NOTIFY_LIST_SIGNATURE;
 | 
						|
  CurrentNotifyList->Notification = Notification;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add the table to the current list of tables
 | 
						|
  //
 | 
						|
  InsertTailList (&AcpiTableInstance->NotifyList, &CurrentNotifyList->Link);
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Unregister a callback when an ACPI table is installed.
 | 
						|
  
 | 
						|
  This function unregisters a function which will be called whenever a new ACPI table is installed.
 | 
						|
  
 | 
						|
  @param[in]  Notification               Points to the callback function to be unregistered.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS           Callback successfully unregistered.
 | 
						|
  @retval EFI_INVALID_PARAMETER Notification does not match a known registration function.                        
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtUnregisterNotify (
 | 
						|
  IN EFI_ACPI_NOTIFICATION_FN   Notification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
 | 
						|
  EFI_ACPI_NOTIFY_LIST      *CurrentNotifyList;
 | 
						|
  LIST_ENTRY                *CurrentLink;
 | 
						|
  LIST_ENTRY                *StartLink;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the instance of the ACPI Table
 | 
						|
  //
 | 
						|
  AcpiTableInstance = SdtGetAcpiTableInstance ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the notify
 | 
						|
  //
 | 
						|
  StartLink   = &AcpiTableInstance->NotifyList;
 | 
						|
  CurrentLink = StartLink->ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink != StartLink) {
 | 
						|
    CurrentNotifyList = EFI_ACPI_NOTIFY_LIST_FROM_LINK (CurrentLink);
 | 
						|
    if (CurrentNotifyList->Notification == Notification) {
 | 
						|
      //
 | 
						|
      // Good! Found notification.
 | 
						|
      //
 | 
						|
      // Remove it from list and free the node.
 | 
						|
      //
 | 
						|
      RemoveEntryList (&(CurrentNotifyList->Link));
 | 
						|
      FreePool (CurrentNotifyList);
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Not found!
 | 
						|
  //
 | 
						|
  return EFI_INVALID_PARAMETER;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register or unregister a callback when an ACPI table is installed.
 | 
						|
  
 | 
						|
  This function registers or unregisters a function which will be called whenever a new ACPI table is
 | 
						|
  installed.
 | 
						|
  
 | 
						|
  @param[in]    Register        If TRUE, then the specified function will be registered. If FALSE, then the specified
 | 
						|
                                function will be unregistered.
 | 
						|
  @param[in]    Notification    Points to the callback function to be registered or unregistered.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS           Callback successfully registered or unregistered.
 | 
						|
  @retval EFI_INVALID_PARAMETER Notification is NULL
 | 
						|
  @retval EFI_INVALID_PARAMETER Register is FALSE and Notification does not match a known registration function.                        
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
RegisterNotify (
 | 
						|
  IN BOOLEAN                    Register,
 | 
						|
  IN EFI_ACPI_NOTIFICATION_FN   Notification
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (Notification == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Register) {
 | 
						|
    //
 | 
						|
    // Register a new notify
 | 
						|
    //
 | 
						|
    SdtRegisterNotify (Notification);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Unregister an old notify
 | 
						|
    //
 | 
						|
    return SdtUnregisterNotify (Notification);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a handle for the first ACPI opcode in an ACPI system description table.
 | 
						|
  
 | 
						|
  @param[in]    TableKey    The table key for the ACPI table, as returned by GetTable().
 | 
						|
  @param[out]   Handle      On return, points to the newly created ACPI handle.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       Handle created successfully.
 | 
						|
  @retval EFI_NOT_FOUND     TableKey does not refer to a valid ACPI table.  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtOpenSdtTable (
 | 
						|
  IN    UINTN           TableKey,
 | 
						|
  OUT   EFI_ACPI_HANDLE *Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_ACPI_TABLE_LIST       *Table;
 | 
						|
  EFI_AML_HANDLE            *AmlHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the instance of the ACPI Table
 | 
						|
  //
 | 
						|
  AcpiTableInstance = SdtGetAcpiTableInstance ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the table
 | 
						|
  //
 | 
						|
  Status = FindTableByHandle (
 | 
						|
             TableKey,
 | 
						|
             &AcpiTableInstance->TableList,
 | 
						|
             &Table
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle = AllocatePool (sizeof(*AmlHandle));
 | 
						|
  ASSERT (AmlHandle != NULL);
 | 
						|
  AmlHandle->Signature       = EFI_AML_ROOT_HANDLE_SIGNATURE;
 | 
						|
  AmlHandle->Buffer          = (VOID *)((UINTN)Table->Table + sizeof(EFI_ACPI_SDT_HEADER));
 | 
						|
  AmlHandle->Size            = Table->Table->Length - sizeof(EFI_ACPI_SDT_HEADER);
 | 
						|
  AmlHandle->AmlByteEncoding = NULL;
 | 
						|
  AmlHandle->Modified        = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // return the ACPI handle
 | 
						|
  //
 | 
						|
  *Handle = (EFI_ACPI_HANDLE)AmlHandle;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a handle for the first ACPI opcode in an ACPI system description table.
 | 
						|
  
 | 
						|
  @param[in]    TableKey    The table key for the ACPI table, as returned by GetTable().
 | 
						|
  @param[out]   Handle      On return, points to the newly created ACPI handle.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       Handle created successfully.
 | 
						|
  @retval EFI_NOT_FOUND     TableKey does not refer to a valid ACPI table.  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
OpenSdt (
 | 
						|
  IN    UINTN           TableKey,
 | 
						|
  OUT   EFI_ACPI_HANDLE *Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return SdtOpenSdtTable (TableKey, Handle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a handle from an ACPI opcode
 | 
						|
  
 | 
						|
  @param[in]  Buffer                 Points to the ACPI opcode.
 | 
						|
  @param[in]  BufferSize             Max buffer size.
 | 
						|
  @param[out] Handle                 Upon return, holds the handle.
 | 
						|
  
 | 
						|
  @retval   EFI_SUCCESS             Success
 | 
						|
  @retval   EFI_INVALID_PARAMETER   Buffer is NULL or Handle is NULL or Buffer points to an
 | 
						|
                                    invalid opcode.
 | 
						|
  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtOpenEx (
 | 
						|
  IN    VOID            *Buffer,
 | 
						|
  IN    UINTN           BufferSize,
 | 
						|
  OUT   EFI_ACPI_HANDLE *Handle 
 | 
						|
  )
 | 
						|
{
 | 
						|
  AML_BYTE_ENCODING   *AmlByteEncoding;
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
 | 
						|
  AmlByteEncoding = AmlSearchByOpByte (Buffer);
 | 
						|
  if (AmlByteEncoding == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do not open NameString as handle
 | 
						|
  //
 | 
						|
  if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Good, find it
 | 
						|
  //
 | 
						|
  AmlHandle = AllocatePool (sizeof(*AmlHandle));
 | 
						|
  ASSERT (AmlHandle != NULL);
 | 
						|
  
 | 
						|
  AmlHandle->Signature       = EFI_AML_HANDLE_SIGNATURE;
 | 
						|
  AmlHandle->Buffer          = Buffer;
 | 
						|
  AmlHandle->AmlByteEncoding = AmlByteEncoding;
 | 
						|
  AmlHandle->Modified        = FALSE;
 | 
						|
 | 
						|
  AmlHandle->Size = AmlGetObjectSize (AmlByteEncoding, Buffer, BufferSize);
 | 
						|
  if (AmlHandle->Size == 0) {
 | 
						|
    FreePool (AmlHandle);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Handle = (EFI_ACPI_HANDLE)AmlHandle;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a handle from an ACPI opcode
 | 
						|
  
 | 
						|
  @param[in]  Buffer                 Points to the ACPI opcode.
 | 
						|
  @param[out] Handle                 Upon return, holds the handle.
 | 
						|
  
 | 
						|
  @retval   EFI_SUCCESS             Success
 | 
						|
  @retval   EFI_INVALID_PARAMETER   Buffer is NULL or Handle is NULL or Buffer points to an
 | 
						|
                                    invalid opcode.
 | 
						|
  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Open (
 | 
						|
  IN    VOID            *Buffer,
 | 
						|
  OUT   EFI_ACPI_HANDLE *Handle 
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  UINTN               MaxSize;
 | 
						|
 | 
						|
  MaxSize = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (Buffer == NULL || Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = SdtGetMaxAmlBufferSize (Buffer, &MaxSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return SdtOpenEx (Buffer, MaxSize, Handle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Close an ACPI handle.
 | 
						|
  
 | 
						|
  @param[in] Handle Returns the handle.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS           Success
 | 
						|
  @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object.  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Close (
 | 
						|
  IN EFI_ACPI_HANDLE Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)Handle;
 | 
						|
  if ((AmlHandle->Signature != EFI_AML_ROOT_HANDLE_SIGNATURE) &&
 | 
						|
      (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update Checksum only if modified
 | 
						|
  //
 | 
						|
  if (AmlHandle->Modified) {
 | 
						|
    Status = SdtUpdateAmlChecksum (AmlHandle->Buffer);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (AmlHandle);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve information about an ACPI object.
 | 
						|
  
 | 
						|
  @param[in]    Handle      ACPI object handle.
 | 
						|
  @param[in]    Index       Index of the data to retrieve from the object. In general, indexes read from left-to-right
 | 
						|
                            in the ACPI encoding, with index 0 always being the ACPI opcode.
 | 
						|
  @param[out]   DataType    Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists
 | 
						|
                            for the specified index.
 | 
						|
  @param[out]   Data        Upon return, points to the pointer to the data.
 | 
						|
  @param[out]   DataSize    Upon return, points to the size of Data.
 | 
						|
  
 | 
						|
  @retval       EFI_SUCCESS           Success.
 | 
						|
  @retval       EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetOption (
 | 
						|
  IN        EFI_ACPI_HANDLE     Handle,
 | 
						|
  IN        UINTN               Index,
 | 
						|
  OUT       EFI_ACPI_DATA_TYPE  *DataType,
 | 
						|
  OUT CONST VOID                **Data,
 | 
						|
  OUT       UINTN               *DataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  AML_BYTE_ENCODING   *AmlByteEncoding;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
 | 
						|
  ASSERT (DataType != NULL);
 | 
						|
  ASSERT (Data != NULL);
 | 
						|
  ASSERT (DataSize != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)Handle;
 | 
						|
  //
 | 
						|
  // Do not check EFI_AML_ROOT_HANDLE_SIGNATURE because there is no option for Root handle
 | 
						|
  //
 | 
						|
  if (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlByteEncoding = AmlHandle->AmlByteEncoding;
 | 
						|
  if (Index > AmlByteEncoding->MaxIndex) {
 | 
						|
    *DataType = EFI_ACPI_DATA_TYPE_NONE;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse option
 | 
						|
  //
 | 
						|
  Status = AmlParseOptionHandleCommon (AmlHandle, (AML_OP_PARSE_INDEX)Index, DataType, (VOID **)Data, DataSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Change information about an ACPI object.
 | 
						|
  
 | 
						|
  @param[in]  Handle    ACPI object handle.
 | 
						|
  @param[in]  Index     Index of the data to retrieve from the object. In general, indexes read from left-to-right
 | 
						|
                        in the ACPI encoding, with index 0 always being the ACPI opcode.
 | 
						|
  @param[in]  Data      Points to the data.
 | 
						|
  @param[in]  DataSize  The size of the Data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Success
 | 
						|
  @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object.
 | 
						|
  @retval EFI_BAD_BUFFER_SIZE   Data cannot be accommodated in the space occupied by
 | 
						|
                                the option.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetOption (
 | 
						|
  IN        EFI_ACPI_HANDLE Handle,
 | 
						|
  IN        UINTN           Index,
 | 
						|
  IN CONST  VOID            *Data,
 | 
						|
  IN        UINTN           DataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  AML_BYTE_ENCODING   *AmlByteEncoding;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  EFI_ACPI_DATA_TYPE  DataType;
 | 
						|
  VOID                *OrgData;
 | 
						|
  UINTN               OrgDataSize;
 | 
						|
 | 
						|
  ASSERT (Data != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)Handle;
 | 
						|
  //
 | 
						|
  // Do not check EFI_AML_ROOT_HANDLE_SIGNATURE because there is no option for Root handle
 | 
						|
  //
 | 
						|
  if (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  AmlByteEncoding = AmlHandle->AmlByteEncoding;
 | 
						|
 | 
						|
  if (Index > AmlByteEncoding->MaxIndex) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse option
 | 
						|
  //
 | 
						|
  Status = AmlParseOptionHandleCommon (AmlHandle, (AML_OP_PARSE_INDEX)Index, &DataType, &OrgData, &OrgDataSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  if (DataType == EFI_ACPI_DATA_TYPE_NONE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DataSize > OrgDataSize) {
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update
 | 
						|
  //
 | 
						|
  CopyMem (OrgData, Data, DataSize);
 | 
						|
  AmlHandle->Modified = TRUE;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the child ACPI objects.
 | 
						|
  
 | 
						|
  @param[in]        ParentHandle    Parent handle.
 | 
						|
  @param[in, out]   Handle          On entry, points to the previously returned handle or NULL to start with the first
 | 
						|
                                    handle. On return, points to the next returned ACPI handle or NULL if there are no
 | 
						|
                                    child objects.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Success
 | 
						|
  @retval EFI_INVALID_PARAMETER     ParentHandle is NULL or does not refer to a valid ACPI object.                                
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetChild (
 | 
						|
  IN EFI_ACPI_HANDLE        ParentHandle,
 | 
						|
  IN OUT EFI_ACPI_HANDLE    *Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlParentHandle;
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  VOID                *Buffer;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
 | 
						|
  ASSERT (Handle != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (ParentHandle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle       = *Handle;
 | 
						|
  if ((AmlHandle != NULL) && (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlParentHandle = (EFI_AML_HANDLE *)ParentHandle;
 | 
						|
  if (AmlParentHandle->Signature == EFI_AML_ROOT_HANDLE_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // Root handle
 | 
						|
    //
 | 
						|
    Status = AmlGetChildFromRoot (AmlParentHandle, AmlHandle, &Buffer);
 | 
						|
  } else if (AmlParentHandle->Signature == EFI_AML_HANDLE_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // Non-root handle
 | 
						|
    //
 | 
						|
    Status = AmlGetChildFromNonRoot (AmlParentHandle, AmlHandle, &Buffer);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Invalid
 | 
						|
    //
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    *Handle = NULL;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  return SdtOpenEx (Buffer, (UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size - (UINTN)Buffer, Handle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the handle of the ACPI object representing the specified ACPI path
 | 
						|
  
 | 
						|
  @param[in]    HandleIn    Points to the handle of the object representing the starting point for the path search.
 | 
						|
  @param[in]    AmlPath     Points to the AML path.
 | 
						|
  @param[out]   HandleOut   On return, points to the ACPI object which represents AcpiPath, relative to
 | 
						|
                            HandleIn.
 | 
						|
                            
 | 
						|
  @retval EFI_SUCCESS           Success
 | 
						|
  @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object.                            
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtFindPathFromNonRoot (
 | 
						|
  IN    EFI_ACPI_HANDLE HandleIn,
 | 
						|
  IN    UINT8           *AmlPath,
 | 
						|
  OUT   EFI_ACPI_HANDLE *HandleOut
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  VOID                *Buffer;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
 | 
						|
  Buffer = NULL;
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)HandleIn;
 | 
						|
 | 
						|
  //
 | 
						|
  // For non-root handle, we need search from THIS node instead of ROOT.
 | 
						|
  //
 | 
						|
  Status = AmlFindPath (AmlHandle, AmlPath, &Buffer, FALSE);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    *HandleOut = NULL;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  return SdtOpenEx (Buffer, (UINTN)AmlHandle->Buffer + AmlHandle->Size - (UINTN)Buffer, HandleOut);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Duplicate AML handle.
 | 
						|
  
 | 
						|
  @param[in]    AmlHandle   Handle to be duplicated.
 | 
						|
                            
 | 
						|
  @return Duplicated AML handle.
 | 
						|
**/
 | 
						|
EFI_AML_HANDLE *
 | 
						|
SdtDuplicateHandle (
 | 
						|
  IN EFI_AML_HANDLE      *AmlHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE  *DstAmlHandle;
 | 
						|
 | 
						|
  DstAmlHandle = AllocatePool (sizeof(*DstAmlHandle));
 | 
						|
  ASSERT (DstAmlHandle != NULL);
 | 
						|
  CopyMem (DstAmlHandle, (VOID *)AmlHandle, sizeof(*DstAmlHandle));
 | 
						|
 | 
						|
  return DstAmlHandle;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the handle of the ACPI object representing the specified ACPI path
 | 
						|
  
 | 
						|
  @param[in]    HandleIn    Points to the handle of the object representing the starting point for the path search.
 | 
						|
  @param[in]    AmlPath     Points to the AML path.
 | 
						|
  @param[out]   HandleOut   On return, points to the ACPI object which represents AcpiPath, relative to
 | 
						|
                            HandleIn.
 | 
						|
                            
 | 
						|
  @retval EFI_SUCCESS           Success
 | 
						|
  @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object.                            
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SdtFindPathFromRoot (
 | 
						|
  IN    EFI_ACPI_HANDLE HandleIn,
 | 
						|
  IN    UINT8           *AmlPath,
 | 
						|
  OUT   EFI_ACPI_HANDLE *HandleOut
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_HANDLE     ChildHandle;
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  VOID                *Buffer;
 | 
						|
 | 
						|
  Buffer = NULL;
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)HandleIn;
 | 
						|
 | 
						|
  //
 | 
						|
  // Handle case that AcpiPath is Root
 | 
						|
  //
 | 
						|
  if (AmlIsRootPath (AmlPath)) {
 | 
						|
    //
 | 
						|
    // Duplicate RootHandle
 | 
						|
    //
 | 
						|
    *HandleOut = (EFI_ACPI_HANDLE)SdtDuplicateHandle (AmlHandle);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Let children find it.
 | 
						|
  //
 | 
						|
  ChildHandle = NULL;
 | 
						|
  while (TRUE) {
 | 
						|
    Status = GetChild (HandleIn, &ChildHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ChildHandle == NULL) {
 | 
						|
      //
 | 
						|
      // Not found
 | 
						|
      //
 | 
						|
      *HandleOut = NULL;
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // More child
 | 
						|
    //
 | 
						|
    AmlHandle = (EFI_AML_HANDLE *)ChildHandle;
 | 
						|
    Status = AmlFindPath (AmlHandle, AmlPath, &Buffer, TRUE);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Buffer != NULL) {
 | 
						|
      //
 | 
						|
      // Great! Find it, open
 | 
						|
      //
 | 
						|
      Status = SdtOpenEx (Buffer, (UINTN)AmlHandle->Buffer + AmlHandle->Size - (UINTN)Buffer, HandleOut);
 | 
						|
      if (!EFI_ERROR (Status))  {
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Not success, try next one
 | 
						|
      //
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Should not run here
 | 
						|
  //
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the handle of the ACPI object representing the specified ACPI path
 | 
						|
  
 | 
						|
  @param[in]    HandleIn    Points to the handle of the object representing the starting point for the path search.
 | 
						|
  @param[in]    AcpiPath    Points to the ACPI path, which conforms to the ACPI encoded path format.
 | 
						|
  @param[out]   HandleOut   On return, points to the ACPI object which represents AcpiPath, relative to
 | 
						|
                            HandleIn.
 | 
						|
                            
 | 
						|
  @retval EFI_SUCCESS           Success
 | 
						|
  @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object.                            
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FindPath (
 | 
						|
  IN    EFI_ACPI_HANDLE HandleIn,
 | 
						|
  IN    VOID            *AcpiPath,
 | 
						|
  OUT   EFI_ACPI_HANDLE *HandleOut
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_AML_HANDLE      *AmlHandle;
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  UINT8               *AmlPath;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid input parameters
 | 
						|
  //
 | 
						|
  if (HandleIn == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AmlHandle = (EFI_AML_HANDLE *)HandleIn;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Convert ASL path to AML path
 | 
						|
  //
 | 
						|
  AmlPath = AmlNameFromAslName (AcpiPath);
 | 
						|
  if (AmlPath == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG_CODE_BEGIN ();
 | 
						|
  DEBUG ((EFI_D_ERROR, "AcpiSdt: FindPath - "));
 | 
						|
  AmlPrintNameString (AmlPath);
 | 
						|
  DEBUG ((EFI_D_ERROR, "\n"));
 | 
						|
  DEBUG_CODE_END ();
 | 
						|
 | 
						|
  if (AmlHandle->Signature == EFI_AML_ROOT_HANDLE_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // Root Handle
 | 
						|
    //
 | 
						|
    Status = SdtFindPathFromRoot (HandleIn, AmlPath, HandleOut);
 | 
						|
  } else if (AmlHandle->Signature == EFI_AML_HANDLE_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // Non-Root handle
 | 
						|
    //
 | 
						|
    Status = SdtFindPathFromNonRoot (HandleIn, AmlPath, HandleOut);
 | 
						|
  } else {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (AmlPath);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  ExitPmAuth Protocol notification event handler.
 | 
						|
 | 
						|
  @param[in] Event    Event whose notification function is being invoked.
 | 
						|
  @param[in] Context  Pointer to the notification function's context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
ExitPmAuthNotification (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS Status;
 | 
						|
  VOID       *DxeSmmReadyToLock;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add more check to locate protocol after got event, because
 | 
						|
  // the library will signal this event immediately once it is register
 | 
						|
  // just in case it is already installed.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiDxeSmmReadyToLockProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &DxeSmmReadyToLock
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall ACPI SDT protocol, so that we can make sure no one update ACPI table from API level.
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallProtocolInterface (
 | 
						|
                  mHandle,
 | 
						|
                  &gEfiAcpiSdtProtocolGuid,
 | 
						|
                  &mPrivateData->AcpiSdtProtocol
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Close event, so it will not be invoked again.
 | 
						|
  //
 | 
						|
  gBS->CloseEvent (Event);
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function initializes AcpiSdt protocol in ACPI table instance.
 | 
						|
 | 
						|
  @param[in]  AcpiTableInstance       Instance to construct
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SdtAcpiTableAcpiSdtConstructor (
 | 
						|
  IN EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID *Registration;
 | 
						|
 | 
						|
  InitializeListHead (&AcpiTableInstance->NotifyList);
 | 
						|
  CopyMem (&AcpiTableInstance->AcpiSdtProtocol, &mAcpiSdtProtocolTemplate, sizeof(mAcpiSdtProtocolTemplate));
 | 
						|
 | 
						|
  //
 | 
						|
  // Register event for ExitPmAuth, so that we can uninstall ACPI SDT protocol after ExitPmAuth.
 | 
						|
  //
 | 
						|
  EfiCreateProtocolNotifyEvent (
 | 
						|
    &gEfiDxeSmmReadyToLockProtocolGuid,
 | 
						|
    TPL_CALLBACK,
 | 
						|
    ExitPmAuthNotification,
 | 
						|
    NULL,
 | 
						|
    &Registration
 | 
						|
    );
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 |