/** @file
Copyright (C) 2020-2025 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "LocalAmlLib.h"
#include
#define FILECODE LIBRARY_DXEAMLGENERATIONLIB_AMLTABLE_FILECODE
// String Length Constants
#define OEM_ID_LENGTH 6
#define OEM_TABLE_ID_LENGTH 8
#define SIGNATURE_LENGTH 4
#define CREATOR_ID_LENGTH 4
/**
Creates an AML Encoded Table
Object must be created between AmlStart and AmlClose Phase
DefBlockHeader := TableSignature TableLength SpecCompliance CheckSum OemID
OemTableID OemRevision CreatorID CreatorRevision
TableSignature := DWordData // As defined in section 5.2.3.
TableLength := DWordData // Length of the table in bytes including the
// block header
SpecCompliance := ByteData // The revision of the structure.
CheckSum := ByteData // Byte checksum of the entire table.
OemID := ByteData(6) // OEM ID of up to 6 characters.
// If the OEM ID is shorter than 6
// characters, it can be terminated with a
// NULL character.
OemTableID := ByteData(8) // OEM Table ID of up to 8 characters.
// If the OEM Table ID is shorter than
// 8 characters, it can be terminated with
// a NULL character.
OemRevision := DWordData // OEM Table Revision.
CreatorID := DWordData // Vendor ID of the ASL compiler.
CreatorRevision := DWordData // Revision of the ASL compiler.
@param[in] Phase - Either AmlStart or AmlClose
@param[in] TableNameString - Table Name
@param[in] ComplianceRev - Compliance Revision
@param[in] OemId - OEM ID
@param[in] OemTableId - OEM ID of table
@param[in] OemRevision - OEM Revision number
@param[in] CreatorId - Vendor ID of the ASL compiler
@param[in] CreatorRevision - Vendor Revision of the ASL compiler
@param[in,out] ListHead - Linked list has completed String Object after
AmlClose.
@retval EFI_SUCCESS
@retval Error status
**/
EFI_STATUS
EFIAPI
AmlDefinitionBlock (
IN AML_FUNCTION_PHASE Phase,
IN CHAR8 *TableNameString,
IN UINT8 ComplianceRev,
IN CHAR8 *OemId,
IN CHAR8 *OemTableId,
IN UINT32 OemRevision,
IN CHAR8 *CreatorId,
IN UINT32 CreatorRevision,
IN OUT LIST_ENTRY *ListHead
)
{
EFI_STATUS Status;
AML_OBJECT_INSTANCE *Object;
AML_OBJECT_INSTANCE *ChildObject;
UINTN ChildCount;
if ((Phase >= AmlInvalid) ||
(ListHead == NULL) ||
(TableNameString == NULL) ||
(OemId == NULL) ||
(OemTableId == NULL) ||
(CreatorId == NULL) ||
(AsciiStrLen (TableNameString) != SIGNATURE_LENGTH) ||
(AsciiStrLen (OemId) > OEM_ID_LENGTH) ||
(AsciiStrLen (OemTableId) > OEM_TABLE_ID_LENGTH) ||
(AsciiStrLen (CreatorId) != CREATOR_ID_LENGTH))
{
return EFI_INVALID_PARAMETER;
}
Status = EFI_DEVICE_ERROR;
Object = NULL;
ChildObject = NULL;
switch (Phase) {
case AmlStart:
Status = InternalAppendNewAmlObject (&Object, TableNameString, ListHead);
// TermList is too complicated and must be added outside
break;
case AmlClose:
// TermList should be closed already
Status = InternalAmlLocateObjectByIdentifier (&Object, TableNameString, ListHead);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: ERROR: locate %a object\n", __func__, TableNameString));
goto Done;
}
// Get rid of original Identifier data
InternalFreeAmlObjectData (Object);
// Collect child data and delete children
Status = InternalAmlCollapseAndReleaseChildren (
&ChildObject,
&ChildCount,
&Object->Link,
ListHead
);
if (EFI_ERROR (Status) ||
(ChildObject->Data == NULL) ||
(ChildObject->DataSize == 0))
{
DEBUG ((DEBUG_ERROR, "%a: ERROR: %a has no child data.\n", __func__, TableNameString));
goto Done;
}
Object->DataSize = ChildObject->DataSize + sizeof (EFI_ACPI_DESCRIPTION_HEADER);
Object->Data = AllocateZeroPool (Object->DataSize);
if (Object->Data == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((DEBUG_ERROR, "%a: ERROR: allocate Object->Data for %a\n", __func__, TableNameString));
goto Done;
}
// Fill table header with data
// Signature
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Signature)],
TableNameString,
AsciiStrLen (TableNameString)
);
// Table Length
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Length)],
(UINT32 *)&Object->DataSize,
sizeof (UINT32)
);
// ACPI Table Version
Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Revision)] = ComplianceRev;
// OEM ID
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, OemId)],
OemId,
AsciiStrLen (OemId)
);
// OEM Table ID
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, OemTableId)],
OemTableId,
AsciiStrLen (OemTableId)
);
// OEM Table Version
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, OemRevision)],
(UINT8 *)&OemRevision,
sizeof (UINT32)
);
// Creator ID
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, CreatorId)],
CreatorId,
AsciiStrLen (CreatorId)
);
// Creator Version
CopyMem (
&Object->Data[OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, CreatorRevision)],
(UINT8 *)&CreatorRevision,
sizeof (UINT32)
);
// Copy rest of data into Object
CopyMem (
&Object->Data[sizeof (EFI_ACPI_DESCRIPTION_HEADER)],
ChildObject->Data,
ChildObject->DataSize
);
// Checksum Set on Table Install
InternalFreeAmlObject (&ChildObject, ListHead);
Object->Completed = TRUE;
Status = EFI_SUCCESS;
break;
default:
Status = EFI_DEVICE_ERROR;
break;
}
Done:
if (EFI_ERROR (Status)) {
InternalFreeAmlObject (&Object, ListHead);
InternalFreeAmlObject (&ChildObject, ListHead);
}
return Status;
}