Hi Pierre, Please find my response inline marked [SAMI]. Regards, Sami Mujawar On 23/06/2021 12:40 PM, Pierre.Gondois@arm.com wrote: > From: Pierre Gondois > > 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 > --- > .../Include/Library/AmlLib/AmlLib.h | 71 +++ > .../Common/AmlLib/CodeGen/AmlCodeGen.c | 439 ++++++++++++++++++ > 2 files changed, 510 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 89350f65f5df..f0861040191f 100644 > --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c > +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c > @@ -12,6 +12,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -1554,3 +1555,441 @@ 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; > + > + // Get the LPI value which is represented as a PackageOp object node > + // which is the 2nd fixed argument (i.e. index 1). > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + goto error_handler; > + } > + Status = AmlCodeGenRdRegister ( > + GenericRegisterDescriptor->AddressSpaceId, > + GenericRegisterDescriptor->RegisterBitWidth, > + GenericRegisterDescriptor->RegisterBitOffset, > + GenericRegisterDescriptor->Address, > + GenericRegisterDescriptor->AccessSize, > + NULL, > + &RdNode > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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); > + 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_2_0_SYSTEM_MEMORY, > + 0, > + 0, > + 0, > + 0, > + NULL, > + &RdNode > + ); > + } > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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_2_0_SYSTEM_MEMORY, [SAMI] Can we useEFI_ACPI_6_4_SYSTEM_MEMORY here instead? > + 0, > + 0, > + 0, > + 0, > + NULL, > + &RdNode > + ); > + } > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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; > +}