⬢ DragonFlyBSD Kernel Audit
DF-5619 / mkdsdt.py
← back to finding ↓ download raw
#!/usr/bin/env python3
"""
mkdsdt.py -- emit a DSDT DSL with 6 Processor objects each carrying a scenario
_CST package (DF-5619 / DF-5620 verification).

_CST GAS buffer layout demanded by DragonFly acpi_PkgRawGas()
(sys/dev/acpica/acpi_package.c:120-129):
  Buffer.Length >= sizeof(ACPI_GENERIC_ADDRESS)+3; GAS memcpy'd from +3.
ACPI_GENERIC_ADDRESS is packed in ACPICA (12 bytes):
  u8 SpaceId, u8 BitWidth, u8 BitOffset, u8 AccessWidth, u64 Address
=> buffer bytes: [pad3][SpaceId][BitWidth][BitOffset][AccessWidth]
                 [Address LE u64][tail]   (19 bytes total)

GAS encodings used here:
  control C1      : SystemMemory(0)/8/0/0 addr 0   (content ignored for C1:
                    the parser never reads element 0 for C1 -- enter is
                    hardwired to acpi_cst_c1_halt_enter)
  nullenter C2    : SystemIO(1)/8/0/0 addr 0   -> acpi_bus_alloc_gas EINVAL
  zerostate C2    : FixedHW(0x7F)/8/0/0 addr 0 -> md mwait path EOPNOTSUPP
  badhint  C2     : FixedHW(0x7F)/1/2/0 addr 0x99999971
                    (Intel FFH _CST encoding: BitWidth=vendor(Intel),
                     BitOffset=class(CX_NATIVE), Address=arg0 mwait hint;
                     hint 0x...71 -> MWAIT_EAX_TO_CX = 8 >= CPU_MWAIT_CX_MAX)
"""
import sys

GAS_TAIL = '0x00, 0x00, 0x00, 0x00'   # bytes 15..18 (tail)


def gas(space, width, off, acc, addr):
    a = addr & 0xFFFFFFFFFFFFFFFF
    b = [(a >> (8 * i)) & 0xFF for i in range(8)]
    return ('0x00, 0x00, 0x00, '
            '0x%02x, 0x%02x, 0x%02x, 0x%02x, '
            '0x%02x, 0x%02x, 0x%02x, 0x%02x, '
            '0x%02x, 0x%02x, 0x%02x, 0x%02x, '
            '%s' % (space, width, off, acc,
                    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
                    GAS_TAIL))


def state(gasbuf, ctype, lat, pw):
    return ('Package (0x04)\n'
            '                {\n'
            '                    Buffer (0x13) { %s },\n'
            '                    0x%02x, 0x%04x, 0x%04x\n'
            '                }' % (gasbuf, ctype, lat, pw))


def cst(states):
    return ('Name (_CST, Package (0x%02x)\n'
            '                {\n'
            '                    0x%02x,\n'
            '                    %s\n'
            '                })'
            % (len(states) + 1, len(states),
               ',\n                    '.join(states)))


SCEN = {
    # one valid C1 (HALT) state -- boots, cx_supported "C1/1"
    'control': cst([state(gas(0x00, 8, 0, 0, 0), 1, 1, 1000)]),
    # one C2 SystemIO/addr0 -- accepted with enter==NULL -> idle NULL call
    'nullenter': cst([state(gas(0x01, 8, 0, 0, 0), 2, 10, 1000)]),
    # one C2 FixedHW -- EOPNOTSUPP skipped -> probe "succeeds" with 0 states
    'zerostate': cst([state(gas(0x7F, 8, 0, 0, 0), 2, 10, 1000)]),
    # valid C1 + rejected C2 FFH w/ invalid mwait hint 0x99999971 (DF-5620)
    'badhint': cst([state(gas(0x00, 8, 0, 0, 0), 1, 1, 1000),
                    state(gas(0x7F, 1, 2, 0, 0x99999971), 2, 10, 1000)]),
}


def main():
    scen, out = sys.argv[1], sys.argv[2]
    body = SCEN[scen]
    procs = []
    for i in range(6):
        procs.append(
            '            Processor (C%03d, 0x%02x, 0x00000000, 0x00)\n'
            '            {\n'
            '                %s\n'
            '            }' % (i, i, body))
    dsdt = ('DefinitionBlock ("", "DSDT", 2, "TST", "DSDT", 0x00000001)\n'
            '{\n'
            '    Scope (\\_SB)\n'
            '    {\n'
            '%s\n'
            '    }\n'
            '}\n' % '\n\n'.join(procs))
    with open(out, 'w') as f:
        f.write(dsdt)
    sys.stderr.write('%s -> %s (%d bytes)\n' % (scen, out, len(dsdt)))


if __name__ == '__main__':
    main()