How to Add a Custom ACPI SSDT to AMI Aptio: A Complete Implementation Guide
A common firmware development task starts with an industrial motherboard based on Intel Coffee Lake or Whiskey Lake. The vendor provides a BIOS ROM, but the project needs additional platform-specific functionality:
- Expose a custom ACPI device to Windows and Linux.
- Describe a board-specific MMIO register block.
- Add control methods for hardware status and configuration.
- Provide wake-up or temperature-reporting interfaces.
- Let an operating-system driver retrieve private platform information through an ACPI
_DSMmethod.
These requirements often point to the same solution: adding a custom Secondary System Description Table (SSDT) to the firmware.
An SSDT provides a modular way to extend the ACPI namespace without directly modifying the platform’s main DSDT. The firmware publishes the table, and the operating system interprets its AML definitions.
This guide follows an AMI Aptio V development workflow, with notes for Aptio 4 projects. It covers ASL authoring, AML compilation, a DXE installer, AMI’s module packaging conventions, ROM verification, firmware flashing, and validation from the operating system.
The example introduces a fictional ACPI device named MYCO0001, with an MMIO register region and several control methods.
Important: This is a development example, not a drop-in production firmware module. Replace all sample hardware addresses and resources with values from the actual board design. AMI project layouts, build rules, module registration, and flashing options vary by firmware release and platform.
🧭 1. ACPI Fundamentals: ASL, AML, DSDT, and SSDT #
Before modifying firmware, it helps to understand how ACPI tables reach the operating system.
1.1 From ASL source to operating-system execution #
ASL is the human-readable language used to describe ACPI objects and control methods. The iasl compiler converts ASL source into AML bytecode, which the operating system’s ACPI interpreter evaluates.
The general flow looks like this:
ASL source code
|
| iasl compiler
v
AML bytecode
|
| packaged into an ACPI table
v
DSDT / SSDT
|
| published by firmware
v
ACPI table discovery by the OS
|
v
AML interpreter
|
v
ACPI namespace and control methodsThe key distinction is that AML execution generally happens in the operating system, not in the DXE firmware module that installs the table.
The firmware is responsible for making the ACPI table available to the operating system. Windows and Linux then parse the table and interpret its AML definitions.
1.2 Understanding the ACPI table hierarchy #
The operating system discovers ACPI tables through the Root System Description Pointer (RSDP).
A simplified view of the table relationships is:
RSDP
|
+-- RSDT / XSDT
|
+-- FADT
| |
| +-- DSDT pointer
|
+-- SSDT
+-- SSDT
+-- APIC / MADT
+-- MCFG
+-- HPET
+-- Other tablesThe distinction matters: the XSDT or RSDT contains pointers to many system description tables, while the FADT provides the address of the DSDT.
| Table | Purpose |
|---|---|
| RSDP | Entry point for ACPI table discovery |
| RSDT / XSDT | Contains pointers to ACPI system description tables |
| FADT | Describes fixed ACPI hardware features and provides the DSDT address |
| DSDT | Contains the primary ACPI namespace definitions |
| SSDT | Adds supplementary definitions to the ACPI namespace |
| MADT | Describes interrupt-controller and processor interrupt structures |
| MCFG | Describes PCI Express configuration-space information |
| HPET | Describes the High Precision Event Timer, where supported |
1.3 Why use an SSDT instead of modifying the DSDT? #
For board-specific additions, an SSDT is often easier to maintain than a direct DSDT modification.
The DSDT is usually closely tied to the chipset and platform configuration. Changing it can create unnecessary integration work when the vendor updates the firmware source.
An SSDT provides a separate table that can add devices, methods, and other namespace objects.
However, SSDTs are not isolated namespaces. Their definitions are incorporated into the system ACPI namespace, so object names must not collide with existing definitions. A device declared in an SSDT can therefore conflict with an object already present in the DSDT or another SSDT.
1.4 ASL naming rules #
ACPI namespace names have strict syntax:
- A NameSeg contains four characters.
- The first character must be an uppercase letter or underscore.
- Subsequent characters may include uppercase letters, digits, and underscores.
- Names beginning with an underscore are reserved for ACPI-defined objects and should not be invented for custom methods.
For example:
Device (DEMO)
{
Method (RVER, 0, Serialized)
{
Return (0x01)
}
}DEMO and RVER are valid four-character names.
The _HID, _UID, _STA, and _CRS objects used later are standardized ACPI objects, not arbitrary custom names.
🛠️ 2. Development Environment and Required Tools #
2.1 AMI Aptio project package #
AMI Aptio source code is distributed through authorized project deliveries, typically under the applicable commercial agreement and NDA.
This tutorial assumes access to an Aptio V project. Aptio 4 follows similar concepts, but its module conventions, headers, and build integration may differ.
Use an existing DXE module from the same project as the template for the installer. Do not assume that a module structure from another Aptio release will work unchanged.
2.2 Tool checklist #
| Tool | Purpose |
|---|---|
iasl |
Compile ASL into AML and disassemble AML for inspection |
acpiexec |
Execute and test ACPI methods in an ACPICA environment |
AMI build tools |
Compile and package the Aptio project |
| MMTOOL | Inspect firmware volumes and FFS modules |
| AFU | Update firmware on supported platforms |
| RU.EXE | Inspect firmware structures and ACPI tables on supported systems |
| USB-to-TTL serial adapter | Capture firmware debug output |
| SPI programmer | Recover a development board after an unsuccessful flash |
Use the ACPICA tools from a trusted source and confirm that their version is compatible with the ACPI language features used by the project.
2.3 Hardware requirements #
Use a development board that can tolerate firmware modification.
For the example, assume an Intel Coffee Lake industrial motherboard with an available MMIO register block. The address used in the ASL example is illustrative only. It must not be copied into production firmware without checking the board’s memory map and resource ownership.
An external SPI programmer is strongly recommended for development platforms. It provides a recovery path if the system can no longer boot after a firmware update.
🏗️ 3. Implementation Overview #
The goal is to add a custom ACPI device with the hardware ID MYCO0001.
After successful installation and enumeration, Linux should expose an ACPI device resembling:
$ ls /sys/bus/acpi/devices/
MYCO0001:00 PNP0103:00 PNP0C01:00 ...The complete development flow is:
1. Write SsdtDemo.asl
|
v
2. Compile with iasl
|
v
3. Inspect AML and test methods with acpiexec
|
v
4. Generate a C-compatible AML array
|
v
5. Create the AMI DXE installer module
|
v
6. Register and enable the module in the Aptio project
|
v
7. Build the firmware image
|
v
8. Inspect the firmware volume with MMTOOL
|
v
9. Flash a development board using the approved update process
|
v
10. Verify the SSDT and device from firmware and OS toolsThe central design principle is simple:
The DXE module installs the ACPI table; the operating system interprets the table and exposes its namespace objects.
That distinction determines how the implementation and validation should be organized.
✍️ 4. Writing the ASL Source #
4.1 Create the custom SSDT #
Create a file named SsdtDemo.asl.
The example declares a device under \_SB, describes a resource region, maps a hardware register block, and defines several methods.
/*
* SsdtDemo.asl
*
* Custom ACPI device example.
* Declares an MMIO register block and several methods.
*/
DefinitionBlock ("", "SSDT", 2, "MYCO", "SSDTDEMO", 0x00000001)
{
Scope (\_SB)
{
Device (DEMO)
{
/*
* Device identification.
*/
Name (_HID, "MYCO0001")
Name (_UID, 0x00)
/*
* Device status:
* Bit 0: Device is present.
* Bit 1: Device is enabled.
* Bit 2: Device should be shown in the UI.
* Bit 3: Device is functioning correctly.
*/
Method (_STA, 0, NotSerialized)
{
Return (0x0F)
}
/*
* Hardware resources.
*
* Replace these values with resources actually
* assigned to this device by the platform.
*/
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (
ReadWrite,
0xFED50000,
0x00001000
)
})
/*
* Register mapping.
*
* The OperationRegion must describe the same
* hardware block reported through _CRS.
*/
OperationRegion (
DMEM,
SystemMemory,
0xFED50000,
0x1000
)
Field (DMEM, DWordAcc, NoLock, Preserve)
{
DVER, 32,
DCTL, 32,
DDTA, 32
}
/*
* Read device version.
*/
Method (RVER, 0, Serialized)
{
Return (DVER)
}
/*
* Write control register.
*/
Method (WCTL, 1, Serialized)
{
Store (Arg0, DCTL)
}
/*
* Write and read back the data register.
*/
Method (ECHO, 1, Serialized)
{
Store (Arg0, DDTA)
Return (DDTA)
}
/*
* Pure arithmetic test method.
*/
Method (ADDX, 2, Serialized)
{
Return (Add (Arg0, Arg1))
}
}
}
}This is a minimal example of an SSDT-based device declaration. The resource description deliberately contains only the MMIO range.
Do not add interrupt or I/O-port descriptors simply because they appear in another example. Each descriptor must correspond to a real resource assigned to the device. Incorrect resource declarations can cause operating-system resource conflicts or unsafe hardware access.
4.2 Understanding the important ASL objects #
| ASL object | Purpose |
|---|---|
DefinitionBlock |
Defines the SSDT header and OEM identification |
Scope (\_SB) |
Places the device under the ACPI System Bus namespace |
Device (DEMO) |
Declares the custom ACPI device |
_HID |
Provides the device’s hardware identification |
_UID |
Distinguishes instances of devices with the same identification |
_STA |
Reports the device’s presence and operating status |
_CRS |
Describes the resources assigned to the device |
OperationRegion |
Defines a region through which AML can access hardware or another address space |
Field |
Maps named fields onto the operation region |
Method |
Defines an AML control method callable by the ACPI interpreter |
The hardware ID MYCO0001 follows the vendor-defined ID format: four uppercase letters followed by four hexadecimal digits.
4.3 _STA: Device visibility and status
#
The _STA method returns a bit field.
| Bit | Meaning |
|---|---|
| Bit 0 | Device is present |
| Bit 1 | Device is enabled and decoding its resources |
| Bit 2 | Device should be shown in the user interface |
| Bit 3 | Device is functioning properly |
Returning 0x0F sets all four bits.
Returning zero indicates that the device is not present. A device may therefore be installed in an SSDT but remain invisible to normal OS enumeration if _STA reports it as absent.
4.4 _CRS and OperationRegion must agree
#
The _CRS object tells the operating system which resources the device consumes.
The OperationRegion declaration identifies the address range that AML methods access.
In this example, both refer to the same 4 KB MMIO region:
Base address: 0xFED50000
Length: 0x1000This is only a demonstration address. Before using a real address, verify that:
- The range is reserved for the device.
- It does not overlap another hardware resource.
- The hardware is accessible in the declared address space.
- The register access width and alignment match the hardware specification.
- The resource description accurately represents the platform allocation.
An AML declaration does not allocate physical MMIO resources or initialize the hardware. Those responsibilities belong to the platform’s hardware and firmware design.
4.5 Understanding Field and register access
#
The Field declaration maps the first three 32-bit values in the operation region:
| Field | Offset | Width |
|---|---|---|
DVER |
0x00 |
32 bits |
DCTL |
0x04 |
32 bits |
DDTA |
0x08 |
32 bits |
For example:
Method (RVER, 0, Serialized)
{
Return (DVER)
}The method reads the version field and returns its value.
Serialized prevents concurrent execution of the same method. This can be useful when methods access shared state or hardware registers, but it does not replace hardware-level locking or synchronization requirements.
4.6 Adding a _DSM interface
#
The example’s RVER, WCTL, and ECHO methods are custom control methods. If an operating-system driver needs a standardized device-specific interface, consider implementing _DSM.
_DSM is a standardized ACPI method with four arguments:
Method (_DSM, 4, Serialized)
{
/*
* Arg0: UUID
* Arg1: Revision
* Arg2: Function index
* Arg3: Function-specific arguments
*
* A production implementation should:
* 1. Validate the UUID.
* 2. Check the requested revision.
* 3. Handle function index 0 as the function-support query.
* 4. Return the appropriate package or value for supported functions.
* 5. Return a suitable response for unsupported functions.
*/
}The UUID identifies the device-specific interface contract. The revision and function index define which operation the driver is requesting.
Do not expose undocumented register access through _DSM without a stable interface specification. The firmware and operating-system driver must agree on the UUID, revision, argument formats, return types, and error behavior.
🧪 5. Compile and Test the AML #
The next step is to compile the ASL source and verify the generated AML before integrating it into the firmware.
5.1 Compile with iasl
#
Run:
iasl SsdtDemo.aslA successful compilation should report zero errors.
Warnings and remarks should still be reviewed. A clean compilation does not guarantee that the table will behave correctly on the target platform.
5.2 Disassemble the generated AML #
Use the compiler’s disassembly mode:
iasl -d SsdtDemo.amlThis generates a disassembled ASL representation that can be compared with the original source.
Round-trip inspection helps catch unexpected compiler output and confirms that the expected device and methods are present.
5.3 Test control methods with acpiexec
#
ACPICA provides acpiexec, which can load AML tables and execute supported control methods in a test environment.
For example:
acpiexec SsdtDemo.amlAt the prompt, invoke the arithmetic method:
acpiexec> execute \_SB.DEMO.ADDX 0x33 0x44The expected result is:
Result: Integer 0x0000000000000077Because:
0x33 + 0x44 = 0x77This verifies the basic AML method logic without flashing the development board.
A hardware-dependent method such as RVER requires a suitable operation-region environment. A host-side ACPICA test should not be mistaken for validation of the actual motherboard’s MMIO mapping or register behavior.
5.4 Generate a C-compatible AML array #
The DXE installer needs a binary representation of the compiled table.
ACPICA’s iasl supports generating C-compatible output. For example:
iasl -tc SsdtDemo.aslCheck the generated output for the exact file format produced by the installed compiler version. The following packaging script assumes that the compiler produces SsdtDemo.hex.
#!/bin/bash
set -euo pipefail
iasl -tc SsdtDemo.asl
test -f SsdtDemo.hex
{
echo '#ifndef SSDT_DEMO_HEX_H_'
echo '#define SSDT_DEMO_HEX_H_'
cat SsdtDemo.hex
echo
echo '#endif'
} > SsdtDemoHex.h
echo "Generated SsdtDemoHex.h"Run this script every time the ASL source changes.
The generated array should contain the ACPI table header. Its first four bytes should identify the SSDT signature:
unsigned char AmlCode[] =
{
0x53, 0x53, 0x44, 0x54, /* "SSDT" */
/* Remaining compiler-generated table bytes */
};Do not hand-edit the generated AML array. Regenerate it from the source instead.
📦 6. Packaging the SSDT Installer as an AMI DXE Module #
The SSDT is not automatically installed merely because the ASL file compiles.
The Aptio project needs a DXE module that locates the ACPI Table Protocol and calls InstallAcpiTable().
6.1 The AMI module file set #
A common AMI Aptio module uses five project files:
| File | Responsibility |
|---|---|
SsdtDemoDxe.c |
DXE installer implementation |
SsdtDemoDxe.dxs |
Dependency expression |
SsdtDemoDxe.cif |
Component information |
SsdtDemoDxe.mak |
Build integration |
SsdtDemoDxe.sdl |
Project configuration token |
The exact requirements depend on the Aptio version and the conventions of the existing project.
A typical directory structure is:
SsdtDemo/
|
+-- SsdtDemo.asl
+-- SsdtDemoHex.h
+-- SsdtDemoDxe.c
+-- SsdtDemoDxe.dxs
+-- SsdtDemoDxe.cif
+-- SsdtDemoDxe.mak
+-- SsdtDemoDxe.sdl
+-- gen-ssdt.shA practical approach is to copy a working DXE module from the same Aptio project and adapt its files. This preserves project-specific conventions that may not be documented in generic examples.
6.2 SsdtDemoDxe.c: Install the ACPI table
#
The DXE installer uses the UEFI ACPI Table Protocol to publish the SSDT.
//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// SsdtDemoDxe.c
// Install custom SSDT into the ACPI table set.
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
#include <Token.h>
#include <AmiDxeLib.h>
#include <Protocol/AcpiTable.h>
#include "SsdtDemoHex.h"
EFI_DRIVER_ENTRY_POINT (SsdtDemoEntryPoint);
EFI_STATUS
SsdtDemoEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
UINTN TableKey;
AcpiTable = NULL;
TableKey = 0;
/*
* Initialize AMI library services before using pBS.
*/
Status = InitAmiLib (ImageHandle, SystemTable);
if (EFI_ERROR (Status)) {
return Status;
}
/*
* Locate the ACPI Table Protocol.
*/
Status = pBS->LocateProtocol (
&gEfiAcpiTableProtocolGuid,
NULL,
(VOID **)&AcpiTable
);
if (EFI_ERROR (Status)) {
return Status;
}
/*
* Install the complete ACPI table.
*
* AmlCode includes the ACPI table header.
* InstallAcpiTable handles table publication and
* checksum processing.
*/
Status = AcpiTable->InstallAcpiTable (
AcpiTable,
(VOID *)AmlCode,
sizeof (AmlCode),
&TableKey
);
return Status;
}The installer performs three basic operations:
- Initializes the AMI library environment.
- Locates the ACPI Table Protocol.
- Installs the generated AML table.
InitAmiLib() and pBS are part of the AMI library pattern used here. Other UEFI projects may use different initialization conventions.
The ACPI Table Protocol handles the mechanics of publishing the table. The installer does not need to manually update the XSDT or calculate the table checksum.
For a production implementation, retain the returned TableKey if the module needs to remove the table later through UninstallAcpiTable(). Also consider duplicate installation, error logging, and the lifetime of the installer module.
6.3 SsdtDemoDxe.dxs: Declare the protocol dependency
#
The DXE driver requires the ACPI Table Protocol.
A typical dependency expression is:
//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// Dependency Expression
// Wait for the ACPI Table Protocol.
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
DEPENDENCY_START
gEfiAcpiTableProtocolGuid : GUID_DEPENDENCY
DEPENDENCY_ENDThis tells the DXE dispatcher that the module depends on the ACPI Table Protocol.
Some older Aptio projects use different GUID macro names or dependency syntax. Follow the conventions of neighboring modules in the actual project.
6.4 SsdtDemoDxe.cif: Component information
#
The component information file describes the module and its source files.
A representative example is:
## @file
# SsdtDemoDxe.cif
# Installs the custom MYCO0001 SSDT.
[Component]
Name = SsdtDemoDxe
Version = 1.00
Description = Install custom ACPI SSDT
BaseName = SsdtDemoDxe
[Sources]
SsdtDemoDxe.c
SsdtDemoHex.h
[Files]
x86\SsdtDemoDxe.efi = SsdtDemoDxeThe actual CIF syntax and required fields must match the project template.
Pay particular attention to module identity. When copying an existing component, assign a new module GUID according to the project’s registration rules. Reusing another module’s FFS file GUID can cause build conflicts or ambiguous module identification.
6.5 SsdtDemoDxe.mak: Build integration
#
A simplified AMI-style makefile may look like this:
#---------------------------------------------------------------------------
# SsdtDemoDxe.mak
#---------------------------------------------------------------------------
all : SsdtDemoDxe
SsdtDemoDxe : $(BUILD_DIR)\SsdtDemoDxe.mak
$(BUILD_DIR)\SsdtDemoDxe.mak : \
$(SsdtDemoDxe_DIR)\$(@B).cif \
$(SsdtDemoDxe_DIR)\$(@B).mak \
$(BUILD_RULES)
$(CIF2MAK) \
$(SsdtDemoDxe_DIR)\$(@B).cif \
$@ \
$(CIF2MAK_DEFAULTS)The CIF2MAK step translates the component description into build rules understood by the Aptio build environment.
This is an illustrative pattern, not a universal Aptio makefile. Use an existing working module as the reference for directory variables, build dependencies, and compiler settings.
6.6 SsdtDemoDxe.sdl: Add a build switch
#
A project token can control whether the module participates in the build.
For example:
## SSDT Demo Module Switch
<Token>
Name = SSDT_DEMO_SUPPORT
Type = Boolean
Value = TRUE
</Token>The token declaration alone does not guarantee that the module will be discovered or built. Some projects require the module to be registered in a parent SDL file or master component list.
Check the project’s existing module-registration pattern before assuming that placing the directory in the module tree is sufficient.
🔧 7. Integrating and Building the Aptio Project #
7.1 Place the module in the correct directory #
Copy the complete SsdtDemo directory into the appropriate module tree.
Common project layouts use directories such as:
Module/
Sources/
Platform/The correct location depends on the project. The build system must be able to discover the module’s CIF, MAK, and SDL definitions.
7.2 Enable the module #
Check the following items:
- The module is registered in the appropriate project component list.
- Its SDL configuration is included.
SSDT_DEMO_SUPPORTis enabled.- Its module GUID is unique.
- The generated
SsdtDemoHex.his included in the build. - The dependency expression references the correct ACPI Table Protocol GUID.
A successful build does not prove that the DXE module was included in the firmware volume. That must be checked separately.
7.3 Build the firmware image #
Run the normal build process for the target Aptio project.
The resulting ROM is commonly placed under a build output directory, with a filename such as:
Build/MyProject.romThe exact location and filename depend on the platform build configuration.
7.4 Capture firmware debug output #
For a DEBUG build, serial output can help confirm that the installer executed.
A typical serial configuration is:
115200 baud
8 data bits
No parity
1 stop bitConnect a USB-to-TTL adapter to the board’s supported serial debug header. Confirm the board’s voltage levels and pinout before connecting the adapter.
Do not assume every COM header uses the same pin assignment or electrical interface.
🔍 8. Verify the Firmware Image with MMTOOL #
Before flashing, inspect the built image.
This step confirms that the DXE module was packaged into the firmware volume.
8.1 Load the ROM #
Open MMTOOL and load the newly generated ROM.
Locate the firmware volume containing DXE drivers and search for the new module using its registered FFS file GUID.
Depending on the MMTOOL version and the project, the component may be displayed by name, GUID, or another module identifier.
8.2 Confirm the module is present #
Check that:
- The module appears in the expected firmware volume.
- Its file GUID matches the new component registration.
- Its file type is appropriate for the DXE module.
- The extracted module contains the expected installer implementation.
If the module is missing, return to the build configuration. Common causes include an unregistered component, a disabled SDL token, or a build rule that was never included.
8.3 Understand what MMTOOL does not prove #
Finding the DXE installer in the firmware image does not prove that the SSDT will be installed successfully at runtime.
There are separate stages:
| Stage | What it proves |
|---|---|
| ASL compilation | The source compiles into AML |
| Host-side AML testing | Selected AML methods behave as expected in the test environment |
| MMTOOL inspection | The DXE installer is present in the ROM |
| Firmware runtime verification | The installer executes and publishes the SSDT |
| OS verification | The operating system discovers the table and enumerates the device |
A complete validation process needs evidence from each relevant stage.
MMTOOL can also replace or insert FFS modules in some firmware images. That capability should not be treated as a substitute for a controlled source-based build. Modifying signed production images can invalidate firmware signatures or conflict with platform security mechanisms such as Intel Boot Guard.
⚠️ 9. Flashing the Development Board with AFU #
Firmware flashing is the highest-risk stage of this workflow.
A failed update can leave the motherboard unable to boot. Use a development board and follow the platform vendor’s approved firmware update procedure.
9.1 Back up the existing firmware #
Before making changes, create a verified backup using the supported method for the board and flash device.
For example, an AFU command may look like:
AFUWINx64.EXE backup.rom /OThe available options depend on the AFU version and platform configuration. Confirm the syntax against the manual supplied with the authorized tool package.
Where possible, keep an additional SPI programmer backup. Verify that the backup file is readable and corresponds to the correct flash device.
9.2 Understand the flash regions #
AFU options such as /P, /B, and /N can refer to different firmware regions, depending on the tool version.
Do not assume that every board supports the same combination.
In particular, flashing NVRAM or other platform-specific regions may overwrite manufacturing data such as serial numbers, MAC addresses, and calibration information.
Use only the update options approved for the target board. A development image that includes an inappropriate NVRAM region can damage the board’s production configuration even if the firmware itself boots successfully.
9.3 Flashing precautions #
Keep these rules in mind:
- Do not interrupt a firmware update. Loss of power during programming can corrupt the flash contents.
- Do not force an unsigned image onto a production platform. Signature enforcement, capsule authentication, and Boot Guard configuration may prevent the update or cause the platform to fail its boot checks.
- Do not overwrite manufacturing data unnecessarily. Preserve NVRAM and platform-specific regions unless the update procedure explicitly requires changing them.
- Keep a recovery method available. Confirm that the board can be recovered using its supported recovery mechanism or an external SPI programmer.
- Verify the exact image and board revision. A firmware image built for a different board revision can cause failures unrelated to the SSDT.
There is no universally safe AFU command line for every Aptio platform. The correct command must come from the board’s firmware update procedure and the matching AFU documentation.
🧰 10. Validate the Installed SSDT #
Once the development board boots successfully, verify that the table was published and that the operating system recognizes the device.
Use multiple independent checks rather than relying on a single tool.
10.1 Firmware-level inspection with RU #
On a compatible platform, RU.EXE can be used to inspect firmware structures and ACPI tables.
Locate the SSDT entry and check its header fields.
For this example, the expected identifiers are:
Signature: SSDT
OEM ID: MYCO
Table ID: SSDTDEMOThe exact RU interface and navigation depend on the version being used.
Seeing the table in firmware memory is evidence that the SSDT was published. It does not by itself prove that all AML objects are valid or that the operating system has successfully enumerated the device.
10.2 Linux: Confirm ACPI device enumeration #
Linux exposes ACPI devices through sysfs.
List the available devices:
ls /sys/bus/acpi/devices/Look for an entry similar to:
MYCO0001:00The exact instance suffix depends on the system.
You can inspect the device directory:
ls -la /sys/bus/acpi/devices/MYCO0001:00/The device should also appear in the ACPI device information available through the kernel.
10.3 Inspect the SSDT table header #
Linux exposes ACPI tables under:
/sys/firmware/acpi/tables/Inspect the SSDT headers:
sudo hexdump -C /sys/firmware/acpi/tables/SSDT* | headThe SSDT signature should begin with:
53 53 44 54Those four bytes correspond to the ASCII characters SSDT.
To inspect the table contents, dump the ACPI tables and disassemble the resulting files:
sudo acpidump -b
iasl -d ssdt*.datSearch the disassembled output:
grep -n "Device (DEMO)" ssdt*.dslUse the actual filenames produced by acpidump; table naming and numbering can vary across systems.
10.4 Check kernel ACPI messages #
Review ACPI-related messages:
dmesg | grep -i acpiLook for namespace collisions, resource conflicts, and AML interpreter errors.
For example, an error such as AE_ALREADY_EXISTS can indicate that the SSDT attempted to define an object that already exists in the namespace.
A table may be present in firmware memory but still contain AML definitions that the operating system cannot load successfully.
10.5 Call a custom method from a Linux driver #
A Linux ACPI driver can evaluate control methods associated with an ACPI device.
For example, a driver matching MYCO0001 could look like this:
static const struct acpi_device_id demo_ids[] = {
{ "MYCO0001", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, demo_ids);
static int demo_probe(struct platform_device *pdev)
{
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
unsigned long long version = 0;
acpi_status status;
if (!adev)
return -ENODEV;
status = acpi_evaluate_integer(
adev->handle,
"RVER",
NULL,
&version
);
if (ACPI_FAILURE(status))
return -EIO;
dev_info(
&pdev->dev,
"DEMO device version: 0x%llx\n",
version
);
return 0;
}This is an illustrative method-evaluation fragment, not a complete Linux driver. The driver’s bus type, registration mechanism, headers, and device matching must agree with the actual platform and kernel configuration.
For a real driver, also validate the return type, error handling, and device lifecycle.
10.6 Windows: Check the device and table #
On Windows, use a compatible ACPI inspection tool to inspect the SSDT and confirm the OEM identifiers.
Then open Device Manager and check whether the device appears with a hardware ID similar to:
ACPI\MYCO0001You can also query devices from an elevated Command Prompt:
pnputil /enum-devices | findstr /i MYCOThe output depends on the Windows version and whether the device is enumerated and exposed through the expected device interface.
🧯 11. Common AMI Aptio and ACPI Integration Problems #
The following issues are worth checking before repeating a firmware build or flash cycle.
| Problem | Likely cause | What to check |
|---|---|---|
Invalid _HID |
Incorrect hardware ID format | Use a valid PNP ID or vendor-defined ID |
| Duplicate module GUID | Copied an existing module without changing its identity | Assign a unique FFS file GUID |
| Module missing from ROM | SDL token disabled or component not registered | Check the project module list and build configuration |
| DXE installer cannot locate ACPI protocol | Dependency expression or dispatch timing is wrong | Verify the protocol GUID and DXS syntax |
| Installer crashes during initialization | AMI library not initialized before using pBS |
Call the required initialization routine |
| SSDT is present but device is missing | _STA reports the device as absent or AML failed to load |
Inspect _STA and kernel ACPI errors |
AE_ALREADY_EXISTS |
Namespace object collision | Check the DSDT and all other SSDTs |
| Resource conflict | _CRS describes an incorrect or overlapping resource |
Verify the actual platform resource allocation |
| Register reads fail | Invalid MMIO mapping, access width, or hardware state | Compare the ASL region with the board register specification |
| Source changes have no effect | Generated AML array was not refreshed | Regenerate SsdtDemoHex.h and rebuild |
| Table is missing at runtime | DXE installer did not execute or installation failed | Add status logging and inspect protocol availability |
| Windows and Linux behave differently | OS-specific ACPI handling or driver expectations | Compare table dumps and OS diagnostics |
11.1 Avoid namespace collisions #
An SSDT shares the system namespace with the DSDT and other SSDTs.
Before choosing a device name, inspect the existing tables. A generic name such as DEMO may already be in use.
Use a project-specific name where appropriate, but remember that namespace uniqueness is not a substitute for correct device identification.
11.2 Keep resource declarations accurate #
A device’s _CRS must describe the resources actually assigned to it.
Declaring an MMIO region in ASL does not reserve that address in the chipset or guarantee that the hardware responds there.
Incorrect resource descriptions can lead to conflicts with other devices or unsafe access to unrelated registers.
11.3 Regenerate AML after every source change #
The firmware installer embeds the compiled AML, not the ASL source.
If SsdtDemo.asl changes but SsdtDemoHex.h does not, the firmware may continue installing an older table.
Make AML regeneration part of the build process whenever possible. This is safer than relying on a manual reminder before every firmware build.
11.4 Do not confuse table installation with hardware initialization #
Installing an SSDT does not initialize the underlying device.
The ASL methods describe how the operating system can interact with the hardware. The hardware itself must already be configured and accessible according to the platform design.
For example, a method that reads an MMIO register assumes that the address is valid and the hardware is in a state where the read is safe.
📋 12. Production Readiness Checklist #
Before integrating the SSDT into a production firmware image, verify each stage.
- The ASL source compiles without errors.
- Warnings and remarks have been reviewed.
- The AML has been disassembled and inspected.
- Host-side tests cover the methods that can be safely simulated.
- The MMIO base address and resource length match the board specification.
_CRSaccurately describes the resources owned by the device.- The ACPI namespace has no duplicate objects.
- The DXE installer uses the correct ACPI Table Protocol.
- The module GUID is unique.
- The module is registered and enabled in the Aptio build system.
- MMTOOL confirms that the installer is present in the expected firmware volume.
- The firmware image has been tested on a recoverable development board.
- The installed SSDT has been inspected after boot.
- Linux and Windows enumeration have been checked where applicable.
- Custom methods and
_DSMbehavior have been tested with the intended driver. - Firmware update and recovery procedures are documented.
🔚 13. Summary #
Adding a custom SSDT to AMI Aptio involves more than writing an ASL file. The table must be compiled, embedded into a DXE installer, registered with the project build system, packaged into the firmware image, and validated after installation.
The complete workflow is:
ASL source
|
v
iasl compilation
|
v
AML inspection and testing
|
v
C-compatible AML array
|
v
AMI DXE installer module
|
v
CIF / DXS / MAK / SDL integration
|
v
Aptio firmware build
|
v
MMTOOL verification
|
v
Controlled firmware update
|
v
RU / Linux / Windows validationThe most important engineering considerations are accurate resource descriptions, unique ACPI namespace objects, correct DXE protocol dependencies, and reliable firmware recovery procedures.
For further background, see ACPI Explained: Architecture, AML, Tables, and Power States and How to Write a UEFI DXE Driver in AMI Aptio 4.
Once the table is correctly integrated and validated, an SSDT provides a maintainable way to expose board-specific hardware and firmware interfaces to the operating system without making unnecessary changes to the platform’s main DSDT.