^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) .. SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) =============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) SSDT Overlays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) =============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) In order to support ACPI open-ended hardware configurations (e.g. development
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) boards) we need a way to augment the ACPI configuration provided by the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) image. A common example is connecting sensors on I2C / SPI buses on development
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) boards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) Although this can be accomplished by creating a kernel platform driver or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) recompiling the firmware image with updated ACPI tables, neither is practical:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) the former proliferates board specific kernel code while the latter requires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) access to firmware tools which are often not publicly available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) Because ACPI supports external references in AML code a more practical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) way to augment firmware ACPI configuration is by dynamically loading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) user defined SSDT tables that contain the board specific information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) For example, to enumerate a Bosch BMA222E accelerometer on the I2C bus of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) Minnowboard MAX development board exposed via the LSE connector [1], the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) following ASL code can be used::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) DefinitionBlock ("minnowmax.aml", "SSDT", 1, "Vendor", "Accel", 0x00000003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) External (\_SB.I2C6, DeviceObj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) Scope (\_SB.I2C6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) Device (STAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) Name (_ADR, Zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) Name (_HID, "BMA222E")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) Method (_CRS, 0, Serialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) Name (RBUF, ResourceTemplate ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) I2cSerialBus (0x0018, ControllerInitiated, 0x00061A80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) AddressingMode7Bit, "\\_SB.I2C6", 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ResourceConsumer, ,)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) GpioInt (Edge, ActiveHigh, Exclusive, PullDown, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) "\\_SB.GPO2", 0x00, ResourceConsumer, , )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { // Pin list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) Return (RBUF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) which can then be compiled to AML binary format::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) $ iasl minnowmax.asl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) Intel ACPI Component Architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ASL Optimizing Compiler version 20140214-64 [Mar 29 2014]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) Copyright (c) 2000 - 2014 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ASL Input: minnomax.asl - 30 lines, 614 bytes, 7 keywords
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) AML Output: minnowmax.aml - 165 bytes, 6 named objects, 1 executable opcodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) [1] https://www.elinux.org/Minnowboard:MinnowMax#Low_Speed_Expansion_.28Top.29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) The resulting AML code can then be loaded by the kernel using one of the methods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) Loading ACPI SSDTs from initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ==============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) This option allows loading of user defined SSDTs from initrd and it is useful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) when the system does not support EFI or when there is not enough EFI storage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) It works in a similar way with initrd based ACPI tables override/upgrade: SSDT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) aml code must be placed in the first, uncompressed, initrd under the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) "kernel/firmware/acpi" path. Multiple files can be used and this will translate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) in loading multiple tables. Only SSDT and OEM tables are allowed. See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) initrd_table_override.txt for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) Here is an example::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) # Add the raw ACPI tables to an uncompressed cpio archive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) # They must be put into a /kernel/firmware/acpi directory inside the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) # cpio archive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) # The uncompressed cpio archive must be the first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) # Other, typically compressed cpio archives, must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) # concatenated on top of the uncompressed one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) mkdir -p kernel/firmware/acpi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) cp ssdt.aml kernel/firmware/acpi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) # Create the uncompressed cpio archive and concatenate the original initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) # on top:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) find kernel | cpio -H newc --create > /boot/instrumented_initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) cat /boot/initrd >>/boot/instrumented_initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) Loading ACPI SSDTs from EFI variables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) =====================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) This is the preferred method, when EFI is supported on the platform, because it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) allows a persistent, OS independent way of storing the user defined SSDTs. There
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) is also work underway to implement EFI support for loading user defined SSDTs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) and using this method will make it easier to convert to the EFI loading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) mechanism when that will arrive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) In order to load SSDTs from an EFI variable the efivar_ssdt kernel command line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) parameter can be used. The argument for the option is the variable name to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) use. If there are multiple variables with the same name but with different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) vendor GUIDs, all of them will be loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) In order to store the AML code in an EFI variable the efivarfs filesystem can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) used. It is enabled and mounted by default in /sys/firmware/efi/efivars in all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) recent distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) Creating a new file in /sys/firmware/efi/efivars will automatically create a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) EFI variable. Updating a file in /sys/firmware/efi/efivars will update the EFI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) variable. Please note that the file name needs to be specially formatted as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "Name-GUID" and that the first 4 bytes in the file (little-endian format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) represent the attributes of the EFI variable (see EFI_VARIABLE_MASK in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) include/linux/efi.h). Writing to the file must also be done with one write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) For example, you can use the following bash script to create/update an EFI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) variable with the content from a given file::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #!/bin/sh -e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) while ! [ -z "$1" ]; do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case "$1" in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "-f") filename="$2"; shift;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "-g") guid="$2"; shift;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *) name="$1";;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) esac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) usage()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) echo "Syntax: ${0##*/} -f filename [ -g guid ] name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) exit 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [ -n "$name" -a -f "$filename" ] || usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) EFIVARFS="/sys/firmware/efi/efivars"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) [ -d "$EFIVARFS" ] || exit 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if stat -tf $EFIVARFS | grep -q -v de5e81e4; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mount -t efivarfs none $EFIVARFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) # try to pick up an existing GUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [ -n "$guid" ] || guid=$(find "$EFIVARFS" -name "$name-*" | head -n1 | cut -f2- -d-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) # use a randomly generated GUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) [ -n "$guid" ] || guid="$(cat /proc/sys/kernel/random/uuid)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) # efivarfs expects all of the data in one write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) tmp=$(mktemp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /bin/echo -ne "\007\000\000\000" | cat - $filename > $tmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dd if=$tmp of="$EFIVARFS/$name-$guid" bs=$(stat -c %s $tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rm $tmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) Loading ACPI SSDTs from configfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) This option allows loading of user defined SSDTs from userspace via the configfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) interface. The CONFIG_ACPI_CONFIGFS option must be select and configfs must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mounted. In the following examples, we assume that configfs has been mounted in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /config.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) New tables can be loading by creating new directories in /config/acpi/table/ and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) writing the SSDT aml code in the aml attribute::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) cd /config/acpi/table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) mkdir my_ssdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) cat ~/ssdt.aml > my_ssdt/aml