162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci============= 462306a36Sopenharmony_ciSSDT Overlays 562306a36Sopenharmony_ci============= 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciIn order to support ACPI open-ended hardware configurations (e.g. development 862306a36Sopenharmony_ciboards) we need a way to augment the ACPI configuration provided by the firmware 962306a36Sopenharmony_ciimage. A common example is connecting sensors on I2C / SPI buses on development 1062306a36Sopenharmony_ciboards. 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciAlthough this can be accomplished by creating a kernel platform driver or 1362306a36Sopenharmony_cirecompiling the firmware image with updated ACPI tables, neither is practical: 1462306a36Sopenharmony_cithe former proliferates board specific kernel code while the latter requires 1562306a36Sopenharmony_ciaccess to firmware tools which are often not publicly available. 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciBecause ACPI supports external references in AML code a more practical 1862306a36Sopenharmony_ciway to augment firmware ACPI configuration is by dynamically loading 1962306a36Sopenharmony_ciuser defined SSDT tables that contain the board specific information. 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciFor example, to enumerate a Bosch BMA222E accelerometer on the I2C bus of the 2262306a36Sopenharmony_ciMinnowboard MAX development board exposed via the LSE connector [1], the 2362306a36Sopenharmony_cifollowing ASL code can be used:: 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci DefinitionBlock ("minnowmax.aml", "SSDT", 1, "Vendor", "Accel", 0x00000003) 2662306a36Sopenharmony_ci { 2762306a36Sopenharmony_ci External (\_SB.I2C6, DeviceObj) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci Scope (\_SB.I2C6) 3062306a36Sopenharmony_ci { 3162306a36Sopenharmony_ci Device (STAC) 3262306a36Sopenharmony_ci { 3362306a36Sopenharmony_ci Name (_HID, "BMA222E") 3462306a36Sopenharmony_ci Name (RBUF, ResourceTemplate () 3562306a36Sopenharmony_ci { 3662306a36Sopenharmony_ci I2cSerialBus (0x0018, ControllerInitiated, 0x00061A80, 3762306a36Sopenharmony_ci AddressingMode7Bit, "\\_SB.I2C6", 0x00, 3862306a36Sopenharmony_ci ResourceConsumer, ,) 3962306a36Sopenharmony_ci GpioInt (Edge, ActiveHigh, Exclusive, PullDown, 0x0000, 4062306a36Sopenharmony_ci "\\_SB.GPO2", 0x00, ResourceConsumer, , ) 4162306a36Sopenharmony_ci { // Pin list 4262306a36Sopenharmony_ci 0 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci }) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci Method (_CRS, 0, Serialized) 4762306a36Sopenharmony_ci { 4862306a36Sopenharmony_ci Return (RBUF) 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciwhich can then be compiled to AML binary format:: 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci $ iasl minnowmax.asl 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci Intel ACPI Component Architecture 5962306a36Sopenharmony_ci ASL Optimizing Compiler version 20140214-64 [Mar 29 2014] 6062306a36Sopenharmony_ci Copyright (c) 2000 - 2014 Intel Corporation 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ASL Input: minnomax.asl - 30 lines, 614 bytes, 7 keywords 6362306a36Sopenharmony_ci AML Output: minnowmax.aml - 165 bytes, 6 named objects, 1 executable opcodes 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci[1] https://www.elinux.org/Minnowboard:MinnowMax#Low_Speed_Expansion_.28Top.29 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciThe resulting AML code can then be loaded by the kernel using one of the methods 6862306a36Sopenharmony_cibelow. 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciLoading ACPI SSDTs from initrd 7162306a36Sopenharmony_ci============================== 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciThis option allows loading of user defined SSDTs from initrd and it is useful 7462306a36Sopenharmony_ciwhen the system does not support EFI or when there is not enough EFI storage. 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciIt works in a similar way with initrd based ACPI tables override/upgrade: SSDT 7762306a36Sopenharmony_ciAML code must be placed in the first, uncompressed, initrd under the 7862306a36Sopenharmony_ci"kernel/firmware/acpi" path. Multiple files can be used and this will translate 7962306a36Sopenharmony_ciin loading multiple tables. Only SSDT and OEM tables are allowed. See 8062306a36Sopenharmony_ciinitrd_table_override.txt for more details. 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciHere is an example:: 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci # Add the raw ACPI tables to an uncompressed cpio archive. 8562306a36Sopenharmony_ci # They must be put into a /kernel/firmware/acpi directory inside the 8662306a36Sopenharmony_ci # cpio archive. 8762306a36Sopenharmony_ci # The uncompressed cpio archive must be the first. 8862306a36Sopenharmony_ci # Other, typically compressed cpio archives, must be 8962306a36Sopenharmony_ci # concatenated on top of the uncompressed one. 9062306a36Sopenharmony_ci mkdir -p kernel/firmware/acpi 9162306a36Sopenharmony_ci cp ssdt.aml kernel/firmware/acpi 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci # Create the uncompressed cpio archive and concatenate the original initrd 9462306a36Sopenharmony_ci # on top: 9562306a36Sopenharmony_ci find kernel | cpio -H newc --create > /boot/instrumented_initrd 9662306a36Sopenharmony_ci cat /boot/initrd >>/boot/instrumented_initrd 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciLoading ACPI SSDTs from EFI variables 9962306a36Sopenharmony_ci===================================== 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciThis is the preferred method, when EFI is supported on the platform, because it 10262306a36Sopenharmony_ciallows a persistent, OS independent way of storing the user defined SSDTs. There 10362306a36Sopenharmony_ciis also work underway to implement EFI support for loading user defined SSDTs 10462306a36Sopenharmony_ciand using this method will make it easier to convert to the EFI loading 10562306a36Sopenharmony_cimechanism when that will arrive. To enable it, the 10662306a36Sopenharmony_ciCONFIG_EFI_CUSTOM_SSDT_OVERLAYS should be chosen to y. 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciIn order to load SSDTs from an EFI variable the ``"efivar_ssdt=..."`` kernel 10962306a36Sopenharmony_cicommand line parameter can be used (the name has a limitation of 16 characters). 11062306a36Sopenharmony_ciThe argument for the option is the variable name to use. If there are multiple 11162306a36Sopenharmony_civariables with the same name but with different vendor GUIDs, all of them will 11262306a36Sopenharmony_cibe loaded. 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciIn order to store the AML code in an EFI variable the efivarfs filesystem can be 11562306a36Sopenharmony_ciused. It is enabled and mounted by default in /sys/firmware/efi/efivars in all 11662306a36Sopenharmony_cirecent distribution. 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciCreating a new file in /sys/firmware/efi/efivars will automatically create a new 11962306a36Sopenharmony_ciEFI variable. Updating a file in /sys/firmware/efi/efivars will update the EFI 12062306a36Sopenharmony_civariable. Please note that the file name needs to be specially formatted as 12162306a36Sopenharmony_ci"Name-GUID" and that the first 4 bytes in the file (little-endian format) 12262306a36Sopenharmony_cirepresent the attributes of the EFI variable (see EFI_VARIABLE_MASK in 12362306a36Sopenharmony_ciinclude/linux/efi.h). Writing to the file must also be done with one write 12462306a36Sopenharmony_cioperation. 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciFor example, you can use the following bash script to create/update an EFI 12762306a36Sopenharmony_civariable with the content from a given file:: 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci #!/bin/sh -e 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci while [ -n "$1" ]; do 13262306a36Sopenharmony_ci case "$1" in 13362306a36Sopenharmony_ci "-f") filename="$2"; shift;; 13462306a36Sopenharmony_ci "-g") guid="$2"; shift;; 13562306a36Sopenharmony_ci *) name="$1";; 13662306a36Sopenharmony_ci esac 13762306a36Sopenharmony_ci shift 13862306a36Sopenharmony_ci done 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci usage() 14162306a36Sopenharmony_ci { 14262306a36Sopenharmony_ci echo "Syntax: ${0##*/} -f filename [ -g guid ] name" 14362306a36Sopenharmony_ci exit 1 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci [ -n "$name" -a -f "$filename" ] || usage 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci EFIVARFS="/sys/firmware/efi/efivars" 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci [ -d "$EFIVARFS" ] || exit 2 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if stat -tf $EFIVARFS | grep -q -v de5e81e4; then 15362306a36Sopenharmony_ci mount -t efivarfs none $EFIVARFS 15462306a36Sopenharmony_ci fi 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci # try to pick up an existing GUID 15762306a36Sopenharmony_ci [ -n "$guid" ] || guid=$(find "$EFIVARFS" -name "$name-*" | head -n1 | cut -f2- -d-) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci # use a randomly generated GUID 16062306a36Sopenharmony_ci [ -n "$guid" ] || guid="$(cat /proc/sys/kernel/random/uuid)" 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci # efivarfs expects all of the data in one write 16362306a36Sopenharmony_ci tmp=$(mktemp) 16462306a36Sopenharmony_ci /bin/echo -ne "\007\000\000\000" | cat - $filename > $tmp 16562306a36Sopenharmony_ci dd if=$tmp of="$EFIVARFS/$name-$guid" bs=$(stat -c %s $tmp) 16662306a36Sopenharmony_ci rm $tmp 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciLoading ACPI SSDTs from configfs 16962306a36Sopenharmony_ci================================ 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciThis option allows loading of user defined SSDTs from user space via the configfs 17262306a36Sopenharmony_ciinterface. The CONFIG_ACPI_CONFIGFS option must be select and configfs must be 17362306a36Sopenharmony_cimounted. In the following examples, we assume that configfs has been mounted in 17462306a36Sopenharmony_ci/sys/kernel/config. 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciNew tables can be loading by creating new directories in /sys/kernel/config/acpi/table 17762306a36Sopenharmony_ciand writing the SSDT AML code in the aml attribute:: 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci cd /sys/kernel/config/acpi/table 18062306a36Sopenharmony_ci mkdir my_ssdt 18162306a36Sopenharmony_ci cat ~/ssdt.aml > my_ssdt/aml 182