Hi Pierre,

This patch looks good to me.

Reviewed-by: Sami Mujawar <[email protected]>

Regards,

Sami Mujawar

On 07/10/2021 04:32 PM, [email protected] wrote:
From: Pierre Gondois <[email protected]>

Add AmlAddLpiState() to generates AML code to add an _LPI state
to an _LPI object created using AmlCreateLpiNode().

AmlAddLpiState increments the count of LPI states in the LPI
node by one, and adds the following package:
   Package() {
     MinResidency,
     WorstCaseWakeLatency,
     Flags,
     ArchFlags,
     ResCntFreq,
     EnableParentState,
     (GenericRegisterDescriptor != NULL) ?           // Entry method. If a
       ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
       Integer,                                      // use it. Use the
                                                     // Integer otherwise
     ResourceTemplate() {                            // NULL Residency
       Register (SystemMemory, 0, 0, 0, 0)           // Counter
     },
     ResourceTemplate() {                            // NULL Usage Counter
       Register (SystemMemory, 0, 0, 0, 0)
     },
     ""                                              // NULL State Name
   },

Signed-off-by: Pierre Gondois <[email protected]>
---
  .../Include/Library/AmlLib/AmlLib.h           |  71 +++
  .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 459 ++++++++++++++++++
  2 files changed, 530 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h 
b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 40c45073d303..4932f6fd9c8b 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -716,6 +716,77 @@ AmlCreateLpiNode (
    OUT       AML_OBJECT_NODE_HANDLE  * NewLpiNode   OPTIONAL
    );

+/** Add an _LPI state to a LPI node created using AmlCreateLpiNode ().
+
+  AmlAddLpiState () increments the Count of LPI states in the LPI node by one,
+  and adds the following package:
+    Package() {
+      MinResidency,
+      WorstCaseWakeLatency,
+      Flags,
+      ArchFlags,
+      ResCntFreq,
+      EnableParentState,
+      (GenericRegisterDescriptor != NULL) ?           // Entry method. If a
+        ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
+        Integer,                                      // use it. Use the
+                                                      // Integer otherwise.
+      ResourceTemplate() {                            // NULL Residency Counter
+        Register (SystemMemory, 0, 0, 0, 0)
+      },
+      ResourceTemplate() {                            // NULL Usage Counter
+        Register (SystemMemory, 0, 0, 0, 0)
+      },
+      ""                                              // NULL State Name
+    },
+
+  Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
+
+  @ingroup CodeGenApis
+
+  @param [in]  MinResidency               Minimum Residency.
+  @param [in]  WorstCaseWakeLatency       Worst case wake-up latency.
+  @param [in]  Flags                      Flags.
+  @param [in]  ArchFlags                  Architectural flags.
+  @param [in]  ResCntFreq                 Residency Counter Frequency.
+  @param [in]  EnableParentState          Enabled Parent State.
+  @param [in]  GenericRegisterDescriptor  Entry Method.
+                                          If not NULL, use this Register to
+                                          describe the entry method address.
+  @param [in]  Integer                    Entry Method.
+                                          If GenericRegisterDescriptor is NULL,
+                                          take this value.
+  @param [in]  ResidencyCounterRegister   If not NULL, use it to populate the
+                                          residency counter register.
+  @param [in]  UsageCounterRegister       If not NULL, use it to populate the
+                                          usage counter register.
+  @param [in]  StateName                  If not NULL, use it to populate the
+                                          state name.
+  @param [in]  LpiNode                    Lpi node created with the function
+                                          AmlCreateLpiNode to which the new LPI
+                                          state is appended.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddLpiState (
+  IN  UINT32                                    MinResidency,
+  IN  UINT32                                    WorstCaseWakeLatency,
+  IN  UINT32                                    Flags,
+  IN  UINT32                                    ArchFlags,
+  IN  UINT32                                    ResCntFreq,
+  IN  UINT32                                    EnableParentState,
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * GenericRegisterDescriptor,  
OPTIONAL
+  IN  UINT64                                    Integer,                    
OPTIONAL
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * ResidencyCounterRegister,   
OPTIONAL
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * UsageCounterRegister,       
OPTIONAL
+  IN  CHAR8                                   * StateName,                  
OPTIONAL
+  IN  AML_OBJECT_NODE_HANDLE                    LpiNode
+  );
+
  // DEPRECATED APIS
  #ifndef DISABLE_NEW_DEPRECATED_INTERFACES

diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c 
b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 2223e4bcfef9..36c908863983 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -12,6 +12,7 @@

  #include <AmlCoreInterface.h>
  #include <AmlEncoding/Aml.h>
+#include <Api/AmlApiHelper.h>
  #include <CodeGen/AmlResourceDataCodeGen.h>
  #include <Tree/AmlNode.h>
  #include <Tree/AmlTree.h>
@@ -1575,3 +1576,461 @@ error_handler:
    }
    return Status;
  }
+
+/** Add an _LPI state to a LPI node created using AmlCreateLpiNode.
+
+  AmlAddLpiState increments the Count of LPI states in the LPI node by one,
+  and adds the following package:
+    Package() {
+      MinResidency,
+      WorstCaseWakeLatency,
+      Flags,
+      ArchFlags,
+      ResCntFreq,
+      EnableParentState,
+      (GenericRegisterDescriptor != NULL) ?           // Entry method. If a
+        ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
+        Integer,                                      // use it. Use the
+                                                      // Integer otherwise.
+      ResourceTemplate() {                            // NULL Residency Counter
+        Register (SystemMemory, 0, 0, 0, 0)
+      },
+      ResourceTemplate() {                            // NULL Usage Counter
+        Register (SystemMemory, 0, 0, 0, 0)
+      },
+      ""                                              // NULL State Name
+    },
+
+  Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
+
+  @param [in]  MinResidency               Minimum Residency.
+  @param [in]  WorstCaseWakeLatency       Worst case wake-up latency.
+  @param [in]  Flags                      Flags.
+  @param [in]  ArchFlags                  Architectural flags.
+  @param [in]  ResCntFreq                 Residency Counter Frequency.
+  @param [in]  EnableParentState          Enabled Parent State.
+  @param [in]  GenericRegisterDescriptor  Entry Method.
+                                          If not NULL, use this Register to
+                                          describe the entry method address.
+  @param [in]  Integer                    Entry Method.
+                                          If GenericRegisterDescriptor is NULL,
+                                          take this value.
+  @param [in]  ResidencyCounterRegister   If not NULL, use it to populate the
+                                          residency counter register.
+  @param [in]  UsageCounterRegister       If not NULL, use it to populate the
+                                          usage counter register.
+  @param [in]  StateName                  If not NULL, use it to populate the
+                                          state name.
+  @param [in]  LpiNode                    Lpi node created with the function
+                                          AmlCreateLpiNode to which the new LPI
+                                          state is appended.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddLpiState (
+  IN  UINT32                                    MinResidency,
+  IN  UINT32                                    WorstCaseWakeLatency,
+  IN  UINT32                                    Flags,
+  IN  UINT32                                    ArchFlags,
+  IN  UINT32                                    ResCntFreq,
+  IN  UINT32                                    EnableParentState,
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * GenericRegisterDescriptor,  
OPTIONAL
+  IN  UINT64                                    Integer,                    
OPTIONAL
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * ResidencyCounterRegister,   
OPTIONAL
+  IN  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE  * UsageCounterRegister,       
OPTIONAL
+  IN  CHAR8                                   * StateName,                  
OPTIONAL
+  IN  AML_OBJECT_NODE_HANDLE                    LpiNode
+  )
+{
+  EFI_STATUS                Status;
+  AML_DATA_NODE_HANDLE      RdNode;
+  AML_OBJECT_NODE_HANDLE    PackageNode;
+  AML_OBJECT_NODE_HANDLE    IntegerNode;
+  AML_OBJECT_NODE_HANDLE    StringNode;
+  AML_OBJECT_NODE_HANDLE    NewLpiPackageNode;
+  AML_OBJECT_NODE_HANDLE    ResourceTemplateNode;
+
+  UINT32                    Index;
+  AML_OBJECT_NODE_HANDLE    CountNode;
+  UINT64                    Count;
+
+  if ((LpiNode == NULL)                                              ||
+      (AmlGetNodeType ((AML_NODE_HANDLE)LpiNode) != EAmlNodeObject)  ||
+      (!AmlNodeHasOpCode (LpiNode, AML_NAME_OP, 0))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RdNode = 0;
+  StringNode = NULL;
+  IntegerNode = NULL;
+  ResourceTemplateNode = NULL;
+
+  // AmlCreateLpiNode () created a LPI container such as:
+  //  Name (_LPI, Package (
+  //                0,  // Revision
+  //                1,  // LevelId
+  //                0   // Count
+  //                ))
+  // Get the LPI container, a PackageOp object node stored as the 2nd fixed
+  // argument (i.e. index 1) of LpiNode.
+  PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+                                          LpiNode,
+                                          EAmlParseIndexTerm1
+                                          );
+  if ((PackageNode == NULL)                                             ||
+      (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) ||
+      (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CountNode = NULL;
+  // The third variable argument is the LPI Count node.
+  for (Index = 0; Index < 3; Index++) {
+    CountNode = (AML_OBJECT_NODE_HANDLE)AmlGetNextVariableArgument (
+                                          (AML_NODE_HANDLE)PackageNode,
+                                          (AML_NODE_HANDLE)CountNode
+                                          );
+    if (CountNode == NULL) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  Status = AmlNodeGetIntegerValue (CountNode, &Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+  Status = AmlUpdateInteger (CountNode, Count + 1);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = AmlCodeGenPackage (&NewLpiPackageNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // MinResidency
+  Status = AmlCodeGenInteger (MinResidency, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // WorstCaseWakeLatency
+  Status = AmlCodeGenInteger (WorstCaseWakeLatency, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // Flags
+  Status = AmlCodeGenInteger (Flags, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // ArchFlags
+  Status = AmlCodeGenInteger (ArchFlags, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // ResCntFreq
+  Status = AmlCodeGenInteger (ResCntFreq, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // EnableParentState
+  Status = AmlCodeGenInteger (EnableParentState, &IntegerNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    IntegerNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)IntegerNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  IntegerNode = NULL;
+
+  // Entry Method
+  if (GenericRegisterDescriptor != NULL) {
+    // Entry Method: As a Register resource data
+    Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      ResourceTemplateNode = NULL;
+      goto error_handler;
+    }
+    Status = AmlCodeGenRdRegister (
+               GenericRegisterDescriptor->AddressSpaceId,
+               GenericRegisterDescriptor->RegisterBitWidth,
+               GenericRegisterDescriptor->RegisterBitOffset,
+               GenericRegisterDescriptor->Address,
+               GenericRegisterDescriptor->AccessSize,
+               NULL,
+               &RdNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      RdNode = NULL;
+      goto error_handler;
+    }
+
+    Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto error_handler;
+    }
+    RdNode = NULL;
+
+    Status = AmlVarListAddTail (
+               (AML_NODE_HANDLE)NewLpiPackageNode,
+               (AML_NODE_HANDLE)ResourceTemplateNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto error_handler;
+    }
+    ResourceTemplateNode = NULL;
+  } else {
+    // Entry Method: As an integer
+    Status = AmlCodeGenInteger (Integer, &IntegerNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      IntegerNode = NULL;
+      goto error_handler;
+    }
+    Status = AmlVarListAddTail (
+               (AML_NODE_HANDLE)NewLpiPackageNode,
+               (AML_NODE_HANDLE)IntegerNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto error_handler;
+    }
+    IntegerNode = NULL;
+  }
+
+  // Residency Counter Register.
+  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    ResourceTemplateNode = NULL;
+    goto error_handler;
+  }
+  if (ResidencyCounterRegister != NULL) {
+    Status = AmlCodeGenRdRegister (
+               ResidencyCounterRegister->AddressSpaceId,
+               ResidencyCounterRegister->RegisterBitWidth,
+               ResidencyCounterRegister->RegisterBitOffset,
+               ResidencyCounterRegister->Address,
+               ResidencyCounterRegister->AccessSize,
+               NULL,
+               &RdNode
+               );
+  } else {
+    Status = AmlCodeGenRdRegister (
+               EFI_ACPI_6_4_SYSTEM_MEMORY,
+               0,
+               0,
+               0,
+               0,
+               NULL,
+               &RdNode
+               );
+  }
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    RdNode = NULL;
+    goto error_handler;
+  }
+
+  Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  RdNode = NULL;
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)ResourceTemplateNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  ResourceTemplateNode = NULL;
+
+  // Usage Counter Register.
+  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    ResourceTemplateNode = NULL;
+    goto error_handler;
+  }
+  if (UsageCounterRegister != NULL) {
+    Status = AmlCodeGenRdRegister (
+               UsageCounterRegister->AddressSpaceId,
+               UsageCounterRegister->RegisterBitWidth,
+               UsageCounterRegister->RegisterBitOffset,
+               UsageCounterRegister->Address,
+               UsageCounterRegister->AccessSize,
+               NULL,
+               &RdNode
+               );
+  } else {
+    Status = AmlCodeGenRdRegister (
+               EFI_ACPI_6_4_SYSTEM_MEMORY,
+               0,
+               0,
+               0,
+               0,
+               NULL,
+               &RdNode
+               );
+  }
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    RdNode = NULL;
+    goto error_handler;
+  }
+
+  Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  RdNode = NULL;
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)ResourceTemplateNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  ResourceTemplateNode = NULL;
+
+  // State name.
+  if (UsageCounterRegister != NULL) {
+    Status = AmlCodeGenString (StateName, &StringNode);
+  } else {
+    Status = AmlCodeGenString ("", &StringNode);
+  }
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    StringNode = NULL;
+    goto error_handler;
+  }
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)NewLpiPackageNode,
+             (AML_NODE_HANDLE)StringNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+  StringNode = NULL;
+
+  // Add the new LPI state to the LpiNode.
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)NewLpiPackageNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  return Status;
+
+error_handler:
+  if (RdNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)RdNode);
+  }
+  if (NewLpiPackageNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)NewLpiPackageNode);
+  }
+  if (StringNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)StringNode);
+  }
+  if (IntegerNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
+  }
+  if (ResourceTemplateNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);
+  }
+
+  return Status;
+}

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81688): https://edk2.groups.io/g/devel/message/81688
Mute This Topic: https://groups.io/mt/86148215/21656
Group Owner: [email protected]
Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to