Debunking Myths Part 1

Today I like to debunk a persistent myth, being that you can override objects in the DSDT, or an already loaded SSDT, from a Secondary System Description Table, but that is simply not true. Let’s start with a blurb taken from the ACPI specification:

Additional tables can only add data; they cannot overwrite data from previous tables.

You can find this line on page 23 of the ACPI 5.0 specification, and the plain simple explanation is that you cannot override an already defined object.

What you can do is extract the DSDT and change the object data, or remove/rename it and then add it with the correct value/data from a Secondary System Description Table.

And to demonstrate that it doesn’t work. That you cannot override already defined objects, I’ve come up with a simple SSDT example. Something that most of you will want to try anyway, but I am not going to explain you why you want to use it. I mean. If I need to explain that to you, then you wouldn’t know what to do with it.

DefinitionBlock ("ssdt.aml", "SSDT", 1, "APPLE ", "general", 0x00001000)
{
    External (\_PR.CPU1, DeviceObj)

    Scope (\_PR)
    {
        //
        // Define a Processor scope ACPI PPM GlobalNvs NVS Region
        //
        // Note: Change the memory location to the one for your (U)EFI/BIOS!
        //
        OperationRegion(PPMT, SystemMemory, 0xDCBC0F18, 0x0029)
        Field (PPMT, AnyAcc, Lock, Preserve)
        {
            PGRV,    8,         // (0) PPM GlobalNvs Revision
                     Offset(6), // (1-5) Reserved
            //
            // Thermal Configuration Values
            //
            ACRT,    8,         // (6) Auto Critical Trip Point
            APSV,    8,         // (7) Auto Passive Trip Point
            AAC0,    8,         // (8) Auto Active Trip Point
            CPID,    32,        // (9) CPUID
            //
            // ConfigTDP Value
            //
            CPPC,    8,         // (13) Boot Mode values for _PPC
            //
            // ConfigTDP Level settings
            //
            CCTP,    8,         // (14) Custom ConfigTdp Enabled/Disabled
            CLVL,    8,         // (15) ConfigTdp Number Of Levels
            CBMI,    8,         // (16) CTDP Boot Mode Index
            PL10,    16,        // (17) CTDP Level 0 Power Limit1
            PL20,    16,        // (19) CTDP Level 0 Power Limit2
            PLW0,    8,         // (21) CTDP Level 0 Power Limit1 Time Window
            CTC0,    8,         // (22) CTDP Level 0 CTC
            TAR0,    8,         // (23) CTDP Level 0 TAR
            PPC0,    8,         // (24) CTDP Level 0 PPC
            PL11,    16,        // (25) CTDP Level 1 Power Limit1
            PL21,    16,        // (27) CTDP Level 1 Power Limit2
            PLW1,    8,         // (29) CTDP Level 1 Power Limit1 Time Window
            CTC1,    8,         // (30) CTDP Level 1 CTC
            TAR1,    8,         // (31) CTDP Level 1 TAR
            PPC1,    8,         // (32) CTDP Level 1 PPC
            PL12,    16,        // (33) CTDP Level 2 Power Limit1
            PL22,    16,        // (35) CTDP Level 2 Power Limit2
            PLW2,    8,         // (37) CTDP Level 2 Power Limit1 Time Window
            CTC2,    8,         // (38) CTDP Level 2 CTC
            TAR2,    8,         // (39) CTDP Level 2 TAR
            PPC2,    8          // (40) CTDP Level 2 PPC
        }

        Scope (\_PR.CPU1)
        {
            Method (_DSM, 4, NotSerialized)
            {
                If (LEqual (Arg2, Zero))
                {
                    Return (Buffer (One) { 0x03 })
                }

                Return (Package (0x36)
                {
                    "PGRV",
                     PGRV,
                    "ACRT",
                     ACRT,
                    "APSV",
                     APSV,
                    "AAC0",
                     AAC0,
                    "CPID",
                     CPID,
                    "CPPC",
                     CPPC,
                    "CCTP",
                     CCTP,
                    "CLVL",
                     CLVL,
                    "CBMI",
                     CBMI,
                    "PL10",
                     PL10,
                    "PL20",
                     PL20,
                    "PLW0",
                     PLW0,
                    "CTC0",
                     CTC0,
                    "TAR0",
                     TAR0,
                    "PPC0",
                     PPC0,
                    "PL11",
                     PL11,
                    "PL21",
                     PL21,
                    "PLW1",
                     PLW1,
                    "CTC1",
                     CTC1,
                    "TAR1",
                     TAR1,
                    "PPC1",
                     PPC1,
                    "PL12",
                     PL12,
                    "PL22",
                     PL22,
                    "PLW2",
                     PLW2,
                    "CTC2",
                     CTC2,
                    "TAR2",
                     TAR2,
                    "PPC2",
                     PPC2,
                })
            }
        }
    }
}

Note: Most people probably need to rename the file to something like SSDT-N.aml – where N is a number between 1 and 30 – or the boot loader (Chameleon, Chimera and Clover) won’t be able to load the file. I don’t have to do this, because I use RevoBoot and use ssdt_usb.aml instead (one of the predefined/supported ACPI table identifiers).

Ok so there you have it. A simple ACPI table (SSDT) with an object called PPMT in it, and when you don’t drop the factory SSDT’s then the ACPI parser will skip it. This because this object is already defined, in most cases. Meaning that while the SSDT can be found in IORegistryExplorer and ioreg (is loaded) the AML parser won’t add the object to the AML namespace – read AML linked node list (EAML) – and as a result… the values from PPMT won’t be there under CPU1. Like it’s not “executed”. Which is true, because the ACPI interpreter will simply ignore it.

Tip: Check the value of CPID which should be something like 0x206AX for Sandy Bridge and 0x306AX for Ivy Bridge processors. This way you know that the memory location for PPMT is correct – extracting your ACPI tables with help of MacIASL is therefore strongly recommended.

2 thoughts on “Debunking Myths Part 1

  1. Where did you find all this objects name descriptions (like ACRT=Auto Critical Trip Point) ?
    Are you editing your posts ? it is second time when I read your post twice and I’m confused 🙂

    • I use the AMI/Intel source code as my reference and thus that is where the info is coming from.

      And yes. I did add the note about RevoBoot and the tip section after my initial commit, due to guests arriving with new hardware (dimastech test bench). Forcing me to rush things a little.

Leave a comment