Creating a Custom SSDT for Legacy Hackintosh LPC, SMBus, and GPIO Controllers

Step-by-step guide to creating a custom SSDT to fix device-id issues on Intel 6-series, 7-series, and X79 chipsets for macOS 10.9–10.15.

When debugging sleep, USB, or power management on a legacy Hackintosh, the fourth or fifth ACPI table you extract often reveals the root cause. The DSDT is huge; patching it systematically is impractical. SSDTs—Secondary System Description Tables—are where Apple’s firmware engineers isolate discrete hardware features. For a user-built system running macOS 10.9 through 10.15, creating a custom SSDT is the most precise way to inject properties, rename devices, or fix IRQ conflicts without touching the DSDT. This guide assumes you have already dumped your native ACPI tables with Clover’s F4 key or OpenCore’s SysReport quirk and are comfortable reading a basic ASL file.

Why a Third SSDT Guide?

Most Hackintosh guides cover SSDTs for CPU power management and USB injection. This one focuses on a specific scenario that most guides skip: creating a small SSDT to override a device that macOS misidentifies during early boot, specifically for legacy LPC, SMBus, and GPIO controllers on Intel 6-series, 7-series, and X79 chipsets. These controllers don’t show up in IORegistryExplorer until after the ACPI tables are loaded, and a wrong device-id can prevent sleep or cause a kernel panic at wake.

Tools and Prerequisites

  • MaciASL (version 1.6 or newer) — the only ASL compiler/editor I’d trust for legacy tables. Don’t use iASL from a random GitHub fork without verifying the checksum.
  • IORegistryExplorer (v2.1 or v3.0) — to confirm device paths after patching.
  • Property List editors — Xcode or PlistEdit Pro for embedding an SSDT into your bootloader config.
  • Backup of your current EFI partition — copy the entire EFI folder to another drive before injecting any new table. A single wrong SSDT can prevent the system from reaching the boot picker.

Step 1: Identify the Target Device Path

Boot your Hackintosh with the native tables loaded (no custom SSDTs). Open IORegistryExplorer and search for the device class you want to patch—for example, AppleLPC or SMBUS. If the device is not present, search for LPC or SMB0 under the PCI0 tree. Note the full ACPI path, such as _SB.PCI0.LPCB or _SB.PCI0.SBUS. Write down the current device-id and vendor-id as seen in the IORegistry entry (under the device-id and vendor-id properties, usually in hex).

For a Sandy Bridge system (e.g., Z68 chipset) the LPC controller often shows a device-id of 0x1C44 (Intel Cougar Point). macOS expects 0x1C46 or 0x1C4A to load the correct AppleLPC kext. If yours is different, you need an SSDT to fake the device-id.

Step 2: Create the SSDT Skeleton

Open MaciASL and create a new document. Set the ACPI version to 1.0 (legacy tables are often 32-bit). Use the following minimal template—don’t add unnecessary scope blocks or external references until you know they exist in your native tables.

DefinitionBlock ("", "SSDT", 1, "HACK", "LPC", 0x00000001)
{
    External (_SB_.PCI0, DeviceObj)

    Scope (_SB.PCI0)
    {
        Device (LPCB)
        {
            Name (_ADR, 0x001F0000)
            Method (_DSM, 4, NotSerialized)
            {
                If (LEqual (Arg2, Zero))
                {
                    Return (Buffer (One, 0x03))
                }

                Return (Package ()
                {
                    "device-id", Buffer ()
                    {
                        0x46, 0x1C, 0x00, 0x00
                    },
                    "vendor-id", Buffer ()
                    {
                        0x86, 0x80, 0x00, 0x00
                    }
                })
            }
        }
    }
}

Replace the _ADR with the correct address for your chipset. For LPC on a 6-series, it is usually 0x001F0000. For SMBus, look for _ADR 0x001F0003. The device-id buffer is in little-endian format: two bytes for the ID, then two zeroes. In the example above, 0x46, 0x1C corresponds to device-id 0x1C46. Verify against your chipset’s datasheet.

Step 3: Compile and Verify

Press compile in MaciASL. If you see warnings about missing external references, add an External statement for every object the compiler complains about—but only if you are certain it exists in your native DSDT. Don’t blindly add External for devices that don’t exist; macOS will reject the table at boot. For a typical Z77 system, you might need:

External (_SB_.PCI0.LPCB, DeviceObj)
External (_SB_.PCI0.LPCB.HPET, DeviceObj)

After compilation succeeds, save the file as SSDT-LPC.aml (not .dsl). Place it in EFI/OC/ACPI (for OpenCore) or EFI/CLOVER/ACPI/patched (for Clover). Add the table to your config.plist under ACPI -> Add with the correct path and enable it. Reboot.

Step 4: Validate in IORegistryExplorer

After reboot, open IORegistryExplorer and locate the same device path. The device-id property should now show your injected value. If you patched LPC, check that AppleLPC is loaded under AppleACPIPlatformExpert. If the kext doesn’t load, your device-id might still be incorrect, or the SSDT isn’t being parsed. Enable ACPI debugging in your bootloader (set syscl debug level) and check the kernel log for ACPI table or SSDT entries.

Common Pitfalls on X79 and C600 Series

X79 chipset (Sandy Bridge-E / Ivy Bridge-E) has a different LPC address—0x001F0000 still applies, but the device-id range is 0x1D40 through 0x1D41. macOS expects 0x1D41 for AppleLPC. Injecting the wrong ID causes a panic at wake from sleep. Additionally, the SMBus controller on X79 is at _ADR 0x001F0004, not 0x001F0003. Double-check your board’s datasheet or dump the DSDT and search for SMB0 to confirm the address.

When Not to Use an SSDT

Some devices, like the HDEF (High Definition Audio) or GFX0, are better patched via DeviceProperties in the bootloader config, because the SSDT approach can conflict with the bootloader’s own injection order. If you already have a working audio layout-id injected via Clover or OpenCore, don’t duplicate it in an SSDT. The SSDT method is safest for devices that macOS cannot see at all until the ACPI tables are loaded—typically LPC, SMBus, and GPIO controllers.

Integrating with iMessage and iCloud Configurations

If your legacy Hackintosh relies on a patched ACPI table for power management, be aware that changing the SSDT can affect the system’s SMBIOS UUID consistency. After injecting a new SSDT, regenerate your SystemSerialNumber and MLB in the bootloader config, then re-login to iMessage. A mismatch between the old and new ACPI tables can cause Apple’s servers to flag the device as changed. For a detailed walkthrough of the iMessage activation process on older systems, refer to our guide on How to Get iCloud and iMessage Working on Legacy Hackintosh (X79, X99, Z77).

Preserving Your Configuration

Once the SSDT works, document the exact device-id, the macOS version, and the bootloader revision. Store the .dsl source file alongside the .aml in a separate folder on your backup drive. A year from now, when you update to a newer bootloader or a different macOS build, you will need to recompile the SSDT with the same iASL version to avoid bit-rot. Legacy tables compiled with iASL 2018 or earlier may fail to load on newer firmware due to minor ACPI specification changes.

If you encounter a kernel panic immediately after adding the SSDT, boot with -s (single-user mode) and remove the table from the EFI partition using the shell. Always keep a copy of your working EFI on a USB stick before testing any new ACPI injection. The SSDT method is powerful, but one misplaced byte in the device-id buffer can lock you out of your system until you physically remove the drive or boot from another volume.