diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 000000000000..3d756b2dbda7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,18 @@ +--- +name: Question / Support +about: I have a question... +title: '' +labels: '' +assignees: '' + +--- + +# STOP! READ BELOW. + +We do not field questions or feature requests by Github Issues! + +Questions or feature requests should be discussed on the mailing list or +Discord. Please see https://github.com/openbmc/openbmc#contact for info +on how to contact us. + +Github Issues in openbmc/openbmc are for bugs only! diff --git a/.templateconf b/.templateconf deleted file mode 100644 index 7809580f0007..000000000000 --- a/.templateconf +++ /dev/null @@ -1 +0,0 @@ -TEMPLATECONF=${TEMPLATECONF:-meta-phosphor/conf} diff --git a/.templateconf b/.templateconf new file mode 120000 index 000000000000..b4266c040b97 --- /dev/null +++ b/.templateconf @@ -0,0 +1 @@ +poky/.templateconf \ No newline at end of file diff --git a/README.md b/README.md index 4b257e3c5a76..03db4e4323c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OpenBMC -[![Build Status](https://openpower.xyz/buildStatus/icon?job=openbmc-build)](https://openpower.xyz/job/openbmc-build/) +[![Build Status](https://jenkins.openbmc.org/buildStatus/icon?job=latest-master)](https://jenkins.openbmc.org/job/latest-master/) OpenBMC is a Linux distribution for management controllers used in devices such as servers, top of rack switches or RAID appliances. It uses @@ -14,66 +14,72 @@ customization for your platform. ### 1) Prerequisite -See the [Yocto documentation](https://docs.yoctoproject.org/ref-manual/system-requirements.html#required-packages-for-the-build-host) +See the +[Yocto documentation](https://docs.yoctoproject.org/ref-manual/system-requirements.html#required-packages-for-the-build-host) for the latest requirements #### Ubuntu -``` -$ sudo apt install git python3-distutils gcc g++ make file wget \ + +```sh +sudo apt install git python3-distutils gcc g++ make file wget \ gawk diffstat bzip2 cpio chrpath zstd lz4 bzip2 ``` #### Fedora -``` -$ sudo dnf install git python3 gcc g++ gawk which bzip2 chrpath cpio -hostname file diffutils diffstat lz4 wget zstd rpcgen patch + +```sh +sudo dnf install git python3 gcc g++ gawk which bzip2 chrpath cpio \ + hostname file diffutils diffstat lz4 wget zstd rpcgen patch ``` ### 2) Download the source -``` + +```sh git clone https://github.com/openbmc/openbmc cd openbmc ``` ### 3) Target your hardware + Any build requires an environment set up according to your hardware target. -There is a special script in the root of this repository that can be used -to configure the environment as needed. The script is called `setup` and -takes the name of your hardware target as an argument. +There is a special script in the root of this repository that can be used to +configure the environment as needed. The script is called `setup` and takes the +name of your hardware target as an argument. The script needs to be sourced while in the top directory of the OpenBMC -repository clone, and, if run without arguments, will display the list -of supported hardware targets, see the following example: +repository clone, and, if run without arguments, will display the list of +supported hardware targets, see the following example: -``` +```text $ . setup [build_dir] Target machine must be specified. Use one of: -bletchley mihawk swift -dl360poc mori tatlin-archive-x86 -e3c246d4i mtjade tiogapass -ethanolx nicole transformers -evb-ast2500 olympus-nuvoton vegman-n110 -evb-ast2600 on5263m5 vegman-rx20 -evb-npcm750 p10bmc vegman-sx20 -f0b palmetto witherspoon -fp5280g2 quanta-q71l witherspoon-tacoma -g220a romulus x11spi -gbs s2600wf yosemitev2 -gsj s6q zaius -kudo s7106 -lannister s8036 +bletchley mori s8036 +dl360poc mtjade swift +e3c246d4i mtmitchell tatlin-archive-x86 +ethanolx nicole tiogapass +evb-ast2500 olympus-nuvoton transformers +evb-ast2600 on5263m5 vegman-n110 +evb-npcm750 p10bmc vegman-rx20 +f0b palmetto vegman-sx20 +fp5280g2 qcom-dc-scm-v1 witherspoon +g220a quanta-q71l witherspoon-tacoma +gbs romed8hm3 x11spi +greatlakes romulus yosemitev2 +gsj s2600wf zaius +kudo s6q +lannister s7106 ``` Once you know the target (e.g. romulus), source the `setup` script as follows: -``` +```sh . setup romulus ``` ### 4) Build -``` +```sh bitbake obmc-phosphor-image ``` @@ -82,38 +88,40 @@ repository. ## OpenBMC Development -The OpenBMC community maintains a set of tutorials new users can go through -to get up to speed on OpenBMC development out +The OpenBMC community maintains a set of tutorials new users can go through to +get up to speed on OpenBMC development out [here](https://github.com/openbmc/docs/blob/master/development/README.md) ## Build Validation and Testing + Commits submitted by members of the OpenBMC GitHub community are compiled and tested via our [Jenkins](https://jenkins.openbmc.org/) server. Commits are run -through two levels of testing. At the repository level the makefile `make -check` directive is run. At the system level, the commit is built into a -firmware image and run with an arm-softmmu QEMU model against a barrage of -[CI tests](https://openpower.xyz/job/openbmc-test-qemu-ci/). +through two levels of testing. At the repository level the makefile `make check` +directive is run. At the system level, the commit is built into a firmware image +and run with an arm-softmmu QEMU model against a barrage of +[CI tests](https://jenkins.openbmc.org/job/CI-MISC/job/run-ci-in-qemu/). Commits submitted by non-members do not automatically proceed through CI testing. After visual inspection of the commit, a CI run can be manually performed by the reviewer. Automated testing against the QEMU model along with supported systems are -performed. The OpenBMC project uses the -[Robot Framework](http://robotframework.org/) for all automation. Our -complete test repository can be found +performed. The OpenBMC project uses the +[Robot Framework](http://robotframework.org/) for all automation. Our complete +test repository can be found [here](https://github.com/openbmc/openbmc-test-automation). ## Submitting Patches -Support of additional hardware and software packages is always welcome. -Please follow the [contributing guidelines](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md) -when making a submission. It is expected that contributions contain test -cases. + +Support of additional hardware and software packages is always welcome. Please +follow the +[contributing guidelines](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md) +when making a submission. It is expected that contributions contain test cases. ## Bug Reporting -[Issues](https://github.com/openbmc/openbmc/issues) are managed on -GitHub. It is recommended you search through the issues before opening -a new one. + +[Issues](https://github.com/openbmc/openbmc/issues) are managed on GitHub. It is +recommended you search through the issues before opening a new one. ## Questions @@ -121,55 +129,59 @@ First, please do a search on the internet. There's a good chance your question has already been asked. For general questions, please use the openbmc tag on -[Stack Overflow](https://stackoverflow.com/questions/tagged/openbmc). -Please review the [discussion](https://meta.stackexchange.com/questions/272956/a-new-code-license-the-mit-this-time-with-attribution-required?cb=1) +[Stack Overflow](https://stackoverflow.com/questions/tagged/openbmc). Please +review the +[discussion](https://meta.stackexchange.com/questions/272956/a-new-code-license-the-mit-this-time-with-attribution-required?cb=1) on Stack Overflow licensing before posting any code. -For technical discussions, please see [contact info](#contact) below for -Discord and mailing list information. Please don't file an issue to ask a -question. You'll get faster results by using the mailing list or Discord. +For technical discussions, please see [contact info](#contact) below for Discord +and mailing list information. Please don't file an issue to ask a question. +You'll get faster results by using the mailing list or Discord. ## Features of OpenBMC -**Feature List** -* Host management: Power, Cooling, LEDs, Inventory, Events, Watchdog -* Full IPMI 2.0 Compliance with DCMI -* Code Update Support for multiple BMC/BIOS images -* Web-based user interface -* REST interfaces -* D-Bus based interfaces -* SSH based SOL -* Remote KVM -* Hardware Simulation -* Automated Testing -* User management -* Virtual media +### Feature List + +- Host management: Power, Cooling, LEDs, Inventory, Events, Watchdog +- Full IPMI 2.0 Compliance with DCMI +- Code Update Support for multiple BMC/BIOS images +- Web-based user interface +- REST interfaces +- D-Bus based interfaces +- SSH based SOL +- Remote KVM +- Hardware Simulation +- Automated Testing +- User management +- Virtual media -**Features In Progress** -* OpenCompute Redfish Compliance -* Verified Boot +### Features In Progress -**Features Requested but need help** -* OpenBMC performance monitoring +- OpenCompute Redfish Compliance +- Verified Boot +### Features Requested but need help + +- OpenBMC performance monitoring ## Finding out more -Dive deeper into OpenBMC by opening the -[docs](https://github.com/openbmc/docs) repository. +Dive deeper into OpenBMC by opening the [docs](https://github.com/openbmc/docs) +repository. ## Technical Steering Committee The Technical Steering Committee (TSC) guides the project. Members are: - * Roxanne Clarke, IBM - * Nancy Yuen, Google - * Sai Dasari, Facebook - * Terry Duncan, Intel - * Sagar Dharia, Microsoft - * Samer El-Haj-Mahmoud, Arm +- Roxanne Clarke, IBM +- Nancy Yuen, Google +- Patrick Williams, Meta +- Terry Duncan, Intel +- Sagar Dharia, Microsoft +- Samer El-Haj-Mahmoud, Arm ## Contact -- Mail: openbmc@lists.ozlabs.org [https://lists.ozlabs.org/listinfo/openbmc](https://lists.ozlabs.org/listinfo/openbmc) -- Discord: https://discord.gg/69Km47zH98 +- Mail: openbmc@lists.ozlabs.org + [https://lists.ozlabs.org/listinfo/openbmc](https://lists.ozlabs.org/listinfo/openbmc) +- Discord: [https://discord.gg/69Km47zH98](https://discord.gg/69Km47zH98) diff --git a/meta-amd/conf/layer.conf b/meta-amd/conf/layer.conf index 136196555de9..2a62b58e5ef7 100644 --- a/meta-amd/conf/layer.conf +++ b/meta-amd/conf/layer.conf @@ -7,4 +7,4 @@ BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ BBFILE_COLLECTIONS += "amd-layer" BBFILE_PATTERN_amd-layer = "^${LAYERDIR}/" -LAYERSERIES_COMPAT_amd-layer = "honister kirkstone" +LAYERSERIES_COMPAT_amd-layer = "langdale mickledore" diff --git a/meta-amd/meta-ethanolx/conf/layer.conf b/meta-amd/meta-ethanolx/conf/layer.conf index 2cd49ff156a3..b6875aca26ba 100644 --- a/meta-amd/meta-ethanolx/conf/layer.conf +++ b/meta-amd/meta-ethanolx/conf/layer.conf @@ -9,4 +9,4 @@ BBFILE_COLLECTIONS += "ethanolx-layer" BBFILE_PATTERN_ethanolx-layer = "^${LAYERDIR}/" BBFILE_PRIORITY_ethanolx-layer = "6" -LAYERSERIES_COMPAT_ethanolx-layer = "honister kirkstone" +LAYERSERIES_COMPAT_ethanolx-layer = "langdale mickledore" diff --git a/meta-amd/meta-ethanolx/conf/machine/ethanolx.conf b/meta-amd/meta-ethanolx/conf/machine/ethanolx.conf index 67fc64c8fed7..dd6ef518acd5 100644 --- a/meta-amd/meta-ethanolx/conf/machine/ethanolx.conf +++ b/meta-amd/meta-ethanolx/conf/machine/ethanolx.conf @@ -2,11 +2,8 @@ KMACHINE = "aspeed" KERNEL_DEVICETREE = "${KMACHINE}-bmc-amd-${MACHINE}.dtb" -PREFERRED_PROVIDER_virtual/bootloader = "u-boot-aspeed" -PREFERRED_PROVIDER_u-boot = "u-boot-aspeed" -PREFERRED_PROVIDER_u-boot-fw-utils = "u-boot-fw-utils-aspeed" - -UBOOT_MACHINE:ethanolx = "ast_g5_phy_config" +UBOOT_DEVICETREE = "ast2500-evb" +UBOOT_MACHINE = "evb-ast2500_defconfig" require conf/machine/include/ast2500.inc require conf/machine/include/obmc-bsp-common.inc @@ -36,7 +33,6 @@ PREFERRED_PROVIDER_virtual/obmc-flash-mgmt = "packagegroup-amd-apps" PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw ?= "phosphor-ipmi-kcs" PREFERRED_PROVIDER_virtual/obmc-inventory-data ?= "${VIRTUAL-RUNTIME_skeleton_workbook}" PREFERRED_PROVIDER_virtual/obmc-system-mgmt = "packagegroup-amd-apps" -PREFERRED_PROVIDER_virtual/obmc-host-ctl ?= "obmc-op-control-host" PREFERRED_PROVIDER_virtual/phosphor-led-manager-config-native = "ethanolx-led-manager-config-native" OVERRIDES .= ":amd" diff --git a/meta-amd/meta-ethanolx/conf/bblayers.conf.sample b/meta-amd/meta-ethanolx/conf/templates/default/bblayers.conf.sample similarity index 100% rename from meta-amd/meta-ethanolx/conf/bblayers.conf.sample rename to meta-amd/meta-ethanolx/conf/templates/default/bblayers.conf.sample diff --git a/meta-amd/meta-ethanolx/conf/conf-notes.txt b/meta-amd/meta-ethanolx/conf/templates/default/conf-notes.txt similarity index 100% rename from meta-amd/meta-ethanolx/conf/conf-notes.txt rename to meta-amd/meta-ethanolx/conf/templates/default/conf-notes.txt diff --git a/meta-amd/meta-ethanolx/conf/local.conf.sample b/meta-amd/meta-ethanolx/conf/templates/default/local.conf.sample similarity index 100% rename from meta-amd/meta-ethanolx/conf/local.conf.sample rename to meta-amd/meta-ethanolx/conf/templates/default/local.conf.sample diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json index 08d66c022f63..baaeee82a1e3 100644 --- a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json +++ b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json @@ -2,42 +2,50 @@ "Exposes": [ { "Name": "P0 Fan connector", - "Status": "disabled", + "Pwm" : 0, + "Tachs": [0], "Type": "FanConnector" }, { "Name": "P1 Fan connector", - "Status": "disabled", + "Pwm" : 1, + "Tachs": [1], "Type": "FanConnector" }, { "Name": "SYS FAN1 connector", - "Status": "disabled", + "Pwm" : 2, + "Tachs": [2], "Type": "FanConnector" }, { "Name": "SYS FAN2 connector", - "Status": "disabled", + "Pwm" : 3, + "Tachs": [3], "Type": "FanConnector" }, { "Name": "SYS FAN3 connector", - "Status": "disabled", + "Pwm" : 4, + "Tachs": [4], "Type": "FanConnector" }, { "Name": "SYS FAN4 connector", - "Status": "disabled", + "Pwm" : 5, + "Tachs": [5], "Type": "FanConnector" }, { "Name": "SYS FAN5 connector", - "Status": "disabled", + "Pwm" : 6, + "Tachs": [6], "Type": "FanConnector" }, { "Name": "SYS FAN6 connector", - "Status": "disabled", + "Pwm" : 7, + "Tachs": [7], "Type": "FanConnector" }, { @@ -1148,6 +1156,314 @@ } ], "Type": "SBTSI" + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "P0_Fan" + ], + "Name": "P0_Fan", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 1" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 1" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "P1_Fan" + ], + "Name": "P1_Fan", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 2" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 2" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN1" + ], + "Name": "SYS_FAN1", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 3" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN2" + ], + "Name": "SYS_FAN2", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 4" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN3" + ], + "Name": "SYS_FAN3", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 5" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN4" + ], + "Name": "SYS_FAN4", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 6" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN5" + ], + "Name": "SYS_FAN5", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 7" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "fan", + "FFGainCoefficient": 1.0, + "FFOffCoefficient": 0.0, + "ICoefficient": 0.0, + "ILimitMax": 0.0, + "ILimitMin": 0.0, + "Inputs": [ + "SYS_FAN6" + ], + "Name": "SYS_FAN6", + "NegativeHysteresis": 0.0, + "OutLimitMax": 100.0, + "OutLimitMin": 10.0, + "Outputs": [ + "Pwm 8" + ], + "PCoefficient": 0.0, + "PositiveHysteresis": 0.0, + "SlewNeg": 0.0, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "Class": "temp", + "FFGainCoefficient": 0.0, + "FFOffCoefficient": 0.0, + "ICoefficient": -1.0, + "ILimitMax": 100, + "ILimitMin": 20, + "Inputs": [ + "CPU0" + ], + "Name": "CPU0 Temperature Control", + "NegativeHysteresis": 5.0, + "OutLimitMax": 100, + "OutLimitMin": 30, + "Outputs": [], + "PCoefficient": -5, + "PositiveHysteresis": 0.0, + "SetPoint": 60.0, + "SlewNeg": -1, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 1" + ] + }, + { + "Class": "temp", + "FFGainCoefficient": 0.0, + "FFOffCoefficient": 0.0, + "ICoefficient": -1.0, + "ILimitMax": 100, + "ILimitMin": 20, + "Inputs": [ + "CPU1" + ], + "Name": "CPU1 Temperature Control", + "NegativeHysteresis": 5.0, + "OutLimitMax": 100, + "OutLimitMin": 30, + "Outputs": [], + "PCoefficient": -5, + "PositiveHysteresis": 0.0, + "SetPoint": 60.0, + "SlewNeg": -1, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 2" + ] + }, + { + "Class": "temp", + "FFGainCoefficient": 0.0, + "FFOffCoefficient": 0.0, + "ICoefficient": -1.0, + "ILimitMax": 100, + "ILimitMin": 20, + "Inputs": [ + "BMC", + "DIMM_P0_ABCD", + "DIMM_P0_ABCD_P1_EFGH", + "DIMM_P0_EFGH", + "DIMM_P0_EFGH_P1_ABCD", + "DIMM_P1_ABCD", + "DIMM_P1_EFGH", + "PCIe_Slots" + ], + "Name": "Board Temperature Control", + "NegativeHysteresis": 3.0, + "OutLimitMax": 100, + "OutLimitMin": 30, + "Outputs": [], + "PCoefficient": -5, + "PositiveHysteresis": 0.0, + "SetPoint": 35.0, + "SlewNeg": -1, + "SlewPos": 0.0, + "Type": "Pid", + "Zones": [ + "Zone 3" + ] + }, + { + "FailSafePercent": 100, + "MinThermalOutput": 10, + "Name": "Zone 1", + "Type": "Pid.Zone" + }, + { + "FailSafePercent": 100, + "MinThermalOutput": 10, + "Name": "Zone 2", + "Type": "Pid.Zone" + }, + { + "FailSafePercent": 100, + "MinThermalOutput": 10, + "Name": "Zone 3", + "Type": "Pid.Zone" } ], "Name": "AMD EthanolX Baseboard", @@ -1159,5 +1475,6 @@ "Model": "EthanolX", "PartNumber": "109-H43111-00A_02", "SerialNumber": "EX782B" - } + }, + "xyz.openbmc_project.Inventory.Item.System": {} } diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json index 329ed02862d3..ed4fec8aa5e7 100644 --- a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json +++ b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json @@ -6,8 +6,6 @@ "MaxReading": 6000, "Name": "P0_Fan", "Type": "AspeedFan", - "Pwm": 1, - "Tachs": [1], "Thresholds": [ { "Direction": "less than", @@ -41,8 +39,6 @@ "MaxReading": 6000, "Name": "P1_Fan", "Type": "AspeedFan", - "Pwm": 2, - "Tachs": [2], "Thresholds": [ { "Direction": "less than", @@ -76,8 +72,6 @@ "MaxReading": 6000, "Name": "SYS_FAN1", "Type": "AspeedFan", - "Pwm": 3, - "Tachs": [3], "Thresholds": [ { "Direction": "less than", @@ -111,8 +105,6 @@ "MaxReading": 6000, "Name": "SYS_FAN2", "Type": "AspeedFan", - "Pwm": 4, - "Tachs": [4], "Thresholds": [ { "Direction": "less than", @@ -146,8 +138,6 @@ "MaxReading": 6000, "Name": "SYS_FAN3", "Type": "AspeedFan", - "Pwm": 5, - "Tachs": [5], "Thresholds": [ { "Direction": "less than", @@ -181,8 +171,6 @@ "MaxReading": 6000, "Name": "SYS_FAN4", "Type": "AspeedFan", - "Pwm": 6, - "Tachs": [6], "Thresholds": [ { "Direction": "less than", @@ -216,8 +204,6 @@ "MaxReading": 6000, "Name": "SYS_FAN5", "Type": "AspeedFan", - "Pwm": 7, - "Tachs": [7], "Thresholds": [ { "Direction": "less than", @@ -251,8 +237,6 @@ "MaxReading": 6000, "Name": "SYS_FAN6", "Type": "AspeedFan", - "Pwm": 8, - "Tachs": [8], "Thresholds": [ { "Direction": "less than", diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager/sol-default.override.yml b/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager/sol-default.override.yml new file mode 100644 index 000000000000..fe9d1e726577 --- /dev/null +++ b/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager/sol-default.override.yml @@ -0,0 +1,17 @@ +/xyz/openbmc_project/ipmi/sol/eth0: + - Interface: xyz.openbmc_project.Ipmi.SOL + Properties: + AccumulateIntervalMS: + Default: 1 + Enable: + Default: 'true' + Privilege: + Default: 4 + Progress: + Default: 0 + RetryCount: + Default: 7 + RetryIntervalMS: + Default: 1 + Threshold: + Default: 1 diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend b/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend index f1c5acabc960..1d832ab56a00 100644 --- a/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend +++ b/meta-amd/meta-ethanolx/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend @@ -1 +1,5 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + PACKAGECONFIG:append:ethanolx = " boot_type" + +SRC_URI += " file://sol-default.override.yml" diff --git a/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/0001-Amd-power-control-modifications-for-EthanolX.patch b/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/0001-Amd-power-control-modifications-for-EthanolX.patch deleted file mode 100644 index dc1b7bc21d5b..000000000000 --- a/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/0001-Amd-power-control-modifications-for-EthanolX.patch +++ /dev/null @@ -1,819 +0,0 @@ -From 1a4aee6e48594cecf7e9083358d3d278f3060650 Mon Sep 17 00:00:00 2001 -From: Supreeth Venkatesh -Date: Mon, 26 Oct 2020 19:04:15 -0500 -Subject: [PATCH 1/1] Amd power control modifications for EthanolX -Content-Type: text/plain; charset="us-ascii" -Content-Transfer-Encoding: 7bit - -This patch modifies recipes-x86 chassis manager code to support AMD -EthanolX customer reference board. -The configuration Json file is updated with the GPIO signals present on -AMD EthanolX file. -The Service file is updated to indicate this is modified version of x86 -power control suitable for AMD platforms. -The source file is modified to remove Intel specific SIO signals and -functions, modify it to support AMD specific GPIO signals. - -Further, Beep() is replaced by lighting up Fault LED, as AMD CRBs does -not have a beeper. - -Signed-off-by: Supreeth Venkatesh ---- - .../config/power-config-host0.json | 23 +- - ...nbmc_project.Chassis.Control.Power.service | 2 +- - power-control-x86/src/power_control.cpp | 430 +++--------------- - 3 files changed, 81 insertions(+), 374 deletions(-) - -diff --git a/power-control-x86/config/power-config-host0.json b/power-control-x86/config/power-config-host0.json -index 567f419..9e1a54a 100644 ---- a/power-control-x86/config/power-config-host0.json -+++ b/power-control-x86/config/power-config-host0.json -@@ -1,15 +1,14 @@ - { -- "IdButton": "ID_BUTTON", -- "NMIButton": "NMI_BUTTON", -- "NMIOut": "NMI_OUT", -- "PostComplete": "POST_COMPLETE", -- "PwrButton": "POWER_BUTTON", -- "PwrOK": "PS_PWROK", -- "PwrOut": "POWER_OUT", -- "RstButton": "RESET_BUTTON", -- "RstOut": "RESET_OUT", -- "SIOOnCtl": "SIO_ONCONTROL", -- "SIOPwrGd": "SIO_POWER_GOOD", -- "SIOS5": "SIO_S5" -+ "IdButton": "CHASSIS_ID_BTN", -+ "NMIButton": "MON_P0_NMI_BTN", -+ "NMIOut": "ASSERT_NMI_BTN", -+ "PostComplete": "MON_PWROK", -+ "PwrButton": "MON_P0_PWR_BTN", -+ "PwrOK": "MON_P0_PWR_GOOD", -+ "PwrOut": "ASSERT_PWR_BTN", -+ "RstButton": "MON_P0_RST_BTN", -+ "RstOut": "ASSERT_RST_BTN", -+ "BmcReady": "ASSERT_BMC_READY", -+ "FaultLed": "FAULT_LED" - } - -diff --git a/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service b/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service -index a80235e..43cf1a7 100644 ---- a/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service -+++ b/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service -@@ -1,5 +1,5 @@ - [Unit] --Description=Intel Power Control -+Description=Amd Power Control - - [Service] - Restart=always -diff --git a/power-control-x86/src/power_control.cpp b/power-control-x86/src/power_control.cpp -index ab704d8..da81531 100644 ---- a/power-control-x86/src/power_control.cpp -+++ b/power-control-x86/src/power_control.cpp -@@ -44,9 +44,8 @@ static std::string powerOutName; - static std::string powerOkName; - static std::string resetOutName; - static std::string nmiOutName; --static std::string sioPwrGoodName; --static std::string sioOnControlName; --static std::string sioS5Name; -+static std::string bmcReadyName; -+static std::string faultLedName; - static std::string postCompleteName; - static std::string powerButtonName; - static std::string resetButtonName; -@@ -55,9 +54,7 @@ static std::string nmiButtonName; - - static std::shared_ptr hostIface; - static std::shared_ptr chassisIface; --#ifdef CHASSIS_SYSTEM_RESET - static std::shared_ptr chassisSysIface; --#endif - static std::shared_ptr powerButtonIface; - static std::shared_ptr resetButtonIface; - static std::shared_ptr nmiButtonIface; -@@ -74,18 +71,15 @@ const static constexpr int powerPulseTimeMs = 200; - const static constexpr int forceOffPulseTimeMs = 15000; - const static constexpr int resetPulseTimeMs = 500; - const static constexpr int powerCycleTimeMs = 5000; --const static constexpr int sioPowerGoodWatchdogTimeMs = 1000; - const static constexpr int psPowerOKWatchdogTimeMs = 8000; - const static constexpr int gracefulPowerOffTimeMs = 60000; - const static constexpr int warmResetCheckTimeMs = 500; --const static constexpr int buttonMaskTimeMs = 60000; - const static constexpr int powerOffSaveTimeMs = 7000; - - const static std::filesystem::path powerControlDir = "/var/lib/power-control"; - const static constexpr std::string_view powerStateFile = "power-state"; - - static bool nmiEnabled = true; --static bool sioEnabled = true; - - // Timers - // Time holding GPIOs asserted -@@ -98,24 +92,14 @@ static boost::asio::steady_timer gracefulPowerOffTimer(io); - static boost::asio::steady_timer warmResetCheckTimer(io); - // Time power supply power OK assertion on power-on - static boost::asio::steady_timer psPowerOKWatchdogTimer(io); --// Time SIO power good assertion on power-on --static boost::asio::steady_timer sioPowerGoodWatchdogTimer(io); - // Time power-off state save for power loss tracking - static boost::asio::steady_timer powerStateSaveTimer(io); - // POH timer - static boost::asio::steady_timer pohCounterTimer(io); --// Time when to allow restart cause updates --static boost::asio::steady_timer restartCauseTimer(io); - - // GPIO Lines and Event Descriptors - static gpiod::line psPowerOKLine; - static boost::asio::posix::stream_descriptor psPowerOKEvent(io); --static gpiod::line sioPowerGoodLine; --static boost::asio::posix::stream_descriptor sioPowerGoodEvent(io); --static gpiod::line sioOnControlLine; --static boost::asio::posix::stream_descriptor sioOnControlEvent(io); --static gpiod::line sioS5Line; --static boost::asio::posix::stream_descriptor sioS5Event(io); - static gpiod::line powerButtonLine; - static boost::asio::posix::stream_descriptor powerButtonEvent(io); - static gpiod::line resetButtonLine; -@@ -128,31 +112,10 @@ static gpiod::line postCompleteLine; - static boost::asio::posix::stream_descriptor postCompleteEvent(io); - static gpiod::line nmiOutLine; - --static constexpr uint8_t beepPowerFail = 8; -- --static void beep(const uint8_t& beepPriority) --{ -- std::cerr << "Beep with priority: " << (unsigned)beepPriority << "\n"; -- -- conn->async_method_call( -- [](boost::system::error_code ec) { -- if (ec) -- { -- std::cerr << "beep returned error with " -- "async_method_call (ec = " -- << ec << ")\n"; -- return; -- } -- }, -- "xyz.openbmc_project.BeepCode", "/xyz/openbmc_project/BeepCode", -- "xyz.openbmc_project.BeepCode", "Beep", uint8_t(beepPriority)); --} -- - enum class PowerState - { - on, - waitForPSPowerOK, -- waitForSIOPowerGood, - off, - transitionToOff, - gracefulTransitionToOff, -@@ -172,9 +135,6 @@ static std::string getPowerStateName(PowerState state) - case PowerState::waitForPSPowerOK: - return "Wait for Power Supply Power OK"; - break; -- case PowerState::waitForSIOPowerGood: -- return "Wait for SIO Power Good"; -- break; - case PowerState::off: - return "Off"; - break; -@@ -215,17 +175,12 @@ enum class Event - { - psPowerOKAssert, - psPowerOKDeAssert, -- sioPowerGoodAssert, -- sioPowerGoodDeAssert, -- sioS5Assert, -- sioS5DeAssert, - postCompleteAssert, - postCompleteDeAssert, - powerButtonPressed, - resetButtonPressed, - powerCycleTimerExpired, - psPowerOKWatchdogTimerExpired, -- sioPowerGoodWatchdogTimerExpired, - gracefulPowerOffTimerExpired, - powerOnRequest, - powerOffRequest, -@@ -245,18 +200,6 @@ static std::string getEventName(Event event) - case Event::psPowerOKDeAssert: - return "power supply power OK de-assert"; - break; -- case Event::sioPowerGoodAssert: -- return "SIO power good assert"; -- break; -- case Event::sioPowerGoodDeAssert: -- return "SIO power good de-assert"; -- break; -- case Event::sioS5Assert: -- return "SIO S5 assert"; -- break; -- case Event::sioS5DeAssert: -- return "SIO S5 de-assert"; -- break; - case Event::postCompleteAssert: - return "POST Complete assert"; - break; -@@ -275,9 +218,6 @@ static std::string getEventName(Event event) - case Event::psPowerOKWatchdogTimerExpired: - return "power supply power OK watchdog timer expired"; - break; -- case Event::sioPowerGoodWatchdogTimerExpired: -- return "SIO power good watchdog timer expired"; -- break; - case Event::gracefulPowerOffTimerExpired: - return "graceful power-off timer expired"; - break; -@@ -319,7 +259,6 @@ static void logEvent(const std::string_view stateHandler, const Event event) - // Power state handlers - static void powerStateOn(const Event event); - static void powerStateWaitForPSPowerOK(const Event event); --static void powerStateWaitForSIOPowerGood(const Event event); - static void powerStateOff(const Event event); - static void powerStateTransitionToOff(const Event event); - static void powerStateGracefulTransitionToOff(const Event event); -@@ -338,9 +277,6 @@ static std::function getPowerStateHandler(PowerState state) - case PowerState::waitForPSPowerOK: - return powerStateWaitForPSPowerOK; - break; -- case PowerState::waitForSIOPowerGood: -- return powerStateWaitForSIOPowerGood; -- break; - case PowerState::off: - return powerStateOff; - break; -@@ -404,7 +340,6 @@ static constexpr std::string_view getHostState(const PowerState state) - return "xyz.openbmc_project.State.Host.HostState.Running"; - break; - case PowerState::waitForPSPowerOK: -- case PowerState::waitForSIOPowerGood: - case PowerState::off: - case PowerState::transitionToOff: - case PowerState::transitionToCycleOff: -@@ -430,7 +365,6 @@ static constexpr std::string_view getChassisState(const PowerState state) - return "xyz.openbmc_project.State.Chassis.PowerState.On"; - break; - case PowerState::waitForPSPowerOK: -- case PowerState::waitForSIOPowerGood: - case PowerState::off: - case PowerState::cycleOff: - return "xyz.openbmc_project.State.Chassis.PowerState.Off"; -@@ -598,7 +532,7 @@ static void systemPowerGoodFailedLog() - "MESSAGE=PowerControl: system power good failed to assert (VR failure)", - "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s", - "OpenBMC.0.1.SystemPowerGoodFailed", "REDFISH_MESSAGE_ARGS=%d", -- sioPowerGoodWatchdogTimeMs, NULL); -+ psPowerOKWatchdogTimeMs, NULL); - } - - static void psPowerOKFailedLog() -@@ -1086,54 +1020,24 @@ static int setGPIOOutputForMs(const std::string& name, const int value, - - static void powerOn() - { -- setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs); -+ setGPIOOutputForMs(power_control::powerOutName, 1, powerPulseTimeMs); - } - - static void gracefulPowerOff() - { -- setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs); -+ setGPIOOutputForMs(power_control::powerOutName, 1, powerPulseTimeMs); - } - - static void forcePowerOff() - { -- if (setGPIOOutputForMs(power_control::powerOutName, 0, -- forceOffPulseTimeMs) < 0) -- { -- return; -- } -+ setGPIOOutputForMs(power_control::powerOutName, 1, forceOffPulseTimeMs); - -- // If the force off timer expires, then the PCH power-button override -- // failed, so attempt the Unconditional Powerdown SMBus command. -- gpioAssertTimer.async_wait([](const boost::system::error_code ec) { -- if (ec) -- { -- // operation_aborted is expected if timer is canceled before -- // completion. -- if (ec != boost::asio::error::operation_aborted) -- { -- std::cerr << "Force power off async_wait failed: " -- << ec.message() << "\n"; -- } -- return; -- } -- std::cerr << "PCH Power-button override failed. Issuing Unconditional " -- "Powerdown SMBus command.\n"; -- const static constexpr size_t pchDevBusAddress = 3; -- const static constexpr size_t pchDevSlaveAddress = 0x44; -- const static constexpr size_t pchCmdReg = 0; -- const static constexpr size_t pchPowerDownCmd = 0x02; -- if (i2cSet(pchDevBusAddress, pchDevSlaveAddress, pchCmdReg, -- pchPowerDownCmd) < 0) -- { -- std::cerr << "Unconditional Powerdown command failed! Not sure " -- "what to do now.\n"; -- } -- }); -+ return; - } - - static void reset() - { -- setGPIOOutputForMs(power_control::resetOutName, 0, resetPulseTimeMs); -+ setGPIOOutputForMs(power_control::resetOutName, 1, resetPulseTimeMs); - } - - static void gracefulPowerOffTimerStart() -@@ -1378,43 +1282,16 @@ static void currentHostStateMonitor() - }); - } - --static void sioPowerGoodWatchdogTimerStart() --{ -- std::cerr << "SIO power good watchdog timer started\n"; -- sioPowerGoodWatchdogTimer.expires_after( -- std::chrono::milliseconds(sioPowerGoodWatchdogTimeMs)); -- sioPowerGoodWatchdogTimer.async_wait( -- [](const boost::system::error_code ec) { -- if (ec) -- { -- // operation_aborted is expected if timer is canceled before -- // completion. -- if (ec != boost::asio::error::operation_aborted) -- { -- std::cerr << "SIO power good watchdog async_wait failed: " -- << ec.message() << "\n"; -- } -- std::cerr << "SIO power good watchdog timer canceled\n"; -- return; -- } -- std::cerr << "SIO power good watchdog timer completed\n"; -- sendPowerControlEvent(Event::sioPowerGoodWatchdogTimerExpired); -- }); --} -- - static void powerStateOn(const Event event) - { -+ gpiod::line line; - logEvent(__FUNCTION__, event); - switch (event) - { - case Event::psPowerOKDeAssert: - setPowerState(PowerState::off); -- // DC power is unexpectedly lost, beep -- beep(beepPowerFail); -- break; -- case Event::sioS5Assert: -- setPowerState(PowerState::transitionToOff); -- addRestartCause(RestartCause::softReset); -+ // DC power is unexpectedly lost, Light Up fault LED -+ power_control::setGPIOOutput(power_control::faultLedName, 1, line); - break; - case Event::postCompleteDeAssert: - setPowerState(PowerState::checkForWarmReset); -@@ -1463,49 +1340,15 @@ static void powerStateWaitForPSPowerOK(const Event event) - switch (event) - { - case Event::psPowerOKAssert: -- { - // Cancel any GPIO assertions held during the transition - gpioAssertTimer.cancel(); - psPowerOKWatchdogTimer.cancel(); -- if (sioEnabled == true) -- { -- sioPowerGoodWatchdogTimerStart(); -- setPowerState(PowerState::waitForSIOPowerGood); -- } -- else -- { -- setPowerState(PowerState::on); -- } -+ setPowerState(PowerState::on); - break; -- } - case Event::psPowerOKWatchdogTimerExpired: - setPowerState(PowerState::off); - psPowerOKFailedLog(); - break; -- case Event::sioPowerGoodAssert: -- psPowerOKWatchdogTimer.cancel(); -- setPowerState(PowerState::on); -- break; -- default: -- phosphor::logging::log( -- "No action taken."); -- break; -- } --} -- --static void powerStateWaitForSIOPowerGood(const Event event) --{ -- logEvent(__FUNCTION__, event); -- switch (event) -- { -- case Event::sioPowerGoodAssert: -- sioPowerGoodWatchdogTimer.cancel(); -- setPowerState(PowerState::on); -- break; -- case Event::sioPowerGoodWatchdogTimerExpired: -- setPowerState(PowerState::off); -- systemPowerGoodFailedLog(); -- break; - default: - phosphor::logging::log( - "No action taken."); -@@ -1519,21 +1362,6 @@ static void powerStateOff(const Event event) - switch (event) - { - case Event::psPowerOKAssert: -- { -- if (sioEnabled == true) -- { -- setPowerState(PowerState::waitForSIOPowerGood); -- } -- else -- { -- setPowerState(PowerState::on); -- } -- break; -- } -- case Event::sioS5DeAssert: -- setPowerState(PowerState::waitForPSPowerOK); -- break; -- case Event::sioPowerGoodAssert: - setPowerState(PowerState::on); - break; - case Event::powerButtonPressed: -@@ -1594,21 +1422,12 @@ static void powerStateCycleOff(const Event event) - switch (event) - { - case Event::psPowerOKAssert: -- { - powerCycleTimer.cancel(); -- if (sioEnabled == true) -- { -- setPowerState(PowerState::waitForSIOPowerGood); -- } -- else -- { -- setPowerState(PowerState::on); -- } -+ setPowerState(PowerState::on); - break; -- } -- case Event::sioS5DeAssert: -+ case Event::psPowerOKDeAssert: - powerCycleTimer.cancel(); -- setPowerState(PowerState::waitForPSPowerOK); -+ setPowerState(PowerState::off); - break; - case Event::powerButtonPressed: - powerCycleTimer.cancel(); -@@ -1667,21 +1486,18 @@ static void powerStateGracefulTransitionToCycleOff(const Event event) - - static void powerStateCheckForWarmReset(const Event event) - { -+ gpiod::line line; - logEvent(__FUNCTION__, event); - switch (event) - { -- case Event::sioS5Assert: -- warmResetCheckTimer.cancel(); -- setPowerState(PowerState::transitionToOff); -- break; - case Event::warmResetDetected: - setPowerState(PowerState::on); - break; - case Event::psPowerOKDeAssert: - warmResetCheckTimer.cancel(); - setPowerState(PowerState::off); -- // DC power is unexpectedly lost, beep -- beep(beepPowerFail); -+ // DC power is unexpectedly lost, Light up Fault LED -+ power_control::setGPIOOutput(power_control::faultLedName, 1, line); - break; - default: - phosphor::logging::log( -@@ -1713,71 +1529,6 @@ static void psPowerOKHandler() - }); - } - --static void sioPowerGoodHandler() --{ -- gpiod::line_event gpioLineEvent = sioPowerGoodLine.event_read(); -- -- Event powerControlEvent = -- gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE -- ? Event::sioPowerGoodAssert -- : Event::sioPowerGoodDeAssert; -- -- sendPowerControlEvent(powerControlEvent); -- sioPowerGoodEvent.async_wait( -- boost::asio::posix::stream_descriptor::wait_read, -- [](const boost::system::error_code ec) { -- if (ec) -- { -- std::cerr << "SIO power good handler error: " << ec.message() -- << "\n"; -- return; -- } -- sioPowerGoodHandler(); -- }); --} -- --static void sioOnControlHandler() --{ -- gpiod::line_event gpioLineEvent = sioOnControlLine.event_read(); -- -- bool sioOnControl = -- gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE; -- std::cerr << "SIO_ONCONTROL value changed: " << sioOnControl << "\n"; -- sioOnControlEvent.async_wait( -- boost::asio::posix::stream_descriptor::wait_read, -- [](const boost::system::error_code ec) { -- if (ec) -- { -- std::cerr << "SIO ONCONTROL handler error: " << ec.message() -- << "\n"; -- return; -- } -- sioOnControlHandler(); -- }); --} -- --static void sioS5Handler() --{ -- gpiod::line_event gpioLineEvent = sioS5Line.event_read(); -- -- Event powerControlEvent = -- gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE -- ? Event::sioS5Assert -- : Event::sioS5DeAssert; -- -- sendPowerControlEvent(powerControlEvent); -- sioS5Event.async_wait(boost::asio::posix::stream_descriptor::wait_read, -- [](const boost::system::error_code ec) { -- if (ec) -- { -- std::cerr << "SIO S5 handler error: " -- << ec.message() << "\n"; -- return; -- } -- sioS5Handler(); -- }); --} -- - static void powerButtonHandler() - { - gpiod::line_event gpioLineEvent = powerButtonLine.event_read(); -@@ -1848,7 +1599,6 @@ static void resetButtonHandler() - }); - } - --#ifdef CHASSIS_SYSTEM_RESET - static constexpr auto systemdBusname = "org.freedesktop.systemd1"; - static constexpr auto systemdPath = "/org/freedesktop/systemd1"; - static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager"; -@@ -1868,7 +1618,6 @@ void systemReset() - systemdBusname, systemdPath, systemdInterface, "StartUnit", - systemTargetName, "replace"); - } --#endif - - static void nmiSetEnablePorperty(bool value) - { -@@ -2041,7 +1790,7 @@ static void postCompleteHandler() - gpiod::line_event gpioLineEvent = postCompleteLine.event_read(); - - bool postComplete = -- gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE; -+ gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE; - if (postComplete) - { - sendPowerControlEvent(Event::postCompleteAssert); -@@ -2129,19 +1878,14 @@ static int loadConfigValues() - resetOutName = data["RstOut"]; - } - -- if (data.contains("SIOOnCtl")) -+ if (data.contains("BmcReady")) - { -- sioOnControlName = data["SIOOnCtl"]; -+ bmcReadyName = data["BmcReady"]; - } - -- if (data.contains("SIOPwrGd")) -+ if (data.contains("FaultLed")) - { -- sioPwrGoodName = data["SIOPwrGd"]; -- } -- -- if (data.contains("SIOS5")) -- { -- sioS5Name = data["SIOS5"]; -+ faultLedName = data["FaultLed"]; - } - - return 0; -@@ -2172,14 +1916,6 @@ int main(int argc, char* argv[]) - power_control::conn->request_name( - "xyz.openbmc_project.Control.Host.RestartCause"); - -- if (power_control::sioPwrGoodName.empty() || -- power_control::sioOnControlName.empty() || -- power_control::sioS5Name.empty()) -- { -- power_control::sioEnabled = false; -- std::cerr << "SIO control GPIOs not defined, disable SIO support.\n"; -- } -- - // Request PS_PWROK GPIO events - if (!power_control::powerOkName.empty()) - { -@@ -2197,37 +1933,6 @@ int main(int argc, char* argv[]) - return -1; - } - -- if (power_control::sioEnabled == true) -- { -- // Request SIO_POWER_GOOD GPIO events -- if (!power_control::requestGPIOEvents( -- power_control::sioPwrGoodName, -- power_control::sioPowerGoodHandler, -- power_control::sioPowerGoodLine, -- power_control::sioPowerGoodEvent)) -- { -- return -1; -- } -- -- // Request SIO_ONCONTROL GPIO events -- if (!power_control::requestGPIOEvents( -- power_control::sioOnControlName, -- power_control::sioOnControlHandler, -- power_control::sioOnControlLine, -- power_control::sioOnControlEvent)) -- { -- return -1; -- } -- -- // Request SIO_S5 GPIO events -- if (!power_control::requestGPIOEvents( -- power_control::sioS5Name, power_control::sioS5Handler, -- power_control::sioS5Line, power_control::sioS5Event)) -- { -- return -1; -- } -- } -- - // Request POWER_BUTTON GPIO events - if (!power_control::powerButtonName.empty()) - { -@@ -2259,7 +1964,9 @@ int main(int argc, char* argv[]) - } - else - { -- std::cerr << "ResetButton not defined...\n"; -+ std::cerr -+ << "resetButton name should be configured from json config file\n"; -+ return -1; - } - - // Request NMI_BUTTON GPIO events -@@ -2303,12 +2010,12 @@ int main(int argc, char* argv[]) - - // Initialize POWER_OUT and RESET_OUT GPIO. - gpiod::line line; -- if (!power_control::setGPIOOutput(power_control::powerOutName, 1, line)) -+ if (!power_control::setGPIOOutput(power_control::powerOutName, 0, line)) - { - return -1; - } - -- if (!power_control::setGPIOOutput(power_control::resetOutName, 1, line)) -+ if (!power_control::setGPIOOutput(power_control::resetOutName, 0, line)) - { - return -1; - } -@@ -2316,6 +2023,13 @@ int main(int argc, char* argv[]) - // Release line - line.reset(); - -+ // DRIVE BMC_READY HIGH -+ gpiod::line bmcReadyline; -+ if (!power_control::setGPIOOutput(power_control::bmcReadyName, 1, bmcReadyline)) -+ { -+ return -1; -+ } -+ - // Initialize the power state - power_control::powerState = power_control::PowerState::off; - // Check power good -@@ -2444,7 +2158,6 @@ int main(int argc, char* argv[]) - - power_control::chassisIface->initialize(); - --#ifdef CHASSIS_SYSTEM_RESET - // Chassis System Service - sdbusplus::asio::object_server chassisSysServer = - sdbusplus::asio::object_server(power_control::conn); -@@ -2481,7 +2194,6 @@ int main(int argc, char* argv[]) - "LastStateChangeTime", power_control::getCurrentTimeMs()); - - power_control::chassisSysIface->initialize(); --#endif - - // Buttons Service - sdbusplus::asio::object_server buttonsServer = -@@ -2531,51 +2243,47 @@ int main(int argc, char* argv[]) - power_control::powerButtonIface->initialize(); - - // Reset Button Interface -- if (!power_control::resetButtonName.empty()) -- { -- power_control::resetButtonIface = buttonsServer.add_interface( -- "/xyz/openbmc_project/chassis/buttons/reset", -- "xyz.openbmc_project.Chassis.Buttons"); -+ power_control::resetButtonIface = buttonsServer.add_interface( -+ "/xyz/openbmc_project/chassis/buttons/reset", -+ "xyz.openbmc_project.Chassis.Buttons"); - -- power_control::resetButtonIface->register_property( -- "ButtonMasked", false, [](const bool requested, bool& current) { -- if (requested) -+ power_control::resetButtonIface->register_property( -+ "ButtonMasked", false, [](const bool requested, bool& current) { -+ if (requested) -+ { -+ if (power_control::resetButtonMask) - { -- if (power_control::resetButtonMask) -- { -- return 1; -- } -- if (!power_control::setGPIOOutput( -- power_control::resetOutName, 1, -- power_control::resetButtonMask)) -- { -- throw std::runtime_error("Failed to request GPIO"); -- return 0; -- } -- std::cerr << "Reset Button Masked.\n"; -+ return 1; - } -- else -+ if (!power_control::setGPIOOutput( -+ power_control::resetOutName, 1, -+ power_control::resetButtonMask)) - { -- if (!power_control::resetButtonMask) -- { -- return 1; -- } -- std::cerr << "Reset Button Un-masked\n"; -- power_control::resetButtonMask.reset(); -+ throw std::runtime_error("Failed to request GPIO"); -+ return 0; - } -- // Update the mask setting -- current = requested; -- return 1; -- }); -+ std::cerr << "Reset Button Masked.\n"; -+ } -+ else -+ { -+ if (!power_control::resetButtonMask) -+ { -+ return 1; -+ } -+ std::cerr << "Reset Button Un-masked\n"; -+ power_control::resetButtonMask.reset(); -+ } -+ // Update the mask setting -+ current = requested; -+ return 1; -+ }); - -- // Check reset button state -- bool resetButtonPressed = -- power_control::resetButtonLine.get_value() == 0; -- power_control::resetButtonIface->register_property("ButtonPressed", -- resetButtonPressed); -+ // Check reset button state -+ bool resetButtonPressed = power_control::resetButtonLine.get_value() == 0; -+ power_control::resetButtonIface->register_property("ButtonPressed", -+ resetButtonPressed); - -- power_control::resetButtonIface->initialize(); -- } -+ power_control::resetButtonIface->initialize(); - - if (power_control::nmiButtonLine) - { --- -2.17.1 - diff --git a/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/power-config-host0.json b/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/power-config-host0.json new file mode 100644 index 000000000000..0d0faf920028 --- /dev/null +++ b/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control/power-config-host0.json @@ -0,0 +1,58 @@ +{ + "gpio_configs":[ + { + "Name" : "IdButton", + "LineName" : "CHASSIS_ID_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveLow" + }, + { + "Name" : "NMIButton", + "LineName" : "MON_P0_NMI_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveLow" + }, + { + "Name" : "NMIOut", + "LineName" : "ASSERT_NMI_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveHigh" + }, + { + "Name" : "PostComplete", + "LineName" : "MON_PWROK", + "Type" : "GPIO", + "Polarity" : "ActiveHigh" + }, + { + "Name" : "PowerButton", + "LineName" : "MON_P0_PWR_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveLow" + }, + { + "Name" : "PowerOk", + "LineName" : "MON_P0_PWR_GOOD", + "Type" : "GPIO", + "Polarity" : "ActiveHigh" + }, + { + "Name" : "PowerOut", + "LineName" : "ASSERT_PWR_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveHigh" + }, + { + "Name" : "ResetButton", + "LineName" : "MON_P0_RST_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveLow" + }, + { + "Name" : "ResetOut", + "LineName" : "ASSERT_RST_BTN", + "Type" : "GPIO", + "Polarity" : "ActiveHigh" + } +] +} diff --git a/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control_%.bbappend b/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control_%.bbappend index 662090ea09c8..cba1306def8e 100644 --- a/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control_%.bbappend +++ b/meta-amd/meta-ethanolx/recipes-x86/chassis/x86-power-control_%.bbappend @@ -1,4 +1,9 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" -SRC_URI += "file://0001-Amd-power-control-modifications-for-EthanolX.patch" -SRCREV = "01a77864f49088bac80474587a123d1f152f2b26" +SRC_URI += "file://power-config-host0.json \ + " + +do_install:append() { + install -d ${D}/${datadir}/${PN} + install -m 0644 ${WORKDIR}/power-config-host0.json ${D}/${datadir}/${PN} +} diff --git a/meta-amd/recipes-amd/amd-fpga/amd-fpga.bb b/meta-amd/recipes-amd/amd-fpga/amd-fpga.bb index 79c80b012938..6e89a4c4dcd9 100644 --- a/meta-amd/recipes-amd/amd-fpga/amd-fpga.bb +++ b/meta-amd/recipes-amd/amd-fpga/amd-fpga.bb @@ -1,6 +1,6 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/${MACHINE}:" -SUMMARY = "AMD Ethanolx FPGA Register Dump Utility" -DESCRIPTION = "AMD Ethanolx FPGA Register Dump Utility" +SUMMARY = "AMD FPGA Register Dump Utility" +DESCRIPTION = "AMD FPGA Register Dump Utility" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE;md5=5e24678b8d0883d9dfa9e9473069ddd2" diff --git a/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb b/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb index 06938055ccc9..f99de8409cd3 100644 --- a/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb +++ b/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb @@ -28,7 +28,9 @@ RDEPENDS:${PN}-chassis = " \ " SUMMARY:${PN}-fans = "AMD Fans" -RDEPENDS:${PN}-fans = "" +RDEPENDS:${PN}-fans = " \ + phosphor-pid-control \ + " SUMMARY:${PN}-flash = "AMD Flash" RDEPENDS:${PN}-flash = " \ diff --git a/meta-amd/recipes-phosphor/console/obmc-console/ethanolx/server.ttyS0.conf b/meta-amd/recipes-phosphor/console/obmc-console/ethanolx/server.ttyS0.conf index 88d84d7cad36..666e66aac0c5 100644 --- a/meta-amd/recipes-phosphor/console/obmc-console/ethanolx/server.ttyS0.conf +++ b/meta-amd/recipes-phosphor/console/obmc-console/ethanolx/server.ttyS0.conf @@ -1,2 +1 @@ -local-tty = ttyS0 baud = 115200 diff --git a/meta-amd/recipes-phosphor/console/obmc-console_%.bbappend b/meta-amd/recipes-phosphor/console/obmc-console_%.bbappend index a533724312ae..92148bd34977 100644 --- a/meta-amd/recipes-phosphor/console/obmc-console_%.bbappend +++ b/meta-amd/recipes-phosphor/console/obmc-console_%.bbappend @@ -1,8 +1,8 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/${MACHINE}:" -OBMC_CONSOLE_HOST_TTY = "ttyS0" +OBMC_CONSOLE_HOST_TTY:ethanolx = "ttyS0" SRC_URI:remove = "file://${BPN}.conf" -SRC_URI += "file://server.ttyS0.conf" +SRC_URI:ethanolx += "file://server.ttyS0.conf" do_install:append() { # Remove upstream-provided configuration diff --git a/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service b/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service new file mode 100644 index 000000000000..659ff3e1e802 --- /dev/null +++ b/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service @@ -0,0 +1,14 @@ +[Unit] +Description=Phosphor-Pid-Control Margin-based Fan Control Daemon +After=xyz.openbmc_project.EntityManager.service +After=xyz.openbmc_project.ObjectMapper.service + +[Service] +Restart=always +ExecStart={bindir}/swampd -t +RestartSec=5 +StartLimitInterval=0 +Type=simple + +[Install] +WantedBy=multi-user.target diff --git a/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend index 4cdfe5a9ebb1..6e528dcb6bd2 100644 --- a/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend +++ b/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend @@ -1,3 +1,5 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" -EXTRA_OECONF:append = " --enable-configure-dbus=yes" +inherit obmc-phosphor-systemd + +SYSTEMD_SERVICE:${PN} = "phosphor-pid-control.service" diff --git a/meta-amd/recipes-phosphor/logging/phosphor-hostlogger_%.bbappend b/meta-amd/recipes-phosphor/logging/phosphor-hostlogger_%.bbappend index 1f2e6c0380d6..503408ae0423 100644 --- a/meta-amd/recipes-phosphor/logging/phosphor-hostlogger_%.bbappend +++ b/meta-amd/recipes-phosphor/logging/phosphor-hostlogger_%.bbappend @@ -1,8 +1,8 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/${MACHINE}:" # Default service instance to install (single-host mode) -DEFAULT_INSTANCE = "ttyS0" +DEFAULT_INSTANCE:ethanolx = "ttyS0" SRC_URI:remove = "file://${BPN}.conf" -SRC_URI += "file://ttyS0.conf" +SRC_URI:ethanolx += "file://ttyS0.conf" diff --git a/meta-ampere/conf/layer.conf b/meta-ampere/conf/layer.conf index dd0027f52e1d..12f55eedc62b 100644 --- a/meta-ampere/conf/layer.conf +++ b/meta-ampere/conf/layer.conf @@ -7,4 +7,4 @@ BBFILES += "${LAYERDIR}/meta-common/recipes-*/*/*.bb \ BBFILE_COLLECTIONS += "ampere-layer" BBFILE_PATTERN_ampere-layer := "^${LAYERDIR}/" -LAYERSERIES_COMPAT_ampere-layer = "honister kirkstone" +LAYERSERIES_COMPAT_ampere-layer = "langdale mickledore" diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb new file mode 100644 index 000000000000..823bea77e3f3 --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb @@ -0,0 +1,33 @@ +SUMMARY = "Altra Boot Progress Handling Service" +DESCRIPTION = "OpenBMC Altra Boot Progress Handling Daemon" + +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit systemd +inherit obmc-phosphor-systemd + +DEPENDS += "systemd" +RDEPENDS:${PN} += "libsystemd" +RDEPENDS:${PN} += "bash" + +SRC_URI = " \ + file://ampere_boot_progress.sh \ + " + +SYSTEMD_PACKAGES = "${PN}" + +HOST_ON_RESET_HOSTTMPL = "ampere-boot-progress.service" +HOST_ON_RESET_HOSTINSTMPL = "ampere-boot-progress.service" +HOST_ON_RESET_HOSTTGTFMT = "obmc-host-already-on@{0}.target" +HOST_ON_RESET_HOSTFMT = "../${HOST_ON_RESET_HOSTTMPL}:${HOST_ON_RESET_HOSTTGTFMT}.requires/${HOST_ON_RESET_HOSTINSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_RESET_HOSTFMT', 'OBMC_HOST_INSTANCES')}" + +SYSTEMD_SERVICE:${PN} += "${HOST_ON_RESET_HOSTTMPL}" + +do_install () { + install -d ${D}${sbindir} + install -m 0755 ${WORKDIR}/ampere_boot_progress.sh ${D}${sbindir}/ +} + diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service new file mode 100644 index 000000000000..267d901a9fdf --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service @@ -0,0 +1,13 @@ +[Unit] +Description=Ampere Altra Boot Progress Handling +After=ampere-host-already-on@0.target +BindTo=obmc-host-already-on@0.target + +[Service] +Restart=simple +ExecStart=/usr/sbin/ampere_boot_progress.sh +SyslogIdentifier=ampere-boot-progress +RemainAfterExit=no + +[Install] +WantedBy=obmc-host-already-on@0.target diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh new file mode 100755 index 000000000000..87ad34f945dd --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh @@ -0,0 +1,201 @@ +#!/bin/bash +# Initialize variables +boot_stage=00 +boot_status=00 +uefi_code=00000000 + +function set_postcode() +{ + # shellcheck disable=SC2086 + busctl set-property xyz.openbmc_project.State.Boot.Raw \ + /xyz/openbmc_project/state/boot/raw0 \ + xyz.openbmc_project.State.Boot.Raw Value \(tay\) "$1" 0 +} + +function update_boot_progress_last_state_time() +{ + # Get BMC current time + bp_last_state_time=$(busctl get-property xyz.openbmc_project.Time.Manager \ + /xyz/openbmc_project/time/bmc \ + xyz.openbmc_project.Time.EpochTime \ + Elapsed | cut -d' ' -f2) + + # Update the Boot Progress LastStateTime + busctl set-property xyz.openbmc_project.State.Host \ + /xyz/openbmc_project/state/host0 \ + xyz.openbmc_project.State.Boot.Progress \ + BootProgressLastUpdate t \ + "$bp_last_state_time" +} + +function update_boot_progress() +{ + bootprog=$1 + + busctl set-property xyz.openbmc_project.State.Host \ + /xyz/openbmc_project/state/host0 \ + xyz.openbmc_project.State.Boot.Progress \ + BootProgress s \ + "xyz.openbmc_project.State.Boot.Progress.ProgressStages.$bootprog" + + # Update Boot Progress LastStateTime + update_boot_progress_last_state_time +} + +function get_boot_stage_string() +{ + bootstage=$1 + ueficode=$2 + + case $bootstage in + + 00) + boot_stage_str="SMpro" + ;; + + 01) + boot_stage_str="PMpro" + ;; + + 02) + boot_stage_str="ATF BL1 (Code=${ueficode})" + ;; + + 03) + boot_stage_str="DDR initialization (Code=${ueficode})" + ;; + + 04) + boot_stage_str="DDR training progress (Code=${ueficode})" + ;; + + 05) + boot_stage_str="ATF BL2 (Code=${ueficode})" + ;; + + 06) + boot_stage_str="ATF BL31 (Code=${ueficode})" + ;; + + 07) + boot_stage_str="ATF BL32 (Code=${ueficode})" + ;; + + 08) + boot_stage_str="UEFI booting (UEFI Code=${ueficode})" + ;; + 09) + boot_stage_str="OS booting" + ;; + + esac + + echo "$boot_stage_str" +} + +function set_boot_progress() +{ + boot_stage=$1 + uefi_code=$2 + + case $boot_stage in + + 02) + update_boot_progress "PrimaryProcInit" + ;; + + 03) + update_boot_progress "MemoryInit" + ;; + + 08) + if [[ "$uefi_code" =~ 0201* ]]; then + update_boot_progress "PCIInit" + fi + ;; + 09) + update_boot_progress "OSStart" + ;; + + esac +} + +function log_redfish_biosboot_ok_event() +{ + logger-systemd --journald << EOF +MESSAGE= +PRIORITY=2 +SEVERITY= +REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSBoot.OK +REDFISH_MESSAGE_ARGS="UEFI firmware booting done" +EOF +} + +function log_redfish_bios_panic_event() +{ + boot_state_str=$(get_boot_stage_string "$1" "$2") + + logger-systemd --journald << EOF +MESSAGE= +PRIORITY=2 +SEVERITY= +REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSFirmwarePanicReason.Warning +REDFISH_MESSAGE_ARGS=${boot_state_str} +EOF +} + +cnt=0 +# If any reason makes SCP fail to access in 6s, break the service. +while [ $cnt -lt 30 ]; +do + # Sleep 200ms + usleep 200000 + if ! read -r bg <<< "$(cat /sys/bus/platform/devices/smpro-misc.2.auto/boot_progress)"; + then + cnt=$((cnt + 1)) + continue + fi + cnt=0 + + # Check if any update from previous check + if [ "$last_bg" == "$bg" ]; then + continue + fi + last_bg=$bg + + # Check if the Host is already ON or not. If Host is already boot, update boot progress and break. + if [ "${boot_stage}" == "00" ] && [ "${bg[0]}" == "09" ]; + then + update_boot_progress "OSRunning" + break + fi + + # Update current boot progress + boot_stage=${bg:2:2} + boot_status=${bg:0:2} + uefi_code=${bg:4} + echo "Boot Progress = ${boot_stage} ${boot_status} ${uefi_code}" + + # Log Boot Progress to dbus + if [ "${boot_status}" == "03" ]; then + # Log Redfish Event if failure. + log_redfish_bios_panic_event "$boot_stage" "$uefi_code" + elif [ "${boot_status}" == "01" ]; then + # Check and set boot progress to dbus + set_boot_progress "$boot_stage" "$uefi_code" + fi + + # Log POST Code to dbus. + set_postcode "0x$boot_stage$boot_status$uefi_code" + + # Stop the service when booting to OS + if [ "${boot_stage}" == "08" ] && [ "${boot_status}" == "02" ]; then + update_boot_progress "SystemInitComplete" + log_redfish_biosboot_ok_event + elif [ "${boot_stage}" == "09" ] && [ "${boot_status}" == "02" ]; + then + update_boot_progress "OSRunning" + break + fi +done + diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl.bb b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl.bb index b0498f8ebba0..54c14d491d26 100644 --- a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl.bb +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl.bb @@ -14,11 +14,17 @@ SRC_URI = " \ file://ampere-host-force-reset@.service \ file://ampere-host-on-host-check@.service \ file://ampere_host_check.sh \ + file://obmc-power-already-on@.target \ + file://obmc-host-already-on@.target \ + file://ampere-bmc-reboot-host-check@.service \ " SYSTEMD_PACKAGES = "${PN}" SYSTEMD_SERVICE:${PN} = " \ ampere-host-force-reset@.service \ + obmc-power-already-on@.target \ + obmc-host-already-on@.target \ + ampere-bmc-reboot-host-check@.service \ " # append force reboot @@ -36,6 +42,21 @@ HOST_ON_RESET_HOSTFMT = "../${HOST_ON_RESET_HOSTTMPL}:${HOST_ON_RESET_HOSTTGTFMT SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_RESET_HOSTFMT', 'OBMC_HOST_INSTANCES')}" SYSTEMD_SERVICE:${PN} += "${HOST_ON_RESET_HOSTTMPL}" +# append on phosphor-wait-power-on +AMPERE_POWER_ON_TGT = "obmc-power-already-on@.target" +AMPERE_POWER_ON_INSTMPL = "obmc-power-already-on@{0}.target" +OP_WAIT_POWER_ON = "phosphor-wait-power-on@{0}.service" +AMPERE_POWER_ON_TARGET_FMT = "../${AMPERE_POWER_ON_TGT}:${OP_WAIT_POWER_ON}.wants/${AMPERE_POWER_ON_INSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'AMPERE_POWER_ON_TARGET_FMT', 'OBMC_HOST_INSTANCES')}" + +# append on obmc-chassis-poweron but will start after phosphor-state-manager init +# host state as running +HOST_CHECK_BMC_REBOOT_HOSTTMPL = "ampere-bmc-reboot-host-check@.service" +HOST_CHECK_BMC_REBOOT_HOSTINSTMPL = "ampere-bmc-reboot-host-check@{0}.service" +HOST_CHECK_BMC_REBOOT_HOSTTGTFMT = "obmc-chassis-poweron@{0}.target" +HOST_CHECK_BMC_REBOOT_HOSTFMT = "../${HOST_CHECK_BMC_REBOOT_HOSTTMPL}:${HOST_CHECK_BMC_REBOOT_HOSTTGTFMT}.requires/${HOST_CHECK_BMC_REBOOT_HOSTINSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_CHECK_BMC_REBOOT_HOSTFMT', 'OBMC_HOST_INSTANCES')}" + do_install() { install -d ${D}/usr/sbin install -m 0755 ${WORKDIR}/ampere_host_check.sh ${D}/${sbindir}/ diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-bmc-reboot-host-check@.service b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-bmc-reboot-host-check@.service new file mode 100644 index 000000000000..feaa3d0b5f9b --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-bmc-reboot-host-check@.service @@ -0,0 +1,15 @@ +[Unit] +Description=Check Host%i status after bmc reboot +After=obmc-host-reset@%i.target +After=obmc-host-reset-running@%i.target +After=mapper-wait@-xyz-openbmc_project-state-host%i.service +OnSuccess=obmc-host-already-on@%i.target +ConditionPathExists=/run/openbmc/chassis@%i-on +ConditionPathExists=/run/openbmc/host@%i-on +Conflicts=obmc-chassis-poweroff@%i.target + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "if [ $(busctl get-property `mapper get-service /xyz/openbmc_project/state/host0` /xyz/openbmc_project/state/host0 xyz.openbmc_project.State.Host CurrentHostState | grep -i '\.Running' | wc -l) != 0 ]; then exit 0; fi" + + diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-host-on-host-check@.service b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-host-on-host-check@.service index e3c87397dc0c..a68d0431f778 100644 --- a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-host-on-host-check@.service +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere-host-on-host-check@.service @@ -5,6 +5,7 @@ After=obmc-power-start-pre@%i.target Conflicts=obmc-host-stop@%i.target Conflicts=phosphor-reset-host-check@%i.service OnFailure=obmc-host-quiesce@%i.target +OnSuccess=obmc-host-already-on@%i.target OnFailureJobMode=flush [Service] diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere_host_check.sh b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere_host_check.sh index 9759b880cc65..ea60fcf69773 100644 --- a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere_host_check.sh +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/ampere_host_check.sh @@ -18,6 +18,10 @@ do Get ss xyz.openbmc_project.Condition.HostFirmware \ CurrentFirmwareCondition | cut -d"." -f6) if [ "$st" == "Running\"" ]; then + if command -v ampere_driver_binder.sh; + then + ampere_driver_binder.sh + fi exit 0 fi sleep 1 diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-host-already-on@.target b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-host-already-on@.target new file mode 100644 index 000000000000..07f5039ec4b2 --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-host-already-on@.target @@ -0,0 +1,6 @@ +[Unit] +Description=Ampere Host %i already on target +Conflicts=obmc-chassis-poweroff@%i.target +Conflicts=obmc-host-quiesce@%i.target +Conflicts=ampere-host-force-reset@%i.service +Conflicts=ampere-host-shutdown-ack@%i.service diff --git a/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-power-already-on@.target b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-power-already-on@.target new file mode 100644 index 000000000000..868348ec2a4c --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/host/ampere-hostctrl/obmc-power-already-on@.target @@ -0,0 +1,5 @@ +[Unit] +Description=Ampere power %i already on target +After=phosphor-wait-power-on@%i.service +Conflicts=obmc-chassis-poweroff@%i.target +Conflicts=ampere-host-shutdown-ack@%i.service diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder.bb b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder.bb new file mode 100644 index 000000000000..498ed50ba6c8 --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder.bb @@ -0,0 +1,35 @@ +SUMMARY = "Ampere Driver Binder Implementation" +DESCRIPTION = "The driver binder for Ampere Computing LLC's systems" +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit systemd +inherit obmc-phosphor-systemd + +RDEPENDS:${PN} = "bash" +S = "${WORKDIR}" + +SRC_URI = " \ + file://ampere-power-on-driver-binder@.service \ + file://ampere-host-on-driver-binder@.service \ + " + +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE:${PN} = " \ + ampere-power-on-driver-binder@.service \ + ampere-host-on-driver-binder@.service \ + " +# bind driver after the power is on +POWER_ON_DRIVER_BINDER_TGT = "ampere-power-on-driver-binder@.service" +POWER_ON_DRIVER_BINDER_INSTMPL = "ampere-power-on-driver-binder@{0}.service" +AMPER_POWER_ON = "obmc-power-already-on@{0}.target" +POWER_ON_DRIVER_BINDER_TARGET_FMT = "../${POWER_ON_DRIVER_BINDER_TGT}:${AMPER_POWER_ON}.wants/${POWER_ON_DRIVER_BINDER_INSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'POWER_ON_DRIVER_BINDER_TARGET_FMT', 'OBMC_HOST_INSTANCES')}" + +# bind driver after the host is on +HOST_ON_DRIVER_BINDER_TGT = "ampere-host-on-driver-binder@.service" +HOST_ON_DRIVER_BINDER_INSTMPL = "ampere-host-on-driver-binder@{0}.service" +AMPER_HOST_RUNNING = "obmc-host-already-on@{0}.target" +HOST_ON_DRIVER_BINDER_TARGET_FMT = "../${HOST_ON_DRIVER_BINDER_TGT}:${AMPER_HOST_RUNNING}.wants/${HOST_ON_DRIVER_BINDER_INSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_DRIVER_BINDER_TARGET_FMT', 'OBMC_HOST_INSTANCES')}" diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-host-on-driver-binder@.service b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-host-on-driver-binder@.service new file mode 100644 index 000000000000..f2a83d4f6bd5 --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-host-on-driver-binder@.service @@ -0,0 +1,13 @@ +[Unit] +Description=Ampere host on driver binder %i +After=obmc-host-already-on@%i.target +BindTo=obmc-host-already-on@%i.target + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "if command -v ampere_host_on_driver_binder.sh; then echo 'Try to bind driver after host on if does not' && ampere_host_on_driver_binder.sh; fi && exit 0;" +SyslogIdentifier=host_on_binder +RemainAfterExit=no + +[Install] +WantedBy=obmc-host-already-on@%i.target diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-power-on-driver-binder@.service b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-power-on-driver-binder@.service new file mode 100644 index 000000000000..01a380bd7bff --- /dev/null +++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-driver-binder/ampere-power-on-driver-binder@.service @@ -0,0 +1,10 @@ +[Unit] +Description=Ampere power on driver binder %i +After=obmc-power-already-on@%i.target +BindTo=obmc-power-already-on@%i.target + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "if command -v ampere_power_on_driver_binder.sh; then echo 'Try to bind driver after power on if does not' && ampere_power_on_driver_binder.sh; fi && exit 0;" +SyslogIdentifier=power_on_binder +RemainAfterExit=no \ No newline at end of file diff --git a/meta-ampere/meta-common/recipes-extended/pam/libpam/pam.d/common-auth b/meta-ampere/meta-common/recipes-extended/pam/libpam/pam.d/common-auth new file mode 100644 index 000000000000..c79219f24d12 --- /dev/null +++ b/meta-ampere/meta-common/recipes-extended/pam/libpam/pam.d/common-auth @@ -0,0 +1,21 @@ +# +# /etc/pam.d/common-auth - authentication settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the authentication modules that define +# the central authentication scheme for use on the system +# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the +# traditional Unix authentication mechanisms. + +# here are the per-package modules (the "Primary" block) +auth [success=ok user_unknown=ignore default=2] pam_tally2.so deny=5 unlock_time=0 +# Try for local user first, and then try for ldap +auth [success=2 default=ignore] pam_unix.so quiet +-auth [success=1 default=ignore] pam_ldap.so ignore_unknown_user ignore_authinfo_unavail +# here's the fallback if no module succeeds +auth requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +auth required pam_permit.so +# and here are more per-package modules (the "Additional" block) diff --git a/meta-ampere/meta-common/recipes-extended/pam/libpam_%.bbappend b/meta-ampere/meta-common/recipes-extended/pam/libpam_%.bbappend index 4ede0332eb2a..ad820d162f2e 100644 --- a/meta-ampere/meta-common/recipes-extended/pam/libpam_%.bbappend +++ b/meta-ampere/meta-common/recipes-extended/pam/libpam_%.bbappend @@ -1,4 +1,5 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += " file://pam.d/common-password \ + file://pam.d/common-auth \ " diff --git a/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/hostconsole.conf b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/hostconsole.conf new file mode 100644 index 000000000000..6900a5d94213 --- /dev/null +++ b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/hostconsole.conf @@ -0,0 +1,91 @@ +#Host console log + +module(load="imuxsock" SysSock.Use="off") + +template(name="ConsoleTemplate" type="string" string="%rawmsg%") + +ruleset(name="ConsoleCPURuleset") { + action(type="omfile" file="/var/log/obmc-console-cpu.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleATFRuleset") { + action(type="omfile" file="/var/log/obmc-console-atf.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleSECPRO0Ruleset") { + action(type="omfile" file="/var/log/obmc-console-secpro0.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleSECPRO1Ruleset") { + action(type="omfile" file="/var/log/obmc-console-secpro1.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleMPRO0Ruleset") { + action(type="omfile" file="/var/log/obmc-console-mpro0.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleMPRO1Ruleset") { + action(type="omfile" file="/var/log/obmc-console-mpro1.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleSCP0Ruleset") { + action(type="omfile" file="/var/log/obmc-console-scp0.log" template="ConsoleTemplate") +} +ruleset(name="ConsoleSCP1Ruleset") { + action(type="omfile" file="/var/log/obmc-console-scp1.log" template="ConsoleTemplate") +} + +# Custom socket for serial console logs. +input(type="imuxsock" + Socket="/run/rsyslog/console/cpu" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleCPURuleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/atf" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleATFRuleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/secpro0" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleSECPRO0Ruleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/secpro1" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleSECPRO1Ruleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/mpro0" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleMPRO0Ruleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/mpro1" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleMPRO1Ruleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/scp0" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleSCP0Ruleset") + +input(type="imuxsock" + Socket="/run/rsyslog/console/scp1" + CreatePath="on" + UseSpecialParser="off" + ParseHostname="off" + ruleset="ConsoleSCP1Ruleset") + +$EscapeControlCharactersOnReceive off +$DropTrailingLFOnReception off + diff --git a/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate index a6ba28d8644b..098236a8f5ac 100644 --- a/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate +++ b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate @@ -20,3 +20,48 @@ systemctl reload rsyslog 2> /dev/null || true endscript } +# Keep up to 2 256k files for cpu console logs +/var/log/obmc-console-cpu.log +{ + copytruncate + rotate 1 + size 256k + missingok + postrotate + systemctl reload rsyslog 2> /dev/null || true + endscript +} +# Keep up to 2 64k files for atf console logs +/var/log/obmc-console-atf.log +{ + copytruncate + rotate 1 + size 64k + missingok + postrotate + systemctl reload rsyslog 2> /dev/null || true + endscript +} +# Keep up to 2 64k files for secpro and mpro console logs +/var/log/obmc-console-*pro*.log +{ + copytruncate + rotate 1 + size 64k + missingok + postrotate + systemctl reload rsyslog 2> /dev/null || true + endscript +} + +# Keep up to 2 64k files for Mt.Jade's scp console logs +/var/log/obmc-console-scp*.log +{ + copytruncate + rotate 1 + size 64k + missingok + postrotate + systemctl reload rsyslog 2> /dev/null || true + endscript +} diff --git a/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend index 034ae3cfa7ba..863f314e28e8 100644 --- a/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend +++ b/meta-ampere/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend @@ -5,6 +5,7 @@ SRC_URI += "file://rsyslog.conf \ file://rotate-event-logs.service \ file://rotate-event-logs.sh \ file://rsyslog-override.conf \ + file://hostconsole.conf \ " FILES:${PN} += "${systemd_system_unitdir}/rsyslog.service.d/rsyslog-override.conf" @@ -18,6 +19,7 @@ do_install:append() { ${D}${systemd_system_unitdir}/rsyslog.service.d/rsyslog-override.conf install -d ${D}${bindir} install -m 0755 ${WORKDIR}/rotate-event-logs.sh ${D}/${bindir}/rotate-event-logs.sh + install -m 0755 ${WORKDIR}/hostconsole.conf ${D}${sysconfdir}/rsyslog.d/hostconsole.conf rm ${D}${sysconfdir}/rsyslog.d/imjournal.conf } diff --git a/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager/firmware_update.sh b/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager/firmware_update.sh index cc39f30fc889..c23f2502aabf 100755 --- a/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager/firmware_update.sh +++ b/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager/firmware_update.sh @@ -1,23 +1,4 @@ #!/bin/bash -# -# Copyright (c) 2021 Ampere Computing LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script updates the EDKII / SCP firmware. -# Author : Chanh Nguyen (chnguyen@amperecomputing.com) -# Date : Sep 7, 2021 -# Modified: usage () { echo "Usage:" @@ -73,9 +54,34 @@ case ${EXTENDED_VERSION} in CMD="/usr/sbin/ampere_firmware_upgrade.sh smpmpro $IMAGE 2" ;; - "fru") + "eeprom" | "eeprom-primary") + IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.img" -o -name "*.slim" -o -name "*.rom" -o -name "*.bin" \)) + CMD="/usr/sbin/ampere_firmware_upgrade.sh eeprom $IMAGE 1" + ;; + + "eeprom-secondary") + IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.img" -o -name "*.slim" -o -name "*.rom" -o -name "*.bin" \)) + CMD="/usr/sbin/ampere_firmware_upgrade.sh eeprom $IMAGE 2" + ;; + + "fru" | "mbfru") IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.bin" \)) - CMD="/usr/sbin/ampere_firmware_upgrade.sh fru $IMAGE" + CMD="/usr/sbin/ampere_firmware_upgrade.sh fru $IMAGE 1" + ;; + + + "bmcfru") + IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.bin" \)) + CMD="/usr/sbin/ampere_firmware_upgrade.sh fru $IMAGE 2" + ;; + + "mbcpld") + IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.jed" \)) + CMD="/usr/bin/ampere_firmware_upgrade.sh mb_cpld $IMAGE" + ;; + "bmccpld") + IMAGE=$(find "${IMG_PATH}" -type f \( -name "*.jed" \)) + CMD="/usr/bin/ampere_firmware_upgrade.sh bmc_cpld $IMAGE" ;; *) diff --git a/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend index 853e5464adc3..0a63812c4b9c 100644 --- a/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend +++ b/meta-ampere/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend @@ -6,7 +6,7 @@ SRC_URI += " \ PACKAGECONFIG[flash_bios] = "-Dhost-bios-upgrade=enabled, -Dhost-bios-upgrade=disabled" -PACKAGECONFIG:append = " flash_bios" +PACKAGECONFIG:append = " flash_bios static-dual-image" SYSTEMD_SERVICE:${PN}:updater += "${@bb.utils.contains('PACKAGECONFIG', 'flash_bios', 'obmc-flash-host-bios@.service', '', d)}" diff --git a/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend b/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend new file mode 100644 index 000000000000..6e2f476085d1 --- /dev/null +++ b/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend @@ -0,0 +1 @@ +SNOOP_DEVICE = "" diff --git a/meta-ampere/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-ampere/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend index bae82cefc460..7c1d3f22421c 100644 --- a/meta-ampere/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend +++ b/meta-ampere/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend @@ -4,4 +4,5 @@ EXTRA_OEMESON:append = " \ -Dinsecure-tftp-update=disabled \ -Dbmcweb-logging=enabled \ -Dredfish-bmc-journal=enabled \ + -Dhttp-body-limit=65 \ " diff --git a/meta-ampere/meta-common/recipes-phosphor/ipmi/ampere-ipmi-oem.bb b/meta-ampere/meta-common/recipes-phosphor/ipmi/ampere-ipmi-oem.bb index 3f84350abd6a..71e36ce8baf6 100644 --- a/meta-ampere/meta-common/recipes-phosphor/ipmi/ampere-ipmi-oem.bb +++ b/meta-ampere/meta-common/recipes-phosphor/ipmi/ampere-ipmi-oem.bb @@ -6,17 +6,15 @@ S = "${WORKDIR}" LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327" -DEPENDS = "boost phosphor-ipmi-host phosphor-logging systemd libgpiod" +DEPENDS = "boost phosphor-ipmi-host phosphor-logging systemd" -inherit cmake pkgconfig obmc-phosphor-ipmiprovider-symlink - -EXTRA_OECMAKE="-DENABLE_TEST=0 -DYOCTO=1" +inherit meson pkgconfig obmc-phosphor-ipmiprovider-symlink LIBRARY_NAMES = "libzampoemcmds.so" S = "${WORKDIR}/git" SRC_URI = "git://github.com/openbmc/ampere-ipmi-oem.git;branch=master;protocol=https" -SRCREV = "4c556399c7161d3742cad978fd64e8ad0fd0aa0a" +SRCREV = "2a19152956defafd7d9c5344b376a428e878c507" HOSTIPMI_PROVIDER_LIBRARY += "${LIBRARY_NAMES}" NETIPMI_PROVIDER_LIBRARY += "${LIBRARY_NAMES}" diff --git a/meta-ampere/meta-common/recipes-phosphor/network/phosphor-network_%.bbappend b/meta-ampere/meta-common/recipes-phosphor/network/phosphor-network_%.bbappend deleted file mode 100644 index ef2e2bab4134..000000000000 --- a/meta-ampere/meta-common/recipes-phosphor/network/phosphor-network_%.bbappend +++ /dev/null @@ -1 +0,0 @@ -PACKAGECONFIG:append = " nic-ethtool" diff --git a/meta-ampere/meta-jade/conf/layer.conf b/meta-ampere/meta-jade/conf/layer.conf index 55d3397f06b7..51b03a128945 100644 --- a/meta-ampere/meta-jade/conf/layer.conf +++ b/meta-ampere/meta-jade/conf/layer.conf @@ -7,4 +7,4 @@ BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ BBFILE_COLLECTIONS += "jade-layer" BBFILE_PATTERN_jade-layer := "^${LAYERDIR}/" -LAYERSERIES_COMPAT_jade-layer = "honister kirkstone" +LAYERSERIES_COMPAT_jade-layer = "langdale mickledore" diff --git a/meta-ampere/meta-jade/conf/machine/mtjade.conf b/meta-ampere/meta-jade/conf/machine/mtjade.conf index c6706d581d4a..914c1605c06e 100644 --- a/meta-ampere/meta-jade/conf/machine/mtjade.conf +++ b/meta-ampere/meta-jade/conf/machine/mtjade.conf @@ -14,9 +14,11 @@ FLASH_SIZE = "65536" MACHINE_FEATURES += "\ obmc-phosphor-chassis-mgmt \ obmc-phosphor-flash-mgmt \ + obmc-phosphor-fan-mgmt \ obmc-chassis-state-mgmt \ obmc-host-state-mgmt \ obmc-bmc-state-mgmt \ + obmc-host-ipmi \ " VOLATILE_LOG_DIR = "no" @@ -28,11 +30,14 @@ OBMC_IMAGE_EXTRA_INSTALL:append = "\ mtjade-gpio-config \ ampere-platform-init \ ampere-ipmi-oem \ - phosphor-nvme \ + phosphor-ipmi-blobs \ + phosphor-ipmi-blobs-binarystore \ + ampere-driver-binder \ " PREFERRED_PROVIDER_virtual/obmc-chassis-mgmt = "packagegroup-ampere-apps" PREFERRED_PROVIDER_virtual/obmc-system-mgmt = "packagegroup-ampere-apps" +PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw = "phosphor-ipmi-ssif" PREFERRED_PROVIDER_virtual/obmc-flash-mgmt = "packagegroup-ampere-apps" PREFERRED_PROVIDER_virtual/phosphor-ipmi-fru-hostfw-config ?= "hostboot-inventory-config-native" PREFERRED_PROVIDER_virtual/phosphor-led-manager-config-native = "mtjade-led-manager-config-native" diff --git a/meta-ampere/meta-jade/conf/bblayers.conf.sample b/meta-ampere/meta-jade/conf/templates/default/bblayers.conf.sample similarity index 100% rename from meta-ampere/meta-jade/conf/bblayers.conf.sample rename to meta-ampere/meta-jade/conf/templates/default/bblayers.conf.sample diff --git a/meta-ampere/meta-jade/conf/conf-notes.txt b/meta-ampere/meta-jade/conf/templates/default/conf-notes.txt similarity index 100% rename from meta-ampere/meta-jade/conf/conf-notes.txt rename to meta-ampere/meta-jade/conf/templates/default/conf-notes.txt diff --git a/meta-ampere/meta-jade/conf/local.conf.sample b/meta-ampere/meta-jade/conf/templates/default/local.conf.sample similarity index 100% rename from meta-ampere/meta-jade/conf/local.conf.sample rename to meta-ampere/meta-jade/conf/templates/default/local.conf.sample diff --git a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb index 2d3f3025e251..f1a1bbede4b5 100644 --- a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb +++ b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb @@ -9,25 +9,31 @@ PACKAGES = " \ ${PN}-chassis \ ${PN}-flash \ ${PN}-system \ + ${PN}-fans \ " PROVIDES += "virtual/obmc-chassis-mgmt" PROVIDES += "virtual/obmc-flash-mgmt" PROVIDES += "virtual/obmc-system-mgmt" +PROVIDES += "virtual/obmc-fan-mgmt" RPROVIDES:${PN}-chassis += "virtual-obmc-chassis-mgmt" RPROVIDES:${PN}-flash += "virtual-obmc-flash-mgmt" RPROVIDES:${PN}-system += "virtual-obmc-system-mgmt" +RPROVIDES:${PN}-fans += "virtual-obmc-fan-mgmt" SUMMARY:${PN}-chassis = "Ampere Chassis" RDEPENDS:${PN}-chassis = " \ obmc-phosphor-buttons-signals \ obmc-phosphor-buttons-handler \ - obmc-op-control-power \ + phosphor-skeleton-control-power \ ampere-hostctrl \ phosphor-hostlogger \ phosphor-sel-logger \ phosphor-logging \ + ac01-boot-progress \ + phosphor-post-code-manager \ + phosphor-host-postd \ " SUMMARY:${PN}-system = "Ampere System" @@ -39,3 +45,7 @@ SUMMARY:${PN}-flash = "Ampere Flash" RDEPENDS:${PN}-flash = " \ phosphor-software-manager \ " + +SUMMARY:${PN}-fans = "Ampere Fans" +RDEPENDS:${PN}-fans = " \ + " diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh index 4b448ef15959..e04af8da26fb 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh @@ -2,54 +2,45 @@ # shellcheck source=/dev/null source /usr/sbin/gpio-lib.sh +source /usr/sbin/gpio-defs.sh -# GPIOAC3 BMC_SPI0_BACKUP_SEL Boot from MAIN SPI-HOST -gpio_configure_output 227 0 +# Configure to boot from MAIN SPI-HOST +gpio_configure_output "$SPI0_BACKUP_SEL" 0 -# GPIOM4 S0_I2C9_ALERT_L -gpio_configure_input 100 - -# GPIOM5 S1_I2C9_ALERT_L -gpio_configure_input 101 - -# GPIOQ7 GPIO_BMC_VGA_FRONT_PRES_L -gpio_configure_input 135 - -# GPIOS0 GPIO_S0_VRHOT_L -gpio_configure_input 144 - -# GPIOS1 GPIO_S1_VRHOT_L -gpio_configure_input 145 - -# GPIOY3 BMC_VGA_SEL -gpio_configure_output 195 1 - -# GPIO_BMC_READY -gpio_configure_output 229 1 +gpio_configure_input "$S0_I2C9_ALERT_L" +gpio_configure_input "$S1_I2C9_ALERT_L" +gpio_configure_input "$GPIO_BMC_VGA_FRONT_PRES_L" +gpio_configure_input "$GPIO_S0_VRHOT_L" +gpio_configure_input "$GPIO_S1_VRHOT_L" +gpio_configure_output "$BMC_VGA_SEL" 1 # ======================================================= # Below GPIOs are controlled by other services so just # initialize in A/C power only. bootstatus=$(cat /sys/class/watchdog/watchdog0/bootstatus) if [ "$bootstatus" == '32' ]; then - # BMC_GPIOR2_EXT_HIGHTEMP_L - gpio_configure_output 138 1 - - # GPIOS5 GPIO_BMC_VR_PMBUS_SEL_L - gpio_configure_output 149 1 - - # GPIOH7 GPIO_BMC_I2C6_RESET_L - gpio_configure_output 63 1 - - # GPIO_BMC_OCP_AUX_PWREN - gpio_configure_output 139 1 - - # GPIO_BMC_OCP_MAIN_PWREN - gpio_configure_output 140 0 - - # BMC_GPIOAC2_SPI0_PROGRAM_SEL - gpio_configure_output 226 0 - - # BMC_GPIOB0_I2C_BACKUP_SEL - gpio_configure_output 8 1 + gpio_configure_output "$BMC_GPIOR2_EXT_HIGHTEMP_L" 1 + gpio_configure_output "$GPIO_BMC_VR_PMBUS_SEL_L" 1 + gpio_configure_output "$GPIO_BMC_I2C6_RESET_L" 1 + + # Initialize OCP register + gpio_configure_output "$OCP_MAIN_PWREN" 0 + + # Configure SPI-NOR/EEPROM switching + gpio_configure_output "$SPI0_PROGRAM_SEL" 0 + gpio_configure_output "$BMC_I2C_BACKUP_SEL" 1 + gpio_configure_output "$SPI0_BACKUP_SEL" 0 + + # Initialize BMC_SYS_PSON_L, SHD_REQ_L, BMC_SYSRESET_L + gpio_configure_output "$SYS_PSON_L" 1 + gpio_configure_output "$S0_SHD_REQ_L" 1 + gpio_configure_output "$S0_SYSRESET_L" 1 + gpio_configure_output "$S1_SYSRESET_L" 1 + + # RTC Lock, SPECIAL_BOOT + gpio_configure_output "$RTC_LOCK" 0 + gpio_configure_output "$S0_SPECIAL_BOOT" 0 + gpio_configure_output "$S1_SPECIAL_BOOT" 0 fi + +gpio_configure_output "$BMC_READY" 1 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils.bbappend b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils.bbappend index d3f4f1a02160..e3a63f1d644c 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils.bbappend +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils.bbappend @@ -6,6 +6,7 @@ SRC_URI:append = " \ file://ampere_power_util.sh \ file://ampere_firmware_upgrade.sh \ file://ampere_flash_bios.sh \ + file://ampere_driver_binder.sh \ " do_install:append() { @@ -15,4 +16,5 @@ do_install:append() { install -m 0755 ${WORKDIR}/ampere_power_util.sh ${D}/${sbindir}/ install -m 0755 ${WORKDIR}/ampere_firmware_upgrade.sh ${D}/${sbindir}/ install -m 0755 ${WORKDIR}/ampere_flash_bios.sh ${D}/${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_driver_binder.sh ${D}/${sbindir}/ } diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_driver_binder.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_driver_binder.sh new file mode 100644 index 000000000000..d41901968a2d --- /dev/null +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_driver_binder.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +DELAY_BEFORE_BIND=5000000 +# Each driver include driver name and driver path +declare -a DRIVER_NAMEs=("2-004f" + "2-004e" + ) +# Driver path should include / at the end +declare -a DRIVER_PATHs=("/sys/bus/i2c/drivers/smpro-core/" + "/sys/bus/i2c/drivers/smpro-core/" + ) + +# get length of an array +arraylength=${#DRIVER_NAMEs[@]} + +usleep $DELAY_BEFORE_BIND +# use for loop to read all values and indexes +for (( i=0; i<"${arraylength}"; i++ )); +do + bindFile="${DRIVER_PATHs[$i]}bind" + driverDir="${DRIVER_PATHs[$i]}${DRIVER_NAMEs[$i]}" + if [ -d "$driverDir" ]; then + echo "Driver ${DRIVER_NAMEs[$i]} is already bound." + continue; + fi + echo "${DRIVER_NAMEs[$i]}" > "$bindFile" +done + +exit 0 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh index 130682d12a89..6f0a11fc9f8f 100755 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh @@ -31,14 +31,26 @@ do_smpmpro_upgrade() { then echo "Turning the Chassis off" obmcutil chassisoff - sleep 15 - # Check if HOST was OFF - chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') - if [ "$chassisstate_off" == 'On' ]; - then - echo "Error : Failed turning the Chassis off" - exit - fi + + # Wait 60s until Chassis is off + cnt=30 + while [ "$cnt" -gt 0 ]; + do + cnt=$((cnt - 1)) + sleep 2 + # Check if HOST was OFF + chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') + if [ "$chassisstate_off" != 'On' ]; + then + break + fi + + if [ "$cnt" == "0" ]; + then + echo "--- Error : Failed turning the Chassis off" + exit 1 + fi + done fi if [[ $SECPRO == 1 ]]; then @@ -73,6 +85,15 @@ do_smpmpro_upgrade() { # 226 is BMC_GPIOAC2_SPI0_PROGRAM_SEL gpioset 0 226=1 + # Deassert SECPRO GPIO PINs + if [[ $SECPRO == 1 ]]; then + echo "De-asserting special GPIO PINs" + # 3 is S0_SPECIAL_BOOT + gpioset 0 3=0 + # 66 is S1_SPECIAL_BOOT + gpioset 0 66=0 + fi + if [ "$chassisstate" == 'On' ]; then sleep 5 @@ -80,20 +101,6 @@ do_smpmpro_upgrade() { obmcutil poweron fi - # Deassert SECPRO GPIO PINs - if [[ $SECPRO == 1 ]]; then - chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}') - if [ "$chassisstate_off" == 'Off' ]; then - obmcutil poweron - fi - - sleep 30s - echo "De-asserting special GPIO PINs" - # 3 is S0_SPECIAL_BOOT - gpioset 0 3=0 - # 66 is S1_SPECIAL_BOOT - gpioset 0 66=0 - fi } diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh index 7852dc4acca8..5a13da481c4a 100755 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh @@ -69,14 +69,26 @@ if [ "$chassisstate" == 'On' ]; then echo "--- Turning the Chassis off" obmcutil chassisoff - sleep 10 - # Check if HOST was OFF - chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') - if [ "$chassisstate_off" == 'On' ]; - then - echo "--- Error : Failed turning the Chassis off" - exit 1 - fi + + # Wait 60s until Chassis is off + cnt=30 + while [ "$cnt" -gt 0 ]; + do + cnt=$((cnt - 1)) + sleep 2 + # Check if HOST was OFF + chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') + if [ "$chassisstate_off" != 'On' ]; + then + break + fi + + if [ "$cnt" == "0" ]; + then + echo "--- Error : Failed turning the Chassis off" + exit 1 + fi + done fi # Switch the host SPI bus to BMC" diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh index fc0edd6fc9a8..2f2a4d6703c2 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh @@ -15,14 +15,19 @@ S0_SHD_REQ_L=49 S0_SHD_ACK_L=50 S0_REBOOT_ACK_L=75 S0_SYSRESET_L=91 +S1_SYSRESET_L=92 ### Table 1: GPIO Assignments +BMC_I2C_BACKUP_SEL=8 S0_CPU_FW_BOOT_OK=48 CPU_BMC_OVERTEMP_L=51 CPU_BMC_HIGHTEMP_L=72 CPU_FAULT_ALERT=73 S1_CPU_FW_BOOT_OK=202 +S0_SPECIAL_BOOT=3 +S1_SPECIAL_BOOT=66 +RTC_LOCK=203 ### Table 2: Alert and Additional Miscellaneous Signals S0_SCP_AUTH_FAILURE=74 @@ -41,3 +46,14 @@ OCP_MAIN_PWREN=140 ### SPI0 Mode selection SPI0_PROGRAM_SEL=226 SPI0_BACKUP_SEL=227 + +### Mt.Jade specific GPIOs +S0_I2C9_ALERT_L=100 +S1_I2C9_ALERT_L=101 +GPIO_BMC_VGA_FRONT_PRES_L=135 +GPIO_S0_VRHOT_L=144 +GPIO_S1_VRHOT_L=145 +BMC_VGA_SEL=195 +BMC_GPIOR2_EXT_HIGHTEMP_L=138 +GPIO_BMC_VR_PMBUS_SEL_L=149 +GPIO_BMC_I2C6_RESET_L=63 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweroff@.service b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweroff@.service index ce59894aa1f9..543b852946de 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweroff@.service +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweroff@.service @@ -1,6 +1,6 @@ [Unit] Description=Ampere set GPIOs before power off -Before=op-wait-power-off@%i.service +Before=phosphor-wait-power-off@%i.service Conflicts=obmc-chassis-poweron@%i.target [Service] diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweron@.service b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweron@.service index e7131a177636..ec2cd68e2084 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweron@.service +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere-gpio-poweron@.service @@ -1,6 +1,6 @@ [Unit] Description=Ampere set GPIOs before power on -Before=op-wait-power-on@%i.service +Before=phosphor-wait-power-on@%i.service After=obmc-power-start-pre@%i.target Conflicts=obmc-chassis-poweroff@%i.target diff --git a/meta-ampere/meta-jade/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg b/meta-ampere/meta-jade/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg index 1fa5d6b83e30..a274dc9fa8f0 100644 --- a/meta-ampere/meta-jade/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg +++ b/meta-ampere/meta-jade/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg @@ -1,3 +1,4 @@ CONFIG_PHY_NCSI=n CONFIG_CMD_MMC=n CONFIG_MMC_SDHCI_ASPEED=n +CONFIG_SYS_DCACHE_OFF=n diff --git a/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg b/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg index fdda06d3eba5..6d65207ff8b9 100644 --- a/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg +++ b/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg @@ -13,6 +13,7 @@ CONFIG_SENSORS_IIO_HWMON=y CONFIG_ASPEED_ADC=y CONFIG_SENSORS_LM75=y CONFIG_I2C_SLAVE=y +CONFIG_SENSORS_SMPRO=y CONFIG_SENSORS_ASPEED=y CONFIG_USB_PHY=y @@ -20,3 +21,15 @@ CONFIG_USB_GADGET=y CONFIG_USB_CONFIGFS=y CONFIG_USB_ASPEED_VHUB=y CONFIG_USB_CONFIGFS_ECM=y + +CONFIG_SSIF_IPMI_BMC=y +CONFIG_NCSI_OEM_CMD_GET_MAC=y + +CONFIG_HWMON=y +CONFIG_MFD_SMPRO=y +CONFIG_SMPRO_MISC=y +CONFIG_SMPRO_ERRMON=y + +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_CIFS=y +CONFIG_CIFS_XATTR=y diff --git a/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed_%.bbappend index f10b28949bc0..bd66ef4158f0 100644 --- a/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed_%.bbappend +++ b/meta-ampere/meta-jade/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -1,6 +1,6 @@ -FILESEXTRAPATHS:prepend:mtjade := "${THISDIR}/${PN}:" +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += " \ - file://${MACHINE}.cfg \ -" + file://mtjade.cfg \ + " diff --git a/meta-ampere/meta-jade/recipes-phosphor/configuration/dbus-sensors_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/configuration/dbus-sensors_%.bbappend index bfd03f8c5ab8..b3be6438d908 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/configuration/dbus-sensors_%.bbappend +++ b/meta-ampere/meta-jade/recipes-phosphor/configuration/dbus-sensors_%.bbappend @@ -1 +1,2 @@ -PACKAGECONFIG:remove = " cpusensor ipmbsensor" +PACKAGECONFIG:remove = " intelcpusensor ipmbsensor" +PACKAGECONFIG:append = " nvmesensor" diff --git a/meta-ampere/meta-jade/recipes-phosphor/configuration/mtjade-yaml-config.bb b/meta-ampere/meta-jade/recipes-phosphor/configuration/mtjade-yaml-config.bb index 06046c30cefa..365d210a112d 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/configuration/mtjade-yaml-config.bb +++ b/meta-ampere/meta-jade/recipes-phosphor/configuration/mtjade-yaml-config.bb @@ -5,14 +5,14 @@ LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5 inherit allarch SRC_URI = " \ - file://mtjade-ipmi-sensors.yaml \ + file://${MACHINE}-ipmi-sensors.yaml \ file://mtjade-ipmi-fru.yaml \ " S = "${WORKDIR}" do_install() { - install -m 0644 -D mtjade-ipmi-sensors.yaml \ + install -m 0644 -D ${MACHINE}-ipmi-sensors.yaml \ ${D}${datadir}/${BPN}/ipmi-sensors.yaml install -m 0644 -D mtjade-ipmi-fru.yaml \ ${D}${datadir}/${BPN}/ipmi-fru-read.yaml diff --git a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS0.conf b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS0.conf index 2d02a51387c4..2d80850416b9 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS0.conf +++ b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS0.conf @@ -1,3 +1,3 @@ +# socket-id is default to obmc-console local-tty = ttyS0 local-tty-baud = 115200 -logfile = /var/log/obmc-console-cpu.log diff --git a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS1.conf b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS1.conf index a77188412bb2..6421f9339774 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS1.conf +++ b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS1.conf @@ -1,4 +1,3 @@ local-tty = ttyS1 local-tty-baud = 115200 socket-id = ttyS1 -logfile = /var/log/obmc-console-scp0.log diff --git a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS2.conf b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS2.conf index 7ac6953e40a4..f8be872f255b 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS2.conf +++ b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS2.conf @@ -1,4 +1,3 @@ local-tty = ttyS2 local-tty-baud = 115200 socket-id = ttyS2 -logfile = /var/log/obmc-console-atf.log diff --git a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS3.conf b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS3.conf index 0ec1b693b095..8f1ebbac7329 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS3.conf +++ b/meta-ampere/meta-jade/recipes-phosphor/console/obmc-console/server.ttyS3.conf @@ -1,4 +1,3 @@ local-tty = ttyS3 local-tty-baud = 115200 socket-id = ttyS3 -logfile = /var/log/obmc-console-scp1.log diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh new file mode 100644 index 000000000000..1802790b11b8 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# shellcheck disable=SC2086 + +for filename in /sys/class/hwmon/*/pwm* +do + echo 255 > $filename +done; diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json new file mode 100644 index 000000000000..2d2143685970 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json @@ -0,0 +1,394 @@ +[ + { + "name": "set_target_fan_not_present", + "groups": [ + { + "name": "air_cooled_zone0_fans", + "interface": "xyz.openbmc_project.Inventory.Item", + "property": { "name": "Present" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + } + ], + "actions": [ + { + "name": "count_state_before_target", + "count": 1, + "state": false, + "target": 255 + } + ] + }, + { + // Hold fans at the given target when a number of rotors are nonfunctional. + "name": "set_target_fan_not_functional", + "groups": [ + { + "name": "fan3", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + }, + { + "name": "fan4", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + }, + { + "name": "fan5", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + }, + { + "name": "fan6", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + }, + { + "name": "fan7", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + }, + { + "name": "fan8", + "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus", + "property": { "name": "Functional" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + } + ], + "actions": [ + { + "name": "count_state_before_target", + "count": 1, + "state": false, + "target": 255 + } + ] + }, + { + "name": "default_fan_floor_on_missing_service", + "groups": [ + { + "name": "zone0_ambient", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "triggers": [ + { + "class": "init", + "method": "name_has_owner" + }, + { + "class": "signal", + "signal": "name_owner_changed" + } + ], + "actions": [ + { + "name": "call_actions_based_on_timer", + "timer": { + "interval": 5000000, + "type": "oneshot" + }, + "actions": [ + { + "name": "default_floor_on_missing_owner", + "groups": [ + { + "name": "zone0_ambient", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ] + } + ] + } + ] + }, + { + "name": "target_mapping_from_TS_temp", + "groups": [ + { + "name": "zone0_ambient", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + }, + { + "class": "timer", + "type": "repeating", + "interval": 5000000, + "preload_groups": true + } + ], + "actions": [ + { + "name": "target_from_group_max", + "groups": [ + { + "name": "zone0_ambient", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "neg_hysteresis": 1, + "pos_hysteresis": 0, + "index": 0, + "map": [ + { "value": 10.0, "target": 38.0 }, + { "value": 18.0, "target": 38.0 }, + { "value": 20.0, "target": 41.0 }, + { "value": 21.0, "target": 43.0 }, + { "value": 22.0, "target": 46.0 }, + { "value": 24.0, "target": 48.0 }, + { "value": 28.0, "target": 51.0 }, + { "value": 32.0, "target": 56.0 }, + { "value": 34.0, "target": 59.0 }, + { "value": 36.0, "target": 61.0 }, + { "value": 40.0, "target": 64.0 }, + { "value": 41.0, "target": 66.0 }, + { "value": 42.0, "target": 69.0 }, + { "value": 43.0, "target": 71.0 }, + { "value": 44.0, "target": 74.0 }, + { "value": 45.0, "target": 77.0 }, + { "value": 46.0, "target": 79.0 }, + { "value": 47.0, "target": 82.0 }, + { "value": 48.0, "target": 84.0 }, + { "value": 49.0, "target": 87.0 }, + { "value": 50.0, "target": 89.0 } + ] + } + ] + }, + { + "name": "target_mapping_from_OCP_temp", + "groups": [ + { + "name": "zone0_ocp", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + }, + { + "class": "timer", + "type": "repeating", + "interval": 5000000, + "preload_groups": true + } + ], + "actions": [ + { + "name": "target_from_group_max", + "groups": [ + { + "name": "zone0_ocp", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "neg_hysteresis": 2, + "pos_hysteresis": 2, + "index": 3, + "map": [ + { "value": 10.0, "target": 38.0 }, + { "value": 65.0, "target": 38.0 }, + { "value": 66.0, "target": 43.0 }, + { "value": 67.0, "target": 51.0 }, + { "value": 68.0, "target": 54.0 }, + { "value": 69.0, "target": 56.0 }, + { "value": 70.0, "target": 61.0 }, + { "value": 71.0, "target": 66.0 }, + { "value": 72.0, "target": 71.0 }, + { "value": 73.0, "target": 77.0 }, + { "value": 74.0, "target": 82.0 }, + { "value": 75.0, "target": 87.0 }, + { "value": 76.0, "target": 92.0 }, + { "value": 77.0, "target": 97.0 }, + { "value": 78.0, "target": 102.0 }, + { "value": 79.0, "target": 107.0 }, + { "value": 80.0, "target": 112.0 }, + { "value": 81.0, "target": 122.0 }, + { "value": 82.0, "target": 128.0 }, + { "value": 83.0, "target": 133.0 }, + { "value": 84.0, "target": 140.0 }, + { "value": 85.0, "target": 148.0 }, + { "value": 86.0, "target": 156.0 }, + { "value": 87.0, "target": 163.0 }, + { "value": 88.0, "target": 171.0 }, + { "value": 89.0, "target": 179.0 }, + { "value": 90.0, "target": 186.0 }, + { "value": 91.0, "target": 194.0 }, + { "value": 92.0, "target": 201.0 }, + { "value": 93.0, "target": 209.0 }, + { "value": 94.0, "target": 217.0 }, + { "value": 95.0, "target": 224.0 }, + { "value": 96.0, "target": 232.0 }, + { "value": 97.0, "target": 240.0 }, + { "value": 98.0, "target": 247.0 }, + { "value": 99.0, "target": 255.0 } + ] + } + ] + }, + { + "name": "target_mapping_from_BP_NVME_temp", + "groups": [ + { + "name": "zone0_bp_nvme", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + }, + { + "class": "timer", + "type": "repeating", + "interval": 5000000, + "preload_groups": true + } + ], + "actions": [ + { + "name": "target_from_group_max", + "groups": [ + { + "name": "zone0_bp_nvme", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "neg_hysteresis": 2, + "pos_hysteresis": 0, + "index": 4, + "map": [ + { "value": 10.0, "target": 38.0 }, + { "value": 35.0, "target": 38.0 }, + { "value": 36.0, "target": 43.0 }, + { "value": 37.0, "target": 48.0 }, + { "value": 38.0, "target": 54.0 }, + { "value": 39.0, "target": 59.0 }, + { "value": 40.0, "target": 64.0 }, + { "value": 41.0, "target": 66.0 }, + { "value": 42.0, "target": 69.0 }, + { "value": 43.0, "target": 71.0 }, + { "value": 44.0, "target": 74.0 }, + { "value": 45.0, "target": 77.0 }, + { "value": 46.0, "target": 79.0 }, + { "value": 47.0, "target": 82.0 }, + { "value": 48.0, "target": 84.0 }, + { "value": 49.0, "target": 87.0 }, + { "value": 50.0, "target": 89.0 }, + { "value": 51.0, "target": 99.0 }, + { "value": 52.0, "target": 99.0 }, + { "value": 53.0, "target": 105.0 }, + { "value": 54.0, "target": 110.0 }, + { "value": 55.0, "target": 115.0 }, + { "value": 56.0, "target": 120.0 }, + { "value": 57.0, "target": 125.0 }, + { "value": 58.0, "target": 130.0 }, + { "value": 59.0, "target": 135.0 }, + { "value": 60.0, "target": 140.0 }, + { "value": 61.0, "target": 150.0 }, + { "value": 62.0, "target": 161.0 }, + { "value": 63.0, "target": 171.0 }, + { "value": 64.0, "target": 181.0 }, + { "value": 65.0, "target": 191.0 }, + { "value": 66.0, "target": 204.0 }, + { "value": 67.0, "target": 217.0 }, + { "value": 68.0, "target": 230.0 }, + { "value": 69.0, "target": 255.0 } + ] + } + ] + }, + { + "name": "target_mapping_from_M2_NVME_temp", + "groups": [ + { + "name": "zone0_m2_nvme", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "triggers": [ + { + "class": "init", + "method": "get_properties" + }, + { + "class": "signal", + "signal": "properties_changed" + }, + { + "class": "timer", + "type": "repeating", + "interval": 5000000, + "preload_groups": true + } + ], + "actions": [ + { + "name": "target_from_group_max", + "groups": [ + { + "name": "zone0_m2_nvme", + "interface": "xyz.openbmc_project.Sensor.Value", + "property": { "name": "Value" } + } + ], + "neg_hysteresis": 2, + "pos_hysteresis": 0, + "index": 5, + "map": [ + { "value": 10.0, "target": 38.0 }, + { "value": 61.0, "target": 38.0 }, + { "value": 68.0, "target": 38.0 }, + { "value": 69.0, "target": 204.0 } + ] + } + ] + } +] diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json new file mode 100644 index 000000000000..a14cab645bc5 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json @@ -0,0 +1,44 @@ +[ + { + "name": "FAN3", + "zone": "0", + "sensors": ["PWM3"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + }, + { + "name": "FAN4", + "zone": "0", + "sensors": ["PWM4"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + }, + { + "name": "FAN5", + "zone": "0", + "sensors": ["PWM5"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + }, + { + "name": "FAN6", + "zone": "0", + "sensors": ["PWM6"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + }, + { + "name": "FAN7", + "zone": "0", + "sensors": ["PWM7"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + }, + { + "name": "FAN8", + "zone": "0", + "sensors": ["PWM8"], + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/" + } +] diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json new file mode 100644 index 000000000000..6bff7bb275ae --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json @@ -0,0 +1,80 @@ +[ + { + "name": "air_cooled_zone0_fans", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8" + ] + }, + { + "name": "fan3", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3/FAN3_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3/FAN3_2" + ] + }, + { + "name": "fan4", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4/FAN4_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4/FAN4_2" + ] + }, + { + "name": "fan5", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5/FAN5_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5/FAN5_2" + ] + }, + { + "name": "fan6", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6/FAN6_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6/FAN6_2" + ] + }, + { + "name": "fan7", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7/FAN7_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7/FAN7_2" + ] + }, + { + "name": "fan8", + "members": [ + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8/FAN8_1", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8/FAN8_2" + ] + }, + { + "name": "zone0_ambient", + "service": "xyz.openbmc_project.HwmonTempSensor", + "members": [ + "/xyz/openbmc_project/sensors/temperature/TS4_Temp" + ] + }, + { + "name": "zone0_ocp", + "members": [ + "/xyz/openbmc_project/sensors/temperature/OCP_Temp" + ] + }, + { + "name": "zone0_bp_nvme", + "members": [ + "/xyz/openbmc_project/sensors/temperature/nvme_bp_max" + ] + }, + { + "name": "zone0_m2_nvme", + "members": [ + "/xyz/openbmc_project/sensors/temperature/nvme_m2_max" + ] + } +] diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json new file mode 100644 index 000000000000..db706e0be812 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json @@ -0,0 +1,160 @@ +{ + "fans": [ + { + "inventory": "/system/chassis/Mt_Jade/FAN3", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN3_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM3", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN3_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM3", + "factor": 82, + "offset": 0 + } + ] + }, + { + "inventory": "/system/chassis/Mt_Jade/FAN4", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN4_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM4", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN4_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM4", + "factor": 82, + "offset": 0 + } + ] + }, + { + "inventory": "/system/chassis/Mt_Jade/FAN5", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN5_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM5", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN5_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM5", + "factor": 82, + "offset": 0 + } + ] + }, + { + "inventory": "/system/chassis/Mt_Jade/FAN6", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN6_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM6", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN6_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM6", + "factor": 82, + "offset": 0 + } + ] + }, + { + "inventory": "/system/chassis/Mt_Jade/FAN7", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN7_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM7", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN7_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM7", + "factor": 82, + "offset": 0 + } + ] + }, + { + "inventory": "/system/chassis/Mt_Jade/FAN8", + "allowed_out_of_range_time": 10, + "deviation": 25, + "num_sensors_nonfunc_for_fan_nonfunc": 1, + "monitor_start_delay": 30, + "set_func_on_present": false, + "sensors": [ + { + "name": "FAN8_1", + "has_target": true, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM8", + "factor": 82, + "offset": 0 + }, + { + "name": "FAN8_2", + "has_target": false, + "target_interface": "xyz.openbmc_project.Control.FanPwm", + "target_path": "/xyz/openbmc_project/control/fanpwm/PWM8", + "factor": 82, + "offset": 0 + } + ] + } + ] + } diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json new file mode 100644 index 000000000000..0eb829686d7b --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json @@ -0,0 +1,99 @@ +[ + { + "name": "FAN3", + "path": "/system/chassis/Mt_Jade/FAN3", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN3_1", + "FAN3_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + }, + { + "name": "FAN4", + "path": "/system/chassis/Mt_Jade/FAN4", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN4_1", + "FAN4_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + }, + { + "name": "FAN5", + "path": "/system/chassis/Mt_Jade/FAN5", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN5_1", + "FAN5_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + }, + { + "name": "FAN6", + "path": "/system/chassis/Mt_Jade/FAN6", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN6_1", + "FAN6_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + }, + { + "name": "FAN7", + "path": "/system/chassis/Mt_Jade/FAN7", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN7_1", + "FAN7_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + }, + { + "name": "FAN8", + "path": "/system/chassis/Mt_Jade/FAN8", + "methods": [ + { + "type": "tach", + "sensors": [ + "FAN8_1", + "FAN8_2" + ] + } + ], + "rpolicy": { + "type": "anyof" + } + } +] + diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json new file mode 100644 index 000000000000..d8ec74f5b209 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json @@ -0,0 +1,10 @@ +[ + { + "name": "0", + "poweron_target": 153, + "default_ceiling": 255, + "default_floor": 255, + "increase_delay": 5, + "decrease_interval": 30 + } +] \ No newline at end of file diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service new file mode 100644 index 000000000000..d50fafbc477e --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Fan Control Daemon +Wants=xyz.openbmc_project.fansensor.service +After=xyz.openbmc_project.fansensor.service +StartLimitIntervalSec=30 +StartLimitBurst=3 + +[Service] +Restart=on-failure +ExecStart=phosphor-fan-control +RestartSec=20 +ExecStopPost=/usr/bin/ampere_set_fan_max_speed.sh diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service new file mode 100644 index 000000000000..78efeede1d39 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Fan Monitor Daemon +Wants=xyz.openbmc_project.fansensor.service +After=xyz.openbmc_project.fansensor.service +StartLimitIntervalSec=30 +StartLimitBurst=3 + +[Service] +Restart=on-failure +ExecStart=phosphor-fan-monitor +RestartSec=20 +ExecStopPost=/usr/bin/ampere_set_fan_max_speed.sh diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend new file mode 100644 index 000000000000..fbcb1be0adda --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend @@ -0,0 +1,41 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" +FILESEXTRAPATHS:append := "${THISDIR}/${PN}/${MACHINE}:" + +RDEPENDS:${PN} += "bash" + +PACKAGECONFIG:append = " json" + +SRC_URI:append = " file://events.json \ + file://fans.json \ + file://groups.json \ + file://zones.json \ + file://monitor.json \ + file://presence.json \ + file://phosphor-fan-control@.service \ + file://phosphor-fan-monitor@.service \ + file://ampere_set_fan_max_speed.sh \ + " + +do_configure:prepend() { + mkdir -p ${S}/control/config_files/${MACHINE} + cp ${WORKDIR}/events.json ${S}/control/config_files/${MACHINE}/events.json + cp ${WORKDIR}/fans.json ${S}/control/config_files/${MACHINE}/fans.json + cp ${WORKDIR}/groups.json ${S}/control/config_files/${MACHINE}/groups.json + cp ${WORKDIR}/zones.json ${S}/control/config_files/${MACHINE}/zones.json + + mkdir -p ${S}/monitor/config_files/${MACHINE} + cp ${WORKDIR}/monitor.json ${S}/monitor/config_files/${MACHINE}/config.json + + mkdir -p ${S}/presence/config_files/${MACHINE} + cp ${WORKDIR}/presence.json ${S}/presence/config_files/${MACHINE}/config.json +} + +do_install:append() { + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/ampere_set_fan_max_speed.sh ${D}${bindir}/ampere_set_fan_max_speed.sh + install -d ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/phosphor-fan-monitor@.service ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/phosphor-fan-control@.service ${D}${systemd_system_unitdir} +} + + diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling.bb b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling.bb index 62b25b1f12ec..645847bf0302 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling.bb +++ b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling.bb @@ -5,43 +5,20 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7ca inherit obmc-phosphor-systemd -DEPENDS += "virtual/obmc-gpio-monitor" -RDEPENDS:${PN} += "virtual/obmc-gpio-monitor" +DEPENDS += "phosphor-gpio-monitor" +RDEPENDS:${PN} += "phosphor-gpio-monitor-monitor" RDEPENDS:${PN} += "bash" -SRC_URI += " \ - file://toggle_fault_led.sh \ - file://ampere_psu_reset_hotswap.sh \ - file://toggle_identify_led.sh \ - file://ampere_scp_failover.sh \ - " - AMPERE_MONITOR_INSTANCES = " \ - reboot_ack shutdown_ack id_button S0_scp_auth_failure \ - S0_overtemp S0_hightemp_start S0_hightemp_stop \ - S1_overtemp S1_hightemp_start S1_hightemp_stop \ - S0_fault_alert_start S0_fault_alert_stop \ - S1_fault_alert_start S1_fault_alert_stop \ - PSU1_VIN_GOOD PSU2_VIN_GOOD \ + S0_hightemp_start S0_hightemp_stop \ + S1_hightemp_start S1_hightemp_stop \ " SYSTEMD_ENVIRONMENT_FILE:${PN} +=" \ - obmc/gpio/reboot_ack \ - obmc/gpio/shutdown_ack \ - obmc/gpio/id_button \ - obmc/gpio/S0_scp_auth_failure \ - obmc/gpio/S0_overtemp \ obmc/gpio/S0_hightemp_start \ obmc/gpio/S0_hightemp_stop \ - obmc/gpio/S1_overtemp \ obmc/gpio/S1_hightemp_start \ obmc/gpio/S1_hightemp_stop \ - obmc/gpio/S0_fault_alert_start \ - obmc/gpio/S0_fault_alert_stop \ - obmc/gpio/S1_fault_alert_start \ - obmc/gpio/S1_fault_alert_stop \ - obmc/gpio/PSU1_VIN_GOOD \ - obmc/gpio/PSU2_VIN_GOOD \ " TMPL = "phosphor-gpio-monitor@.service" @@ -50,22 +27,8 @@ TGT = "multi-user.target" FMT = "../${TMPL}:${TGT}.requires/${INSTFMT}" SYSTEMD_SERVICE:${PN} += " \ - ampere-host-shutdown-ack@.service \ - ampere_overtemp@.service \ ampere_hightemp_start@.service \ ampere_hightemp_stop@.service \ - ampere_fault_led_start@.service \ - ampere_fault_led_stop@.service \ - psu_hotswap_reset@.service \ - id-button-pressed.service \ - ampere_scp_failover.service \ " SYSTEMD_LINK:${PN} += "${@compose_list(d, 'FMT', 'AMPERE_MONITOR_INSTANCES')}" -do_install() { - install -d ${D}${sbindir} - install -m 0755 ${WORKDIR}/toggle_fault_led.sh ${D}${sbindir}/ - install -m 0755 ${WORKDIR}/toggle_identify_led.sh ${D}${sbindir}/ - install -m 0755 ${WORKDIR}/ampere_psu_reset_hotswap.sh ${D}${sbindir}/ - install -m 0755 ${WORKDIR}/ampere_scp_failover.sh ${D}${sbindir}/ -} diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_start@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_start@.service deleted file mode 100644 index 18ee1bee52d9..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_start@.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Ampere Computing LLC fault event condition service -Wants=mapper-wait@-xyz-openbmc_project-led-groups.service -After=mapper-wait@-xyz-openbmc_project-led-groups.service -StartLimitIntervalSec=0 - -[Service] -Type=oneshot -ExecStart=/usr/bin/env toggle_fault_led.sh %i on -SyslogIdentifier=fault-led diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_stop@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_stop@.service deleted file mode 100644 index 83f442cef404..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_fault_led_stop@.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Ampere Computing LLC fault event condition service -Wants=mapper-wait@-xyz-openbmc_project-led-groups.service -After=mapper-wait@-xyz-openbmc_project-led-groups.service -StartLimitIntervalSec=0 - -[Service] -Type=oneshot -ExecStart=/usr/bin/env toggle_fault_led.sh %i off -SyslogIdentifier=fault-led diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_overtemp@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_overtemp@.service deleted file mode 100644 index 587cba195d33..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_overtemp@.service +++ /dev/null @@ -1,7 +0,0 @@ -[Unit] -Description=Ampere Computing LLC Overtemp event - -[Service] -Restart=no -ExecStart=/usr/bin/env obmcutil chassisoff -ExecStartPost=/usr/bin/env ampere_add_redfishevent.sh OpenBMC.0.1.CPUThermalTrip.Critical %i diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/id-button-pressed.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/id-button-pressed.service deleted file mode 100644 index f633fc30769b..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/id-button-pressed.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=ID Button Pressed Service -Wants=mapper-wait@-xyz-openbmc_project-led-groups.service -After=mapper-wait@-xyz-openbmc_project-led-groups.service -StartLimitIntervalSec=0 - -[Service] -Type=oneshot -ExecStart=/usr/bin/env toggle_identify_led.sh -SyslogIdentifier=id-button diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU1_VIN_GOOD b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU1_VIN_GOOD deleted file mode 100644 index cf13085b1d65..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU1_VIN_GOOD +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=60 -POLARITY=0 -TARGET=psu_hotswap_reset@0.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU2_VIN_GOOD b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU2_VIN_GOOD deleted file mode 100644 index 7588c2595cf5..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/PSU2_VIN_GOOD +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=61 -POLARITY=0 -TARGET=psu_hotswap_reset@1.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_start b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_start deleted file mode 100644 index c13da449c7c3..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_start +++ /dev/null @@ -1,5 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=73 -POLARITY=1 -TARGET=ampere_fault_led_start@0.service -EXTRA_ARGS=--continue diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_stop b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_stop deleted file mode 100644 index 7233f881a89f..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_fault_alert_stop +++ /dev/null @@ -1,5 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=73 -POLARITY=0 -TARGET=ampere_fault_led_stop@0.service -EXTRA_ARGS=--continue diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_overtemp b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_overtemp deleted file mode 100644 index e39e19680505..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_overtemp +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=51 -POLARITY=1 -TARGET=ampere_overtemp@0.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_scp_auth_failure b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_scp_auth_failure deleted file mode 100644 index e8e975f9f0b1..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S0_scp_auth_failure +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=74 -POLARITY=1 -TARGET=ampere_scp_failover.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_start b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_start deleted file mode 100644 index 6fa47857bf8e..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_start +++ /dev/null @@ -1,5 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=201 -POLARITY=1 -TARGET=ampere_fault_led_start@1.service -EXTRA_ARGS=--continue diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_stop b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_stop deleted file mode 100644 index 36b29ec462aa..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_fault_alert_stop +++ /dev/null @@ -1,5 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=201 -POLARITY=0 -TARGET=ampere_fault_led_stop@1.service -EXTRA_ARGS=--continue diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_overtemp b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_overtemp deleted file mode 100644 index c7bb8c1bc464..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/S1_overtemp +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=206 -POLARITY=1 -TARGET=ampere_overtemp@1.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/id_button b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/id_button deleted file mode 100644 index 70e2b585b2e1..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/id_button +++ /dev/null @@ -1,5 +0,0 @@ -DEVPATH=/dev/input/by-path/platform-gpio-keys-event -KEY=133 -POLARITY=1 -TARGET=id-button-pressed.service -EXTRA_ARGS=--continue diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/reboot_ack b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/reboot_ack deleted file mode 100644 index a8ad98ee7574..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/reboot_ack +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/event0 -KEY=75 -POLARITY=1 -TARGET=obmc-host-force-warm-reboot@0.target diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/shutdown_ack b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/shutdown_ack deleted file mode 100644 index 18cc87246f60..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/obmc/gpio/shutdown_ack +++ /dev/null @@ -1,4 +0,0 @@ -DEVPATH=/dev/input/event0 -KEY=50 -POLARITY=1 -TARGET=ampere-host-shutdown-ack@0.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_fault_led.sh b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_fault_led.sh deleted file mode 100644 index 58aa47f8e8f1..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_fault_led.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# -# Toggle the state of identify LED Group - -socket=$1 -isOn=$2 - -# Create /tmp/fault* file -if [ "$isOn" == "on" ]; then - touch /tmp/fault"$socket" -else - rm /tmp/fault"$socket" -fi - -# Set Fault Led state -if [[ -f /tmp/fault0 ]] || [[ -f /tmp/fault1 ]]; then - target='true' -else - target='false' -fi - -SERVICE="xyz.openbmc_project.LED.GroupManager" -INTERFACE="xyz.openbmc_project.Led.Group" -PROPERTY="Asserted" - -# Get current state -object=$(busctl tree $SERVICE --list | grep system_fault) - -# Set target state -busctl set-property $SERVICE "$object" $INTERFACE $PROPERTY b $target diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_identify_led.sh b/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_identify_led.sh deleted file mode 100755 index f6eae0e245b3..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/toggle_identify_led.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# -# Toggle the state of identify LED Group - -SERVICE="xyz.openbmc_project.LED.GroupManager" -INTERFACE="xyz.openbmc_project.Led.Group" -PROPERTY="Asserted" - -# Get enclosure_identify state -identify_object=$(busctl tree $SERVICE --list | grep -m 1 identify) -identify_state=$(busctl get-property $SERVICE "$identify_object" $INTERFACE $PROPERTY \ - | awk '{print $NF;}') - -# Get enclosure_identify_blink state -identify_blink_object=$(busctl tree $SERVICE --list | grep identify_blink) -identify_blink_state=$(busctl get-property $SERVICE "$identify_blink_object" $INTERFACE $PROPERTY \ - | awk '{print $NF;}') - -# Set state -if [ "$identify_state" = "false" ] && [ "$identify_blink_state" = "false" ]; then - # Turn on the UID LED - busctl set-property $SERVICE "$identify_object" $INTERFACE $PROPERTY b true -elif [ "$identify_state" = "false" ] && [ "$identify_blink_state" = "true" ]; then - # Turn off the UID LED when LED is blinking state - busctl set-property $SERVICE "$identify_blink_object" $INTERFACE $PROPERTY b false -elif [ "$identify_state" = "true" ] && [ "$identify_blink_state" = "false" ]; then - # Turn off the UID LED - busctl set-property $SERVICE "$identify_object" $INTERFACE $PROPERTY b false -else - echo "Invalid case! When identify_blink_state is true, the identify_state will set to false" -fi diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere-host-shutdown-ack@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service similarity index 100% rename from meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere-host-shutdown-ack@.service rename to meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service new file mode 100644 index 000000000000..a3efc9ff9996 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Ampere Computing LLC Overtemp event + +[Service] +Restart=no +ExecStart=/bin/sh -c "touch /tmp/fault_overtemp && obmcutil chassisoff" +ExecStartPost=/bin/sh -c "ampere_add_redfishevent.sh OpenBMC.0.1.CPUThermalTrip.Critical %i && sleep 10 && rm /tmp/fault_overtemp" diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_psu_reset_hotswap.sh b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_psu_reset_hotswap.sh similarity index 100% rename from meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_psu_reset_hotswap.sh rename to meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_psu_reset_hotswap.sh diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_scp_failover.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_scp_failover.service similarity index 100% rename from meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_scp_failover.service rename to meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_scp_failover.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_scp_failover.sh b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_scp_failover.sh similarity index 89% rename from meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_scp_failover.sh rename to meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_scp_failover.sh index 56319a30745e..c1c16aba5c82 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/ampere_scp_failover.sh +++ b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_scp_failover.sh @@ -7,6 +7,8 @@ # and logs an event in SEL. # shellcheck disable=SC1091 +# shellcheck disable=SC2046 + source /usr/sbin/gpio-lib.sh source /usr/sbin/gpio-defs.sh @@ -16,7 +18,7 @@ if [ "${I2C_BACKUP_SEL}" == "1" ]; then # If it is HIGH, set it LOW. Then reset the Host to boot from # the failover Boot EEPROM. echo "scp-failover: switch HOST to failover boot EEPROM" - gpioset "$(gpiofind BMC_SELECT_EEPROM)"=0 + gpioset $(gpiofind BMC_SELECT_EEPROM)=0 # Reset the Host to boot on the failover EEPROM ampere_power_util.sh mb force_reset @@ -25,7 +27,7 @@ else obmcutil chassisoff echo "scp-failover: switch HOST back to the main Boot EEPROM" - gpioset "$(gpiofind BMC_SELECT_EEPROM)"=1 + gpioset $(gpiofind BMC_SELECT_EEPROM)=1 # Log event ampere_add_redfishevent.sh OpenBMC.0.1.GeneralFirmwareSecurityViolation.Critical "SCP Authentication failure" diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json new file mode 100644 index 000000000000..7b89a145be42 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json @@ -0,0 +1,53 @@ +[ + { + "Name": "REBOOT_ACK", + "ChipId": "0", + "GpioNum": 75, + "EventMon": "FALLING", + "Target": "obmc-host-force-warm-reboot@0.target", + "Continue": true + }, + { + "Name": "SHUTDOWN_ACK", + "ChipId": "0", + "GpioNum": 50, + "EventMon": "FALLING", + "Target": "ampere-host-shutdown-ack@0.service", + "Continue": true + }, + { + "Name": "S0_OVERTEMP", + "LineName": "S0_OVERTEMP_L", + "EventMon": "FALLING", + "Target": "ampere_overtemp@0.service", + "Continue": true + }, + { + "Name": "S1_OVERTEMP", + "LineName": "S1_OVERTEMP_L", + "EventMon": "FALLING", + "Target": "ampere_overtemp@1.service", + "Continue": true + }, + { + "Name": "S0_SCP_AUTH_FAIL", + "LineName": "S0_SCP_AUTH_FAIL_L", + "EventMon": "FALLING", + "Target": "ampere_scp_failover.service", + "Continue": true + }, + { + "Name": "PSU1_VIN_GOOD", + "LineName": "PSU1_VIN_GOOD", + "EventMon": "RISING", + "Target": "psu_hotswap_reset@0.service", + "Continue": true + }, + { + "Name": "PSU2_VIN_GOOD", + "LineName": "PSU2_VIN_GOOD", + "EventMon": "RISING", + "Target": "psu_hotswap_reset@1.service", + "Continue": true + } +] diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/psu_hotswap_reset@.service b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/psu_hotswap_reset@.service similarity index 100% rename from meta-ampere/meta-jade/recipes-phosphor/gpio/ampere-gpio-handling/psu_hotswap_reset@.service rename to meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor/psu_hotswap_reset@.service diff --git a/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend new file mode 100644 index 000000000000..f798fee8359c --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend @@ -0,0 +1,35 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +inherit systemd +inherit obmc-phosphor-systemd + +RDEPENDS:${PN}-monitor += "bash" +RDEPENDS:${PN} += "bash" + +SRC_URI += " \ + file://phosphor-multi-gpio-monitor.json \ + file://ampere_scp_failover.sh \ + file://ampere_psu_reset_hotswap.sh \ + " + +SYSTEMD_SERVICE:${PN}-monitor += " \ + ampere-host-shutdown-ack@.service \ + ampere_overtemp@.service \ + ampere_scp_failover.service \ + psu_hotswap_reset@.service \ + " + +FILES:${PN}-monitor += " \ + /usr/share/${PN}/phosphor-multi-gpio-monitor.json \ + /usr/sbin/ampere_scp_failover.sh \ + /usr/sbin/ampere_psu_reset_hotswap.sh \ + " + +SYSTEMD_LINK:${PN}-monitor:append = " ../phosphor-multi-gpio-monitor.service:multi-user.target.requires/phosphor-multi-gpio-monitor.service" + +do_install:append() { + install -d ${D}${sbindir} + install -m 0644 ${WORKDIR}/phosphor-multi-gpio-monitor.json ${D}${datadir}/${PN}/ + install -m 0755 ${WORKDIR}/ampere_scp_failover.sh ${D}${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_psu_reset_hotswap.sh ${D}${sbindir}/ +} diff --git a/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf new file mode 100644 index 000000000000..e0c10a42ed80 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf @@ -0,0 +1,3 @@ +# SOCKET-ID is default to obmc-console +MODE=stream +STREAM_DST=/run/rsyslog/console/cpu diff --git a/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf new file mode 100644 index 000000000000..faaf1a458ede --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS1 +MODE=stream +STREAM_DST=/run/rsyslog/console/scp0 diff --git a/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf new file mode 100644 index 000000000000..5d3cfb68280c --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS2 +MODE=stream +STREAM_DST=/run/rsyslog/console/atf diff --git a/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf new file mode 100644 index 000000000000..14bfd4b2c1ab --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS3 +MODE=stream +STREAM_DST=/run/rsyslog/console/scp1 diff --git a/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend new file mode 100644 index 000000000000..38521ade21f6 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend @@ -0,0 +1,18 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI:append = " \ + file://ttyS0.conf \ + file://ttyS1.conf \ + file://ttyS2.conf \ + file://ttyS3.conf \ + " + +do_install:append() { + + # Install the configurations + install -m 0755 -d ${D}${sysconfdir}/${BPN} + install -m 0644 ${WORKDIR}/*.conf ${D}${sysconfdir}/${BPN}/ + + # Remove upstream-provided default configuration + rm -f ${D}${sysconfdir}/${BPN}/ttyVUART0.conf +} diff --git a/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend index 23358f003ccd..eadb7e4a4884 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend +++ b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend @@ -1 +1 @@ -FILESEXTRAPATHS:append:mtjade := "${THISDIR}/${PN}:" +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" diff --git a/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json new file mode 100644 index 000000000000..4998665c844b --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json @@ -0,0 +1,178 @@ +{ + "0" : { + "name" : "IPMB", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "ipmb", + "protocol_type" : "ipmb-1.0", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "1" : { + "name" : "eth0", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "2" : { + "name" : "eth1", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "3" : { + "name" : "usb0", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "4" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "5" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "6" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "7" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "8" : { + "name" : "INTRABMC", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "oem", + "protocol_type" : "oem", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "9" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "10" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "11" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "12" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "13" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "14" : { + "name" : "SELF", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "ipmb", + "protocol_type" : "ipmb-1.0", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "15" : { + "name" : "ipmi_ssif", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "smbus-v2.0", + "protocol_type" : "ipmi-smbus", + "session_supported" : "session-less", + "is_ipmi" : true + } + } +} diff --git a/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif/ssifbridge.service b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif/ssifbridge.service new file mode 100644 index 000000000000..71232abf3408 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif/ssifbridge.service @@ -0,0 +1,19 @@ +[Unit] +Description=Phosphor IPMI SSIF DBus Bridge +StartLimitBurst=3 +StartLimitIntervalSec=300 +After=phosphor-ipmi-host.service + +[Service] +Restart=always +RestartSec=10 +TimeoutStartSec=60 +TimeoutStopSec=60 +ExecStart=/usr/bin/ssifbridged +ExecStopPost=/bin/sh -c "/usr/bin/gpioset 0 228=0" +ExecStartPost=/bin/sh -c "/usr/bin/gpioset 0 228=1" +SyslogIdentifier=ssifbridged + +[Install] +WantedBy=multi-user.target +RequiredBy= diff --git a/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif_%.bbappend new file mode 100644 index 000000000000..d08dfd2d2d87 --- /dev/null +++ b/meta-ampere/meta-jade/recipes-phosphor/ipmi/phosphor-ipmi-ssif_%.bbappend @@ -0,0 +1,7 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +SRC_URI += " file://ssifbridge.service" + +do_install:append() { + cp ${WORKDIR}/ssifbridge.service ${D}${systemd_system_unitdir}/ssifbridge.service +} diff --git a/meta-ampere/meta-jade/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend b/meta-ampere/meta-jade/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend index 3656006b0db0..5e726c363b59 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend +++ b/meta-ampere/meta-jade/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend @@ -1,16 +1,16 @@ -RDEPENDS:${PN}-extras:append:mtjade = " \ - webui-vue \ - phosphor-image-signing \ - phosphor-virtual-sensor \ - phosphor-misc-usb-ctrl \ - ampere-gpio-handling \ - " +RDEPENDS:${PN}-extras:append = " \ + webui-vue \ + phosphor-image-signing \ + phosphor-virtual-sensor \ + phosphor-misc-usb-ctrl \ + ampere-gpio-handling \ + " -RDEPENDS:${PN}-inventory:append:mtjade = " \ - dbus-sensors \ - entity-manager \ - " +RDEPENDS:${PN}-inventory:append = " \ + dbus-sensors \ + entity-manager \ + " -RDEPENDS:${PN}-extras:remove:mtjade = " phosphor-hwmon" +RDEPENDS:${PN}-extras:remove = " phosphor-hwmon" VIRTUAL-RUNTIME_obmc-sensors-hwmon ?= "dbus-sensors" -RDEPENDS:${PN}-extras:append:mtjade = " phosphor-virtual-sensor" +RDEPENDS:${PN}-extras:append = " phosphor-virtual-sensor" diff --git a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme/nvme_config.json b/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme/nvme_config.json deleted file mode 100644 index 9c2aade75dd5..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme/nvme_config.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "config": [ - { - "NVMeDriveIndex": 0, - "NVMeDriveBusID": 50 - }, - { - "NVMeDriveIndex": 1, - "NVMeDriveBusID": 51 - }, - { - "NVMeDriveIndex": 2, - "NVMeDriveBusID": 52 - }, - { - "NVMeDriveIndex": 3, - "NVMeDriveBusID": 53 - }, - { - "NVMeDriveIndex": 4, - "NVMeDriveBusID": 54 - }, - { - "NVMeDriveIndex": 5, - "NVMeDriveBusID": 55 - }, - { - "NVMeDriveIndex": 6, - "NVMeDriveBusID": 56 - }, - { - "NVMeDriveIndex": 7, - "NVMeDriveBusID": 57 - }, - { - "NVMeDriveIndex": 8, - "NVMeDriveBusID": 60 - }, - { - "NVMeDriveIndex": 9, - "NVMeDriveBusID": 61 - }, - { - "NVMeDriveIndex": 10, - "NVMeDriveBusID": 62 - }, - { - "NVMeDriveIndex": 11, - "NVMeDriveBusID": 63 - }, - { - "NVMeDriveIndex": 12, - "NVMeDriveBusID": 64 - }, - { - "NVMeDriveIndex": 13, - "NVMeDriveBusID": 65 - }, - { - "NVMeDriveIndex": 14, - "NVMeDriveBusID": 66 - }, - { - "NVMeDriveIndex": 15, - "NVMeDriveBusID": 67 - }, - { - "NVMeDriveIndex": 16, - "NVMeDriveBusID": 70 - }, - { - "NVMeDriveIndex": 17, - "NVMeDriveBusID": 71 - }, - { - "NVMeDriveIndex": 18, - "NVMeDriveBusID": 72 - }, - { - "NVMeDriveIndex": 19, - "NVMeDriveBusID": 73 - }, - { - "NVMeDriveIndex": 20, - "NVMeDriveBusID": 74 - }, - { - "NVMeDriveIndex": 21, - "NVMeDriveBusID": 75 - }, - { - "NVMeDriveIndex": 22, - "NVMeDriveBusID": 76 - }, - { - "NVMeDriveIndex": 23, - "NVMeDriveBusID": 77 - }, - { - "NVMeDriveIndex": 24, - "NVMeDriveBusID": 80 - }, - { - "NVMeDriveIndex": 25, - "NVMeDriveBusID": 81 - } - ], - "threshold": [ - { - "criticalHigh": 80, - "criticalLow": 0, - "warningHigh": 70, - "warningLow": 5, - "maxValue": 127, - "minValue": -128 - } - ] -} diff --git a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme_%.bbappend deleted file mode 100644 index 5eadc25f74b9..000000000000 --- a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-nvme_%.bbappend +++ /dev/null @@ -1,8 +0,0 @@ -FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" - -SRC_URI += " file://nvme_config.json" - -do_install:append() { - install -m 0644 -D ${WORKDIR}/nvme_config.json \ - ${D}/etc/nvme -} diff --git a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-virtual-sensor/virtual_sensor_config.json b/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-virtual-sensor/virtual_sensor_config.json index eabda2e3bdd2..3bc8bf38ae6f 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-virtual-sensor/virtual_sensor_config.json +++ b/meta-ampere/meta-jade/recipes-phosphor/sensors/phosphor-virtual-sensor/virtual_sensor_config.json @@ -46,15 +46,11 @@ "Expression": "((P0 == P0) ? P0 : 0) + ((P1 == P1) ? P1 : 0)" }, { - "Desc": { - "Name": "S1_CPU_Pwr", - "SensorType": "power" - }, - "Threshold" : - { - "CriticalHigh": 500 + "Desc":{ + "Name":"nvme_bp_max", + "SensorType":"temperature" }, - "Associations": + "Associations": [ [ "chassis", @@ -67,31 +63,6 @@ "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade" ] ], - "Params": { - "DbusParam": [ - { - "ParamName": "P1", - "Desc": { - "Name": "S1_Core_VRD_Pwr", - "SensorType": "power" - } - }, - { - "ParamName": "P2", - "Desc": { - "Name": "S1_SOC_VRD_Pwr", - "SensorType": "power" - } - } - ] - }, - "Expression": "(P1 + P2) >= 0 ? (P1 + P2) : NULL" - }, - { - "Desc":{ - "Name":"nvme_bp_max", - "SensorType":"temperature" - }, "Params":{ "DbusParam": [ { @@ -264,13 +235,26 @@ } ] }, - "Expression": "max(0,(n0 == n0) ? n0 : NULL,(n1 == n1) ? n1 : NULL,(n2 == n2) ? n2 : NULL,(n3 == n3) ? n3 : NULL,(n4 == n4) ? n4 : NULL,(n5 == n5) ? n5 : NULL,(n6 == n6) ? n6 : NULL,(n7 == n7) ? n7 : NULL,(n8 == n8) ? n8 : NULL,(n9 == n9) ? n9 : NULL,(n10 == n10) ? n10 : NULL,(n11 == n11) ? n11 : NULL,(n12 == n12) ? n12 : NULL,(n13 == n13) ? n13 : NULL,(n14 == n14) ? n14 : NULL,(n15 == n15) ? n15 : NULL,(n16 == n16) ? n16 : NULL,(n17 == n17) ? n17 : NULL,(n18 == n18) ? n18 : NULL,(n19 == n19) ? n19 : NULL,(n20 == n20) ? n20 : NULL,(n21 == n21) ? n21 : NULL,(n22 == n22) ? n22 : NULL,(n23 == n23) ? n23 : NULL)" + "Expression": "max((n0 == n0) ? n0 : 0,(n1 == n1) ? n1 : 0,(n2 == n2) ? n2 : 0,(n3 == n3) ? n3 : 0,(n4 == n4) ? n4 : 0,(n5 == n5) ? n5 : 0,(n6 == n6) ? n6 : 0,(n7 == n7) ? n7 : 0,(n8 == n8) ? n8 : 0,(n9 == n9) ? n9 : 0,(n10 == n10) ? n10 : 0,(n11 == n11) ? n11 : 0,(n12 == n12) ? n12 : 0,(n13 == n13) ? n13 : 0,(n14 == n14) ? n14 : 0,(n15 == n15) ? n15 : 0,(n16 == n16) ? n16 : 0,(n17 == n17) ? n17 : 0,(n18 == n18) ? n18 : 0,(n19 == n19) ? n19 : 0,(n20 == n20) ? n20 : 0,(n21 == n21) ? n21 : 0,(n22 == n22) ? n22 : 0,(n23 == n23) ? n23 : 0)" }, { "Desc":{ "Name":"nvme_m2_max", "SensorType":"temperature" }, + "Associations": + [ + [ + "chassis", + "all_sensors", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade" + ], + [ + "inventory", + "sensors", + "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade" + ] + ], "Params":{ "DbusParam": [ { @@ -289,7 +273,7 @@ } ] }, - "Expression": "max(0,(n24 == n24) ? n24 : NULL,(n25 == n25) ? n25 : NULL)" + "Expression": "max((n24 == n24) ? n24 : 0,(n25 == n25) ? n25 : 0)" } ] diff --git a/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf/gpio_defs.json b/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf/gpio_defs.json index 0b6ad45afc1c..009defda1ea2 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf/gpio_defs.json +++ b/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf/gpio_defs.json @@ -49,6 +49,11 @@ "name": "RESET_BUTTON", "pin": "R5", "direction": "both" + }, + { + "name": "ID_BTN", + "pin": "Q5", + "direction": "both" } ] } diff --git a/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend index 23358f003ccd..eadb7e4a4884 100644 --- a/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend +++ b/meta-ampere/meta-jade/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend @@ -1 +1 @@ -FILESEXTRAPATHS:append:mtjade := "${THISDIR}/${PN}:" +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" diff --git a/meta-ampere/meta-mitchell/conf/layer.conf b/meta-ampere/meta-mitchell/conf/layer.conf new file mode 100644 index 000000000000..8f58810bfdfd --- /dev/null +++ b/meta-ampere/meta-mitchell/conf/layer.conf @@ -0,0 +1,11 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "mitchell-layer" +BBFILE_PATTERN_mitchell-layer := "^${LAYERDIR}/" +LAYERSERIES_COMPAT_mitchell-layer = "langdale mickledore" + diff --git a/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf b/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf new file mode 100644 index 000000000000..339c7c1ee50d --- /dev/null +++ b/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf @@ -0,0 +1,46 @@ +KMACHINE = "aspeed" +KERNEL_DEVICETREE = "${KMACHINE}-bmc-ampere-mtmitchell.dtb" +UBOOT_DEVICETREE = "ast2600-bletchley" +UBOOT_MACHINE = "ast2600_openbmc_spl_defconfig" +SPL_BINARY = "spl/u-boot-spl.bin" +SOCSEC_SIGN_ENABLE = "0" + +SERIAL_CONSOLES = "115200;ttyS4" + +require conf/machine/include/ast2600.inc +require conf/machine/include/obmc-bsp-common.inc + +FLASH_SIZE = "65536" +VOLATILE_LOG_DIR = "no" + +MACHINE_FEATURES += "\ + obmc-bmc-state-mgmt \ + obmc-chassis-state-mgmt \ + obmc-host-ipmi \ + obmc-host-state-mgmt \ + obmc-phosphor-chassis-mgmt \ + obmc-phosphor-flash-mgmt \ + " + +OBMC_IMAGE_EXTRA_INSTALL:append = " \ + ampere-utils \ + ampere-usbnet \ + phosphor-misc-usb-ctrl \ + ampere-platform-init \ + ampere-ipmi-oem \ + ampere-hostctrl \ + ampere-driver-binder \ + ampere-mac-update \ + phosphor-ipmi-blobs \ + phosphor-ipmi-blobs-binarystore \ + util-linux \ + ampere-sysfw-hang-handler \ + " + +PREFERRED_PROVIDER_virtual/obmc-chassis-mgmt = "packagegroup-obmc-ampere-apps" +PREFERRED_PROVIDER_virtual/obmc-system-mgmt = "packagegroup-obmc-ampere-apps" +PREFERRED_PROVIDER_virtual/obmc-flash-mgmt = "packagegroup-obmc-ampere-apps" +PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw = "phosphor-ipmi-ssif" +PREFERRED_PROVIDER_virtual/phosphor-led-manager-config-native = "ampere-led-manager-config-native" + +OVERRIDES .= ":ampere" diff --git a/meta-ampere/meta-mitchell/conf/templates/default/bblayers.conf.sample b/meta-ampere/meta-mitchell/conf/templates/default/bblayers.conf.sample new file mode 100644 index 000000000000..a6e860f3b896 --- /dev/null +++ b/meta-ampere/meta-mitchell/conf/templates/default/bblayers.conf.sample @@ -0,0 +1,31 @@ +# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +LCONF_VERSION = "8" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-openembedded/meta-oe \ + ##OEROOT##/meta-openembedded/meta-networking \ + ##OEROOT##/meta-openembedded/meta-perl \ + ##OEROOT##/meta-openembedded/meta-python \ + ##OEROOT##/meta-security \ + ##OEROOT##/meta-phosphor \ + ##OEROOT##/meta-aspeed \ + ##OEROOT##/meta-ampere \ + ##OEROOT##/meta-ampere/meta-mitchell \ + " +BBLAYERS_NON_REMOVABLE ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-openembedded/meta-oe \ + ##OEROOT##/meta-openembedded/meta-networking \ + ##OEROOT##/meta-openembedded/meta-perl \ + ##OEROOT##/meta-openembedded/meta-python \ + ##OEROOT##/meta-security \ + ##OEROOT##/meta-phosphor \ + ##OEROOT##/meta-aspeed \ + ##OEROOT##/meta-ampere \ + ##OEROOT##/meta-ampere/meta-mitchell \ + " diff --git a/meta-bytedance/meta-g220a/conf/conf-notes.txt b/meta-ampere/meta-mitchell/conf/templates/default/conf-notes.txt similarity index 100% rename from meta-bytedance/meta-g220a/conf/conf-notes.txt rename to meta-ampere/meta-mitchell/conf/templates/default/conf-notes.txt diff --git a/meta-ampere/meta-mitchell/conf/templates/default/local.conf.sample b/meta-ampere/meta-mitchell/conf/templates/default/local.conf.sample new file mode 100644 index 000000000000..b852ff05e1c7 --- /dev/null +++ b/meta-ampere/meta-mitchell/conf/templates/default/local.conf.sample @@ -0,0 +1,214 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +MACHINE ??= "mtmitchell" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "openbmc-phosphor" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to ipk: +PACKAGE_CLASSES ?= "package_ipk" + +# +# SDK/ADT target architecture +# +# This variable specifies the architecture to build SDK/ADT items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686 and x86_64 +#SDKMACHINE ?= "i686" + +SANITY_TESTED_DISTROS:append ?= " *" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, exmap, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-swab' to perform host system intrusion detection +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +USER_CLASSES ?= "buildstats" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. To +# enable this uncomment this line. See classes/testimage(-auto).bbclass for +# further details. +#TEST_IMAGE = "1" +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necessary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS ??= "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + HALT,${TMPDIR},100M,1K \ + HALT,${DL_DIR},100M,1K \ + HALT,${SSTATE_DIR},100M,1K \ + HALT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + + +# +# Qemu configuration +# +# By default qemu will build with a builtin VNC server where graphical output can be +# seen. The two lines below enable the SDL backend too. This assumes there is a +# libsdl library available on your build system. +#PACKAGECONFIG_append_pn-qemu-native = " sdl" +#PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl" +#ASSUME_PROVIDED += "libsdl-native" + + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "2" diff --git a/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler.bb b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler.bb new file mode 100644 index 000000000000..7562cbdaa4bb --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler.bb @@ -0,0 +1,31 @@ +SUMMARY = "Ampere Computing LLC System Firmware Hang Handler" +DESCRIPTION = "A host control implementation suitable for Ampere Computing LLC's systems" +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit systemd +inherit obmc-phosphor-systemd + +RDEPENDS:${PN} = "bash" +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +SYSTEMD_PACKAGES = "${PN}" + +SRC_URI = " \ + file://ampere-sysfw-hang-handler.service \ + file://ampere_sysfw_hang_handler.sh \ + " + +SYSTEMD_SERVICE:${PN} += "ampere-sysfw-hang-handler.service" + +SYSFW_HANG_TGT = "ampere-sysfw-hang-handler.service" +SYSFW_HANG_INSTMPL = "ampere-sysfw-hang-handler.service" +AMPER_HOST_RUNNING = "obmc-host-already-on@{0}.target" +SYSFW_HANG_TARGET_FMT = "../${SYSFW_HANG_TGT}:${AMPER_HOST_RUNNING}.wants/${SYSFW_HANG_INSTMPL}" +SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'SYSFW_HANG_TARGET_FMT', 'OBMC_HOST_INSTANCES')}" + +do_install() { + install -d ${D}/usr/sbin + install -m 0755 ${WORKDIR}/ampere_sysfw_hang_handler.sh ${D}/${sbindir}/ +} diff --git a/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere-sysfw-hang-handler.service b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere-sysfw-hang-handler.service new file mode 100644 index 000000000000..5eeaf5cc96fd --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere-sysfw-hang-handler.service @@ -0,0 +1,13 @@ +[Unit] +Description=Ampere System Firmware Hang Handler +After=obmc-host-already-on@0.target +BindTo=obmc-host-already-on@0.target +ConditionPathExists=!/var/ampere/sysfw-hang-disable + +[Service] +Type=simple +ExecStart=/usr/bin/env ampere_sysfw_hang_handler.sh +SyslogIdentifier=ampere_sysfw_hang + +[Install] +WantedBy=obmc-host-already-on@0.target diff --git a/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere_sysfw_hang_handler.sh b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere_sysfw_hang_handler.sh new file mode 100644 index 000000000000..c3f77fd8b1cf --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/host/ampere-sysfw-hang-handler/ampere_sysfw_hang_handler.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# shellcheck disable=SC2046 +# shellcheck source=/dev/null + +source /usr/sbin/gpio-lib.sh + +# Do event trigger +function sel_trigger() +{ + echo "Error: system firmware hang, trigger sel" + ampere_add_redfishevent.sh OpenBMC.0.1.SystemPowerOnFailed.Critical +} + +# Do reset the system +function reset_system() +{ + echo "Error: system firmware hang, reset the system" + ipmitool chassis power reset +} + +s0_last_hb_state=0 +cnt=-1 +while true +do + # Monitor heart beat GPIO value, GPIOF4 for Socket 0 + s0_hb_state=$(gpio_name_get s0-heartbeat) + if [ "$s0_last_hb_state" != "$s0_hb_state" ]; then + cnt=0 + else + cnt=$((cnt + 1)) + fi + + if [ "$cnt" -ge 6 ]; then + echo "Error: system firmware hang" + sel_trigger + reset_system + exit 0 + fi + s0_last_hb_state="$s0_hb_state" + sleep 0.5 +done + +exit 0 diff --git a/meta-ampere/meta-mitchell/recipes-ampere/packagegroups/packagegroup-obmc-ampere-apps.bb b/meta-ampere/meta-mitchell/recipes-ampere/packagegroups/packagegroup-obmc-ampere-apps.bb new file mode 100644 index 000000000000..2960d8ac44b1 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/packagegroups/packagegroup-obmc-ampere-apps.bb @@ -0,0 +1,40 @@ +SUMMARY = "OpenBMC for Ampere - Applications" +PR = "r1" + +inherit packagegroup + +PROVIDES = "${PACKAGES}" +PACKAGES = " \ + ${PN}-chassis \ + ${PN}-flash \ + ${PN}-system \ + " + +PROVIDES += "virtual/obmc-chassis-mgmt" +PROVIDES += "virtual/obmc-flash-mgmt" +PROVIDES += "virtual/obmc-system-mgmt" + +RPROVIDES:${PN}-chassis += "virtual-obmc-chassis-mgmt" +RPROVIDES:${PN}-flash += "virtual-obmc-flash-mgmt" +RPROVIDES:${PN}-system += "virtual-obmc-system-mgmt" + +SUMMARY:${PN}-chassis = "Ampere Chassis" +RDEPENDS:${PN}-chassis = " \ + obmc-phosphor-buttons-signals \ + obmc-phosphor-buttons-handler \ + phosphor-skeleton-control-power \ + ampere-hostctrl \ + phosphor-hostlogger \ + phosphor-sel-logger \ + phosphor-logging \ + " + +SUMMARY:${PN}-system = "Ampere System" +RDEPENDS:${PN}-system = " \ + smbios-mdr \ + " + +SUMMARY:${PN}-flash = "Ampere Flash" +RDEPENDS:${PN}-flash = " \ + phosphor-software-manager \ + " diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update.bb b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update.bb new file mode 100644 index 000000000000..7deb05a21933 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update.bb @@ -0,0 +1,18 @@ +SUMMARY = "Ampere Computing LLC Update MAC Address from FRU Inventory Information" +DESCRIPTION = "Update MAC Address from FRU Inventory Information for Ampere systems" +PR = "r1" + +LICENSE = "Apache-2.0" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit systemd +inherit obmc-phosphor-systemd + +DEPENDS = "systemd" +RDEPENDS:${PN} = "bash" + +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +SYSTEMD_SERVICE:${PN} = "ampere_update_mac.service" + diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.service b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.service new file mode 100644 index 000000000000..f68f029aed9e --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.service @@ -0,0 +1,16 @@ +[Unit] +Description=Updating MAC Address Service From FRU inventory +Requires=xyz.openbmc_project.EntityManager.service +After=xyz.openbmc_project.EntityManager.service +StartLimitInterval=25 +StartLimitBurst=5 + +[Service] +ExecStart=/usr/bin/env ampere_update_mac.sh eth0 14 80 +SyslogIdentifier=ampere_update_mac.sh +RemainAfterExit=yes +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy={SYSTEMD_DEFAULT_TARGET} diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init.bb b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init.bb new file mode 100644 index 000000000000..dd5f599d4ba5 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init.bb @@ -0,0 +1,35 @@ +SUMMARY = "Phosphor OpenBMC Platform Init Service" +DESCRIPTION = "Phosphor OpenBMC Platform Init Daemon" + +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit systemd +inherit obmc-phosphor-systemd + +DEPENDS += "systemd" +RDEPENDS:${PN} += "libsystemd" +RDEPENDS:${PN} += "bash" + +SRC_URI = " \ + file://ampere-platform-init.service \ + file://ampere-bmc-heartbeat.service \ + file://ampere_platform_init.sh \ + file://ampere_bmc_heartbeat.sh \ + file://${MACHINE}_platform_gpios_init.sh \ + file://gpio-lib.sh \ + " +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE:${PN} = "ampere-platform-init.service ampere-bmc-heartbeat.service" + +do_install () { + install -d ${D}${sbindir} + install -m 0755 ${WORKDIR}/gpio-lib.sh ${D}${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_platform_init.sh ${D}${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_bmc_heartbeat.sh ${D}${sbindir}/ + install -m 0755 ${WORKDIR}/${MACHINE}_platform_gpios_init.sh ${D}${sbindir}/platform_gpios_init.sh + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${WORKDIR}/ampere-platform-init.service ${D}${systemd_unitdir}/system +} + diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-bmc-heartbeat.service b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-bmc-heartbeat.service new file mode 100644 index 000000000000..d491fd9c6e80 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-bmc-heartbeat.service @@ -0,0 +1,14 @@ +[Unit] +Description=Ampere BMC heartbeat service +Wants=obmc-mapper.target +After=obmc-mapper.target + +[Service] +Type=simple +Restart=always +ExecStart=/usr/bin/env ampere_bmc_heartbeat.sh +SyslogIdentifier = "ampere-bmc-heartbeat" + +[Install] +WantedBy=multi-user.target + diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-platform-init.service b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-platform-init.service new file mode 100644 index 000000000000..72a34cba64f5 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere-platform-init.service @@ -0,0 +1,11 @@ +[Unit] +Description = Ampere Platform Initialization + +[Service] +Restart=no +RemainAfterExit=true +Type=oneshot +ExecStart=/usr/sbin/ampere_platform_init.sh + +[Install] +WantedBy=sysinit.target diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_bmc_heartbeat.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_bmc_heartbeat.sh new file mode 100644 index 000000000000..5ecea31e6ca4 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_bmc_heartbeat.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# shellcheck disable=SC2154 +# shellcheck source=/dev/null + +source /usr/sbin/gpio-lib.sh + +value=0 +while true; +do + if [[ $value -eq 0 ]]; then + value=1 + gpio_name_set led-sw-hb 1 + gpio_name_set led-bmc-hb 0 + else + value=0 + gpio_name_set led-sw-hb 0 + gpio_name_set led-bmc-hb 1 + fi + sleep 1s +done diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh new file mode 100644 index 000000000000..33dc7ea16a64 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# shellcheck disable=SC2154 +# shellcheck source=/dev/null + +source /usr/sbin/gpio-lib.sh +source /usr/sbin/platform_gpios_init.sh + +#pre platform init function. implemented in platform_gpios_init.sh +pre-platform-init + +# ======================================================= +# Setting default value for device sel and mux +bootstatus=$(cat /sys/class/watchdog/watchdog0/bootstatus) +if [ "$bootstatus" == '32' ]; then + echo "CONFIGURE: gpio pins to output high after AC power" + for gpioName in "${output_high_gpios_in_ac[@]}"; do + gpio_name_set "$gpioName" 1 + done + echo "CONFIGURE: gpio pins to output low after AC power" + for gpioName in "${output_low_gpios_in_ac[@]}"; do + gpio_name_set "$gpioName" 0 + done + echo "CONFIGURE: gpio pins to input after AC power" + for gpioName in "${input_gpios_in_ac[@]}"; do + gpio_name_input "$gpioName" + done +fi + +# ======================================================= +# Setting default value for others gpio pins +echo "CONFIGURE: gpio pins to output high" +for gpioName in "${output_high_gpios_in_bmc_reboot[@]}"; do + gpio_name_set "$gpioName" 1 +done +echo "CONFIGURE: gpio pins to output low" +for gpioName in "${output_low_gpios_in_bmc_reboot[@]}"; do + gpio_name_set "$gpioName" 0 +done +echo "CONFIGURE: gpio pins to input" +for gpioName in "${input_gpios_in_bmc_reboot[@]}"; do + gpio_name_input "$gpioName" +done + +#post platform init function. implemented in platform_gpios_init.sh +post-platform-init + +exit 0 diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/gpio-lib.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/gpio-lib.sh new file mode 100644 index 000000000000..3e503c490985 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/gpio-lib.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# shellcheck disable=SC2154 +# shellcheck source=/dev/null + +# Configure GPIO as output and set its value +AST2600_GPIO_BASE=( + 816 + 780 +) + +function gpio_configure_output() { + echo "$1" > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio"$1"/direction + echo "$2" > /sys/class/gpio/gpio"$1"/value + echo "$1" > /sys/class/gpio/unexport +} + +function gpio_get_val() { + echo "$1" > /sys/class/gpio/export + cat /sys/class/gpio/gpio"$1"/value + echo "$1" > /sys/class/gpio/unexport +} + +# Configure GPIO as input +function gpio_configure_input() { + echo "$1" > /sys/class/gpio/export + echo "in" > /sys/class/gpio/gpio"$1"/direction + echo "$1" > /sys/class/gpio/unexport +} + +function gpio_name_set() +{ + str=$(gpiofind "$1") + #Verify error code when run gpiofind + if [ "$?" == '1' ]; then + echo "Invalid gpio name $1" + else + gpioid=$(echo "$str"|cut -c 9) + offset=$(echo "$str"|cut -d " " -f 2) + gpioPin=$(("$offset" + ${AST2600_GPIO_BASE[$gpioid]})) + gpio_configure_output "$gpioPin" "$2" + fi +} + +function gpio_name_get() +{ + str=$(gpiofind "$1") + #Verify error code when run gpiofind + if [ "$?" == '1' ]; then + echo "Invalid gpio name $1" + else + offset=$(echo "$str"|cut -d " " -f 2) + gpioid=$(echo "$str"|cut -c 9) + gpioPin=$(("$offset" + ${AST2600_GPIO_BASE[$gpioid]})) + gpio_get_val "$gpioPin" + fi +} + +function gpio_name_input() +{ + str=$(gpiofind "$1") + #Verify error code when run gpiofind + if [ "$?" == '1' ]; then + echo "Invalid gpio name $1" + else + gpioid=$(echo "$str"|cut -c 9) + offset=$(echo "$str"|cut -d " " -f 2) + gpioPin=$(("$offset" + ${AST2600_GPIO_BASE[$gpioid]})) + gpio_configure_input "$gpioPin" + fi +} \ No newline at end of file diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/mtmitchell_platform_gpios_init.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/mtmitchell_platform_gpios_init.sh new file mode 100644 index 000000000000..4c304668eb9e --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/mtmitchell_platform_gpios_init.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# shellcheck disable=SC2154 +# shellcheck source=/dev/null + +source /usr/sbin/gpio-lib.sh + +function bind_rtc_driver() { + # If rtc device can not present, bind the device + if [[ ! -e /dev/rtc0 ]]; then + echo "Bind rtc driver" + echo 6-0051 > /sys/bus/i2c/drivers/rtc-pcf85063/bind + fi +} + +function pre-platform-init() { + echo "Do pre platform init" +} + +function post-platform-init() { + # gpio-leds is controlling bmc-ready, not by gpio + echo 1 > /sys/class/leds/bmc-ready/brightness + + # Bind rtc driver + bind_rtc_driver +} + +export output_high_gpios_in_ac=( + # add device enable, mux setting, device select gpios + "spi0-backup-sel" + "i2c-backup-sel" +) + +export output_low_gpios_in_ac=( + # add device enable, mux setting, device select gpios + "spi0-program-sel" + "ocp-main-pwren" +) + +export input_gpios_in_ac=( + # add device enable, mux setting, device select gpios +) + +export output_high_gpios_in_bmc_reboot=( + "host0-sysreset-n" + "host0-pmin-n" + "vrd-sel" + "spd-sel" + "ext-high-temp-n" + "wd-disable-n" + "hpm-stby-rst-n" + "jtag-sel-s0" + "cpld-user-mode" + "jtag-srst-n" + "host0-shd-req-n" +) + +export output_low_gpios_in_bmc_reboot=( + "rtc-battery-voltage-read-enable" + "s0-rtc-lock" + "hpm-fw-recovery" + "led-fault" + "spi-nor-access" + "host0-special-boot" +) + +export input_gpios_in_bmc_reboot=( + "s0-vrd-fault-n" + "s1-vrd-fault-n" + "irq-n" + "presence-ps0" + "presence-ps1" + "hsc-12vmain-alt2-n" + "s0-pcp-oc-warn-n" + "s1-pcp-oc-warn-n" + "cpu-bios-recover" + "s0-heartbeat" + "hs-scout-proc-hot" + "s0-vr-hot-n" + "s1-vr-hot-n" + "hsc-12vmain-alt1-n" + "power-chassis-good" + "power-button" + "s0-ddr-save" + "soc-spi-nor-access" + "presence-cpu0" + "jtag-dbgr-prsnt-n" + "ps0-ac-loss-n" + "ps1-ac-loss-n" + "s1-ddr-save" + "sys-pgood" + "presence-cpu1" + "s0-fault-alert" + "s0-sys-auth-failure-n" + "host0-ready" + "ocp-pgood" + "s1-fault-alert" + "s1-fw-boot-ok" + "s0-spi-auth-fail-n" + "s1-sys-auth-failure-n" + "reset-button" + "ps0-pgood" + "ps1-pgood" + "s0-soc-pgood" +) diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend new file mode 100644 index 000000000000..341ca13894ba --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend @@ -0,0 +1,20 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +INSANE_SKIP:${PN} = "already-stripped" + +SRC_URI:append = " \ + file://ampere_power_util.sh \ + file://ampere_firmware_upgrade.sh \ + file://ampere_flash_bios.sh \ + file://ampere_power_on_driver_binder.sh \ + file://ampere_firmware_version.sh \ + " + +do_install:append() { + install -d ${D}/usr/sbin + install -m 0755 ${WORKDIR}/ampere_power_util.sh ${D}/${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_firmware_upgrade.sh ${D}/${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_flash_bios.sh ${D}/${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_power_on_driver_binder.sh ${D}/${sbindir}/ + install -m 0755 ${WORKDIR}/ampere_firmware_version.sh ${D}/${sbindir}/ +} diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh new file mode 100755 index 000000000000..dce6e6ccaaee --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_upgrade.sh @@ -0,0 +1,201 @@ +#!/bin/bash + +# Helper script to flash FRU and Boot EEPROM devices. +# +# Syntax for FRU: +# ampere_firmware_upgrade.sh fru [] +# dev: 1 for MB FRU (default), 2 for BMC FRU. +# +# Syntax for EEPROM: +# ampere_firmware_upgrade.sh eeprom [] +# dev: 1 for main Boot EEPROM (default), 2 for secondary Boot EEPROM (if supported) +# +# Syntax for Mainboard CPLD: +# ampere_firmware_upgrade.sh main_cpld +# +# Syntax for BMC CPLD: +# ampere_firmware_upgrade.sh bmc_cpld +# +# Syntax for Backplane CPLD: +# ampere_firmware_upgrade.sh bp_cpld [] +# target: 1 for Front Backplane 1 +# 2 for Front Backplane 2 +# 3 for Front Backplane 3 +# 4 for Rear Backplane 1 +# 5 for Rear Backplane 2 +# + +# shellcheck disable=SC2046 + +do_eeprom_flash() { + FIRMWARE_IMAGE=$IMAGE + BACKUP_SEL=$2 + + # Turn off the Host if it is currently ON + chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}') + echo "Current Chassis State: $chassisstate" + if [ "$chassisstate" == 'On' ]; + then + echo "Turning the Chassis off" + obmcutil chassisoff + sleep 15 + # Check if HOST was OFF + chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') + if [ "$chassisstate_off" == 'On' ]; + then + echo "Error : Failed turning the Chassis off" + exit 1 + fi + fi + + # Switch EEPROM control to BMC AST2600 I2C + # BMC_GPIOW6_SPI0_PROGRAM_SEL + gpioset $(gpiofind spi0-program-sel)=1 + + # BMC_GPIOX0_I2C_BACKUP_SEL (GPIO 184) + if [[ $BACKUP_SEL == 1 ]]; then + echo "Run update Primary EEPROM" + gpioset $(gpiofind i2c-backup-sel)=0 + elif [[ $BACKUP_SEL == 2 ]]; then + echo "Run update Failover EEPROM" + gpioset $(gpiofind i2c-backup-sel)=1 + else + echo "Please choose Primary EEPROM (1) or Failover EEPROM (2)" + exit 0 + fi + + # The EEPROM (AT24C64WI) with address 0x50 at BMC_I2C11 bus + # Write Firmware to EEPROM and read back for validation + ampere_eeprom_prog -b 10 -s 0x50 -p -f "$FIRMWARE_IMAGE" + + # Switch to primary EEPROM + gpioset $(gpiofind i2c-backup-sel)=0 + + # Switch EEPROM control to CPU HOST + gpioset $(gpiofind spi0-program-sel)=0 + + if [ "$chassisstate" == 'On' ]; + then + sleep 5 + echo "Turn on the Host" + obmcutil poweron + fi +} + +do_fru_flash() { + FRU_IMAGE=$1 + FRU_DEV=$2 + + if [[ $FRU_DEV == 1 ]]; then + if [ -f /sys/bus/i2c/devices/4-0050/eeprom ]; then + FRU_DEVICE="/sys/bus/i2c/devices/4-0050/eeprom" + else + FRU_DEVICE="/sys/bus/i2c/devices/3-0050/eeprom" + fi + echo "Flash MB FRU with image $IMAGE at $FRU_DEVICE" + elif [[ $FRU_DEV == 2 ]]; then + FRU_DEVICE="/sys/bus/i2c/devices/14-0050/eeprom" + echo "Flash BMC FRU with image $IMAGE at $FRU_DEVICE" + else + echo "Please select MB FRU (1) or BMC FRU (2)" + exit 0 + fi + + ampere_fru_upgrade -d "$FRU_DEVICE" -f "$FRU_IMAGE" + + systemctl restart xyz.openbmc_project.FruDevice.service + systemctl restart phosphor-ipmi-host.service + + echo "Done" +} + +do_mb_cpld_flash() { + MB_CPLD_IMAGE=$1 + echo "Flashing MB CPLD" + gpioset $(gpiofind hpm-fw-recovery)=1 + gpioset $(gpiofind jtag-program-sel)=1 + sleep 2 + ampere_cpldupdate_jtag -t 1 -p "$MB_CPLD_IMAGE" + gpioset $(gpiofind hpm-fw-recovery)=0 + echo "Done" +} + +do_bmc_cpld_flash() { + BMC_CPLD_IMAGE=$1 + echo "Flashing BMC CPLD" + gpioset $(gpiofind jtag-program-sel)=0 + sleep 2 + ampere_cpldupdate_jtag -t 1 -p "$BMC_CPLD_IMAGE" + echo "Done" +} + +do_bp_cpld_flash() { + BP_CPLD_IMAGE=$1 + BP_TARGET=$2 + if [[ $BP_TARGET == 1 ]]; then + echo "Flashing Front Backplane 1 CPLD" + ampere_cpldupdate_i2c -b 101 -s 0x40 -t 2 -p "$BP_CPLD_IMAGE" + elif [[ $BP_TARGET == 2 ]]; then + echo "Flashing Front Backplane 2 CPLD" + ampere_cpldupdate_i2c -b 102 -s 0x40 -t 2 -p "$BP_CPLD_IMAGE" + elif [[ $BP_TARGET == 3 ]]; then + echo "Flashing Front Backplane 3 CPLD" + ampere_cpldupdate_i2c -b 100 -s 0x40 -t 2 -p "$BP_CPLD_IMAGE" + elif [[ $BP_TARGET == 4 ]]; then + echo "Flashing Rear Backplane 1 CPLD" + ampere_cpldupdate_i2c -b 103 -s 0x40 -t 2 -p "$BP_CPLD_IMAGE" + elif [[ $BP_TARGET == 5 ]]; then + echo "Flashing Rear Backplane 2 CPLD" + ampere_cpldupdate_i2c -b 104 -s 0x40 -t 2 -p "$BP_CPLD_IMAGE" + fi + + echo "Done" +} + +if [ $# -eq 0 ]; then + echo "Usage:" + echo " - Flash Boot EEPROM" + echo " $(basename "$0") eeprom " + echo " - Flash FRU" + echo " $(basename "$0") fru [dev]" + echo " Where:" + echo " dev: 1 - MB FRU, 2 - BMC FRU" + echo " - Flash Mainboard CPLD" + echo " $(basename "$0") mb_cpld " + echo " - Flash BMC CPLD (only for DC-SCM BMC board)" + echo " $(basename "$0") bmc_cpld " + echo " - Flash Backplane CPLD" + echo " $(basename "$0") bp_cpld " + echo " Where:" + echo " Target: 1 - FrontBP1, 2 - FrontBP2, 3 - FrontBP3" + echo " 4 - RearBP1, 5 - RearBP2" + exit 0 +fi + +TYPE=$1 +IMAGE=$2 +TARGET=$3 +if [ -z "$3" ]; then + BACKUP_SEL=1 +else + BACKUP_SEL=$3 +fi + +if [[ $TYPE == "eeprom" ]]; then + # Run EEPROM update: write/read/validation with CRC32 checksum + do_eeprom_flash "$IMAGE" "$BACKUP_SEL" +elif [[ $TYPE == "fru" ]]; then + # Run FRU update + do_fru_flash "$IMAGE" "$BACKUP_SEL" +elif [[ $TYPE == "mb_cpld" ]]; then + # Run Mainboard CPLD update + do_mb_cpld_flash "$IMAGE" +elif [[ $TYPE == "bmc_cpld" ]]; then + # Run CPLD BMC update + do_bmc_cpld_flash "$IMAGE" +elif [[ $TYPE == "bp_cpld" ]]; then + # Run Backplane CPLD update + do_bp_cpld_flash "$IMAGE" "$TARGET" +fi + +exit 0 diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_version.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_version.sh new file mode 100755 index 000000000000..081e3030f611 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_firmware_version.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# Helper script to report firmware version for components on the system (MB CPLD, Backplane CPLD, …) +# Author : Hieu Huynh (hieu.huynh@amperecomputing.com) +# +# Get MB CPLD firmware revision: +# ampere_firmware_version.sh mb_cpld +# +# Get BMC CPLD firmware revision: +# ampere_firmware_version.sh bmc_cpld +# +# Get Backplane CPLD firmware revision: +# ampere_firmware_version.sh bp_cpld +# : 1 for Front Backplane 1 +# 2 for Front Backplane 2 +# 3 for Front Backplane 3 +# 4 for Rear Backplane 1 +# 5 for Rear Backplane 2 + +# shellcheck disable=SC2046 + +do_mb_cpld_firmware_report() { + echo "MB CPLD" + gpioset $(gpiofind hpm-fw-recovery)=1 + gpioset $(gpiofind jtag-program-sel)=1 + sleep 1 + ampere_cpldupdate_jtag -v + ampere_cpldupdate_jtag -i +} + +do_bmc_cpld_firmware_report() { + echo "BMC CPLD (Only for DC-SCM board)" + gpioset $(gpiofind jtag-program-sel)=0 + sleep 1 + ampere_cpldupdate_jtag -v + ampere_cpldupdate_jtag -i +} + +do_bp_cpld_firmware_report() { + BP_ID=$1 + if [[ $BP_ID == 1 ]]; then + echo "Front Backplane 1 CPLD" + ampere_cpldupdate_i2c -b 101 -s 0x40 -t 2 -v + ampere_cpldupdate_i2c -b 101 -s 0x40 -t 2 -i + elif [[ $BP_ID == 2 ]]; then + echo "Front Backplane 2 CPLD" + ampere_cpldupdate_i2c -b 102 -s 0x40 -t 2 -v + ampere_cpldupdate_i2c -b 102 -s 0x40 -t 2 -i + elif [[ $BP_ID == 3 ]]; then + echo "Front Backplane 3 CPLD" + ampere_cpldupdate_i2c -b 100 -s 0x40 -t 2 -v + ampere_cpldupdate_i2c -b 100 -s 0x40 -t 2 -i + elif [[ $BP_ID == 4 ]]; then + echo "Rear Backplane 1 CPLD" + ampere_cpldupdate_i2c -b 103 -s 0x40 -t 2 -v + ampere_cpldupdate_i2c -b 103 -s 0x40 -t 2 -i + elif [[ $BP_ID == 5 ]]; then + echo "Rear Backplane 2 CPLD" + ampere_cpldupdate_i2c -b 104 -s 0x40 -t 2 -v + ampere_cpldupdate_i2c -b 104 -s 0x40 -t 2 -i + fi +} + +if [ $# -eq 0 ]; then + echo "Usage:" + echo " - Get MB CPLD firmware revision" + echo " $(basename "$0") mb_cpld" + echo " - Get BMC CPLD firmware revision" + echo " $(basename "$0") bmc_cpld" + echo " - Get Backplane CPLD firmware revision" + echo " $(basename "$0") bp_cpld " + echo " :" + echo " 1 - FrontBP1" + echo " 2 - FrontBP2" + echo " 3 - FrontBP3" + echo " 4 - RearBP1" + echo " 5 - RearBP2" + exit 0 +fi + +TYPE=$1 +ID=$2 + +if [[ $TYPE == "mb_cpld" ]]; then + do_mb_cpld_firmware_report +elif [[ $TYPE == "bmc_cpld" ]]; then + do_bmc_cpld_firmware_report +elif [[ $TYPE == "bp_cpld" ]]; then + if [ -z "$ID" ]; then + echo "Please choose backplanes id: 1 - FrontBP1, 2 - FrontBP2, 3 - FrontBP3, 4 - FrontBP4, 5 - FrontBP5" + exit 0 + elif [[ "$ID" -ge "1" ]] && [[ "$ID" -le "5" ]]; then + do_bp_cpld_firmware_report "$ID" + else + echo "Backplanes id invalid" + fi +fi + +exit 0 diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh new file mode 100755 index 000000000000..0e0c18c6d602 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_flash_bios.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +# This script is used to flash the UEFI/EDKII + +# Syntax: ampere_flash_bios.sh $image_file $device_sellect +# Where: +# $image_file : the image binary file +# $device_sellect : 1 - Host Main SPI Nor +# 2 - Host Second SPI Nor + +# Author : Chanh Nguyen (chnguyen@amperecomputing.com) + +# Note: +# BMC_GPIOW6_SPI0_PROGRAM_SEL (GPIO 182): 1 => BMC owns SPI bus for upgrading +# 0 => HOST owns SPI bus for upgrading + +# BMC_GPIOW7_SPI0_BACKUP_SEL (GPIO 183) : 1 => to switch SPI_CS0_L to primary SPI Nor device +# 0 => to switch SPI_CS0_L to second SPI Nor device + +# shellcheck disable=SC2046 + +do_flash () { + # Check the HNOR partition available + HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') + if [ -z "$HOST_MTD" ]; + then + # Check the ASpeed SMC driver binded before + HOST_SPI=/sys/bus/platform/drivers/spi-aspeed-smc/1e630000.spi + if [ -d "$HOST_SPI" ]; then + echo "Unbind the ASpeed SMC driver" + echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/unbind + sleep 2 + fi + + # If the HNOR partition is not available, then bind again driver + echo "--- Bind the ASpeed SMC driver" + echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/bind + sleep 2 + + HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') + if [ -z "$HOST_MTD" ]; + then + echo "Fail to probe Host SPI-NOR device" + exit 1 + fi + fi + + echo "--- Flashing firmware image $IMAGE to @/dev/$HOST_MTD" + flashcp -v "$IMAGE" /dev/"$HOST_MTD" +} + + +if [ $# -eq 0 ]; then + echo "Usage: $(basename "$0") " + exit 0 +fi + +IMAGE="$1" +if [ ! -f "$IMAGE" ]; then + echo "The image file $IMAGE does not exist" + exit 1 +fi + +if [ -z "$2" ]; then + DEV_SEL="1" # by default, select primary device +else + DEV_SEL="$2" +fi + +# Turn off the Host if it is currently ON +chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}') +echo "--- Current Chassis State: $chassisstate" +if [ "$chassisstate" == 'On' ]; +then + echo "--- Turning the Chassis off" + obmcutil chassisoff + sleep 10 + # Check if HOST was OFF + chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}') + if [ "$chassisstate_off" == 'On' ]; + then + echo "--- Error : Failed turning the Chassis off" + exit 1 + fi +fi + +# Switch the host SPI bus to BMC" +echo "--- Switch the host SPI bus to BMC." +if ! gpioset $(gpiofind spi0-program-sel)=1; then + echo "ERROR: Switch the host SPI bus to BMC. Please check gpio state" + exit 1 +fi + +# Switch the host SPI bus (between primary and secondary) +# 183 is BMC_GPIOW7_SPI0_BACKUP_SEL +if [[ $DEV_SEL == 1 ]]; then + echo "Run update Primary Host SPI-NOR" + gpioset $(gpiofind spi0-backup-sel)=1 # Primary SPI +elif [[ $DEV_SEL == 2 ]]; then + echo "Run update Second Host SPI-NOR" + gpioset $(gpiofind spi0-backup-sel)=0 # Second SPI +else + echo "Please choose primary SPI (1) or second SPI (2)" + exit 0 +fi + +# Flash the firmware +do_flash + +# Switch the SPI bus to the primary spi device +echo "Switch to the Primary Host SPI-NOR" +gpioset $(gpiofind spi0-backup-sel)=1 # Primary SPI + +# Switch the host SPI bus to HOST." +echo "--- Switch the host SPI bus to HOST." +if ! gpioset $(gpiofind spi0-program-sel)=0; then + echo "ERROR: Switch the host SPI bus to HOST. Please check gpio state" + exit 1 +fi + +if [ "$chassisstate" == 'On' ]; +then + sleep 5 + echo "Turn on the Host" + obmcutil poweron +fi diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh new file mode 100644 index 000000000000..a1f30c26dce2 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Each driver include driver name and driver path +declare -a DRIVER_NAMEs=( + "107-0070" + "100-0071" + "101-0071" + "102-0071" + "103-0071" + "104-0071" + "100-0050" + "101-0050" + "102-0050" + "100-004c" + "101-004c" + "102-004c" + ) +# Driver path should include / at the end +declare -a DRIVER_PATHs=( + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/pca954x/" + "/sys/bus/i2c/drivers/at24/" + "/sys/bus/i2c/drivers/at24/" + "/sys/bus/i2c/drivers/at24/" + "/sys/bus/i2c/drivers/lm75/" + "/sys/bus/i2c/drivers/lm75/" + "/sys/bus/i2c/drivers/lm75/" + ) + +# get length of an array +arraylength=${#DRIVER_NAMEs[@]} + +# use for loop to read all values and indexes +for (( i=0; i<"${arraylength}"; i++ )); +do + bindFile="${DRIVER_PATHs[$i]}bind" + driverDir="${DRIVER_PATHs[$i]}${DRIVER_NAMEs[$i]}" + echo "binding ${DRIVER_NAMEs[$i]} path ${DRIVER_PATHs[$i]} on Chassi Power On" + if [ -d "$driverDir" ]; then + echo "Driver ${DRIVER_NAMEs[$i]} is already bound." + else + echo "${DRIVER_NAMEs[$i]}" > "$bindFile" + fi +done + +exit 0 diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh new file mode 100644 index 000000000000..6f799f03f249 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# shellcheck disable=SC2046 +# shellcheck source=/dev/null + +source /usr/sbin/gpio-lib.sh + +# Usage of this utility +function usage() { + echo "usage: power-util mb [status|shutdown_ack|force_reset|soft_off]"; +} + +power_status() { + st=$(busctl get-property xyz.openbmc_project.State.Chassis /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis CurrentPowerState | cut -d"." -f6) + if [ "$st" == "On\"" ]; then + echo "on" + else + echo "off" + fi +} + +shutdown_ack() { + if [ -f "/run/openbmc/host@0-softpoweroff" ]; then + echo "Receive shutdown ACK triggered after softportoff the host." + touch /run/openbmc/host@0-softpoweroff-shutdown-ack + else + echo "Receive shutdown ACK triggered" + sleep 3 + systemctl start obmc-chassis-poweroff@0.target + fi +} + +soft_off() { + # Trigger shutdown_req + touch /run/openbmc/host@0-softpoweroff + gpio_name_set host0-shd-req-n 0 + sleep 0.05 + gpio_name_set host0-shd-req-n 1 + + # Wait for shutdown_ack from the host in 30 seconds + cnt=30 + while [ $cnt -gt 0 ]; + do + # Wait for SHUTDOWN_ACK and create the host@0-softpoweroff-shutdown-ack + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + break + fi + sleep 1 + cnt=$((cnt - 1)) + done + + # Softpoweroff is successed + sleep 2 + rm -rf /run/openbmc/host@0-softpoweroff + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + rm -rf /run/openbmc/host@0-softpoweroff-shutdown-ack + fi + echo 0 +} + +force_reset() { + if [ -f "/run/openbmc/host@0-softpoweroff" ]; then + # In graceful host reset, after trigger os shutdown, + # the phosphor-state-manager will call force-warm-reset + # in this case the force_reset should wait for shutdown_ack from host + cnt=30 + while [ $cnt -gt 0 ]; + do + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + break + fi + echo "Waiting for shutdown-ack count down $cnt" + sleep 1 + cnt=$((cnt - 1)) + done + # The host OS is failed to shutdown + if [ $cnt == 0 ]; then + echo "Shutdown-ack time out after 30s." + exit 0 + fi + fi + rm -f /run/openbmc/host@0-on + echo "Triggering sysreset pin" + gpio_name_set host0-sysreset-n 0 + sleep 1 + gpio_name_set host0-sysreset-n 1 +} + + +if [ ! -d "/run/openbmc/" ]; then + mkdir -p "/run/openbmc/" +fi + +if [ "$2" == "shutdown_ack" ]; then + shutdown_ack +elif [ "$2" == "status" ]; then + power_status +elif [ "$2" == "force_reset" ]; then + force_reset +elif [ "$2" == "soft_off" ]; then + ret=$(soft_off) + if [ "$ret" == 0 ]; then + echo "The host is already softoff" + else + echo "Failed to softoff the host" + fi + exit "$ret"; +else + echo "Invalid parameter2=$2" + usage; +fi + +exit 0; diff --git a/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg b/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg new file mode 100644 index 000000000000..e88414a1b97c --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk/ampere.cfg @@ -0,0 +1,2 @@ +CONFIG_PHY_NCSI=n + diff --git a/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend b/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend new file mode 100644 index 000000000000..133671c1da61 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +SRC_URI += " \ + file://ampere.cfg \ + " diff --git a/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed/ampere.cfg b/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed/ampere.cfg new file mode 100644 index 000000000000..5235f1e703d8 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed/ampere.cfg @@ -0,0 +1,45 @@ +# +# BOM +# +CONFIG_RTC_DRV_PCF85063=y +CONFIG_IIO_MUX=y +CONFIG_MUX_GPIO=y +CONFIG_I2C_MUX=y + +CONFIG_SENSORS_IIO_HWMON=y +CONFIG_ASPEED_ADC=y +CONFIG_SENSORS_LM75=y +CONFIG_SENSORS_EMC1403=y +CONFIG_LTC2497=y +CONFIG_I2C_SLAVE=y +CONFIG_SENSORS_ASPEED=y + +CONFIG_USB_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_ASPEED_VHUB=y +CONFIG_USB_CONFIGFS_ECM=y + +CONFIG_SERIAL_8250_NR_UARTS=10 +CONFIG_SERIAL_8250_RUNTIME_UARTS=10 + +CONFIG_HWMON=y + +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_SENSORS_ASPEED=y + +CONFIG_SSIF_IPMI_BMC=y + +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR=y + +CONFIG_SENSORS_MAX31790=y + +CONFIG_NET_NCSI=y +CONFIG_NCSI_OEM_CMD_GET_MAC=y + +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_CIFS=y +CONFIG_CIFS_XATTR=y diff --git a/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed_%.bbappend new file mode 100644 index 000000000000..4cac8de388cf --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI += " \ + file://ampere.cfg \ + " diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/ampere_uartmux_ctrl.sh b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/ampere_uartmux_ctrl.sh new file mode 100644 index 000000000000..1d1fbed121cf --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/ampere_uartmux_ctrl.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# shellcheck disable=SC2046 + +if [ $# -lt 2 ]; then + exit 1 +fi + +case "$1" in + 1) GPIO_UARTx_MODE0="uart1-mode0" + GPIO_UARTx_MODE1="uart1-mode1" + # CPU0 UART0 connects to BMC UART1 + CONSOLE_PORT=0 + ;; + 2) GPIO_UARTx_MODE0="uart2-mode0" + GPIO_UARTx_MODE1="uart2-mode1" + # CPU0 UART1 connects to BMC UART2 + CONSOLE_PORT=1 + ;; + 3) GPIO_UARTx_MODE0="uart3-mode0" + GPIO_UARTx_MODE1="uart3-mode1" + # CPU0 UART4 connects to BMC UART3 + CONSOLE_PORT=2 + ;; + 4) GPIO_UARTx_MODE0="uart4-mode0" + GPIO_UARTx_MODE1="uart4-mode1" + # CPU1 UART1 connects to BMC UART4 + CONSOLE_PORT=3 + ;; + *) echo "Invalid UART port selection" + exit 1 + ;; +esac + +# Only switch the MUX when there is no active connection. This means we only +# switch the MUX before the first session starts and after the last session +# closes. We do this by querying number of connected sessions to the socket +# of requested console port. +# Example format: Accepted: 1; Connected: 1; +CONNECTED=$(systemctl --no-pager status obmc-console-ttyS${CONSOLE_PORT}-ssh.socket | grep -w Connected | cut -d ':' -f 3 | tr -d ' ;') +if [ ! "$CONNECTED" -le 1 ]; then + echo "Please close all connected session to ttyS${CONSOLE_PORT} !" + exit 0 +fi + +echo "Ampere UART MUX CTRL UART port $1 to mode $2" + +case "$2" in + # To HDR + 1) gpioset $(gpiofind "$GPIO_UARTx_MODE0")=1 + gpioset $(gpiofind "$GPIO_UARTx_MODE1")=0 + exit 0 + ;; + # To BMC + 2) gpioset $(gpiofind "$GPIO_UARTx_MODE0")=0 + gpioset $(gpiofind "$GPIO_UARTx_MODE1")=1 + exit 0 + ;; + *) echo "Invalid UART mode selection" + exit 1 + ;; +esac diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-server-setup.sh b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-server-setup.sh new file mode 100644 index 000000000000..946c92bc3c37 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-server-setup.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +# shellcheck disable=SC3010 + +tty="$1" +uart=0 + +case "${tty}" in + "ttyS0") uart=1 + ;; + "ttyS1") uart=2 + ;; + "ttyS2") uart=3 + ;; + "ttyS3") uart=4 + ;; + "ttyS7") uart=0 + ;; + "ttyS8") uart=0 + ;; + *) echo "Invalid tty passed to $0. Exiting!" + exit 1; + ;; +esac + +# Default the host routing through the mux to use the BMC (2) +# This allows the SoL console in webui, and the ssh port 2200, to work +# upon startup. If UART transcievers are installed on the header and required, +# this value should be set to 1 +if [[ ${uart} -ne 0 ]] +then + /usr/sbin/ampere_uartmux_ctrl.sh ${uart} 2 +fi + +/usr/sbin/obmc-console-server --config /etc/obmc-console/server."${tty}".conf "${tty}" diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh.socket new file mode 100644 index 000000000000..183a7a4f3cca --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS0.service + +[Socket] +ListenStream=2200 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh@.service new file mode 100644 index 000000000000..f964454e0bf6 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS0-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS0.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS0.conf" -p ttyS0 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh.socket new file mode 100644 index 000000000000..bdbf562585fb --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS1.service + +[Socket] +ListenStream=2201 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh@.service new file mode 100644 index 000000000000..697c24271134 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS1-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS1.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS1.conf" -p ttyS1 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh.socket new file mode 100644 index 000000000000..f8934fd41cb0 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS2.service + +[Socket] +ListenStream=2202 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh@.service new file mode 100644 index 000000000000..7d7f31490a64 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS2-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS2.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS2.conf" -p ttyS2 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh.socket new file mode 100644 index 000000000000..fd7f3e3f9752 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS3.service + +[Socket] +ListenStream=2203 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh@.service new file mode 100644 index 000000000000..261f3a12ef10 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS3-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS3.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS3.conf" -p ttyS3 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh.socket new file mode 100644 index 000000000000..de670bafb6bc --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS7.service + +[Socket] +ListenStream=2204 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh@.service new file mode 100644 index 000000000000..8ce8ba0b39b7 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS7-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS7.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS7.conf" -p ttyS7 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh.socket b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh.socket new file mode 100644 index 000000000000..b2ad91799d2e --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection socket +Wants=obmc-console@ttyS8.service + +[Socket] +ListenStream=2205 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh@.service new file mode 100644 index 000000000000..cd5bda3f268a --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console-ttyS8-ssh@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Phosphor Host Console SSH Per-Connection +Wants=obmc-console@ttyS8.service + +[Service] +Environment="DROPBEAR_RSAKEY_DIR=/etc/dropbear" +EnvironmentFile=/etc/default/dropbear +ExecStart=/usr/sbin/dropbear -i -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/server.ttyS8.conf" -p ttyS8 -F $DROPBEAR_EXTRA_ARGS +SyslogIdentifier=dropbear +ExecReload=/bin/kill -HUP $MAINPID +StandardInput=socket +KillMode=process diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console@.service b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console@.service new file mode 100644 index 000000000000..22a5df269065 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/obmc-console@.service @@ -0,0 +1,17 @@ +[Unit] +Description=Phosphor Console Muxer listening on device /dev/%I +BindsTo=dev-%i.device +After=dev-%i.device +StartLimitBurst=3 +StartLimitIntervalSec=300 + +[Service] +ExecStart=/usr/sbin/obmc-console-server-setup.sh %i +SyslogIdentifier=obmc-console-server +Restart=always +RestartSec=10 +TimeoutStartSec=60 +TimeoutStopSec=60 + +[Install] +WantedBy=multi-user.target diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS0.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS0.conf new file mode 100644 index 000000000000..2d80850416b9 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS0.conf @@ -0,0 +1,3 @@ +# socket-id is default to obmc-console +local-tty = ttyS0 +local-tty-baud = 115200 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS1.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS1.conf new file mode 100644 index 000000000000..6421f9339774 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS1.conf @@ -0,0 +1,3 @@ +local-tty = ttyS1 +local-tty-baud = 115200 +socket-id = ttyS1 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS2.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS2.conf new file mode 100644 index 000000000000..f8be872f255b --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS2.conf @@ -0,0 +1,3 @@ +local-tty = ttyS2 +local-tty-baud = 115200 +socket-id = ttyS2 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS3.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS3.conf new file mode 100644 index 000000000000..8f1ebbac7329 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS3.conf @@ -0,0 +1,3 @@ +local-tty = ttyS3 +local-tty-baud = 115200 +socket-id = ttyS3 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS7.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS7.conf new file mode 100644 index 000000000000..decc72f2936f --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS7.conf @@ -0,0 +1,3 @@ +local-tty = ttyS7 +local-tty-baud = 115200 +socket-id = ttyS7 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS8.conf b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS8.conf new file mode 100644 index 000000000000..df56992ad9f1 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console/server.ttyS8.conf @@ -0,0 +1,3 @@ +local-tty = ttyS8 +local-tty-baud = 115200 +socket-id = ttyS8 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console_%.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console_%.bbappend new file mode 100644 index 000000000000..2b7673ef38a6 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/console/obmc-console_%.bbappend @@ -0,0 +1,54 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" +RDEPENDS:${PN} += "bash" + +# Remove what installed by common recipe +OBMC_CONSOLE_HOST_TTY = "" +SYSTEMD_SUBSTITUTIONS:remove = "OBMC_CONSOLE_HOST_TTY:${OBMC_CONSOLE_HOST_TTY}:${PN}-ssh@.service" +SYSTEMD_SUBSTITUTIONS:remove = "OBMC_CONSOLE_HOST_TTY:${OBMC_CONSOLE_HOST_TTY}:${PN}-ssh.socket" +SYSTEMD_SERVICE:${PN}:remove = " \ + ${PN}-ssh.socket \ + ${PN}-ssh@.service \ + " + +# Declare port spcific conf and service files +HOST_CONSOLE_TTY = "ttyS0 ttyS1 ttyS2 ttyS3 ttyS7 ttyS8" + +CONSOLE_CONF_FMT = "file://server.{0}.conf" +SRC_URI += "${@compose_list(d, 'CONSOLE_CONF_FMT', 'HOST_CONSOLE_TTY')}" +SRC_URI += "file://${BPN}-server-setup.sh" +SRC_URI += "file://${BPN}@.service" +SRC_URI += "file://ampere_uartmux_ctrl.sh" + +CONSOLE_SSH_SOCKET_FILE_FMT = "file://${PN}-{0}-ssh.socket" +CONSOLE_SSH_SERVICE_FILE_FMT = "file://${PN}-{0}-ssh@.service" +SRC_URI += "${@compose_list(d, 'CONSOLE_SSH_SOCKET_FILE_FMT', 'HOST_CONSOLE_TTY')}" +SRC_URI += "${@compose_list(d, 'CONSOLE_SSH_SERVICE_FILE_FMT', 'HOST_CONSOLE_TTY')}" + +CONSOLE_SSH_SOCKET_FMT = "${PN}-{0}-ssh.socket" +CONSOLE_SSH_SERVICE_FMT = "${PN}-{0}-ssh@.service" + +SYSTEMD_SERVICE:${PN} = " \ + ${PN}@.service \ + ${@compose_list(d, 'CONSOLE_SSH_SOCKET_FMT', 'HOST_CONSOLE_TTY')} \ + ${@compose_list(d, 'CONSOLE_SSH_SERVICE_FMT', 'HOST_CONSOLE_TTY')} \ + " +do_install:append() { + for i in ${HOST_CONSOLE_TTY} + do + install -m 0644 ${WORKDIR}/server.${i}.conf ${D}${sysconfdir}/${BPN}/server.${i}.conf + install -m 0644 ${WORKDIR}/${BPN}-${i}-ssh.socket ${D}${systemd_unitdir}/system/${BPN}-${i}-ssh.socket + install -m 0644 ${WORKDIR}/${BPN}-${i}-ssh@.service ${D}${systemd_unitdir}/system/${BPN}-${i}-ssh@.service + done + install -m 0755 ${WORKDIR}/${BPN}-server-setup.sh ${D}${sbindir}/${BPN}-server-setup.sh + + # Deal with files installed by the base package's .bb install function + rm -f ${D}${sysconfdir}/${BPN}.conf + rm -f ${D}${sysconfdir}/${BPN}/server.ttyVUART0.conf + rm -rf ${D}${systemd_unitdir}/system/${BPN}-ssh@.service.d/ + rm -f ${D}${systemd_unitdir}/system/${BPN}-ssh@.service + rm -f ${D}${systemd_unitdir}/system/${BPN}-ssh.socket + # Overwrite base package's obmc-console@.service with our own + install -m 0644 ${WORKDIR}/${BPN}@.service ${D}${systemd_unitdir}/system/${BPN}@.service + install -d ${D}/usr/sbin + install -m 0755 ${WORKDIR}/ampere_uartmux_ctrl.sh ${D}/${sbindir}/ampere_uartmux_ctrl.sh +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service new file mode 100644 index 000000000000..6588191aaef4 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service @@ -0,0 +1,8 @@ +[Unit] +Description=Ampere Computing LLC host shutdown ACK +Conflicts=obmc-chassis-poweron@0.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/env ampere_power_util.sh mb shutdown_ack +SyslogIdentifier=ampere_host_shutdown_ack diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service new file mode 100644 index 000000000000..06c2e9b22676 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere_overtemp@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Ampere Computing LLC Overtemp event handling + +[Service] +Restart=no +ExecStart=/bin/sh -c "touch /tmp/fault_overtemp && obmcutil chassisoff" +ExecStartPost=/bin/sh -c "ampere_add_redfishevent.sh OpenBMC.0.1.CPUThermalTrip.Critical %i && sleep 10 && rm /tmp/fault_overtemp" diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json new file mode 100644 index 000000000000..bc039aa12f95 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json @@ -0,0 +1,30 @@ +[ + { + "Name": "REBOOT_ACK", + "LineName": "host0-reboot-ack-n", + "EventMon": "FALLING", + "Target": "obmc-host-force-warm-reboot@0.target", + "Continue": true + }, + { + "Name": "SHUTDOWN_ACK", + "LineName": "host0-shd-ack-n", + "EventMon": "FALLING", + "Target": "ampere-host-shutdown-ack@0.service", + "Continue": true + }, + { + "Name": "S0_OVERTEMP", + "LineName": "s0-overtemp-n", + "EventMon": "FALLING", + "Target": "ampere_overtemp@0.service", + "Continue": true + }, + { + "Name": "S1_OVERTEMP", + "LineName": "s1-overtemp-n", + "EventMon": "FALLING", + "Target": "ampere_overtemp@1.service", + "Continue": true + } +] diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend new file mode 100644 index 000000000000..62fbc6440a70 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend @@ -0,0 +1,23 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +RDEPENDS:${PN}-monitor += "bash" + +SRC_URI += " \ + file://phosphor-multi-gpio-monitor.json \ + " + +SYSTEMD_SERVICE:${PN}-monitor += " \ + ampere-host-shutdown-ack@.service \ + ampere_overtemp@.service \ + " + +FILES:${PN}-monitor += " \ + /usr/share/${PN}/phosphor-multi-gpio-monitor.json \ + " + +SYSTEMD_LINK:${PN}-monitor:append = " ../phosphor-multi-gpio-monitor.service:multi-user.target.requires/phosphor-multi-gpio-monitor.service" + +do_install:append() { + install -d ${D}${bindir} + install -m 0644 ${WORKDIR}/phosphor-multi-gpio-monitor.json ${D}${datadir}/${PN}/ +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf new file mode 100644 index 000000000000..e0c10a42ed80 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS0.conf @@ -0,0 +1,3 @@ +# SOCKET-ID is default to obmc-console +MODE=stream +STREAM_DST=/run/rsyslog/console/cpu diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf new file mode 100644 index 000000000000..c2218e5eb0b4 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS1.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS1 +MODE=stream +STREAM_DST=/run/rsyslog/console/mpro0 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf new file mode 100644 index 000000000000..5d3cfb68280c --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS2.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS2 +MODE=stream +STREAM_DST=/run/rsyslog/console/atf diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf new file mode 100644 index 000000000000..7c4f5e98f0cf --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS3.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS3 +MODE=stream +STREAM_DST=/run/rsyslog/console/secpro0 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS7.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS7.conf new file mode 100644 index 000000000000..b811dcf031c8 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS7.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS7 +MODE=stream +STREAM_DST=/run/rsyslog/console/mpro1 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS8.conf b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS8.conf new file mode 100644 index 000000000000..dfe25d3f01c6 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger/ttyS8.conf @@ -0,0 +1,3 @@ +SOCKET_ID=ttyS8 +MODE=stream +STREAM_DST=/run/rsyslog/console/secpro1 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend new file mode 100644 index 000000000000..977f7cc819dd --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/hostlogger/phosphor-hostlogger_%.bbappend @@ -0,0 +1,20 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI:append = " \ + file://ttyS0.conf \ + file://ttyS1.conf \ + file://ttyS2.conf \ + file://ttyS3.conf \ + file://ttyS7.conf \ + file://ttyS8.conf \ + " + +do_install:append() { + + # Install the configurations + install -m 0755 -d ${D}${sysconfdir}/${BPN} + install -m 0644 ${WORKDIR}/*.conf ${D}${sysconfdir}/${BPN}/ + + # Remove upstream-provided default configuration + rm -f ${D}${sysconfdir}/${BPN}/ttyVUART0.conf +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/ampere-ipmi-oem.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/ampere-ipmi-oem.bbappend new file mode 100644 index 000000000000..4e1523df7b3d --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/ampere-ipmi-oem.bbappend @@ -0,0 +1,2 @@ +PACKAGECONFIG:append = " mac-address-manual-fru-conf" +PACKAGECONFIG[mac-address-manual-fru-conf] = "-Dmac-address-fru-bus=14 -Dmac-address-fru-addr=80" diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend new file mode 100644 index 000000000000..13ed796955f6 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend @@ -0,0 +1,2 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json new file mode 100644 index 000000000000..4998665c844b --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json @@ -0,0 +1,178 @@ +{ + "0" : { + "name" : "IPMB", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "ipmb", + "protocol_type" : "ipmb-1.0", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "1" : { + "name" : "eth0", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "2" : { + "name" : "eth1", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "3" : { + "name" : "usb0", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "lan-802.3", + "protocol_type" : "ipmb-1.0", + "session_supported" : "multi-session", + "is_ipmi" : true + } + }, + "4" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "5" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "6" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "7" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "8" : { + "name" : "INTRABMC", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "oem", + "protocol_type" : "oem", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "9" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "10" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "11" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "12" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "13" : { + "name" : "RESERVED", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "reserved", + "protocol_type" : "na", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "14" : { + "name" : "SELF", + "is_valid" : false, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "ipmb", + "protocol_type" : "ipmb-1.0", + "session_supported" : "session-less", + "is_ipmi" : true + } + }, + "15" : { + "name" : "ipmi_ssif", + "is_valid" : true, + "active_sessions" : 0, + "channel_info" : { + "medium_type" : "smbus-v2.0", + "protocol_type" : "ipmi-smbus", + "session_supported" : "session-less", + "is_ipmi" : true + } + } +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json new file mode 100644 index 000000000000..8e89732e151d --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json @@ -0,0 +1,2 @@ +{"id": 32, "revision": 1, "addn_dev_support": 141, + "manuf_id": 52538, "prod_id": 131, "aux": 0} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config-native.bb b/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config-native.bb new file mode 100644 index 000000000000..3b15b53a592e --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config-native.bb @@ -0,0 +1,17 @@ +SUMMARY = "Phosphor LED Group Management for Mt. Mitchell" +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit native + +PROVIDES += "virtual/phosphor-led-manager-config-native" + +SRC_URI += "file://led.yaml" + +# Overwrite the example led layout yaml file prior +# to building the phosphor-led-manager package +do_install() { + DEST=${D}${datadir}/phosphor-led-manager + install -D ${WORKDIR}/led.yaml ${DEST}/led.yaml +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config/led.yaml b/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config/led.yaml new file mode 100644 index 000000000000..3e321ed5c69a --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/leds/ampere-led-manager-config/led.yaml @@ -0,0 +1,32 @@ +bmc_booted: + power: + Action: 'Blink' + DutyOn: 50 + Period: 1000 + Priority: 'On' + +power_on: + power: + Action: 'On' + DutyOn: 50 + Period: 0 + Priority: 'On' + +systemFault: + fault: + Action: 'On' + DutyOn: 50 + Period: 0 + Priority: 'Blink' + +enclosure_identify: + identify: + Action: 'On' + DutyOn: 50 + Period: 1000 + +enclosure_identify_blink: + identify: + Action: 'Blink' + DutyOn: 50 + Period: 1000 diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend new file mode 100644 index 000000000000..9ba7f522f9c6 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend @@ -0,0 +1,15 @@ +RDEPENDS:${PN}-extras:append = " \ + webui-vue \ + phosphor-image-signing \ + phosphor-virtual-sensor \ + phosphor-misc-usb-ctrl \ + " + +RDEPENDS:${PN}-inventory:append = " \ + dbus-sensors \ + entity-manager \ + " + +RDEPENDS:${PN}-extras:remove = " phosphor-hwmon" +VIRTUAL-RUNTIME_obmc-sensors-hwmon ?= "dbus-sensors" +RDEPENDS:${PN}-extras:append = " phosphor-virtual-sensor" diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf/mtmitchell_gpio_defs.json b/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf/mtmitchell_gpio_defs.json new file mode 100644 index 000000000000..f3542849f007 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf/mtmitchell_gpio_defs.json @@ -0,0 +1,45 @@ +{ + "gpio_configs": { + + "power_config": { + "power_good_in": "PGOOD", + "power_up_outs": [ + {"name": "OCP_MAIN_PWREN", "polarity": true}, + {"name": "BMC_SYS_PSON_L", "polarity": false} + ] + } + }, + + "gpio_definitions": [ + { + "name": "PGOOD", + "pin": "H3", + "direction": "in" + }, + { + "name": "BMC_SYS_PSON_L", + "pin": "F2", + "direction": "out" + }, + { + "name": "POWER_BUTTON", + "pin": "I6", + "direction": "both" + }, + { + "name": "RESET_BUTTON", + "pin": "Z0", + "direction": "both" + }, + { + "name": "OCP_MAIN_PWREN", + "pin": "W1", + "direction": "out" + }, + { + "name": "ID_BTN", + "pin": "S2", + "direction": "both" + } + ] +} diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend new file mode 100644 index 000000000000..331c244ab4b5 --- /dev/null +++ b/meta-ampere/meta-mitchell/recipes-phosphor/skeleton/obmc-libobmc-intf_%.bbappend @@ -0,0 +1,10 @@ +FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" + +SRC_URI += "\ + file://${MACHINE}_gpio_defs.json \ + " + +do_install:append() { + install -d ${D}${sysconfdir}/default/obmc/gpio/ + install -m 0644 ${WORKDIR}/${MACHINE}_gpio_defs.json ${D}/${sysconfdir}/default/obmc/gpio/gpio_defs.json +} diff --git a/meta-arm/.gitignore b/meta-arm/.gitignore new file mode 100644 index 000000000000..bee8a64b79a9 --- /dev/null +++ b/meta-arm/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/meta-arm/.gitlab-ci.yml b/meta-arm/.gitlab-ci.yml new file mode 100644 index 000000000000..d61443df5f9f --- /dev/null +++ b/meta-arm/.gitlab-ci.yml @@ -0,0 +1,257 @@ +image: ghcr.io/siemens/kas/kas:latest-release + +variables: + CPU_REQUEST: "" + DEFAULT_TAG: "" + # These are needed as the k8s executor doesn't respect the container entrypoint + # by default + FF_KUBERNETES_HONOR_ENTRYPOINT: 1 + FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY: 0 + +stages: + - prep + - build + +# Common job fragment to get a worker ready +.setup: + tags: + - $DEFAULT_TAG + stage: build + interruptible: true + variables: + KAS_WORK_DIR: $CI_PROJECT_DIR/work + KAS_REPO_REF_DIR: $CI_BUILDS_DIR/persist/repos + SSTATE_DIR: $CI_BUILDS_DIR/persist/sstate + DL_DIR: $CI_BUILDS_DIR/persist/downloads + BB_LOGCONFIG: $CI_PROJECT_DIR/ci/logging.yml + TOOLCHAIN_DIR: $CI_BUILDS_DIR/persist/toolchains + IMAGE_DIR: $CI_PROJECT_DIR/work/build/tmp/deploy/images + TOOLCHAIN_LINK_DIR: $CI_PROJECT_DIR/work/build/toolchains + before_script: + - echo KAS_WORK_DIR = $KAS_WORK_DIR + - echo SSTATE_DIR = $SSTATE_DIR + - echo DL_DIR = $DL_DIR + - rm -rf $KAS_WORK_DIR + - mkdir --verbose --parents $KAS_WORK_DIR $KAS_REPO_REF_DIR $SSTATE_DIR $DL_DIR $TOOLCHAIN_DIR $TOOLCHAIN_LINK_DIR + # Must do this here, as it's the only way to make sure the toolchain is installed on the same builder + - ./ci/get-binary-toolchains $DL_DIR $TOOLCHAIN_DIR $TOOLCHAIN_LINK_DIR + +# Generalised fragment to do a Kas build +.build: + extends: .setup + variables: + KUBERNETES_CPU_REQUEST: $CPU_REQUEST + script: + - KASFILES=$(./ci/jobs-to-kas "$CI_JOB_NAME") + - kas dump --update --force-checkout --resolve-refs --resolve-env $KASFILES + - kas build $KASFILES + - ./ci/check-warnings $KAS_WORK_DIR/build/warnings.log + artifacts: + name: "logs" + when: on_failure + paths: + - $CI_PROJECT_DIR/work/build/tmp/work*/**/temp/log.do_*.* + +# +# Prep stage, update repositories once +# +update-repos: + extends: .setup + stage: prep + script: + - flock --verbose --timeout 60 $KAS_REPO_REF_DIR ./ci/update-repos + +# +# Build stage, the actual build jobs +# +# Available options for building are +# TOOLCHAINS: [gcc, clang, armgcc, external-gccarm] +# TCLIBC: [glibc, musl] +# FIRMWARE: [uboot, edk2] +# VIRT: [none, xen] +# TESTING: testimage + +corstone500: + extends: .build + parallel: + matrix: + - TESTING: testimage + tags: + - x86_64 + +corstone1000-fvp: + extends: .build + parallel: + matrix: + - TESTING: [testimage,tftf] + tags: + - x86_64 + +corstone1000-mps3: + extends: .build + +fvp-base: + extends: .build + parallel: + matrix: + - TESTING: testimage + +fvp-base-arm32: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, external-gccarm] + TESTING: testimage + +fvp-baser-aemv8r64: + extends: .build + parallel: + matrix: + - TESTING: testimage + tags: + - x86_64 + +fvps: + extends: .build + +generic-arm64: + extends: .build + +juno: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + FIRMWARE: [uboot, edk2] + +musca-b1: + extends: .build + +musca-s1: + extends: .build + +n1sdp: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, armgcc] + TS: [none, trusted-services] + +qemu-generic-arm64: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + TESTING: testimage + +qemuarm64-secureboot: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + TCLIBC: [glibc, musl] + TS: [none, trusted-services] + TESTING: testimage + +qemuarm64: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + EFI: [uboot, edk2] + TESTING: testimage + - VIRT: xen + +qemuarm-secureboot: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + TESTING: testimage + +qemuarm: + extends: .build + parallel: + matrix: + - TOOLCHAINS: [gcc, clang] + EFI: [uboot, edk2] + TESTING: testimage + - VIRT: xen + +qemuarmv5: + extends: .build + parallel: + matrix: + - TESTING: testimage + +sgi575: + extends: .build + +tc1: + extends: .build + tags: + - x86_64 + +toolchains: + extends: .build + +selftest: + extends: .setup + script: + - KASFILES=./ci/qemuarm64.yml:./ci/selftest.yml + - kas shell --update --force-checkout $KASFILES -c 'oe-selftest --num-processes 1 --run-tests runfvp' + +# Validate layers are Yocto Project Compatible +check-layers: + extends: .setup + script: + - kas shell --update --force-checkout ci/base.yml:ci/meta-openembedded.yml --command \ + "yocto-check-layer-wrapper $CI_PROJECT_DIR/$LAYER --dependency $CI_PROJECT_DIR/meta-* $KAS_WORK_DIR/meta-openembedded/meta-oe --no-auto-dependency" + parallel: + matrix: + - LAYER: [meta-arm, meta-arm-bsp, meta-arm-toolchain] + +pending-updates: + extends: .setup + artifacts: + paths: + - update-report + script: + - rm -fr update-report + # This configuration has all of the layers we need enabled + - kas shell --update --force-checkout ci/qemuarm64.yml:ci/meta-openembedded.yml --command \ + "$CI_PROJECT_DIR/scripts/machine-summary.py -t report -o $CI_PROJECT_DIR/update-report $($CI_PROJECT_DIR/ci/listmachines.py meta-arm meta-arm-bsp)" + # Do this on x86 whilst the compilers are x86-only + tags: + - x86_64 + +# What percentage of machines in the layer do we build +machine-coverage: + extends: .setup + script: + - ./ci/check-machine-coverage + coverage: '/Coverage: \d+/' + +metrics: + extends: .setup + artifacts: + reports: + metrics: metrics.txt + script: + - kas shell --update --force-checkout ci/base.yml --command \ + "$CI_PROJECT_DIR/ci/patchreview $CI_PROJECT_DIR/meta-* --verbose --metrics $CI_PROJECT_DIR/metrics.txt" + +documentation: + extends: .setup + script: + - | + sudo pip3 install -r meta-arm-bsp/documentation/requirements.txt + for CONF in meta-*/documentation/*/conf.py ; do + SOURCE_DIR=$(dirname $CONF) + MACHINE=$(basename $SOURCE_DIR) + sphinx-build -vW $SOURCE_DIR build-docs/$MACHINE + done + test -d build-docs/ + artifacts: + paths: + - build-docs/ diff --git a/meta-arm/COPYING.MIT b/meta-arm/COPYING.MIT new file mode 100644 index 000000000000..89de354795ec --- /dev/null +++ b/meta-arm/COPYING.MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/meta-arm/README.md b/meta-arm/README.md new file mode 100644 index 000000000000..7779258551f2 --- /dev/null +++ b/meta-arm/README.md @@ -0,0 +1,64 @@ +Introduction +------------ +This repository contains the Arm layers for OpenEmbedded. + +* meta-arm + + This layer contains general recipes for the Arm architecture, such as firmware, FVPs, and Arm-specific integration. + +* meta-arm-autonomy + + This layer is the distribution for a reference stack for autonomous systems. + +* meta-arm-bsp + + This layer contains machines for Arm reference platforms, for example FVP Base, N1SDP, and Juno. + +* meta-arm-toolchain + + This layer contains recipes for Arm's binary toolchains (GCC and Clang for -A and -M), and a recipe to build Arm's GCC. + +Other Directories +----------------- + +* ci + + This directory contains gitlab continuous integration configuration files (KAS yaml files) as well as scripts needed for this + +* kas + + This directory contains KAS yaml files to describe builds for systems not used in CI + +* scripts + + This directory contains scripts used in running the CI tests + +Contributing +------------ +Currently, we only accept patches from the meta-arm mailing list. For general +information on how to submit a patch, please read +https://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded + +E-mail meta-arm@lists.yoctoproject.org with patches created using this process. You can configure git-send-email to automatically use this address for the meta-arm repository with the following git command: + +$ git config --local --add sendemail.to meta-arm@lists.yoctoproject.org + +Commits and patches added should follow the OpenEmbedded patch guidelines: + +https://www.openembedded.org/wiki/Commit_Patch_Message_Guidelines + +The component being changed in the shortlog should be prefixed with the layer name (without the meta- prefix), for example: + + arm-bsp/trusted-firmware-a: decrease frobbing level + + arm-toolchain/gcc: enable foobar v2 + +Reporting bugs +-------------- +E-mail meta-arm@lists.yoctoproject.org with the error encountered and the steps +to reproduce the issue. + +Maintainer(s) +------------- +* Jon Mason +* Ross Burton diff --git a/meta-arm/ci/armgcc.yml b/meta-arm/ci/armgcc.yml new file mode 100644 index 000000000000..9fb38cf22dc2 --- /dev/null +++ b/meta-arm/ci/armgcc.yml @@ -0,0 +1,6 @@ +header: + version: 11 + +local_conf_header: + cc: | + GCCVERSION = "arm-12.2" diff --git a/meta-arm/ci/base.yml b/meta-arm/ci/base.yml new file mode 100644 index 000000000000..23fb7cc76fc6 --- /dev/null +++ b/meta-arm/ci/base.yml @@ -0,0 +1,45 @@ +header: + version: 11 + +distro: poky + +defaults: + repos: + refspec: master + +repos: + meta-arm: + layers: + meta-arm: + meta-arm-bsp: + meta-arm-toolchain: + + poky: + url: https://git.yoctoproject.org/git/poky + layers: + meta: + meta-poky: + +env: + BB_LOGCONFIG: "" + TOOLCHAIN_DIR: "" + +local_conf_header: + base: | + CONF_VERSION = "2" + LICENSE_FLAGS_ACCEPTED += "Arm-FVP-EULA" + setup: | + PACKAGE_CLASSES = "package_ipk" + PACKAGECONFIG:remove:pn-qemu-system-native = "gtk+ sdl" + EXTRA_IMAGE_FEATURES:append = " debug-tweaks" + PACKAGECONFIG:append:pn-perf = " coresight" + INHERIT += "rm_work" + DISTRO_FEATURES:remove = "ptest" + extrapackages: | + CORE_IMAGE_EXTRA_INSTALL += "perf opencsd" + CORE_IMAGE_EXTRA_INSTALL:append:aarch64 = " gator-daemon" + +machine: unset + +target: + - core-image-sato diff --git a/meta-arm/ci/check-machine-coverage b/meta-arm/ci/check-machine-coverage new file mode 100755 index 000000000000..f329fcebac9c --- /dev/null +++ b/meta-arm/ci/check-machine-coverage @@ -0,0 +1,28 @@ +#! /usr/bin/env python3 + +from pathlib import Path +import sys +from listmachines import list_machines + +metaarm = Path.cwd() + +if metaarm.name != "meta-arm": + print("Not running inside meta-arm") + sys.exit(1) + +# Find all layers +layers = (p.name for p in metaarm.glob("meta-*") if p.is_dir()) +# All machine configurations +machines = list_machines(layers) + +# All kas files +kas = metaarm.glob("ci/*.yml") +kas = set(p.stem for p in kas) + +missing = machines - kas +print(f"The following machines are missing: {', '.join(sorted(missing))}.") + +covered = len(machines) - len(missing) +total = len(machines) +percent = int(covered / total * 100) +print(f"Coverage: {percent}%") diff --git a/meta-arm/ci/check-warnings b/meta-arm/ci/check-warnings new file mode 100755 index 000000000000..89ae955dfe81 --- /dev/null +++ b/meta-arm/ci/check-warnings @@ -0,0 +1,19 @@ +#! /bin/bash + +# Expects the path to a log file as $1, and if this file has any content +# then display the contents and exit with an error code. + +set -e -u + +LOGFILE=$1 + +LINES=$(grep --invert-match "attempting MIRRORS if available" $LOGFILE | wc -l) +if test "$LINES" -ne 0; then + echo ============================== + echo The build had warnings/errors: + echo ============================== + cat $LOGFILE + exit 1 +fi + +exit 0 diff --git a/meta-arm/ci/clang.yml b/meta-arm/ci/clang.yml new file mode 100644 index 000000000000..a2063f19c0cc --- /dev/null +++ b/meta-arm/ci/clang.yml @@ -0,0 +1,10 @@ +header: + version: 11 + +repos: + meta-clang: + url: https://github.com/kraj/meta-clang + +local_conf_header: + clang: | + TOOLCHAIN = "clang" diff --git a/meta-arm/ci/corstone1000-common.yml b/meta-arm/ci/corstone1000-common.yml new file mode 100644 index 000000000000..65ff9d38618c --- /dev/null +++ b/meta-arm/ci/corstone1000-common.yml @@ -0,0 +1,15 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/meta-openembedded.yml + +local_conf_header: + extrapackages: | + # Intentionally blank to prevent perf from being added to the image in base.yml + +distro: poky-tiny + +target: + - corstone1000-image + - perf diff --git a/meta-arm/ci/corstone1000-fvp.yml b/meta-arm/ci/corstone1000-fvp.yml new file mode 100644 index 000000000000..7d21b9842880 --- /dev/null +++ b/meta-arm/ci/corstone1000-fvp.yml @@ -0,0 +1,12 @@ +header: + version: 11 + includes: + - ci/corstone1000-common.yml + - ci/fvp.yml + +local_conf_header: + fvp-config: | + # Remove Dropbear SSH as it will not fit into the corstone1000 image. + IMAGE_FEATURES:remove = " ssh-server-dropbear" + +machine: corstone1000-fvp diff --git a/meta-arm/ci/corstone1000-mps3.yml b/meta-arm/ci/corstone1000-mps3.yml new file mode 100644 index 000000000000..2df7d97671ee --- /dev/null +++ b/meta-arm/ci/corstone1000-mps3.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/corstone1000-common.yml + +machine: corstone1000-mps3 diff --git a/meta-arm/ci/corstone500.yml b/meta-arm/ci/corstone500.yml new file mode 100644 index 000000000000..437c97c5d776 --- /dev/null +++ b/meta-arm/ci/corstone500.yml @@ -0,0 +1,19 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/fvp.yml + +local_conf_header: + fvp-config: | + IMAGE_FEATURES:remove = " ssh-server-dropbear" + extrapackages: | + # Intentionally blank to prevent perf from being added to the image in base.yml + +machine: corstone500 + +distro: poky-tiny + +target: + - core-image-minimal + - perf diff --git a/meta-arm/ci/edk2.yml b/meta-arm/ci/edk2.yml new file mode 100644 index 000000000000..1261bf10fcbb --- /dev/null +++ b/meta-arm/ci/edk2.yml @@ -0,0 +1,17 @@ +header: + version: 11 + +local_conf_header: + bootfirmware: | + PREFERRED_PROVIDER_virtual/bootloader = "edk2-firmware" + MACHINE_FEATURES += "efi" + TFA_UBOOT = "0" + TFA_UEFI = "1" + + EXTRA_IMAGEDEPENDS += "edk2-firmware" + EFI_PROVIDER ?= "grub-efi" + + QB_DEFAULT_BIOS = "QEMU_EFI.fd" + WKS_FILE ?= "efi-disk.wks.in" + failing_tests: | + TEST_SUITES:remove = "xorg" diff --git a/meta-arm/ci/external-gccarm.yml b/meta-arm/ci/external-gccarm.yml new file mode 100644 index 000000000000..2af8b5e8e962 --- /dev/null +++ b/meta-arm/ci/external-gccarm.yml @@ -0,0 +1,8 @@ +header: + version: 11 + +local_conf_header: + cc: | + SKIP_RECIPE[gcc-cross-arm] = "Using external toolchain" + TCMODE = "external-arm" + EXTERNAL_TOOLCHAIN = "${TOPDIR}/toolchains/${TARGET_ARCH}" diff --git a/meta-arm/ci/fvp-base-arm32.yml b/meta-arm/ci/fvp-base-arm32.yml new file mode 100644 index 000000000000..9f790f670d62 --- /dev/null +++ b/meta-arm/ci/fvp-base-arm32.yml @@ -0,0 +1,7 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/fvp.yml + +machine: fvp-base-arm32 diff --git a/meta-arm/ci/fvp-base.yml b/meta-arm/ci/fvp-base.yml new file mode 100644 index 000000000000..fbba69844445 --- /dev/null +++ b/meta-arm/ci/fvp-base.yml @@ -0,0 +1,7 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/fvp.yml + +machine: fvp-base diff --git a/meta-arm/ci/fvp-baser-aemv8r64.yml b/meta-arm/ci/fvp-baser-aemv8r64.yml new file mode 100644 index 000000000000..40818bc6a3b7 --- /dev/null +++ b/meta-arm/ci/fvp-baser-aemv8r64.yml @@ -0,0 +1,7 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: fvp-baser-aemv8r64 + diff --git a/meta-arm/ci/fvp.yml b/meta-arm/ci/fvp.yml new file mode 100644 index 000000000000..a12c621e0b66 --- /dev/null +++ b/meta-arm/ci/fvp.yml @@ -0,0 +1,11 @@ +header: + version: 11 + +local_conf_header: + testimagefvp: | + INHERIT = "fvpboot" + # This fails but we can't add to the ignorelist from meta-arm yet + # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14604 + TEST_SUITES:remove = "parselogs" + failing_tests: | + TEST_SUITES:remove = "xorg" diff --git a/meta-arm/ci/fvps.yml b/meta-arm/ci/fvps.yml new file mode 100644 index 000000000000..e3bc5fe5a067 --- /dev/null +++ b/meta-arm/ci/fvps.yml @@ -0,0 +1,19 @@ +# Simple target to build the FVPs that are publically available + +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarm64 + +local_conf_header: + sdk: | + SDKMACHINE = "x86_64" + +target: + - nativesdk-fvp-base-a-aem + - nativesdk-fvp-n1-edge + - nativesdk-fvp-sgi575 + - nativesdk-fvp-corstone500 + - nativesdk-fvp-corstone1000 diff --git a/meta-arm/ci/generic-arm64.yml b/meta-arm/ci/generic-arm64.yml new file mode 100644 index 000000000000..873c9fd193b2 --- /dev/null +++ b/meta-arm/ci/generic-arm64.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: generic-arm64 diff --git a/meta-arm/ci/get-binary-toolchains b/meta-arm/ci/get-binary-toolchains new file mode 100755 index 000000000000..23c3bbb16b1c --- /dev/null +++ b/meta-arm/ci/get-binary-toolchains @@ -0,0 +1,50 @@ +#!/bin/bash +set -u -e + +BASENAME=arm-gnu-toolchain +VER=${VER:-12.2.rel1} +HOST_ARCH=${HOST_ARCH:-$(uname -m)} + +DOWNLOAD_DIR=$1 +TOOLCHAIN_DIR=$2 +TOOLCHAIN_LINK_DIR=$3 + +# These should be already created by .gitlab-ci.yml, but do here if run outside of that env +mkdir -p $DOWNLOAD_DIR $TOOLCHAIN_DIR $TOOLCHAIN_LINK_DIR + +download() { + TRIPLE=$1 + URL=https://developer.arm.com/-/media/Files/downloads/gnu/$VER/binrel/$BASENAME-$VER-$HOST_ARCH-$TRIPLE.tar.xz + wget -P $DOWNLOAD_DIR -nc $URL +} + +if [ $HOST_ARCH = "aarch64" ]; then + # AArch64 Linux hosted cross compilers + + # AArch32 target with hard float + download arm-none-linux-gnueabihf +elif [ $HOST_ARCH = "x86_64" ]; then + # x86_64 Linux hosted cross compilers + + # AArch32 target with hard float + download arm-none-linux-gnueabihf + + # AArch64 GNU/Linux target + download aarch64-none-linux-gnu +else + echo "ERROR - Unknown build arch of $HOST_ARCH" + exit 1 +fi + +for i in arm aarch64; do + if [ ! -d $TOOLCHAIN_DIR/$BASENAME-$VER-$HOST_ARCH-$i-none-linux-gnu*/ ]; then + if [ ! -f $DOWNLOAD_DIR/$BASENAME-$VER-$HOST_ARCH-$i-none-linux-gnu*.tar.xz ]; then + continue + fi + + tar -C $TOOLCHAIN_DIR -axvf $DOWNLOAD_DIR/$BASENAME-$VER-$HOST_ARCH-$i-none-linux-gnu*.tar.xz + fi + + # Setup a link for the toolchain to use local to the building machine (e.g., not in a shared location) + ln -s $TOOLCHAIN_DIR/$BASENAME-$VER-$HOST_ARCH-$i-none-linux-gnu* $TOOLCHAIN_LINK_DIR/$i +done diff --git a/meta-arm/ci/jobs-to-kas b/meta-arm/ci/jobs-to-kas new file mode 100755 index 000000000000..d6896b7728d9 --- /dev/null +++ b/meta-arm/ci/jobs-to-kas @@ -0,0 +1,27 @@ +#! /bin/bash + +# This script is expecting an input of machine name, optionally followed by a +# colon and a list of one or more parameters separated by commas between +# brackets. For example, the following are acceptable: +# corstone500 +# fvp-base: [testimage] +# qemuarm64-secureboot: [clang, glibc, testimage] +# +# Turn this list into a series of yml files separated by colons to pass to kas + +set -e -u + +FILES="ci/$(echo $1 | cut -d ':' -f 1).yml" + +for i in $(echo $1 | cut -s -d ':' -f 2 | sed 's/[][,]//g'); do + # Given that there are no yml files for gcc or glibc, as those are the + # defaults, we can simply ignore those parameters. They are necessary + # to pass in so that matrix can correctly setup all of the permutations + # of each individual run. + if [[ $i == 'none' || $i == 'gcc' || $i == 'glibc' || $i == 'uboot' ]]; then + continue + fi + FILES+=":ci/$i.yml" +done + +echo $FILES diff --git a/meta-arm/ci/juno.yml b/meta-arm/ci/juno.yml new file mode 100644 index 000000000000..b2ee60a7e9e9 --- /dev/null +++ b/meta-arm/ci/juno.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: juno diff --git a/meta-arm/ci/listmachines.py b/meta-arm/ci/listmachines.py new file mode 100755 index 000000000000..04d207e48b20 --- /dev/null +++ b/meta-arm/ci/listmachines.py @@ -0,0 +1,29 @@ +#! /usr/bin/env python3 + +import pathlib +import typing +import sys + +""" +List all of the machines available under the listed sub-layers of meta-arm. +""" +def list_machines(layers: typing.Sequence[str]) -> typing.Set[str]: + machines = set() + + # We know we're in meta-arm/scripts, so find the top-level directory + metaarm = pathlib.Path(__file__).resolve().parent.parent + if metaarm.name != "meta-arm": + raise Exception("Not running inside meta-arm") + + for layer in layers: + machines |= set(p.stem for p in (metaarm / layer / "conf" / "machine").glob("*.conf")) + return machines + +if __name__ == "__main__": + if len(sys.argv) > 1: + machines = list_machines(sys.argv[1:]) + print(" ".join(sorted(machines))) + sys.exit(0) + else: + print("Usage:\n$ %s [layer name ...] " % sys.argv[0]) + sys.exit(1) diff --git a/meta-arm/ci/logging.yml b/meta-arm/ci/logging.yml new file mode 100644 index 000000000000..3af10295f8f3 --- /dev/null +++ b/meta-arm/ci/logging.yml @@ -0,0 +1,13 @@ +# Python logging configuration to write all warnings to a separate file +version: 1 + +handlers: + warnings: + class: logging.FileHandler + level: WARNING + filename: warnings.log + formatter: BitBake.logfileFormatter + +loggers: + BitBake: + handlers: [warnings] diff --git a/meta-arm/ci/meta-openembedded.yml b/meta-arm/ci/meta-openembedded.yml new file mode 100644 index 000000000000..bed338dae05c --- /dev/null +++ b/meta-arm/ci/meta-openembedded.yml @@ -0,0 +1,11 @@ +header: + version: 11 + +repos: + meta-openembedded: + url: https://git.openembedded.org/meta-openembedded + layers: + meta-filesystems: + meta-networking: + meta-oe: + meta-python: diff --git a/meta-arm/ci/meta-virtualization.yml b/meta-arm/ci/meta-virtualization.yml new file mode 100644 index 000000000000..1cd0e21a8925 --- /dev/null +++ b/meta-arm/ci/meta-virtualization.yml @@ -0,0 +1,8 @@ +header: + version: 11 + includes: + - ci/meta-openembedded.yml + +repos: + meta-virtualization: + url: git://git.yoctoproject.org/meta-virtualization diff --git a/meta-arm/ci/musca-b1.yml b/meta-arm/ci/musca-b1.yml new file mode 100644 index 000000000000..b38dd1e401ae --- /dev/null +++ b/meta-arm/ci/musca-b1.yml @@ -0,0 +1,10 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/meta-openembedded.yml + +machine: musca-b1 + +target: + - trusted-firmware-m diff --git a/meta-arm/ci/musca-s1.yml b/meta-arm/ci/musca-s1.yml new file mode 100644 index 000000000000..29f289a31a03 --- /dev/null +++ b/meta-arm/ci/musca-s1.yml @@ -0,0 +1,10 @@ +header: + version: 11 + includes: + - ci/base.yml + - ci/meta-openembedded.yml + +machine: musca-s1 + +target: + - trusted-firmware-m diff --git a/meta-arm/ci/musl.yml b/meta-arm/ci/musl.yml new file mode 100644 index 000000000000..ee7905ec8d35 --- /dev/null +++ b/meta-arm/ci/musl.yml @@ -0,0 +1,6 @@ +header: + version: 11 + +local_conf_header: + libc: | + TCLIBC = "musl" diff --git a/meta-arm/ci/n1sdp.yml b/meta-arm/ci/n1sdp.yml new file mode 100644 index 000000000000..797a52255c14 --- /dev/null +++ b/meta-arm/ci/n1sdp.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: n1sdp diff --git a/meta-arm/ci/patchreview b/meta-arm/ci/patchreview new file mode 100755 index 000000000000..b23eda1f1431 --- /dev/null +++ b/meta-arm/ci/patchreview @@ -0,0 +1,286 @@ +#! /usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-only +# + +# TODO +# - option to just list all broken files +# - test suite +# - validate signed-off-by + +import argparse +import collections +import json +import os +import re +import subprocess + +status_values = ( + "accepted", + "pending", + "inappropriate", + "backport", + "submitted", + "denied", +) + + +class PatchResult: + # Whether the patch has an Upstream-Status or not + missing_upstream_status = False + # If the Upstream-Status tag is malformed in some way (string for bad bit) + malformed_upstream_status = None + # If the Upstream-Status value is unknown (boolean) + unknown_upstream_status = False + # The upstream status value (Pending, etc) + upstream_status = None + # Whether the patch has a Signed-off-by or not + missing_sob = False + # Whether the Signed-off-by tag is malformed in some way + malformed_sob = False + # The Signed-off-by tag value + sob = None + # Whether a patch looks like a CVE but doesn't have a CVE tag + missing_cve = False + + +class Summary: + total = 0 + cve_missing = 0 + sob_missing = 0 + sob_malformed = 0 + status_missing = 0 + status_malformed = 0 + status_pending = 0 + +def blame_patch(patch): + """ + From a patch filename, return a list of "commit summary (author name )" strings representing the history. + """ + return subprocess.check_output(("git", "log", + "--follow", "--find-renames", "--diff-filter=A", + "--format=%s (%aN <%aE>)", + "--", patch)).decode("utf-8").splitlines() + +def patchreview(patches): + # General pattern: start of line, optional whitespace, tag with optional + # hyphen or spaces, maybe a colon, some whitespace, then the value, all case + # insensitive. + sob_re = re.compile(r"^[\t ]*(Signed[-_ ]off[-_ ]by:?)[\t ]*(.+)", re.IGNORECASE | re.MULTILINE) + status_re = re.compile(r"^[\t ]*(Upstream[-_ ]Status:?)[\t ]*(\w*)", re.IGNORECASE | re.MULTILINE) + cve_tag_re = re.compile(r"^[\t ]*(CVE:)[\t ]*(.*)", re.IGNORECASE | re.MULTILINE) + cve_re = re.compile(r"cve-[0-9]{4}-[0-9]{4,6}", re.IGNORECASE) + + results = {} + + for patch in patches: + + result = PatchResult() + results[patch] = result + + content = open(patch, encoding="ascii", errors="ignore").read() + + # Find the Signed-off-by tag + match = sob_re.search(content) + if match: + value = match.group(1) + if value != "Signed-off-by:": + result.malformed_sob = value + result.sob = match.group(2) + else: + result.missing_sob = True + + # Find the Upstream-Status tag + match = status_re.search(content) + if match: + value = match.group(1) + if value != "Upstream-Status:": + result.malformed_upstream_status = value + + value = match.group(2).lower() + # TODO: check case + if value not in status_values: + result.unknown_upstream_status = True + result.upstream_status = value + else: + result.missing_upstream_status = True + + # Check that patches which looks like CVEs have CVE tags + if cve_re.search(patch) or cve_re.search(content): + if not cve_tag_re.search(content): + result.missing_cve = True + # TODO: extract CVE list + + return results + + +def analyse(results, want_blame=False, verbose=True): + """ + want_blame: display blame data for each malformed patch + verbose: display per-file results instead of just summary + """ + + # want_blame requires verbose, so disable blame if we're not verbose + if want_blame and not verbose: + want_blame = False + + summary = Summary() + + for patch in sorted(results): + r = results[patch] + summary.total += 1 + need_blame = False + + # Build statistics + if r.missing_sob: + summary.sob_missing += 1 + if r.malformed_sob: + summary.sob_malformed += 1 + if r.missing_upstream_status: + summary.status_missing += 1 + if r.malformed_upstream_status or r.unknown_upstream_status: + summary.status_malformed += 1 + # Count patches with no status as pending + summary.status_pending += 1 + if r.missing_cve: + summary.cve_missing += 1 + if r.upstream_status == "pending": + summary.status_pending += 1 + + # Output warnings + if r.missing_sob: + need_blame = True + if verbose: + print("Missing Signed-off-by tag (%s)" % patch) + if r.malformed_sob: + need_blame = True + if verbose: + print("Malformed Signed-off-by '%s' (%s)" % (r.malformed_sob, patch)) + if r.missing_cve: + need_blame = True + if verbose: + print("Missing CVE tag (%s)" % patch) + if r.missing_upstream_status: + need_blame = True + if verbose: + print("Missing Upstream-Status tag (%s)" % patch) + if r.malformed_upstream_status: + need_blame = True + if verbose: + print("Malformed Upstream-Status '%s' (%s)" % (r.malformed_upstream_status, patch)) + if r.unknown_upstream_status: + need_blame = True + if verbose: + print("Unknown Upstream-Status value '%s' (%s)" % (r.upstream_status, patch)) + + if want_blame and need_blame: + print("\n".join(blame_patch(patch)) + "\n") + + return summary + + +def display_summary(summary, verbose): + def percent(num): + try: + return "%d (%d%%)" % (num, round(num * 100.0 / summary.total)) + except ZeroDivisionError: + return "N/A" + + if verbose: + print() + + print("""Total patches found: %d +Patches missing Signed-off-by: %s +Patches with malformed Signed-off-by: %s +Patches missing CVE: %s +Patches missing Upstream-Status: %s +Patches with malformed Upstream-Status: %s +Patches in Pending state: %s""" % (summary.total, + percent(summary.sob_missing), + percent(summary.sob_malformed), + percent(summary.cve_missing), + percent(summary.status_missing), + percent(summary.status_malformed), + percent(summary.status_pending))) + + +def generate_metrics(summary, output): + # https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md + # Summary attribute name, MetricPoint help + mapping = ( + ("total", "Total patches"), + ("cve_missing", "Patches missing CVE tag"), + ("sob_malformed", "Patches with malformed Signed-off-by"), + ("sob_missing", "Patches with missing Signed-off-by"), + ("status_malformed", "Patches with malformed Upstream-Status"), + ("status_missing", "Patches with missing Upstream-Status"), + ("status_pending", "Patches with Pending Upstream-Status") + ) + for attr, help in mapping: + metric = f"patch_check_{attr}" + value = getattr(summary, attr) + output.write(f""" +# TYPE {metric} gauge +# HELP {help} +{metric} {value} +""") + output.write("\n# EOF\n") + +def histogram(results): + import math + + from toolz import dicttoolz, recipes + counts = recipes.countby(lambda r: r.upstream_status, results.values()) + bars = dicttoolz.valmap(lambda v: "#" * int(math.ceil(float(v) / len(results) * 100)), counts) + for k in bars: + print("%-20s %s (%d)" % (k.capitalize() if k else "No status", bars[k], counts[k])) + +def gather_patches(directories): + patches = [] + for directory in directories: + filenames = subprocess.check_output(("git", "-C", directory, "ls-files", "recipes-*/**/*.patch", "recipes-*/**/*.diff")).decode("utf-8").split() + patches += [os.path.join(directory, f) for f in filenames] + return patches + +if __name__ == "__main__": + args = argparse.ArgumentParser(description="Patch Review Tool") + args.add_argument("-b", "--blame", action="store_true", help="show blame for malformed patches") + args.add_argument("-v", "--verbose", action="store_true", help="show per-patch results") + args.add_argument("-g", "--histogram", action="store_true", help="show patch histogram") + args.add_argument("-j", "--json", help="update JSON") + args.add_argument("-m", "--metrics", type=argparse.FileType('w'), help="write OpenMetrics") + args.add_argument("dirs", metavar="DIRECTORY", nargs="+", help="directory to scan") + args = args.parse_args() + + patches = gather_patches(args.dirs) + results = patchreview(patches) + summary = analyse(results, want_blame=args.blame, verbose=args.verbose) + display_summary(summary, verbose=args.verbose) + + if args.json: + if os.path.isfile(args.json): + data = json.load(open(args.json)) + else: + data = [] + + row = collections.Counter() + row["total"] = len(results) + row["date"] = subprocess.check_output(["git", "-C", args.dirs[0], "show", "-s", "--pretty=format:%cd", "--date=format:%s"]).decode("utf-8").strip() + for r in results.values(): + if r.upstream_status in status_values: + row[r.upstream_status] += 1 + if r.malformed_upstream_status or r.missing_upstream_status: + row["malformed-upstream-status"] += 1 + if r.malformed_sob or r.missing_sob: + row["malformed-sob"] += 1 + + data.append(row) + json.dump(data, open(args.json, "w")) + + if args.metrics: + generate_metrics(summary, args.metrics) + + if args.histogram: + print() + histogram(results) diff --git a/meta-arm/ci/qemu-generic-arm64.yml b/meta-arm/ci/qemu-generic-arm64.yml new file mode 100644 index 000000000000..32c4b9812eb5 --- /dev/null +++ b/meta-arm/ci/qemu-generic-arm64.yml @@ -0,0 +1,14 @@ +header: + version: 11 + includes: + - ci/generic-arm64.yml + +local_conf_header: + failing_tests: | + DEFAULT_TEST_SUITES:remove = "parselogs" + +machine: qemu-generic-arm64 + +target: + - core-image-sato + - sbsa-acs diff --git a/meta-arm/ci/qemuarm-secureboot.yml b/meta-arm/ci/qemuarm-secureboot.yml new file mode 100644 index 000000000000..044661cdc779 --- /dev/null +++ b/meta-arm/ci/qemuarm-secureboot.yml @@ -0,0 +1,12 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarm-secureboot + +target: + - core-image-base + - optee-examples + - optee-test + - optee-os-tadevkit diff --git a/meta-arm/ci/qemuarm.yml b/meta-arm/ci/qemuarm.yml new file mode 100644 index 000000000000..4155847c19d8 --- /dev/null +++ b/meta-arm/ci/qemuarm.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarm diff --git a/meta-arm/ci/qemuarm64-secureboot.yml b/meta-arm/ci/qemuarm64-secureboot.yml new file mode 100644 index 000000000000..f617dfc5ca10 --- /dev/null +++ b/meta-arm/ci/qemuarm64-secureboot.yml @@ -0,0 +1,12 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarm64-secureboot + +target: + - core-image-base + - optee-examples + - optee-test + - optee-os-tadevkit diff --git a/meta-arm/ci/qemuarm64.yml b/meta-arm/ci/qemuarm64.yml new file mode 100644 index 000000000000..663903443220 --- /dev/null +++ b/meta-arm/ci/qemuarm64.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarm64 diff --git a/meta-arm/ci/qemuarmv5.yml b/meta-arm/ci/qemuarmv5.yml new file mode 100644 index 000000000000..18c7a15a2d7e --- /dev/null +++ b/meta-arm/ci/qemuarmv5.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: qemuarmv5 diff --git a/meta-arm/ci/selftest.yml b/meta-arm/ci/selftest.yml new file mode 100644 index 000000000000..9a587354bd41 --- /dev/null +++ b/meta-arm/ci/selftest.yml @@ -0,0 +1,7 @@ +header: + version: 11 + +local_conf_header: + setup: | + BB_LOGCONFIG = "" + SANITY_TESTED_DISTROS = "" diff --git a/meta-arm/ci/sgi575.yml b/meta-arm/ci/sgi575.yml new file mode 100644 index 000000000000..1895fc523e02 --- /dev/null +++ b/meta-arm/ci/sgi575.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: sgi575 diff --git a/meta-arm/ci/tc1.yml b/meta-arm/ci/tc1.yml new file mode 100644 index 000000000000..fd9acbd27e9d --- /dev/null +++ b/meta-arm/ci/tc1.yml @@ -0,0 +1,9 @@ +header: + version: 11 + includes: + - ci/base.yml + +machine: tc1 + +target: + - tc-artifacts-image diff --git a/meta-arm/ci/testimage.yml b/meta-arm/ci/testimage.yml new file mode 100644 index 000000000000..d7de7d061c1e --- /dev/null +++ b/meta-arm/ci/testimage.yml @@ -0,0 +1,19 @@ +header: + version: 11 + +local_conf_header: + testimage: | + IMAGE_CLASSES += "testimage" + TESTIMAGE_AUTO = "1" + kvm: | + QEMU_USE_KVM = "" + slirp: | + TEST_RUNQEMUPARAMS = "slirp" + TEST_SERVER_IP = "127.0.0.1" + QEMU_USE_SLIRP = "1" + sshd: | + IMAGE_FEATURES:append = " ssh-server-dropbear" + sshkeys: | + CORE_IMAGE_EXTRA_INSTALL += "ssh-pregen-hostkeys" + universally_failing_tests: | + TEST_SUITES:remove = "opkg" diff --git a/meta-arm/ci/tftf.yml b/meta-arm/ci/tftf.yml new file mode 100644 index 000000000000..6e42d9c68862 --- /dev/null +++ b/meta-arm/ci/tftf.yml @@ -0,0 +1,7 @@ +header: + version: 9 + +local_conf_header: + tftf: | + TFA_UBOOT = "0" + TFTF_TESTS = "1" diff --git a/meta-arm/ci/toolchains.yml b/meta-arm/ci/toolchains.yml new file mode 100644 index 000000000000..080d8d978e42 --- /dev/null +++ b/meta-arm/ci/toolchains.yml @@ -0,0 +1,19 @@ +header: + version: 11 + includes: + - ci/base.yml + +# Target is arm64 and SDK is x86-64 to ensure that we exercise both +# architectures + +machine: qemuarm64 +local_conf_header: + toolchains: | + SDKMACHINE = "x86_64" + +target: + - gcc-aarch64-none-elf + - nativesdk-gcc-aarch64-none-elf + - gcc-arm-none-eabi + - nativesdk-gcc-arm-none-eabi + - nativesdk-androidclang diff --git a/meta-arm/ci/trusted-services.yml b/meta-arm/ci/trusted-services.yml new file mode 100644 index 000000000000..433ec78b3783 --- /dev/null +++ b/meta-arm/ci/trusted-services.yml @@ -0,0 +1,14 @@ +header: + version: 11 + includes: + - ci/meta-openembedded.yml + +local_conf_header: + trusted_services: | + TEST_SUITES:append = " trusted_services" + # Include TS Crypto, Storage, ITS, Attestation and SMM-Gateway SPs into optee-os image + MACHINE_FEATURES:append = " arm-ffa ts-crypto ts-storage ts-its ts-attestation ts-smm-gateway" + # Include TS demo/test tools into image + IMAGE_INSTALL:append = " packagegroup-ts-tests" + # Include TS PSA Arch tests into image + IMAGE_INSTALL:append = " packagegroup-ts-tests-psa" diff --git a/meta-arm/ci/update-repos b/meta-arm/ci/update-repos new file mode 100755 index 000000000000..91ff19758472 --- /dev/null +++ b/meta-arm/ci/update-repos @@ -0,0 +1,42 @@ +#! /usr/bin/env python3 + +# Update clones of the repositories we need in KAS_REPO_REF_DIR to speed up fetches + +import sys +import os +import subprocess +import pathlib + +def repo_shortname(url): + # Taken from Kas (Repo.__getattr__) to ensure the logic is right + from urllib.parse import urlparse + url = urlparse(url) + return ('{url.netloc}{url.path}' + .format(url=url) + .replace('@', '.') + .replace(':', '.') + .replace('/', '.') + .replace('*', '.')) + +repositories = ( + "https://git.yoctoproject.org/git/poky", + "https://git.openembedded.org/meta-openembedded", + "https://git.yoctoproject.org/git/meta-virtualization", + "https://github.com/kraj/meta-clang", +) + +if __name__ == "__main__": + if "KAS_REPO_REF_DIR" not in os.environ: + print("KAS_REPO_REF_DIR needs to be set") + sys.exit(1) + + base_repodir = pathlib.Path(os.environ["KAS_REPO_REF_DIR"]) + + for repo in repositories: + repodir = base_repodir / repo_shortname(repo) + if repodir.exists(): + print("Updating %s..." % repo) + subprocess.run(["git", "-C", repodir, "fetch"], check=True) + else: + print("Cloning %s..." % repo) + subprocess.run(["git", "clone", "--bare", repo, repodir], check=True) diff --git a/meta-arm/ci/xen.yml b/meta-arm/ci/xen.yml new file mode 100644 index 000000000000..d8b75d44dc8f --- /dev/null +++ b/meta-arm/ci/xen.yml @@ -0,0 +1,11 @@ +header: + version: 11 + includes: + - ci/meta-virtualization.yml + +local_conf_header: + meta-virt: | + DISTRO_FEATURES:append = " virtualization xen" + +target: + - xen-image-minimal diff --git a/meta-arm/documentation/oeqa-fvp.md b/meta-arm/documentation/oeqa-fvp.md new file mode 100644 index 000000000000..e146885197f5 --- /dev/null +++ b/meta-arm/documentation/oeqa-fvp.md @@ -0,0 +1,55 @@ +# OEQA on Arm FVPs + +OE-Core's [oeqa][OEQA] framework provides a method of performing runtime tests on machines using the `testimage` Yocto task. meta-arm has good support for writing test cases against [Arm FVPs][FVP], meaning the [runfvp][RUNFVP] boot configuration can be re-used. + +Tests can be configured to run automatically post-build by setting the variable `TESTIMAGE_AUTO="1"`, e.g. in your Kas file or local.conf. + +There are two main methods of testing, using different test "targets". Both test targets generate an additional log file with the prefix 'fvp_log' in the image recipe's `${WORKDIR}/testimage` containing the FVP's stdout. + +## OEFVPTarget + +This runs test cases on a machine using SSH. It therefore requires that an SSH server is installed in the image. + +In test cases, the primary interface with the target is, e.g: +``` +(status, output) = self.target.run('uname -a') +``` +which runs a single command on the target (using `ssh -c`) and returns the status code and the output. It is therefore useful for running tests in a Linux environment. + +For examples of test cases, see meta/lib/oeqa/runtime/cases in OE-Core. The majority of test cases depend on `ssh.SSHTest.test_ssh`, which first validates that the SSH connection is functioning. + +Example machine configuration: +``` +TEST_TARGET = "OEFVPTarget" +TEST_SERVER_IP = "127.0.0.1" +TEST_TARGET_IP = "127.0.0.1:8022" +IMAGE_FEATURES:append = " ssh-server-dropbear" +FVP_CONFIG[bp.virtio_net.hostbridge.userNetPorts] ?= "8022=22" +``` + +## OEFVPSerialTarget + +This runs tests against one or more serial consoles on the FVP. It is more flexible than OEFVPTarget, but test cases written for this test target do not support the test cases in OE-core. As it does not require an SSH server, it is suitable for machines with performance or memory limitations. + +Internally, this test target launches a [Pexpect][PEXPECT] instance for each entry in FVP_CONSOLES which can be used with the provided alias. The whole Pexpect API is exposed on the target, where the alias is always passed as the first argument, e.g.: +``` +self.target.expect('default', r'root@.*\:~#', timeout=30) +self.assertNotIn(b'ERROR:', self.target.before('tf-a')) +``` + +For an example of a full test case, see meta-arm/lib/oeqa/runtime/cases/linuxboot.py This test case can be used to minimally verify that a machine boots to a Linux shell. The default timeout is 10 minutes, but this can be configured with the variable TEST_FVP_LINUX_BOOT_TIMEOUT, which expects a value in seconds. + +The SSH interface described above is also available on OEFVPSerialTarget to support writing a set of hybrid test suites that use a combination of serial and SSH access. Note however that this test target does not guarantee that Linux has booted to shell prior to running any tests, so the test cases in OE-core are not supported. + +Example machine configuration: +``` +TEST_TARGET="OEFVPSerialTarget" +TEST_SUITES="linuxboot" +FVP_CONSOLES[default] = "terminal_0" +FVP_CONSOLES[tf-a] = "s_terminal_0" +``` + +[OEQA]: https://docs.yoctoproject.org/test-manual/intro.html +[FVP]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms +[RUNFVP]: runfvp.md +[PEXPECT]: https://pexpect.readthedocs.io/en/stable/overview.html diff --git a/meta-arm/documentation/runfvp.md b/meta-arm/documentation/runfvp.md new file mode 100644 index 000000000000..01b136934bb9 --- /dev/null +++ b/meta-arm/documentation/runfvp.md @@ -0,0 +1,131 @@ +# Running Images with a FVP + +The `runfvp` tool in meta-arm makes it easy to run Yocto Project disk images inside a [Fixed Virtual Platform (FVP)][FVP]. Some FVPs, such as the [Arm Architecture Models][AEM], are available free to download, but others need registration or are only available commercially. The `fvp-base` machine in meta-arm-bsp uses one of these AEM models. + +## Running images with `runfvp` + +To build images with the FVP integration, the `fvpboot` class needs to be inherited. If the machine does not do this explicitly it can be done in `local.conf`: + +``` +INHERIT += "fvpboot" +``` + +The class will download the correct FVP and write a `.fvpconf` configuration file when an image is built. + +To run an image in a FVP, pass either a machine name or a `.fvpconf` path to `runfvp`. + +``` +$ ./meta-arm/scripts/runfvp tmp/deploy/images/fvp-base/core-image-minimal-fvp-base.fvpconf +``` + +When a machine name is passed, `runfvp` will start the latest image that has been built for that machine. This requires that the BitBake environment has been initialized (using `oe-init-build-env` or similar) as it will start BitBake to determine where the images are. + +``` +$ ./meta-arm/scripts/runfvp fvp-base +``` + +Note that currently meta-arm's `scripts` directory isn't in `PATH`, so a full path needs to be used. + +`runfvp` will automatically start terminals connected to each of the serial ports that the machine specifies. This can be controlled by using the `--terminals` option, for example `--terminals=none` will mean no terminals are started, and `--terminals=tmux` will start the terminals in [`tmux`][tmux] sessions. Alternatively, passing `--console` will connect the serial port directly to the current session, without needing to open further windows. + +The default terminal can also be configured by writing a [INI-style][INI] configuration file to `~/.config/runfvp.conf`: + +``` +[RunFVP] +Terminal=tmux +``` + +Arbitrary options can be passed directly to the FVP by specifying them after a double dash, for example this will list all of the FVP parameters: + +``` +$ runfvp fvp-base -- --list-params +``` + +## Configuring machines with `fvpboot` + +To configure a machine so that it can be ran inside `runfvp`, a number of variables need to be set in the machine configuration file (such as `meta-arm-bsp/conf/machine/fvp-base.conf`). + +Note that at present these variables are not stable and their behaviour may be changed in the future. + +### `FVP_EXE` + +The name of the FVP binary itself, for example `fvp-base` uses `FVP_Base_RevC-2xAEMvA`. + +### `FVP_PROVIDER` + +The name of the recipe that provides the FVP executable set in `FVP_EXE`, for example `fvp-base` uses `fvp-base-a-aem-native`. This *must* be a `-native` recipe as the binary will be executed on the build host. + +There are recipes for common FVPs in meta-arm already, and writing new recipes is trivial. For FVPs which are free to download `fvp-base-a-aem.bb` is a good example. Some FVPs must be downloaded separately as they need an account on Arm's website, `fvp-base-r-aem.bb` is a good example of those. + +If `FVP_PROVIDER` is not set then it is assumed that `FVP_EXE` is installed on the host already. + +### `FVP_CONFIG` + +Parameters passed to the FVP with the `--parameter`/`-C` option. These are expressed as variable flags so individual parameters can be altered easily. For example: + +``` +FVP_CONFIG[bp.flashloader0.fname] = "${DEPLOY_DIR_IMAGE}/fip-fvp.bin" +``` + +### `FVP_DATA` + +Specify raw data to load at the specified address, passed to the FVP with the `--data` option. This is a space-separated list of parameters in the format `[INST=]FILE@[MEMSPACE:]ADDRESS`. For example: + +``` +FVP_DATA = "cluster0.cpu0=${DEPLOY_DIR_IMAGE}/Image@0x80080000 \ + cluster0.cpu0=${DEPLOY_DIR_IMAGE}/fvp-base-revc.dtb@0x83000000" +``` + +### `FVP_APPLICATIONS` + +Applications to load on the cores, passed to the FVP with the `--application` option. These are expressed as variable flags with the flag name being the instance and flag value the filename, for example: + +``` +FVP_APPLICATIONS[cluster0] = "${DEPLOY_DIR_IMAGE}/linux-system.axf" +``` + +Note that symbols are not allowed in flag names, so if you need to use a wildcard in the instance then you'll need to use `FVP_EXTRA_ARGS` and `--application` directly. + +### `FVP_TERMINALS` + +Map hardware serial ports to abstract names. For example the `FVP_Base_RevC-2xAEMvA` FVP exposes four serial ports, `terminal_0` to `terminal_3`. Typically only `terminal_0` is used in the `fvp-base` machine so this can be named `"Console"` and the others `""`. When runfvp starts terminals it will only start named serial ports, so instead of opening four windows where only one is useful, it will only open one. + +For example: +``` +FVP_TERMINALS[bp.terminal_0] = "Console" +FVP_TERMINALS[bp.terminal_1] = "" +FVP_TERMINALS[bp.terminal_2] = "" +FVP_TERMINALS[bp.terminal_3] = "" +``` + +### `FVP_CONSOLES` + +This specifies what serial ports can be used in oeqa tests, along with an alias to be used in the test cases. Note that the values have to be the FVP identifier but without the board prefix, for example: +``` +FVP_CONSOLES[default] = "terminal_0" +FVP_CONSOLES[tf-a] = "s_terminal_0" +``` + +The 'default' console is also used when `--console` is passed to runfvp. + +### `FVP_EXTRA_ARGS` + +Arbitrary extra arguments that are passed directly to the FVP. For example: + +``` +FVP_EXTRA_ARGS = "--simlimit 60" +``` + +### `FVP_ENV_PASSTHROUGH` + +The FVP is launched with an isolated set of environment variables. Add the name of a Bitbake variable to this list to pass it through to the FVP environment. For example: + +``` +FVP_ENV_PASSTHROUGH = "ARMLMD_LICENSE_FILE FM_TRACE_PLUGINS" +``` + + +[AEM]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models +[FVP]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms +[tmux]: https://tmux.github.io/ +[INI]: https://docs.python.org/3/library/configparser.html diff --git a/meta-arm/documentation/trusted-services.md b/meta-arm/documentation/trusted-services.md new file mode 100644 index 000000000000..e3cee6b3c04b --- /dev/null +++ b/meta-arm/documentation/trusted-services.md @@ -0,0 +1,53 @@ +# The Trusted Services: framework for developing root-of-trust services + + meta-arm layer includes recipes for [Trusted Services][1] Secure Partitions and Normal World applications +in `meta-arm/recipes-security/trusted-services` + +## Secure Partitions recipes + +We define dedicated recipes for all supported Trusted Services (TS) Secure Partitions. +These recipes produce ELF and DTB files for SPs. +These files are automatically included into optee-os image accordingly to defined MACHINE_FEATURES. + +### How to include TS SPs + +To include TS SPs into optee-os image you need to add into MACHINE_FEATURES +features for each [Secure Partition][2] you would like to include: + +| Secure Partition | MACHINE_FEATURE | +| ----------------- | --------------- | +| Attestation | ts-attesation | +| Crypto | ts-crypto | +| Internal Storage | ts-its | +| Protected Storage | ts-storage | +| se-proxy | ts-se-proxy | +| smm-gateway | ts-smm-gateway | + +Other steps depend on your machine/platform definition: + +1. For communications between Secure and Normal Words Linux kernel option `CONFIG_ARM_FFA_TRANSPORT=y` +is required. If your platform doesn't include it already you can add `arm-ffa` into MACHINE_FEATURES. + +2. optee-os might require platform specific OP-TEE build parameters (for example what SEL the SPM Core is implemented at). +You can find examples in `meta-arm/recipes-security/optee/optee-os_%.bbappend` for qemuarm64-secureboot machine +and in `meta-arm-bsp/recipes-security/optee/optee-os-n1sdp.inc` and `meta-arm-bsp/recipes-security/optee/optee-os-corstone1000-common.inc` +for N1SDP and Corstone1000 platforms accordingly. + +3. trusted-firmware-a might require platform specific TF-A build parameters (SPD and SPMC details on the platform). +See `meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend` for qemuarm64-secureboot machine +and in `meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-n1sdp.inc` and +`meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc` for N1SDP and Corstone1000 platforms. + +## Normal World applications + + Optionally for testing purposes you can add `packagegroup-ts-tests` and `packagegroup-ts-tests-psa` package groups into your image. +They include [Trusted Services test and demo tools][3] + +## OEQA Trusted Services tests + + meta-arm also includes Trusted Service OEQA tests which can be used for automated testing. +See `ci/trusted-services.yml` for an example how to include them into an image. + +[1] https://trusted-services.readthedocs.io/en/integration/overview/introduction.html +[2] https://trusted-services.readthedocs.io/en/integration/developer/deployments/secure-partitions.html +[3] https://trusted-services.readthedocs.io/en/integration/developer/deployments/test-executables.html diff --git a/meta-arm/kas/corstone1000-base.yml b/meta-arm/kas/corstone1000-base.yml new file mode 100644 index 000000000000..5fe7f4da58e5 --- /dev/null +++ b/meta-arm/kas/corstone1000-base.yml @@ -0,0 +1,42 @@ +header: + version: 11 + +distro: poky-tiny + +defaults: + repos: + refspec: langdale + +repos: + meta-arm: + layers: + meta-arm: + meta-arm-bsp: + meta-arm-toolchain: + + poky: + url: https://git.yoctoproject.org/git/poky + layers: + meta: + meta-poky: + meta-yocto-bsp: + + meta-openembedded: + url: https://git.openembedded.org/meta-openembedded + layers: + meta-oe: + meta-python: + +local_conf_header: + base: | + CONF_VERSION = "2" + PACKAGE_CLASSES = "package_ipk" + LICENSE_FLAGS_ACCEPTED += "armcompiler" + BB_NUMBER_THREADS ?= "16" + PARALLEL_MAKE ?= "-j16" + PACKAGECONFIG:append:pn-perf = " coresight" + +machine: unset + +target: + - corstone1000-image diff --git a/meta-arm/kas/corstone1000-fvp.yml b/meta-arm/kas/corstone1000-fvp.yml new file mode 100644 index 000000000000..d0d10a738fd2 --- /dev/null +++ b/meta-arm/kas/corstone1000-fvp.yml @@ -0,0 +1,16 @@ +header: + version: 11 + includes: + - kas/corstone1000-base.yml + +machine: corstone1000-fvp + +local_conf_header: + fvp-config: | + # Remove Dropbear SSH as it will not fit into the corstone1000 image. + IMAGE_FEATURES:remove = " ssh-server-dropbear" + INHERIT = " ${@bb.utils.contains('BUILD_ARCH', 'x86_64', 'fvpboot', '', d)}" + LICENSE_FLAGS_ACCEPTED:append = " Arm-FVP-EULA" + +target: + - corstone1000-image diff --git a/meta-arm/kas/corstone1000-mps3.yml b/meta-arm/kas/corstone1000-mps3.yml new file mode 100644 index 000000000000..53be4382fe54 --- /dev/null +++ b/meta-arm/kas/corstone1000-mps3.yml @@ -0,0 +1,6 @@ +header: + version: 11 + includes: + - kas/corstone1000-base.yml + +machine: corstone1000-mps3 diff --git a/meta-arm/kas/corstone500.yml b/meta-arm/kas/corstone500.yml new file mode 100644 index 000000000000..a454a469b7d2 --- /dev/null +++ b/meta-arm/kas/corstone500.yml @@ -0,0 +1,47 @@ +header: + version: 11 + +distro: poky-tiny + +defaults: + repos: + refspec: master + +repos: + meta-arm: + layers: + meta-arm: + meta-arm-bsp: + meta-arm-toolchain: + + poky: + url: https://git.yoctoproject.org/git/poky + refspec: master + layers: + meta: + meta-poky: + meta-yocto-bsp: + + meta-openembedded: + url: https://git.openembedded.org/meta-openembedded + refspec: master + layers: + meta-oe: + meta-python: + +local_conf_header: + base: | + CONF_VERSION = "2" + PACKAGE_CLASSES = "package_ipk" + LICENSE_FLAGS_ACCEPTED += "armcompiler" + BB_NUMBER_THREADS ?= "16" + PARALLEL_MAKE ?= "-j16" + PACKAGECONFIG:append:pn-perf = " coresight" + fvp-config: | + IMAGE_CLASSES:append = " ${@bb.utils.contains('BUILD_ARCH', 'x86_64', 'fvpboot', '', d)}" + LICENSE_FLAGS_ACCEPTED:append = " Arm-FVP-EULA" + +machine: corstone500 + +target: + - core-image-minimal diff --git a/meta-arm/kas/fvp-baser-aemv8r64-bsp.yml b/meta-arm/kas/fvp-baser-aemv8r64-bsp.yml new file mode 100644 index 000000000000..dd175d03da49 --- /dev/null +++ b/meta-arm/kas/fvp-baser-aemv8r64-bsp.yml @@ -0,0 +1,41 @@ +header: + version: 9 + +distro: poky +machine: fvp-baser-aemv8r64 + +defaults: + repos: + refspec: master + +repos: + meta-arm: + url: https://git.yoctoproject.org/git/meta-arm + path: layers/meta-arm + layers: + meta-arm: + meta-arm-bsp: + meta-arm-toolchain: + + poky: + url: https://git.yoctoproject.org/git/poky + path: layers/poky + layers: + meta: + meta-poky: + +env: + FVP_BASE_R_ARM_EULA_ACCEPT: "False" + +local_conf_header: + base: | + CONF_VERSION = "2" + PACKAGE_CLASSES = "package_ipk" + PACKAGECONFIG:remove:pn-qemu-system-native = "gtk+ sdl" + EXTRA_IMAGE_FEATURES:append = " debug-tweaks ssh-server-openssh" + CORE_IMAGE_EXTRA_INSTALL:append = " ssh-pregen-hostkeys" + LICENSE_FLAGS_ACCEPTED:append = " ${@oe.utils.vartrue('FVP_BASE_R_ARM_EULA_ACCEPT', 'Arm-FVP-EULA', '', d)}" + IMAGE_CLASSES:append = " testimage" + +target: + - core-image-minimal diff --git a/meta-arm/kas/fvp-baser-aemv8r64-rt-bsp.yml b/meta-arm/kas/fvp-baser-aemv8r64-rt-bsp.yml new file mode 100644 index 000000000000..19ee747f92a8 --- /dev/null +++ b/meta-arm/kas/fvp-baser-aemv8r64-rt-bsp.yml @@ -0,0 +1,8 @@ +header: + version: 9 + includes: + - kas/fvp-baser-aemv8r64-bsp.yml + +local_conf_header: + base-rt: | + PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-rt" diff --git a/meta-arm/kas/tftf.yml b/meta-arm/kas/tftf.yml new file mode 100644 index 000000000000..6e42d9c68862 --- /dev/null +++ b/meta-arm/kas/tftf.yml @@ -0,0 +1,7 @@ +header: + version: 9 + +local_conf_header: + tftf: | + TFA_UBOOT = "0" + TFTF_TESTS = "1" diff --git a/meta-arm/meta-arm-bsp/README.md b/meta-arm/meta-arm-bsp/README.md new file mode 100644 index 000000000000..490ddca97edb --- /dev/null +++ b/meta-arm/meta-arm-bsp/README.md @@ -0,0 +1 @@ +See ../README.md diff --git a/meta-arm/meta-arm-bsp/classes/wic_nopt.bbclass b/meta-arm/meta-arm-bsp/classes/wic_nopt.bbclass new file mode 100644 index 000000000000..322be498867d --- /dev/null +++ b/meta-arm/meta-arm-bsp/classes/wic_nopt.bbclass @@ -0,0 +1,9 @@ +# This class removes the empty partition table header +# in the WIC file when --no-table WKS option is used + +IMAGE_TYPES += "wic.nopt" + +CONVERSIONTYPES += "nopt" + +# 1024 bytes are skipped which corresponds to the size of the partition table header to remove +CONVERSION_CMD:nopt = "tail -c +1025 ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type} > ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type}.nopt" diff --git a/meta-arm/meta-arm-bsp/conf/layer.conf b/meta-arm/meta-arm-bsp/conf/layer.conf new file mode 100644 index 000000000000..e192a83ddf72 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/layer.conf @@ -0,0 +1,21 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "meta-arm-bsp" +BBFILE_PATTERN_meta-arm-bsp = "^${LAYERDIR}/" +BBFILE_PRIORITY_meta-arm-bsp = "5" + +LAYERSERIES_COMPAT_meta-arm-bsp = "mickledore" + +LAYERDEPENDS_meta-arm-bsp = "core meta-arm" +# This won't be used by layerindex-fetch, but works everywhere else +LAYERDEPENDS_meta-arm-bsp:append:corstone1000 = " meta-python openembedded-layer" +LAYERDEPENDS_meta-arm-bsp:append:musca-b1 = " meta-python" +LAYERDEPENDS_meta-arm-bsp:append:musca-s1 = " meta-python" + +# Additional license directories. +LICENSE_PATH += "${LAYERDIR}/custom-licenses" diff --git a/meta-arm/meta-arm-bsp/conf/machine/corstone1000-fvp.conf b/meta-arm/meta-arm-bsp/conf/machine/corstone1000-fvp.conf new file mode 100644 index 000000000000..2a72f7ff23ff --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/corstone1000-fvp.conf @@ -0,0 +1,50 @@ +#@TYPE: Machine +#@NAME: corstone1000-fvp machine +#@DESCRIPTION: Machine configuration for Corstone1000 64-bit FVP +require conf/machine/include/corstone1000.inc + +TFA_TARGET_PLATFORM = "fvp" + +TFM_PLATFORM_IS_FVP = "TRUE" + +# testimage config +TEST_TARGET = "OEFVPSerialTarget" +TEST_SUITES = "linuxboot" + +# FVP Config +FVP_PROVIDER ?= "fvp-corstone1000-native" +FVP_EXE ?= "FVP_Corstone-1000" +FVP_CONSOLE ?= "host_terminal_0" + +# FVP Parameters +FVP_CONFIG[se.trustedBootROMloader.fname] ?= "${DEPLOY_DIR_IMAGE}/bl1.bin" +FVP_CONFIG[board.xnvm_size] ?= "64" +FVP_CONFIG[se.trustedSRAM_config] ?= "6" +FVP_CONFIG[se.BootROM_config] ?= "3" +FVP_CONFIG[board.hostbridge.interfaceName] ?= "tap0" +FVP_CONFIG[board.smsc_91c111.enabled] ?= "1" +FVP_CONFIG[board.hostbridge.userNetworking] ?= "true" +FVP_CONFIG[board.hostbridge.userNetPorts] ?= "5555=5555,8080=80,8022=22" +FVP_CONFIG[board.se_flash_size] ?= "8192" +FVP_CONFIG[diagnostics] ?= "4" +FVP_CONFIG[disable_visualisation] ?= "true" +FVP_CONFIG[se.nvm.update_raw_image] ?= "0" + +# Boot image +FVP_DATA ?= "board.flash0=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.wic.nopt@0x68100000" + +# External system (cortex-M3) +FVP_CONFIG[extsys_harness0.extsys_flashloader.fname] ?= "${DEPLOY_DIR_IMAGE}/es_flashfw.bin" + +# FVP Terminals +FVP_TERMINALS[host.host_terminal_0] ?= "Normal World Console" +FVP_TERMINALS[host.host_terminal_1] ?= "Secure World Console" +FVP_TERMINALS[se.secenc_terminal] ?= "Secure Enclave Console" +FVP_TERMINALS[extsys0.extsys_terminal] ?= "Cortex M3" + +# MMC card configuration +FVP_CONFIG[board.msd_mmc.card_type] ?= "SDHC" +FVP_CONFIG[board.msd_mmc.p_fast_access] ?= "0" +FVP_CONFIG[board.msd_mmc.diagnostics] ?= "2" +FVP_CONFIG[board.msd_mmc.p_max_block_count] ?= "0xFFFF" +FVP_CONFIG[board.msd_config.pl180_fifo_depth] ?= "16" diff --git a/meta-arm/meta-arm-bsp/conf/machine/corstone1000-mps3.conf b/meta-arm/meta-arm-bsp/conf/machine/corstone1000-mps3.conf new file mode 100644 index 000000000000..88f3d9dd262a --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/corstone1000-mps3.conf @@ -0,0 +1,9 @@ +#@TYPE: Machine +#@NAME: corstone1000-mps3 machine +#@DESCRIPTION: Machine configuration for Corstone1000 64-bit MPS3 FPGA board + +require conf/machine/include/corstone1000.inc + +TFA_TARGET_PLATFORM = "fpga" + +PLATFORM_IS_FVP = "FALSE" diff --git a/meta-arm/meta-arm-bsp/conf/machine/corstone500.conf b/meta-arm/meta-arm-bsp/conf/machine/corstone500.conf new file mode 100644 index 000000000000..dfc850db7804 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/corstone500.conf @@ -0,0 +1,45 @@ +#@TYPE: Machine +#@NAME: Corstone-500 machine +#@DESCRIPTION: Machine configuration for the Corstone-500 platform + +require conf/machine/include/arm/armv7a/tune-cortexa5.inc + +# Corstone-500 is built against poky-tiny distro. +# poky-tiny sets PREFERRED_PROVIDER_virtual/kernel to linux-yocto-tiny. +# Since distro config is evaluated after the machine config, we need to +# use the strongest override possible (forcevariable) so the +# PREFERRED_PROVIDER_virtual/kernel specified in the machine config will +# apply. +# +PREFERRED_PROVIDER_virtual/kernel:forcevariable = "linux-yocto" +PREFERRED_VERSION_linux-yocto ?= "5.19%" + +EXTRA_IMAGEDEPENDS += "trusted-firmware-a u-boot" + +IMAGE_CLASSES += "wic_nopt" +IMAGE_FEATURES += "debug-tweaks" +IMAGE_FSTYPES:forcevariable = "cpio.gz squashfs wic wic.nopt" + +SERIAL_CONSOLES = "115200;ttyAMA0" + +# Corstone-500 u-boot configuration +UBOOT_MACHINE = "corstone500_defconfig" +UBOOT_IMAGE_ENTRYPOINT = "0x84000000" +UBOOT_IMAGE_LOADADDRESS = "0x84000000" +PREFERRED_VERSION_u-boot ?= "2022.10" + +# making sure EXTRA_IMAGEDEPENDS will be used while creating the image +WKS_FILE_DEPENDS:append = " ${EXTRA_IMAGEDEPENDS}" + +WKS_FILE ?= "core-image-minimal.corstone500.wks" + +TEST_TARGET = "OEFVPSerialTarget" +TEST_SUITES = "linuxboot" + +FVP_PROVIDER ?= "fvp-corstone500-native" +FVP_EXE ?= "FVP_Corstone-500" +FVP_CONFIG[board.flashloader0.fname] ?= "${DEPLOY_DIR_IMAGE}/bl1.bin" +FVP_DATA ?= "css.cluster.cpu0=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.wic.nopt@0x80000000" +FVP_CONSOLE ?= "terminal_0" +FVP_TERMINALS[css.terminal_0] ?= "console" +FVP_TERMINALS[css.terminal_1] ?= "" diff --git a/meta-arm/meta-arm-bsp/conf/machine/fvp-base-arm32.conf b/meta-arm/meta-arm-bsp/conf/machine/fvp-base-arm32.conf new file mode 100644 index 000000000000..d3452b74ae12 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/fvp-base-arm32.conf @@ -0,0 +1,23 @@ +# Configuration for Armv7-A Base Platform FVP + +#@TYPE: Machine +#@NAME: Armv7-A Base Platform FVP machine +#@DESCRIPTION: Machine configuration for Armv7-A Base Platform FVP model + +require conf/machine/include/fvp-common.inc +require conf/machine/include/arm/arch-armv7a.inc + +# FVP u-boot configuration +PREFERRED_VERSION_u-boot ?= "2022.04" +UBOOT_MACHINE = "vexpress_aemv8a_aarch32_defconfig" + +KERNEL_IMAGETYPE = "zImage" + +FVP_CONFIG[cluster0.cpu0.CONFIG64] = "0" +FVP_CONFIG[cluster0.cpu1.CONFIG64] = "0" +FVP_CONFIG[cluster0.cpu2.CONFIG64] = "0" +FVP_CONFIG[cluster0.cpu3.CONFIG64] = "0" +FVP_CONFIG[cluster1.cpu0.CONFIG64] = "0" +FVP_CONFIG[cluster1.cpu1.CONFIG64] = "0" +FVP_CONFIG[cluster1.cpu2.CONFIG64] = "0" +FVP_CONFIG[cluster1.cpu3.CONFIG64] = "0" diff --git a/meta-arm/meta-arm-bsp/conf/machine/fvp-base.conf b/meta-arm/meta-arm-bsp/conf/machine/fvp-base.conf new file mode 100644 index 000000000000..1ba070824e18 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/fvp-base.conf @@ -0,0 +1,19 @@ +# Configuration for Armv8-A Base Platform FVP + +#@TYPE: Machine +#@NAME: Armv8-A Base Platform FVP machine +#@DESCRIPTION: Machine configuration for Armv8-A Base Platform FVP model + +require conf/machine/include/fvp-common.inc +require conf/machine/include/arm/arch-armv8a.inc + +TUNE_FEATURES = "aarch64" + +PREFERRED_VERSION_u-boot ?= "2022.04" + +# FVP u-boot configuration +UBOOT_MACHINE = "vexpress_aemv8a_semi_defconfig" + +KERNEL_IMAGETYPE = "Image" + +FVP_CONFIG[bp.virtio_rng.enabled] ?= "1" diff --git a/meta-arm/meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf b/meta-arm/meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf new file mode 100644 index 000000000000..0c2ea1224f3c --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf @@ -0,0 +1,63 @@ +# Configuration for Fixed Virtual Platform BaseR AEMv8r64 Machine + +#@TYPE: Machine +#@NAME: FVP BaseR AEMv8r64 Machine +#@DESCRIPTION: Machine configuration for FVP BaseR AEMv8r64 + +require conf/machine/include/arm/armv8r/arch-armv8r64.inc + +EXTRA_IMAGEDEPENDS += "boot-wrapper-aarch64" + +PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" +PREFERRED_VERSION_u-boot ?= "2022.10" + +KERNEL_IMAGETYPE = "Image" +KERNEL_DEVICETREE = "arm/fvp-baser-aemv8r64.dtb" + +UBOOT_MACHINE ?= "vexpress_aemv8r_defconfig" + +SERIAL_CONSOLES = "115200;ttyAMA0" + +IMAGE_CLASSES:append = " fvpboot" +IMAGE_FSTYPES += "wic" +WKS_FILE ?= "efi-disk.wks.in" +EFI_PROVIDER ?= "grub-efi" +MACHINE_FEATURES:append = " efi" + +# As this is a virtual target that will not be used in the real world there is +# no need for real SSH keys. +MACHINE_EXTRA_RRECOMMENDS += "ssh-pregen-hostkeys" + +# testimage configuration +TEST_TARGET = "OEFVPSerialTarget" +TEST_SUITES = "linuxboot" +TEST_TARGET_IP ?= "127.0.0.1:8022" +TEST_SERVER_IP ?= "127.0.1.1" + +FVP_EXTRA_ARGS = "-a cluster0*=${DEPLOY_DIR_IMAGE}/linux-system.axf" +FVP_PROVIDER ?= "fvp-base-r-aem-native" +FVP_EXE ?= "FVP_BaseR_AEMv8R" +FVP_CONSOLE ?= "terminal_0" + +# FVP parameters +FVP_CONFIG[bp.exclusive_monitor.monitor_access_level] ?= "2" +FVP_CONFIG[bp.refcounter.non_arch_start_at_default] ?= "1" +FVP_CONFIG[bp.refcounter.use_real_time] ?= "1" +FVP_CONFIG[bp.ve_sysregs.exit_on_shutdown] ?= "1" +FVP_CONFIG[bp.virtio_net.enabled] ?= "1" +FVP_CONFIG[bp.virtio_net.hostbridge.userNetPorts] ?= "8022=22" +FVP_CONFIG[bp.virtio_net.hostbridge.userNetworking] ?= "1" +FVP_CONFIG[bp.virtio_net.secure_accesses] = "1" +FVP_CONFIG[bp.virtio_rng.enabled] ?= "1" +FVP_CONFIG[bp.virtio_rng.secure_accesses] = "1" +FVP_CONFIG[bp.virtioblockdevice.image_path] ?= "${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.wic" +FVP_CONFIG[bp.virtioblockdevice.secure_accesses] = "1" +FVP_CONFIG[cache_state_modelled] ?= "0" +FVP_CONFIG[cci400.force_on_from_start] = "1" +FVP_CONFIG[cluster0.gicv3.cpuintf-mmap-access-level] ?= "2" +FVP_CONFIG[cluster0.gicv3.extended-interrupt-range-support] ?= "1" +FVP_CONFIG[cluster0.gicv3.SRE-EL2-enable-RAO] ?= "1" +FVP_CONFIG[cluster0.gicv3.SRE-enable-action-on-mmap] ?= "2" +FVP_CONFIG[cluster0.has_aarch64] ?= "1" +FVP_CONFIG[gic_distributor.GICD_CTLR-DS-1-means-secure-only] ?= "1" +FVP_CONFIG[gic_distributor.has-two-security-states] ?= "0" diff --git a/meta-arm/meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc b/meta-arm/meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc new file mode 100644 index 000000000000..5db12e2c5d59 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc @@ -0,0 +1,10 @@ +require conf/machine/include/arm/arch-armv8r.inc + +TUNE_FEATURES:tune-armv8r =+ "aarch64" +PACKAGE_EXTRA_ARCHS:tune-armv8r =+ "aarch64" +BASE_LIB:tune-armv8r = "lib64" +BASE_LIB:tune-armv8r-crc = "lib64" +BASE_LIB:tune-armv8r-crypto = "lib64" +BASE_LIB:tune-armv8r-simd = "lib64" +BASE_LIB:tune-armv8r-crc-simd = "lib64" +BASE_LIB:tune-armv8r-crc-crypto-simd = "lib64" diff --git a/meta-arm/meta-arm-bsp/conf/machine/include/corstone1000.inc b/meta-arm/meta-arm-bsp/conf/machine/include/corstone1000.inc new file mode 100644 index 000000000000..d5d6418d9c93 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/include/corstone1000.inc @@ -0,0 +1,75 @@ +require conf/machine/include/arm/armv8a/tune-cortexa35.inc + +MACHINEOVERRIDES =. "corstone1000:" + +# TF-A +TFA_PLATFORM = "corstone1000" +EXTRA_IMAGEDEPENDS += "trusted-firmware-a" + +TFA_BL2_BINARY = "bl2-corstone1000.bin" +TFA_FIP_BINARY = "fip-corstone1000.bin" + +# TF-M +EXTRA_IMAGEDEPENDS += "virtual/trusted-firmware-m" + +# TF-M settings for signing host images +TFA_BL2_RE_IMAGE_LOAD_ADDRESS = "0x62353000" +TFA_BL2_RE_SIGN_BIN_SIZE = "0x2d000" +TFA_FIP_RE_IMAGE_LOAD_ADDRESS = "0x68130000" +TFA_FIP_RE_SIGN_BIN_SIZE = "0x00200000" +RE_LAYOUT_WRAPPER_VERSION = "0.0.7" +TFM_SIGN_PRIVATE_KEY = "${libdir}/tfm-scripts/root-RSA-3072_1.pem" +RE_IMAGE_OFFSET = "0x1000" + +# u-boot +PREFERRED_VERSION_u-boot ?= "2022.10" +EXTRA_IMAGEDEPENDS += "u-boot" + +UBOOT_CONFIG ??= "EFI" +UBOOT_CONFIG[EFI] = "corstone1000_defconfig" +UBOOT_ENTRYPOINT = "0x80000000" +UBOOT_LOADADDRESS = "0x80000000" +UBOOT_BOOTARGS = "earlycon=pl011,0x1a510000 console=ttyAMA0 loglevel=9" +UBOOT_ARCH = "arm" +UBOOT_EXTLINUX = "0" + +#optee +PREFERRED_VERSION_optee-os ?= "3.18.%" +PREFERRED_VERSION_optee-client ?= "3.18.%" +EXTRA_IMAGEDEPENDS += "optee-os" +OPTEE_ARCH = "arm64" +OPTEE_BINARY = "tee-pager_v2.bin" + +# Include smm-gateway and se-proxy SPs into optee-os binary +MACHINE_FEATURES += "ts-smm-gateway ts-se-proxy" +TS_PLATFORM = "arm/corstone1000" + +# External System(Cortex-M3) +EXTRA_IMAGEDEPENDS += "external-system" + +# Linux kernel +PREFERRED_PROVIDER_virtual/kernel:forcevariable = "linux-yocto" +PREFERRED_VERSION_linux-yocto = "5.19%" +KERNEL_IMAGETYPE = "Image.gz" + +INITRAMFS_IMAGE_BUNDLE ?= "1" + +#telling the build system which image is responsible of the generation of the initramfs rootfs +INITRAMFS_IMAGE = "corstone1000-initramfs-image" + +# add FF-A support in the kernel +MACHINE_FEATURES += "arm-ffa" + +# prevent the kernel image from being included in the intramfs rootfs +PACKAGE_EXCLUDE = "kernel-image-*" + +# enable this feature for kernel debugging +# MACHINE_FEATURES += "corstone1000_kernel_debug" + +# login terminal serial port settings +SERIAL_CONSOLES ?= "115200;ttyAMA0" + +# making sure EXTRA_IMAGEDEPENDS will be used while creating the image +WKS_FILE_DEPENDS:append = " ${EXTRA_IMAGEDEPENDS}" + +WKS_FILE ?= "corstone1000-image.corstone1000.wks" diff --git a/meta-arm/meta-arm-bsp/conf/machine/include/fvp-common.inc b/meta-arm/meta-arm-bsp/conf/machine/include/fvp-common.inc new file mode 100644 index 000000000000..b6fc74da68fd --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/include/fvp-common.inc @@ -0,0 +1,48 @@ +# FVP common parameters + +# +# Capturing FVP common configurations (Armv8-A Base Platform FVP, +# Armv8-A Foundation Platform and Armv7-A Base Platform FVP). +# + +MACHINE_FEATURES = "optee" + +IMAGE_FSTYPES += "wic" +WKS_FILE ?= "fvp-base.wks" + +SERIAL_CONSOLES = "115200;ttyAMA0" + +PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" + +KERNEL_DEVICETREE = "arm/fvp-base-revc.dtb" + +EXTRA_IMAGEDEPENDS += "trusted-firmware-a u-boot" + +# As this is a virtual target that will not be used in the real world there is +# no need for real SSH keys. +MACHINE_EXTRA_RRECOMMENDS += "ssh-pregen-hostkeys" + +TEST_TARGET = "OEFVPTarget" +TEST_TARGET_IP = "127.0.0.1:8022" + +FVP_PROVIDER ?= "fvp-base-a-aem-native" +FVP_EXE ?= "FVP_Base_RevC-2xAEMvA" +FVP_CONFIG[bp.ve_sysregs.exit_on_shutdown] ?= "1" +FVP_CONFIG[bp.virtio_net.enabled] ?= "1" +FVP_CONFIG[bp.virtio_net.hostbridge.userNetworking] ?= "1" +# Tell testimage to connect to localhost:8022, and forward that to SSH in the FVP. +FVP_CONFIG[bp.virtio_net.hostbridge.userNetPorts] = "8022=22" +FVP_CONFIG[cache_state_modelled] ?= "0" +FVP_CONFIG[bp.secureflashloader.fname] ?= "${DEPLOY_DIR_IMAGE}/bl1-fvp.bin" +FVP_CONFIG[bp.flashloader0.fname] ?= "${DEPLOY_DIR_IMAGE}/fip-fvp.bin" +FVP_CONFIG[bp.virtioblockdevice.image_path] ?= "${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.wic" +# Set the baseline to ARMv8.4, as the default is 8.0. +FVP_CONFIG[cluster0.has_arm_v8-4] = "1" +FVP_CONFIG[cluster1.has_arm_v8-4] = "1" +FVP_CONSOLE ?= "terminal_0" +FVP_DATA ?= "cluster0.cpu0=${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}@0x80080000 \ + cluster0.cpu0=${DEPLOY_DIR_IMAGE}/fvp-base-revc.dtb@0x8fc00000" +FVP_TERMINALS[bp.terminal_0] ?= "Console" +FVP_TERMINALS[bp.terminal_1] ?= "" +FVP_TERMINALS[bp.terminal_2] ?= "" +FVP_TERMINALS[bp.terminal_3] ?= "" diff --git a/meta-arm/meta-arm-bsp/conf/machine/include/tc.inc b/meta-arm/meta-arm-bsp/conf/machine/include/tc.inc new file mode 100644 index 000000000000..f51497decdab --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/include/tc.inc @@ -0,0 +1,40 @@ +TUNE_FEATURES = "aarch64" + +require conf/machine/include/arm/arch-armv8a.inc + +MACHINEOVERRIDES =. "tc:" + +# Das U-boot +UBOOT_MACHINE ?= "total_compute_defconfig" +PREFERRED_VERSION_u-boot ?= "2022.04" +UBOOT_RD_LOADADDRESS = "0x88000000" +UBOOT_RD_ENTRYPOINT = "0x88000000" +UBOOT_LOADADDRESS = "0x80080000" +UBOOT_ENTRYPOINT = "0x80080000" +# Below options will generate a key to sign the kernel Image and INITRAMFS_IMAGE +# according to the default parameters of kernel-fitimage.bbclass. If the user +# would prefer to use their own keys, disable the key generation using the +# FIT_GENERATE_KEYS parameter and specify the location of the keys using the +# below paramters. +UBOOT_SIGN_ENABLE = "1" +UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb" +UBOOT_SIGN_KEYNAME = "dev_key" +UBOOT_SIGN_KEYDIR = "${DEPLOY_DIR_IMAGE}/keys" +FIT_GENERATE_KEYS = "1" + +PREFERRED_PROVIDER_virtual/kernel ?= "linux-arm64-ack" + +# OP-TEE +PREFERRED_VERSION_optee-os ?= "3.18%" +PREFERRED_VERSION_optee-client ?= "3.18%" +PREFERRED_VERSION_optee-test ?= "3.18%" + +# Cannot use the default zImage on arm64 +KERNEL_IMAGETYPE = "Image" +KERNEL_IMAGETYPES += "fitImage" +KERNEL_CLASSES = " kernel-fitimage " + +IMAGE_FSTYPES += "cpio.gz" +INITRAMFS_IMAGE ?= "core-image-minimal" + +SERIAL_CONSOLES = "115200;ttyAMA0" diff --git a/meta-arm/meta-arm-bsp/conf/machine/juno.conf b/meta-arm/meta-arm-bsp/conf/machine/juno.conf new file mode 100644 index 000000000000..43d6b3e3310d --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/juno.conf @@ -0,0 +1,29 @@ +# Configuration for juno development board + +#@TYPE: Machine +#@NAME: Juno machine +#@DESCRIPTION: Machine configuration for Juno + +TUNE_FEATURES = "aarch64" + +require conf/machine/include/arm/arch-armv8a.inc + +MACHINE_FEATURES = "usbhost usbgadget alsa screen wifi bluetooth optee pci" + +KERNEL_IMAGETYPE = "Image.gz" +KERNEL_DEVICETREE = "arm/juno.dtb arm/juno-r1.dtb arm/juno-r2.dtb" + +IMAGE_FSTYPES += "tar.bz2 ext4 cpio.gz" + +SERIAL_CONSOLES = "115200;ttyAMA0" + +PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" +PREFERRED_PROVIDER_virtual/bootloader ?= "u-boot" + +EXTRA_IMAGEDEPENDS += "trusted-firmware-a virtual/bootloader firmware-image-juno" + +# Juno u-boot configuration +UBOOT_MACHINE = "vexpress_aemv8a_juno_defconfig" + +INITRAMFS_IMAGE_BUNDLE ?= "1" +INITRAMFS_IMAGE = "core-image-minimal" diff --git a/meta-arm/meta-arm-bsp/conf/machine/musca-b1.conf b/meta-arm/meta-arm-bsp/conf/machine/musca-b1.conf new file mode 100644 index 000000000000..4e9cf829429d --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/musca-b1.conf @@ -0,0 +1,23 @@ +# Configuration for Musca-B1 development board + +#@TYPE: Machine +#@NAME: Musca-B1 machine +#@DESCRIPTION: Machine configuration for Musca-B1 + +DEFAULTTUNE ?= "armv8m-main" +require conf/machine/include/arm/armv8-m/tune-cortexm33.inc + +# GLIBC will not work with Cortex-M. +TCLIBC = "newlib" + +# For runqemu +IMAGE_FSTYPES += "ext4" +IMAGE_CLASSES += "qemuboot" +QB_SYSTEM_NAME = "qemu-system-arm" +QB_MACHINE = "-machine musca-b1" +QB_CPU = "-cpu cortex-m33" +QB_GRAPHICS = "-nographic -vga none" +QB_MEM = "512k" +QB_RNG = "" + +TFM_PLATFORM = "arm/musca_b1" diff --git a/meta-arm/meta-arm-bsp/conf/machine/musca-s1.conf b/meta-arm/meta-arm-bsp/conf/machine/musca-s1.conf new file mode 100644 index 000000000000..3d3bc4de94e6 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/musca-s1.conf @@ -0,0 +1,22 @@ +# Configuration for Musca-S1 development board + +#@TYPE: Machine +#@NAME: Musca-S1 machine +#@DESCRIPTION: Machine configuration for Musca-S1 + +require conf/machine/include/arm/armv8-m/tune-cortexm33.inc + +# GLIBC will not work with Cortex-M. +TCLIBC = "newlib" + +# For runqemu +IMAGE_FSTYPES += "ext4" +IMAGE_CLASSES += "qemuboot" +QB_SYSTEM_NAME = "qemu-system-arm" +QB_MACHINE = "-machine musca-s1" +QB_CPU = "-cpu cortex-m33" +QB_GRAPHICS = "-nographic -vga none" +QB_MEM = "512k" +QB_RNG = "" + +TFM_PLATFORM = "arm/musca_s1" diff --git a/meta-arm/meta-arm-bsp/conf/machine/n1sdp.conf b/meta-arm/meta-arm-bsp/conf/machine/n1sdp.conf new file mode 100644 index 000000000000..581e6af0bba8 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/n1sdp.conf @@ -0,0 +1,41 @@ +# Configuration for Arm N1SDP development board + +#@TYPE: Machine +#@NAME: N1SDP machine +#@DESCRIPTION: Machine configuration for N1SDP + +require conf/machine/include/arm/armv8-2a/tune-neoversen1.inc + +KERNEL_IMAGETYPE = "Image" + +IMAGE_FSTYPES += "wic wic.gz wic.bmap tar.bz2 ext4" + +SERIAL_CONSOLES = "115200;ttyAMA0" + +# Set default WKS +WKS_FILE ?= "n1sdp-efidisk.wks" +IMAGE_EFI_BOOT_FILES ?= "n1sdp-multi-chip.dtb n1sdp-single-chip.dtb" +WKS_FILE_DEPENDS:append = " ${EXTRA_IMAGEDEPENDS}" + +# Use kernel provided by yocto +PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" +PREFERRED_VERSION_linux-yocto ?= "5.19%" + +# RTL8168E Gigabit Ethernet Controller is attached to the PCIe interface +MACHINE_ESSENTIAL_EXTRA_RDEPENDS += "linux-firmware-rtl8168" + +EXTRA_IMAGEDEPENDS += "trusted-firmware-a" +EXTRA_IMAGEDEPENDS += "virtual/control-processor-firmware" + +#UEFI EDK2 firmware +EXTRA_IMAGEDEPENDS += "edk2-firmware" + +#optee +PREFERRED_VERSION_optee-os ?= "3.18.%" + +#grub-efi +EFI_PROVIDER ?= "grub-efi" +MACHINE_FEATURES += "efi" + +# SD-Card firmware +EXTRA_IMAGEDEPENDS += "sdcard-image-n1sdp" diff --git a/meta-arm/meta-arm-bsp/conf/machine/sgi575.conf b/meta-arm/meta-arm-bsp/conf/machine/sgi575.conf new file mode 100644 index 000000000000..3c2c94b6dcbf --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/sgi575.conf @@ -0,0 +1,24 @@ +# Configuration for Arm SGI575 development board + +#@TYPE: Machine +#@NAME: SGI575 +#@DESCRIPTION: Machine configuration for SGI575 + +require conf/machine/include/arm/armv8-2a/tune-cortexa75.inc + +EXTRA_IMAGEDEPENDS += "virtual/control-processor-firmware" + +EXTRA_IMAGEDEPENDS += "trusted-firmware-a" + +KERNEL_IMAGETYPE ?= "Image" +PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" +SERIAL_CONSOLES = "115200;ttyAMA0" + +#grub-efi +EFI_PROVIDER ?= "grub-efi" +MACHINE_FEATURES += "efi" + +IMAGE_FSTYPES += "cpio.gz wic" + +WKS_FILE ?= "sgi575-efidisk.wks" +WKS_FILE_DEPENDS:append = " ${EXTRA_IMAGEDEPENDS}" diff --git a/meta-arm/meta-arm-bsp/conf/machine/tc1.conf b/meta-arm/meta-arm-bsp/conf/machine/tc1.conf new file mode 100644 index 000000000000..42c5d8d5adf8 --- /dev/null +++ b/meta-arm/meta-arm-bsp/conf/machine/tc1.conf @@ -0,0 +1,7 @@ +# Configuration for TC1 + +#@TYPE: Machine +#@NAME: TC1 +#@DESCRIPTION: Machine configuration for TC1 + +require conf/machine/include/tc.inc diff --git a/meta-arm/meta-arm-bsp/custom-licenses/STM-SLA0044-Rev5 b/meta-arm/meta-arm-bsp/custom-licenses/STM-SLA0044-Rev5 new file mode 100644 index 000000000000..edb5cd5512ae --- /dev/null +++ b/meta-arm/meta-arm-bsp/custom-licenses/STM-SLA0044-Rev5 @@ -0,0 +1,18 @@ +SLA0044 Rev5/February 2018 + +BY INSTALLING COPYING, DOWNLOADING, ACCESSING OR OTHERWISE USING THIS SOFTWARE OR ANY PART THEREOF (AND THE RELATED DOCUMENTATION) FROM STMICROELECTRONICS INTERNATIONAL N.V, SWISS BRANCH AND/OR ITS AFFILIATED COMPANIES (STMICROELECTRONICS), THE RECIPIENT, ON BEHALF OF HIMSELF OR HERSELF, OR ON BEHALF OF ANY ENTITY BY WHICH SUCH RECIPIENT IS EMPLOYED AND/OR ENGAGED AGREES TO BE BOUND BY THIS SOFTWARE LICENSE AGREEMENT. + +Under STMicroelectronics’ intellectual property rights, the redistribution, reproduction and use in source and binary forms of the software or any part thereof, with or without modification, are permitted provided that the following conditions are met: +1. Redistribution of source code (modified or not) must retain any copyright notice, this list of conditions and the disclaimer set forth below as items 10 and 11. +2. Redistributions in binary form, except as embedded into microcontroller or microprocessor device manufactured by or for STMicroelectronics or a software update for such device, must reproduce any copyright notice provided with the binary code, this list of conditions, and the disclaimer set forth below as items 10 and 11, in documentation and/or other materials provided with the distribution. +3. Neither the name of STMicroelectronics nor the names of other contributors to this software may be used to endorse or promote products derived from this software or part thereof without specific written permission. +4. This software or any part thereof, including modifications and/or derivative works of this software, must be used and execute solely and exclusively on or in combination with a microcontroller or microprocessor device manufactured by or for STMicroelectronics. +5. No use, reproduction or redistribution of this software partially or totally may be done in any manner that would subject this software to any Open Source Terms. “Open Source Terms” shall mean any open source license which requires as part of distribution of software that the source code of such software is distributed therewith or otherwise made available, or open source license that substantially complies with the Open Source definition specified at www.opensource.org and any other comparable open source license such as for example GNU General Public License (GPL), Eclipse Public License (EPL), Apache Software License, BSD license or MIT license. +6. STMicroelectronics has no obligation to provide any maintenance, support or updates for the software. +7. The software is and will remain the exclusive property of STMicroelectronics and its licensors. The recipient will not take any action that jeopardizes STMicroelectronics and its licensors' proprietary rights or acquire any rights in the software, except the limited rights specified hereunder. +8. The recipient shall comply with all applicable laws and regulations affecting the use of the software or any part thereof including any applicable export control law or regulation. +9. Redistribution and use of this software or any part thereof other than as permitted under this license is void and will automatically terminate your rights under this license. +10. THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY RIGHTS, WHICH ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +11. EXCEPT AS EXPRESSLY PERMITTED HEREUNDER, NO LICENSE OR OTHER RIGHTS, WHETHER EXPRESS OR IMPLIED, ARE GRANTED UNDER ANY PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF STMICROELECTRONICS OR ANY THIRD PARTY. + + diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/change-log.rst b/meta-arm/meta-arm-bsp/documentation/corstone1000/change-log.rst new file mode 100644 index 000000000000..64e82aac98fa --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/change-log.rst @@ -0,0 +1,164 @@ +.. + # Copyright (c) 2022, Arm Limited. + # + # SPDX-License-Identifier: MIT + +########## +Change Log +########## + +This document contains a summary of the new features, changes and +fixes in each release of Corstone-1000 software stack. + +****************** +Version 2022.11.23 +****************** + +Changes +======= + +- Booting the External System (Cortex-M3) with RTX RTOS +- Adding MHU communication between the HOST (Cortex-A35) and the External System +- Adding a Linux application to test the External System +- Adding ESRT (EFI System Resource Table) support +- Upgrading the SW stack recipes +- Upgrades for the U-Boot FF-A driver and MM communication + +Corstone-1000 components versions +======================================= + ++-------------------------------------------+------------+ +| arm-ffa-tee | 1.1.1 | ++-------------------------------------------+------------+ +| arm-ffa-user | 5.0.0 | ++-------------------------------------------+------------+ +| corstone1000-external-sys-tests | 1.0 | ++-------------------------------------------+------------+ +| external-system | 0.1.0 | ++-------------------------------------------+------------+ +| linux-yocto | 5.19 | ++-------------------------------------------+------------+ +| u-boot | 2022.07 | ++-------------------------------------------+------------+ +| optee-client | 3.18.0 | ++-------------------------------------------+------------+ +| optee-os | 3.18.0 | ++-------------------------------------------+------------+ +| trusted-firmware-a | 2.7.0 | ++-------------------------------------------+------------+ +| trusted-firmware-m | 1.6.0 | ++-------------------------------------------+------------+ +| ts-newlib | 4.1.0 | ++-------------------------------------------+------------+ +| ts-psa-{crypto, iat, its. ps}-api-test | 451aa087a4 | ++-------------------------------------------+------------+ +| ts-sp-{se-proxy, smm-gateway} | 3d4956770f | ++-------------------------------------------+------------+ + +Yocto distribution components versions +======================================= + ++-------------------------------------------+---------------------+ +| meta-arm | langdale | ++-------------------------------------------+---------------------+ +| poky | langdale | ++-------------------------------------------+---------------------+ +| meta-openembedded | langdale | ++-------------------------------------------+---------------------+ +| busybox | 1.35.0 | ++-------------------------------------------+---------------------+ +| musl | 1.2.3+git37e18b7bf3 | ++-------------------------------------------+---------------------+ +| gcc-arm-none-eabi-native | 11.2-2022.02 | ++-------------------------------------------+---------------------+ +| gcc-cross-aarch64 | 12.2 | ++-------------------------------------------+---------------------+ +| openssl | 3.0.5 | ++-------------------------------------------+---------------------+ + +****************** +Version 2022.04.04 +****************** + +Changes +======= +- Linux distro openSUSE, raw image installation and boot in the FVP. +- SCT test support in FVP. +- Manual capsule update support in FVP. + +****************** +Version 2022.02.25 +****************** + +Changes +======= +- Building and running psa-arch-tests on Corstone-1000 FVP +- Enabled smm-gateway partition in Trusted Service on Corstone-1000 FVP +- Enabled MHU driver in Trusted Service on Corstone-1000 FVP +- Enabled OpenAMP support in SE proxy SP on Corstone-1000 FVP + +****************** +Version 2022.02.21 +****************** + +Changes +======= +- psa-arch-tests: recipe is dropped and merged into the secure-partitons recipe. +- psa-arch-tests: The tests are align with latest tfm version for psa-crypto-api suite. + +****************** +Version 2022.01.18 +****************** + +Changes +======= +- psa-arch-tests: change master to main for psa-arch-tests +- U-Boot: fix null pointer exception for get_image_info +- TF-M: fix capsule instability issue for Corstone-1000 + +****************** +Version 2022.01.07 +****************** + +Changes +======= +- Corstone-1000: fix SystemReady-IR ACS test (SCT, FWTS) failures. +- U-Boot: send bootcomplete event to secure enclave. +- U-Boot: support populating Corstone-1000 image_info to ESRT table. +- U-Boot: add ethernet device and enable configs to support bootfromnetwork SCT. + +****************** +Version 2021.12.15 +****************** + +Changes +======= +- Enabling Corstone-1000 FPGA support on: + - Linux 5.10 + - OP-TEE 3.14 + - Trusted Firmware-A 2.5 + - Trusted Firmware-M 1.5 +- Building and running psa-arch-tests +- Adding openamp support in SE proxy SP +- OP-TEE: adding smm-gateway partition +- U-Boot: introducing Arm FF-A and MM support + +****************** +Version 2021.10.29 +****************** + +Changes +======= +- Enabling Corstone-1000 FVP support on: + - Linux 5.10 + - OP-TEE 3.14 + - Trusted Firmware-A 2.5 + - Trusted Firmware-M 1.4 +- Linux kernel: enabling EFI, adding FF-A debugfs driver, integrating ARM_FFA_TRANSPORT. +- U-Boot: Extending EFI support +- python3-imgtool: adding recipe for Trusted-firmware-m +- python3-imgtool: adding the Yocto recipe used in signing host images (based on MCUBOOT format) + +-------------- + +*Copyright (c) 2022, Arm Limited. All rights reserved.* diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/conf.py b/meta-arm/meta-arm-bsp/documentation/corstone1000/conf.py new file mode 100644 index 000000000000..e9cab6335977 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/conf.py @@ -0,0 +1,52 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'corstone1000' +copyright = '2020-2022, Arm Limited' +author = 'Arm Limited' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'docs/infra'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/CorstoneSubsystems.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/CorstoneSubsystems.png new file mode 100644 index 000000000000..a41e721027e9 Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/CorstoneSubsystems.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/ExternalFlash.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/ExternalFlash.png new file mode 100644 index 000000000000..38407c08d9e1 Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/ExternalFlash.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureBootChain.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureBootChain.png new file mode 100644 index 000000000000..bc5b4ba35eed Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureBootChain.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureFirmwareUpdate.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureFirmwareUpdate.png new file mode 100644 index 000000000000..5fdae9db29e5 Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureFirmwareUpdate.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureServices.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureServices.png new file mode 100644 index 000000000000..b7631b0230ed Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/SecureServices.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/images/UEFISupport.png b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/UEFISupport.png new file mode 100644 index 000000000000..f58531719d50 Binary files /dev/null and b/meta-arm/meta-arm-bsp/documentation/corstone1000/images/UEFISupport.png differ diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/index.rst b/meta-arm/meta-arm-bsp/documentation/corstone1000/index.rst new file mode 100644 index 000000000000..8626c42c2b72 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/index.rst @@ -0,0 +1,16 @@ +.. + # Copyright (c) 2022, Arm Limited. + # + # SPDX-License-Identifier: MIT + +################ +ARM Corstone1000 +################ + +.. toctree:: + :maxdepth: 1 + + software-architecture + user-guide + release-notes + change-log diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/release-notes.rst b/meta-arm/meta-arm-bsp/documentation/corstone1000/release-notes.rst new file mode 100644 index 000000000000..89a4fa9ab265 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/release-notes.rst @@ -0,0 +1,177 @@ +.. + # Copyright (c) 2022, Arm Limited. + # + # SPDX-License-Identifier: MIT + +############# +Release notes +############# + + +************************* +Disclaimer +************************* + +You expressly assume all liabilities and risks relating to your use or operation +of Your Software and Your Hardware designed or modified using the Arm Tools, +including without limitation, Your software or Your Hardware designed or +intended for safety-critical applications. Should Your Software or Your Hardware +prove defective, you assume the entire cost of all necessary servicing, repair +or correction. + + +************************** +Release notes - 2022.11.23 +************************** + +Known Issues or Limitations +--------------------------- + - The external-system can not be reset individually on (or using) AN550_v1 FPGA release. However, the system-wide reset still applies to the external-system. + - FPGA supports Linux distro install and boot through installer. However, FVP only supports openSUSE raw image installation and boot. + - Due to the performance uplimit of MPS3 FPGA and FVP, some Linux distros like Fedora Rawhide can not boot on Corstone-1000 (i.e. user may experience timeouts or boot hang). + - Below SCT FAILURE is a known issues in the FVP: + UEFI Compliant - Boot from network protocols must be implemented -- FAILURE + - Below SCT FAILURE is a known issue when a terminal emulator (in the system where the user connects to serial ports) does not support 80x25 or 80x50 mode: + EFI_SIMPLE_TEXT_OUT_PROTOCOL.SetMode - SetMode() with valid mode -- FAILURE + - Known limitations regarding ACS tests: The behavior after running ACS tests on FVP is not consistent. Both behaviors are expected and are valid; + The system might boot till the Linux prompt. Or, the system might wait after finishing the ACS tests. + In both cases, the system executes the entire test suite and writes the results as stated in the user guide. + + +Platform Support +----------------- + - This software release is tested on Corstone-1000 FPGA version AN550_v1 + https://developer.arm.com/downloads/-/download-fpga-images + - This software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.19_21 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +************************** +Release notes - 2022.04.04 +************************** + +Known Issues or Limitations +--------------------------- + - FPGA support Linux distro install and boot through installer. However, + FVP only support openSUSE raw image installation and boot. + - Due to the performance uplimit of MPS3 FPGA and FVP, some Linux distros like Fedora Rawhide + cannot boot on Corstone-1000 (i.e. user may experience timeouts or boot hang). + - Below SCT FAILURE is a known issues in the FVP: + UEFI Compliant - Boot from network protocols must be implemented -- FAILURE + +Platform Support +----------------- + - This software release is tested on Corstone-1000 FPGA version AN550_v1 + - This software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.17_23 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +************************** +Release notes - 2022.02.25 +************************** + +Known Issues or Limitations +--------------------------- + - The following tests only work on Corstone-1000 FPGA: ACS tests (SCT, FWTS, + BSA), manual capsule update test, Linux distro install and boot. + +Platform Support +---------------- + - This software release is tested on Corstone-1000 FPGA version AN550_v1 + - This software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.17_23 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +Release notes - 2022.02.21 +-------------------------- + +Known Issues or Limitations +--------------------------- + - The following tests only work on Corstone-1000 FPGA: ACS tests (SCT, FWTS, + BSA), manual capsule update test, Linux distro install and boot, psa-arch-test. + +Platform Support +---------------- + - This software release is tested on Corstone-1000 FPGA version AN550_v1 + - This software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.16.21 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +Release notes - 2022.01.18 +-------------------------- + +Known Issues or Limitations +--------------------------- + + - Before running each SystemReady-IR tests: ACS tests (SCT, FWTS, BSA), manual + capsule update test, Linux distro install and boot, etc., the SecureEnclave + flash must be cleaned. See user-guide "Clean Secure Flash Before Testing" + section. + +Release notes - 2021.12.15 +-------------------------- + +Software Features +------------------ +The following components are present in the release: + + - Yocto version Honister + - Linux kernel version 5.10 + - U-Boot 2021.07 + - OP-TEE version 3.14 + - Trusted Firmware-A 2.5 + - Trusted Firmware-M 1.5 + - OpenAMP 347397decaa43372fc4d00f965640ebde042966d + - Trusted Services a365a04f937b9b76ebb2e0eeade226f208cbc0d2 + + +Platform Support +---------------- + - This software release is tested on Corstone-1000 FPGA version AN550_v1 + - This software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.16.21 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +Known Issues or Limitations +--------------------------- + - The following tests only work on Corstone-1000 FPGA: ACS tests (SCT, FWTS, + BSA), manual capsule update test, Linux distro install and boot, and + psa-arch-tests. + - Only the manual capsule update from UEFI shell is supported on FPGA. + - Due to flash size limitation and to support A/B banks,the wic image provided + by the user should be smaller than 15MB. + - The failures in PSA Arch Crypto Test are known limitations with crypto + library. It requires further investigation. The user can refer to `PSA Arch Crypto Test Failure Analysis In TF-M V1.5 Release `__ + for the reason for each failing test. + + +Release notes - 2021.10.29 +-------------------------- + +Software Features +----------------- +This initial release of Corstone-1000 supports booting Linux on the Cortex-A35 +and TF-M/MCUBOOT in the Secure Enclave. The following components are present in +the release: + + - Linux kernel version 5.10 + - U-Boot 2021.07 + - OP-TEE version 3.14 + - Trusted Firmware-A 2.5 + - Trusted Firmware-M 1.4 + +Platform Support +---------------- + - This Software release is tested on Corstone-1000 Fast Model platform (FVP) version 11.16.21 + https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps + +Known Issues or Limitations +--------------------------- + - No software support for external system(Cortex M3) + - No communication established between A35 and M0+ + - Very basic functionality of booting Secure Enclave, Trusted Firmware-A , OP-TEE , u-boot and Linux are performed + +Support +------- +For technical support email: support-subsystem-iot@arm.com + +For all security issues, contact Arm by email at arm-security@arm.com. + +-------------- + +*Copyright (c) 2022, Arm Limited. All rights reserved.* diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/software-architecture.rst b/meta-arm/meta-arm-bsp/documentation/corstone1000/software-architecture.rst new file mode 100644 index 000000000000..a17f1b8a6809 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/software-architecture.rst @@ -0,0 +1,239 @@ +.. + # Copyright (c) 2022, Arm Limited. + # + # SPDX-License-Identifier: MIT + +###################### +Software architecture +###################### + + +***************** +ARM corstone1000 +***************** + +ARM corstone1000 is a reference solution for IoT devices. It is part of +Total Solution for IoT which consists of hardware and software reference +implementation. + +Corstone1000 software plus hardware reference solution is PSA Level-2 ready +certified (`PSA L2 Ready`_) as well as System Ready IR certified(`SRIR cert`_). +More information on the corstone1000 subsystem product and design can be +found at: +`Arm corstone1000 Software`_ and `Arm corstone1000 Technical Overview`_. + +This readme explicitly focuses on the software part of the solution and +provides internal details on the software components. The reference +software package of the platform can be retrieved following instructions +present in the user-guide document. + +*************** +Design Overview +*************** + +The software architecture of corstone1000 platform is a reference +implementation of Platform Security Architecture (`PSA`_) which provides +framework to build secure IoT devices. + +The base system architecture of the platform is created from three +different tyes of systems: Secure Enclave, Host and External System. +Each subsystem provides different functionality to overall SoC. + + +.. image:: images/CorstoneSubsystems.png + :width: 720 + :alt: CorstoneSubsystems + + +The Secure Enclave System, provides PSA Root of Trust (RoT) and +cryptographic functions. It is based on an Cortex-M0+ processor, +CC312 Cryptographic Accelerator and peripherals, such as watchdog and +secure flash. Software running on the Secure Enclave is isolated via +hardware for enhanced security. Communication with the Secure Encalve +is achieved using Message Hnadling Units (MHUs) and shared memory. +On system power on, the Secure Enclaves boots first. Its software +comprises of two boot loading stages, both based on mcuboot, and +TrustedFirmware-M(`TF-M`_) as runtime software. The software design on +Secure Enclave follows Firmware Framework for M class +processor (`FF-M`_) specification. + +The Host System is based on ARM Cotex-A35 processor with standardized +peripherals to allow for the booting of a Linux OS. The Cortex-A35 has +the TrustZone technology that allows secure and non-secure security +states in the processor. The software design in the Host System follows +Firmware Framework for A class procseeor (`FF-A`_) specification. +The boot process follows Trusted Boot Base Requirement (`TBBR`_). +The Host Subsystem is taken out of reset by the Secure Enclave system +during its final stages of the initialization. The Host subsystem runs +FF-A Secure Partitions(based on `Trusted Services`_) and OPTEE-OS +(`OPTEE-OS`_) in the secure world, and u-boot(`u-boot repo`_) and +linux (`linux repo`_) in the non-secure world. The communication between +non-secure and the secure world is performed via FF-A messages. + +An external system is intended to implement use-case specific +functionality. The system is based on Cortex-M3 and run RTX RTOS. +Communictaion between external system and Host(cortex-A35) is performed +using MHU as transport mechanism and rpmsg messaging system. + +Overall, the corstone1000 architecture is designed to cover a range +of Power, Performance, and Area (PPA) applications, and enable extension +for use-case specific applications, for example, sensors, cloud +connectivitiy, and edge computing. + +***************** +Secure Boot Chain +***************** + +For the security of a device, it is essential that only authorized +software should run on the device. The corstone1000 boot uses a +Secure Boot Chain process where an already authenticated image verifies +and loads the following software in the chain. For the boot chain +process to work, the start of the chain should be trusted, forming the +Root of Trust (RoT) of the device. The RoT of the device is immutable in +nature and encoded into the device by the device owner before it +is deployed into the field. In Corstone1000, the BL1 image of the secure +enclave and content of the CC312 OTP (One Time Programmable) memory +forms the RoT. The BL1 image exists in ROM (Read Only Memory). + +.. image:: images/SecureBootChain.png + :width: 870 + :alt: SecureBootChain + +It is a lengthy chain to boot the software on corstone1000. On power on, +the secure enclave starts executing BL1 code from the ROM which is the RoT +of the device. Authentication of an image involves the steps listed below: + +- Load image from flash to dynamic RAM. +- The public key present in the image header is validated by comparing with the hash. Depending on the image, the hash of the public key is either stored in the OTP or part of the software which is being already verfied in the previous stages. +- The image is validated using the public key. + +In the secure enclave, BL1 authenticates the BL2 and passes the execution +control. BL2 authenticates the initial boot loader of the host (Host BL2) +and TF-M. The execution control is now passed to TF-M. TF-M being the run +time executable of secure enclaves initializes itself and, in the end, +brings the host CPU out of rest. The host follows the boot standard defined +in the `TBBR`_ to authenticate the secure and non-secure software. + +*************** +Secure Services +*************** + +corstone1000 is unique in providing a secure environment to run a secure +workload. The platform has Trustzone technology in the Host subsystem but +it also has hardware isolated secure enclave environment to run such secure +workloads. In corstone1000, known Secure Services such as Crypto, Protected +Storage, Internal Trusted Storage and Attestation are available via PSA +Functional APIs in TF-M. There is no difference for a user communicating to +these services which are running on a secure enclave instead of the +secure world of the host subsystem. The below diagram presents the data +flow path for such calls. + + +.. image:: images/SecureServices.png + :width: 930 + :alt: SecureServices + + +The SE Proxy SP (Secure Enclave Proxy Secure Partition) is a proxy partition +managed by OPTEE which forwards such calls to the secure enclave. The +solution relies on OpenAMP which uses shared memory and MHU interrupts as +a doorbell for communication between two cores. corstone1000 implements +isolation level 2. Cortex-M0+ MPU (Memory Protection Unit) is used to implement +isolation level 2. + +For a user to define its own secure service, both the options of the host +secure world or secure encalve are available. It's a trade-off between +lower latency vs higher security. Services running on a secure enclave are +secure by real hardware isolation but have a higher latency path. In the +second scenario, the services running on the secure world of the host +subsystem have lower latency but virtual hardware isolation created by +Trustzone technology. + + +********************** +Secure Firmware Update +********************** + +Apart from always booting the authorized images, it is also essential that +the device only accepts the authorized images in the firmware update +process. corstone1000 supports OTA (Over the Air) firmware updates and +follows Platform Security Firmware Update sepcification (`FWU`_). + +As standardized into `FWU`_, the external flash is divided into two +banks of which one bank has currently running images and the other bank is +used for staging new images. There are four updatable units, i.e. Secure +Enclave's BL2 and TF-M, and Host's FIP (Firmware Image Package) and Kernel +Image. The new images are accepted in the form of a UEFI capsule. + + +.. image:: images/ExternalFlash.png + :width: 690 + :alt: ExternalFlash + + +The Metadata Block in the flash has the below firmware update state machine. +TF-M runs an OTA service that is responsible for accepting and updating the +images in the flash. The communication between the UEFI Capsule update +subsystem and the OTA service follows the same data path explained above. +The OTA service writes the new images to the passive bank after successful +capsule verification. It changes the state of the system to trial state and +triggers the reset. Boot loaders in Secure Enclave and Host read the Metadata +block to get the information on the boot bank. In the successful trial stage, +the acknowledgment from the host moves the state of the system from trial to +regular. Any failure in the trial stage or system hangs leads to a system +reset. This is made sure by the use of watchdog hardware. The Secure Enclave's +BL1 has the logic to identify multiple resets and eventually switch back to the +previous good bank. The ability to revert to the previous bank is crucial to +guarantee the availability of the device. + + +.. image:: images/SecureFirmwareUpdate.png + :width: 430 + :alt: SecureFirmwareUpdate + + + +****************************** +UEFI Runtime Support in u-boot +****************************** + +Implementation of UEFI boottime and runtime APIs require variable storage. +In corstone1000, these UEFI variables are stored in the Protected Storage +service. The below diagram presents the data flow to store UEFI variables. +The u-boot implementation of the UEFI subsystem uses the FF-A driver to +communicate with the SMM Service in the secure world. The backend of the +SMM service uses the proxy PS from the SE Proxy SP. From there on, the PS +calls are forwarded to the secure enclave as explained above. + + +.. image:: images/UEFISupport.png + :width: 590 + :alt: UEFISupport + + +*************** +References +*************** +`ARM corstone1000 Search`_ +`Arm security features`_ + +-------------- + +*Copyright (c) 2022, Arm Limited. All rights reserved.* + +.. _Arm corstone1000 Technical Overview: https://developer.arm.com/documentation/102360/0000 +.. _Arm corstone1000 Software: https://developer.arm.com/Tools%20and%20Software/Corstone-1000%20Software +.. _Arm corstone1000 Search: https://developer.arm.com/search#q=corstone-1000 +.. _Arm security features: https://www.arm.com/architecture/security-features/platform-security +.. _linux repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ +.. _FF-A: https://developer.arm.com/documentation/den0077/latest +.. _FF-M: https://developer.arm.com/-/media/Files/pdf/PlatformSecurityArchitecture/Architect/DEN0063-PSA_Firmware_Framework-1.0.0-2.pdf?revision=2d1429fa-4b5b-461a-a60e-4ef3d8f7f4b4&hash=3BFD6F3E687F324672F18E5BE9F08EDC48087C93 +.. _FWU: https://developer.arm.com/documentation/den0118/a/ +.. _OPTEE-OS: https://github.com/OP-TEE/optee_os +.. _PSA: https://www.psacertified.org/ +.. _PSA L2 Ready: https://www.psacertified.org/products/corstone-1000/ +.. _SRIR cert: https://armkeil.blob.core.windows.net/developer/Files/pdf/certificate-list/arm-systemready-ir-certification-arm-corstone-1000.pdf +.. _TBBR: https://developer.arm.com/documentation/den0006/latest +.. _TF-M: https://www.trustedfirmware.org/projects/tf-m/ +.. _Trusted Services: https://www.trustedfirmware.org/projects/trusted-services/ +.. _u-boot repo: https://github.com/u-boot/u-boot.git diff --git a/meta-arm/meta-arm-bsp/documentation/corstone1000/user-guide.rst b/meta-arm/meta-arm-bsp/documentation/corstone1000/user-guide.rst new file mode 100644 index 000000000000..e173f244b479 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone1000/user-guide.rst @@ -0,0 +1,1078 @@ +.. + # Copyright (c) 2022, Arm Limited. + # + # SPDX-License-Identifier: MIT + +########## +User Guide +########## + +Notice +------ +The Corstone-1000 software stack uses the `Yocto Project `__ to build +a tiny Linux distribution suitable for the Corstone-1000 platform (kernel and initramfs filesystem less than 5 MB on the flash). +The Yocto Project relies on the `Bitbake `__ +tool as its build tool. Please see `Yocto Project documentation `__ +for more information. + + +Prerequisites +------------- +These instructions assume your host PC is running Ubuntu Linux 18.04 or 20.04 LTS, with at least 32GB of free disk space and 16GB of RAM as minimum requirement. The following instructions expect that you are using a bash shell. All the paths stated in this document are absolute paths. + +The following prerequisites must be available on the host system. To resolve these dependencies, run: + +:: + + sudo apt-get update + sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \ + build-essential chrpath socat cpio python3 python3-pip python3-pexpect \ + xz-utils debianutils iputils-ping python3-git libegl1-mesa libsdl1.2-dev \ + xterm zstd liblz4-tool picocom + sudo apt-get upgrade libstdc++6 + +Provided components +------------------- +Within the Yocto Project, each component included in the Corstone-1000 software stack is specified as +a `bitbake recipe `__. +The recipes specific to the Corstone-1000 BSP are located at: +``<_workspace>/meta-arm/meta-arm-bsp/``. + +The Yocto machine config files for the Corstone-1000 FVP and FPGA targets are: + + - ``<_workspace>/meta-arm/meta-arm-bsp/conf/machine/include/corstone1000.inc`` + - ``<_workspace>/meta-arm/meta-arm-bsp/conf/machine/corstone1000-fvp.conf`` + - ``<_workspace>/meta-arm/meta-arm-bsp/conf/machine/corstone1000-mps3.conf`` + +***************** +Software for Host +***************** + +Trusted Firmware-A +================== +Based on `Trusted Firmware-A `__ + ++----------+---------------------------------------------------------------------------------------------------+ +| bbappend | <_workspace>/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.7.bbappend | ++----------+---------------------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/meta-arm/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.7.bb | ++----------+---------------------------------------------------------------------------------------------------+ + +OP-TEE +====== +Based on `OP-TEE `__ + ++----------+------------------------------------------------------------------------------------+ +| bbappend | <_workspace>/meta-arm/meta-arm-bsp/recipes-security/optee/optee-os_3.18.0.bbappend | ++----------+------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/meta-arm/meta-arm/recipes-security/optee/optee-os_3.18.0.bb | ++----------+------------------------------------------------------------------------------------+ + +U-Boot +======= +Based on `U-Boot `__ + ++----------+---------------------------------------------------------------------+ +| bbappend | <_workspace>/meta-arm/meta-arm/recipes-bsp/u-boot/u-boot_%.bbappend | ++----------+---------------------------------------------------------------------+ +| Recipe | <_workspace>/poky/meta/recipes-bsp/u-boot/u-boot_2022.07.bb | ++----------+---------------------------------------------------------------------+ + +Linux +===== +The distro is based on the `poky-tiny `__ +distribution which is a Linux distribution stripped down to a minimal configuration. + +The provided distribution is based on busybox and built using muslibc. The +recipe responsible for building a tiny version of Linux is listed below. + ++-----------+----------------------------------------------------------------------------------------------+ +| bbappend | <_workspace>/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-yocto_%.bbappend | ++-----------+----------------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/poky/meta/recipes-kernel/linux/linux-yocto_5.19.bb | ++-----------+----------------------------------------------------------------------------------------------+ +| defconfig | <_workspace>/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig | ++-----------+----------------------------------------------------------------------------------------------+ + +External System Tests +======================= +Based on `Corstone-1000/applications `__ + ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/meta-arm/meta-arm-bsp/recipes-test/corstone1000-external-sys-tests/corstone1000-external-sys-tests_1.0.bb | ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +The recipe provides the systems-comms-tests command run in Linux and used for testing the External System. + +************************************************** +Software for Boot Processor (a.k.a Secure Enclave) +************************************************** +Based on `Trusted Firmware-M `__ + ++----------+-------------------------------------------------------------------------------------------------+ +| bbappend | <_workspace>/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_%.bbappend | ++----------+-------------------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_1.6.0.bb | ++----------+-------------------------------------------------------------------------------------------------+ + +************************************************** +Software for the External System +************************************************** + +RTX +==== +Based on `RTX RTOS `__ + ++----------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Recipe | <_workspace>/meta-arm/meta-arm-bsp/recipes-bsp/external-system/external-system_0.1.0.bb | ++----------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Building the software stack +--------------------------- +Create a new folder that will be your workspace and will henceforth be referred +to as ``<_workspace>`` in these instructions. To create the folder, run: + +:: + + mkdir <_workspace> + cd <_workspace> + +Corstone-1000 software is based on the Yocto Project which uses kas and bitbake +commands to build the stack. To install kas tool, run: + +:: + + pip3 install kas + +If 'kas' command is not found in command-line, please make sure the user installation directories are visible on $PATH. If you have sudo rights, try 'sudo pip3 install kas'. + +In the top directory of the workspace ``<_workspace>``, run: + +:: + + git clone https://git.yoctoproject.org/git/meta-arm -b CORSTONE1000-2022.11.23 + +To build a Corstone-1000 image for MPS3 FPGA, run: + +:: + + kas build meta-arm/kas/corstone1000-mps3.yml + +Alternatively, to build a Corstone-1000 image for FVP, run: + +:: + + kas build meta-arm/kas/corstone1000-fvp.yml + +The initial clean build will be lengthy, given that all host utilities are to +be built as well as the target images. This includes host executables (python, +cmake, etc.) and the required toolchain(s). + +Once the build is successful, all output binaries will be placed in the following folders: + - ``<_workspace>/build/tmp/deploy/images/corstone1000-fvp/`` folder for FVP build; + - ``<_workspace>/build/tmp/deploy/images/corstone1000-mps3/`` folder for FPGA build. + +Everything apart from the Secure Enclave ROM firmware and External System firmware, is bundled into a single binary, the +``corstone1000-image-corstone1000-{mps3,fvp}.wic.nopt`` file. + +The output binaries run in the Corstone-1000 platform are the following: + - The Secure Enclave ROM firmware: ``<_workspace>/build/tmp/deploy/images/corstone1000-{mps3,fvp}/bl1.bin`` + - The External System firmware: ``<_workspace>/build/tmp/deploy/images/corstone1000-{mps3,fvp}/es_flashfw.bin`` + - The flash image: ``<_workspace>/build/tmp/deploy/images/corstone1000-{mps3,fvp}/corstone1000-image-corstone1000-{mps3,fvp}.wic.nopt`` + +Flash the firmware image on FPGA +-------------------------------- + +The user should download the FPGA bit file image ``AN550: Arm® Corstone™-1000 for MPS3 Version 1`` +from `this link `__ +and under the section ``Arm® Corstone™-1000 for MPS3``. + +The directory structure of the FPGA bundle is shown below. + +:: + + Boardfiles + ├── MB + │   ├── BRD_LOG.TXT + │   ├── HBI0309B + │   │   ├── AN550 + │   │   │   ├── AN550_v1.bit + │   │   │   ├── an550_v1.txt + │   │   │   └── images.txt + │   │   ├── board.txt + │   │   └── mbb_v210.ebf + │   └── HBI0309C + │   ├── AN550 + │   │   ├── AN550_v1.bit + │   │   ├── an550_v1.txt + │   │   └── images.txt + │   ├── board.txt + │   └── mbb_v210.ebf + ├── SOFTWARE + │   ├── ES0.bin + │   ├── SE.bin + │   └── an550_st.axf + └── config.txt + +Depending upon the MPS3 board version (printed on the MPS3 board) you should update the images.txt file +(in corresponding HBI0309x folder. Boardfiles/MB/HBI0309/AN550/images.txt) so that the file points to the images under SOFTWARE directory. + +The images.txt file that is compatible with the latest version of the software +stack can be seen below; + +:: + + ;************************************************ + ; Preload port mapping * + ;************************************************ + ; PORT 0 & ADDRESS: 0x00_0000_0000 QSPI Flash (XNVM) (32MB) + ; PORT 0 & ADDRESS: 0x00_8000_0000 OCVM (DDR4 2GB) + ; PORT 1 Secure Enclave (M0+) ROM (64KB) + ; PORT 2 External System 0 (M3) Code RAM (256KB) + ; PORT 3 Secure Enclave OTP memory (8KB) + ; PORT 4 CVM (4MB) + ;************************************************ + + [IMAGES] + TOTALIMAGES: 3 ;Number of Images (Max: 32) + + IMAGE0PORT: 1 + IMAGE0ADDRESS: 0x00_0000_0000 + IMAGE0UPDATE: RAM + IMAGE0FILE: \SOFTWARE\bl1.bin + + IMAGE1PORT: 0 + IMAGE1ADDRESS: 0x00_0010_0000 + IMAGE1UPDATE: AUTOQSPI + IMAGE1FILE: \SOFTWARE\cs1000.bin + + IMAGE2PORT: 2 + IMAGE2ADDRESS: 0x00_0000_0000 + IMAGE2UPDATE: RAM + IMAGE2FILE: \SOFTWARE\es0.bin + +OUTPUT_DIR = ``<_workspace>/build/tmp/deploy/images/corstone1000-mps3`` + +1. Copy ``bl1.bin`` from OUTPUT_DIR directory to SOFTWARE directory of the FPGA bundle. +2. Copy ``es_flashfw.bin`` from OUTPUT_DIR directory to SOFTWARE directory of the FPGA bundle + and rename the binary to ``es0.bin``. +3. Copy ``corstone1000-image-corstone1000-mps3.wic.nopt`` from OUTPUT_DIR directory to SOFTWARE + directory of the FPGA bundle and rename the wic.nopt image to ``cs1000.bin``. + + +**NOTE:** Renaming of the images are required because MCC firmware has +limitation of 8 characters before .(dot) and 3 characters after .(dot). + +Now, copy the entire folder to board's SDCard and reboot the board. + +Running the software on FPGA +---------------------------- + +On the host machine, open 4 serial port terminals. In case of Linux machine it will +be ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 and it might be different on Windows machines. + + - ttyUSB0 for MCC, OP-TEE and Secure Partition + - ttyUSB1 for Boot Processor (Cortex-M0+) + - ttyUSB2 for Host Processor (Cortex-A35) + - ttyUSB3 for External System Processor (Cortex-M3) + +Run following commands to open serial port terminals on Linux: + +:: + + sudo picocom -b 115200 /dev/ttyUSB0 # in one terminal + sudo picocom -b 115200 /dev/ttyUSB1 # in another terminal + sudo picocom -b 115200 /dev/ttyUSB2 # in another terminal. + sudo picocom -b 115200 /dev/ttyUSB3 # in another terminal. + +Once the system boot is completed, you should see console +logs on the serial port terminals. Once the HOST(Cortex-A35) is +booted completely, user can login to the shell using +**"root"** login. + +If system does not boot and only the ttyUSB1 logs are visible, please follow the steps in `Clean Secure Flash Before Testing (applicable to FPGA only)`_ under `SystemReady-IR tests`_ section. The previous image used in FPGA (MPS3) might have filled the Secure Flash completely. The best practice is to clean the secure flash in this case. + + +Running the software on FVP +--------------------------- + +An FVP (Fixed Virtual Platform) model of the Corstone-1000 platform must be available to run the +Corstone-1000 FVP software image. + +A Yocto recipe is provided and allows to download the latest supported FVP version. + +The recipe is located at <_workspace>/meta-arm/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb + +The latest supported Fixed Virtual Platform (FVP) version is 11.19_21 and is automatically downloaded and installed when using the runfvp command as detailed below. The FVP version can be checked by running the following command: + +:: + +<_workspace>/meta-arm/scripts/runfvp <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.fvpconf -- --version + +The FVP can also be manually downloaded from the `Arm Ecosystem FVPs`_ page. On this page, navigate +to "Corstone IoT FVPs" section to download the Corstone-1000 platform FVP installer. Follow the +instructions of the installer and setup the FVP. + +To run the FVP using the runfvp command, please run the following command: + +:: + +<_workspace>/meta-arm/scripts/runfvp --terminals=xterm <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.fvpconf + +When the script is executed, three terminal instances will be launched, one for the boot processor +(aka Secure Enclave) processing element and two for the Host processing element. Once the FVP is +executing, the Boot Processor will start to boot, wherein the relevant memory contents of the .wic.nopt +file are copied to their respective memory locations within the model, enforce firewall policies +on memories and peripherals and then, bring the host out of reset. + +The host will boot trusted-firmware-a, OP-TEE, U-Boot and then Linux, and present a login prompt +(FVP host_terminal_0): + +:: + + corstone1000-fvp login: + +Login using the username root. + +The External System can be released out of reset on demand using the systems-comms-tests command. + +SystemReady-IR tests +------------------------- + +********************* +Testing steps +********************* + +**NOTE**: Running the SystemReady-IR tests described below requires the user to +work with USB sticks. In our testing, not all USB stick models work well with +MPS3 FPGA. Here are the USB sticks models that are stable in our test +environment. + + - HP V165W 8 GB USB Flash Drive + - SanDisk Ultra 32GB Dual USB Flash Drive USB M3.0 + - SanDisk Ultra 16GB Dual USB Flash Drive USB M3.0 + +**NOTE**: +Before running each of the tests in this chapter, the user should follow the +steps described in following section "Clean Secure Flash Before Testing" to +erase the SecureEnclave flash cleanly and prepare a clean board environment for +the testing. + +Clean Secure Flash Before Testing (applicable to FPGA only) +================================================================== + +To prepare a clean board environment with clean secure flash for the testing, +the user should prepare an image that erases the secure flash cleanly during +boot. Run following commands to build such image. + +:: + + cd <_workspace> + git clone https://git.yoctoproject.org/git/meta-arm -b CORSTONE1000-2022.11.23 + git clone https://git.gitlab.arm.com/arm-reference-solutions/systemready-patch.git -b CORSTONE1000-2022.11.23 + cp -f systemready-patch/embedded-a/corstone1000/erase_flash/0001-arm-bsp-trusted-firmware-m-corstone1000-Clean-Secure.patch meta-arm + cd meta-arm + git apply 0001-arm-bsp-trusted-firmware-m-corstone1000-Clean-Secure.patch + cd .. + kas build meta-arm/kas/corstone1000-mps3.yml + +Replace the bl1.bin and cs1000.bin files on the SD card with following files: + - The ROM firmware: <_workspace>/build/tmp/deploy/images/corstone1000-mps3/bl1.bin + - The flash image: <_workspace>/build/tmp/deploy/images/corstone1000-mps3/corstone1000-image-corstone1000-mps3.wic.nopt + +Now reboot the board. This step erases the Corstone-1000 SecureEnclave flash +completely, the user should expect following message from TF-M log (can be seen +in ttyUSB1): + +:: + + !!!SECURE FLASH HAS BEEN CLEANED!!! + NOW YOU CAN FLASH THE ACTUAL CORSTONE1000 IMAGE + PLEASE REMOVE THE LATEST ERASE SECURE FLASH PATCH AND BUILD THE IMAGE AGAIN + +Then the user should follow "Building the software stack" to build a clean +software stack and flash the FPGA as normal. And continue the testing. + +Run SystemReady-IR ACS tests +============================= + +ACS image contains two partitions. BOOT partition and RESULT partition. +Following packages are under BOOT partition + + * SCT + * FWTS + * BSA uefi + * BSA linux + * grub + * uefi manual capsule application + +RESULT partition is used to store the test results. +PLEASE MAKE SURE THAT THE RESULT PARTITION IS EMPTY BEFORE YOU START THE TESTING. OTHERWISE THE TEST RESULTS +WILL NOT BE CONSISTENT + +FPGA instructions for ACS image +================================ + +This section describes how the user can build and run Architecture Compliance +Suite (ACS) tests on Corstone-1000. + +First, the user should download the `Arm SystemReady ACS repository `__. +This repository contains the infrastructure to build the Architecture +Compliance Suite (ACS) and the bootable prebuilt images to be used for the +certifications of SystemReady-IR. To download the repository, run command: + +:: + + cd <_workspace> + git clone https://github.com/ARM-software/arm-systemready.git -b v21.09_REL1.0 + +Once the repository is successfully downloaded, the prebuilt ACS live image can be found in: + - ``<_workspace>/arm-systemready/IR/prebuilt_images/v21.07_0.9_BETA/ir_acs_live_image.img.xz`` + +**NOTE**: This prebuilt ACS image includes v5.13 kernel, which doesn't provide +USB driver support for Corstone-1000. The ACS image with newer kernel version +and with full USB support for Corstone-1000 will be available in the next +SystemReady release in this repository. + +Then, the user should prepare a USB stick with ACS image. In the given example here, +we assume the USB device is ``/dev/sdb`` (the user should use ``lsblk`` command to +confirm). Be cautious here and don't confuse your host PC's own hard drive with the +USB drive. Run the following commands to prepare the ACS image in USB stick: + +:: + + cd <_workspace>/arm-systemready/IR/prebuilt_images/v21.07_0.9_BETA + unxz ir_acs_live_image.img.xz + sudo dd if=ir_acs_live_image.img of=/dev/sdb iflag=direct oflag=direct bs=1M status=progress; sync + +Once the USB stick with ACS image is prepared, the user should make sure that +ensure that only the USB stick with the ACS image is connected to the board, +and then boot the board. + +The FPGA will reset multiple times during the test, and it might take approx. 24-36 hours to finish the test. At the end of test, the FPGA host terminal will halt showing a shell prompt. Once test is finished the result can be copied following above instructions. + +FVP instructions for ACS image and run +============================================ + +Download ACS image from: + - ``https://gitlab.arm.com/systemready/acs/arm-systemready/-/tree/linux-5.17-rc7/IR/prebuilt_images/v22.04_1.0-Linux-v5.17-rc7`` + +Use the below command to run the FVP with ACS image support in the +SD card. + +:: + + unxz ${/ir_acs_live_image.img.xz} + + tmux + + <_workspace>/meta-arm/scripts/runfvp <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.fvpconf -- -C board.msd_mmc.p_mmc_file="${/ir_acs_live_image.img}" + +The test results can be fetched using following commands: + +:: + + sudo mkdir /mnt/test + sudo mount -o rw,offset= /ir_acs_live_image.img /mnt/test/ + fdisk -lu /ir_acs_live_image.img + -> Device Start End Sectors Size Type + /ir_acs_live_image_modified.img1 2048 1050622 1048575 512M Microsoft basic data + /ir_acs_live_image_modified.img2 1050624 1153022 102399 50M Microsoft basic data + + -> = 1050624 * 512 (sector size) = 537919488 + +The FVP will reset multiple times during the test, and it might take up to 1 day to finish +the test. At the end of test, the FVP host terminal will halt showing a shell prompt. +Once test is finished, the FVP can be stoped, and result can be copied following above +instructions. + +Common to FVP and FPGA +=========================== + +U-Boot should be able to boot the grub bootloader from +the 1st partition and if grub is not interrupted, tests are executed +automatically in the following sequence: + + - SCT + - UEFI BSA + - FWTS + - BSA Linux + +The results can be fetched from the ``acs_results`` folder in the RESULT partition of the USB stick (FPGA) / SD Card (FVP). + +##################################################### + +Manual capsule update and ESRT checks +--------------------------------------------------------------------- + +The following section describes running manual capsule update with the ``direct`` method. + +The steps described in this section perform manual capsule update and show how to use the ESRT feature +to retrieve the installed capsule details. + +For the following tests two capsules are needed to perform 2 capsule updates. A positive update and a negative update. + +A positive test case capsule which boots the platform correctly until the Linux prompt, and a negative test case with an +incorrect capsule (corrupted or outdated) which fails to boot to the host software. + +Check the "Run SystemReady-IR ACS tests" section above to download and unpack the ACS image file + - ``ir_acs_live_image.img.xz`` + +Download edk2 under <_workspace> : + +:: + + git clone https://github.com/tianocore/edk2.git + +********************* +Generating Capsules +********************* + +The capsule binary size (wic.nopt file) should be less than 15 MB. + +Based on the user's requirement, the user can change the firmware version +number given to ``--fw-version`` option (the version number needs to be >= 1). + +Generating FPGA Capsules +======================== + +:: + + <_workspace>/edk2/BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ + cs1k_cap_mps3_v5 --fw-version 5 --lsv 0 --guid \ + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ + 0 --verbose <_workspace>/build/tmp/deploy/images/corstone1000-mps3/corstone1000-image-corstone1000-mps3.wic.nopt + +:: + + <_workspace>/edk2/BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ + cs1k_cap_mps3_v6 --fw-version 6 --lsv 0 --guid \ + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ + 0 --verbose <_workspace>/build/tmp/deploy/images/corstone1000-mps3/corstone1000-image-corstone1000-mps3.wic.nopt + +Generating FVP Capsules +======================== + +:: + + <_workspace>/edk2/BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ + cs1k_cap_fvp_v6 --fw-version 6 --lsv 0 --guid \ + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ + 0 --verbose <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.wic.nopt + +:: + + <_workspace>/edk2/BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ + cs1k_cap_fvp_v5 --fw-version 5 --lsv 0 --guid \ + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ + 0 --verbose <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.wic.nopt + +********************* +Copying Capsules +********************* + +Copying the FPGA capsules +========================= + +The user should prepare a USB stick as explained in ACS image section (see above). +Place the generated ``cs1k_cap`` files in the root directory of the boot partition +in the USB stick. Note: As we are running the direct method, the ``cs1k_cap`` file +should not be under the EFI/UpdateCapsule directory as this may or may not trigger +the on disk method. + +:: + + sudo cp cs1k_cap_mps3_v6 /BOOT/ + sudo cp cs1k_cap_mps3_v5 /BOOT/ + sync + +Copying the FVP capsules +======================== + +First, mount the IR image: + +:: + + sudo mkdir /mnt/test + sudo mount -o rw,offset=1048576 /ir_acs_live_image.img /mnt/test + +Then, copy the capsules: + +:: + + sudo cp cs1k_cap_fvp_v6 /mnt/test/ + sudo cp cs1k_cap_fvp_v5 /mnt/test/ + sync + +Then, unmount the IR image: + +:: + + sudo umount /mnt/test + +**NOTE:** + +Size of first partition in the image file is calculated in the following way. The data is +just an example and might vary with different ir_acs_live_image.img files. + +:: + + fdisk -lu /ir_acs_live_image.img + -> Device Start End Sectors Size Type + /ir_acs_live_image_modified.img1 2048 1050622 1048575 512M Microsoft basic data + /ir_acs_live_image_modified.img2 1050624 1153022 102399 50M Microsoft basic data + + -> = 2048 * 512 (sector size) = 1048576 + +****************************** +Performing the capsule update +****************************** + +During this section we will be using the capsule with the higher version (cs1k_cap__v6) for the positive scenario +and the capsule with the lower version (cs1k_cap__v5) for the negative scenario. + +Running the FVP with the IR prebuilt image +============================================== + +Run the FVP with the IR prebuilt image: + +:: + + <_workspace>/meta-arm/scripts/runfvp --terminals=xterm <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.fvpconf -- -C "board.msd_mmc.p_mmc_file ${/ir_acs_live_image.img}" + +Running the FPGA with the IR prebuilt image +============================================== + +Insert the prepared USB stick then Power cycle the MPS3 board. + +Executing capsule update for FVP and FPGA +============================================== + +Reach u-boot then interrupt the boot to reach the EFI shell. + +:: + + Press ESC in 4 seconds to skip startup.nsh or any other key to continue. + +Then, type FS0: as shown below: + +:: + + FS0: + +In case of the positive scenario run the update with the higher version capsule as shown below: + +:: + + EFI/BOOT/app/CapsuleApp.efi cs1k_cap__v6 + +After successfully updating the capsule the system will reset. + +In case of the negative scenario run the update with the lower version capsule as shown below: + +:: + + EFI/BOOT/app/CapsuleApp.efi cs1k_cap__v5 + +The command above should fail and in the TF-M logs the following message should appear: + +:: + + ERROR: flash_full_capsule: version error + +Then, reboot manually: + +:: + + Shell> reset + +FPGA: Select Corstone-1000 Linux kernel boot +============================================== + +Remove the USB stick before u-boot is reached so the Corstone-1000 kernel will be detected and used for booting. + +**NOTE:** Otherwise, the execution ends up in the ACS live image. + +FVP: Select Corstone-1000 Linux kernel boot +============================================== + +Interrupt the u-boot shell. + +:: + + Hit any key to stop autoboot: + +Run the following commands in order to run the Corstone-1000 Linux kernel and being able to check the ESRT table. + +**NOTE:** Otherwise, the execution ends up in the ACS live image. + +:: + + $ run retrieve_kernel_load_addr + $ unzip $kernel_addr 0x90000000 + $ loadm 0x90000000 $kernel_addr_r 0xf00000 + $ bootefi $kernel_addr_r $fdtcontroladdr + + +*********************** +Capsule update status +*********************** + +Positive scenario +================= + +In the positive case scenario, the user should see following log in TF-M log, +indicating the new capsule image is successfully applied, and the board boots +correctly. + +:: + + ... + SysTick_Handler: counted = 10, expiring on = 360 + SysTick_Handler: counted = 20, expiring on = 360 + SysTick_Handler: counted = 30, expiring on = 360 + ... + metadata_write: success: active = 1, previous = 0 + accept_full_capsule: exit: fwu state is changed to regular + ... + + +It's possible to check the content of the ESRT table after the system fully boots. + +In the Linux command-line run the following: + +:: + + # cd /sys/firmware/efi/esrt/entries/entry0 + # cat * + + 0x0 + e2bb9c06-70e9-4b14-97a3-5a7913176e3f + 0 + 6 + 0 + 6 + 0 + +.. line-block:: + capsule_flags: 0x0 + fw_class: e2bb9c06-70e9-4b14-97a3-5a7913176e3f + fw_type: 0 + fw_version: 6 + last_attempt_status: 0 + last_attempt_version: 6 + lowest_supported_fw_ver: 0 + + +Negative scenario +================= + +In the negative case scenario (rollback the capsule version), the user should +see appropriate logs in the secure enclave terminal. + +:: + + ... + uefi_capsule_retrieve_images: image 0 at 0xa0000070, size=15654928 + uefi_capsule_retrieve_images: exit + flash_full_capsule: enter: image = 0x0xa0000070, size = 15654928, version = 10 + ERROR: flash_full_capsule: version error + private_metadata_write: enter: boot_index = 1 + private_metadata_write: success + fmp_set_image_info:133 Enter + FMP image update: image id = 0 + FMP image update: status = 1version=11 last_attempt_version=10. + fmp_set_image_info:157 Exit. + corstone1000_fwu_flash_image: exit: ret = -1 + ... + + +If capsule pass initial verification, but fails verifications performed during +boot time, secure enclave will try new images predetermined number of times +(defined in the code), before reverting back to the previous good bank. + +:: + + ... + metadata_write: success: active = 0, previous = 1 + fwu_select_previous: in regular state by choosing previous active bank + ... + +It's possible to check the content of the ESRT table after the system fully boots. + +In the Linux command-line run the following: + +:: + + # cd /sys/firmware/efi/esrt/entries/entry0 + # cat * + + 0x0 + e2bb9c06-70e9-4b14-97a3-5a7913176e3f + 0 + 6 + 1 + 5 + 0 + +.. line-block:: + capsule_flags: 0x0 + fw_class: e2bb9c06-70e9-4b14-97a3-5a7913176e3f + fw_type: 0 + fw_version: 6 + last_attempt_status: 1 + last_attempt_version: 5 + lowest_supported_fw_ver: 0 + +Linux distros tests +---------------------------------- + +*************************************************************************************** +Debian/OpenSUSE install and boot (applicable to FPGA only) +*************************************************************************************** + +To test Linux distro install and boot, the user should prepare two empty USB sticks (minimum size should be 4GB and formatted with FAT32). + +Download one of following Linux distro images: + - Debian installer image: https://cdimage.debian.org/cdimage/weekly-builds/arm64/iso-dvd/ + - OpenSUSE Tumbleweed installer image: http://download.opensuse.org/ports/aarch64/tumbleweed/iso/ + - The user should look for a DVD Snapshot like openSUSE-Tumbleweed-DVD-aarch64-Snapshot-Media.iso + +Once the .iso file is downloaded, the .iso file needs to be flashed to your USB drive. + +In the given example here, we assume the USB device is ``/dev/sdb`` (the user +should use `lsblk` command to confirm). Be cautious here and don't confuse your +host PC's own hard drive with the USB drive. Then copy the contents of an iso +file into the first USB stick, run: + +:: + + sudo dd if= of=/dev/sdb iflag=direct oflag=direct status=progress bs=1M; sync; + +Boot the MSP3 board with the first USB stick connected. Open following minicom sessions: + +:: + + sudo picocom -b 115200 /dev/ttyUSB0 # in one terminal + sudo picocom -b 115200 /dev/ttyUSB2 # in another terminal. + +Now plug in the second USB stick (once installation screen is visible), the distro installation process will start. The installation prompt can be seen in ttyUSB2. If installer does not start, please try to reboot the board with both USB sticks connected and repeat the process. + +**NOTE:** Due to the performance limitation of Corstone-1000 MPS3 FPGA, the +distro installation process can take up to 24 hours to complete. + +Once installation is complete, unplug the first USB stick and reboot the board. +After successfully installing and booting the Linux distro, the user should see +a login prompt: + +:: + + debian login: + +Login with the username root. + +**NOTE:** The Debian installer has a known issue "Install the GRUB bootloader - unable to install " and these are the steps to +follow on the subsequent popups to solve the issue during the installation: + +1. Select "Continue", then "Continue" again on the next popup +2. Scroll down and select "Execute a shell" +3. Select "Continue" +4. Enter the following command: + +:: + + in-target grub-install --no-nvram --force-extra-removable + +5. Enter the following command: + +:: + + in-target update-grub + +6. Enter the following command: + +:: + + exit + +7. Select "Continue without boot loader", then select "Continue" on the next popup +8. At this stage, the installation should proceed as normal. + +*************************************************************************************** +OpenSUSE Raw image install and boot (applicable to FVP only) +*************************************************************************************** + +Steps to download openSUSE Tumbleweed raw image: + - Go to: http://download.opensuse.org/ports/aarch64/tumbleweed/appliances/ + - The user should look for a Tumbleweed-ARM-JeOS-efi.aarch64-* Snapshot, for example, ``openSUSE-Tumbleweed-ARM-JeOS-efi.aarch64--Snapshot.raw.xz`` + +Once the .raw.xz file is downloaded, the raw image file needs to be extracted: + +:: + + unxz + + +The above command will generate a file ending with extension .raw image. Now, use the following command +to run FVP with raw image installation process. + +:: + +<_workspace>/meta-arm/scripts/runfvp --terminals=xterm <_workspace>/build/tmp/deploy/images/corstone1000-fvp/corstone1000-image-corstone1000-fvp.fvpconf -- -C board.msd_mmc.p_mmc_file="${openSUSE raw image file path}" + +After successfully installing and booting the Linux distro, the user should see +a openSUSE login prompt. + +:: + + localhost login: + +Login with the username 'root' and password 'linux'. + +PSA API tests +---------------------- + +*************************************************************************************** +Run PSA API test commands (applicable to both FPGA and FVP) +*************************************************************************************** + +When running PSA API test commands (aka PSA Arch Tests) on MPS3 FPGA, the user should make sure there is no +USB stick connected to the board. Power on the board and boot the board to +Linux. Then, the user should follow the steps below to run the tests. + +When running the tests on the Corstone-1000 FVP, the user should follow the +instructions in `Running the software on FVP`_ section to boot Linux in FVP +host_terminal_0, and login using the username ``root``. + +First, load FF-A TEE kernel module: + +:: + + insmod /lib/modules/5.19.14-yocto-standard/extra/arm-ffa-tee.ko + +Then, check whether the FF-A TEE driver is loaded correctly by using the following command: + +:: + + cat /proc/modules | grep arm_ffa_tee + +The output should be: + +:: + + arm_ffa_tee 16384 - - Live 0xffffffc0004f0000 (O) + +Now, run the PSA API tests in the following order: + +:: + + psa-iat-api-test + psa-crypto-api-test + psa-its-api-test + psa-ps-api-test + +External System tests +----------------------------------- + +*************************************************************************************** +Running the External System test command (systems-comms-tests) +*************************************************************************************** + +Test 1: Releasing the External System out of reset +=================================================== + +Run this command in the Linux command-line: + +:: + + systems-comms-tests 1 + +The output on the External System terminal should be: + +:: + + ___ ___ + | / __| + |=== \___ + |___ |___/ + External System Cortex-M3 Processor + Running RTX RTOS + v0.1.0_2022-10-19_16-41-32-8c9dca7 + MHUv2 module 'MHU0_H' started + MHUv2 module 'MHU1_H' started + MHUv2 module 'MHU0_SE' started + MHUv2 module 'MHU1_SE' started + +Test 2: Communication +============================================= + +Test 2 releases the External System out of reset if not already done. Then, it performs communication between host and External System. + +After running Test 1, run this command in the Linux command-line: + +:: + + systems-comms-tests 2 + +Additional output on the External System terminal will be printed: + +:: + + MHUv2: Message from 'MHU0_H': 0xabcdef1 + Received 'abcdef1' From Host MHU0 + CMD: Increment and return to sender... + MHUv2: Message from 'MHU1_H': 0xabcdef1 + Received 'abcdef1' From Host MHU1 + CMD: Increment and return to sender... + +When running Test 2 the first, Test 1 will be run in the background. + +The output on the External System terminal should be: + +:: + + ___ ___ + | / __| + |=== \___ + |___ |___/ + External System Cortex-M3 Processor + Running RTX RTOS + v0.1.0_2022-10-19_16-41-32-8c9dca7 + MHUv2 module 'MHU0_H' started + MHUv2 module 'MHU1_H' started + MHUv2 module 'MHU0_SE' started + MHUv2 module 'MHU1_SE' started + MHUv2: Message from 'MHU0_H': 0xabcdef1 + Received 'abcdef1' From Host MHU0 + CMD: Increment and return to sender... + MHUv2: Message from 'MHU1_H': 0xabcdef1 + Received 'abcdef1' From Host MHU1 + CMD: Increment and return to sender... + +The output on the Host terminal should be: + +:: + + Received abcdf00 from es0mhu0 + Received abcdf00 from es0mhu1 + + +Tests results +----------------------------------- + +As a reference for the end user, reports for various tests for `Corstone-1000 software (CORSTONE1000-2022.11.23) `__ +can be found in `here `__. + +Running the software on FVP on Windows +--------------------------------------------------------------- + +If the user needs to run the Corstone-1000 software on FVP on Windows. The user +should follow the build instructions in this document to build on Linux host +PC, and copy the output binaries to the Windows PC where the FVP is located, +and launch the FVP binary. + +-------------- + +*Copyright (c) 2022, Arm Limited. All rights reserved.* + +.. _Arm Ecosystem FVPs: https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps diff --git a/meta-arm/meta-arm-bsp/documentation/corstone500.md b/meta-arm/meta-arm-bsp/documentation/corstone500.md new file mode 100644 index 000000000000..0f019611b728 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/corstone500.md @@ -0,0 +1,28 @@ +# Corstone-500 Platform Support in meta-arm-bsp + +## Howto Build and Run + +### Configuration: + +Use the kas + +### Build: + +``bash$ kas build kas/corstone500.yml + +### Run: + +Building using kas should have fetch the Fixed Virtual Platform for this +platform and installed at: + +build/tmp/sysroots-components/x86_64/fvp-corstone500-native/usr/bin/./FVP_Corstone-500 + +with this in place is possible to launch the FVP using the runfvp inside the +scripts directory: + +cd scripts + +./runfvp ../build/tmp/deploy/images/corstone500/core-image-minimal-corstone500.fvpconf --console + +this will output the console in the launching terminal + diff --git a/meta-arm/meta-arm-bsp/documentation/fvp-base-arm32.md b/meta-arm/meta-arm-bsp/documentation/fvp-base-arm32.md new file mode 100644 index 000000000000..141e61f3ab33 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/fvp-base-arm32.md @@ -0,0 +1,30 @@ +# Armv8-A Base Platform FVP (32-bit) Support in meta-arm-bsp + +## Howto Build and Run + +### Configuration: +In the local.conf file, `MACHINE` should be set: +``` +MACHINE = "fvp-base-arm32" +``` + +### Build: +``` +$ bitbake core-image-base +``` + +### Run: +The `fvp-base` machine has support for the `runfvp` script, so running is simple: + +``` +$ runfvp tmp/deploy/images/fvp-base-arm32/core-image-base-fvp-base-arm32.fvpconf +``` +## Devices supported in the kernel +- serial +- virtio disk +- network +- watchdog +- rtc + +## Devices not supported or not functional +None diff --git a/meta-arm/meta-arm-bsp/documentation/fvp-base.md b/meta-arm/meta-arm-bsp/documentation/fvp-base.md new file mode 100644 index 000000000000..7eda8d34face --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/fvp-base.md @@ -0,0 +1,30 @@ +# Armv8-A Base Platform FVP Support in meta-arm-bsp + +## Howto Build and Run + +### Configuration: +In the local.conf file, `MACHINE` should be set: +``` +MACHINE = "fvp-base" +``` + +### Build: +``` +$ bitbake core-image-base +``` + +### Run: +The `fvp-base` machine has support for the `runfvp` script, so running is simple: + +``` +$ runfvp tmp/deploy/images/fvp-base/core-image-base-fvp-base.fvpconf +``` +## Devices supported in the kernel +- serial +- virtio disk +- network +- watchdog +- rtc + +## Devices not supported or not functional +None diff --git a/meta-arm/meta-arm-bsp/documentation/fvp-baser-aemv8r64.md b/meta-arm/meta-arm-bsp/documentation/fvp-baser-aemv8r64.md new file mode 100644 index 000000000000..e29aad34d6aa --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/fvp-baser-aemv8r64.md @@ -0,0 +1,264 @@ +Armv8-R AArch64 AEM FVP Support in meta-arm-bsp +=============================================== + +Overview +-------- + +Fixed Virtual Platforms (FVP) are complete simulations of an Arm system, +including processor, memory and peripherals. These are set out in a +"programmer's view", which gives you a comprehensive model on which to build +and test your software. + +The Armv8-R AEM FVP is a free of charge Armv8-R Fixed Virtual Platform. It +supports the latest Armv8-R feature set. + +This BSP implements a reference stack for the AArch64 support in the R-class +first announced with the Cortex-R82 processor: +https://developer.arm.com/ip-products/processors/cortex-r/cortex-r82 + +Fast Models Fixed Virtual Platforms (FVP) Reference Guide: +https://developer.arm.com/docs/100966/latest + + +BSP Support +----------- + +The fvp-baser-aemv8r64 Yocto MACHINE supports the following BSP components, +where either a standard or Real-Time Linux kernel (PREEMPT\_RT) can be built +and run: + + - FVP_Base_AEMv8R: v11.20.15 + - boot-wrapper-aarch64: provides PSCI support + - U-Boot: v2022.07 - provides UEFI services + - Linux kernel: linux-yocto-5.15 + - Linux kernel with PREEMPT\_RT support: linux-yocto-rt-5.15 + +Note that the Real-Time Linux kernel (PREEMPT\_RT) does not use the real-time +architectural extensions of the Armv8-R feature set. + +High-Level Architecture +----------------------- + +The diagram below shows the current boot flow: + + +---------------------------------------------------------------+ + | Linux kernel | + +---------------------------------------------------------------+ + /|\ /|\ + | | + | UEFI services | + | PSCI services | + \|/ | + +----------------+ | S-EL1 + ----| U-Boot |------------------------------|----------- + +----------------+ | S-EL2 + /|\ | + | | + | | + | | + +--------------------------------------------------\|/----------+ + | +----------------+ +----------------+ | + | boot-wrapper-aarch64 | Device tree | | PSCI handler | | + | +----------------+ +----------------+ | + +---------------------------------------------------------------+ + + +The firmware binary (generated as `linux-system.axf`) includes +boot-wrapper-aarch64, the flattened device tree and U-Boot. U-Boot is configured +to automatically detect a virtio block device and boot the UEFI payload at the +path `/efi/boot/bootaa64.efi`. Using the standard build, the first partition +contains a Grub image at this path, which boots the Linux kernel at `/Image` on +the same partition. The second partition of the image contains the Linux root +file system. + +There is no EL3 or non-secure world in the Armv8-R AArch64 architecture, so the +reset vector starts boot-wrapper-aarch64 at S-EL2. Boot-wrapper-aarch64 is +compiled with the `--enable-keep-el` flag, which causes it to boot U-Boot at +S-EL2 too. U-Boot is compiled with the `CONFIG_ARMV8_SWITCH_TO_EL1` flag, which +causes it to switch to S-EL1 before booting Linux. + +The bundled device tree is passed to U-Boot via register x0. U-Boot passes the +same device tree to Linux via the UEFI system table. + +Power state management is provided by PSCI services in boot-wrapper-aarch64. +Linux accesses the PSCI handler via HVC calls to S-EL2. U-Boot has been patched +to prevent it from overriding the exception vector at S-EL2. The PSCI handler +memory region is added to a `/memreserve/` node in the device tree. + +Please note that the final firmware architecture for the fvp-baser-aemv8r64 is +not yet stabilized. The patches in this layer are provided for development and +evaluation purposes only, and should not be used in production firmware. + +Quick start: Howto Build and Run +-------------------------------- + +### Host environment setup +The following instructions have been tested on hosts running Ubuntu 18.04 and +Ubuntu 20.04. +Install the required packages for the build host: +https://docs.yoctoproject.org/singleindex.html#required-packages-for-the-build-host + +Kas is a setup tool for bitbake based projects. The minimal supported version +is 3.0, install it like so: + + pip3 install --user --upgrade kas + +For more details on kas, see https://kas.readthedocs.io/. + +To build the images for the fvp-baser-aemv8r64 machine, you also need to accept +the EULA at +https://developer.arm.com/downloads/-/arm-ecosystem-fvps/eula +by setting the following environment variable: + + FVP_BASE_R_ARM_EULA_ACCEPT="True" + +**Note:** The host machine should have at least 50 GBytes of free disk space +for the next steps to work correctly. + +### Fetch sources +To fetch and build the ongoing development of the software stack follow the +instructions on this document. + +To fetch and build the version 1 (single core) find instructions at https://community.arm.com/developer/tools-software/oss-platforms/w/docs/633/release-1-single-core + +To fetch and build the version 2 (linux smp) find instructions at https://community.arm.com/developer/tools-software/oss-platforms/w/docs/634/release-2---smp + +Fetch the meta-arm repository into a build directory: + + mkdir -p ~/fvp-baser-aemv8r64-build + cd ~/fvp-baser-aemv8r64-build + git clone https://git.yoctoproject.org/git/meta-arm + + +### Build +Building with the standard Linux kernel: + + cd ~/fvp-baser-aemv8r64-build + export FVP_BASE_R_ARM_EULA_ACCEPT="True" + kas build meta-arm/kas/fvp-baser-aemv8r64-bsp.yml + +Building with the Real-Time Linux kernel (PREEMPT\_RT): + + cd ~/fvp-baser-aemv8r64-build + export FVP_BASE_R_ARM_EULA_ACCEPT="True" + kas build meta-arm/kas/fvp-baser-aemv8r64-rt-bsp.yml + +### Run +To run an image after the build is done with the standard Linux kernel: + + kas shell --keep-config-unchanged \ + meta-arm/kas/fvp-baser-aemv8r64-bsp.yml \ + --command "../layers/meta-arm/scripts/runfvp \ + --console " + +To run an image after the build is done with the Real-Time Linux kernel +(PREEMPT\_RT): + + kas shell --keep-config-unchanged \ + meta-arm/kas/fvp-baser-aemv8r64-rt-bsp.yml \ + --command "../layers/meta-arm/scripts/runfvp \ + --console " + +**Note:** The terminal console login is `root` without password. + +To finish the fvp emulation, you need to close the telnet session: + + - Escape to telnet console with ``ctrl+]``. + - Run ``quit`` to close the session. + +### Networking +The FVP is configured by default to use "user-mode networking", which simulates +an IP router and DHCP server to avoid additional host dependencies and +networking configuration. Outbound connections work automatically, e.g. by +running: + + wget www.arm.com + +Inbound connections require an explicit port mapping from the host. By default, +port 8022 on the host is mapped to port 22 on the FVP, so that the following +command will connect to an ssh server running on the FVP: + + ssh root@localhost -p 8022 + +Note that user-mode networking does not support ICMP, so `ping` will not work. +For more information about user-mode networking, please see +https://developer.arm.com/documentation/100964/1117/Introduction-to-Fast-Models/User-mode-networking?lang=en + +### File sharing between host and fvp +It is possible to share a directory between the host machine and the fvp using +the virtio P9 device component included in the kernel. To do so, create a +directory to be mounted from the host machine: + + mkdir /path/to/host-mount-dir + +Then, add the following parameter containing the path to the directory when +launching the model: + + --parameter 'bp.virtiop9device.root_path=/path/to/host-mount-dir' + +e.g. for the standard Linux kernel: + + kas shell --keep-config-unchanged \ + meta-arm/kas/fvp-baser-aemv8r64-bsp.yml \ + --command "../layers/meta-arm/scripts/runfvp \ + --console -- --parameter \ + 'bp.virtiop9device.root_path=/path/to/host-mount-dir'" + +Once you are logged into the fvp, the host directory can be mounted in a +directory on the model using the following command: + + mount -t 9p -o trans=virtio,version=9p2000.L FM /path/to/fvp-mount-dir + +Devices supported in the kernel +------------------------------- + +- serial +- virtio 9p +- virtio disk +- virtio network +- virtio rng +- watchdog +- rtc + +Known Issues and Limitations +---------------------------- + +- Only PSCI CPU\_ON and CPU\_OFF functions are supported +- Linux kernel does not support booting from secure EL2 on Armv8-R AArch64 +- Linux KVM does not support Armv8-R AArch64 +- Device DMA memory cache-coherence issue: the FVP `cache_state_modelled` + parameter will affect the cache coherence behavior of peripherals’ DMA. When + users set `cache_state_modelled=1`, they also have to set + `cci400.force_on_from_start=1` to force the FVP to enable snooping on upstream + ports. + +Change Log +---------- +- Enabled the ability for U-Boot to apply device tree overlays +- Fixed bug in U-Boot that caused changes to the `memory` node in the device + tree to be ignored. +- Added boot-wrapper-aarch64 support for booting SMP payloads at S-EL2. +- Enabled testimage support by default. +- Added virtio\_rng to improve random number generation. +- Added U-Boot v2022.01 for UEFI support. +- Updated Linux kernel version from 5.14 to 5.15 for both standard and + Real-Time (PREEMPT\_RT) builds. +- Updated boot-wrapper-aarch64 revision and added support for booting U-Boot. +- Included boot-wrapper-aarch64 PSCI services in `/memreserve/` region. +- Fixed the counter frequency initialization in boot-wrapper-aarch64. +- Configured the FVP to use the default RAM size of 4 Gb +- Fixed PL011 and SP805 register sizes in the device tree. +- Added virtio\_net User Networking mode by default and removed instructions + about tap networking setup. +- Updated Linux kernel version from 5.10 to 5.14 for both standard and + Real-Time (PREEMPT\_RT) builds. +- Enabled SMP support via boot-wrapper-aarch64 providing the PSCI CPU\_ON and + CPU\_OFF functions. +- Introduced Armv8-R64 compiler flags. +- Added Linux PREEMPT\_RT support via linux-yocto-rt-5.10. +- Added support for file sharing with the host machine using Virtio P9. +- Added support for runfvp. +- Added performance event support (PMU) in the Linux device tree. +- Introduced the fvp-baser-aemv8r64 machine and its BSP composed of + boot-wrapper-aarch64 and linux-yocto-5.10 supporting serial, virtio disk, + virtio network, watchdog and rtc. diff --git a/meta-arm/meta-arm-bsp/documentation/juno.md b/meta-arm/meta-arm-bsp/documentation/juno.md new file mode 100644 index 000000000000..69e56bc22bb3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/juno.md @@ -0,0 +1,75 @@ +# Juno Development Platform Support in meta-arm-bsp + +## Howto Build and Run + +### Configuration: +In the local.conf file, MACHINE should be set as follow: +MACHINE ?= "juno" + +Juno is using a USB hard drive for root filesystem by default. The distribution +used must have ```usbhost``` and ```usbgadget``` in DISTRO_FEATURES (this is +the case in poky distribution). + +### Build: +```bash$ bitbake core-image-minimal``` + +### Update Juno SD card: + +The SD card content is generated during the build here: +tmp/deploy/images/juno/firmware-image-juno.tar.gz + +Its content must be written on the Juno firmware SD card. +To do this: +- insert the sdcard of the Juno in an SD card reader and mount it: +```bash$ sudo mount /dev/sdx1 /mnt``` +(replace sdx by the device of the SD card) + +- erase its content and put the new one: +```bash$ sudo rm -rf /mnt/*``` +```bash$ sudo tar --no-same-owner -xzf tmp/deploy/images/juno/firmware-image-juno.tar.gz -C /mnt/``` +```bash$ sudo umount /mnt``` + +- reinsert the SD card in the Juno board + +### Create an USB hard drive: + +Linux root file system should be stored on the second partition of an USB +drive that must be plugged on the Juno Platform. + +This partition should be initialized with the content of the filesystem +generated by yocto that you can find here: +tmp/deploy/images/juno/core-image-minimal-juno.tar.bz2 + +To do this +- Format a USB disk, create two primary partitions (ext4). +- mount the secondary partition +- untar tmp/deploy/images/juno/core-image-minimal-juno.tar.bz2 on to the + secondary partition. + +### Run: +You must insert the SD card and the USB drive and power-on the Juno board. +The console should be available on the second serial line: +screen -L /dev/tty.usbserial 115200 + +On the first boot the images will be flashed which can take some time. + +## Devices supported in the kernel +- serial +- usb +- network +- watchdog +- rtc +- mmc + +### Untested: +- i2c +- dma +- pci +- sata +- sound + +## Devices not supported or not functional +- framebuffer: not functional + The HDMI is not properly detected. +- GPU (no user land libraries). + The mali-midgard-kernel can be used to have a kernel driver diff --git a/meta-arm/meta-arm-bsp/documentation/musca-b1.md b/meta-arm/meta-arm-bsp/documentation/musca-b1.md new file mode 100644 index 000000000000..a7439e53eedb --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/musca-b1.md @@ -0,0 +1,15 @@ +# Musca B1 + +## Overview +For a description of the hardware, go to +https://developer.arm.com/tools-and-software/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board + +For emulated hardware, go to +https://www.qemu.org/docs/master/system/arm/musca.html + +## Building +In the local.conf file, MACHINE should be set as follows: +MACHINE ?= "musca-b1" + +To build the trusted firmware-m: +```bash$ bitbake trusted-firmware-m``` diff --git a/meta-arm/meta-arm-bsp/documentation/n1sdp.md b/meta-arm/meta-arm-bsp/documentation/n1sdp.md new file mode 100644 index 000000000000..d8661a5c3484 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/n1sdp.md @@ -0,0 +1,78 @@ +# N1SDP Development Platform Support in meta-arm-bsp + +## Overview +The N1SDP provides access to the Arm Neoverse N1 SoC. The N1SDP enables software development for key enterprise technology +and general Arm software development. The N1SDP consists of the N1 board containing the N1 SoC. +The N1 SoC contains two dual-core Arm Neoverse N1 processor clusters. + +The system demonstrates Arm technology in the context of Cache-Coherent Interconnect for Accelerators (CCIX) protocol by: + +- Running coherent traffic between the N1 SoC and an accelerator card. +- Coherent communication between two N1 SoCs. +- Enabling development of CCIX-enabled FPGA accelerators. + +Further information on N1SDP can be found at +https://community.arm.com/developer/tools-software/oss-platforms/w/docs/458/neoverse-n1-sdp + +## Configuration: +In the local.conf file, MACHINE should be set as follow: +MACHINE ?= "n1sdp" + +## Building +```bash$ bitbake core-image-minimal``` + +## Running + +# Update Firmware on SD card: + +(*) To use n1sdp board in single chip mode, flash: + n1sdp-board-firmware_primary.tar.gz firmware. + +(*) To use n1sdp board in multi chip mode, flash: + n1sdp-board-firmware_primary.tar.gz firmware to primary board, + n1sdp-board-firmware_secondary.tar.gz firmware to secondary board. + +The SD card content is generated during the build here: + tmp/deploy/images/n1sdp/n1sdp-board-firmware_primary.tar.gz + tmp/deploy/images/n1sdp/n1sdp-board-firmware_secondary.tar.gz + + +Its content must be written on the N1SDP firmware SD card. +To do this: +- insert the sdcard of the N1SDP in an SD card reader and mount it: +```bash$ sudo mount /dev/sdx1 /mnt``` +(replace sdx by the device of the SD card) + +- erase its content and put the new one: +```bash$ sudo rm -rf /mnt/*``` +```bash$ sudo tar --no-same-owner -xzf tmp/deploy/images/n1sdp/n1sdp-board-firmware_primary.tar.gz -C /mnt/``` +```bash$ sudo umount /mnt``` + +- reinsert the SD card in the N1SDP board + +Firmware tarball contains iofpga configuration files, scp and uefi binaries. + +**NOTE**: +If the N1SDP board was manufactured after November 2019 (Serial Number greater +than 36253xxx), a different PMIC firmware image must be used to prevent +potential damage to the board. More details can be found in [1]. +The `MB/HBI0316A/io_v123f.txt` file located in the microSD needs to be updated. +To update it, set the PMIC image (300k_8c2.bin) to be used in the newer models +by running the following commands on your host PC: + + $ sudo umount /dev/sdx1 + $ sudo mount /dev/sdx1 /mnt + $ sudo sed -i '/^MBPMIC: pms_0V85.bin/s/^/;/g' /mnt/MB/HBI0316A/io_v123f.txt + $ sudo sed -i '/^;MBPMIC: 300k_8c2.bin/s/^;//g' /mnt/MB/HBI0316A/io_v123f.txt + $ sudo umount /mnt + +# Prepare an USB hard drive: + +Grub boot partition is placed on first partition of the *.wic image, +Linux root file system is placed on the second partition of the *.wic image: + tmp/deploy/images/n1sdp/core-image-minimal-n1sdp.wic + +This *.wic image should be copied to USB stick with simple dd call. + + +[1]: https://community.arm.com/developer/tools-software/oss-platforms/w/docs/604/notice-potential-damage-to-n1sdp-boards-if-using-latest-firmware-release diff --git a/meta-arm/meta-arm-bsp/documentation/requirements.txt b/meta-arm/meta-arm-bsp/documentation/requirements.txt new file mode 100644 index 000000000000..b82e5e071a77 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/requirements.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2022, Arm Limited. +# +# SPDX-License-Identifier: MIT + +# Read The Docs specific +jinja2==3.1.1 + +# Required to build the documentation +sphinx==4.5.0 +sphinx_rtd_theme==1.0.0 +sphinx-copybutton==0.5.0 +docutils==0.17.1 diff --git a/meta-arm/meta-arm-bsp/documentation/tc1.md b/meta-arm/meta-arm-bsp/documentation/tc1.md new file mode 100644 index 000000000000..464f77ee0a42 --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/tc1.md @@ -0,0 +1,32 @@ +# TC1 Platform Support in meta-arm-bsp + +## Overview +The Total Compute platform provides an envelope for all of Arm's latest IP and +software solutions, optimised to work together. Further information can be +found on the Total Compute community page: +https://community.arm.com/developer/tools-software/oss-platforms/w/docs/606/total-compute + +The user guide for TC1 platform with detailed instructions for +syncing and building the source code and running on TC1 Fixed Virtual Platform +for poky and android distributions is available at: +https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/tree/docs/tc1/user-guide.rst + +## Building +In the local.conf file, MACHINE should be set as follows: +MACHINE = "tc1" + +To build the required binaries for tc1, run the commmand: +```bash$ bitbake tc-artifacts-image``` + +Trusted-firmware-a is the final component to be built with the rest of the +components dependent of it, therefore building tc-artifacts-image which depends +on trusted-firmware-a will build all the required binaries. + +## Running +To run the produced binaries in a TC1 Fixed Virtual Platform please get +the run scripts at: +https://git.linaro.org/landing-teams/working/arm/model-scripts.git/ + +and follow the instructions in the user-guide.rst available in: +https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/tree/docs/tc1/user-guide.rst + diff --git a/meta-arm/meta-arm-bsp/documentation/template.md b/meta-arm/meta-arm-bsp/documentation/template.md new file mode 100644 index 000000000000..7beeb5950cad --- /dev/null +++ b/meta-arm/meta-arm-bsp/documentation/template.md @@ -0,0 +1,19 @@ +# *Hardware Name* + +## Overview + +*Brief summary of the hardware* + +*Link to reference documentation* + +## Building + +*Any special steps required to build successfully beyond setting MACHINE* + +*For example: corstone700 needs DISTRO=poky-tiny, musca only supports TF-M* + +## Running + +*A summary of how to deploy or execute the image* + +*For example, an overview of the N1SDP SD structure, or FVP arguments* diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc new file mode 100644 index 000000000000..8ffa0aa2e07f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc @@ -0,0 +1,36 @@ +COMPATIBLE_MACHINE = "fvp-baser-aemv8r64" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files/${MACHINE}:" +SRC_URI:append = " \ + file://0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch \ + file://0002-aarch64-Prepare-for-EL1-booting.patch \ + file://0003-aarch64-Prepare-for-lower-EL-booting.patch \ + file://0004-gic-v3-Prepare-for-gicv3-with-EL2.patch \ + file://0005-aarch64-Prepare-for-booting-with-EL2.patch \ + file://0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch \ + file://0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch \ + file://0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch \ + file://0009-lds-Mark-the-mem-range.patch \ + file://0010-common-Introduce-the-libfdt.patch \ + file://0011-common-Add-essential-libc-functions.patch \ + file://0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch \ + file://0013-platform-Add-print_hex-func.patch \ + file://0014-common-Add-mem-usage-to-memreserve.patch \ + file://0015-boot-Add-the-enable-keep-el-compile-option.patch \ + file://0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch \ + file://0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch \ + file://0018-PSCI-Add-function-call-entry-point.patch \ + file://0019-lds-Rearrange-and-mark-the-sections.patch \ + file://0020-common-Provide-firmware-info-using-libfdt.patch \ + file://0021-boot-Enable-firmware-node-initialization.patch \ + " + +BOOT_WRAPPER_AARCH64_CMDLINE = "\ +earlycon console=ttyAMA0 loglevel=8 rootfstype=ext4 root=/dev/vda1 rw" + +EXTRA_OECONF += "--enable-psci=hvc --enable-keep-el" + +TUNE_CCARGS = "" + +BOOT_WRAPPER_AARCH64_KERNEL = "u-boot.bin" +do_deploy[depends] += "u-boot:do_deploy" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend new file mode 100644 index 000000000000..c2e7e6e3ffb7 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend @@ -0,0 +1,4 @@ +MACHINE_BOOT_WRAPPER_AARCH64_REQUIRE ?= "" +MACHINE_BOOT_WRAPPER_AARCH64_REQUIRE:fvp-baser-aemv8r64 ?= "boot-wrapper-aarch64-fvp-baser-aemv8r64.inc" + +require ${MACHINE_BOOT_WRAPPER_AARCH64_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch new file mode 100644 index 000000000000..566070a4f35d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch @@ -0,0 +1,135 @@ +From 3e7cfbe39a2a053d2a6b0d928cc172ed9d1c6da8 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Rename labels and prepare for lower EL booting + +Prepare for booting from lower EL. Rename *_el3 relavant labels with +*_el_max and *_no_el3 with *_keep_el. Since the original _no_el3 means +"We neither do init sequence at this highest EL nor drop to lower EL +when entering to kernel", we rename it with _keep_el to make it more +clear for lower EL initialisation. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +--- + arch/aarch64/boot.S | 28 ++++++++++++++++++++-------- + arch/aarch64/psci.S | 9 +++++---- + arch/aarch64/spin.S | 4 ++-- + 3 files changed, 27 insertions(+), 14 deletions(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 27ba449..84e1646 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -21,18 +21,30 @@ ASM_FUNC(_start) + + /* + * EL3 initialisation ++ * Boot sequence ++ * If CurrentEL == EL3, then goto EL3 initialisation and drop to ++ * lower EL before entering the kernel. ++ * Else, no initialisation and keep the current EL before ++ * entering the kernel. + */ + mrs x0, CurrentEL + cmp x0, #CURRENTEL_EL3 +- b.eq 1f ++ b.eq el3_init + ++ /* ++ * We stay in the current EL for entering the kernel ++ */ + mov w0, #1 +- ldr x1, =flag_no_el3 ++ ldr x1, =flag_keep_el + str w0, [x1] + +- b start_no_el3 ++ b start_keep_el + +-1: mov x0, #0x30 // RES1 ++ /* ++ * EL3 initialisation ++ */ ++el3_init: ++ mov x0, #0x30 // RES1 + orr x0, x0, #(1 << 0) // Non-secure EL1 + orr x0, x0, #(1 << 8) // HVC enable + +@@ -124,7 +136,7 @@ ASM_FUNC(_start) + + bl gic_secure_init + +- b start_el3 ++ b start_el_max + + err_invalid_id: + b . +@@ -151,7 +163,7 @@ ASM_FUNC(jump_kernel) + bl find_logical_id + bl setup_stack // Reset stack pointer + +- ldr w0, flag_no_el3 ++ ldr w0, flag_keep_el + cmp w0, #0 // Prepare Z flag + + mov x0, x20 +@@ -160,7 +172,7 @@ ASM_FUNC(jump_kernel) + mov x3, x23 + + b.eq 1f +- br x19 // No EL3 ++ br x19 // Keep current EL + + 1: mov x4, #SPSR_KERNEL + +@@ -178,5 +190,5 @@ ASM_FUNC(jump_kernel) + + .data + .align 3 +-flag_no_el3: ++flag_keep_el: + .long 0 +diff --git a/arch/aarch64/psci.S b/arch/aarch64/psci.S +index 8bd224b..7b8919a 100644 +--- a/arch/aarch64/psci.S ++++ b/arch/aarch64/psci.S +@@ -79,7 +79,7 @@ smc_exit: + ldp x18, x19, [sp], #16 + eret + +-ASM_FUNC(start_el3) ++ASM_FUNC(start_el_max) + ldr x0, =vector + bl setup_vector + +@@ -89,10 +89,11 @@ ASM_FUNC(start_el3) + b psci_first_spin + + /* +- * This PSCI implementation requires EL3. Without EL3 we'll only boot the +- * primary cpu, all others will be trapped in an infinite loop. ++ * This PSCI implementation requires the highest EL(EL3 or Armv8-R EL2). ++ * Without the highest EL, we'll only boot the primary cpu, all othersr ++ * will be trapped in an infinite loop. + */ +-ASM_FUNC(start_no_el3) ++ASM_FUNC(start_keep_el) + cpuid x0, x1 + bl find_logical_id + cbz x0, psci_first_spin +diff --git a/arch/aarch64/spin.S b/arch/aarch64/spin.S +index 1ea1c0b..bfb1d47 100644 +--- a/arch/aarch64/spin.S ++++ b/arch/aarch64/spin.S +@@ -12,8 +12,8 @@ + + .text + +-ASM_FUNC(start_el3) +-ASM_FUNC(start_no_el3) ++ASM_FUNC(start_el_max) ++ASM_FUNC(start_keep_el) + cpuid x0, x1 + bl find_logical_id + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch new file mode 100644 index 000000000000..46447b8f288b --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch @@ -0,0 +1,48 @@ +From 26f9b5354c2de9cc052531096ff92b04c3a3846f Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Prepare for EL1 booting + +When booting from EL1, add a check and skip the init of +sctlr_el2 in jump_kernel + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +Reviewed-by: Andre Przywara +--- + arch/aarch64/boot.S | 6 +++++- + arch/aarch64/include/asm/cpu.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 84e1646..b589744 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -156,10 +156,14 @@ ASM_FUNC(jump_kernel) + ldr x0, =SCTLR_EL1_KERNEL + msr sctlr_el1, x0 + ++ mrs x0, CurrentEL ++ cmp x0, #CURRENTEL_EL2 ++ b.lt 1f ++ + ldr x0, =SCTLR_EL2_KERNEL + msr sctlr_el2, x0 + +- cpuid x0, x1 ++1: cpuid x0, x1 + bl find_logical_id + bl setup_stack // Reset stack pointer + +diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h +index 63eb1c3..b1003f4 100644 +--- a/arch/aarch64/include/asm/cpu.h ++++ b/arch/aarch64/include/asm/cpu.h +@@ -11,6 +11,7 @@ + + #define MPIDR_ID_BITS 0xff00ffffff + ++#define CURRENTEL_EL2 (2 << 2) + #define CURRENTEL_EL3 (3 << 2) + + /* diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch new file mode 100644 index 000000000000..db81355b66c9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch @@ -0,0 +1,55 @@ +From ce628de7699dd6401ddf713efaa49872e2733619 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Prepare for lower EL booting + +Save SPSR_KERNEL into spsr_to_elx during el3_init. +The jump_kernel will load spsr_to_elx into spsr_el3. + +This change will make it easier to control whether drop to lower EL +before jumping to the kernel. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +Reviewed-by: Andre Przywara +--- + arch/aarch64/boot.S | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index b589744..6b45afc 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -130,7 +130,16 @@ el3_init: + mov x0, #ZCR_EL3_LEN_MASK // SVE: Enable full vector len + msr ZCR_EL3, x0 // for EL2. + +-1: ++ /* ++ * Save SPSR_KERNEL into spsr_to_elx. ++ * The jump_kernel will load spsr_to_elx into spsr_el3 ++ */ ++1: mov w0, #SPSR_KERNEL ++ ldr x1, =spsr_to_elx ++ str w0, [x1] ++ b el_max_init ++ ++el_max_init: + ldr x0, =COUNTER_FREQ + msr cntfrq_el0, x0 + +@@ -178,7 +187,7 @@ ASM_FUNC(jump_kernel) + b.eq 1f + br x19 // Keep current EL + +-1: mov x4, #SPSR_KERNEL ++1: ldr w4, spsr_to_elx + + /* + * If bit 0 of the kernel address is set, we're entering in AArch32 +@@ -196,3 +205,5 @@ ASM_FUNC(jump_kernel) + .align 3 + flag_keep_el: + .long 0 ++spsr_to_elx: ++ .long 0 diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch new file mode 100644 index 000000000000..e10182e1ab12 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch @@ -0,0 +1,105 @@ +From 483d363bf825082b6db6de3c57d169e741861891 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] gic-v3: Prepare for gicv3 with EL2 + +This is a preparation for allowing boot-wrapper configuring the gicv3 +with EL2. + +When confiuring with EL2, since there is no ICC_CTLR_EL2, the +ICC_CTLR_EL3 cannot be replaced with ICC_CTLR_EL2 simply. +See [https://developer.arm.com/documentation/ihi0069/latest/]. + +As the caller, gic_secure_init expects the ICC_CTLR to be written, +we change the function into gic_init_icc_ctlr(). In the GIC spec, +the r/w bits in this register ([6:0]) either affect EL3 IRQ routing +(not applicable since no EL3), non-secure IRQ handling (not applicable +since only secure state in Armv8-R aarch64), or are aliased to +ICC_CTLR_EL1 bits. +So, based on this, the new gic_init_icc_ctlr() would be: +When currentEL is EL3, init ICC_CTLR_EL3 as before. +When currentEL is not EL3, init ICC_CTLR_EL1 with ICC_CTLR_EL1_RESET. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +Reviewed-by: Andre Przywara +--- + arch/aarch32/include/asm/gic-v3.h | 7 +++++++ + arch/aarch64/include/asm/gic-v3.h | 23 ++++++++++++++++++++--- + common/gic-v3.c | 2 +- + 3 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/arch/aarch32/include/asm/gic-v3.h b/arch/aarch32/include/asm/gic-v3.h +index 65f38de..11e7bc7 100644 +--- a/arch/aarch32/include/asm/gic-v3.h ++++ b/arch/aarch32/include/asm/gic-v3.h +@@ -9,6 +9,8 @@ + #ifndef __ASM_AARCH32_GICV3_H + #define __ASM_AARCH32_GICV3_H + ++#define ICC_CTLR_RESET (0UL) ++ + static inline void gic_write_icc_sre(uint32_t val) + { + asm volatile ("mcr p15, 6, %0, c12, c12, 5" : : "r" (val)); +@@ -19,4 +21,9 @@ static inline void gic_write_icc_ctlr(uint32_t val) + asm volatile ("mcr p15, 6, %0, c12, c12, 4" : : "r" (val)); + } + ++static inline void gic_init_icc_ctlr() ++{ ++ gic_write_icc_ctlr(ICC_CTLR_RESET); ++} ++ + #endif +diff --git a/arch/aarch64/include/asm/gic-v3.h b/arch/aarch64/include/asm/gic-v3.h +index 5b32380..090ab0b 100644 +--- a/arch/aarch64/include/asm/gic-v3.h ++++ b/arch/aarch64/include/asm/gic-v3.h +@@ -15,14 +15,31 @@ + #define ICC_CTLR_EL3 "S3_6_C12_C12_4" + #define ICC_PMR_EL1 "S3_0_C4_C6_0" + ++#define ICC_CTLR_EL3_RESET (0UL) ++#define ICC_CTLR_EL1_RESET (0UL) ++ ++static inline uint32_t current_el(void) ++{ ++ uint32_t val; ++ ++ asm volatile ("mrs %0, CurrentEL" : "=r" (val)); ++ return val; ++} ++ + static inline void gic_write_icc_sre(uint32_t val) + { +- asm volatile ("msr " ICC_SRE_EL3 ", %0" : : "r" (val)); ++ if (current_el() == CURRENTEL_EL3) ++ asm volatile ("msr " ICC_SRE_EL3 ", %0" : : "r" (val)); ++ else ++ asm volatile ("msr " ICC_SRE_EL2 ", %0" : : "r" (val)); + } + +-static inline void gic_write_icc_ctlr(uint32_t val) ++static inline void gic_init_icc_ctlr() + { +- asm volatile ("msr " ICC_CTLR_EL3 ", %0" : : "r" (val)); ++ if (current_el() == CURRENTEL_EL3) ++ asm volatile ("msr " ICC_CTLR_EL3 ", %0" : : "r" (ICC_CTLR_EL3_RESET)); ++ else ++ asm volatile ("msr " ICC_CTLR_EL1 ", %0" : : "r" (ICC_CTLR_EL1_RESET)); + } + + #endif +diff --git a/common/gic-v3.c b/common/gic-v3.c +index 6207007..a0fe564 100644 +--- a/common/gic-v3.c ++++ b/common/gic-v3.c +@@ -117,6 +117,6 @@ void gic_secure_init(void) + gic_write_icc_sre(ICC_SRE_Enable | ICC_SRE_DIB | ICC_SRE_DFB | ICC_SRE_SRE); + isb(); + +- gic_write_icc_ctlr(0); ++ gic_init_icc_ctlr(); + isb(); + } diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch new file mode 100644 index 000000000000..3b6f78a57929 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch @@ -0,0 +1,63 @@ +From be814863cdd5f61d9a16eec012d500550053c8c6 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Prepare for booting with EL2 + +Prepare for allowing boot-wrapper to be entered in EL2. +Detect current EL and set the corresponding EL registers. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +Reviewed-by: Andre Przywara +--- + arch/aarch64/boot.S | 8 ++++++++ + arch/aarch64/utils.S | 10 +++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 6b45afc..908764a 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -195,10 +195,18 @@ ASM_FUNC(jump_kernel) + */ + bfi x4, x19, #5, #1 + ++ mrs x5, CurrentEL ++ cmp x5, #CURRENTEL_EL2 ++ b.eq 1f ++ + msr elr_el3, x19 + msr spsr_el3, x4 + eret + ++1: msr elr_el2, x19 ++ msr spsr_el2, x4 ++ eret ++ + .ltorg + + .data +diff --git a/arch/aarch64/utils.S b/arch/aarch64/utils.S +index 85c7f8a..f02a249 100644 +--- a/arch/aarch64/utils.S ++++ b/arch/aarch64/utils.S +@@ -34,10 +34,18 @@ ASM_FUNC(find_logical_id) + ret + + /* +- * Setup EL3 vectors ++ * Setup EL3/EL2 vectors + * x0: vector address + */ + ASM_FUNC(setup_vector) ++ mrs x1, CurrentEL ++ cmp x1, #CURRENTEL_EL2 ++ b.eq 1f ++ + msr VBAR_EL3, x0 + isb + ret ++ ++1: msr VBAR_EL2, x0 ++ isb ++ ret diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch new file mode 100644 index 000000000000..aaacc7294583 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch @@ -0,0 +1,182 @@ +From 81df76f8d94cb6c31c01739b078a72bdb8497441 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Introduce EL2 boot code for Armv8-R AArch64 + +The Armv8-R AArch64 profile does not support the EL3 exception level. +The Armv8-R AArch64 profile allows for an (optional) VMSAv8-64 MMU +at EL1, which allows to run off-the-shelf Linux. However EL2 only +supports a PMSA, which is not supported by Linux, so we need to drop +into EL1 before entering the kernel. + +We add a new err_invalid_arch symbol as a dead loop. If we detect the +current Armv8-R aarch64 only supports with PMSA, meaning we cannot boot +Linux anymore, then we jump to err_invalid_arch. + +During Armv8-R aarch64 init, to make sure nothing unexpected traps into +EL2, we auto-detect and config FIEN and EnSCXT in HCR_EL2. + +The boot sequence is: +If CurrentEL == EL3, then goto EL3 initialisation and drop to lower EL + before entering the kernel. +If CurrentEL == EL2 && id_aa64mmfr0_el1.MSA == 0xf (Armv8-R aarch64), + if id_aa64mmfr0_el1.MSA_frac == 0x2, + then goto Armv8-R AArch64 initialisation and drop to EL1 before + entering the kernel. + else, which means VMSA unsupported and cannot boot Linux, + goto err_invalid_arch (dead loop). +Else, no initialisation and keep the current EL before entering the + kernel. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han +--- + arch/aarch64/boot.S | 92 +++++++++++++++++++++++++++++++++- + arch/aarch64/include/asm/cpu.h | 2 + + 2 files changed, 92 insertions(+), 2 deletions(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 908764a..def9192 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -24,16 +24,24 @@ ASM_FUNC(_start) + * Boot sequence + * If CurrentEL == EL3, then goto EL3 initialisation and drop to + * lower EL before entering the kernel. ++ * If CurrentEL == EL2 && id_aa64mmfr0_el1.MSA == 0xf, then ++ * If id_aa64mmfr0_el1.MSA_frac == 0x2, then goto ++ * Armv8-R AArch64 initialisation and drop to EL1 before ++ * entering the kernel. ++ * Else, which means VMSA unsupported and cannot boot Linux, ++ * goto err_invalid_arch (dead loop). + * Else, no initialisation and keep the current EL before + * entering the kernel. + */ + mrs x0, CurrentEL +- cmp x0, #CURRENTEL_EL3 +- b.eq el3_init ++ cmp x0, #CURRENTEL_EL2 ++ bgt el3_init ++ beq el2_init + + /* + * We stay in the current EL for entering the kernel + */ ++keep_el: + mov w0, #1 + ldr x1, =flag_keep_el + str w0, [x1] +@@ -139,6 +147,85 @@ el3_init: + str w0, [x1] + b el_max_init + ++ /* ++ * EL2 Armv8-R AArch64 initialisation ++ */ ++el2_init: ++ /* Detect Armv8-R AArch64 */ ++ mrs x1, id_aa64mmfr0_el1 ++ /* ++ * Check MSA, bits [51:48]: ++ * 0xf means Armv8-R AArch64. ++ * If not 0xf, proceed in Armv8-A EL2. ++ */ ++ ubfx x0, x1, #48, #4 // MSA ++ cmp x0, 0xf ++ bne keep_el ++ /* ++ * Check MSA_frac, bits [55:52]: ++ * 0x2 means EL1&0 translation regime also supports VMSAv8-64. ++ */ ++ ubfx x0, x1, #52, #4 // MSA_frac ++ cmp x0, 0x2 ++ /* ++ * If not 0x2, no VMSA, so cannot boot Linux and dead loop. ++ * Also, since the architecture guarantees that those CPUID ++ * fields never lose features when the value in a field ++ * increases, we use blt to cover it. ++ */ ++ blt err_invalid_arch ++ ++ mrs x0, midr_el1 ++ msr vpidr_el2, x0 ++ ++ mrs x0, mpidr_el1 ++ msr vmpidr_el2, x0 ++ ++ mov x0, #(1 << 31) // VTCR_MSA: VMSAv8-64 support ++ msr vtcr_el2, x0 ++ ++ /* Init HCR_EL2 */ ++ mov x0, #(1 << 31) // RES1: Armv8-R aarch64 only ++ ++ mrs x1, id_aa64pfr0_el1 ++ ubfx x2, x1, #56, 4 // ID_AA64PFR0_EL1.CSV2 ++ cmp x2, 0x2 ++ b.lt 1f ++ /* ++ * Disable trap when accessing SCTXNUM_EL0 or SCTXNUM_EL1 ++ * if FEAT_CSV2. ++ */ ++ orr x0, x0, #(1 << 53) // HCR_EL2.EnSCXT ++ ++1: ubfx x2, x1, #28, 4 // ID_AA64PFR0_EL1.RAS ++ cmp x2, 0x2 ++ b.lt 1f ++ /* Disable trap when accessing ERXPFGCDN_EL1 if FEAT_RASv1p1. */ ++ orr x0, x0, #(1 << 47) // HCR_EL2.FIEN ++ ++ /* Enable pointer authentication if present */ ++1: mrs x1, id_aa64isar1_el1 ++ /* ++ * If ID_AA64ISAR1_EL1.{GPI, GPA, API, APA} == {0000, 0000, 0000, 0000} ++ * then HCR_EL2.APK and HCR_EL2.API are RES 0. ++ * Else ++ * set HCR_EL2.APK and HCR_EL2.API. ++ */ ++ ldr x2, =(((0xff) << 24) | (0xff << 4)) ++ and x1, x1, x2 ++ cbz x1, 1f ++ ++ orr x0, x0, #(1 << 40) // HCR_EL2.APK ++ orr x0, x0, #(1 << 41) // HCR_EL2.API ++ ++1: msr hcr_el2, x0 ++ isb ++ ++ mov w0, #SPSR_KERNEL_EL1 ++ ldr x1, =spsr_to_elx ++ str w0, [x1] ++ // fall through ++ + el_max_init: + ldr x0, =COUNTER_FREQ + msr cntfrq_el0, x0 +@@ -148,6 +235,7 @@ el_max_init: + b start_el_max + + err_invalid_id: ++err_invalid_arch: + b . + + /* +diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h +index b1003f4..91f803c 100644 +--- a/arch/aarch64/include/asm/cpu.h ++++ b/arch/aarch64/include/asm/cpu.h +@@ -25,6 +25,7 @@ + #define SPSR_I (1 << 7) /* IRQ masked */ + #define SPSR_F (1 << 6) /* FIQ masked */ + #define SPSR_T (1 << 5) /* Thumb */ ++#define SPSR_EL1H (5 << 0) /* EL1 Handler mode */ + #define SPSR_EL2H (9 << 0) /* EL2 Handler mode */ + #define SPSR_HYP (0x1a << 0) /* M[3:0] = hyp, M[4] = AArch32 */ + +@@ -43,6 +44,7 @@ + #else + #define SCTLR_EL1_KERNEL SCTLR_EL1_RES1 + #define SPSR_KERNEL (SPSR_A | SPSR_D | SPSR_I | SPSR_F | SPSR_EL2H) ++#define SPSR_KERNEL_EL1 (SPSR_A | SPSR_D | SPSR_I | SPSR_F | SPSR_EL1H) + #endif + + #ifndef __ASSEMBLY__ diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch new file mode 100644 index 000000000000..b130854895f8 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch @@ -0,0 +1,89 @@ +From f5a31b4f4ea8daaa0d337d5a2322ddb1912083fc Mon Sep 17 00:00:00 2001 +From: Qi Feng +Date: Wed, 26 May 2021 17:52:01 +0800 +Subject: [PATCH] Allow --enable-psci to choose between smc and hvc + +According to Armv8-R AArch64 manual [1], Armv8-R AArch64 does not +support smc: + +- Pseudocode for AArch64.CheckForSMCUndefOrTrap has this snippet: + + if !HaveEL(EL3) || PSTATE.EL == EL0 then + UNDEFINED; + + And Armv8-R AArch64 does not have EL3. + +- In the document of HCR_EL2 TSC bit: + If EL3 is not implemented and HCR_EL2.NV is 0, it is IMPLEMENTATION + DEFINED whether this bit is: + - RES0. + - Implemented with the functionality as described in HCR_EL2.TSC. + +So hvc is needed in this situation. And due to the lack of libfdt, the +psci method cannot be modified at runtime. + +To use smc, use --enable-psci or --enable-psci=smc. +To use hvc, use --enable-psci=hvc. + +[1]: https://developer.arm.com/documentation/ddi0600/latest/ + +Issue-Id: SCM-2654 +Upstream-Status: Pending +Signed-off-by: Qi Feng +Change-Id: Ib8afabdad2d98bc37371d165bbb6f1f9b88bfc87 + +Upstream-Status: Pending +Signed-off-by: Huifeng Zhang +--- + Makefile.am | 10 +++++----- + configure.ac | 14 +++++++++----- + 2 files changed, 14 insertions(+), 10 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index f941b07..88a27de 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -50,11 +50,11 @@ endif + if PSCI + ARCH_OBJ += psci.o + COMMON_OBJ += psci.o +-PSCI_NODE := psci { \ +- compatible = \"arm,psci\"; \ +- method = \"smc\"; \ +- cpu_on = <$(PSCI_CPU_ON)>; \ +- cpu_off = <$(PSCI_CPU_OFF)>; \ ++PSCI_NODE := psci { \ ++ compatible = \"arm,psci\"; \ ++ method = \"$(PSCI_METHOD)\"; \ ++ cpu_on = <$(PSCI_CPU_ON)>; \ ++ cpu_off = <$(PSCI_CPU_OFF)>; \ + }; + CPU_NODES := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/addpsci.pl $(KERNEL_DTB)) + else +diff --git a/configure.ac b/configure.ac +index 9e3b722..53e51be 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -83,13 +83,17 @@ AS_IF([test "x$X_IMAGE" != "x"], + # Allow a user to pass --enable-psci + AC_ARG_ENABLE([psci], + AS_HELP_STRING([--disable-psci], [disable the psci boot method]), +- [USE_PSCI=$enableval], [USE_PSCI="yes"]) +-AM_CONDITIONAL([PSCI], [test "x$USE_PSCI" = "xyes"]) +-AS_IF([test "x$USE_PSCI" = "xyes"], [], [USE_PSCI=no]) +- +-AS_IF([test "x$USE_PSCI" != "xyes" -a "x$KERNEL_ES" = "x32"], ++ [case "${enableval}" in ++ yes|smc) USE_PSCI=smc ;; ++ hvc) USE_PSCI=hvc ;; ++ *) AC_MSG_ERROR([Bad value "${enableval}" for --enable-psci. Use "smc" or "hvc"]) ;; ++ esac], [USE_PSCI="yes"]) ++AM_CONDITIONAL([PSCI], [test "x$USE_PSCI" = "xyes" -o "x$USE_PSCI" = "xsmc" -o "x$USE_PSCI" = "xhvc"]) ++ ++AS_IF([test "x$USE_PSCI" = "xno" -a "x$KERNEL_ES" = "x32"], + [AC_MSG_ERROR([With an AArch32 kernel, boot method must be PSCI.])] + ) ++AC_SUBST([PSCI_METHOD], [$USE_PSCI]) + + # Allow a user to pass --with-initrd + AC_ARG_WITH([initrd], diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch new file mode 100644 index 000000000000..2ce28b707130 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch @@ -0,0 +1,48 @@ +From 3f4614e02f0f8d2522510578da2752f8e3511bb3 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Mon, 25 Oct 2021 17:09:13 +0800 +Subject: [PATCH] aarch64: Disable CNTPCT_EL0 trap for v8-R64 + +To allow EL1 to access CNTPCT_EL0 without traping into EL2, we need to +set CNTHCTL_EL2.EL1PCTEN to 1. + +For v8-R64, the CNTHCTL_EL2 register follows the v8-A architecture. +However, as described in the v8-A architecture profile, the +CNTHCTL_EL2's bit assignments are different according to whether the +FEAT_VHE is implemented. + +Since v8-R64 does not support FEAT_VHE, we do not need to detect +FEAT_VHE. We can simply set CNTHCTL_EL2.EL1PCTEN to 1. + +Issue-ID: SCM-3508 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I4147e66341c8153312021e6f2ab67d0037246da1 +--- + arch/aarch64/boot.S | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index def9192..6dbd5cc 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -219,6 +219,18 @@ el2_init: + orr x0, x0, #(1 << 41) // HCR_EL2.API + + 1: msr hcr_el2, x0 ++ ++ /* ++ * To disable trap when accessing CNTPCT_EL0, we need to set ++ * CNTHCTL_EL2.EL1PCTEN to 1. However, the CNTHCTL_EL2 bit assignments ++ * are different according to whether the FEAT_VHE is implemented. ++ * ++ * For Armv8-R AArch64, FEAT_VHE is not supported, so we do not need to ++ * detect FEAT_VHE(ID_AA64MMFR1_EL1.VH) and simply set ++ * CNTHCTL_EL2.EL1PCTEN to 1. ++ */ ++ mov x0, #1 // CNTHCTL_EL2.EL1PCTEN ++ msr cnthctl_el2, x0 + isb + + mov w0, #SPSR_KERNEL_EL1 diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch new file mode 100644 index 000000000000..0c310eb553c0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch @@ -0,0 +1,38 @@ +From 2851f0e6c1216894b9498d7b91256bb1ef49e544 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 2 Nov 2021 15:10:28 +0800 +Subject: [PATCH] lds: Mark the mem range + +Add firmware_start and firmware_end, so that we can use them to +calculate the mem range of boot-wrapper and then set the range to +/memreserve/ of dtb. + +Issue-ID: SCM-3815 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: Idc5a2894e193c75381049a0f359b4b2a51c567ee +--- + model.lds.S | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/model.lds.S b/model.lds.S +index d4e7e13..ab98ddf 100644 +--- a/model.lds.S ++++ b/model.lds.S +@@ -64,6 +64,7 @@ SECTIONS + #endif + + .boot PHYS_OFFSET: { ++ PROVIDE(firmware_start = .); + *(.init) + *(.text*) + *(.data* .rodata* .bss* COMMON) +@@ -76,6 +77,7 @@ SECTIONS + mbox = .; + QUAD(0x0) + } ++ PROVIDE(firmware_end = .); + + ASSERT(etext <= (PHYS_OFFSET + TEXT_LIMIT), ".text overflow!") + } diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch new file mode 100644 index 000000000000..0305f8ba005d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch @@ -0,0 +1,6044 @@ +From fadf04f44b679d85e55b2e5f220fecbebb52ad03 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 28 Dec 2021 17:02:17 +0800 +Subject: [PATCH] common: Introduce the libfdt + +We introduce libfdt (v1.6.1) [1] to boot-wrapper, so we can dynamically +add the firmware node. + +According to [2]: The libfdt is GPL/BSD dual-licensed which means it can +be used either under the terms of GPL, or under the terms of BSD. +We choose BSD because the boot-wrapper is under BSD. + +[1]: https://github.com/dgibson/dtc/tree/v1.6.1/libfdt +[2]: https://github.com/dgibson/dtc/blob/v1.6.1/README.license + +Issue-Id: SCM-3814 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: Iec2f469053c8ac0ed38838c597b21a42bdf67b38 +--- + common/libfdt/README.license | 56 + + common/libfdt/fdt.c | 335 +++++ + common/libfdt/fdt_addresses.c | 101 ++ + common/libfdt/fdt_check.c | 93 ++ + common/libfdt/fdt_empty_tree.c | 38 + + common/libfdt/fdt_overlay.c | 882 +++++++++++++ + common/libfdt/fdt_ro.c | 859 +++++++++++++ + common/libfdt/fdt_rw.c | 500 +++++++ + common/libfdt/fdt_strerror.c | 59 + + common/libfdt/fdt_sw.c | 384 ++++++ + common/libfdt/fdt_wip.c | 94 ++ + common/libfdt/libfdt_internal.h | 192 +++ + include/fdt.h | 66 + + include/libfdt.h | 2147 +++++++++++++++++++++++++++++++ + include/libfdt_env.h | 95 ++ + 15 files changed, 5901 insertions(+) + create mode 100644 common/libfdt/README.license + create mode 100644 common/libfdt/fdt.c + create mode 100644 common/libfdt/fdt_addresses.c + create mode 100644 common/libfdt/fdt_check.c + create mode 100644 common/libfdt/fdt_empty_tree.c + create mode 100644 common/libfdt/fdt_overlay.c + create mode 100644 common/libfdt/fdt_ro.c + create mode 100644 common/libfdt/fdt_rw.c + create mode 100644 common/libfdt/fdt_strerror.c + create mode 100644 common/libfdt/fdt_sw.c + create mode 100644 common/libfdt/fdt_wip.c + create mode 100644 common/libfdt/libfdt_internal.h + create mode 100644 include/fdt.h + create mode 100644 include/libfdt.h + create mode 100644 include/libfdt_env.h + +diff --git a/common/libfdt/README.license b/common/libfdt/README.license +new file mode 100644 +index 0000000..102b004 +--- /dev/null ++++ b/common/libfdt/README.license +@@ -0,0 +1,56 @@ ++Licensing and contribution policy of dtc and libfdt ++=================================================== ++ ++This dtc package contains two pieces of software: dtc itself, and ++libfdt which comprises the files in the libfdt/ subdirectory. These ++two pieces of software, although closely related, are quite distinct. ++dtc does not incorporate or rely on libfdt for its operation, nor vice ++versa. It is important that these two pieces of software have ++different license conditions. ++ ++As SPDX license tags in each source file attest, dtc is licensed ++under the GNU GPL. The full text of the GPL can be found in the file ++entitled 'GPL' which should be included in this package. dtc code, ++therefore, may not be incorporated into works which do not have a GPL ++compatible license. ++ ++libfdt, however, is GPL/BSD dual-licensed. That is, it may be used ++either under the terms of the GPL, or under the terms of the 2-clause ++BSD license (aka the ISC license). The full terms of that license can ++be found are in the file entitled 'BSD-2-Clause'. This is, in ++practice, equivalent to being BSD licensed, since the terms of the BSD ++license are strictly more permissive than the GPL. ++ ++I made the decision to license libfdt in this way because I want to ++encourage widespread and correct usage of flattened device trees, ++including by proprietary or otherwise GPL-incompatible firmware or ++tools. Allowing libfdt to be used under the terms of the BSD license ++makes that it easier for vendors or authors of such software to do so. ++ ++This does mean that libfdt code could be "stolen" - say, included in a ++proprietary fimware and extended without contributing those extensions ++back to the libfdt mainline. While I hope that doesn't happen, I ++believe the goal of allowing libfdt to be widely used is more ++important than avoiding that. libfdt is quite small, and hardly ++rocket science; so the incentive for such impolite behaviour is small, ++and the inconvenience caused thereby is not dire. ++ ++Licenses such as the LGPL which would allow code to be used in non-GPL ++software, but also require contributions to be returned were ++considered. However, libfdt is designed to be used in firmwares and ++other environments with unusual technical constraints. It's difficult ++to anticipate all possible changes which might be needed to meld ++libfdt into such environments and so difficult to suitably word a ++license that puts the boundary between what is and isn't permitted in ++the intended place. Again, I judged encouraging widespread use of ++libfdt by keeping the license terms simple and familiar to be the more ++important goal. ++ ++**IMPORTANT** It's intended that all of libfdt as released remain ++permissively licensed this way. Therefore only contributions which ++are released under these terms can be merged into the libfdt mainline. ++ ++ ++David Gibson ++(principal original author of dtc and libfdt) ++2 November 2007 +diff --git a/common/libfdt/fdt.c b/common/libfdt/fdt.c +new file mode 100644 +index 0000000..9fe7cf4 +--- /dev/null ++++ b/common/libfdt/fdt.c +@@ -0,0 +1,335 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++/* ++ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks ++ * that the given buffer contains what appears to be a flattened ++ * device tree with sane information in its header. ++ */ ++int32_t fdt_ro_probe_(const void *fdt) ++{ ++ uint32_t totalsize = fdt_totalsize(fdt); ++ ++ if (can_assume(VALID_DTB)) ++ return totalsize; ++ ++ /* The device tree must be at an 8-byte aligned address */ ++ if ((uintptr_t)fdt & 7) ++ return -FDT_ERR_ALIGNMENT; ++ ++ if (fdt_magic(fdt) == FDT_MAGIC) { ++ /* Complete tree */ ++ if (!can_assume(LATEST)) { ++ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) ++ return -FDT_ERR_BADVERSION; ++ if (fdt_last_comp_version(fdt) > ++ FDT_LAST_SUPPORTED_VERSION) ++ return -FDT_ERR_BADVERSION; ++ } ++ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { ++ /* Unfinished sequential-write blob */ ++ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) ++ return -FDT_ERR_BADSTATE; ++ } else { ++ return -FDT_ERR_BADMAGIC; ++ } ++ ++ if (totalsize < INT32_MAX) ++ return totalsize; ++ else ++ return -FDT_ERR_TRUNCATED; ++} ++ ++static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) ++{ ++ return (off >= hdrsize) && (off <= totalsize); ++} ++ ++static int check_block_(uint32_t hdrsize, uint32_t totalsize, ++ uint32_t base, uint32_t size) ++{ ++ if (!check_off_(hdrsize, totalsize, base)) ++ return 0; /* block start out of bounds */ ++ if ((base + size) < base) ++ return 0; /* overflow */ ++ if (!check_off_(hdrsize, totalsize, base + size)) ++ return 0; /* block end out of bounds */ ++ return 1; ++} ++ ++size_t fdt_header_size_(uint32_t version) ++{ ++ if (version <= 1) ++ return FDT_V1_SIZE; ++ else if (version <= 2) ++ return FDT_V2_SIZE; ++ else if (version <= 3) ++ return FDT_V3_SIZE; ++ else if (version <= 16) ++ return FDT_V16_SIZE; ++ else ++ return FDT_V17_SIZE; ++} ++ ++size_t fdt_header_size(const void *fdt) ++{ ++ return can_assume(LATEST) ? FDT_V17_SIZE : ++ fdt_header_size_(fdt_version(fdt)); ++} ++ ++int fdt_check_header(const void *fdt) ++{ ++ size_t hdrsize; ++ ++ /* The device tree must be at an 8-byte aligned address */ ++ if ((uintptr_t)fdt & 7) ++ return -FDT_ERR_ALIGNMENT; ++ ++ if (fdt_magic(fdt) != FDT_MAGIC) ++ return -FDT_ERR_BADMAGIC; ++ if (!can_assume(LATEST)) { ++ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) ++ || (fdt_last_comp_version(fdt) > ++ FDT_LAST_SUPPORTED_VERSION)) ++ return -FDT_ERR_BADVERSION; ++ if (fdt_version(fdt) < fdt_last_comp_version(fdt)) ++ return -FDT_ERR_BADVERSION; ++ } ++ hdrsize = fdt_header_size(fdt); ++ if (!can_assume(VALID_DTB)) { ++ ++ if ((fdt_totalsize(fdt) < hdrsize) ++ || (fdt_totalsize(fdt) > INT_MAX)) ++ return -FDT_ERR_TRUNCATED; ++ ++ /* Bounds check memrsv block */ ++ if (!check_off_(hdrsize, fdt_totalsize(fdt), ++ fdt_off_mem_rsvmap(fdt))) ++ return -FDT_ERR_TRUNCATED; ++ } ++ ++ if (!can_assume(VALID_DTB)) { ++ /* Bounds check structure block */ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 17) { ++ if (!check_off_(hdrsize, fdt_totalsize(fdt), ++ fdt_off_dt_struct(fdt))) ++ return -FDT_ERR_TRUNCATED; ++ } else { ++ if (!check_block_(hdrsize, fdt_totalsize(fdt), ++ fdt_off_dt_struct(fdt), ++ fdt_size_dt_struct(fdt))) ++ return -FDT_ERR_TRUNCATED; ++ } ++ ++ /* Bounds check strings block */ ++ if (!check_block_(hdrsize, fdt_totalsize(fdt), ++ fdt_off_dt_strings(fdt), ++ fdt_size_dt_strings(fdt))) ++ return -FDT_ERR_TRUNCATED; ++ } ++ ++ return 0; ++} ++ ++const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) ++{ ++ unsigned int uoffset = offset; ++ unsigned int absoffset = offset + fdt_off_dt_struct(fdt); ++ ++ if (offset < 0) ++ return NULL; ++ ++ if (!can_assume(VALID_INPUT)) ++ if ((absoffset < uoffset) ++ || ((absoffset + len) < absoffset) ++ || (absoffset + len) > fdt_totalsize(fdt)) ++ return NULL; ++ ++ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) ++ if (((uoffset + len) < uoffset) ++ || ((offset + len) > fdt_size_dt_struct(fdt))) ++ return NULL; ++ ++ return fdt_offset_ptr_(fdt, offset); ++} ++ ++uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) ++{ ++ const fdt32_t *tagp, *lenp; ++ uint32_t tag; ++ int offset = startoffset; ++ const char *p; ++ ++ *nextoffset = -FDT_ERR_TRUNCATED; ++ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); ++ if (!can_assume(VALID_DTB) && !tagp) ++ return FDT_END; /* premature end */ ++ tag = fdt32_to_cpu(*tagp); ++ offset += FDT_TAGSIZE; ++ ++ *nextoffset = -FDT_ERR_BADSTRUCTURE; ++ switch (tag) { ++ case FDT_BEGIN_NODE: ++ /* skip name */ ++ do { ++ p = fdt_offset_ptr(fdt, offset++, 1); ++ } while (p && (*p != '\0')); ++ if (!can_assume(VALID_DTB) && !p) ++ return FDT_END; /* premature end */ ++ break; ++ ++ case FDT_PROP: ++ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); ++ if (!can_assume(VALID_DTB) && !lenp) ++ return FDT_END; /* premature end */ ++ /* skip-name offset, length and value */ ++ offset += sizeof(struct fdt_property) - FDT_TAGSIZE ++ + fdt32_to_cpu(*lenp); ++ if (!can_assume(LATEST) && ++ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && ++ ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) ++ offset += 4; ++ break; ++ ++ case FDT_END: ++ case FDT_END_NODE: ++ case FDT_NOP: ++ break; ++ ++ default: ++ return FDT_END; ++ } ++ ++ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) ++ return FDT_END; /* premature end */ ++ ++ *nextoffset = FDT_TAGALIGN(offset); ++ return tag; ++} ++ ++int fdt_check_node_offset_(const void *fdt, int offset) ++{ ++ if (!can_assume(VALID_INPUT) ++ && ((offset < 0) || (offset % FDT_TAGSIZE))) ++ return -FDT_ERR_BADOFFSET; ++ ++ if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE) ++ return -FDT_ERR_BADOFFSET; ++ ++ return offset; ++} ++ ++int fdt_check_prop_offset_(const void *fdt, int offset) ++{ ++ if (!can_assume(VALID_INPUT) ++ && ((offset < 0) || (offset % FDT_TAGSIZE))) ++ return -FDT_ERR_BADOFFSET; ++ ++ if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP) ++ return -FDT_ERR_BADOFFSET; ++ ++ return offset; ++} ++ ++int fdt_next_node(const void *fdt, int offset, int *depth) ++{ ++ int nextoffset = 0; ++ uint32_t tag; ++ ++ if (offset >= 0) ++ if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) ++ return nextoffset; ++ ++ do { ++ offset = nextoffset; ++ tag = fdt_next_tag(fdt, offset, &nextoffset); ++ ++ switch (tag) { ++ case FDT_PROP: ++ case FDT_NOP: ++ break; ++ ++ case FDT_BEGIN_NODE: ++ if (depth) ++ (*depth)++; ++ break; ++ ++ case FDT_END_NODE: ++ if (depth && ((--(*depth)) < 0)) ++ return nextoffset; ++ break; ++ ++ case FDT_END: ++ if ((nextoffset >= 0) ++ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) ++ return -FDT_ERR_NOTFOUND; ++ else ++ return nextoffset; ++ } ++ } while (tag != FDT_BEGIN_NODE); ++ ++ return offset; ++} ++ ++int fdt_first_subnode(const void *fdt, int offset) ++{ ++ int depth = 0; ++ ++ offset = fdt_next_node(fdt, offset, &depth); ++ if (offset < 0 || depth != 1) ++ return -FDT_ERR_NOTFOUND; ++ ++ return offset; ++} ++ ++int fdt_next_subnode(const void *fdt, int offset) ++{ ++ int depth = 1; ++ ++ /* ++ * With respect to the parent, the depth of the next subnode will be ++ * the same as the last. ++ */ ++ do { ++ offset = fdt_next_node(fdt, offset, &depth); ++ if (offset < 0 || depth < 1) ++ return -FDT_ERR_NOTFOUND; ++ } while (depth > 1); ++ ++ return offset; ++} ++ ++const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) ++{ ++ int len = strlen(s) + 1; ++ const char *last = strtab + tabsize - len; ++ const char *p; ++ ++ for (p = strtab; p <= last; p++) ++ if (memcmp(p, s, len) == 0) ++ return p; ++ return NULL; ++} ++ ++int fdt_move(const void *fdt, void *buf, int bufsize) ++{ ++ if (!can_assume(VALID_INPUT) && bufsize < 0) ++ return -FDT_ERR_NOSPACE; ++ ++ FDT_RO_PROBE(fdt); ++ ++ if (fdt_totalsize(fdt) > (unsigned int)bufsize) ++ return -FDT_ERR_NOSPACE; ++ ++ memmove(buf, fdt, fdt_totalsize(fdt)); ++ return 0; ++} +diff --git a/common/libfdt/fdt_addresses.c b/common/libfdt/fdt_addresses.c +new file mode 100644 +index 0000000..9a82cd0 +--- /dev/null ++++ b/common/libfdt/fdt_addresses.c +@@ -0,0 +1,101 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2014 David Gibson ++ * Copyright (C) 2018 embedded brains GmbH ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++static int fdt_cells(const void *fdt, int nodeoffset, const char *name) ++{ ++ const fdt32_t *c; ++ uint32_t val; ++ int len; ++ ++ c = fdt_getprop(fdt, nodeoffset, name, &len); ++ if (!c) ++ return len; ++ ++ if (len != sizeof(*c)) ++ return -FDT_ERR_BADNCELLS; ++ ++ val = fdt32_to_cpu(*c); ++ if (val > FDT_MAX_NCELLS) ++ return -FDT_ERR_BADNCELLS; ++ ++ return (int)val; ++} ++ ++int fdt_address_cells(const void *fdt, int nodeoffset) ++{ ++ int val; ++ ++ val = fdt_cells(fdt, nodeoffset, "#address-cells"); ++ if (val == 0) ++ return -FDT_ERR_BADNCELLS; ++ if (val == -FDT_ERR_NOTFOUND) ++ return 2; ++ return val; ++} ++ ++int fdt_size_cells(const void *fdt, int nodeoffset) ++{ ++ int val; ++ ++ val = fdt_cells(fdt, nodeoffset, "#size-cells"); ++ if (val == -FDT_ERR_NOTFOUND) ++ return 1; ++ return val; ++} ++ ++/* This function assumes that [address|size]_cells is 1 or 2 */ ++int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, ++ const char *name, uint64_t addr, uint64_t size) ++{ ++ int addr_cells, size_cells, ret; ++ uint8_t data[sizeof(fdt64_t) * 2], *prop; ++ ++ ret = fdt_address_cells(fdt, parent); ++ if (ret < 0) ++ return ret; ++ addr_cells = ret; ++ ++ ret = fdt_size_cells(fdt, parent); ++ if (ret < 0) ++ return ret; ++ size_cells = ret; ++ ++ /* check validity of address */ ++ prop = data; ++ if (addr_cells == 1) { ++ if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) ++ return -FDT_ERR_BADVALUE; ++ ++ fdt32_st(prop, (uint32_t)addr); ++ } else if (addr_cells == 2) { ++ fdt64_st(prop, addr); ++ } else { ++ return -FDT_ERR_BADNCELLS; ++ } ++ ++ /* check validity of size */ ++ prop += addr_cells * sizeof(fdt32_t); ++ if (size_cells == 1) { ++ if (size > UINT32_MAX) ++ return -FDT_ERR_BADVALUE; ++ ++ fdt32_st(prop, (uint32_t)size); ++ } else if (size_cells == 2) { ++ fdt64_st(prop, size); ++ } else { ++ return -FDT_ERR_BADNCELLS; ++ } ++ ++ return fdt_appendprop(fdt, nodeoffset, name, data, ++ (addr_cells + size_cells) * sizeof(fdt32_t)); ++} +diff --git a/common/libfdt/fdt_check.c b/common/libfdt/fdt_check.c +new file mode 100644 +index 0000000..fa410a8 +--- /dev/null ++++ b/common/libfdt/fdt_check.c +@@ -0,0 +1,93 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++int fdt_check_full(const void *fdt, size_t bufsize) ++{ ++ int err; ++ int num_memrsv; ++ int offset, nextoffset = 0; ++ uint32_t tag; ++ unsigned int depth = 0; ++ const void *prop; ++ const char *propname; ++ bool expect_end = false; ++ ++ if (bufsize < FDT_V1_SIZE) ++ return -FDT_ERR_TRUNCATED; ++ if (bufsize < fdt_header_size(fdt)) ++ return -FDT_ERR_TRUNCATED; ++ err = fdt_check_header(fdt); ++ if (err != 0) ++ return err; ++ if (bufsize < fdt_totalsize(fdt)) ++ return -FDT_ERR_TRUNCATED; ++ ++ num_memrsv = fdt_num_mem_rsv(fdt); ++ if (num_memrsv < 0) ++ return num_memrsv; ++ ++ while (1) { ++ offset = nextoffset; ++ tag = fdt_next_tag(fdt, offset, &nextoffset); ++ ++ if (nextoffset < 0) ++ return nextoffset; ++ ++ /* If we see two root nodes, something is wrong */ ++ if (expect_end && tag != FDT_END) ++ return -FDT_ERR_BADSTRUCTURE; ++ ++ switch (tag) { ++ case FDT_NOP: ++ break; ++ ++ case FDT_END: ++ if (depth != 0) ++ return -FDT_ERR_BADSTRUCTURE; ++ return 0; ++ ++ case FDT_BEGIN_NODE: ++ depth++; ++ if (depth > INT_MAX) ++ return -FDT_ERR_BADSTRUCTURE; ++ ++ /* The root node must have an empty name */ ++ if (depth == 1) { ++ const char *name; ++ int len; ++ ++ name = fdt_get_name(fdt, offset, &len); ++ if (*name || len) ++ return -FDT_ERR_BADSTRUCTURE; ++ } ++ break; ++ ++ case FDT_END_NODE: ++ if (depth == 0) ++ return -FDT_ERR_BADSTRUCTURE; ++ depth--; ++ if (depth == 0) ++ expect_end = true; ++ break; ++ ++ case FDT_PROP: ++ prop = fdt_getprop_by_offset(fdt, offset, &propname, ++ &err); ++ if (!prop) ++ return err; ++ break; ++ ++ default: ++ return -FDT_ERR_INTERNAL; ++ } ++ } ++} +diff --git a/common/libfdt/fdt_empty_tree.c b/common/libfdt/fdt_empty_tree.c +new file mode 100644 +index 0000000..49d54d4 +--- /dev/null ++++ b/common/libfdt/fdt_empty_tree.c +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2012 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++int fdt_create_empty_tree(void *buf, int bufsize) ++{ ++ int err; ++ ++ err = fdt_create(buf, bufsize); ++ if (err) ++ return err; ++ ++ err = fdt_finish_reservemap(buf); ++ if (err) ++ return err; ++ ++ err = fdt_begin_node(buf, ""); ++ if (err) ++ return err; ++ ++ err = fdt_end_node(buf); ++ if (err) ++ return err; ++ ++ err = fdt_finish(buf); ++ if (err) ++ return err; ++ ++ return fdt_open_into(buf, buf, bufsize); ++} +diff --git a/common/libfdt/fdt_overlay.c b/common/libfdt/fdt_overlay.c +new file mode 100644 +index 0000000..d217e79 +--- /dev/null ++++ b/common/libfdt/fdt_overlay.c +@@ -0,0 +1,882 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2016 Free Electrons ++ * Copyright (C) 2016 NextThing Co. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++/** ++ * overlay_get_target_phandle - retrieves the target phandle of a fragment ++ * @fdto: pointer to the device tree overlay blob ++ * @fragment: node offset of the fragment in the overlay ++ * ++ * overlay_get_target_phandle() retrieves the target phandle of an ++ * overlay fragment when that fragment uses a phandle (target ++ * property) instead of a path (target-path property). ++ * ++ * returns: ++ * the phandle pointed by the target property ++ * 0, if the phandle was not found ++ * -1, if the phandle was malformed ++ */ ++static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) ++{ ++ const fdt32_t *val; ++ int len; ++ ++ val = fdt_getprop(fdto, fragment, "target", &len); ++ if (!val) ++ return 0; ++ ++ if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) ++ return (uint32_t)-1; ++ ++ return fdt32_to_cpu(*val); ++} ++ ++/** ++ * overlay_get_target - retrieves the offset of a fragment's target ++ * @fdt: Base device tree blob ++ * @fdto: Device tree overlay blob ++ * @fragment: node offset of the fragment in the overlay ++ * @pathp: pointer which receives the path of the target (or NULL) ++ * ++ * overlay_get_target() retrieves the target offset in the base ++ * device tree of a fragment, no matter how the actual targeting is ++ * done (through a phandle or a path) ++ * ++ * returns: ++ * the targeted node offset in the base device tree ++ * Negative error code on error ++ */ ++static int overlay_get_target(const void *fdt, const void *fdto, ++ int fragment, char const **pathp) ++{ ++ uint32_t phandle; ++ const char *path = NULL; ++ int path_len = 0, ret; ++ ++ /* Try first to do a phandle based lookup */ ++ phandle = overlay_get_target_phandle(fdto, fragment); ++ if (phandle == (uint32_t)-1) ++ return -FDT_ERR_BADPHANDLE; ++ ++ /* no phandle, try path */ ++ if (!phandle) { ++ /* And then a path based lookup */ ++ path = fdt_getprop(fdto, fragment, "target-path", &path_len); ++ if (path) ++ ret = fdt_path_offset(fdt, path); ++ else ++ ret = path_len; ++ } else ++ ret = fdt_node_offset_by_phandle(fdt, phandle); ++ ++ /* ++ * If we haven't found either a target or a ++ * target-path property in a node that contains a ++ * __overlay__ subnode (we wouldn't be called ++ * otherwise), consider it a improperly written ++ * overlay ++ */ ++ if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) ++ ret = -FDT_ERR_BADOVERLAY; ++ ++ /* return on error */ ++ if (ret < 0) ++ return ret; ++ ++ /* return pointer to path (if available) */ ++ if (pathp) ++ *pathp = path ? path : NULL; ++ ++ return ret; ++} ++ ++/** ++ * overlay_phandle_add_offset - Increases a phandle by an offset ++ * @fdt: Base device tree blob ++ * @node: Device tree overlay blob ++ * @name: Name of the property to modify (phandle or linux,phandle) ++ * @delta: offset to apply ++ * ++ * overlay_phandle_add_offset() increments a node phandle by a given ++ * offset. ++ * ++ * returns: ++ * 0 on success. ++ * Negative error code on error ++ */ ++static int overlay_phandle_add_offset(void *fdt, int node, ++ const char *name, uint32_t delta) ++{ ++ const fdt32_t *val; ++ uint32_t adj_val; ++ int len; ++ ++ val = fdt_getprop(fdt, node, name, &len); ++ if (!val) ++ return len; ++ ++ if (len != sizeof(*val)) ++ return -FDT_ERR_BADPHANDLE; ++ ++ adj_val = fdt32_to_cpu(*val); ++ if ((adj_val + delta) < adj_val) ++ return -FDT_ERR_NOPHANDLES; ++ ++ adj_val += delta; ++ if (adj_val == (uint32_t)-1) ++ return -FDT_ERR_NOPHANDLES; ++ ++ return fdt_setprop_inplace_u32(fdt, node, name, adj_val); ++} ++ ++/** ++ * overlay_adjust_node_phandles - Offsets the phandles of a node ++ * @fdto: Device tree overlay blob ++ * @node: Offset of the node we want to adjust ++ * @delta: Offset to shift the phandles of ++ * ++ * overlay_adjust_node_phandles() adds a constant to all the phandles ++ * of a given node. This is mainly use as part of the overlay ++ * application process, when we want to update all the overlay ++ * phandles to not conflict with the overlays of the base device tree. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_adjust_node_phandles(void *fdto, int node, ++ uint32_t delta) ++{ ++ int child; ++ int ret; ++ ++ ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); ++ if (ret && ret != -FDT_ERR_NOTFOUND) ++ return ret; ++ ++ ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); ++ if (ret && ret != -FDT_ERR_NOTFOUND) ++ return ret; ++ ++ fdt_for_each_subnode(child, fdto, node) { ++ ret = overlay_adjust_node_phandles(fdto, child, delta); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay ++ * @fdto: Device tree overlay blob ++ * @delta: Offset to shift the phandles of ++ * ++ * overlay_adjust_local_phandles() adds a constant to all the ++ * phandles of an overlay. This is mainly use as part of the overlay ++ * application process, when we want to update all the overlay ++ * phandles to not conflict with the overlays of the base device tree. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) ++{ ++ /* ++ * Start adjusting the phandles from the overlay root ++ */ ++ return overlay_adjust_node_phandles(fdto, 0, delta); ++} ++ ++/** ++ * overlay_update_local_node_references - Adjust the overlay references ++ * @fdto: Device tree overlay blob ++ * @tree_node: Node offset of the node to operate on ++ * @fixup_node: Node offset of the matching local fixups node ++ * @delta: Offset to shift the phandles of ++ * ++ * overlay_update_local_nodes_references() update the phandles ++ * pointing to a node within the device tree overlay by adding a ++ * constant delta. ++ * ++ * This is mainly used as part of a device tree application process, ++ * where you want the device tree overlays phandles to not conflict ++ * with the ones from the base device tree before merging them. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_update_local_node_references(void *fdto, ++ int tree_node, ++ int fixup_node, ++ uint32_t delta) ++{ ++ int fixup_prop; ++ int fixup_child; ++ int ret; ++ ++ fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { ++ const fdt32_t *fixup_val; ++ const char *tree_val; ++ const char *name; ++ int fixup_len; ++ int tree_len; ++ int i; ++ ++ fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, ++ &name, &fixup_len); ++ if (!fixup_val) ++ return fixup_len; ++ ++ if (fixup_len % sizeof(uint32_t)) ++ return -FDT_ERR_BADOVERLAY; ++ fixup_len /= sizeof(uint32_t); ++ ++ tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); ++ if (!tree_val) { ++ if (tree_len == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_BADOVERLAY; ++ ++ return tree_len; ++ } ++ ++ for (i = 0; i < fixup_len; i++) { ++ fdt32_t adj_val; ++ uint32_t poffset; ++ ++ poffset = fdt32_to_cpu(fixup_val[i]); ++ ++ /* ++ * phandles to fixup can be unaligned. ++ * ++ * Use a memcpy for the architectures that do ++ * not support unaligned accesses. ++ */ ++ memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); ++ ++ adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); ++ ++ ret = fdt_setprop_inplace_namelen_partial(fdto, ++ tree_node, ++ name, ++ strlen(name), ++ poffset, ++ &adj_val, ++ sizeof(adj_val)); ++ if (ret == -FDT_ERR_NOSPACE) ++ return -FDT_ERR_BADOVERLAY; ++ ++ if (ret) ++ return ret; ++ } ++ } ++ ++ fdt_for_each_subnode(fixup_child, fdto, fixup_node) { ++ const char *fixup_child_name = fdt_get_name(fdto, fixup_child, ++ NULL); ++ int tree_child; ++ ++ tree_child = fdt_subnode_offset(fdto, tree_node, ++ fixup_child_name); ++ if (tree_child == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_BADOVERLAY; ++ if (tree_child < 0) ++ return tree_child; ++ ++ ret = overlay_update_local_node_references(fdto, ++ tree_child, ++ fixup_child, ++ delta); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * overlay_update_local_references - Adjust the overlay references ++ * @fdto: Device tree overlay blob ++ * @delta: Offset to shift the phandles of ++ * ++ * overlay_update_local_references() update all the phandles pointing ++ * to a node within the device tree overlay by adding a constant ++ * delta to not conflict with the base overlay. ++ * ++ * This is mainly used as part of a device tree application process, ++ * where you want the device tree overlays phandles to not conflict ++ * with the ones from the base device tree before merging them. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_update_local_references(void *fdto, uint32_t delta) ++{ ++ int fixups; ++ ++ fixups = fdt_path_offset(fdto, "/__local_fixups__"); ++ if (fixups < 0) { ++ /* There's no local phandles to adjust, bail out */ ++ if (fixups == -FDT_ERR_NOTFOUND) ++ return 0; ++ ++ return fixups; ++ } ++ ++ /* ++ * Update our local references from the root of the tree ++ */ ++ return overlay_update_local_node_references(fdto, 0, fixups, ++ delta); ++} ++ ++/** ++ * overlay_fixup_one_phandle - Set an overlay phandle to the base one ++ * @fdt: Base Device Tree blob ++ * @fdto: Device tree overlay blob ++ * @symbols_off: Node offset of the symbols node in the base device tree ++ * @path: Path to a node holding a phandle in the overlay ++ * @path_len: number of path characters to consider ++ * @name: Name of the property holding the phandle reference in the overlay ++ * @name_len: number of name characters to consider ++ * @poffset: Offset within the overlay property where the phandle is stored ++ * @label: Label of the node referenced by the phandle ++ * ++ * overlay_fixup_one_phandle() resolves an overlay phandle pointing to ++ * a node in the base device tree. ++ * ++ * This is part of the device tree overlay application process, when ++ * you want all the phandles in the overlay to point to the actual ++ * base dt nodes. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_fixup_one_phandle(void *fdt, void *fdto, ++ int symbols_off, ++ const char *path, uint32_t path_len, ++ const char *name, uint32_t name_len, ++ int poffset, const char *label) ++{ ++ const char *symbol_path; ++ uint32_t phandle; ++ fdt32_t phandle_prop; ++ int symbol_off, fixup_off; ++ int prop_len; ++ ++ if (symbols_off < 0) ++ return symbols_off; ++ ++ symbol_path = fdt_getprop(fdt, symbols_off, label, ++ &prop_len); ++ if (!symbol_path) ++ return prop_len; ++ ++ symbol_off = fdt_path_offset(fdt, symbol_path); ++ if (symbol_off < 0) ++ return symbol_off; ++ ++ phandle = fdt_get_phandle(fdt, symbol_off); ++ if (!phandle) ++ return -FDT_ERR_NOTFOUND; ++ ++ fixup_off = fdt_path_offset_namelen(fdto, path, path_len); ++ if (fixup_off == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_BADOVERLAY; ++ if (fixup_off < 0) ++ return fixup_off; ++ ++ phandle_prop = cpu_to_fdt32(phandle); ++ return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, ++ name, name_len, poffset, ++ &phandle_prop, ++ sizeof(phandle_prop)); ++}; ++ ++/** ++ * overlay_fixup_phandle - Set an overlay phandle to the base one ++ * @fdt: Base Device Tree blob ++ * @fdto: Device tree overlay blob ++ * @symbols_off: Node offset of the symbols node in the base device tree ++ * @property: Property offset in the overlay holding the list of fixups ++ * ++ * overlay_fixup_phandle() resolves all the overlay phandles pointed ++ * to in a __fixups__ property, and updates them to match the phandles ++ * in use in the base device tree. ++ * ++ * This is part of the device tree overlay application process, when ++ * you want all the phandles in the overlay to point to the actual ++ * base dt nodes. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, ++ int property) ++{ ++ const char *value; ++ const char *label; ++ int len; ++ ++ value = fdt_getprop_by_offset(fdto, property, ++ &label, &len); ++ if (!value) { ++ if (len == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_INTERNAL; ++ ++ return len; ++ } ++ ++ do { ++ const char *path, *name, *fixup_end; ++ const char *fixup_str = value; ++ uint32_t path_len, name_len; ++ uint32_t fixup_len; ++ char *sep, *endptr; ++ int poffset, ret; ++ ++ fixup_end = memchr(value, '\0', len); ++ if (!fixup_end) ++ return -FDT_ERR_BADOVERLAY; ++ fixup_len = fixup_end - fixup_str; ++ ++ len -= fixup_len + 1; ++ value += fixup_len + 1; ++ ++ path = fixup_str; ++ sep = memchr(fixup_str, ':', fixup_len); ++ if (!sep || *sep != ':') ++ return -FDT_ERR_BADOVERLAY; ++ ++ path_len = sep - path; ++ if (path_len == (fixup_len - 1)) ++ return -FDT_ERR_BADOVERLAY; ++ ++ fixup_len -= path_len + 1; ++ name = sep + 1; ++ sep = memchr(name, ':', fixup_len); ++ if (!sep || *sep != ':') ++ return -FDT_ERR_BADOVERLAY; ++ ++ name_len = sep - name; ++ if (!name_len) ++ return -FDT_ERR_BADOVERLAY; ++ ++ poffset = strtoul(sep + 1, &endptr, 10); ++ if ((*endptr != '\0') || (endptr <= (sep + 1))) ++ return -FDT_ERR_BADOVERLAY; ++ ++ ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, ++ path, path_len, name, name_len, ++ poffset, label); ++ if (ret) ++ return ret; ++ } while (len > 0); ++ ++ return 0; ++} ++ ++/** ++ * overlay_fixup_phandles - Resolve the overlay phandles to the base ++ * device tree ++ * @fdt: Base Device Tree blob ++ * @fdto: Device tree overlay blob ++ * ++ * overlay_fixup_phandles() resolves all the overlay phandles pointing ++ * to nodes in the base device tree. ++ * ++ * This is one of the steps of the device tree overlay application ++ * process, when you want all the phandles in the overlay to point to ++ * the actual base dt nodes. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_fixup_phandles(void *fdt, void *fdto) ++{ ++ int fixups_off, symbols_off; ++ int property; ++ ++ /* We can have overlays without any fixups */ ++ fixups_off = fdt_path_offset(fdto, "/__fixups__"); ++ if (fixups_off == -FDT_ERR_NOTFOUND) ++ return 0; /* nothing to do */ ++ if (fixups_off < 0) ++ return fixups_off; ++ ++ /* And base DTs without symbols */ ++ symbols_off = fdt_path_offset(fdt, "/__symbols__"); ++ if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) ++ return symbols_off; ++ ++ fdt_for_each_property_offset(property, fdto, fixups_off) { ++ int ret; ++ ++ ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * overlay_apply_node - Merges a node into the base device tree ++ * @fdt: Base Device Tree blob ++ * @target: Node offset in the base device tree to apply the fragment to ++ * @fdto: Device tree overlay blob ++ * @node: Node offset in the overlay holding the changes to merge ++ * ++ * overlay_apply_node() merges a node into a target base device tree ++ * node pointed. ++ * ++ * This is part of the final step in the device tree overlay ++ * application process, when all the phandles have been adjusted and ++ * resolved and you just have to merge overlay into the base device ++ * tree. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_apply_node(void *fdt, int target, ++ void *fdto, int node) ++{ ++ int property; ++ int subnode; ++ ++ fdt_for_each_property_offset(property, fdto, node) { ++ const char *name; ++ const void *prop; ++ int prop_len; ++ int ret; ++ ++ prop = fdt_getprop_by_offset(fdto, property, &name, ++ &prop_len); ++ if (prop_len == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_INTERNAL; ++ if (prop_len < 0) ++ return prop_len; ++ ++ ret = fdt_setprop(fdt, target, name, prop, prop_len); ++ if (ret) ++ return ret; ++ } ++ ++ fdt_for_each_subnode(subnode, fdto, node) { ++ const char *name = fdt_get_name(fdto, subnode, NULL); ++ int nnode; ++ int ret; ++ ++ nnode = fdt_add_subnode(fdt, target, name); ++ if (nnode == -FDT_ERR_EXISTS) { ++ nnode = fdt_subnode_offset(fdt, target, name); ++ if (nnode == -FDT_ERR_NOTFOUND) ++ return -FDT_ERR_INTERNAL; ++ } ++ ++ if (nnode < 0) ++ return nnode; ++ ++ ret = overlay_apply_node(fdt, nnode, fdto, subnode); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * overlay_merge - Merge an overlay into its base device tree ++ * @fdt: Base Device Tree blob ++ * @fdto: Device tree overlay blob ++ * ++ * overlay_merge() merges an overlay into its base device tree. ++ * ++ * This is the next to last step in the device tree overlay application ++ * process, when all the phandles have been adjusted and resolved and ++ * you just have to merge overlay into the base device tree. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_merge(void *fdt, void *fdto) ++{ ++ int fragment; ++ ++ fdt_for_each_subnode(fragment, fdto, 0) { ++ int overlay; ++ int target; ++ int ret; ++ ++ /* ++ * Each fragments will have an __overlay__ node. If ++ * they don't, it's not supposed to be merged ++ */ ++ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); ++ if (overlay == -FDT_ERR_NOTFOUND) ++ continue; ++ ++ if (overlay < 0) ++ return overlay; ++ ++ target = overlay_get_target(fdt, fdto, fragment, NULL); ++ if (target < 0) ++ return target; ++ ++ ret = overlay_apply_node(fdt, target, fdto, overlay); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int get_path_len(const void *fdt, int nodeoffset) ++{ ++ int len = 0, namelen; ++ const char *name; ++ ++ FDT_RO_PROBE(fdt); ++ ++ for (;;) { ++ name = fdt_get_name(fdt, nodeoffset, &namelen); ++ if (!name) ++ return namelen; ++ ++ /* root? we're done */ ++ if (namelen == 0) ++ break; ++ ++ nodeoffset = fdt_parent_offset(fdt, nodeoffset); ++ if (nodeoffset < 0) ++ return nodeoffset; ++ len += namelen + 1; ++ } ++ ++ /* in case of root pretend it's "/" */ ++ if (len == 0) ++ len++; ++ return len; ++} ++ ++/** ++ * overlay_symbol_update - Update the symbols of base tree after a merge ++ * @fdt: Base Device Tree blob ++ * @fdto: Device tree overlay blob ++ * ++ * overlay_symbol_update() updates the symbols of the base tree with the ++ * symbols of the applied overlay ++ * ++ * This is the last step in the device tree overlay application ++ * process, allowing the reference of overlay symbols by subsequent ++ * overlay operations. ++ * ++ * returns: ++ * 0 on success ++ * Negative error code on failure ++ */ ++static int overlay_symbol_update(void *fdt, void *fdto) ++{ ++ int root_sym, ov_sym, prop, path_len, fragment, target; ++ int len, frag_name_len, ret, rel_path_len; ++ const char *s, *e; ++ const char *path; ++ const char *name; ++ const char *frag_name; ++ const char *rel_path; ++ const char *target_path; ++ char *buf; ++ void *p; ++ ++ ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); ++ ++ /* if no overlay symbols exist no problem */ ++ if (ov_sym < 0) ++ return 0; ++ ++ root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); ++ ++ /* it no root symbols exist we should create them */ ++ if (root_sym == -FDT_ERR_NOTFOUND) ++ root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); ++ ++ /* any error is fatal now */ ++ if (root_sym < 0) ++ return root_sym; ++ ++ /* iterate over each overlay symbol */ ++ fdt_for_each_property_offset(prop, fdto, ov_sym) { ++ path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); ++ if (!path) ++ return path_len; ++ ++ /* verify it's a string property (terminated by a single \0) */ ++ if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) ++ return -FDT_ERR_BADVALUE; ++ ++ /* keep end marker to avoid strlen() */ ++ e = path + path_len; ++ ++ if (*path != '/') ++ return -FDT_ERR_BADVALUE; ++ ++ /* get fragment name first */ ++ s = strchr(path + 1, '/'); ++ if (!s) { ++ /* Symbol refers to something that won't end ++ * up in the target tree */ ++ continue; ++ } ++ ++ frag_name = path + 1; ++ frag_name_len = s - path - 1; ++ ++ /* verify format; safe since "s" lies in \0 terminated prop */ ++ len = sizeof("/__overlay__/") - 1; ++ if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { ++ /* //__overlay__/ */ ++ rel_path = s + len; ++ rel_path_len = e - rel_path - 1; ++ } else if ((e - s) == len ++ && (memcmp(s, "/__overlay__", len - 1) == 0)) { ++ /* //__overlay__ */ ++ rel_path = ""; ++ rel_path_len = 0; ++ } else { ++ /* Symbol refers to something that won't end ++ * up in the target tree */ ++ continue; ++ } ++ ++ /* find the fragment index in which the symbol lies */ ++ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, ++ frag_name_len); ++ /* not found? */ ++ if (ret < 0) ++ return -FDT_ERR_BADOVERLAY; ++ fragment = ret; ++ ++ /* an __overlay__ subnode must exist */ ++ ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); ++ if (ret < 0) ++ return -FDT_ERR_BADOVERLAY; ++ ++ /* get the target of the fragment */ ++ ret = overlay_get_target(fdt, fdto, fragment, &target_path); ++ if (ret < 0) ++ return ret; ++ target = ret; ++ ++ /* if we have a target path use */ ++ if (!target_path) { ++ ret = get_path_len(fdt, target); ++ if (ret < 0) ++ return ret; ++ len = ret; ++ } else { ++ len = strlen(target_path); ++ } ++ ++ ret = fdt_setprop_placeholder(fdt, root_sym, name, ++ len + (len > 1) + rel_path_len + 1, &p); ++ if (ret < 0) ++ return ret; ++ ++ if (!target_path) { ++ /* again in case setprop_placeholder changed it */ ++ ret = overlay_get_target(fdt, fdto, fragment, &target_path); ++ if (ret < 0) ++ return ret; ++ target = ret; ++ } ++ ++ buf = p; ++ if (len > 1) { /* target is not root */ ++ if (!target_path) { ++ ret = fdt_get_path(fdt, target, buf, len + 1); ++ if (ret < 0) ++ return ret; ++ } else ++ memcpy(buf, target_path, len + 1); ++ ++ } else ++ len--; ++ ++ buf[len] = '/'; ++ memcpy(buf + len + 1, rel_path, rel_path_len); ++ buf[len + 1 + rel_path_len] = '\0'; ++ } ++ ++ return 0; ++} ++ ++int fdt_overlay_apply(void *fdt, void *fdto) ++{ ++ uint32_t delta; ++ int ret; ++ ++ FDT_RO_PROBE(fdt); ++ FDT_RO_PROBE(fdto); ++ ++ ret = fdt_find_max_phandle(fdt, &delta); ++ if (ret) ++ goto err; ++ ++ ret = overlay_adjust_local_phandles(fdto, delta); ++ if (ret) ++ goto err; ++ ++ ret = overlay_update_local_references(fdto, delta); ++ if (ret) ++ goto err; ++ ++ ret = overlay_fixup_phandles(fdt, fdto); ++ if (ret) ++ goto err; ++ ++ ret = overlay_merge(fdt, fdto); ++ if (ret) ++ goto err; ++ ++ ret = overlay_symbol_update(fdt, fdto); ++ if (ret) ++ goto err; ++ ++ /* ++ * The overlay has been damaged, erase its magic. ++ */ ++ fdt_set_magic(fdto, ~0); ++ ++ return 0; ++ ++err: ++ /* ++ * The overlay might have been damaged, erase its magic. ++ */ ++ fdt_set_magic(fdto, ~0); ++ ++ /* ++ * The base device tree might have been damaged, erase its ++ * magic. ++ */ ++ fdt_set_magic(fdt, ~0); ++ ++ return ret; ++} +diff --git a/common/libfdt/fdt_ro.c b/common/libfdt/fdt_ro.c +new file mode 100644 +index 0000000..17584da +--- /dev/null ++++ b/common/libfdt/fdt_ro.c +@@ -0,0 +1,859 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++static int fdt_nodename_eq_(const void *fdt, int offset, ++ const char *s, int len) ++{ ++ int olen; ++ const char *p = fdt_get_name(fdt, offset, &olen); ++ ++ if (!p || olen < len) ++ /* short match */ ++ return 0; ++ ++ if (memcmp(p, s, len) != 0) ++ return 0; ++ ++ if (p[len] == '\0') ++ return 1; ++ else if (!memchr(s, '@', len) && (p[len] == '@')) ++ return 1; ++ else ++ return 0; ++} ++ ++const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) ++{ ++ int32_t totalsize; ++ uint32_t absoffset; ++ size_t len; ++ int err; ++ const char *s, *n; ++ ++ if (can_assume(VALID_INPUT)) { ++ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; ++ ++ if (lenp) ++ *lenp = strlen(s); ++ return s; ++ } ++ totalsize = fdt_ro_probe_(fdt); ++ err = totalsize; ++ if (totalsize < 0) ++ goto fail; ++ ++ err = -FDT_ERR_BADOFFSET; ++ absoffset = stroffset + fdt_off_dt_strings(fdt); ++ if (absoffset >= (unsigned)totalsize) ++ goto fail; ++ len = totalsize - absoffset; ++ ++ if (fdt_magic(fdt) == FDT_MAGIC) { ++ if (stroffset < 0) ++ goto fail; ++ if (can_assume(LATEST) || fdt_version(fdt) >= 17) { ++ if ((unsigned)stroffset >= fdt_size_dt_strings(fdt)) ++ goto fail; ++ if ((fdt_size_dt_strings(fdt) - stroffset) < len) ++ len = fdt_size_dt_strings(fdt) - stroffset; ++ } ++ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { ++ unsigned int sw_stroffset = -stroffset; ++ ++ if ((stroffset >= 0) || ++ (sw_stroffset > fdt_size_dt_strings(fdt))) ++ goto fail; ++ if (sw_stroffset < len) ++ len = sw_stroffset; ++ } else { ++ err = -FDT_ERR_INTERNAL; ++ goto fail; ++ } ++ ++ s = (const char *)fdt + absoffset; ++ n = memchr(s, '\0', len); ++ if (!n) { ++ /* missing terminating NULL */ ++ err = -FDT_ERR_TRUNCATED; ++ goto fail; ++ } ++ ++ if (lenp) ++ *lenp = n - s; ++ return s; ++ ++fail: ++ if (lenp) ++ *lenp = err; ++ return NULL; ++} ++ ++const char *fdt_string(const void *fdt, int stroffset) ++{ ++ return fdt_get_string(fdt, stroffset, NULL); ++} ++ ++static int fdt_string_eq_(const void *fdt, int stroffset, ++ const char *s, int len) ++{ ++ int slen; ++ const char *p = fdt_get_string(fdt, stroffset, &slen); ++ ++ return p && (slen == len) && (memcmp(p, s, len) == 0); ++} ++ ++int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) ++{ ++ uint32_t max = 0; ++ int offset = -1; ++ ++ while (true) { ++ uint32_t value; ++ ++ offset = fdt_next_node(fdt, offset, NULL); ++ if (offset < 0) { ++ if (offset == -FDT_ERR_NOTFOUND) ++ break; ++ ++ return offset; ++ } ++ ++ value = fdt_get_phandle(fdt, offset); ++ ++ if (value > max) ++ max = value; ++ } ++ ++ if (phandle) ++ *phandle = max; ++ ++ return 0; ++} ++ ++int fdt_generate_phandle(const void *fdt, uint32_t *phandle) ++{ ++ uint32_t max; ++ int err; ++ ++ err = fdt_find_max_phandle(fdt, &max); ++ if (err < 0) ++ return err; ++ ++ if (max == FDT_MAX_PHANDLE) ++ return -FDT_ERR_NOPHANDLES; ++ ++ if (phandle) ++ *phandle = max + 1; ++ ++ return 0; ++} ++ ++static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) ++{ ++ unsigned int offset = n * sizeof(struct fdt_reserve_entry); ++ unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset; ++ ++ if (!can_assume(VALID_INPUT)) { ++ if (absoffset < fdt_off_mem_rsvmap(fdt)) ++ return NULL; ++ if (absoffset > fdt_totalsize(fdt) - ++ sizeof(struct fdt_reserve_entry)) ++ return NULL; ++ } ++ return fdt_mem_rsv_(fdt, n); ++} ++ ++int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) ++{ ++ const struct fdt_reserve_entry *re; ++ ++ FDT_RO_PROBE(fdt); ++ re = fdt_mem_rsv(fdt, n); ++ if (!can_assume(VALID_INPUT) && !re) ++ return -FDT_ERR_BADOFFSET; ++ ++ *address = fdt64_ld_(&re->address); ++ *size = fdt64_ld_(&re->size); ++ return 0; ++} ++ ++int fdt_num_mem_rsv(const void *fdt) ++{ ++ int i; ++ const struct fdt_reserve_entry *re; ++ ++ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { ++ if (fdt64_ld_(&re->size) == 0) ++ return i; ++ } ++ return -FDT_ERR_TRUNCATED; ++} ++ ++static int nextprop_(const void *fdt, int offset) ++{ ++ uint32_t tag; ++ int nextoffset; ++ ++ do { ++ tag = fdt_next_tag(fdt, offset, &nextoffset); ++ ++ switch (tag) { ++ case FDT_END: ++ if (nextoffset >= 0) ++ return -FDT_ERR_BADSTRUCTURE; ++ else ++ return nextoffset; ++ ++ case FDT_PROP: ++ return offset; ++ } ++ offset = nextoffset; ++ } while (tag == FDT_NOP); ++ ++ return -FDT_ERR_NOTFOUND; ++} ++ ++int fdt_subnode_offset_namelen(const void *fdt, int offset, ++ const char *name, int namelen) ++{ ++ int depth; ++ ++ FDT_RO_PROBE(fdt); ++ ++ for (depth = 0; ++ (offset >= 0) && (depth >= 0); ++ offset = fdt_next_node(fdt, offset, &depth)) ++ if ((depth == 1) ++ && fdt_nodename_eq_(fdt, offset, name, namelen)) ++ return offset; ++ ++ if (depth < 0) ++ return -FDT_ERR_NOTFOUND; ++ return offset; /* error */ ++} ++ ++int fdt_subnode_offset(const void *fdt, int parentoffset, ++ const char *name) ++{ ++ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); ++} ++ ++int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) ++{ ++ const char *end = path + namelen; ++ const char *p = path; ++ int offset = 0; ++ ++ FDT_RO_PROBE(fdt); ++ ++ /* see if we have an alias */ ++ if (*path != '/') { ++ const char *q = memchr(path, '/', end - p); ++ ++ if (!q) ++ q = end; ++ ++ p = fdt_get_alias_namelen(fdt, p, q - p); ++ if (!p) ++ return -FDT_ERR_BADPATH; ++ offset = fdt_path_offset(fdt, p); ++ ++ p = q; ++ } ++ ++ while (p < end) { ++ const char *q; ++ ++ while (*p == '/') { ++ p++; ++ if (p == end) ++ return offset; ++ } ++ q = memchr(p, '/', end - p); ++ if (! q) ++ q = end; ++ ++ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); ++ if (offset < 0) ++ return offset; ++ ++ p = q; ++ } ++ ++ return offset; ++} ++ ++int fdt_path_offset(const void *fdt, const char *path) ++{ ++ return fdt_path_offset_namelen(fdt, path, strlen(path)); ++} ++ ++const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) ++{ ++ const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); ++ const char *nameptr; ++ int err; ++ ++ if (((err = fdt_ro_probe_(fdt)) < 0) ++ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) ++ goto fail; ++ ++ nameptr = nh->name; ++ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { ++ /* ++ * For old FDT versions, match the naming conventions of V16: ++ * give only the leaf name (after all /). The actual tree ++ * contents are loosely checked. ++ */ ++ const char *leaf; ++ leaf = strrchr(nameptr, '/'); ++ if (leaf == NULL) { ++ err = -FDT_ERR_BADSTRUCTURE; ++ goto fail; ++ } ++ nameptr = leaf+1; ++ } ++ ++ if (len) ++ *len = strlen(nameptr); ++ ++ return nameptr; ++ ++ fail: ++ if (len) ++ *len = err; ++ return NULL; ++} ++ ++int fdt_first_property_offset(const void *fdt, int nodeoffset) ++{ ++ int offset; ++ ++ if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) ++ return offset; ++ ++ return nextprop_(fdt, offset); ++} ++ ++int fdt_next_property_offset(const void *fdt, int offset) ++{ ++ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) ++ return offset; ++ ++ return nextprop_(fdt, offset); ++} ++ ++static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, ++ int offset, ++ int *lenp) ++{ ++ int err; ++ const struct fdt_property *prop; ++ ++ if (!can_assume(VALID_INPUT) && ++ (err = fdt_check_prop_offset_(fdt, offset)) < 0) { ++ if (lenp) ++ *lenp = err; ++ return NULL; ++ } ++ ++ prop = fdt_offset_ptr_(fdt, offset); ++ ++ if (lenp) ++ *lenp = fdt32_ld_(&prop->len); ++ ++ return prop; ++} ++ ++const struct fdt_property *fdt_get_property_by_offset(const void *fdt, ++ int offset, ++ int *lenp) ++{ ++ /* Prior to version 16, properties may need realignment ++ * and this API does not work. fdt_getprop_*() will, however. */ ++ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { ++ if (lenp) ++ *lenp = -FDT_ERR_BADVERSION; ++ return NULL; ++ } ++ ++ return fdt_get_property_by_offset_(fdt, offset, lenp); ++} ++ ++static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, ++ int offset, ++ const char *name, ++ int namelen, ++ int *lenp, ++ int *poffset) ++{ ++ for (offset = fdt_first_property_offset(fdt, offset); ++ (offset >= 0); ++ (offset = fdt_next_property_offset(fdt, offset))) { ++ const struct fdt_property *prop; ++ ++ prop = fdt_get_property_by_offset_(fdt, offset, lenp); ++ if (!can_assume(LIBFDT_FLAWLESS) && !prop) { ++ offset = -FDT_ERR_INTERNAL; ++ break; ++ } ++ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff), ++ name, namelen)) { ++ if (poffset) ++ *poffset = offset; ++ return prop; ++ } ++ } ++ ++ if (lenp) ++ *lenp = offset; ++ return NULL; ++} ++ ++ ++const struct fdt_property *fdt_get_property_namelen(const void *fdt, ++ int offset, ++ const char *name, ++ int namelen, int *lenp) ++{ ++ /* Prior to version 16, properties may need realignment ++ * and this API does not work. fdt_getprop_*() will, however. */ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { ++ if (lenp) ++ *lenp = -FDT_ERR_BADVERSION; ++ return NULL; ++ } ++ ++ return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, ++ NULL); ++} ++ ++ ++const struct fdt_property *fdt_get_property(const void *fdt, ++ int nodeoffset, ++ const char *name, int *lenp) ++{ ++ return fdt_get_property_namelen(fdt, nodeoffset, name, ++ strlen(name), lenp); ++} ++ ++const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, ++ const char *name, int namelen, int *lenp) ++{ ++ int poffset; ++ const struct fdt_property *prop; ++ ++ prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, ++ &poffset); ++ if (!prop) ++ return NULL; ++ ++ /* Handle realignment */ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && ++ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) ++ return prop->data + 4; ++ return prop->data; ++} ++ ++const void *fdt_getprop_by_offset(const void *fdt, int offset, ++ const char **namep, int *lenp) ++{ ++ const struct fdt_property *prop; ++ ++ prop = fdt_get_property_by_offset_(fdt, offset, lenp); ++ if (!prop) ++ return NULL; ++ if (namep) { ++ const char *name; ++ int namelen; ++ ++ if (!can_assume(VALID_INPUT)) { ++ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff), ++ &namelen); ++ if (!name) { ++ if (lenp) ++ *lenp = namelen; ++ return NULL; ++ } ++ *namep = name; ++ } else { ++ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff)); ++ } ++ } ++ ++ /* Handle realignment */ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && ++ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) ++ return prop->data + 4; ++ return prop->data; ++} ++ ++const void *fdt_getprop(const void *fdt, int nodeoffset, ++ const char *name, int *lenp) ++{ ++ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); ++} ++ ++uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) ++{ ++ const fdt32_t *php; ++ int len; ++ ++ /* FIXME: This is a bit sub-optimal, since we potentially scan ++ * over all the properties twice. */ ++ php = fdt_getprop(fdt, nodeoffset, "phandle", &len); ++ if (!php || (len != sizeof(*php))) { ++ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); ++ if (!php || (len != sizeof(*php))) ++ return 0; ++ } ++ ++ return fdt32_ld_(php); ++} ++ ++const char *fdt_get_alias_namelen(const void *fdt, ++ const char *name, int namelen) ++{ ++ int aliasoffset; ++ ++ aliasoffset = fdt_path_offset(fdt, "/aliases"); ++ if (aliasoffset < 0) ++ return NULL; ++ ++ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); ++} ++ ++const char *fdt_get_alias(const void *fdt, const char *name) ++{ ++ return fdt_get_alias_namelen(fdt, name, strlen(name)); ++} ++ ++int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) ++{ ++ int pdepth = 0, p = 0; ++ int offset, depth, namelen; ++ const char *name; ++ ++ FDT_RO_PROBE(fdt); ++ ++ if (buflen < 2) ++ return -FDT_ERR_NOSPACE; ++ ++ for (offset = 0, depth = 0; ++ (offset >= 0) && (offset <= nodeoffset); ++ offset = fdt_next_node(fdt, offset, &depth)) { ++ while (pdepth > depth) { ++ do { ++ p--; ++ } while (buf[p-1] != '/'); ++ pdepth--; ++ } ++ ++ if (pdepth >= depth) { ++ name = fdt_get_name(fdt, offset, &namelen); ++ if (!name) ++ return namelen; ++ if ((p + namelen + 1) <= buflen) { ++ memcpy(buf + p, name, namelen); ++ p += namelen; ++ buf[p++] = '/'; ++ pdepth++; ++ } ++ } ++ ++ if (offset == nodeoffset) { ++ if (pdepth < (depth + 1)) ++ return -FDT_ERR_NOSPACE; ++ ++ if (p > 1) /* special case so that root path is "/", not "" */ ++ p--; ++ buf[p] = '\0'; ++ return 0; ++ } ++ } ++ ++ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) ++ return -FDT_ERR_BADOFFSET; ++ else if (offset == -FDT_ERR_BADOFFSET) ++ return -FDT_ERR_BADSTRUCTURE; ++ ++ return offset; /* error from fdt_next_node() */ ++} ++ ++int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, ++ int supernodedepth, int *nodedepth) ++{ ++ int offset, depth; ++ int supernodeoffset = -FDT_ERR_INTERNAL; ++ ++ FDT_RO_PROBE(fdt); ++ ++ if (supernodedepth < 0) ++ return -FDT_ERR_NOTFOUND; ++ ++ for (offset = 0, depth = 0; ++ (offset >= 0) && (offset <= nodeoffset); ++ offset = fdt_next_node(fdt, offset, &depth)) { ++ if (depth == supernodedepth) ++ supernodeoffset = offset; ++ ++ if (offset == nodeoffset) { ++ if (nodedepth) ++ *nodedepth = depth; ++ ++ if (supernodedepth > depth) ++ return -FDT_ERR_NOTFOUND; ++ else ++ return supernodeoffset; ++ } ++ } ++ ++ if (!can_assume(VALID_INPUT)) { ++ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) ++ return -FDT_ERR_BADOFFSET; ++ else if (offset == -FDT_ERR_BADOFFSET) ++ return -FDT_ERR_BADSTRUCTURE; ++ } ++ ++ return offset; /* error from fdt_next_node() */ ++} ++ ++int fdt_node_depth(const void *fdt, int nodeoffset) ++{ ++ int nodedepth; ++ int err; ++ ++ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); ++ if (err) ++ return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : ++ -FDT_ERR_INTERNAL; ++ return nodedepth; ++} ++ ++int fdt_parent_offset(const void *fdt, int nodeoffset) ++{ ++ int nodedepth = fdt_node_depth(fdt, nodeoffset); ++ ++ if (nodedepth < 0) ++ return nodedepth; ++ return fdt_supernode_atdepth_offset(fdt, nodeoffset, ++ nodedepth - 1, NULL); ++} ++ ++int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, ++ const char *propname, ++ const void *propval, int proplen) ++{ ++ int offset; ++ const void *val; ++ int len; ++ ++ FDT_RO_PROBE(fdt); ++ ++ /* FIXME: The algorithm here is pretty horrible: we scan each ++ * property of a node in fdt_getprop(), then if that didn't ++ * find what we want, we scan over them again making our way ++ * to the next node. Still it's the easiest to implement ++ * approach; performance can come later. */ ++ for (offset = fdt_next_node(fdt, startoffset, NULL); ++ offset >= 0; ++ offset = fdt_next_node(fdt, offset, NULL)) { ++ val = fdt_getprop(fdt, offset, propname, &len); ++ if (val && (len == proplen) ++ && (memcmp(val, propval, len) == 0)) ++ return offset; ++ } ++ ++ return offset; /* error from fdt_next_node() */ ++} ++ ++int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) ++{ ++ int offset; ++ ++ if ((phandle == 0) || (phandle == ~0U)) ++ return -FDT_ERR_BADPHANDLE; ++ ++ FDT_RO_PROBE(fdt); ++ ++ /* FIXME: The algorithm here is pretty horrible: we ++ * potentially scan each property of a node in ++ * fdt_get_phandle(), then if that didn't find what ++ * we want, we scan over them again making our way to the next ++ * node. Still it's the easiest to implement approach; ++ * performance can come later. */ ++ for (offset = fdt_next_node(fdt, -1, NULL); ++ offset >= 0; ++ offset = fdt_next_node(fdt, offset, NULL)) { ++ if (fdt_get_phandle(fdt, offset) == phandle) ++ return offset; ++ } ++ ++ return offset; /* error from fdt_next_node() */ ++} ++ ++int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) ++{ ++ int len = strlen(str); ++ const char *p; ++ ++ while (listlen >= len) { ++ if (memcmp(str, strlist, len+1) == 0) ++ return 1; ++ p = memchr(strlist, '\0', listlen); ++ if (!p) ++ return 0; /* malformed strlist.. */ ++ listlen -= (p-strlist) + 1; ++ strlist = p + 1; ++ } ++ return 0; ++} ++ ++int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) ++{ ++ const char *list, *end; ++ int length, count = 0; ++ ++ list = fdt_getprop(fdt, nodeoffset, property, &length); ++ if (!list) ++ return length; ++ ++ end = list + length; ++ ++ while (list < end) { ++ length = strnlen(list, end - list) + 1; ++ ++ /* Abort if the last string isn't properly NUL-terminated. */ ++ if (list + length > end) ++ return -FDT_ERR_BADVALUE; ++ ++ list += length; ++ count++; ++ } ++ ++ return count; ++} ++ ++int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, ++ const char *string) ++{ ++ int length, len, idx = 0; ++ const char *list, *end; ++ ++ list = fdt_getprop(fdt, nodeoffset, property, &length); ++ if (!list) ++ return length; ++ ++ len = strlen(string) + 1; ++ end = list + length; ++ ++ while (list < end) { ++ length = strnlen(list, end - list) + 1; ++ ++ /* Abort if the last string isn't properly NUL-terminated. */ ++ if (list + length > end) ++ return -FDT_ERR_BADVALUE; ++ ++ if (length == len && memcmp(list, string, length) == 0) ++ return idx; ++ ++ list += length; ++ idx++; ++ } ++ ++ return -FDT_ERR_NOTFOUND; ++} ++ ++const char *fdt_stringlist_get(const void *fdt, int nodeoffset, ++ const char *property, int idx, ++ int *lenp) ++{ ++ const char *list, *end; ++ int length; ++ ++ list = fdt_getprop(fdt, nodeoffset, property, &length); ++ if (!list) { ++ if (lenp) ++ *lenp = length; ++ ++ return NULL; ++ } ++ ++ end = list + length; ++ ++ while (list < end) { ++ length = strnlen(list, end - list) + 1; ++ ++ /* Abort if the last string isn't properly NUL-terminated. */ ++ if (list + length > end) { ++ if (lenp) ++ *lenp = -FDT_ERR_BADVALUE; ++ ++ return NULL; ++ } ++ ++ if (idx == 0) { ++ if (lenp) ++ *lenp = length - 1; ++ ++ return list; ++ } ++ ++ list += length; ++ idx--; ++ } ++ ++ if (lenp) ++ *lenp = -FDT_ERR_NOTFOUND; ++ ++ return NULL; ++} ++ ++int fdt_node_check_compatible(const void *fdt, int nodeoffset, ++ const char *compatible) ++{ ++ const void *prop; ++ int len; ++ ++ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); ++ if (!prop) ++ return len; ++ ++ return !fdt_stringlist_contains(prop, len, compatible); ++} ++ ++int fdt_node_offset_by_compatible(const void *fdt, int startoffset, ++ const char *compatible) ++{ ++ int offset, err; ++ ++ FDT_RO_PROBE(fdt); ++ ++ /* FIXME: The algorithm here is pretty horrible: we scan each ++ * property of a node in fdt_node_check_compatible(), then if ++ * that didn't find what we want, we scan over them again ++ * making our way to the next node. Still it's the easiest to ++ * implement approach; performance can come later. */ ++ for (offset = fdt_next_node(fdt, startoffset, NULL); ++ offset >= 0; ++ offset = fdt_next_node(fdt, offset, NULL)) { ++ err = fdt_node_check_compatible(fdt, offset, compatible); ++ if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) ++ return err; ++ else if (err == 0) ++ return offset; ++ } ++ ++ return offset; /* error from fdt_next_node() */ ++} +diff --git a/common/libfdt/fdt_rw.c b/common/libfdt/fdt_rw.c +new file mode 100644 +index 0000000..3621d36 +--- /dev/null ++++ b/common/libfdt/fdt_rw.c +@@ -0,0 +1,500 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++static int fdt_blocks_misordered_(const void *fdt, ++ int mem_rsv_size, int struct_size) ++{ ++ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) ++ || (fdt_off_dt_struct(fdt) < ++ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) ++ || (fdt_off_dt_strings(fdt) < ++ (fdt_off_dt_struct(fdt) + struct_size)) ++ || (fdt_totalsize(fdt) < ++ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); ++} ++ ++static int fdt_rw_probe_(void *fdt) ++{ ++ if (can_assume(VALID_DTB)) ++ return 0; ++ FDT_RO_PROBE(fdt); ++ ++ if (!can_assume(LATEST) && fdt_version(fdt) < 17) ++ return -FDT_ERR_BADVERSION; ++ if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), ++ fdt_size_dt_struct(fdt))) ++ return -FDT_ERR_BADLAYOUT; ++ if (!can_assume(LATEST) && fdt_version(fdt) > 17) ++ fdt_set_version(fdt, 17); ++ ++ return 0; ++} ++ ++#define FDT_RW_PROBE(fdt) \ ++ { \ ++ int err_; \ ++ if ((err_ = fdt_rw_probe_(fdt)) != 0) \ ++ return err_; \ ++ } ++ ++static inline unsigned int fdt_data_size_(void *fdt) ++{ ++ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); ++} ++ ++static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) ++{ ++ char *p = splicepoint; ++ unsigned int dsize = fdt_data_size_(fdt); ++ size_t soff = p - (char *)fdt; ++ ++ if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) ++ return -FDT_ERR_BADOFFSET; ++ if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) ++ return -FDT_ERR_BADOFFSET; ++ if (dsize - oldlen + newlen > fdt_totalsize(fdt)) ++ return -FDT_ERR_NOSPACE; ++ memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); ++ return 0; ++} ++ ++static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, ++ int oldn, int newn) ++{ ++ int delta = (newn - oldn) * sizeof(*p); ++ int err; ++ err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); ++ if (err) ++ return err; ++ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); ++ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); ++ return 0; ++} ++ ++static int fdt_splice_struct_(void *fdt, void *p, ++ int oldlen, int newlen) ++{ ++ int delta = newlen - oldlen; ++ int err; ++ ++ if ((err = fdt_splice_(fdt, p, oldlen, newlen))) ++ return err; ++ ++ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); ++ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); ++ return 0; ++} ++ ++/* Must only be used to roll back in case of error */ ++static void fdt_del_last_string_(void *fdt, const char *s) ++{ ++ int newlen = strlen(s) + 1; ++ ++ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); ++} ++ ++static int fdt_splice_string_(void *fdt, int newlen) ++{ ++ void *p = (char *)fdt ++ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); ++ int err; ++ ++ if ((err = fdt_splice_(fdt, p, 0, newlen))) ++ return err; ++ ++ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); ++ return 0; ++} ++ ++/** ++ * fdt_find_add_string_() - Find or allocate a string ++ * ++ * @fdt: pointer to the device tree to check/adjust ++ * @s: string to find/add ++ * @allocated: Set to 0 if the string was found, 1 if not found and so ++ * allocated. Ignored if can_assume(NO_ROLLBACK) ++ * @return offset of string in the string table (whether found or added) ++ */ ++static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) ++{ ++ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); ++ const char *p; ++ char *new; ++ int len = strlen(s) + 1; ++ int err; ++ ++ if (!can_assume(NO_ROLLBACK)) ++ *allocated = 0; ++ ++ p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); ++ if (p) ++ /* found it */ ++ return (p - strtab); ++ ++ new = strtab + fdt_size_dt_strings(fdt); ++ err = fdt_splice_string_(fdt, len); ++ if (err) ++ return err; ++ ++ if (!can_assume(NO_ROLLBACK)) ++ *allocated = 1; ++ ++ memcpy(new, s, len); ++ return (new - strtab); ++} ++ ++int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) ++{ ++ struct fdt_reserve_entry *re; ++ int err; ++ ++ FDT_RW_PROBE(fdt); ++ ++ re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); ++ err = fdt_splice_mem_rsv_(fdt, re, 0, 1); ++ if (err) ++ return err; ++ ++ re->address = cpu_to_fdt64(address); ++ re->size = cpu_to_fdt64(size); ++ return 0; ++} ++ ++int fdt_del_mem_rsv(void *fdt, int n) ++{ ++ struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); ++ ++ FDT_RW_PROBE(fdt); ++ ++ if (n >= fdt_num_mem_rsv(fdt)) ++ return -FDT_ERR_NOTFOUND; ++ ++ return fdt_splice_mem_rsv_(fdt, re, 1, 0); ++} ++ ++static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, ++ int len, struct fdt_property **prop) ++{ ++ int oldlen; ++ int err; ++ ++ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); ++ if (!*prop) ++ return oldlen; ++ ++ if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), ++ FDT_TAGALIGN(len)))) ++ return err; ++ ++ (*prop)->len = cpu_to_fdt32(len); ++ return 0; ++} ++ ++static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, ++ int len, struct fdt_property **prop) ++{ ++ int proplen; ++ int nextoffset; ++ int namestroff; ++ int err; ++ int allocated; ++ ++ if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) ++ return nextoffset; ++ ++ namestroff = fdt_find_add_string_(fdt, name, &allocated); ++ if (namestroff < 0) ++ return namestroff; ++ ++ *prop = fdt_offset_ptr_w_(fdt, nextoffset); ++ proplen = sizeof(**prop) + FDT_TAGALIGN(len); ++ ++ err = fdt_splice_struct_(fdt, *prop, 0, proplen); ++ if (err) { ++ /* Delete the string if we failed to add it */ ++ if (!can_assume(NO_ROLLBACK) && allocated) ++ fdt_del_last_string_(fdt, name); ++ return err; ++ } ++ ++ (*prop)->tag = cpu_to_fdt32(FDT_PROP); ++ (*prop)->nameoff = cpu_to_fdt32(namestroff); ++ (*prop)->len = cpu_to_fdt32(len); ++ return 0; ++} ++ ++int fdt_set_name(void *fdt, int nodeoffset, const char *name) ++{ ++ char *namep; ++ int oldlen, newlen; ++ int err; ++ ++ FDT_RW_PROBE(fdt); ++ ++ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); ++ if (!namep) ++ return oldlen; ++ ++ newlen = strlen(name); ++ ++ err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), ++ FDT_TAGALIGN(newlen+1)); ++ if (err) ++ return err; ++ ++ memcpy(namep, name, newlen+1); ++ return 0; ++} ++ ++int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, ++ int len, void **prop_data) ++{ ++ struct fdt_property *prop; ++ int err; ++ ++ FDT_RW_PROBE(fdt); ++ ++ err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); ++ if (err == -FDT_ERR_NOTFOUND) ++ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); ++ if (err) ++ return err; ++ ++ *prop_data = prop->data; ++ return 0; ++} ++ ++int fdt_setprop(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len) ++{ ++ void *prop_data; ++ int err; ++ ++ err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); ++ if (err) ++ return err; ++ ++ if (len) ++ memcpy(prop_data, val, len); ++ return 0; ++} ++ ++int fdt_appendprop(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len) ++{ ++ struct fdt_property *prop; ++ int err, oldlen, newlen; ++ ++ FDT_RW_PROBE(fdt); ++ ++ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); ++ if (prop) { ++ newlen = len + oldlen; ++ err = fdt_splice_struct_(fdt, prop->data, ++ FDT_TAGALIGN(oldlen), ++ FDT_TAGALIGN(newlen)); ++ if (err) ++ return err; ++ prop->len = cpu_to_fdt32(newlen); ++ memcpy(prop->data + oldlen, val, len); ++ } else { ++ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); ++ if (err) ++ return err; ++ memcpy(prop->data, val, len); ++ } ++ return 0; ++} ++ ++int fdt_delprop(void *fdt, int nodeoffset, const char *name) ++{ ++ struct fdt_property *prop; ++ int len, proplen; ++ ++ FDT_RW_PROBE(fdt); ++ ++ prop = fdt_get_property_w(fdt, nodeoffset, name, &len); ++ if (!prop) ++ return len; ++ ++ proplen = sizeof(*prop) + FDT_TAGALIGN(len); ++ return fdt_splice_struct_(fdt, prop, proplen, 0); ++} ++ ++int fdt_add_subnode_namelen(void *fdt, int parentoffset, ++ const char *name, int namelen) ++{ ++ struct fdt_node_header *nh; ++ int offset, nextoffset; ++ int nodelen; ++ int err; ++ uint32_t tag; ++ fdt32_t *endtag; ++ ++ FDT_RW_PROBE(fdt); ++ ++ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); ++ if (offset >= 0) ++ return -FDT_ERR_EXISTS; ++ else if (offset != -FDT_ERR_NOTFOUND) ++ return offset; ++ ++ /* Try to place the new node after the parent's properties */ ++ tag = fdt_next_tag(fdt, parentoffset, &nextoffset); ++ /* the fdt_subnode_offset_namelen() should ensure this never hits */ ++ if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE)) ++ return -FDT_ERR_INTERNAL; ++ do { ++ offset = nextoffset; ++ tag = fdt_next_tag(fdt, offset, &nextoffset); ++ } while ((tag == FDT_PROP) || (tag == FDT_NOP)); ++ ++ nh = fdt_offset_ptr_w_(fdt, offset); ++ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; ++ ++ err = fdt_splice_struct_(fdt, nh, 0, nodelen); ++ if (err) ++ return err; ++ ++ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); ++ memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); ++ memcpy(nh->name, name, namelen); ++ endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); ++ *endtag = cpu_to_fdt32(FDT_END_NODE); ++ ++ return offset; ++} ++ ++int fdt_add_subnode(void *fdt, int parentoffset, const char *name) ++{ ++ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); ++} ++ ++int fdt_del_node(void *fdt, int nodeoffset) ++{ ++ int endoffset; ++ ++ FDT_RW_PROBE(fdt); ++ ++ endoffset = fdt_node_end_offset_(fdt, nodeoffset); ++ if (endoffset < 0) ++ return endoffset; ++ ++ return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), ++ endoffset - nodeoffset, 0); ++} ++ ++static void fdt_packblocks_(const char *old, char *new, ++ int mem_rsv_size, ++ int struct_size, ++ int strings_size) ++{ ++ int mem_rsv_off, struct_off, strings_off; ++ ++ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); ++ struct_off = mem_rsv_off + mem_rsv_size; ++ strings_off = struct_off + struct_size; ++ ++ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); ++ fdt_set_off_mem_rsvmap(new, mem_rsv_off); ++ ++ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); ++ fdt_set_off_dt_struct(new, struct_off); ++ fdt_set_size_dt_struct(new, struct_size); ++ ++ memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size); ++ fdt_set_off_dt_strings(new, strings_off); ++ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); ++} ++ ++int fdt_open_into(const void *fdt, void *buf, int bufsize) ++{ ++ int err; ++ int mem_rsv_size, struct_size; ++ int newsize; ++ const char *fdtstart = fdt; ++ const char *fdtend = fdtstart + fdt_totalsize(fdt); ++ char *tmp; ++ ++ FDT_RO_PROBE(fdt); ++ ++ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) ++ * sizeof(struct fdt_reserve_entry); ++ ++ if (can_assume(LATEST) || fdt_version(fdt) >= 17) { ++ struct_size = fdt_size_dt_struct(fdt); ++ } else if (fdt_version(fdt) == 16) { ++ struct_size = 0; ++ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) ++ ; ++ if (struct_size < 0) ++ return struct_size; ++ } else { ++ return -FDT_ERR_BADVERSION; ++ } ++ ++ if (can_assume(LIBFDT_ORDER) || ++ !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { ++ /* no further work necessary */ ++ err = fdt_move(fdt, buf, bufsize); ++ if (err) ++ return err; ++ fdt_set_version(buf, 17); ++ fdt_set_size_dt_struct(buf, struct_size); ++ fdt_set_totalsize(buf, bufsize); ++ return 0; ++ } ++ ++ /* Need to reorder */ ++ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size ++ + struct_size + fdt_size_dt_strings(fdt); ++ ++ if (bufsize < newsize) ++ return -FDT_ERR_NOSPACE; ++ ++ /* First attempt to build converted tree at beginning of buffer */ ++ tmp = buf; ++ /* But if that overlaps with the old tree... */ ++ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { ++ /* Try right after the old tree instead */ ++ tmp = (char *)(uintptr_t)fdtend; ++ if ((tmp + newsize) > ((char *)buf + bufsize)) ++ return -FDT_ERR_NOSPACE; ++ } ++ ++ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size, ++ fdt_size_dt_strings(fdt)); ++ memmove(buf, tmp, newsize); ++ ++ fdt_set_magic(buf, FDT_MAGIC); ++ fdt_set_totalsize(buf, bufsize); ++ fdt_set_version(buf, 17); ++ fdt_set_last_comp_version(buf, 16); ++ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); ++ ++ return 0; ++} ++ ++int fdt_pack(void *fdt) ++{ ++ int mem_rsv_size; ++ ++ FDT_RW_PROBE(fdt); ++ ++ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) ++ * sizeof(struct fdt_reserve_entry); ++ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt), ++ fdt_size_dt_strings(fdt)); ++ fdt_set_totalsize(fdt, fdt_data_size_(fdt)); ++ ++ return 0; ++} +diff --git a/common/libfdt/fdt_strerror.c b/common/libfdt/fdt_strerror.c +new file mode 100644 +index 0000000..b435693 +--- /dev/null ++++ b/common/libfdt/fdt_strerror.c +@@ -0,0 +1,59 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++struct fdt_errtabent { ++ const char *str; ++}; ++ ++#define FDT_ERRTABENT(val) \ ++ [(val)] = { .str = #val, } ++ ++static struct fdt_errtabent fdt_errtable[] = { ++ FDT_ERRTABENT(FDT_ERR_NOTFOUND), ++ FDT_ERRTABENT(FDT_ERR_EXISTS), ++ FDT_ERRTABENT(FDT_ERR_NOSPACE), ++ ++ FDT_ERRTABENT(FDT_ERR_BADOFFSET), ++ FDT_ERRTABENT(FDT_ERR_BADPATH), ++ FDT_ERRTABENT(FDT_ERR_BADPHANDLE), ++ FDT_ERRTABENT(FDT_ERR_BADSTATE), ++ ++ FDT_ERRTABENT(FDT_ERR_TRUNCATED), ++ FDT_ERRTABENT(FDT_ERR_BADMAGIC), ++ FDT_ERRTABENT(FDT_ERR_BADVERSION), ++ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), ++ FDT_ERRTABENT(FDT_ERR_BADLAYOUT), ++ FDT_ERRTABENT(FDT_ERR_INTERNAL), ++ FDT_ERRTABENT(FDT_ERR_BADNCELLS), ++ FDT_ERRTABENT(FDT_ERR_BADVALUE), ++ FDT_ERRTABENT(FDT_ERR_BADOVERLAY), ++ FDT_ERRTABENT(FDT_ERR_NOPHANDLES), ++ FDT_ERRTABENT(FDT_ERR_BADFLAGS), ++}; ++#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) ++ ++const char *fdt_strerror(int errval) ++{ ++ if (errval > 0) ++ return ""; ++ else if (errval == 0) ++ return ""; ++ else if (-errval < FDT_ERRTABSIZE) { ++ const char *s = fdt_errtable[-errval].str; ++ ++ if (s) ++ return s; ++ } ++ ++ return ""; ++} +diff --git a/common/libfdt/fdt_sw.c b/common/libfdt/fdt_sw.c +new file mode 100644 +index 0000000..4c569ee +--- /dev/null ++++ b/common/libfdt/fdt_sw.c +@@ -0,0 +1,384 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++static int fdt_sw_probe_(void *fdt) ++{ ++ if (!can_assume(VALID_INPUT)) { ++ if (fdt_magic(fdt) == FDT_MAGIC) ++ return -FDT_ERR_BADSTATE; ++ else if (fdt_magic(fdt) != FDT_SW_MAGIC) ++ return -FDT_ERR_BADMAGIC; ++ } ++ ++ return 0; ++} ++ ++#define FDT_SW_PROBE(fdt) \ ++ { \ ++ int err; \ ++ if ((err = fdt_sw_probe_(fdt)) != 0) \ ++ return err; \ ++ } ++ ++/* 'memrsv' state: Initial state after fdt_create() ++ * ++ * Allowed functions: ++ * fdt_add_reservemap_entry() ++ * fdt_finish_reservemap() [moves to 'struct' state] ++ */ ++static int fdt_sw_probe_memrsv_(void *fdt) ++{ ++ int err = fdt_sw_probe_(fdt); ++ if (err) ++ return err; ++ ++ if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) ++ return -FDT_ERR_BADSTATE; ++ return 0; ++} ++ ++#define FDT_SW_PROBE_MEMRSV(fdt) \ ++ { \ ++ int err; \ ++ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ ++ return err; \ ++ } ++ ++/* 'struct' state: Enter this state after fdt_finish_reservemap() ++ * ++ * Allowed functions: ++ * fdt_begin_node() ++ * fdt_end_node() ++ * fdt_property*() ++ * fdt_finish() [moves to 'complete' state] ++ */ ++static int fdt_sw_probe_struct_(void *fdt) ++{ ++ int err = fdt_sw_probe_(fdt); ++ if (err) ++ return err; ++ ++ if (!can_assume(VALID_INPUT) && ++ fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) ++ return -FDT_ERR_BADSTATE; ++ return 0; ++} ++ ++#define FDT_SW_PROBE_STRUCT(fdt) \ ++ { \ ++ int err; \ ++ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ ++ return err; \ ++ } ++ ++static inline uint32_t sw_flags(void *fdt) ++{ ++ /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ ++ return fdt_last_comp_version(fdt); ++} ++ ++/* 'complete' state: Enter this state after fdt_finish() ++ * ++ * Allowed functions: none ++ */ ++ ++static void *fdt_grab_space_(void *fdt, size_t len) ++{ ++ unsigned int offset = fdt_size_dt_struct(fdt); ++ unsigned int spaceleft; ++ ++ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) ++ - fdt_size_dt_strings(fdt); ++ ++ if ((offset + len < offset) || (offset + len > spaceleft)) ++ return NULL; ++ ++ fdt_set_size_dt_struct(fdt, offset + len); ++ return fdt_offset_ptr_w_(fdt, offset); ++} ++ ++int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) ++{ ++ const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), ++ sizeof(struct fdt_reserve_entry)); ++ void *fdt = buf; ++ ++ if (bufsize < hdrsize) ++ return -FDT_ERR_NOSPACE; ++ ++ if (flags & ~FDT_CREATE_FLAGS_ALL) ++ return -FDT_ERR_BADFLAGS; ++ ++ memset(buf, 0, bufsize); ++ ++ /* ++ * magic and last_comp_version keep intermediate state during the fdt ++ * creation process, which is replaced with the proper FDT format by ++ * fdt_finish(). ++ * ++ * flags should be accessed with sw_flags(). ++ */ ++ fdt_set_magic(fdt, FDT_SW_MAGIC); ++ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); ++ fdt_set_last_comp_version(fdt, flags); ++ ++ fdt_set_totalsize(fdt, bufsize); ++ ++ fdt_set_off_mem_rsvmap(fdt, hdrsize); ++ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); ++ fdt_set_off_dt_strings(fdt, 0); ++ ++ return 0; ++} ++ ++int fdt_create(void *buf, int bufsize) ++{ ++ return fdt_create_with_flags(buf, bufsize, 0); ++} ++ ++int fdt_resize(void *fdt, void *buf, int bufsize) ++{ ++ size_t headsize, tailsize; ++ char *oldtail, *newtail; ++ ++ FDT_SW_PROBE(fdt); ++ ++ if (bufsize < 0) ++ return -FDT_ERR_NOSPACE; ++ ++ headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); ++ tailsize = fdt_size_dt_strings(fdt); ++ ++ if (!can_assume(VALID_DTB) && ++ headsize + tailsize > fdt_totalsize(fdt)) ++ return -FDT_ERR_INTERNAL; ++ ++ if ((headsize + tailsize) > (unsigned)bufsize) ++ return -FDT_ERR_NOSPACE; ++ ++ oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; ++ newtail = (char *)buf + bufsize - tailsize; ++ ++ /* Two cases to avoid clobbering data if the old and new ++ * buffers partially overlap */ ++ if (buf <= fdt) { ++ memmove(buf, fdt, headsize); ++ memmove(newtail, oldtail, tailsize); ++ } else { ++ memmove(newtail, oldtail, tailsize); ++ memmove(buf, fdt, headsize); ++ } ++ ++ fdt_set_totalsize(buf, bufsize); ++ if (fdt_off_dt_strings(buf)) ++ fdt_set_off_dt_strings(buf, bufsize); ++ ++ return 0; ++} ++ ++int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) ++{ ++ struct fdt_reserve_entry *re; ++ int offset; ++ ++ FDT_SW_PROBE_MEMRSV(fdt); ++ ++ offset = fdt_off_dt_struct(fdt); ++ if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) ++ return -FDT_ERR_NOSPACE; ++ ++ re = (struct fdt_reserve_entry *)((char *)fdt + offset); ++ re->address = cpu_to_fdt64(addr); ++ re->size = cpu_to_fdt64(size); ++ ++ fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); ++ ++ return 0; ++} ++ ++int fdt_finish_reservemap(void *fdt) ++{ ++ int err = fdt_add_reservemap_entry(fdt, 0, 0); ++ ++ if (err) ++ return err; ++ ++ fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); ++ return 0; ++} ++ ++int fdt_begin_node(void *fdt, const char *name) ++{ ++ struct fdt_node_header *nh; ++ int namelen; ++ ++ FDT_SW_PROBE_STRUCT(fdt); ++ ++ namelen = strlen(name) + 1; ++ nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); ++ if (! nh) ++ return -FDT_ERR_NOSPACE; ++ ++ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); ++ memcpy(nh->name, name, namelen); ++ return 0; ++} ++ ++int fdt_end_node(void *fdt) ++{ ++ fdt32_t *en; ++ ++ FDT_SW_PROBE_STRUCT(fdt); ++ ++ en = fdt_grab_space_(fdt, FDT_TAGSIZE); ++ if (! en) ++ return -FDT_ERR_NOSPACE; ++ ++ *en = cpu_to_fdt32(FDT_END_NODE); ++ return 0; ++} ++ ++static int fdt_add_string_(void *fdt, const char *s) ++{ ++ char *strtab = (char *)fdt + fdt_totalsize(fdt); ++ unsigned int strtabsize = fdt_size_dt_strings(fdt); ++ unsigned int len = strlen(s) + 1; ++ unsigned int struct_top, offset; ++ ++ offset = strtabsize + len; ++ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); ++ if (fdt_totalsize(fdt) - offset < struct_top) ++ return 0; /* no more room :( */ ++ ++ memcpy(strtab - offset, s, len); ++ fdt_set_size_dt_strings(fdt, strtabsize + len); ++ return -offset; ++} ++ ++/* Must only be used to roll back in case of error */ ++static void fdt_del_last_string_(void *fdt, const char *s) ++{ ++ int strtabsize = fdt_size_dt_strings(fdt); ++ int len = strlen(s) + 1; ++ ++ fdt_set_size_dt_strings(fdt, strtabsize - len); ++} ++ ++static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) ++{ ++ char *strtab = (char *)fdt + fdt_totalsize(fdt); ++ int strtabsize = fdt_size_dt_strings(fdt); ++ const char *p; ++ ++ *allocated = 0; ++ ++ p = fdt_find_string_(strtab - strtabsize, strtabsize, s); ++ if (p) ++ return p - strtab; ++ ++ *allocated = 1; ++ ++ return fdt_add_string_(fdt, s); ++} ++ ++int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) ++{ ++ struct fdt_property *prop; ++ int nameoff; ++ int allocated; ++ ++ FDT_SW_PROBE_STRUCT(fdt); ++ ++ /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ ++ if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { ++ allocated = 1; ++ nameoff = fdt_add_string_(fdt, name); ++ } else { ++ nameoff = fdt_find_add_string_(fdt, name, &allocated); ++ } ++ if (nameoff == 0) ++ return -FDT_ERR_NOSPACE; ++ ++ prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); ++ if (! prop) { ++ if (allocated) ++ fdt_del_last_string_(fdt, name); ++ return -FDT_ERR_NOSPACE; ++ } ++ ++ prop->tag = cpu_to_fdt32(FDT_PROP); ++ prop->nameoff = cpu_to_fdt32(nameoff); ++ prop->len = cpu_to_fdt32(len); ++ *valp = prop->data; ++ return 0; ++} ++ ++int fdt_property(void *fdt, const char *name, const void *val, int len) ++{ ++ void *ptr; ++ int ret; ++ ++ ret = fdt_property_placeholder(fdt, name, len, &ptr); ++ if (ret) ++ return ret; ++ memcpy(ptr, val, len); ++ return 0; ++} ++ ++int fdt_finish(void *fdt) ++{ ++ char *p = (char *)fdt; ++ fdt32_t *end; ++ int oldstroffset, newstroffset; ++ uint32_t tag; ++ int offset, nextoffset; ++ ++ FDT_SW_PROBE_STRUCT(fdt); ++ ++ /* Add terminator */ ++ end = fdt_grab_space_(fdt, sizeof(*end)); ++ if (! end) ++ return -FDT_ERR_NOSPACE; ++ *end = cpu_to_fdt32(FDT_END); ++ ++ /* Relocate the string table */ ++ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); ++ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); ++ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); ++ fdt_set_off_dt_strings(fdt, newstroffset); ++ ++ /* Walk the structure, correcting string offsets */ ++ offset = 0; ++ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { ++ if (tag == FDT_PROP) { ++ struct fdt_property *prop = ++ fdt_offset_ptr_w_(fdt, offset); ++ int nameoff; ++ ++ nameoff = fdt32_to_cpu(prop->nameoff); ++ nameoff += fdt_size_dt_strings(fdt); ++ prop->nameoff = cpu_to_fdt32(nameoff); ++ } ++ offset = nextoffset; ++ } ++ if (nextoffset < 0) ++ return nextoffset; ++ ++ /* Finally, adjust the header */ ++ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); ++ ++ /* And fix up fields that were keeping intermediate state. */ ++ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION); ++ fdt_set_magic(fdt, FDT_MAGIC); ++ ++ return 0; ++} +diff --git a/common/libfdt/fdt_wip.c b/common/libfdt/fdt_wip.c +new file mode 100644 +index 0000000..c2d7566 +--- /dev/null ++++ b/common/libfdt/fdt_wip.c +@@ -0,0 +1,94 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include "libfdt_env.h" ++ ++#include ++#include ++ ++#include "libfdt_internal.h" ++ ++int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, ++ const char *name, int namelen, ++ uint32_t idx, const void *val, ++ int len) ++{ ++ void *propval; ++ int proplen; ++ ++ propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, ++ &proplen); ++ if (!propval) ++ return proplen; ++ ++ if ((unsigned)proplen < (len + idx)) ++ return -FDT_ERR_NOSPACE; ++ ++ memcpy((char *)propval + idx, val, len); ++ return 0; ++} ++ ++int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len) ++{ ++ const void *propval; ++ int proplen; ++ ++ propval = fdt_getprop(fdt, nodeoffset, name, &proplen); ++ if (!propval) ++ return proplen; ++ ++ if (proplen != len) ++ return -FDT_ERR_NOSPACE; ++ ++ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, ++ strlen(name), 0, ++ val, len); ++} ++ ++static void fdt_nop_region_(void *start, int len) ++{ ++ fdt32_t *p; ++ ++ for (p = start; (char *)p < ((char *)start + len); p++) ++ *p = cpu_to_fdt32(FDT_NOP); ++} ++ ++int fdt_nop_property(void *fdt, int nodeoffset, const char *name) ++{ ++ struct fdt_property *prop; ++ int len; ++ ++ prop = fdt_get_property_w(fdt, nodeoffset, name, &len); ++ if (!prop) ++ return len; ++ ++ fdt_nop_region_(prop, len + sizeof(*prop)); ++ ++ return 0; ++} ++ ++int fdt_node_end_offset_(void *fdt, int offset) ++{ ++ int depth = 0; ++ ++ while ((offset >= 0) && (depth >= 0)) ++ offset = fdt_next_node(fdt, offset, &depth); ++ ++ return offset; ++} ++ ++int fdt_nop_node(void *fdt, int nodeoffset) ++{ ++ int endoffset; ++ ++ endoffset = fdt_node_end_offset_(fdt, nodeoffset); ++ if (endoffset < 0) ++ return endoffset; ++ ++ fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), ++ endoffset - nodeoffset); ++ return 0; ++} +diff --git a/common/libfdt/libfdt_internal.h b/common/libfdt/libfdt_internal.h +new file mode 100644 +index 0000000..16bda19 +--- /dev/null ++++ b/common/libfdt/libfdt_internal.h +@@ -0,0 +1,192 @@ ++/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ ++#ifndef LIBFDT_INTERNAL_H ++#define LIBFDT_INTERNAL_H ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++#include ++ ++#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) ++#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) ++ ++int32_t fdt_ro_probe_(const void *fdt); ++#define FDT_RO_PROBE(fdt) \ ++ { \ ++ int32_t totalsize_; \ ++ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ ++ return totalsize_; \ ++ } ++ ++int fdt_check_node_offset_(const void *fdt, int offset); ++int fdt_check_prop_offset_(const void *fdt, int offset); ++const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); ++int fdt_node_end_offset_(void *fdt, int nodeoffset); ++ ++static inline const void *fdt_offset_ptr_(const void *fdt, int offset) ++{ ++ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; ++} ++ ++static inline void *fdt_offset_ptr_w_(void *fdt, int offset) ++{ ++ return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); ++} ++ ++static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) ++{ ++ const struct fdt_reserve_entry *rsv_table = ++ (const struct fdt_reserve_entry *) ++ ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); ++ ++ return rsv_table + n; ++} ++static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) ++{ ++ return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); ++} ++ ++/* ++ * Internal helpers to access tructural elements of the device tree ++ * blob (rather than for exaple reading integers from within property ++ * values). We assume that we are either given a naturally aligned ++ * address for the platform or if we are not, we are on a platform ++ * where unaligned memory reads will be handled in a graceful manner. ++ * If not the external helpers fdtXX_ld() from libfdt.h can be used ++ * instead. ++ */ ++static inline uint32_t fdt32_ld_(const fdt32_t *p) ++{ ++ return fdt32_to_cpu(*p); ++} ++ ++static inline uint64_t fdt64_ld_(const fdt64_t *p) ++{ ++ return fdt64_to_cpu(*p); ++} ++ ++#define FDT_SW_MAGIC (~FDT_MAGIC) ++ ++/**********************************************************************/ ++/* Checking controls */ ++/**********************************************************************/ ++ ++#ifndef FDT_ASSUME_MASK ++#define FDT_ASSUME_MASK 0 ++#endif ++ ++/* ++ * Defines assumptions which can be enabled. Each of these can be enabled ++ * individually. For maximum safety, don't enable any assumptions! ++ * ++ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. ++ * You should have another method of validating the device tree, such as a ++ * signature or hash check before using libfdt. ++ * ++ * For situations where security is not a concern it may be safe to enable ++ * ASSUME_SANE. ++ */ ++enum { ++ /* ++ * This does essentially no checks. Only the latest device-tree ++ * version is correctly handled. Inconsistencies or errors in the device ++ * tree may cause undefined behaviour or crashes. Invalid parameters ++ * passed to libfdt may do the same. ++ * ++ * If an error occurs when modifying the tree it may leave the tree in ++ * an intermediate (but valid) state. As an example, adding a property ++ * where there is insufficient space may result in the property name ++ * being added to the string table even though the property itself is ++ * not added to the struct section. ++ * ++ * Only use this if you have a fully validated device tree with ++ * the latest supported version and wish to minimise code size. ++ */ ++ ASSUME_PERFECT = 0xff, ++ ++ /* ++ * This assumes that the device tree is sane. i.e. header metadata ++ * and basic hierarchy are correct. ++ * ++ * With this assumption enabled, normal device trees produced by libfdt ++ * and the compiler should be handled safely. Malicious device trees and ++ * complete garbage may cause libfdt to behave badly or crash. Truncated ++ * device trees (e.g. those only partially loaded) can also cause ++ * problems. ++ * ++ * Note: Only checks that relate exclusively to the device tree itself ++ * (not the parameters passed to libfdt) are disabled by this ++ * assumption. This includes checking headers, tags and the like. ++ */ ++ ASSUME_VALID_DTB = 1 << 0, ++ ++ /* ++ * This builds on ASSUME_VALID_DTB and further assumes that libfdt ++ * functions are called with valid parameters, i.e. not trigger ++ * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any ++ * extensive checking of parameters and the device tree, making various ++ * assumptions about correctness. ++ * ++ * It doesn't make sense to enable this assumption unless ++ * ASSUME_VALID_DTB is also enabled. ++ */ ++ ASSUME_VALID_INPUT = 1 << 1, ++ ++ /* ++ * This disables checks for device-tree version and removes all code ++ * which handles older versions. ++ * ++ * Only enable this if you know you have a device tree with the latest ++ * version. ++ */ ++ ASSUME_LATEST = 1 << 2, ++ ++ /* ++ * This assumes that it is OK for a failed addition to the device tree, ++ * due to lack of space or some other problem, to skip any rollback ++ * steps (such as dropping the property name from the string table). ++ * This is safe to enable in most circumstances, even though it may ++ * leave the tree in a sub-optimal state. ++ */ ++ ASSUME_NO_ROLLBACK = 1 << 3, ++ ++ /* ++ * This assumes that the device tree components appear in a 'convenient' ++ * order, i.e. the memory reservation block first, then the structure ++ * block and finally the string block. ++ * ++ * This order is not specified by the device-tree specification, ++ * but is expected by libfdt. The device-tree compiler always created ++ * device trees with this order. ++ * ++ * This assumption disables a check in fdt_open_into() and removes the ++ * ability to fix the problem there. This is safe if you know that the ++ * device tree is correctly ordered. See fdt_blocks_misordered_(). ++ */ ++ ASSUME_LIBFDT_ORDER = 1 << 4, ++ ++ /* ++ * This assumes that libfdt itself does not have any internal bugs. It ++ * drops certain checks that should never be needed unless libfdt has an ++ * undiscovered bug. ++ * ++ * This can generally be considered safe to enable. ++ */ ++ ASSUME_LIBFDT_FLAWLESS = 1 << 5, ++}; ++ ++/** ++ * can_assume_() - check if a particular assumption is enabled ++ * ++ * @mask: Mask to check (ASSUME_...) ++ * @return true if that assumption is enabled, else false ++ */ ++static inline bool can_assume_(int mask) ++{ ++ return FDT_ASSUME_MASK & mask; ++} ++ ++/** helper macros for checking assumptions */ ++#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) ++ ++#endif /* LIBFDT_INTERNAL_H */ +diff --git a/include/fdt.h b/include/fdt.h +new file mode 100644 +index 0000000..f2e6880 +--- /dev/null ++++ b/include/fdt.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ ++#ifndef FDT_H ++#define FDT_H ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ * Copyright 2012 Kim Phillips, Freescale Semiconductor. ++ */ ++ ++#ifndef __ASSEMBLY__ ++ ++struct fdt_header { ++ fdt32_t magic; /* magic word FDT_MAGIC */ ++ fdt32_t totalsize; /* total size of DT block */ ++ fdt32_t off_dt_struct; /* offset to structure */ ++ fdt32_t off_dt_strings; /* offset to strings */ ++ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ ++ fdt32_t version; /* format version */ ++ fdt32_t last_comp_version; /* last compatible version */ ++ ++ /* version 2 fields below */ ++ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're ++ booting on */ ++ /* version 3 fields below */ ++ fdt32_t size_dt_strings; /* size of the strings block */ ++ ++ /* version 17 fields below */ ++ fdt32_t size_dt_struct; /* size of the structure block */ ++}; ++ ++struct fdt_reserve_entry { ++ fdt64_t address; ++ fdt64_t size; ++}; ++ ++struct fdt_node_header { ++ fdt32_t tag; ++ char name[0]; ++}; ++ ++struct fdt_property { ++ fdt32_t tag; ++ fdt32_t len; ++ fdt32_t nameoff; ++ char data[0]; ++}; ++ ++#endif /* !__ASSEMBLY */ ++ ++#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ ++#define FDT_TAGSIZE sizeof(fdt32_t) ++ ++#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ ++#define FDT_END_NODE 0x2 /* End node */ ++#define FDT_PROP 0x3 /* Property: name off, ++ size, content */ ++#define FDT_NOP 0x4 /* nop */ ++#define FDT_END 0x9 ++ ++#define FDT_V1_SIZE (7*sizeof(fdt32_t)) ++#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) ++#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) ++#define FDT_V16_SIZE FDT_V3_SIZE ++#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) ++ ++#endif /* FDT_H */ +diff --git a/include/libfdt.h b/include/libfdt.h +new file mode 100644 +index 0000000..a7f432c +--- /dev/null ++++ b/include/libfdt.h +@@ -0,0 +1,2147 @@ ++/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ ++#ifndef LIBFDT_H ++#define LIBFDT_H ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ */ ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define FDT_FIRST_SUPPORTED_VERSION 0x02 ++#define FDT_LAST_COMPATIBLE_VERSION 0x10 ++#define FDT_LAST_SUPPORTED_VERSION 0x11 ++ ++/* Error codes: informative error codes */ ++#define FDT_ERR_NOTFOUND 1 ++ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ ++#define FDT_ERR_EXISTS 2 ++ /* FDT_ERR_EXISTS: Attempted to create a node or property which ++ * already exists */ ++#define FDT_ERR_NOSPACE 3 ++ /* FDT_ERR_NOSPACE: Operation needed to expand the device ++ * tree, but its buffer did not have sufficient space to ++ * contain the expanded tree. Use fdt_open_into() to move the ++ * device tree to a buffer with more space. */ ++ ++/* Error codes: codes for bad parameters */ ++#define FDT_ERR_BADOFFSET 4 ++ /* FDT_ERR_BADOFFSET: Function was passed a structure block ++ * offset which is out-of-bounds, or which points to an ++ * unsuitable part of the structure for the operation. */ ++#define FDT_ERR_BADPATH 5 ++ /* FDT_ERR_BADPATH: Function was passed a badly formatted path ++ * (e.g. missing a leading / for a function which requires an ++ * absolute path) */ ++#define FDT_ERR_BADPHANDLE 6 ++ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. ++ * This can be caused either by an invalid phandle property ++ * length, or the phandle value was either 0 or -1, which are ++ * not permitted. */ ++#define FDT_ERR_BADSTATE 7 ++ /* FDT_ERR_BADSTATE: Function was passed an incomplete device ++ * tree created by the sequential-write functions, which is ++ * not sufficiently complete for the requested operation. */ ++ ++/* Error codes: codes for bad device tree blobs */ ++#define FDT_ERR_TRUNCATED 8 ++ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly ++ * terminated (overflows, goes outside allowed bounds, or ++ * isn't properly terminated). */ ++#define FDT_ERR_BADMAGIC 9 ++ /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a ++ * device tree at all - it is missing the flattened device ++ * tree magic number. */ ++#define FDT_ERR_BADVERSION 10 ++ /* FDT_ERR_BADVERSION: Given device tree has a version which ++ * can't be handled by the requested operation. For ++ * read-write functions, this may mean that fdt_open_into() is ++ * required to convert the tree to the expected version. */ ++#define FDT_ERR_BADSTRUCTURE 11 ++ /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt ++ * structure block or other serious error (e.g. misnested ++ * nodes, or subnodes preceding properties). */ ++#define FDT_ERR_BADLAYOUT 12 ++ /* FDT_ERR_BADLAYOUT: For read-write functions, the given ++ * device tree has it's sub-blocks in an order that the ++ * function can't handle (memory reserve map, then structure, ++ * then strings). Use fdt_open_into() to reorganize the tree ++ * into a form suitable for the read-write operations. */ ++ ++/* "Can't happen" error indicating a bug in libfdt */ ++#define FDT_ERR_INTERNAL 13 ++ /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. ++ * Should never be returned, if it is, it indicates a bug in ++ * libfdt itself. */ ++ ++/* Errors in device tree content */ ++#define FDT_ERR_BADNCELLS 14 ++ /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells ++ * or similar property with a bad format or value */ ++ ++#define FDT_ERR_BADVALUE 15 ++ /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected ++ * value. For example: a property expected to contain a string list ++ * is not NUL-terminated within the length of its value. */ ++ ++#define FDT_ERR_BADOVERLAY 16 ++ /* FDT_ERR_BADOVERLAY: The device tree overlay, while ++ * correctly structured, cannot be applied due to some ++ * unexpected or missing value, property or node. */ ++ ++#define FDT_ERR_NOPHANDLES 17 ++ /* FDT_ERR_NOPHANDLES: The device tree doesn't have any ++ * phandle available anymore without causing an overflow */ ++ ++#define FDT_ERR_BADFLAGS 18 ++ /* FDT_ERR_BADFLAGS: The function was passed a flags field that ++ * contains invalid flags or an invalid combination of flags. */ ++ ++#define FDT_ERR_ALIGNMENT 19 ++ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte ++ * aligned. */ ++ ++#define FDT_ERR_MAX 19 ++ ++/* constants */ ++#define FDT_MAX_PHANDLE 0xfffffffe ++ /* Valid values for phandles range from 1 to 2^32-2. */ ++ ++/**********************************************************************/ ++/* Low-level functions (you probably don't need these) */ ++/**********************************************************************/ ++ ++#ifndef SWIG /* This function is not useful in Python */ ++const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); ++#endif ++static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) ++{ ++ return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); ++} ++ ++uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); ++ ++/* ++ * External helpers to access words from a device tree blob. They're built ++ * to work even with unaligned pointers on platforms (such as ARMv5) that don't ++ * like unaligned loads and stores. ++ */ ++static inline uint16_t fdt16_ld(const fdt16_t *p) ++{ ++ const uint8_t *bp = (const uint8_t *)p; ++ ++ return ((uint16_t)bp[0] << 8) | bp[1]; ++} ++ ++static inline uint32_t fdt32_ld(const fdt32_t *p) ++{ ++ const uint8_t *bp = (const uint8_t *)p; ++ ++ return ((uint32_t)bp[0] << 24) ++ | ((uint32_t)bp[1] << 16) ++ | ((uint32_t)bp[2] << 8) ++ | bp[3]; ++} ++ ++static inline void fdt32_st(void *property, uint32_t value) ++{ ++ uint8_t *bp = (uint8_t *)property; ++ ++ bp[0] = value >> 24; ++ bp[1] = (value >> 16) & 0xff; ++ bp[2] = (value >> 8) & 0xff; ++ bp[3] = value & 0xff; ++} ++ ++static inline uint64_t fdt64_ld(const fdt64_t *p) ++{ ++ const uint8_t *bp = (const uint8_t *)p; ++ ++ return ((uint64_t)bp[0] << 56) ++ | ((uint64_t)bp[1] << 48) ++ | ((uint64_t)bp[2] << 40) ++ | ((uint64_t)bp[3] << 32) ++ | ((uint64_t)bp[4] << 24) ++ | ((uint64_t)bp[5] << 16) ++ | ((uint64_t)bp[6] << 8) ++ | bp[7]; ++} ++ ++static inline void fdt64_st(void *property, uint64_t value) ++{ ++ uint8_t *bp = (uint8_t *)property; ++ ++ bp[0] = value >> 56; ++ bp[1] = (value >> 48) & 0xff; ++ bp[2] = (value >> 40) & 0xff; ++ bp[3] = (value >> 32) & 0xff; ++ bp[4] = (value >> 24) & 0xff; ++ bp[5] = (value >> 16) & 0xff; ++ bp[6] = (value >> 8) & 0xff; ++ bp[7] = value & 0xff; ++} ++ ++/**********************************************************************/ ++/* Traversal functions */ ++/**********************************************************************/ ++ ++int fdt_next_node(const void *fdt, int offset, int *depth); ++ ++/** ++ * fdt_first_subnode() - get offset of first direct subnode ++ * @fdt: FDT blob ++ * @offset: Offset of node to check ++ * ++ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none ++ */ ++int fdt_first_subnode(const void *fdt, int offset); ++ ++/** ++ * fdt_next_subnode() - get offset of next direct subnode ++ * @fdt: FDT blob ++ * @offset: Offset of previous subnode ++ * ++ * After first calling fdt_first_subnode(), call this function repeatedly to ++ * get direct subnodes of a parent node. ++ * ++ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more ++ * subnodes ++ */ ++int fdt_next_subnode(const void *fdt, int offset); ++ ++/** ++ * fdt_for_each_subnode - iterate over all subnodes of a parent ++ * ++ * @node: child node (int, lvalue) ++ * @fdt: FDT blob (const void *) ++ * @parent: parent node (int) ++ * ++ * This is actually a wrapper around a for loop and would be used like so: ++ * ++ * fdt_for_each_subnode(node, fdt, parent) { ++ * Use node ++ * ... ++ * } ++ * ++ * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { ++ * Error handling ++ * } ++ * ++ * Note that this is implemented as a macro and @node is used as ++ * iterator in the loop. The parent variable be constant or even a ++ * literal. ++ */ ++#define fdt_for_each_subnode(node, fdt, parent) \ ++ for (node = fdt_first_subnode(fdt, parent); \ ++ node >= 0; \ ++ node = fdt_next_subnode(fdt, node)) ++ ++/**********************************************************************/ ++/* General functions */ ++/**********************************************************************/ ++#define fdt_get_header(fdt, field) \ ++ (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) ++#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) ++#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) ++#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) ++#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) ++#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) ++#define fdt_version(fdt) (fdt_get_header(fdt, version)) ++#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) ++#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) ++#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) ++#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) ++ ++#define fdt_set_hdr_(name) \ ++ static inline void fdt_set_##name(void *fdt, uint32_t val) \ ++ { \ ++ struct fdt_header *fdth = (struct fdt_header *)fdt; \ ++ fdth->name = cpu_to_fdt32(val); \ ++ } ++fdt_set_hdr_(magic); ++fdt_set_hdr_(totalsize); ++fdt_set_hdr_(off_dt_struct); ++fdt_set_hdr_(off_dt_strings); ++fdt_set_hdr_(off_mem_rsvmap); ++fdt_set_hdr_(version); ++fdt_set_hdr_(last_comp_version); ++fdt_set_hdr_(boot_cpuid_phys); ++fdt_set_hdr_(size_dt_strings); ++fdt_set_hdr_(size_dt_struct); ++#undef fdt_set_hdr_ ++ ++/** ++ * fdt_header_size - return the size of the tree's header ++ * @fdt: pointer to a flattened device tree ++ * ++ * Return: size of DTB header in bytes ++ */ ++size_t fdt_header_size(const void *fdt); ++ ++/** ++ * fdt_header_size_ - internal function to get header size from a version number ++ * @version: devicetree version number ++ * ++ * Return: size of DTB header in bytes ++ */ ++size_t fdt_header_size_(uint32_t version); ++ ++/** ++ * fdt_check_header - sanity check a device tree header ++ * @fdt: pointer to data which might be a flattened device tree ++ * ++ * fdt_check_header() checks that the given buffer contains what ++ * appears to be a flattened device tree, and that the header contains ++ * valid information (to the extent that can be determined from the ++ * header alone). ++ * ++ * returns: ++ * 0, if the buffer appears to contain a valid device tree ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_TRUNCATED, standard meanings, as above ++ */ ++int fdt_check_header(const void *fdt); ++ ++/** ++ * fdt_move - move a device tree around in memory ++ * @fdt: pointer to the device tree to move ++ * @buf: pointer to memory where the device is to be moved ++ * @bufsize: size of the memory space at buf ++ * ++ * fdt_move() relocates, if possible, the device tree blob located at ++ * fdt to the buffer at buf of size bufsize. The buffer may overlap ++ * with the existing device tree blob at fdt. Therefore, ++ * fdt_move(fdt, fdt, fdt_totalsize(fdt)) ++ * should always succeed. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, standard meanings ++ */ ++int fdt_move(const void *fdt, void *buf, int bufsize); ++ ++/**********************************************************************/ ++/* Read-only functions */ ++/**********************************************************************/ ++ ++int fdt_check_full(const void *fdt, size_t bufsize); ++ ++/** ++ * fdt_get_string - retrieve a string from the strings block of a device tree ++ * @fdt: pointer to the device tree blob ++ * @stroffset: offset of the string within the strings block (native endian) ++ * @lenp: optional pointer to return the string's length ++ * ++ * fdt_get_string() retrieves a pointer to a single string from the ++ * strings block of the device tree blob at fdt, and optionally also ++ * returns the string's length in *lenp. ++ * ++ * returns: ++ * a pointer to the string, on success ++ * NULL, if stroffset is out of bounds, or doesn't point to a valid string ++ */ ++const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); ++ ++/** ++ * fdt_string - retrieve a string from the strings block of a device tree ++ * @fdt: pointer to the device tree blob ++ * @stroffset: offset of the string within the strings block (native endian) ++ * ++ * fdt_string() retrieves a pointer to a single string from the ++ * strings block of the device tree blob at fdt. ++ * ++ * returns: ++ * a pointer to the string, on success ++ * NULL, if stroffset is out of bounds, or doesn't point to a valid string ++ */ ++const char *fdt_string(const void *fdt, int stroffset); ++ ++/** ++ * fdt_find_max_phandle - find and return the highest phandle in a tree ++ * @fdt: pointer to the device tree blob ++ * @phandle: return location for the highest phandle value found in the tree ++ * ++ * fdt_find_max_phandle() finds the highest phandle value in the given device ++ * tree. The value returned in @phandle is only valid if the function returns ++ * success. ++ * ++ * returns: ++ * 0 on success or a negative error code on failure ++ */ ++int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); ++ ++/** ++ * fdt_get_max_phandle - retrieves the highest phandle in a tree ++ * @fdt: pointer to the device tree blob ++ * ++ * fdt_get_max_phandle retrieves the highest phandle in the given ++ * device tree. This will ignore badly formatted phandles, or phandles ++ * with a value of 0 or -1. ++ * ++ * This function is deprecated in favour of fdt_find_max_phandle(). ++ * ++ * returns: ++ * the highest phandle on success ++ * 0, if no phandle was found in the device tree ++ * -1, if an error occurred ++ */ ++static inline uint32_t fdt_get_max_phandle(const void *fdt) ++{ ++ uint32_t phandle; ++ int err; ++ ++ err = fdt_find_max_phandle(fdt, &phandle); ++ if (err < 0) ++ return (uint32_t)-1; ++ ++ return phandle; ++} ++ ++/** ++ * fdt_generate_phandle - return a new, unused phandle for a device tree blob ++ * @fdt: pointer to the device tree blob ++ * @phandle: return location for the new phandle ++ * ++ * Walks the device tree blob and looks for the highest phandle value. On ++ * success, the new, unused phandle value (one higher than the previously ++ * highest phandle value in the device tree blob) will be returned in the ++ * @phandle parameter. ++ * ++ * Return: 0 on success or a negative error-code on failure ++ */ ++int fdt_generate_phandle(const void *fdt, uint32_t *phandle); ++ ++/** ++ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries ++ * @fdt: pointer to the device tree blob ++ * ++ * Returns the number of entries in the device tree blob's memory ++ * reservation map. This does not include the terminating 0,0 entry ++ * or any other (0,0) entries reserved for expansion. ++ * ++ * returns: ++ * the number of entries ++ */ ++int fdt_num_mem_rsv(const void *fdt); ++ ++/** ++ * fdt_get_mem_rsv - retrieve one memory reserve map entry ++ * @fdt: pointer to the device tree blob ++ * @n: index of reserve map entry ++ * @address: pointer to 64-bit variable to hold the start address ++ * @size: pointer to 64-bit variable to hold the size of the entry ++ * ++ * On success, @address and @size will contain the address and size of ++ * the n-th reserve map entry from the device tree blob, in ++ * native-endian format. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, standard meanings ++ */ ++int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); ++ ++/** ++ * fdt_subnode_offset_namelen - find a subnode based on substring ++ * @fdt: pointer to the device tree blob ++ * @parentoffset: structure block offset of a node ++ * @name: name of the subnode to locate ++ * @namelen: number of characters of name to consider ++ * ++ * Identical to fdt_subnode_offset(), but only examine the first ++ * namelen characters of name for matching the subnode name. This is ++ * useful for finding subnodes based on a portion of a larger string, ++ * such as a full path. ++ * ++ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found. ++ */ ++#ifndef SWIG /* Not available in Python */ ++int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, ++ const char *name, int namelen); ++#endif ++/** ++ * fdt_subnode_offset - find a subnode of a given node ++ * @fdt: pointer to the device tree blob ++ * @parentoffset: structure block offset of a node ++ * @name: name of the subnode to locate ++ * ++ * fdt_subnode_offset() finds a subnode of the node at structure block ++ * offset parentoffset with the given name. name may include a unit ++ * address, in which case fdt_subnode_offset() will find the subnode ++ * with that unit address, or the unit address may be omitted, in ++ * which case fdt_subnode_offset() will find an arbitrary subnode ++ * whose name excluding unit address matches the given name. ++ * ++ * returns: ++ * structure block offset of the requested subnode (>=0), on success ++ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist ++ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE ++ * tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings. ++ */ ++int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); ++ ++/** ++ * fdt_path_offset_namelen - find a tree node by its full path ++ * @fdt: pointer to the device tree blob ++ * @path: full path of the node to locate ++ * @namelen: number of characters of path to consider ++ * ++ * Identical to fdt_path_offset(), but only consider the first namelen ++ * characters of path as the path name. ++ * ++ * Return: offset of the node or negative libfdt error value otherwise ++ */ ++#ifndef SWIG /* Not available in Python */ ++int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); ++#endif ++ ++/** ++ * fdt_path_offset - find a tree node by its full path ++ * @fdt: pointer to the device tree blob ++ * @path: full path of the node to locate ++ * ++ * fdt_path_offset() finds a node of a given path in the device tree. ++ * Each path component may omit the unit address portion, but the ++ * results of this are undefined if any such path component is ++ * ambiguous (that is if there are multiple nodes at the relevant ++ * level matching the given component, differentiated only by unit ++ * address). ++ * ++ * returns: ++ * structure block offset of the node with the requested path (>=0), on ++ * success ++ * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid ++ * -FDT_ERR_NOTFOUND, if the requested node does not exist ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings. ++ */ ++int fdt_path_offset(const void *fdt, const char *path); ++ ++/** ++ * fdt_get_name - retrieve the name of a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: structure block offset of the starting node ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_get_name() retrieves the name (including unit address) of the ++ * device tree node at structure block offset nodeoffset. If lenp is ++ * non-NULL, the length of this name is also returned, in the integer ++ * pointed to by lenp. ++ * ++ * returns: ++ * pointer to the node's name, on success ++ * If lenp is non-NULL, *lenp contains the length of that name ++ * (>=0) ++ * NULL, on error ++ * if lenp is non-NULL *lenp contains an error code (<0): ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE ++ * tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, standard meanings ++ */ ++const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); ++ ++/** ++ * fdt_first_property_offset - find the offset of a node's first property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: structure block offset of a node ++ * ++ * fdt_first_property_offset() finds the first property of the node at ++ * the given structure block offset. ++ * ++ * returns: ++ * structure block offset of the property (>=0), on success ++ * -FDT_ERR_NOTFOUND, if the requested node has no properties ++ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings. ++ */ ++int fdt_first_property_offset(const void *fdt, int nodeoffset); ++ ++/** ++ * fdt_next_property_offset - step through a node's properties ++ * @fdt: pointer to the device tree blob ++ * @offset: structure block offset of a property ++ * ++ * fdt_next_property_offset() finds the property immediately after the ++ * one at the given structure block offset. This will be a property ++ * of the same node as the given property. ++ * ++ * returns: ++ * structure block offset of the next property (>=0), on success ++ * -FDT_ERR_NOTFOUND, if the given property is the last in its node ++ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings. ++ */ ++int fdt_next_property_offset(const void *fdt, int offset); ++ ++/** ++ * fdt_for_each_property_offset - iterate over all properties of a node ++ * ++ * @property: property offset (int, lvalue) ++ * @fdt: FDT blob (const void *) ++ * @node: node offset (int) ++ * ++ * This is actually a wrapper around a for loop and would be used like so: ++ * ++ * fdt_for_each_property_offset(property, fdt, node) { ++ * Use property ++ * ... ++ * } ++ * ++ * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { ++ * Error handling ++ * } ++ * ++ * Note that this is implemented as a macro and property is used as ++ * iterator in the loop. The node variable can be constant or even a ++ * literal. ++ */ ++#define fdt_for_each_property_offset(property, fdt, node) \ ++ for (property = fdt_first_property_offset(fdt, node); \ ++ property >= 0; \ ++ property = fdt_next_property_offset(fdt, property)) ++ ++/** ++ * fdt_get_property_by_offset - retrieve the property at a given offset ++ * @fdt: pointer to the device tree blob ++ * @offset: offset of the property to retrieve ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_get_property_by_offset() retrieves a pointer to the ++ * fdt_property structure within the device tree blob at the given ++ * offset. If lenp is non-NULL, the length of the property value is ++ * also returned, in the integer pointed to by lenp. ++ * ++ * Note that this code only works on device tree versions >= 16. fdt_getprop() ++ * works on all versions. ++ * ++ * returns: ++ * pointer to the structure representing the property ++ * if lenp is non-NULL, *lenp contains the length of the property ++ * value (>=0) ++ * NULL, on error ++ * if lenp is non-NULL, *lenp contains an error code (<0): ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++const struct fdt_property *fdt_get_property_by_offset(const void *fdt, ++ int offset, ++ int *lenp); ++ ++/** ++ * fdt_get_property_namelen - find a property based on substring ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to find ++ * @name: name of the property to find ++ * @namelen: number of characters of name to consider ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * Identical to fdt_get_property(), but only examine the first namelen ++ * characters of name for matching the property name. ++ * ++ * Return: pointer to the structure representing the property, or NULL ++ * if not found ++ */ ++#ifndef SWIG /* Not available in Python */ ++const struct fdt_property *fdt_get_property_namelen(const void *fdt, ++ int nodeoffset, ++ const char *name, ++ int namelen, int *lenp); ++#endif ++ ++/** ++ * fdt_get_property - find a given property in a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to find ++ * @name: name of the property to find ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_get_property() retrieves a pointer to the fdt_property ++ * structure within the device tree blob corresponding to the property ++ * named 'name' of the node at offset nodeoffset. If lenp is ++ * non-NULL, the length of the property value is also returned, in the ++ * integer pointed to by lenp. ++ * ++ * returns: ++ * pointer to the structure representing the property ++ * if lenp is non-NULL, *lenp contains the length of the property ++ * value (>=0) ++ * NULL, on error ++ * if lenp is non-NULL, *lenp contains an error code (<0): ++ * -FDT_ERR_NOTFOUND, node does not have named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE ++ * tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, ++ const char *name, int *lenp); ++static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, ++ const char *name, ++ int *lenp) ++{ ++ return (struct fdt_property *)(uintptr_t) ++ fdt_get_property(fdt, nodeoffset, name, lenp); ++} ++ ++/** ++ * fdt_getprop_by_offset - retrieve the value of a property at a given offset ++ * @fdt: pointer to the device tree blob ++ * @offset: offset of the property to read ++ * @namep: pointer to a string variable (will be overwritten) or NULL ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_getprop_by_offset() retrieves a pointer to the value of the ++ * property at structure block offset 'offset' (this will be a pointer ++ * to within the device blob itself, not a copy of the value). If ++ * lenp is non-NULL, the length of the property value is also ++ * returned, in the integer pointed to by lenp. If namep is non-NULL, ++ * the property's namne will also be returned in the char * pointed to ++ * by namep (this will be a pointer to within the device tree's string ++ * block, not a new copy of the name). ++ * ++ * returns: ++ * pointer to the property's value ++ * if lenp is non-NULL, *lenp contains the length of the property ++ * value (>=0) ++ * if namep is non-NULL *namep contiains a pointer to the property ++ * name. ++ * NULL, on error ++ * if lenp is non-NULL, *lenp contains an error code (<0): ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++#ifndef SWIG /* This function is not useful in Python */ ++const void *fdt_getprop_by_offset(const void *fdt, int offset, ++ const char **namep, int *lenp); ++#endif ++ ++/** ++ * fdt_getprop_namelen - get property value based on substring ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to find ++ * @name: name of the property to find ++ * @namelen: number of characters of name to consider ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * Identical to fdt_getprop(), but only examine the first namelen ++ * characters of name for matching the property name. ++ * ++ * Return: pointer to the property's value or NULL on error ++ */ ++#ifndef SWIG /* Not available in Python */ ++const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, ++ const char *name, int namelen, int *lenp); ++static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, ++ const char *name, int namelen, ++ int *lenp) ++{ ++ return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, ++ namelen, lenp); ++} ++#endif ++ ++/** ++ * fdt_getprop - retrieve the value of a given property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to find ++ * @name: name of the property to find ++ * @lenp: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_getprop() retrieves a pointer to the value of the property ++ * named @name of the node at offset @nodeoffset (this will be a ++ * pointer to within the device blob itself, not a copy of the value). ++ * If @lenp is non-NULL, the length of the property value is also ++ * returned, in the integer pointed to by @lenp. ++ * ++ * returns: ++ * pointer to the property's value ++ * if lenp is non-NULL, *lenp contains the length of the property ++ * value (>=0) ++ * NULL, on error ++ * if lenp is non-NULL, *lenp contains an error code (<0): ++ * -FDT_ERR_NOTFOUND, node does not have named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE ++ * tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++const void *fdt_getprop(const void *fdt, int nodeoffset, ++ const char *name, int *lenp); ++static inline void *fdt_getprop_w(void *fdt, int nodeoffset, ++ const char *name, int *lenp) ++{ ++ return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); ++} ++ ++/** ++ * fdt_get_phandle - retrieve the phandle of a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: structure block offset of the node ++ * ++ * fdt_get_phandle() retrieves the phandle of the device tree node at ++ * structure block offset nodeoffset. ++ * ++ * returns: ++ * the phandle of the node at nodeoffset, on success (!= 0, != -1) ++ * 0, if the node has no phandle, or another error occurs ++ */ ++uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); ++ ++/** ++ * fdt_get_alias_namelen - get alias based on substring ++ * @fdt: pointer to the device tree blob ++ * @name: name of the alias th look up ++ * @namelen: number of characters of name to consider ++ * ++ * Identical to fdt_get_alias(), but only examine the first @namelen ++ * characters of @name for matching the alias name. ++ * ++ * Return: a pointer to the expansion of the alias named @name, if it exists, ++ * NULL otherwise ++ */ ++#ifndef SWIG /* Not available in Python */ ++const char *fdt_get_alias_namelen(const void *fdt, ++ const char *name, int namelen); ++#endif ++ ++/** ++ * fdt_get_alias - retrieve the path referenced by a given alias ++ * @fdt: pointer to the device tree blob ++ * @name: name of the alias th look up ++ * ++ * fdt_get_alias() retrieves the value of a given alias. That is, the ++ * value of the property named @name in the node /aliases. ++ * ++ * returns: ++ * a pointer to the expansion of the alias named 'name', if it exists ++ * NULL, if the given alias or the /aliases node does not exist ++ */ ++const char *fdt_get_alias(const void *fdt, const char *name); ++ ++/** ++ * fdt_get_path - determine the full path of a node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose path to find ++ * @buf: character buffer to contain the returned path (will be overwritten) ++ * @buflen: size of the character buffer at buf ++ * ++ * fdt_get_path() computes the full path of the node at offset ++ * nodeoffset, and records that path in the buffer at buf. ++ * ++ * NOTE: This function is expensive, as it must scan the device tree ++ * structure from the start to nodeoffset. ++ * ++ * returns: ++ * 0, on success ++ * buf contains the absolute path of the node at ++ * nodeoffset, as a NUL-terminated string. ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) ++ * characters and will not fit in the given buffer. ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); ++ ++/** ++ * fdt_supernode_atdepth_offset - find a specific ancestor of a node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose parent to find ++ * @supernodedepth: depth of the ancestor to find ++ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL ++ * ++ * fdt_supernode_atdepth_offset() finds an ancestor of the given node ++ * at a specific depth from the root (where the root itself has depth ++ * 0, its immediate subnodes depth 1 and so forth). So ++ * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); ++ * will always return 0, the offset of the root node. If the node at ++ * nodeoffset has depth D, then: ++ * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); ++ * will return nodeoffset itself. ++ * ++ * NOTE: This function is expensive, as it must scan the device tree ++ * structure from the start to nodeoffset. ++ * ++ * returns: ++ * structure block offset of the node at node offset's ancestor ++ * of depth supernodedepth (>=0), on success ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of ++ * nodeoffset ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, ++ int supernodedepth, int *nodedepth); ++ ++/** ++ * fdt_node_depth - find the depth of a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose parent to find ++ * ++ * fdt_node_depth() finds the depth of a given node. The root node ++ * has depth 0, its immediate subnodes depth 1 and so forth. ++ * ++ * NOTE: This function is expensive, as it must scan the device tree ++ * structure from the start to nodeoffset. ++ * ++ * returns: ++ * depth of the node at nodeoffset (>=0), on success ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_node_depth(const void *fdt, int nodeoffset); ++ ++/** ++ * fdt_parent_offset - find the parent of a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose parent to find ++ * ++ * fdt_parent_offset() locates the parent node of a given node (that ++ * is, it finds the offset of the node which contains the node at ++ * nodeoffset as a subnode). ++ * ++ * NOTE: This function is expensive, as it must scan the device tree ++ * structure from the start to nodeoffset, *twice*. ++ * ++ * returns: ++ * structure block offset of the parent of the node at nodeoffset ++ * (>=0), on success ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_parent_offset(const void *fdt, int nodeoffset); ++ ++/** ++ * fdt_node_offset_by_prop_value - find nodes with a given property value ++ * @fdt: pointer to the device tree blob ++ * @startoffset: only find nodes after this offset ++ * @propname: property name to check ++ * @propval: property value to search for ++ * @proplen: length of the value in propval ++ * ++ * fdt_node_offset_by_prop_value() returns the offset of the first ++ * node after startoffset, which has a property named propname whose ++ * value is of length proplen and has value equal to propval; or if ++ * startoffset is -1, the very first such node in the tree. ++ * ++ * To iterate through all nodes matching the criterion, the following ++ * idiom can be used: ++ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, ++ * propval, proplen); ++ * while (offset != -FDT_ERR_NOTFOUND) { ++ * // other code here ++ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, ++ * propval, proplen); ++ * } ++ * ++ * Note the -1 in the first call to the function, if 0 is used here ++ * instead, the function will never locate the root node, even if it ++ * matches the criterion. ++ * ++ * returns: ++ * structure block offset of the located node (>= 0, >startoffset), ++ * on success ++ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the ++ * tree after startoffset ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, ++ const char *propname, ++ const void *propval, int proplen); ++ ++/** ++ * fdt_node_offset_by_phandle - find the node with a given phandle ++ * @fdt: pointer to the device tree blob ++ * @phandle: phandle value ++ * ++ * fdt_node_offset_by_phandle() returns the offset of the node ++ * which has the given phandle value. If there is more than one node ++ * in the tree with the given phandle (an invalid tree), results are ++ * undefined. ++ * ++ * returns: ++ * structure block offset of the located node (>= 0), on success ++ * -FDT_ERR_NOTFOUND, no node with that phandle exists ++ * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); ++ ++/** ++ * fdt_node_check_compatible - check a node's compatible property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of a tree node ++ * @compatible: string to match against ++ * ++ * fdt_node_check_compatible() returns 0 if the given node contains a ++ * @compatible property with the given string as one of its elements, ++ * it returns non-zero otherwise, or on error. ++ * ++ * returns: ++ * 0, if the node has a 'compatible' property listing the given string ++ * 1, if the node has a 'compatible' property, but it does not list ++ * the given string ++ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property ++ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_node_check_compatible(const void *fdt, int nodeoffset, ++ const char *compatible); ++ ++/** ++ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value ++ * @fdt: pointer to the device tree blob ++ * @startoffset: only find nodes after this offset ++ * @compatible: 'compatible' string to match against ++ * ++ * fdt_node_offset_by_compatible() returns the offset of the first ++ * node after startoffset, which has a 'compatible' property which ++ * lists the given compatible string; or if startoffset is -1, the ++ * very first such node in the tree. ++ * ++ * To iterate through all nodes matching the criterion, the following ++ * idiom can be used: ++ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); ++ * while (offset != -FDT_ERR_NOTFOUND) { ++ * // other code here ++ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); ++ * } ++ * ++ * Note the -1 in the first call to the function, if 0 is used here ++ * instead, the function will never locate the root node, even if it ++ * matches the criterion. ++ * ++ * returns: ++ * structure block offset of the located node (>= 0, >startoffset), ++ * on success ++ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the ++ * tree after startoffset ++ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, standard meanings ++ */ ++int fdt_node_offset_by_compatible(const void *fdt, int startoffset, ++ const char *compatible); ++ ++/** ++ * fdt_stringlist_contains - check a string list property for a string ++ * @strlist: Property containing a list of strings to check ++ * @listlen: Length of property ++ * @str: String to search for ++ * ++ * This is a utility function provided for convenience. The list contains ++ * one or more strings, each terminated by \0, as is found in a device tree ++ * "compatible" property. ++ * ++ * Return: 1 if the string is found in the list, 0 not found, or invalid list ++ */ ++int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); ++ ++/** ++ * fdt_stringlist_count - count the number of strings in a string list ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of a tree node ++ * @property: name of the property containing the string list ++ * ++ * Return: ++ * the number of strings in the given property ++ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated ++ * -FDT_ERR_NOTFOUND if the property does not exist ++ */ ++int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); ++ ++/** ++ * fdt_stringlist_search - find a string in a string list and return its index ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of a tree node ++ * @property: name of the property containing the string list ++ * @string: string to look up in the string list ++ * ++ * Note that it is possible for this function to succeed on property values ++ * that are not NUL-terminated. That's because the function will stop after ++ * finding the first occurrence of @string. This can for example happen with ++ * small-valued cell properties, such as #address-cells, when searching for ++ * the empty string. ++ * ++ * return: ++ * the index of the string in the list of strings ++ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated ++ * -FDT_ERR_NOTFOUND if the property does not exist or does not contain ++ * the given string ++ */ ++int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, ++ const char *string); ++ ++/** ++ * fdt_stringlist_get() - obtain the string at a given index in a string list ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of a tree node ++ * @property: name of the property containing the string list ++ * @index: index of the string to return ++ * @lenp: return location for the string length or an error code on failure ++ * ++ * Note that this will successfully extract strings from properties with ++ * non-NUL-terminated values. For example on small-valued cell properties ++ * this function will return the empty string. ++ * ++ * If non-NULL, the length of the string (on success) or a negative error-code ++ * (on failure) will be stored in the integer pointer to by lenp. ++ * ++ * Return: ++ * A pointer to the string at the given index in the string list or NULL on ++ * failure. On success the length of the string will be stored in the memory ++ * location pointed to by the lenp parameter, if non-NULL. On failure one of ++ * the following negative error codes will be returned in the lenp parameter ++ * (if non-NULL): ++ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated ++ * -FDT_ERR_NOTFOUND if the property does not exist ++ */ ++const char *fdt_stringlist_get(const void *fdt, int nodeoffset, ++ const char *property, int index, ++ int *lenp); ++ ++/**********************************************************************/ ++/* Read-only functions (addressing related) */ ++/**********************************************************************/ ++ ++/** ++ * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells ++ * ++ * This is the maximum value for #address-cells, #size-cells and ++ * similar properties that will be processed by libfdt. IEE1275 ++ * requires that OF implementations handle values up to 4. ++ * Implementations may support larger values, but in practice higher ++ * values aren't used. ++ */ ++#define FDT_MAX_NCELLS 4 ++ ++/** ++ * fdt_address_cells - retrieve address size for a bus represented in the tree ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node to find the address size for ++ * ++ * When the node has a valid #address-cells property, returns its value. ++ * ++ * returns: ++ * 0 <= n < FDT_MAX_NCELLS, on success ++ * 2, if the node has no #address-cells property ++ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid ++ * #address-cells property ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_address_cells(const void *fdt, int nodeoffset); ++ ++/** ++ * fdt_size_cells - retrieve address range size for a bus represented in the ++ * tree ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node to find the address range size for ++ * ++ * When the node has a valid #size-cells property, returns its value. ++ * ++ * returns: ++ * 0 <= n < FDT_MAX_NCELLS, on success ++ * 1, if the node has no #size-cells property ++ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid ++ * #size-cells property ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_size_cells(const void *fdt, int nodeoffset); ++ ++ ++/**********************************************************************/ ++/* Write-in-place functions */ ++/**********************************************************************/ ++ ++/** ++ * fdt_setprop_inplace_namelen_partial - change a property's value, ++ * but not its size ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @namelen: number of characters of name to consider ++ * @idx: index of the property to change in the array ++ * @val: pointer to data to replace the property value with ++ * @len: length of the property value ++ * ++ * Identical to fdt_setprop_inplace(), but modifies the given property ++ * starting from the given index, and using only the first characters ++ * of the name. It is useful when you want to manipulate only one value of ++ * an array and you have a string that doesn't end with \0. ++ * ++ * Return: 0 on success, negative libfdt error value otherwise ++ */ ++#ifndef SWIG /* Not available in Python */ ++int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, ++ const char *name, int namelen, ++ uint32_t idx, const void *val, ++ int len); ++#endif ++ ++/** ++ * fdt_setprop_inplace - change a property's value, but not its size ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: pointer to data to replace the property value with ++ * @len: length of the property value ++ * ++ * fdt_setprop_inplace() replaces the value of a given property with ++ * the data in val, of length len. This function cannot change the ++ * size of a property, and so will only work if len is equal to the ++ * current length of the property. ++ * ++ * This function will alter only the bytes in the blob which contain ++ * the given property value, and will not alter or move any other part ++ * of the tree. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, if len is not equal to the property's current length ++ * -FDT_ERR_NOTFOUND, node does not have the named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++#ifndef SWIG /* Not available in Python */ ++int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len); ++#endif ++ ++/** ++ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 32-bit integer value to replace the property with ++ * ++ * fdt_setprop_inplace_u32() replaces the value of a given property ++ * with the 32-bit integer value in val, converting val to big-endian ++ * if necessary. This function cannot change the size of a property, ++ * and so will only work if the property already exists and has length ++ * 4. ++ * ++ * This function will alter only the bytes in the blob which contain ++ * the given property value, and will not alter or move any other part ++ * of the tree. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 ++ * -FDT_ERR_NOTFOUND, node does not have the named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, ++ const char *name, uint32_t val) ++{ ++ fdt32_t tmp = cpu_to_fdt32(val); ++ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 64-bit integer value to replace the property with ++ * ++ * fdt_setprop_inplace_u64() replaces the value of a given property ++ * with the 64-bit integer value in val, converting val to big-endian ++ * if necessary. This function cannot change the size of a property, ++ * and so will only work if the property already exists and has length ++ * 8. ++ * ++ * This function will alter only the bytes in the blob which contain ++ * the given property value, and will not alter or move any other part ++ * of the tree. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 ++ * -FDT_ERR_NOTFOUND, node does not have the named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, ++ const char *name, uint64_t val) ++{ ++ fdt64_t tmp = cpu_to_fdt64(val); ++ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_setprop_inplace_cell - change the value of a single-cell property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node containing the property ++ * @name: name of the property to change the value of ++ * @val: new value of the 32-bit cell ++ * ++ * This is an alternative name for fdt_setprop_inplace_u32() ++ * Return: 0 on success, negative libfdt error number otherwise. ++ */ ++static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, ++ const char *name, uint32_t val) ++{ ++ return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); ++} ++ ++/** ++ * fdt_nop_property - replace a property with nop tags ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to nop ++ * @name: name of the property to nop ++ * ++ * fdt_nop_property() will replace a given property's representation ++ * in the blob with FDT_NOP tags, effectively removing it from the ++ * tree. ++ * ++ * This function will alter only the bytes in the blob which contain ++ * the property, and will not alter or move any other part of the ++ * tree. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOTFOUND, node does not have the named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_nop_property(void *fdt, int nodeoffset, const char *name); ++ ++/** ++ * fdt_nop_node - replace a node (subtree) with nop tags ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node to nop ++ * ++ * fdt_nop_node() will replace a given node's representation in the ++ * blob, including all its subnodes, if any, with FDT_NOP tags, ++ * effectively removing it from the tree. ++ * ++ * This function will alter only the bytes in the blob which contain ++ * the node and its properties and subnodes, and will not alter or ++ * move any other part of the tree. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_nop_node(void *fdt, int nodeoffset); ++ ++/**********************************************************************/ ++/* Sequential write functions */ ++/**********************************************************************/ ++ ++/* fdt_create_with_flags flags */ ++#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 ++ /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property ++ * names in the fdt. This can result in faster creation times, but ++ * a larger fdt. */ ++ ++#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) ++ ++/** ++ * fdt_create_with_flags - begin creation of a new fdt ++ * @buf: pointer to memory allocated where fdt will be created ++ * @bufsize: size of the memory space at fdt ++ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. ++ * ++ * fdt_create_with_flags() begins the process of creating a new fdt with ++ * the sequential write interface. ++ * ++ * fdt creation process must end with fdt_finished() to produce a valid fdt. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt ++ * -FDT_ERR_BADFLAGS, flags is not valid ++ */ ++int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); ++ ++/** ++ * fdt_create - begin creation of a new fdt ++ * @buf: pointer to memory allocated where fdt will be created ++ * @bufsize: size of the memory space at fdt ++ * ++ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt ++ */ ++int fdt_create(void *buf, int bufsize); ++ ++int fdt_resize(void *fdt, void *buf, int bufsize); ++int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); ++int fdt_finish_reservemap(void *fdt); ++int fdt_begin_node(void *fdt, const char *name); ++int fdt_property(void *fdt, const char *name, const void *val, int len); ++static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) ++{ ++ fdt32_t tmp = cpu_to_fdt32(val); ++ return fdt_property(fdt, name, &tmp, sizeof(tmp)); ++} ++static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) ++{ ++ fdt64_t tmp = cpu_to_fdt64(val); ++ return fdt_property(fdt, name, &tmp, sizeof(tmp)); ++} ++ ++#ifndef SWIG /* Not available in Python */ ++static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) ++{ ++ return fdt_property_u32(fdt, name, val); ++} ++#endif ++ ++/** ++ * fdt_property_placeholder - add a new property and return a ptr to its value ++ * ++ * @fdt: pointer to the device tree blob ++ * @name: name of property to add ++ * @len: length of property value in bytes ++ * @valp: returns a pointer to where where the value should be placed ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_NOSPACE, standard meanings ++ */ ++int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); ++ ++#define fdt_property_string(fdt, name, str) \ ++ fdt_property(fdt, name, str, strlen(str)+1) ++int fdt_end_node(void *fdt); ++int fdt_finish(void *fdt); ++ ++/**********************************************************************/ ++/* Read-write functions */ ++/**********************************************************************/ ++ ++int fdt_create_empty_tree(void *buf, int bufsize); ++int fdt_open_into(const void *fdt, void *buf, int bufsize); ++int fdt_pack(void *fdt); ++ ++/** ++ * fdt_add_mem_rsv - add one memory reserve map entry ++ * @fdt: pointer to the device tree blob ++ * @address: 64-bit start address of the reserve map entry ++ * @size: 64-bit size of the reserved region ++ * ++ * Adds a reserve map entry to the given blob reserving a region at ++ * address address of length size. ++ * ++ * This function will insert data into the reserve map and will ++ * therefore change the indexes of some entries in the table. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new reservation entry ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); ++ ++/** ++ * fdt_del_mem_rsv - remove a memory reserve map entry ++ * @fdt: pointer to the device tree blob ++ * @n: entry to remove ++ * ++ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from ++ * the blob. ++ * ++ * This function will delete data from the reservation table and will ++ * therefore change the indexes of some entries in the table. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there ++ * are less than n+1 reserve map entries) ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_del_mem_rsv(void *fdt, int n); ++ ++/** ++ * fdt_set_name - change the name of a given node ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: structure block offset of a node ++ * @name: name to give the node ++ * ++ * fdt_set_name() replaces the name (including unit address, if any) ++ * of the given node with the given string. NOTE: this function can't ++ * efficiently check if the new name is unique amongst the given ++ * node's siblings; results are undefined if this function is invoked ++ * with a name equal to one of the given node's siblings. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob ++ * to contain the new name ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, standard meanings ++ */ ++int fdt_set_name(void *fdt, int nodeoffset, const char *name); ++ ++/** ++ * fdt_setprop - create or change a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: pointer to data to set the property value to ++ * @len: length of the property value ++ * ++ * fdt_setprop() sets the value of the named property in the given ++ * node to the given value and length, creating the property if it ++ * does not already exist. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_setprop(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len); ++ ++/** ++ * fdt_setprop_placeholder - allocate space for a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @len: length of the property value ++ * @prop_data: return pointer to property data ++ * ++ * fdt_setprop_placeholer() allocates the named property in the given node. ++ * If the property exists it is resized. In either case a pointer to the ++ * property data is returned. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, ++ int len, void **prop_data); ++ ++/** ++ * fdt_setprop_u32 - set a property to a 32-bit integer ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 32-bit integer value for the property (native endian) ++ * ++ * fdt_setprop_u32() sets the value of the named property in the given ++ * node to the given 32-bit integer value (converting to big-endian if ++ * necessary), or creates a new property with that value if it does ++ * not already exist. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, ++ uint32_t val) ++{ ++ fdt32_t tmp = cpu_to_fdt32(val); ++ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_setprop_u64 - set a property to a 64-bit integer ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 64-bit integer value for the property (native endian) ++ * ++ * fdt_setprop_u64() sets the value of the named property in the given ++ * node to the given 64-bit integer value (converting to big-endian if ++ * necessary), or creates a new property with that value if it does ++ * not already exist. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, ++ uint64_t val) ++{ ++ fdt64_t tmp = cpu_to_fdt64(val); ++ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_setprop_cell - set a property to a single cell value ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 32-bit integer value for the property (native endian) ++ * ++ * This is an alternative name for fdt_setprop_u32() ++ * ++ * Return: 0 on success, negative libfdt error value otherwise. ++ */ ++static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, ++ uint32_t val) ++{ ++ return fdt_setprop_u32(fdt, nodeoffset, name, val); ++} ++ ++/** ++ * fdt_setprop_string - set a property to a string value ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @str: string value for the property ++ * ++ * fdt_setprop_string() sets the value of the named property in the ++ * given node to the given string value (using the length of the ++ * string to determine the new length of the property), or creates a ++ * new property with that value if it does not already exist. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++#define fdt_setprop_string(fdt, nodeoffset, name, str) \ ++ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) ++ ++ ++/** ++ * fdt_setprop_empty - set a property to an empty value ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * ++ * fdt_setprop_empty() sets the value of the named property in the ++ * given node to an empty (zero length) value, or creates a new empty ++ * property if it does not already exist. ++ * ++ * This function may insert or delete data from the blob, and will ++ * therefore change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++#define fdt_setprop_empty(fdt, nodeoffset, name) \ ++ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) ++ ++/** ++ * fdt_appendprop - append to or create a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to append to ++ * @val: pointer to data to append to the property value ++ * @len: length of the data to append to the property value ++ * ++ * fdt_appendprop() appends the value to the named property in the ++ * given node, creating the property if it does not already exist. ++ * ++ * This function may insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_appendprop(void *fdt, int nodeoffset, const char *name, ++ const void *val, int len); ++ ++/** ++ * fdt_appendprop_u32 - append a 32-bit integer value to a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 32-bit integer value to append to the property (native endian) ++ * ++ * fdt_appendprop_u32() appends the given 32-bit integer value ++ * (converting to big-endian if necessary) to the value of the named ++ * property in the given node, or creates a new property with that ++ * value if it does not already exist. ++ * ++ * This function may insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, ++ const char *name, uint32_t val) ++{ ++ fdt32_t tmp = cpu_to_fdt32(val); ++ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_appendprop_u64 - append a 64-bit integer value to a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 64-bit integer value to append to the property (native endian) ++ * ++ * fdt_appendprop_u64() appends the given 64-bit integer value ++ * (converting to big-endian if necessary) to the value of the named ++ * property in the given node, or creates a new property with that ++ * value if it does not already exist. ++ * ++ * This function may insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, ++ const char *name, uint64_t val) ++{ ++ fdt64_t tmp = cpu_to_fdt64(val); ++ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); ++} ++ ++/** ++ * fdt_appendprop_cell - append a single cell value to a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @val: 32-bit integer value to append to the property (native endian) ++ * ++ * This is an alternative name for fdt_appendprop_u32() ++ * ++ * Return: 0 on success, negative libfdt error value otherwise. ++ */ ++static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, ++ const char *name, uint32_t val) ++{ ++ return fdt_appendprop_u32(fdt, nodeoffset, name, val); ++} ++ ++/** ++ * fdt_appendprop_string - append a string to a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to change ++ * @name: name of the property to change ++ * @str: string value to append to the property ++ * ++ * fdt_appendprop_string() appends the given string to the value of ++ * the named property in the given node, or creates a new property ++ * with that value if it does not already exist. ++ * ++ * This function may insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain the new property value ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ ++ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) ++ ++/** ++ * fdt_appendprop_addrrange - append a address range property ++ * @fdt: pointer to the device tree blob ++ * @parent: offset of the parent node ++ * @nodeoffset: offset of the node to add a property at ++ * @name: name of property ++ * @addr: start address of a given range ++ * @size: size of a given range ++ * ++ * fdt_appendprop_addrrange() appends an address range value (start ++ * address and size) to the value of the named property in the given ++ * node, or creates a new property with that value if it does not ++ * already exist. ++ * If "name" is not specified, a default "reg" is used. ++ * Cell sizes are determined by parent's #address-cells and #size-cells. ++ * ++ * This function may insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid ++ * #address-cells property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size ++ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to ++ * contain a new property ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, ++ const char *name, uint64_t addr, uint64_t size); ++ ++/** ++ * fdt_delprop - delete a property ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node whose property to nop ++ * @name: name of the property to nop ++ * ++ * fdt_del_property() will delete the given property. ++ * ++ * This function will delete data from the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOTFOUND, node does not have the named property ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_delprop(void *fdt, int nodeoffset, const char *name); ++ ++/** ++ * fdt_add_subnode_namelen - creates a new node based on substring ++ * @fdt: pointer to the device tree blob ++ * @parentoffset: structure block offset of a node ++ * @name: name of the subnode to create ++ * @namelen: number of characters of name to consider ++ * ++ * Identical to fdt_add_subnode(), but use only the first @namelen ++ * characters of @name as the name of the new node. This is useful for ++ * creating subnodes based on a portion of a larger string, such as a ++ * full path. ++ * ++ * Return: structure block offset of the created subnode (>=0), ++ * negative libfdt error value otherwise ++ */ ++#ifndef SWIG /* Not available in Python */ ++int fdt_add_subnode_namelen(void *fdt, int parentoffset, ++ const char *name, int namelen); ++#endif ++ ++/** ++ * fdt_add_subnode - creates a new node ++ * @fdt: pointer to the device tree blob ++ * @parentoffset: structure block offset of a node ++ * @name: name of the subnode to locate ++ * ++ * fdt_add_subnode() creates a new node as a subnode of the node at ++ * structure block offset parentoffset, with the given name (which ++ * should include the unit address, if any). ++ * ++ * This function will insert data into the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * structure block offset of the created nodeequested subnode (>=0), on ++ * success ++ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist ++ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE ++ * tag ++ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of ++ * the given name ++ * -FDT_ERR_NOSPACE, if there is insufficient free space in the ++ * blob to contain the new node ++ * -FDT_ERR_NOSPACE ++ * -FDT_ERR_BADLAYOUT ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings. ++ */ ++int fdt_add_subnode(void *fdt, int parentoffset, const char *name); ++ ++/** ++ * fdt_del_node - delete a node (subtree) ++ * @fdt: pointer to the device tree blob ++ * @nodeoffset: offset of the node to nop ++ * ++ * fdt_del_node() will remove the given node, including all its ++ * subnodes if any, from the blob. ++ * ++ * This function will delete data from the blob, and will therefore ++ * change the offsets of some existing nodes. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_del_node(void *fdt, int nodeoffset); ++ ++/** ++ * fdt_overlay_apply - Applies a DT overlay on a base DT ++ * @fdt: pointer to the base device tree blob ++ * @fdto: pointer to the device tree overlay blob ++ * ++ * fdt_overlay_apply() will apply the given device tree overlay on the ++ * given base device tree. ++ * ++ * Expect the base device tree to be modified, even if the function ++ * returns an error. ++ * ++ * returns: ++ * 0, on success ++ * -FDT_ERR_NOSPACE, there's not enough space in the base device tree ++ * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or ++ * properties in the base DT ++ * -FDT_ERR_BADPHANDLE, ++ * -FDT_ERR_BADOVERLAY, ++ * -FDT_ERR_NOPHANDLES, ++ * -FDT_ERR_INTERNAL, ++ * -FDT_ERR_BADLAYOUT, ++ * -FDT_ERR_BADMAGIC, ++ * -FDT_ERR_BADOFFSET, ++ * -FDT_ERR_BADPATH, ++ * -FDT_ERR_BADVERSION, ++ * -FDT_ERR_BADSTRUCTURE, ++ * -FDT_ERR_BADSTATE, ++ * -FDT_ERR_TRUNCATED, standard meanings ++ */ ++int fdt_overlay_apply(void *fdt, void *fdto); ++ ++/** ++ * fdt_overlay_target_offset - retrieves the offset of a fragment's target ++ * @fdt: Base device tree blob ++ * @fdto: Device tree overlay blob ++ * @fragment_offset: node offset of the fragment in the overlay ++ * @pathp: pointer which receives the path of the target (or NULL) ++ * ++ * fdt_overlay_target_offset() retrieves the target offset in the base ++ * device tree of a fragment, no matter how the actual targeting is ++ * done (through a phandle or a path) ++ * ++ * returns: ++ * the targeted node offset in the base device tree ++ * Negative error code on error ++ */ ++int fdt_overlay_target_offset(const void *fdt, const void *fdto, ++ int fragment_offset, char const **pathp); ++ ++/**********************************************************************/ ++/* Debugging / informational functions */ ++/**********************************************************************/ ++ ++const char *fdt_strerror(int errval); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LIBFDT_H */ +diff --git a/include/libfdt_env.h b/include/libfdt_env.h +new file mode 100644 +index 0000000..51b31d1 +--- /dev/null ++++ b/include/libfdt_env.h +@@ -0,0 +1,95 @@ ++/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ ++#ifndef LIBFDT_ENV_H ++#define LIBFDT_ENV_H ++/* ++ * libfdt - Flat Device Tree manipulation ++ * Copyright (C) 2006 David Gibson, IBM Corporation. ++ * Copyright 2012 Kim Phillips, Freescale Semiconductor. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __CHECKER__ ++#define FDT_FORCE __attribute__((force)) ++#define FDT_BITWISE __attribute__((bitwise)) ++#else ++#define FDT_FORCE ++#define FDT_BITWISE ++#endif ++ ++typedef uint16_t FDT_BITWISE fdt16_t; ++typedef uint32_t FDT_BITWISE fdt32_t; ++typedef uint64_t FDT_BITWISE fdt64_t; ++ ++#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) ++#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) ++#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ ++ (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) ++#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ ++ (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ ++ (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ ++ (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) ++ ++static inline uint16_t fdt16_to_cpu(fdt16_t x) ++{ ++ return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); ++} ++static inline fdt16_t cpu_to_fdt16(uint16_t x) ++{ ++ return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); ++} ++ ++static inline uint32_t fdt32_to_cpu(fdt32_t x) ++{ ++ return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); ++} ++static inline fdt32_t cpu_to_fdt32(uint32_t x) ++{ ++ return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); ++} ++ ++static inline uint64_t fdt64_to_cpu(fdt64_t x) ++{ ++ return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); ++} ++static inline fdt64_t cpu_to_fdt64(uint64_t x) ++{ ++ return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); ++} ++#undef CPU_TO_FDT64 ++#undef CPU_TO_FDT32 ++#undef CPU_TO_FDT16 ++#undef EXTRACT_BYTE ++ ++#ifdef __APPLE__ ++#include ++ ++/* strnlen() is not available on Mac OS < 10.7 */ ++# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ ++ MAC_OS_X_VERSION_10_7) ++ ++#define strnlen fdt_strnlen ++ ++/* ++ * fdt_strnlen: returns the length of a string or max_count - which ever is ++ * smallest. ++ * Input 1 string: the string whose size is to be determined ++ * Input 2 max_count: the maximum value returned by this function ++ * Output: length of the string or max_count (the smallest of the two) ++ */ ++static inline size_t fdt_strnlen(const char *string, size_t max_count) ++{ ++ const char *p = memchr(string, 0, max_count); ++ return p ? p - string : max_count; ++} ++ ++#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < ++ MAC_OS_X_VERSION_10_7) */ ++ ++#endif /* __APPLE__ */ ++ ++#endif /* LIBFDT_ENV_H */ diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch new file mode 100644 index 000000000000..871a178f98aa --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch @@ -0,0 +1,101 @@ +From 0f2c7ca446063be6b193fbf870d38c0af19e15c5 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 28 Dec 2021 17:28:25 +0800 +Subject: [PATCH] common: Add essential libc functions + +The libfdt uses some of the libc functions, e.g. memcmp, memmove, +strlen .etc. Add them in lib.c. + +The code is copied from TF-A (v2.5) [1] project, which is under the +terms of BSD license. It is the same with boot-wrapper. + +[1]: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + +Issue-Id: SCM-3814 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: If3b55b00afa8694c7522df989a41e0b38eda1d38 +--- + common/lib.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 70 insertions(+), 1 deletion(-) + +diff --git a/common/lib.c b/common/lib.c +index fcf5f69..0be1c4a 100644 +--- a/common/lib.c ++++ b/common/lib.c +@@ -32,4 +32,73 @@ void *memset(void *s, int c, size_t n) + return s; + } + +-/* TODO: memmove and memcmp could also be called */ ++int memcmp(const void *s1, const void *s2, size_t len) ++{ ++ const unsigned char *s = s1; ++ const unsigned char *d = s2; ++ unsigned char sc; ++ unsigned char dc; ++ ++ while (len--) { ++ sc = *s++; ++ dc = *d++; ++ if (sc - dc) ++ return (sc - dc); ++ } ++ ++ return 0; ++} ++ ++void *memmove(void *dst, const void *src, size_t len) ++{ ++ if ((size_t)dst - (size_t)src >= len) { ++ /* destination not in source data, so can safely use memcpy */ ++ return memcpy(dst, src, len); ++ } else { ++ /* copy backwards... */ ++ const char *end = dst; ++ const char *s = (const char *)src + len; ++ char *d = (char *)dst + len; ++ while (d != end) ++ *--d = *--s; ++ } ++ return dst; ++} ++ ++void *memchr(const void *src, int c, size_t len) ++{ ++ const unsigned char *s = src; ++ ++ while (len--) { ++ if (*s == (unsigned char)c) ++ return (void *) s; ++ s++; ++ } ++ ++ return NULL; ++} ++ ++char *strrchr(const char *p, int ch) ++{ ++ char *save; ++ char c; ++ ++ c = ch; ++ for (save = NULL;; ++p) { ++ if (*p == c) ++ save = (char *)p; ++ if (*p == '\0') ++ return (save); ++ } ++ /* NOTREACHED */ ++} ++ ++size_t strlen(const char *s) ++{ ++ const char *cursor = s; ++ ++ while (*cursor) ++ cursor++; ++ ++ return cursor - s; ++} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch new file mode 100644 index 000000000000..5917ef2052c2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch @@ -0,0 +1,61 @@ +From de5d2b6c200ae5dd8113751e58bf7cf5844eec5a Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 28 Dec 2021 17:42:48 +0800 +Subject: [PATCH] Makefile: Add the libfdt to the Makefile system + +Add the libfdt into Makefile system. The libfdt uses const value and +thus gcc will enable the stack guard. The stack guard will fail the +compile. Add -fno-stack-protector to fix it. + +Issue-Id: SCM-3814 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I472bc28cdc5cde3b22461a4b7d7a3752ae382b4b +--- + Makefile.am | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 88a27de..5e8668a 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -36,6 +36,9 @@ PSCI_CPU_OFF := 0x84000002 + COMMON_SRC := common/ + COMMON_OBJ := boot.o bakery_lock.o platform.o lib.o + ++LIBFDT_SRC := common/libfdt/ ++LIBFDT_OBJS := fdt.o fdt_ro.o fdt_rw.o ++ + ARCH_OBJ := boot.o stack.o utils.o + + if BOOTWRAPPER_32 +@@ -125,11 +128,12 @@ CHOSEN_NODE := chosen { \ + CPPFLAGS += $(INITRD_FLAGS) + CFLAGS += -I$(top_srcdir)/include/ -I$(top_srcdir)/$(ARCH_SRC)/include/ + CFLAGS += -Wall -fomit-frame-pointer ++CFLAGS += -fno-stack-protector + CFLAGS += -ffunction-sections -fdata-sections + CFLAGS += -fno-pic -fno-pie + LDFLAGS += --gc-sections + +-OBJ := $(addprefix $(ARCH_SRC),$(ARCH_OBJ)) $(addprefix $(COMMON_SRC),$(COMMON_OBJ)) ++OBJ := $(addprefix $(ARCH_SRC),$(ARCH_OBJ)) $(addprefix $(COMMON_SRC),$(COMMON_OBJ)) $(addprefix $(LIBFDT_SRC),$(LIBFDT_OBJS)) + + # Don't lookup all prerequisites in $(top_srcdir), only the source files. When + # building outside the source tree $(ARCH_SRC) needs to be created. +@@ -150,10 +154,13 @@ $(ARCH_SRC): + $(COMMON_SRC): + $(MKDIR_P) $@ + ++$(LIBFDT_SRC): ++ $(MKDIR_P) $@ ++ + %.o: %.S Makefile | $(ARCH_SRC) + $(CC) $(CPPFLAGS) -D__ASSEMBLY__ $(CFLAGS) $(DEFINES) -c -o $@ $< + +-%.o: %.c Makefile | $(COMMON_SRC) ++%.o: %.c Makefile | $(COMMON_SRC) $(LIBFDT_SRC) + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $< + + model.lds: $(LD_SCRIPT) Makefile diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch new file mode 100644 index 000000000000..136e18ed2e13 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch @@ -0,0 +1,67 @@ +From 5b8cb5192dbd0332e027e8999c3afe4433983291 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Wed, 29 Dec 2021 10:50:21 +0800 +Subject: [PATCH] platform: Add print_hex func + +Refine the print functions, and add a new print_hex func to print hex +numbers. + +Issue-Id: SCM-3814 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: Ic960345d9ef0b41d81d30c4a4dbd9c31139907c4 +--- + common/platform.c | 33 +++++++++++++++++++++++++-------- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/common/platform.c b/common/platform.c +index d11f568..8269392 100644 +--- a/common/platform.c ++++ b/common/platform.c +@@ -30,20 +30,37 @@ + #define V2M_SYS(reg) ((void *)SYSREGS_BASE + V2M_SYS_##reg) + #endif + +-static void print_string(const char *str) ++static void print_char(const char c) + { + uint32_t flags; ++ do { ++ flags = raw_readl(PL011(UARTFR)); ++ } while (flags & PL011_UARTFR_FIFO_FULL); + ++ raw_writel(c, PL011(UARTDR)); ++ ++ do { ++ flags = raw_readl(PL011(UARTFR)); ++ } while (flags & PL011_UARTFR_BUSY); ++} ++ ++void print_string(const char *str) ++{ + while (*str) { +- do +- flags = raw_readl(PL011(UARTFR)); +- while (flags & PL011_UARTFR_FIFO_FULL); ++ print_char(*str++); ++ } ++} + +- raw_writel(*str++, PL011(UARTDR)); ++#define HEX_CHARS_PER_INT (2 * sizeof(int)) ++ ++void print_hex(unsigned int val) ++{ + +- do +- flags = raw_readl(PL011(UARTFR)); +- while (flags & PL011_UARTFR_BUSY); ++ const char hex_chars[16] = "0123456789abcdef"; ++ int i; ++ for (i = HEX_CHARS_PER_INT - 1; i >= 0; i--) { ++ int v = (val >> (4 * i)) & 0xf; ++ print_char(hex_chars[v]); + } + } + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch new file mode 100644 index 000000000000..ea5181602990 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch @@ -0,0 +1,96 @@ +From b447242cd2457bec20d47fe6a8a5758d97a3bde3 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Wed, 19 Jan 2022 16:19:02 +0800 +Subject: [PATCH] common: Add mem usage to /memreserve/ + +Set /memreserve/ to prevent next boot stages from overrding PSCI +services with libfdt. + +Issue-Id: SCM-3815 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I2ea80cdf736a910fa2c3deb622e21d50f04be960 +--- + Makefile.am | 2 +- + common/boot.c | 1 + + common/device_tree.c | 34 ++++++++++++++++++++++++++++++++++ + include/boot.h | 1 + + 4 files changed, 37 insertions(+), 1 deletion(-) + create mode 100644 common/device_tree.c + +diff --git a/Makefile.am b/Makefile.am +index 5e8668a..734de92 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -34,7 +34,7 @@ endif + PSCI_CPU_OFF := 0x84000002 + + COMMON_SRC := common/ +-COMMON_OBJ := boot.o bakery_lock.o platform.o lib.o ++COMMON_OBJ := boot.o bakery_lock.o platform.o lib.o device_tree.o + + LIBFDT_SRC := common/libfdt/ + LIBFDT_OBJS := fdt.o fdt_ro.o fdt_rw.o +diff --git a/common/boot.c b/common/boot.c +index c74d34c..ee2bea0 100644 +--- a/common/boot.c ++++ b/common/boot.c +@@ -63,6 +63,7 @@ void __noreturn first_spin(unsigned int cpu, unsigned long *mbox, + { + if (cpu == 0) { + init_platform(); ++ dt_add_memreserve(); + + *mbox = (unsigned long)&entrypoint; + sevl(); +diff --git a/common/device_tree.c b/common/device_tree.c +new file mode 100644 +index 0000000..4d0876c +--- /dev/null ++++ b/common/device_tree.c +@@ -0,0 +1,34 @@ ++/* ++ * device_tree.c - Basic device tree node handler ++ * ++ * Copyright (C) 2021 ARM Limited. All rights reserved. ++ * ++ * Use of this source code is governed by a BSD-style license that can be ++ * found in the LICENSE.txt file. ++ */ ++#include ++ ++extern unsigned long dtb; ++extern char firmware_start[], firmware_end[]; ++ ++extern void print_string(const char *str); ++ ++static void *blob; ++ ++ ++void dt_add_memreserve(void) ++{ ++ int ret; ++ ++ blob = (void*)&dtb; ++ print_string("Add /memreserve/\n\r"); ++ ++ fdt_open_into(blob, blob, fdt_totalsize(blob) + ++ sizeof(struct fdt_reserve_entry)); ++ ret = fdt_add_mem_rsv(blob, (uint64_t)firmware_start, ++ (uint64_t)(firmware_end - firmware_start)); ++ ++ if(ret < 0) { ++ print_string("reserve mem add err\n\r"); ++ } ++} +diff --git a/include/boot.h b/include/boot.h +index d75e013..c3e2ec1 100644 +--- a/include/boot.h ++++ b/include/boot.h +@@ -16,4 +16,5 @@ void __noreturn spin(unsigned long *mbox, unsigned long invalid, int is_entry); + void __noreturn first_spin(unsigned int cpu, unsigned long *mbox, + unsigned long invalid_addr); + ++void dt_add_memreserve(void); + #endif diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch new file mode 100644 index 000000000000..0411ef02290b --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch @@ -0,0 +1,102 @@ +From 8271c21bcff260295203214b7b8c87cdb8236453 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 4 Jan 2022 17:01:55 +0800 +Subject: [PATCH] boot: Add the --enable-keep-el compile option + +Add --enable-keep-el compile option to enable boot-wrapper booting next +stage at EL2. +The Armv8R AArch64 boots at EL2. If the next stage requires EL2 booting, +the boot-wrapper should not drop to EL1. +Currently, this option only works for Armv8R AArch64. Also, to work with +Linux PSCI, this option will cause secondary cores booting at EL1. + +Issue-Id: SCM-3813 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I3ba9c87cf0b59d163ca433f74c9e3a46e5ca2c63 +--- + Makefile.am | 4 ++++ + arch/aarch64/boot.S | 6 +++++- + common/psci.c | 6 ++++++ + configure.ac | 5 +++++ + 4 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 734de92..054becd 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -33,6 +33,10 @@ PSCI_CPU_ON := 0xc4000003 + endif + PSCI_CPU_OFF := 0x84000002 + ++if KEEP_EL ++DEFINES += -DKEEP_EL ++endif ++ + COMMON_SRC := common/ + COMMON_OBJ := boot.o bakery_lock.o platform.o lib.o device_tree.o + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 6dbd5cc..157c097 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -233,7 +233,11 @@ el2_init: + msr cnthctl_el2, x0 + isb + ++#ifdef KEEP_EL ++ mov w0, #SPSR_KERNEL ++#else + mov w0, #SPSR_KERNEL_EL1 ++#endif + ldr x1, =spsr_to_elx + str w0, [x1] + // fall through +@@ -313,5 +317,5 @@ ASM_FUNC(jump_kernel) + .align 3 + flag_keep_el: + .long 0 +-spsr_to_elx: ++ASM_DATA(spsr_to_elx) + .long 0 +diff --git a/common/psci.c b/common/psci.c +index a0e8700..945780b 100644 +--- a/common/psci.c ++++ b/common/psci.c +@@ -18,6 +18,8 @@ + #error "No MPIDRs provided" + #endif + ++extern unsigned int spsr_to_elx; ++ + static unsigned long branch_table[NR_CPUS]; + + bakery_ticket_t branch_table_lock[NR_CPUS]; +@@ -44,6 +46,10 @@ static int psci_cpu_on(unsigned long target_mpidr, unsigned long address) + ret = psci_store_address(cpu, address); + bakery_unlock(branch_table_lock, this_cpu); + ++#ifdef KEEP_EL ++ spsr_to_elx = SPSR_KERNEL_EL1; ++#endif ++ + return ret; + } + +diff --git a/configure.ac b/configure.ac +index 53e51be..0e07db3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -25,6 +25,11 @@ AS_IF([test "x$BOOTWRAPPER_ES" = x32 -a "x$KERNEL_ES" != x32], + [AC_MSG_ERROR([a 32-bit boot-wrapper cannot launch a 64-bit kernel])] + ) + ++AC_ARG_ENABLE([keep-el], ++ AC_HELP_STRING([--enable-keep-el], [keep exception level when start kernel]), ++ [KEEP_EL=yes], [KEEP_EL=no]) ++AM_CONDITIONAL([KEEP_EL], [test "x$KEEP_EL" = xyes]) ++ + # Allow a user to pass --with-kernel-dir + AC_ARG_WITH([kernel-dir], + AS_HELP_STRING([--with-kernel-dir], [specify the root Linux kernel build directory (required)]), diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch new file mode 100644 index 000000000000..a6b16e403a57 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch @@ -0,0 +1,34 @@ +From dd3e3f414d0e6ed1643c2e2ccac676b7fc1dc7a9 Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Tue, 1 Feb 2022 11:28:46 +0000 +Subject: [PATCH] Makefile: Change COUNTER_FREQ to 100 MHz + +Older Arm Fast Models (AEM < RevC) had a base frequency of 24 MHz. but +the RevC base models use 100 MHz. There is not a robust method of +determining the configured base frequency at runtime, so update +COUNTER_FREQ to be 100 MHz. + +Issue-Id: SCM-3871 +Upstream-Status: Pending +Signed-off-by: Peter Hoyes +Change-Id: Ia9ad0f8ee488d1a887791f1fa1d8f3bf9c5887fd +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 40bc5d6..b48173c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -13,7 +13,7 @@ SCRIPT_DIR := $(top_srcdir)/scripts + PHYS_OFFSET := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findmem.pl $(KERNEL_DTB)) + UART_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,pl011') + SYSREGS_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,vexpress-sysreg' 2> /dev/null) +-COUNTER_FREQ := 24000000 ++COUNTER_FREQ := 100000000 + + CPU_IDS := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findcpuids.pl $(KERNEL_DTB)) + NR_CPUS := $(shell echo $(CPU_IDS) | tr ',' ' ' | wc -w) +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch new file mode 100644 index 000000000000..8d981f525c41 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch @@ -0,0 +1,52 @@ +From 6923f2a0c59cf92ba5ad50ec1d658a357b4ba5d7 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 2 Nov 2021 10:48:39 +0800 +Subject: [PATCH] PSCI: Apply flush cache after setting branch_data + +For v8-R64, Hypervisor calls boot-wrapper's PSCI service using simple +function call (instead of hvc). + +In this case, hypervisor's main core has enabled MPU and cache, but +the secondary cores which are spinning have not enabled cache. +That means if the main core set the branch_data to 1 to boot other +cores, the secondary cores cannot see the change of branch_data and +also cannot break the spin. + +Thus, the PSCI service in boot-wrapper needs a cache flush after +setting branch_data in order to let other cores see the change. + +Issue-ID: SCM-3816 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: Ifc282091c54d8fb2ffdb8cfa7fd3ffc1f4be717e +--- + common/psci.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/common/psci.c b/common/psci.c +index 945780b..6efc695 100644 +--- a/common/psci.c ++++ b/common/psci.c +@@ -24,12 +24,18 @@ static unsigned long branch_table[NR_CPUS]; + + bakery_ticket_t branch_table_lock[NR_CPUS]; + ++static inline void flush_per_cpu_data(void *data) ++{ ++ asm volatile ("dc cvac, %0" : : "r" (data)); ++} ++ + static int psci_store_address(unsigned int cpu, unsigned long address) + { + if (branch_table[cpu] != PSCI_ADDR_INVALID) + return PSCI_RET_ALREADY_ON; + + branch_table[cpu] = address; ++ flush_per_cpu_data((void*)&(branch_table[cpu])); + return PSCI_RET_SUCCESS; + } + +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch new file mode 100644 index 000000000000..97cd3cb9e0ac --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch @@ -0,0 +1,74 @@ +From ed46e83df2400b1b3f3364169aacf787bd91bd45 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 25 Jan 2022 14:56:36 +0800 +Subject: [PATCH] PSCI: Add function call entry point + +The max exception level of Armv8R AArch64 is EL2, which means it has no +exclusive EL for firmware. That is, firmware and hypervisors have to share +the EL2. Also, hypervisors cannot call firmware services via a 'smc' +instruction. Thus, boot-wrapper has to provide a function entry point +for Armv8R AArch64. + +Issue-Id: SCM-3816 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I06ec8e50298603155c6d8ae2330e71db2f111182 +--- + common/psci.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/common/psci.c b/common/psci.c +index 6efc695..8fdefb5 100644 +--- a/common/psci.c ++++ b/common/psci.c +@@ -20,6 +20,8 @@ + + extern unsigned int spsr_to_elx; + ++unsigned long flag_from_smc_fn[NR_CPUS]; ++ + static unsigned long branch_table[NR_CPUS]; + + bakery_ticket_t branch_table_lock[NR_CPUS]; +@@ -49,12 +51,14 @@ static int psci_cpu_on(unsigned long target_mpidr, unsigned long address) + return PSCI_RET_INVALID_PARAMETERS; + + bakery_lock(branch_table_lock, this_cpu); +- ret = psci_store_address(cpu, address); +- bakery_unlock(branch_table_lock, this_cpu); +- + #ifdef KEEP_EL +- spsr_to_elx = SPSR_KERNEL_EL1; ++ if (!flag_from_smc_fn[this_cpu]) { ++ spsr_to_elx = SPSR_KERNEL_EL1; ++ flush_per_cpu_data((void*)&(spsr_to_elx)); ++ } + #endif ++ ret = psci_store_address(cpu, address); ++ bakery_unlock(branch_table_lock, this_cpu); + + return ret; + } +@@ -90,6 +94,18 @@ long psci_call(unsigned long fid, unsigned long arg1, unsigned long arg2) + } + } + ++long smc_fn_entry(unsigned long fid, unsigned long arg1, unsigned long arg2) ++{ ++ long ret; ++ unsigned int this_cpu = this_cpu_logical_id(); ++ ++ flag_from_smc_fn[this_cpu] = 1; ++ ret = psci_call(fid, arg1, arg2); ++ flag_from_smc_fn[this_cpu] = 0; ++ ++ return ret; ++} ++ + void __noreturn psci_first_spin(unsigned int cpu) + { + if (cpu == MPIDR_INVALID) +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch new file mode 100644 index 000000000000..1f10209da198 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch @@ -0,0 +1,61 @@ +From 36b5fa3f4db49ac7aef42ff1d58a895226c7e96c Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Tue, 2 Nov 2021 15:10:28 +0800 +Subject: [PATCH] lds: Rearrange and mark the sections + +To make it possible for the next stage to protect sections with MPU, +boot-wrapper needs to provide the text and data section information. +By rearranging the .data .rodata and .vector sections, all sections +can be split into 2 big sections: + - RO and Executable + - RW and Non-Executable +Add firmware_data to mark the boundry, thus: +firmware_start to firmware_data - 1 indicates RO and Executable section, +firmware_data to firmware_end - 1 indicates RW and Non-Executable +section. + +Also, the firmware_data and firmware_end should align with 64 bytes, +since Armv8R AArch64 MPU requires it. + +Issue-ID: SCM-3816 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I55342aa7492f2c7b5c16ab9a6472c8cb45cff8fd +--- + model.lds.S | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/model.lds.S b/model.lds.S +index ab98ddf..85451f9 100644 +--- a/model.lds.S ++++ b/model.lds.S +@@ -63,12 +63,16 @@ SECTIONS + } + #endif + ++#define FIRMWARE_ALIGN . = ALIGN(1 << 6) + .boot PHYS_OFFSET: { + PROVIDE(firmware_start = .); + *(.init) + *(.text*) +- *(.data* .rodata* .bss* COMMON) + *(.vectors) ++ *(.rodata*) ++ FIRMWARE_ALIGN; ++ PROVIDE(firmware_data = .); ++ *(.data* .bss* COMMON) + *(.stack) + PROVIDE(etext = .); + } +@@ -77,6 +81,7 @@ SECTIONS + mbox = .; + QUAD(0x0) + } ++ FIRMWARE_ALIGN; + PROVIDE(firmware_end = .); + + ASSERT(etext <= (PHYS_OFFSET + TEXT_LIMIT), ".text overflow!") +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch new file mode 100644 index 000000000000..cafcc09bedd0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch @@ -0,0 +1,345 @@ +From 8bdbb64d13f14d40546b71dbcfee2b2a8ea002a5 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Wed, 29 Dec 2021 15:17:38 +0800 +Subject: [PATCH] common: Provide firmware info using libfdt + +Boot-wrapper uses libfdt to provide more info in device tree. +We add a new node to include those new firmware relevant infomation. +The new node defined as follows: + fw-shared-info { + compatible = "firmware,shared_info"; + + #address-cells = <0x02>; + #size-cells = <0x02>; + + version = "1.0"; + regions = ; + regions-permission = "RX", "R", "RWX", "RW"; + regions-cache = "Cache", "NCache", "Cache", "Device" + + function_entry = ; + }; +The node path is /fw-shared-info. +For boot-wrapper, in real case, it will be: + fw-shared-info { + compatible = "firmware,shared_info"; + + #address-cells = <0x02>; + #size-cells = <0x02>; + + version = "1.0"; + regions = <0x0 firmware_start 0x0 firmware_code_size + 0x0 firmware_data 0x0 firmware_data_size>; + regions-permission = "RX", "RW"; + regions-cache = "Cache", "Cache"; + + function_entry = <0x0 smc_fn_entry>; + }; + +Issue-Id: SCM-3816 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: I6ebc59ce2bd3939b0fe066720d57821eaa1bed27 +--- + common/device_tree.c | 271 ++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 270 insertions(+), 1 deletion(-) + +diff --git a/common/device_tree.c b/common/device_tree.c +index 4d0876c..7f7befc 100644 +--- a/common/device_tree.c ++++ b/common/device_tree.c +@@ -8,13 +8,225 @@ + */ + #include + ++#define DEVICE_TREE_DEBUG 1 ++ ++#define FW_NODE_NAME "/fw-shared-info" ++#define FW_COMPAT "firmware,shared_info" ++#define FW_INFO_VER "1.0" ++ ++#ifdef BOOTWRAPPER_32 ++#define CELL_NUM 1 ++#define VAL_TYPE uint32_t ++#else ++#define CELL_NUM 2 ++#define VAL_TYPE uint64_t ++#endif ++ ++#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) ++ + extern unsigned long dtb; +-extern char firmware_start[], firmware_end[]; ++extern char firmware_start[], firmware_data[], firmware_end[]; ++ ++extern long smc_fn_entry(unsigned long, unsigned long, unsigned long); + + extern void print_string(const char *str); ++extern void print_hex(unsigned int val); + + static void *blob; + ++static char *realloc_node(char *fdt, const char *name) ++{ ++ int delta; ++ int new_sz; ++ /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */ ++ delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1) ++ + FDT_TAGSIZE; ++ new_sz = fdt_totalsize(fdt) + delta; ++ fdt_open_into(fdt, fdt, new_sz); ++ return fdt; ++} ++ ++static int create_node(const char *node_name) ++{ ++ int node = 0; ++ char *p; ++ ++ p = strrchr(node_name, '/'); ++ if (!p) { ++ print_string("node name without '/'\r\n"); ++ return -1; ++ } ++ *p = '\0'; ++ ++ blob = realloc_node(blob, p + 1); ++ ++ if (p > node_name) { ++ node = fdt_path_offset(blob, node_name); ++ if (node < 0) { ++ print_string("no node name\r\n"); ++ return -1; ++ } ++ } ++ ++ node = fdt_add_subnode(blob, node, p + 1); ++ if (node < 0) { ++ print_string("add subnode err\r\n"); ++ return -1; ++ } ++ ++ return node; ++} ++ ++static int dt_create_fw_node(void) { ++ int fw_node; ++ ++ fw_node = fdt_path_offset(blob, FW_NODE_NAME); ++ ++ if(fw_node < 0) { ++ fw_node = create_node(FW_NODE_NAME); ++ } ++ ++ return fw_node; ++} ++ ++static char *realloc_property(char *fdt, int nodeoffset, const char *name, ++ int newlen) ++{ ++ int delta = 0; ++ int oldlen = 0; ++ int new_sz; ++ ++ if (!fdt_get_property(fdt, nodeoffset, name, &oldlen)) ++ delta = sizeof(struct fdt_property) + strlen(name) + 1; ++ ++ if (newlen > oldlen) ++ delta += ALIGN(newlen) - ALIGN(oldlen); ++ ++ new_sz = fdt_totalsize(fdt) + delta; ++ fdt_open_into(fdt, fdt, new_sz); ++ return fdt; ++} ++ ++static void dt_set_prop(int node, char *property, void *buf, int len) ++{ ++ int err; ++ ++ err = fdt_setprop(blob, node, property, buf, len); ++ if (err == -FDT_ERR_NOSPACE) { ++ blob = realloc_property(blob, node, property, len); ++ err = fdt_setprop(blob, node, property, buf, len); ++ } ++ if (err) { ++ print_string("fdt error\n\r"); ++ } ++} ++ ++static void dt_set_prop_u32(int node, char *property, uint32_t val) ++{ ++ fdt32_t fdt_val = cpu_to_fdt32(val); ++ int len = sizeof(fdt32_t); ++ ++ dt_set_prop(node, property, (void*)&fdt_val, len); ++} ++ ++static void dt_set_prop_u64(int node, char *property, uint64_t val) ++{ ++ fdt64_t fdt_val = cpu_to_fdt64(val); ++ int len = sizeof(fdt64_t); ++ ++ dt_set_prop(node, property, (void*)&fdt_val, len); ++} ++ ++/* This dt_set_prop_u32_array maybe unused according to the BOOTWRAPPER_32 */ ++__attribute__((unused)) ++static void dt_set_prop_u32_array(int node, char *property, uint32_t *vals, ++ int size) ++{ ++ fdt32_t *fdt_vals = (fdt32_t*)vals; ++ int len = sizeof(fdt32_t) * size; ++ ++ for (int i = 0; i < size; i++) { ++ fdt_vals[i] = cpu_to_fdt32(vals[i]); ++ } ++ ++ dt_set_prop(node, property, (void*)fdt_vals, len); ++} ++ ++static void dt_set_prop_u64_array(int node, char *property, uint64_t *vals, ++ int size) ++{ ++ fdt64_t *fdt_vals = (fdt64_t*)vals; ++ int len = sizeof(fdt64_t) * size; ++ ++ for (int i = 0; i < size; i++) { ++ fdt_vals[i] = cpu_to_fdt64(vals[i]); ++ } ++ ++ dt_set_prop(node, property, (void*)fdt_vals, len); ++} ++ ++#if DEVICE_TREE_DEBUG ++static void dt_dump_string(const void *s, int len) ++{ ++ char *sub = (char*)s; ++ int sublen; ++ while(*sub && ((uint64_t)sub - (uint64_t)s) < len) { ++ sublen = strlen(sub) + 1; ++ print_string(sub); ++ print_string(" "); ++ sub += sublen; ++ } ++ print_string("\n\r"); ++} ++ ++static void dt_dump_fdt32_array(const void *vals, int len) ++{ ++ fdt32_t *fdt_vals = (fdt32_t*)vals; ++ len = len / sizeof(fdt32_t); ++ for (int i = 0; i < len; i++) { ++ print_hex(fdt32_to_cpu(fdt_vals[i])); ++ print_string(" "); ++ } ++ print_string("\n\r"); ++} ++ ++static void dt_dump(int node, char *property, char type) ++{ ++ const void *val; ++ int len; ++ ++ val = fdt_getprop(blob, node, property, &len); ++ print_string(property); ++ print_string(": "); ++ ++ if (type == 's') { ++ /* string type */ ++ dt_dump_string(val, len); ++ return; ++ } ++ ++ /* uint type */ ++ dt_dump_fdt32_array(val, len); ++} ++ ++void dt_dump_all(int node) ++{ ++ if (node >= 0) { ++ print_string(FW_NODE_NAME" info:\r\n"); ++ dt_dump(node, "compatible", 's'); ++ dt_dump(node, "version", 's'); ++ dt_dump(node, "function_entry", 'i'); ++ dt_dump(node, "address-cells", 'i'); ++ dt_dump(node, "size-cells", 'i'); ++ dt_dump(node, "regions", 'i'); ++ dt_dump(node, "regions-permission", 's'); ++ dt_dump(node, "regions-cache", 's'); ++ print_string("\r\n"); ++ } ++} ++#else ++void dt_dump_all(int node) { (void*)node; return; } ++#endif + + void dt_add_memreserve(void) + { +@@ -32,3 +244,60 @@ void dt_add_memreserve(void) + print_string("reserve mem add err\n\r"); + } + } ++ ++void dt_fw_node_init(int enable) ++{ ++ int fw_node; ++ ++ VAL_TYPE regions[] = { ++ /* code region: start, end, ro, x, cachable */ ++ (VAL_TYPE)firmware_start, ++ (VAL_TYPE)(firmware_data - firmware_start), ++ /* data region: start, end, rw, xn, cachable */ ++ (VAL_TYPE)firmware_data, ++ (VAL_TYPE)(firmware_end - firmware_data), ++ }; ++ int regions_num = sizeof(regions) / sizeof(VAL_TYPE); ++ char regions_permission[] = "RX\0RW"; ++ char regions_cache[] = "Cache\0Cache"; ++ ++ if (!enable) ++ return; ++ ++ print_string("Prepare "FW_NODE_NAME" node\n\r"); ++ ++ blob = (void*)&dtb; ++ ++ if(fdt_path_offset(blob, "/psci") < 0) { ++ print_string("/psci node not found\n\r"); ++ return; ++ } ++ ++ fw_node = dt_create_fw_node(); ++ ++ if(fw_node < 0) { ++ print_string(FW_NODE_NAME" node create err\n\r"); ++ } ++ ++ dt_set_prop(fw_node, "compatible", FW_COMPAT, sizeof(FW_COMPAT)); ++ dt_set_prop(fw_node, "version", FW_INFO_VER, sizeof(FW_INFO_VER)); ++ ++ dt_set_prop_u32(fw_node, "address-cells", CELL_NUM); ++ dt_set_prop_u32(fw_node, "size-cells", CELL_NUM); ++ dt_set_prop(fw_node, "regions-permission", regions_permission, ++ sizeof(regions_permission)); ++ dt_set_prop(fw_node, "regions-cache", regions_cache, ++ sizeof(regions_cache)); ++ ++#ifdef BOOTWRAPPER_32 ++ dt_set_prop_u32_array(fw_node, "regions", regions, regions_num); ++ dt_set_prop_u32(fw_node, "function_entry", (VAL_TYPE)smc_fn_entry); ++#else ++ dt_set_prop_u64_array(fw_node, "regions", regions, regions_num); ++ dt_set_prop_u64(fw_node, "function_entry", (VAL_TYPE)smc_fn_entry); ++#endif ++ ++ fdt_pack(blob); ++ ++ dt_dump_all(fw_node); ++} +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch new file mode 100644 index 000000000000..943afdee3a5e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch @@ -0,0 +1,98 @@ +From 6dfc937d1ae54d2ae9f8c60ca29ba73ca14dc8c4 Mon Sep 17 00:00:00 2001 +From: Jaxson Han +Date: Wed, 29 Dec 2021 15:33:17 +0800 +Subject: [PATCH] boot: Enable firmware node initialization + +Enable the firmware node initialization, so that the next stage +(hypervisor) could share the EL2 with firmware (boot-wrapper). The next +stage (hypervisor) get the smccc entry point, code/data sections, the +sections attrs and firmware node version and so on. +It is worth noting that this EL2 sharing mechanism is only for Armv8R +AArch64, thus add flag_v8r to record if the arch is Armv8R AArch64. +Enable the firmware node initialization only if it is Armv8R AArch64. +Also, we increase the stack size to 1024 to fix the stack overflow issue +when using the libfdt. + +Add -fno-builtin options to CFLAGS to avoid the issue that the 'memset' +in common/lib.c conflicts with builtin 'memset' function. GCC version +>= 10 will have an incorrect compilation without -fno-builtin; + +Issue-Id: SCM-3816 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Jaxson Han +Change-Id: Ib274485a34d26215595fd0cd737be86610289817 +--- + Makefile.am | 4 ++-- + arch/aarch64/boot.S | 6 ++++++ + common/boot.c | 4 ++++ + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 054becd..b01809c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -23,7 +23,7 @@ DEFINES += -DCPU_IDS=$(CPU_IDS) + DEFINES += -DNR_CPUS=$(NR_CPUS) + DEFINES += $(if $(SYSREGS_BASE), -DSYSREGS_BASE=$(SYSREGS_BASE), ) + DEFINES += -DUART_BASE=$(UART_BASE) +-DEFINES += -DSTACK_SIZE=256 ++DEFINES += -DSTACK_SIZE=1024 + + if KERNEL_32 + DEFINES += -DKERNEL_32 +@@ -132,7 +132,7 @@ CHOSEN_NODE := chosen { \ + CPPFLAGS += $(INITRD_FLAGS) + CFLAGS += -I$(top_srcdir)/include/ -I$(top_srcdir)/$(ARCH_SRC)/include/ + CFLAGS += -Wall -fomit-frame-pointer +-CFLAGS += -fno-stack-protector ++CFLAGS += -fno-stack-protector -fno-builtin + CFLAGS += -ffunction-sections -fdata-sections + CFLAGS += -fno-pic -fno-pie + LDFLAGS += --gc-sections +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 157c097..f310387 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -240,6 +240,10 @@ el2_init: + #endif + ldr x1, =spsr_to_elx + str w0, [x1] ++ ++ mov w0, #1 ++ ldr x1, =flag_v8r ++ str w0, [x1] + // fall through + + el_max_init: +@@ -319,3 +323,5 @@ flag_keep_el: + .long 0 + ASM_DATA(spsr_to_elx) + .long 0 ++ASM_DATA(flag_v8r) ++ .long 0 +diff --git a/common/boot.c b/common/boot.c +index ee2bea0..38b2dca 100644 +--- a/common/boot.c ++++ b/common/boot.c +@@ -11,6 +11,9 @@ + + extern unsigned long entrypoint; + extern unsigned long dtb; ++extern unsigned int flag_v8r; ++ ++extern void dt_fw_node_init(int enable); + + void init_platform(void); + +@@ -64,6 +67,7 @@ void __noreturn first_spin(unsigned int cpu, unsigned long *mbox, + if (cpu == 0) { + init_platform(); + dt_add_memreserve(); ++ dt_fw_node_init(flag_v8r == 1); + + *mbox = (unsigned long)&entrypoint; + sevl(); +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/external-system/external-system_0.1.0.bb b/meta-arm/meta-arm-bsp/recipes-bsp/external-system/external-system_0.1.0.bb new file mode 100644 index 000000000000..5bb8c37c56dd --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/external-system/external-system_0.1.0.bb @@ -0,0 +1,47 @@ +SUMMARY = "External system Cortex-M3 Firmware" +DESCRIPTION = "Firmware to be loaded and run in External System Harness in\ + support to the main application CPU." +HOMEPAGE = "https://git.linaro.org/landing-teams/working/arm/external-system.git" +DEPENDS = "gcc-arm-none-eabi-native" +INHIBIT_DEFAULT_DEPS="1" +LICENSE = "BSD-3-Clause & Apache-2.0" +LIC_FILES_CHKSUM = "file://license.md;md5=e44b2531cd6ffe9dece394dbe988d9a0 \ + file://cmsis/LICENSE.txt;md5=e3fc50a88d0a364313df4b21ef20c29e" + +SRC_URI = "gitsm://git.gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx.git;protocol=https;branch=master" +SRCREV = "8c9dca74b104ff6c9722fb0738ba93dd3719c080" +PV .= "+git${SRCPV}" + +COMPATIBLE_MACHINE = "(corstone1000)" + +# PRODUCT is passed to the Makefile to specify the platform to be used. +PRODUCT = "corstone-1000" + +S = "${WORKDIR}/git" +B = "${WORKDIR}/build" + +LDFLAGS[unexport] = "1" + +do_compile() { + oe_runmake -C ${S} V=y \ + BUILD_PATH=${B} \ + PRODUCT=${PRODUCT} \ + CROSS_COMPILE=arm-none-eabi- \ + all +} + +do_compile[cleandirs] = "${B}" + +do_install() { + install -D -p -m 0644 ${B}/product/${PRODUCT}/firmware/release/bin/firmware.bin ${D}/firmware/es_flashfw.bin +} + +FILES:${PN} = "/firmware" +SYSROOT_DIRS += "/firmware" + +inherit deploy + +do_deploy() { + cp -rf ${D}/firmware/* ${DEPLOYDIR}/ +} +addtask deploy after do_install diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-feat-emulate-cntp-timer-register-accesses-using-cnth.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-feat-emulate-cntp-timer-register-accesses-using-cnth.patch new file mode 100644 index 000000000000..a9a839ea8d78 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-feat-emulate-cntp-timer-register-accesses-using-cnth.patch @@ -0,0 +1,250 @@ +From f526797b83113cc64e3e658c22d8a5d269896a2a Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Fri, 4 Mar 2022 16:48:14 +0000 +Subject: [PATCH] feat: emulate cntp timer register accesses using cnthps + +Upstream-Status: Inappropriate [Experimental feature] +Signed-off-by: Ben Horgan +Change-Id: I67508203273baf3bd8e6be2d99717028db945715 +--- + Makefile | 3 +- + src/arch/aarch64/hypervisor/BUILD.gn | 1 + + src/arch/aarch64/hypervisor/cpu.c | 11 ++- + src/arch/aarch64/hypervisor/handler.c | 6 ++ + src/arch/aarch64/hypervisor/timer_el1.c | 104 ++++++++++++++++++++++++ + src/arch/aarch64/hypervisor/timer_el1.h | 20 +++++ + src/arch/aarch64/msr.h | 8 ++ + 7 files changed, 150 insertions(+), 3 deletions(-) + create mode 100644 src/arch/aarch64/hypervisor/timer_el1.c + create mode 100644 src/arch/aarch64/hypervisor/timer_el1.h + +diff --git a/Makefile b/Makefile +index 95cab9a5..21cca938 100644 +--- a/Makefile ++++ b/Makefile +@@ -60,7 +60,8 @@ CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \ + # debug_el1.c : uses XMACROS, which checkpatch doesn't understand. + # perfmon.c : uses XMACROS, which checkpatch doesn't understand. + # feature_id.c : uses XMACROS, which checkpatch doesn't understand. +-CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c" ++# timer_el1.c : uses XMACROS, which checkpatch doesn't understand. ++CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c\|src/arch/aarch64/hypervisor/timer_el1.c" + + OUT ?= out/$(PROJECT) + OUT_DIR = out/$(PROJECT) +diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn +index 6068d1e8..de1a414d 100644 +--- a/src/arch/aarch64/hypervisor/BUILD.gn ++++ b/src/arch/aarch64/hypervisor/BUILD.gn +@@ -45,6 +45,7 @@ source_set("hypervisor") { + "handler.c", + "perfmon.c", + "psci_handler.c", ++ "timer_el1.c", + "vm.c", + ] + +diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c +index bcf5ffce..d2df77d8 100644 +--- a/src/arch/aarch64/hypervisor/cpu.c ++++ b/src/arch/aarch64/hypervisor/cpu.c +@@ -98,13 +98,20 @@ void arch_regs_reset(struct vcpu *vcpu) + if (is_primary) { + /* + * cnthctl_el2 is redefined when VHE is enabled. +- * EL1PCTEN, don't trap phys cnt access. +- * EL1PCEN, don't trap phys timer access. ++ * EL1PCTEN, don't trap phys cnt access. Except when in ++ * secure world without vhe. ++ * EL1PCEN, don't trap phys timer access. Except when in ++ * secure world without vhe. + */ + if (has_vhe_support()) { + cnthctl |= (1U << 10) | (1U << 11); + } else { ++#if SECURE_WORLD == 1 ++ cnthctl &= ~(1U << 0); ++ cnthctl &= ~(1U << 1); ++#else + cnthctl |= (1U << 0) | (1U << 1); ++#endif + } + } + +diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c +index 4bd8a3b4..4c1b6e48 100644 +--- a/src/arch/aarch64/hypervisor/handler.c ++++ b/src/arch/aarch64/hypervisor/handler.c +@@ -34,6 +34,7 @@ + #include "psci_handler.h" + #include "smc.h" + #include "sysregs.h" ++#include "timer_el1.h" + + /** + * Hypervisor Fault Address Register Non-Secure. +@@ -1277,6 +1278,11 @@ void handle_system_register_access(uintreg_t esr_el2) + inject_el1_unknown_exception(vcpu, esr_el2); + return; + } ++ } else if (timer_el1_is_register_access(esr_el2)) { ++ if (!timer_el1_process_access(vcpu, vm_id, esr_el2)) { ++ inject_el1_unknown_exception(vcpu, esr_el2); ++ return; ++ } + } else { + inject_el1_unknown_exception(vcpu, esr_el2); + return; +diff --git a/src/arch/aarch64/hypervisor/timer_el1.c b/src/arch/aarch64/hypervisor/timer_el1.c +new file mode 100644 +index 00000000..c30e5543 +--- /dev/null ++++ b/src/arch/aarch64/hypervisor/timer_el1.c +@@ -0,0 +1,104 @@ ++/* ++ * Copyright 2022 The Hafnium Authors. ++ * ++ * Use of this source code is governed by a BSD-style ++ * license that can be found in the LICENSE file or at ++ * https://opensource.org/licenses/BSD-3-Clause. ++ */ ++ ++#include "timer_el1.h" ++ ++#include "hf/dlog.h" ++ ++#include "msr.h" ++#include "sysregs.h" ++ ++/* ++ * Physical timer (CNTP) register encodings as defined in ++ * table D13-8 of the ARMv8 ARM (DDI0487F). ++ * TYPE, op0, op1, crn, crm, op2 ++ * The register names are the concatenation of ++ * "CNTP_", TYPE and "_EL2". ++ */ ++#define CNTP_REGISTERS \ ++ X(CTL, 3, 3, 14, 2, 1) \ ++ X(CVAL, 3, 3, 14, 2, 2) \ ++ X(TVAL, 3, 3, 14, 2, 0) \ ++ ++bool timer_el1_is_register_access(uintreg_t esr) ++{ ++ uintreg_t sys_register = GET_ISS_SYSREG(esr); ++ bool is_timer_access; ++ switch (sys_register) { ++#define X(type, op0, op1, crn, crm, op2) \ ++ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \ ++ is_timer_access = true; \ ++ break; ++ CNTP_REGISTERS ++#undef X ++ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)): ++ is_timer_access = true; ++ break; ++ default: ++ is_timer_access = false; ++ } ++ ++ return is_timer_access; ++} ++ ++/* Accesses to CNTP timer emulated with CNTHPS */ ++bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id, ++ uintreg_t esr) ++{ ++ uintreg_t sys_register = GET_ISS_SYSREG(esr); ++ uintreg_t rt_register = GET_ISS_RT(esr); ++ uintreg_t value; ++ ++ if (ISS_IS_READ(esr)) { ++ switch (sys_register) { ++#define X(type, op0, op1, crn, crm, op2) \ ++ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \ ++ value = read_msr(MSR_CNTHPS_##type##_EL2); \ ++ vcpu->regs.r[rt_register] = value; \ ++ break; ++ CNTP_REGISTERS ++#undef X ++ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)): ++ value = read_msr(cntpct_el0); ++ vcpu->regs.r[rt_register] = value; ++ break; ++ default: ++ dlog_notice( ++ "Unsupported timer register " ++ "read: " ++ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, " ++ "rt=%d.\n", ++ GET_ISS_OP0(esr), GET_ISS_OP1(esr), ++ GET_ISS_CRN(esr), GET_ISS_CRM(esr), ++ GET_ISS_OP2(esr), GET_ISS_RT(esr)); ++ break; ++ } ++ } else { ++ value = vcpu->regs.r[rt_register]; ++ switch (sys_register) { ++#define X(type, op0, op1, crn, crm, op2) \ ++ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \ ++ write_msr(MSR_CNTHPS_##type##_EL2, value); \ ++ break; ++ CNTP_REGISTERS ++#undef X ++ default: ++ dlog_notice( ++ "Unsupported timer register " ++ "write: " ++ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, " ++ "rt=%d, value=%d.\n", ++ GET_ISS_OP0(esr), GET_ISS_OP1(esr), ++ GET_ISS_CRN(esr), GET_ISS_CRM(esr), ++ GET_ISS_OP2(esr), GET_ISS_RT(esr), value); ++ break; ++ } ++ } ++ ++ return true; ++} +diff --git a/src/arch/aarch64/hypervisor/timer_el1.h b/src/arch/aarch64/hypervisor/timer_el1.h +new file mode 100644 +index 00000000..04a43b6c +--- /dev/null ++++ b/src/arch/aarch64/hypervisor/timer_el1.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright 2022 The Hafnium Authors. ++ * ++ * Use of this source code is governed by a BSD-style ++ * license that can be found in the LICENSE file or at ++ * https://opensource.org/licenses/BSD-3-Clause. ++ */ ++ ++#pragma once ++ ++#include "hf/arch/types.h" ++ ++#include "hf/cpu.h" ++ ++#include "vmapi/hf/ffa.h" ++ ++bool timer_el1_is_register_access(uintreg_t esr); ++ ++bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id, ++ uintreg_t esr); +diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h +index cd6778b4..55e78330 100644 +--- a/src/arch/aarch64/msr.h ++++ b/src/arch/aarch64/msr.h +@@ -126,3 +126,11 @@ + #define MSR_ELR_EL12 S3_5_C4_C0_1 + + #endif ++ ++/* ++ * Secure EL2 Physical timer (CNTHPS) register encodings as defined in ++ * table D13-8 of the ARMv8 ARM (DDI0487F). ++ */ ++#define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1 ++#define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2 ++#define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-tc-increase-heap-pages.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-tc-increase-heap-pages.patch new file mode 100644 index 000000000000..fa35efc11221 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0001-tc-increase-heap-pages.patch @@ -0,0 +1,27 @@ +From 613dea068fa546956717ce0b60328e39d451f661 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Fri, 29 Apr 2022 20:07:50 +0100 +Subject: [PATCH] tc: increase heap pages + +Upstream-Status: Pending +Signed-off-by: Arunachalam Ganapathy +--- + BUILD.gn | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/BUILD.gn b/BUILD.gn +index 6b9b383..62ba763 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -235,7 +235,7 @@ aarch64_toolchains("secure_tc") { + gicd_base_address = "0x30000000" + gicr_base_address = "0x30080000" + gicr_frames = 8 +- heap_pages = 60 ++ heap_pages = 120 + max_cpus = 8 + max_vms = 16 + branch_protection = "standard" +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-emulate-interrupt-controller-register-access.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-emulate-interrupt-controller-register-access.patch new file mode 100644 index 000000000000..d9ec6e2a995a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-emulate-interrupt-controller-register-access.patch @@ -0,0 +1,157 @@ +From 97a8ca1835f5d9512dacda497540d5523e56c7dd Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Tue, 26 Apr 2022 14:43:58 +0100 +Subject: [PATCH] feat: emulate interrupt controller register access + +This emulates ICC_SGI1R_EL1 and ICC_IGRPEN1_EL1 register + +Signed-off-by: Arunachalam Ganapathy +Change-Id: I0c11f034f3676067597461a183a341c809adcaa4 +Upstream-Status: Inappropriate [Experimental feature] +--- + src/arch/aarch64/hypervisor/handler.c | 5 ++ + src/arch/aarch64/hypervisor/perfmon.c | 84 +++++++++++++++++++++++++++ + src/arch/aarch64/hypervisor/perfmon.h | 5 ++ + src/arch/aarch64/msr.h | 3 + + 4 files changed, 97 insertions(+) + +diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c +index 4c1b6e48..cd5146bd 100644 +--- a/src/arch/aarch64/hypervisor/handler.c ++++ b/src/arch/aarch64/hypervisor/handler.c +@@ -1283,6 +1283,11 @@ void handle_system_register_access(uintreg_t esr_el2) + inject_el1_unknown_exception(vcpu, esr_el2); + return; + } ++ } else if (intr_ctrl_is_register_access(esr_el2)) { ++ if (!intr_ctrl_el1_process_access(vcpu, vm_id, esr_el2)) { ++ inject_el1_unknown_exception(vcpu, esr_el2); ++ return; ++ } + } else { + inject_el1_unknown_exception(vcpu, esr_el2); + return; +diff --git a/src/arch/aarch64/hypervisor/perfmon.c b/src/arch/aarch64/hypervisor/perfmon.c +index f13b0354..05e216c8 100644 +--- a/src/arch/aarch64/hypervisor/perfmon.c ++++ b/src/arch/aarch64/hypervisor/perfmon.c +@@ -116,6 +116,10 @@ + X(PMEVTYPER30_EL0 , 3, 3, 14, 15, 6) \ + X(PMCCFILTR_EL0 , 3, 3, 14, 15, 7) + ++#define INTR_CTRL_REGISTERS \ ++ X(ICC_IGRPEN1_EL1 , 3, 0, 12, 12, 7) \ ++ X(ICC_SGI1R_EL1 , 3, 0, 12, 11, 5) \ ++ + /* clang-format on */ + + /** +@@ -232,3 +236,83 @@ uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id) + + return 0; + } ++ ++bool intr_ctrl_is_register_access(uintreg_t esr) ++{ ++ uintreg_t op0 = GET_ISS_OP0(esr); ++ uintreg_t op1 = GET_ISS_OP1(esr); ++ uintreg_t crn = GET_ISS_CRN(esr); ++ uintreg_t crm = GET_ISS_CRM(esr); ++ ++ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 12) { ++ return true; ++ } ++ ++ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 11) { ++ return true; ++ } ++ ++ return false; ++} ++ ++bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id, ++ uintreg_t esr) ++{ ++ uintreg_t sys_register = GET_ISS_SYSREG(esr); ++ uintreg_t rt_register = GET_ISS_RT(esr); ++ uintreg_t value; ++ ++ /* +1 because Rt can access register XZR */ ++ CHECK(rt_register < NUM_GP_REGS + 1); ++ ++ if (ISS_IS_READ(esr)) { ++ switch (sys_register) { ++#define X(reg_name, op0, op1, crn, crm, op2) \ ++ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \ ++ value = read_msr(reg_name); \ ++ break; ++ INTR_CTRL_REGISTERS ++#undef X ++ default: ++ value = vcpu->regs.r[rt_register]; ++ dlog_notice( ++ "Unsupported interrupt control register " ++ "read: " ++ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, " ++ "rt=%d.\n", ++ GET_ISS_OP0(esr), GET_ISS_OP1(esr), ++ GET_ISS_CRN(esr), GET_ISS_CRM(esr), ++ GET_ISS_OP2(esr), GET_ISS_RT(esr)); ++ break; ++ } ++ if (rt_register != RT_REG_XZR) { ++ vcpu->regs.r[rt_register] = value; ++ } ++ } else { ++ if (rt_register != RT_REG_XZR) { ++ value = vcpu->regs.r[rt_register]; ++ } else { ++ value = 0; ++ } ++ switch (sys_register) { ++#define X(reg_name, op0, op1, crn, crm, op2) \ ++ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \ ++ write_msr(reg_name, value); \ ++ break; ++ INTR_CTRL_REGISTERS ++#undef X ++ default: ++ dlog_notice( ++ "Unsupported interrupt control register " ++ "write: " ++ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, " ++ "rt=%d.\n", ++ GET_ISS_OP0(esr), GET_ISS_OP1(esr), ++ GET_ISS_CRN(esr), GET_ISS_CRM(esr), ++ GET_ISS_OP2(esr), GET_ISS_RT(esr)); ++ break; ++ } ++ } ++ ++ return true; ++} +diff --git a/src/arch/aarch64/hypervisor/perfmon.h b/src/arch/aarch64/hypervisor/perfmon.h +index 81669ba1..c90d45bf 100644 +--- a/src/arch/aarch64/hypervisor/perfmon.h ++++ b/src/arch/aarch64/hypervisor/perfmon.h +@@ -70,3 +70,8 @@ bool perfmon_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id, + uintreg_t esr_el2); + + uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id); ++ ++bool intr_ctrl_is_register_access(uintreg_t esr); ++ ++bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id, ++ uintreg_t esr); +diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h +index 55e78330..82aa8846 100644 +--- a/src/arch/aarch64/msr.h ++++ b/src/arch/aarch64/msr.h +@@ -134,3 +134,6 @@ + #define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1 + #define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2 + #define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0 ++ ++#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 ++#define ICC_SGI1R_EL1 S3_0_C12_C11_5 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-vhe-enable-vhe-and-disable-branch-protection-fo.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-vhe-enable-vhe-and-disable-branch-protection-fo.patch new file mode 100644 index 000000000000..9960f65dcf0c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0002-feat-vhe-enable-vhe-and-disable-branch-protection-fo.patch @@ -0,0 +1,31 @@ +From 1fef5bd2504ce3a203c56a3b66dba773cd4893c6 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Thu, 8 Sep 2022 10:47:10 +0530 +Subject: [PATCH] feat(vhe): enable vhe and disable branch protection for TC + +Signed-off-by: Davidson K +Change-Id: I60cd607d9f2bf0114b482980e7ca68e24aaf4d1f +Upstream-Status: Pending [Not submitted to upstream yet] +--- + BUILD.gn | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/BUILD.gn b/BUILD.gn +index 62ba763..f26ce03 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -238,7 +238,6 @@ aarch64_toolchains("secure_tc") { + heap_pages = 120 + max_cpus = 8 + max_vms = 16 +- branch_protection = "standard" + toolchain_args = { + plat_ffa = "//src/arch/aarch64/plat/ffa:spmc" + plat_psci = "//src/arch/aarch64/plat/psci:spmc" +@@ -247,5 +246,6 @@ aarch64_toolchains("secure_tc") { + secure_world = "1" + pl011_base_address = "0x7ff80000" + enable_mte = "1" ++ enable_vhe = "1" + } + } diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0003-feat-disable-alignment-check-for-EL0-partitions.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0003-feat-disable-alignment-check-for-EL0-partitions.patch new file mode 100644 index 000000000000..5e620cf31856 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0003-feat-disable-alignment-check-for-EL0-partitions.patch @@ -0,0 +1,318 @@ +From 1c4d28493faed6cf189c75fa91d19131e6a34e04 Mon Sep 17 00:00:00 2001 +From: Olivier Deprez +Date: Mon, 8 Aug 2022 19:14:23 +0200 +Subject: [PATCH] feat: disable alignment check for EL0 partitions + +Relax hw alignment check specifically for (S-)EL0 partitions when +Hafnium runs with VHE enabled. EL1 partitions have a specific control +for EL1 and EL0 with respect to alignment check. +Create a hyp_state structure (from already defined flying registers) +within the vCPU context to hold the Hypervisor EL2 static configuration +applied when a vCPU runs. This state is switched back and forth when +running the Hypervisor or the VM. +Add SCTLR_EL2 to this context. An EL0 partition context is initialized +with SCTLR_EL2.A=0 such that alignment check is disabled when EL0 runs +in the EL2&0 translation regime. SCTLR_EL2.A is set back when returning +to the Hypervisor such that Hypervisor execution runs with aligment +check enabled at EL2. +Remove HCR_EL2 saving from vCPU exit path provided this register state +is static and doesn't change while a vCPU runs. +The rationale for such change is to permit running upstream SW stacks +such as the EDKII/StandaloneMm [1] for which default build assumes +unaligned accesses are permitted. Similar query exists for running +Trusted Services on top of Hafnium [2]. + +[1] https://github.com/tianocore/edk2/tree/master/StandaloneMmPkg +[2] https://trusted-services.readthedocs.io/en/integration/ + +Signed-off-by: Olivier Deprez +Change-Id: I2906f4c712425fcfb31adbf89e2e3b9ca293f181 +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/hafnium/hafnium/+/16195] +--- + src/arch/aarch64/hypervisor/cpu.c | 9 ++++--- + src/arch/aarch64/hypervisor/exceptions.S | 32 ++++++++++++++++-------- + src/arch/aarch64/hypervisor/feature_id.c | 6 ++--- + src/arch/aarch64/hypervisor/handler.c | 18 +++++++------ + src/arch/aarch64/inc/hf/arch/types.h | 9 +++++-- + src/arch/aarch64/mm.c | 2 +- + src/arch/aarch64/sysregs.c | 11 ++++++-- + src/arch/aarch64/sysregs.h | 2 +- + 8 files changed, 59 insertions(+), 30 deletions(-) + +diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c +index d2df77d8..a000159b 100644 +--- a/src/arch/aarch64/hypervisor/cpu.c ++++ b/src/arch/aarch64/hypervisor/cpu.c +@@ -115,7 +115,9 @@ void arch_regs_reset(struct vcpu *vcpu) + } + } + +- r->hcr_el2 = get_hcr_el2_value(vm_id, vcpu->vm->el0_partition); ++ r->hyp_state.hcr_el2 = ++ get_hcr_el2_value(vm_id, vcpu->vm->el0_partition); ++ r->hyp_state.sctlr_el2 = get_sctlr_el2_value(vcpu->vm->el0_partition); + r->lazy.cnthctl_el2 = cnthctl; + if (vcpu->vm->el0_partition) { + CHECK(has_vhe_support()); +@@ -125,10 +127,11 @@ void arch_regs_reset(struct vcpu *vcpu) + * are ignored and treated as 0. There is no need to mask the + * VMID (used as asid) to only 8 bits. + */ +- r->ttbr0_el2 = pa_addr(table) | ((uint64_t)vm_id << 48); ++ r->hyp_state.ttbr0_el2 = ++ pa_addr(table) | ((uint64_t)vm_id << 48); + r->spsr = PSR_PE_MODE_EL0T; + } else { +- r->ttbr0_el2 = read_msr(ttbr0_el2); ++ r->hyp_state.ttbr0_el2 = read_msr(ttbr0_el2); + r->lazy.vtcr_el2 = arch_mm_get_vtcr_el2(); + r->lazy.vttbr_el2 = pa_addr(table) | ((uint64_t)vm_id << 48); + #if SECURE_WORLD == 1 +diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S +index 539e196d..d3732f86 100644 +--- a/src/arch/aarch64/hypervisor/exceptions.S ++++ b/src/arch/aarch64/hypervisor/exceptions.S +@@ -20,6 +20,9 @@ + #define ID_AA64PFR0_SVE_SHIFT (32) + #define ID_AA64PFR0_SVE_LENGTH (4) + ++#define SCTLR_EL2_A_SHIFT (1) ++#define HCR_EL2_TGE_SHIFT (27) ++ + /** + * Saves the volatile registers into the register buffer of the current vCPU. + */ +@@ -51,8 +54,6 @@ + mrs x1, elr_el2 + mrs x2, spsr_el2 + stp x1, x2, [x18, #VCPU_REGS + 8 * 31] +- mrs x1, hcr_el2 +- str x1, [x18, #VCPU_REGS + 8 * 33] + .endm + + /** +@@ -871,12 +872,13 @@ vcpu_restore_volatile_and_run: + msr elr_el2, x1 + msr spsr_el2, x2 + +- ldr x1, [x0, #VCPU_REGS + 8 * 33] ++ ldp x1, x2, [x0, #VCPU_REGS + 8 * 33] + msr hcr_el2, x1 ++ msr ttbr0_el2, x2 + isb + +- ldr x1, [x0, #VCPU_REGS + 8 * 34] +- msr ttbr0_el2, x1 ++ ldr x1, [x0, #VCPU_REGS + 8 * 35] ++ msr sctlr_el2, x1 + isb + + /* Restore x0..x3, which we have used as scratch before. */ +@@ -886,15 +888,17 @@ vcpu_restore_volatile_and_run: + + #if ENABLE_VHE + enable_vhe_tge: ++ mrs x0, id_aa64mmfr1_el1 ++ tst x0, #0xf00 ++ b.eq 1f ++ + /** + * Switch to host mode ({E2H, TGE} = {1,1}) when VHE is enabled. + * Note that E2H is always set when VHE is enabled. + */ +- mrs x0, id_aa64mmfr1_el1 +- tst x0, #0xf00 +- b.eq 1f +- orr x1, x1, #(1 << 27) +- msr hcr_el2, x1 ++ mrs x0, hcr_el2 ++ orr x0, x0, #(1 << HCR_EL2_TGE_SHIFT) ++ msr hcr_el2, x0 + isb + + /** +@@ -905,6 +909,14 @@ enable_vhe_tge: + ldr x0, [x0] + msr ttbr0_el2, x0 + isb ++ ++ /** ++ * Enable alignment check while Hypervisor runs. ++ */ ++ mrs x0, sctlr_el2 ++ orr x0, x0, #(1 << SCTLR_EL2_A_SHIFT) ++ msr sctlr_el2, x0 ++ isb + 1: + ret + #endif +diff --git a/src/arch/aarch64/hypervisor/feature_id.c b/src/arch/aarch64/hypervisor/feature_id.c +index ed3bf8f1..57f32627 100644 +--- a/src/arch/aarch64/hypervisor/feature_id.c ++++ b/src/arch/aarch64/hypervisor/feature_id.c +@@ -175,7 +175,7 @@ void feature_set_traps(struct vm *vm, struct arch_regs *regs) + ~(ID_AA64MMFR1_EL1_VH_MASK << ID_AA64MMFR1_EL1_VH_SHIFT); + + if (features & HF_FEATURE_RAS) { +- regs->hcr_el2 |= HCR_EL2_TERR; ++ regs->hyp_state.hcr_el2 |= HCR_EL2_TERR; + vm->arch.tid3_masks.id_aa64mmfr1_el1 &= + ~ID_AA64MMFR1_EL1_SPEC_SEI; + vm->arch.tid3_masks.id_aa64pfr0_el1 &= ~ID_AA64PFR0_EL1_RAS; +@@ -221,14 +221,14 @@ void feature_set_traps(struct vm *vm, struct arch_regs *regs) + } + + if (features & HF_FEATURE_LOR) { +- regs->hcr_el2 |= HCR_EL2_TLOR; ++ regs->hyp_state.hcr_el2 |= HCR_EL2_TLOR; + + vm->arch.tid3_masks.id_aa64mmfr1_el1 &= ~ID_AA64MMFR1_EL1_LO; + } + + if (features & HF_FEATURE_PAUTH) { + /* APK and API bits *enable* trapping when cleared. */ +- regs->hcr_el2 &= ~(HCR_EL2_APK | HCR_EL2_API); ++ regs->hyp_state.hcr_el2 &= ~(HCR_EL2_APK | HCR_EL2_API); + + vm->arch.tid3_masks.id_aa64isar1_el1 &= ~ID_AA64ISAR1_EL1_GPI; + vm->arch.tid3_masks.id_aa64isar1_el1 &= ~ID_AA64ISAR1_EL1_GPA; +diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c +index cd5146bd..8a3d6289 100644 +--- a/src/arch/aarch64/hypervisor/handler.c ++++ b/src/arch/aarch64/hypervisor/handler.c +@@ -272,9 +272,9 @@ noreturn void sync_current_exception_noreturn(uintreg_t elr, uintreg_t spsr) + static void set_virtual_irq(struct arch_regs *r, bool enable) + { + if (enable) { +- r->hcr_el2 |= HCR_EL2_VI; ++ r->hyp_state.hcr_el2 |= HCR_EL2_VI; + } else { +- r->hcr_el2 &= ~HCR_EL2_VI; ++ r->hyp_state.hcr_el2 &= ~HCR_EL2_VI; + } + } + +@@ -283,14 +283,15 @@ static void set_virtual_irq(struct arch_regs *r, bool enable) + */ + static void set_virtual_irq_current(bool enable) + { +- uintreg_t hcr_el2 = current()->regs.hcr_el2; ++ struct vcpu *vcpu = current(); ++ uintreg_t hcr_el2 = vcpu->regs.hyp_state.hcr_el2; + + if (enable) { + hcr_el2 |= HCR_EL2_VI; + } else { + hcr_el2 &= ~HCR_EL2_VI; + } +- current()->regs.hcr_el2 = hcr_el2; ++ vcpu->regs.hyp_state.hcr_el2 = hcr_el2; + } + + /** +@@ -300,9 +301,9 @@ static void set_virtual_irq_current(bool enable) + static void set_virtual_fiq(struct arch_regs *r, bool enable) + { + if (enable) { +- r->hcr_el2 |= HCR_EL2_VF; ++ r->hyp_state.hcr_el2 |= HCR_EL2_VF; + } else { +- r->hcr_el2 &= ~HCR_EL2_VF; ++ r->hyp_state.hcr_el2 &= ~HCR_EL2_VF; + } + } + +@@ -311,14 +312,15 @@ static void set_virtual_fiq(struct arch_regs *r, bool enable) + */ + static void set_virtual_fiq_current(bool enable) + { +- uintreg_t hcr_el2 = current()->regs.hcr_el2; ++ struct vcpu *vcpu = current(); ++ uintreg_t hcr_el2 = vcpu->regs.hyp_state.hcr_el2; + + if (enable) { + hcr_el2 |= HCR_EL2_VF; + } else { + hcr_el2 &= ~HCR_EL2_VF; + } +- current()->regs.hcr_el2 = hcr_el2; ++ vcpu->regs.hyp_state.hcr_el2 = hcr_el2; + } + + #if SECURE_WORLD == 1 +diff --git a/src/arch/aarch64/inc/hf/arch/types.h b/src/arch/aarch64/inc/hf/arch/types.h +index 6379d73e..6b8b24f1 100644 +--- a/src/arch/aarch64/inc/hf/arch/types.h ++++ b/src/arch/aarch64/inc/hf/arch/types.h +@@ -79,8 +79,13 @@ struct arch_regs { + uintreg_t r[NUM_GP_REGS]; + uintreg_t pc; + uintreg_t spsr; +- uintreg_t hcr_el2; +- uintreg_t ttbr0_el2; ++ ++ /* Hypervisor configuration while a vCPU runs. */ ++ struct { ++ uintreg_t hcr_el2; ++ uintreg_t ttbr0_el2; ++ uintreg_t sctlr_el2; ++ } hyp_state; + + /* + * System registers. +diff --git a/src/arch/aarch64/mm.c b/src/arch/aarch64/mm.c +index 8ee65ca0..487ae353 100644 +--- a/src/arch/aarch64/mm.c ++++ b/src/arch/aarch64/mm.c +@@ -886,7 +886,7 @@ bool arch_mm_init(paddr_t table) + #endif + (0xff << (8 * STAGE1_NORMALINDX)), + +- .sctlr_el2 = get_sctlr_el2_value(), ++ .sctlr_el2 = get_sctlr_el2_value(false), + .vstcr_el2 = (1U << 31) | /* RES1. */ + (0 << 30) | /* SA. */ + (0 << 29) | /* SW. */ +diff --git a/src/arch/aarch64/sysregs.c b/src/arch/aarch64/sysregs.c +index e8c154b1..087ba4ed 100644 +--- a/src/arch/aarch64/sysregs.c ++++ b/src/arch/aarch64/sysregs.c +@@ -159,7 +159,7 @@ uintreg_t get_cptr_el2_value(void) + /** + * Returns the value for SCTLR_EL2 for the CPU. + */ +-uintreg_t get_sctlr_el2_value(void) ++uintreg_t get_sctlr_el2_value(bool is_el0_partition) + { + uintreg_t sctlr_el2_value = 0; + +@@ -173,7 +173,14 @@ uintreg_t get_sctlr_el2_value(void) + + /* MMU-related bits. */ + sctlr_el2_value |= SCTLR_EL2_M; +- sctlr_el2_value |= SCTLR_EL2_A; ++ ++ /* ++ * Alignment check enabled, but in the case of an EL0 partition ++ * with VHE enabled. ++ */ ++ if (!(has_vhe_support() && is_el0_partition)) { ++ sctlr_el2_value |= SCTLR_EL2_A; ++ } + sctlr_el2_value |= SCTLR_EL2_C; + sctlr_el2_value |= SCTLR_EL2_SA; + sctlr_el2_value |= SCTLR_EL2_I; +diff --git a/src/arch/aarch64/sysregs.h b/src/arch/aarch64/sysregs.h +index babd2375..6fdab58e 100644 +--- a/src/arch/aarch64/sysregs.h ++++ b/src/arch/aarch64/sysregs.h +@@ -668,7 +668,7 @@ uintreg_t get_mdcr_el2_value(void); + + uintreg_t get_cptr_el2_value(void); + +-uintreg_t get_sctlr_el2_value(void); ++uintreg_t get_sctlr_el2_value(bool is_el0_partition); + + /** + * Branch Target Identification mechanism support in AArch64 state. + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0004-feat-vhe-set-STAGE1_NS-while-mapping-memory-from-NWd.patch b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0004-feat-vhe-set-STAGE1_NS-while-mapping-memory-from-NWd.patch new file mode 100644 index 000000000000..cfa7cfb73d82 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/files/tc/0004-feat-vhe-set-STAGE1_NS-while-mapping-memory-from-NWd.patch @@ -0,0 +1,41 @@ +From 4b59905d2fec01cc17038b1c167b4e57e7835adf Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Thu, 7 Oct 2021 12:20:08 +0530 +Subject: [PATCH] feat(vhe): set STAGE1_NS while mapping memory from NWd to SWd + +If the memory is shared by a VM executing in non secure world, attribute +MM_MODE_NS had to be set while mapping that in a S-EL0 SP executing in +secure world. It will not be needed for a S-EL1 SP since the NS bit is +available only for the stage 1 translations and the stage 1 translations +for a S-EL1 SP will be handled by a trusted OS running in S-EL1. + +Signed-off-by: Davidson K +Change-Id: I074e2d5a50a659bd3c097d797c4901f08d210b1b +Upstream-Status: Pending [Not submitted to upstream yet] +--- + src/ffa_memory.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/ffa_memory.c b/src/ffa_memory.c +index 048cca9c..8910cc79 100644 +--- a/src/ffa_memory.c ++++ b/src/ffa_memory.c +@@ -2483,6 +2483,18 @@ struct ffa_value ffa_memory_retrieve(struct vm_locked to_locked, + + memory_to_attributes = ffa_memory_permissions_to_mode( + permissions, share_state->sender_orig_mode); ++ ++ if (to_locked.vm->el0_partition) { ++ /* ++ * Get extra mapping attributes for the given VM ID. ++ * If the memory is shared by a VM executing in non secure ++ * world, attribute MM_MODE_NS had to be set while mapping ++ * that in a SP executing in secure world. ++ */ ++ memory_to_attributes |= arch_mm_extra_attributes_from_vm( ++ retrieve_request->sender); ++ } ++ + ret = ffa_retrieve_check_update( + to_locked, memory_region->sender, share_state->fragments, + share_state->fragment_constituent_counts, diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc.inc b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc.inc new file mode 100644 index 000000000000..433d56129e15 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc.inc @@ -0,0 +1,25 @@ +# TC specific configuration + +COMPATIBLE_MACHINE = "(tc?)" +HAFNIUM_PLATFORM = "secure_tc" + +# Intermediate SHA with 2.7 baseline version +SRCREV = "dd0561820946fe23bcd57cc129140437f72102a5" +PV = "2.7+git${SRCPV}" + +FILESEXTRAPATHS:prepend:tc := "${THISDIR}/files/tc:" + +SRC_URI:remove = "file://0003-Fix-build-with-clang-15.patch" + +SRC_URI:append = " \ + file://0001-feat-emulate-cntp-timer-register-accesses-using-cnth.patch \ + file://0002-feat-emulate-interrupt-controller-register-access.patch \ + file://0003-feat-disable-alignment-check-for-EL0-partitions.patch \ + file://0004-feat-vhe-set-STAGE1_NS-while-mapping-memory-from-NWd.patch \ + file://0001-tc-increase-heap-pages.patch;patchdir=project/reference \ + file://0002-feat-vhe-enable-vhe-and-disable-branch-protection-fo.patch;patchdir=project/reference \ + " + +do_compile() { + PATH="${S}/prebuilts/linux-x64/clang/bin:$PATH" oe_runmake -C ${S} +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium_%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium_%.bbappend new file mode 100644 index 000000000000..bfc2c464a1a1 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/hafnium/hafnium_%.bbappend @@ -0,0 +1,6 @@ +# Machine specific configurations + +MACHINE_HAFNIUM_REQUIRE ?= "" +MACHINE_HAFNIUM_REQUIRE:tc = "hafnium-tc.inc" + +require ${MACHINE_HAFNIUM_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb new file mode 100644 index 000000000000..76a7126b2916 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb @@ -0,0 +1,32 @@ +SUMARY = "Corstone1000 platform Image" +DESCRIPTION = "This is the main image which is the container of all the binaries \ + generated for the Corstone1000 platform." +LICENSE = "MIT" + +COMPATIBLE_MACHINE = "corstone1000" + +inherit image +inherit wic_nopt tfm_sign_image + +PACKAGE_INSTALL = "" + +IMAGE_FSTYPES += "wic wic.nopt" + +do_sign_images() { + # Sign TF-A BL2 + sign_host_image ${RECIPE_SYSROOT}/firmware/${TFA_BL2_BINARY} \ + ${TFA_BL2_RE_IMAGE_LOAD_ADDRESS} ${TFA_BL2_RE_SIGN_BIN_SIZE} + + # Update BL2 in the FIP image + cp ${RECIPE_SYSROOT}/firmware/${TFA_FIP_BINARY} . + fiptool update --tb-fw ${TFM_IMAGE_SIGN_DIR}/signed_${TFA_BL2_BINARY} \ + ${TFM_IMAGE_SIGN_DIR}/${TFA_FIP_BINARY} + + # Sign the FIP image + sign_host_image ${TFM_IMAGE_SIGN_DIR}/${TFA_FIP_BINARY} \ + ${TFA_FIP_RE_IMAGE_LOAD_ADDRESS} ${TFA_FIP_RE_SIGN_BIN_SIZE} +} +do_sign_images[depends] = "\ + trusted-firmware-a:do_populate_sysroot \ + fiptool-native:do_populate_sysroot \ + " diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-initramfs-image.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-initramfs-image.bb new file mode 100644 index 000000000000..46427b749e35 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-initramfs-image.bb @@ -0,0 +1,30 @@ +SUMARY = "Corstone1000 platform Initramfs Image" +DESCRIPTION = "This is the main Linux image which includes an initramfs kernel/rootfs bundle." + +LICENSE = "MIT" + +COMPATIBLE_MACHINE = "corstone1000" + +IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}" + +inherit core-image + +# By default all basic packages required for a bootable system are installed +# by core-image . These packages are: packagegroup-core-boot and +# packagegroup-base-extended + +inherit image-buildinfo + +IMAGE_FEATURES += "debug-tweaks" + +#package management is not supported in corstone1000 +IMAGE_FEATURES:remove = "package-management" + +# all optee packages +IMAGE_INSTALL += "optee-client" + +# external system linux userspace test application +IMAGE_INSTALL += "corstone1000-external-sys-tests" + +# TS PSA API tests commands for crypto, its, ps and iat +IMAGE_INSTALL += "packagegroup-ts-tests-psa" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno.bb new file mode 100644 index 000000000000..45f2ec726ada --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno.bb @@ -0,0 +1,79 @@ +DESCRIPTION = "Firmware Image for Juno to be copied to the Configuration \ +microSD card" + +LICENSE = "BSD-3-Clause" +SECTION = "firmware" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9" + +INHIBIT_DEFAULT_DEPS = "1" +DEPENDS = "trusted-firmware-a virtual/kernel virtual/control-processor-firmware" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +COMPATIBLE_MACHINE = "juno" + +LINARO_RELEASE = "19.06" + +SRC_URI = "http://releases.linaro.org/members/arm/platforms/${LINARO_RELEASE}/juno-latest-oe-uboot.zip;subdir=${UNPACK_DIR} \ + file://images-r0.txt \ + file://images-r1.txt \ + file://images-r2.txt \ + file://uEnv.txt \ +" +SRC_URI[md5sum] = "01b662b81fa409d55ff298238ad24003" +SRC_URI[sha256sum] = "b8a3909bb3bc4350a8771b863193a3e33b358e2a727624a77c9ecf13516cec82" + +UNPACK_DIR = "juno-firmware-${LINARO_RELEASE}" + +inherit deploy nopackages + +do_configure[noexec] = "1" +do_compile[noexec] = "1" + +# The ${D} is used as a temporary directory and we don't generate any +# packages for this recipe. +do_install() { + cp -a ${WORKDIR}/${UNPACK_DIR} ${D} + cp -f ${RECIPE_SYSROOT}/firmware/bl1-juno.bin \ + ${D}/${UNPACK_DIR}/SOFTWARE/bl1.bin + + cp -f ${RECIPE_SYSROOT}/firmware/fip-juno.bin \ + ${D}/${UNPACK_DIR}/SOFTWARE/fip.bin + + cp -f ${RECIPE_SYSROOT}/firmware/scp_romfw_bypass.bin \ + ${D}/${UNPACK_DIR}/SOFTWARE/scp_bl1.bin + + # u-boot environment file + cp -f ${WORKDIR}/uEnv.txt ${D}/${UNPACK_DIR}/SOFTWARE/ + + # Juno images list file + cp -f ${WORKDIR}/images-r0.txt ${D}/${UNPACK_DIR}/SITE1/HBI0262B/images.txt + cp -f ${WORKDIR}/images-r1.txt ${D}/${UNPACK_DIR}/SITE1/HBI0262C/images.txt + cp -f ${WORKDIR}/images-r2.txt ${D}/${UNPACK_DIR}/SITE1/HBI0262D/images.txt +} + +do_deploy() { + # To avoid dependency loop between firmware-image-juno:do_install + # and virtual/kernel:do_deploy when INITRAMFS_IMAGE_BUNDLE = "1", + # we need to handle the kernel binaries copying in the do_deploy + # task. + for f in ${KERNEL_DEVICETREE}; do + install -m 755 -c ${DEPLOY_DIR_IMAGE}/$(basename $f) \ + ${D}/${UNPACK_DIR}/SOFTWARE/. + done + + if [ "${INITRAMFS_IMAGE_BUNDLE}" -eq 1 ]; then + cp -L -f ${DEPLOY_DIR_IMAGE}/Image.gz-initramfs-juno.bin \ + ${D}/${UNPACK_DIR}/SOFTWARE/Image + else + cp -L -f ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE} ${D}/${UNPACK_DIR}/SOFTWARE/ + fi + + # Compress the files + tar -C ${D}/${UNPACK_DIR} -zcvf ${WORKDIR}/${PN}.tar.gz ./ + + # Deploy the compressed archive to the deploy folder + install -D -p -m0644 ${WORKDIR}/${PN}.tar.gz ${DEPLOYDIR}/${PN}.tar.gz +} +do_deploy[depends] += "virtual/kernel:do_deploy" +addtask deploy after do_install diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r0.txt b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r0.txt new file mode 100644 index 000000000000..3b36ed13497d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r0.txt @@ -0,0 +1,71 @@ +TITLE: Versatile Express Images Configuration File + +[IMAGES] +TOTALIMAGES: 10 ;Number of Images (Max: 32) + +NOR0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR0ADDRESS: 0x00000000 ;Image Flash Address +NOR0FILE: \SOFTWARE\fip.bin ;Image File Name +NOR0LOAD: 00000000 ;Image Load Address +NOR0ENTRY: 00000000 ;Image Entry Point + +NOR1UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR1ADDRESS: 0x03EC0000 ;Image Flash Address +NOR1FILE: \SOFTWARE\bl1.bin ;Image File Name +NOR1LOAD: 00000000 ;Image Load Address +NOR1ENTRY: 00000000 ;Image Entry Point + +NOR2UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR2ADDRESS: 0x00500000 ;Image Flash Address +NOR2FILE: \SOFTWARE\Image ;Image File Name +NOR2NAME: norkern ;Rename kernel to norkern +NOR2LOAD: 00000000 ;Image Load Address +NOR2ENTRY: 00000000 ;Image Entry Point + +NOR3UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR3ADDRESS: 0x03000000 ;Image Flash Address +NOR3FILE: \SOFTWARE\juno.dtb ;Image File Name +NOR3NAME: board.dtb ;Specify target filename to preserve file extension +NOR3LOAD: 00000000 ;Image Load Address +NOR3ENTRY: 00000000 ;Image Entry Point + +NOR4UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR4ADDRESS: 0x030C0000 ;Image Flash Address +NOR4FILE: \SOFTWARE\hdlcdclk.dat ;Image File Name +NOR4LOAD: 00000000 ;Image Load Address +NOR4ENTRY: 00000000 ;Image Entry Point + +NOR5UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR5ADDRESS: 0x03E40000 ;Image Flash Address +NOR5FILE: \SOFTWARE\scp_bl1.bin ;Image File Name +NOR5LOAD: 00000000 ;Image Load Address +NOR5ENTRY: 00000000 ;Image Entry Point + +NOR6UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR6ADDRESS: 0x0BF00000 ;Image Flash Address +NOR6FILE: \SOFTWARE\startup.nsh ;Image File Name +NOR6NAME: startup.nsh +NOR6LOAD: 00000000 ;Image Load Address +NOR6ENTRY: 00000000 ;Image Entry Point + +NOR7UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR7ADDRESS: 0x0BFC0000 ;Image Flash Address +NOR7FILE: \SOFTWARE\blank.img ;Image File Name +NOR7NAME: BOOTENV +NOR7LOAD: 00000000 ;Image Load Address +NOR7ENTRY: 00000000 ;Image Entry Point + +NOR8UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR8ADDRESS: 0x03100000 ;Image Flash Address +NOR8FILE: \SOFTWARE\selftest ;Image File Name +NOR8LOAD: 00000000 ;Image Load Address +NOR8ENTRY: 00000000 ;Image Entry Point + +NOR9UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR9ADDRESS: 0x03180000 ;Image Flash Address +NOR9NAME: uEnv.txt +NOR9FILE: \SOFTWARE\uEnv.txt ;Image File Name +NOR9LOAD: 00000000 ;Image Load Address +NOR9ENTRY: 00000000 ;Image Entry Point + + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r1.txt b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r1.txt new file mode 100644 index 000000000000..5db13affaf44 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r1.txt @@ -0,0 +1,71 @@ +TITLE: Versatile Express Images Configuration File + +[IMAGES] +TOTALIMAGES: 10 ;Number of Images (Max: 32) + +NOR0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR0ADDRESS: 0x00000000 ;Image Flash Address +NOR0FILE: \SOFTWARE\fip.bin ;Image File Name +NOR0LOAD: 00000000 ;Image Load Address +NOR0ENTRY: 00000000 ;Image Entry Point + +NOR1UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR1ADDRESS: 0x03EC0000 ;Image Flash Address +NOR1FILE: \SOFTWARE\bl1.bin ;Image File Name +NOR1LOAD: 00000000 ;Image Load Address +NOR1ENTRY: 00000000 ;Image Entry Point + +NOR2UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR2ADDRESS: 0x00500000 ;Image Flash Address +NOR2FILE: \SOFTWARE\Image ;Image File Name +NOR2NAME: norkern ;Rename kernel to norkern +NOR2LOAD: 00000000 ;Image Load Address +NOR2ENTRY: 00000000 ;Image Entry Point + +NOR3UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR3ADDRESS: 0x03000000 ;Image Flash Address +NOR3FILE: \SOFTWARE\juno-r1.dtb ;Image File Name +NOR3NAME: board.dtb ;Specify target filename to preserve file extension +NOR3LOAD: 00000000 ;Image Load Address +NOR3ENTRY: 00000000 ;Image Entry Point + +NOR4UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR4ADDRESS: 0x030C0000 ;Image Flash Address +NOR4FILE: \SOFTWARE\hdlcdclk.dat ;Image File Name +NOR4LOAD: 00000000 ;Image Load Address +NOR4ENTRY: 00000000 ;Image Entry Point + +NOR5UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR5ADDRESS: 0x03E40000 ;Image Flash Address +NOR5FILE: \SOFTWARE\scp_bl1.bin ;Image File Name +NOR5LOAD: 00000000 ;Image Load Address +NOR5ENTRY: 00000000 ;Image Entry Point + +NOR6UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR6ADDRESS: 0x0BF00000 ;Image Flash Address +NOR6FILE: \SOFTWARE\startup.nsh ;Image File Name +NOR6NAME: startup.nsh +NOR6LOAD: 00000000 ;Image Load Address +NOR6ENTRY: 00000000 ;Image Entry Point + +NOR7UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR7ADDRESS: 0x0BFC0000 ;Image Flash Address +NOR7FILE: \SOFTWARE\blank.img ;Image File Name +NOR7NAME: BOOTENV +NOR7LOAD: 00000000 ;Image Load Address +NOR7ENTRY: 00000000 ;Image Entry Point + +NOR8UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR8ADDRESS: 0x03100000 ;Image Flash Address +NOR8FILE: \SOFTWARE\selftest ;Image File Name +NOR8LOAD: 00000000 ;Image Load Address +NOR8ENTRY: 00000000 ;Image Entry Point + +NOR9UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR9ADDRESS: 0x03180000 ;Image Flash Address +NOR9NAME: uEnv.txt +NOR9FILE: \SOFTWARE\uEnv.txt ;Image File Name +NOR9LOAD: 00000000 ;Image Load Address +NOR9ENTRY: 00000000 ;Image Entry Point + + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r2.txt b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r2.txt new file mode 100644 index 000000000000..7c499bfbda23 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/images-r2.txt @@ -0,0 +1,71 @@ +TITLE: Versatile Express Images Configuration File + +[IMAGES] +TOTALIMAGES: 10 ;Number of Images (Max: 32) + +NOR0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR0ADDRESS: 0x00000000 ;Image Flash Address +NOR0FILE: \SOFTWARE\fip.bin ;Image File Name +NOR0LOAD: 00000000 ;Image Load Address +NOR0ENTRY: 00000000 ;Image Entry Point + +NOR1UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR1ADDRESS: 0x03EC0000 ;Image Flash Address +NOR1FILE: \SOFTWARE\bl1.bin ;Image File Name +NOR1LOAD: 00000000 ;Image Load Address +NOR1ENTRY: 00000000 ;Image Entry Point + +NOR2UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR2ADDRESS: 0x00500000 ;Image Flash Address +NOR2FILE: \SOFTWARE\Image ;Image File Name +NOR2NAME: norkern ;Rename kernel to norkern +NOR2LOAD: 00000000 ;Image Load Address +NOR2ENTRY: 00000000 ;Image Entry Point + +NOR3UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR3ADDRESS: 0x03000000 ;Image Flash Address +NOR3FILE: \SOFTWARE\juno-r2.dtb ;Image File Name +NOR3NAME: board.dtb ;Specify target filename to preserve file extension +NOR3LOAD: 00000000 ;Image Load Address +NOR3ENTRY: 00000000 ;Image Entry Point + +NOR4UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR4ADDRESS: 0x030C0000 ;Image Flash Address +NOR4FILE: \SOFTWARE\hdlcdclk.dat ;Image File Name +NOR4LOAD: 00000000 ;Image Load Address +NOR4ENTRY: 00000000 ;Image Entry Point + +NOR5UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR5ADDRESS: 0x03E40000 ;Image Flash Address +NOR5FILE: \SOFTWARE\scp_bl1.bin ;Image File Name +NOR5LOAD: 00000000 ;Image Load Address +NOR5ENTRY: 00000000 ;Image Entry Point + +NOR6UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR6ADDRESS: 0x0BF00000 ;Image Flash Address +NOR6FILE: \SOFTWARE\startup.nsh ;Image File Name +NOR6NAME: startup.nsh +NOR6LOAD: 00000000 ;Image Load Address +NOR6ENTRY: 00000000 ;Image Entry Point + +NOR7UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR7ADDRESS: 0x0BFC0000 ;Image Flash Address +NOR7FILE: \SOFTWARE\blank.img ;Image File Name +NOR7NAME: BOOTENV +NOR7LOAD: 00000000 ;Image Load Address +NOR7ENTRY: 00000000 ;Image Entry Point + +NOR8UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR8ADDRESS: 0x03100000 ;Image Flash Address +NOR8FILE: \SOFTWARE\selftest ;Image File Name +NOR8LOAD: 00000000 ;Image Load Address +NOR8ENTRY: 00000000 ;Image Entry Point + +NOR9UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE +NOR9ADDRESS: 0x03180000 ;Image Flash Address +NOR9NAME: uEnv.txt +NOR9FILE: \SOFTWARE\uEnv.txt ;Image File Name +NOR9LOAD: 00000000 ;Image Load Address +NOR9ENTRY: 00000000 ;Image Entry Point + + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/uEnv.txt b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/uEnv.txt new file mode 100644 index 000000000000..77c02e3677c0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/firmware-image-juno/uEnv.txt @@ -0,0 +1,11 @@ +uenvcmd=run mybootcmd +mybootcmd=echo Loading custom boot command; \ +echo Loading kernel; \ +afs load ${kernel_name} ${kernel_addr_r} ; \ +if test $? -eq 1; then echo Loading ${kernel_alt_name} instead of ${kernel_name}; afs load ${kernel_alt_name} ${kernel_addr_r}; fi; \ +echo Loading device tree; \ +afs load ${fdtfile} ${fdt_addr_r}; \ +if test $? -eq 1; then echo Loading ${fdt_alt_name} instead of ${fdtfile}; \ +afs load ${fdt_alt_name} ${fdt_addr_r}; fi; fdt addr ${fdt_addr_r}; fdt resize; \ +booti ${kernel_addr_r} - ${fdt_addr_r}; + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/n1sdp-board-firmware_2022.06.22.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/n1sdp-board-firmware_2022.06.22.bb new file mode 100644 index 000000000000..ef7a4fca0b45 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/n1sdp-board-firmware_2022.06.22.bb @@ -0,0 +1,36 @@ +SUMMARY = "Board Firmware binaries for N1SDP" +SECTION = "firmware" + +LICENSE = "STM-SLA0044-Rev5" +LIC_FILES_CHKSUM = "file://LICENSES/MB/STM.TXT;md5=1b74d8c842307d03c116f2d71cbf868a" + +inherit deploy + +INHIBIT_DEFAULT_DEPS = "1" + +PACKAGE_ARCH = "${MACHINE_ARCH}" +COMPATIBLE_MACHINE = "n1sdp" + +SRC_URI = "git://git.gitlab.arm.com/arm-reference-solutions/board-firmware.git;protocol=https;branch=n1sdp" + +SRCREV = "6d5253584a9c2fdc2edbdc39bf6f2436215d1382" + +S = "${WORKDIR}/git" + +INSTALL_DIR = "/n1sdp-board-firmware_source" + +do_install() { + rm -rf ${S}/SOFTWARE + install -d ${D}${INSTALL_DIR} + cp -Rp --no-preserve=ownership ${S}/* ${D}${INSTALL_DIR} +} + +FILES:${PN}-staticdev += " ${INSTALL_DIR}/LIB/sensor.a" +FILES:${PN} = "${INSTALL_DIR}" +SYSROOT_DIRS += "${INSTALL_DIR}" + +do_deploy() { + install -d ${DEPLOYDIR}${INSTALL_DIR} + cp -Rp --no-preserve=ownership ${S}/* ${DEPLOYDIR}${INSTALL_DIR} +} +addtask deploy after do_install before do_build diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/sdcard-image-n1sdp_0.1.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/sdcard-image-n1sdp_0.1.bb new file mode 100644 index 000000000000..3ed71c57d247 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/sdcard-image-n1sdp_0.1.bb @@ -0,0 +1,85 @@ +SUMMARY = "Firmware image recipe for generating SD-Card artifacts." + +inherit deploy nopackages + +DEPENDS = "trusted-firmware-a \ + virtual/control-processor-firmware \ + n1sdp-board-firmware" + +LICENSE = "MIT" +PACKAGE_ARCH = "${MACHINE_ARCH}" +COMPATIBLE_MACHINE = "n1sdp" +RM_WORK_EXCLUDE += "${PN}" +do_configure[noexec] = "1" +do_compile[noexec] = "1" +do_install[noexec] = "1" + +FIRMWARE_DIR = "n1sdp-board-firmware_source" +PRIMARY_DIR = "${WORKDIR}/n1sdp-board-firmware_primary" +SECONDARY_DIR = "${WORKDIR}/n1sdp-board-firmware_secondary" + +SOC_BINARIES = "mcp_fw.bin scp_fw.bin mcp_rom.bin scp_rom.bin" + +prepare_package() { + cd ${WORKDIR} + + # Master/Primary + cp -av ${RECIPE_SYSROOT}/${FIRMWARE_DIR}/* ${PRIMARY_DIR} + mkdir -p ${PRIMARY_DIR}/SOFTWARE/ + + # Copy FIP binary + cp -v ${RECIPE_SYSROOT}/firmware/fip.bin ${PRIMARY_DIR}/SOFTWARE/ + + # Copy SOC binaries + for f in ${SOC_BINARIES}; do + cp -v ${RECIPE_SYSROOT}/firmware/${f} ${PRIMARY_DIR}/SOFTWARE/ + done + + sed -i -e 's|^C2C_ENABLE.*|C2C_ENABLE: TRUE ;C2C enable TRUE/FALSE|' \ + ${PRIMARY_DIR}/MB/HBI0316A/io_v123f.txt + sed -i -e 's|^C2C_SIDE.*|C2C_SIDE: MASTER ;C2C side SLAVE/MASTER|' \ + ${PRIMARY_DIR}/MB/HBI0316A/io_v123f.txt + sed -i -e 's|.*SOCCON: 0x1170.*PLATFORM_CTRL.*|SOCCON: 0x1170 0x00000100 ;SoC SCC PLATFORM_CTRL|' \ + ${PRIMARY_DIR}/MB/HBI0316A/io_v123f.txt + + # Update load address for trusted boot + sed -i -e '/^IMAGE4ADDRESS:/ s|0x60200000|0x64200000|' ${PRIMARY_DIR}/MB/HBI0316A/images.txt + sed -i -e '/^IMAGE4UPDATE:/ s|FORCE |SCP_AUTO|' ${PRIMARY_DIR}/MB/HBI0316A/images.txt + sed -i -e '/^IMAGE4FILE: \\SOFTWARE\\/s|uefi.bin|fip.bin |' ${PRIMARY_DIR}/MB/HBI0316A/images.txt + + # Slave/Secondary + cp -av ${RECIPE_SYSROOT}/${FIRMWARE_DIR}/* ${SECONDARY_DIR} + mkdir -p ${SECONDARY_DIR}/SOFTWARE/ + + # Copy SOC binaries + for f in ${SOC_BINARIES}; do + cp -v ${RECIPE_SYSROOT}/firmware/${f} ${SECONDARY_DIR}/SOFTWARE/ + done + + sed -i -e 's|^C2C_ENABLE.*|C2C_ENABLE: TRUE ;C2C enable TRUE/FALSE|' \ + ${SECONDARY_DIR}/MB/HBI0316A/io_v123f.txt + sed -i -e 's|^C2C_SIDE.*|C2C_SIDE: SLAVE ;C2C side SLAVE/MASTER|' \ + ${SECONDARY_DIR}/MB/HBI0316A/io_v123f.txt + sed -i -e 's|.*SOCCON: 0x1170.*PLATFORM_CTRL.*|SOCCON: 0x1170 0x00000101 ;SoC SCC PLATFORM_CTRL|' \ + ${SECONDARY_DIR}/MB/HBI0316A/io_v123f.txt + sed -i -e '/^TOTALIMAGES:/ s|5|4|' ${SECONDARY_DIR}/MB/HBI0316A/images.txt + sed -i -e 's|^IMAGE4|;&|' ${SECONDARY_DIR}/MB/HBI0316A/images.txt +} + +do_deploy() { + # prepare Master & Slave packages + prepare_package + + for dir in ${PRIMARY_DIR} ${SECONDARY_DIR}; do + dir_name=$(basename ${dir}) + mkdir -p ${D}/${dir_name} + cp -av ${dir} ${D} + + # Compress the files + tar -C ${D}/${dir_name} -zcvf ${DEPLOYDIR}/${dir_name}.tar.gz ./ + done +} +do_deploy[dirs] += "${PRIMARY_DIR} ${SECONDARY_DIR}" +do_deploy[cleandirs] += "${PRIMARY_DIR} ${SECONDARY_DIR}" +do_deploy[umask] = "022" +addtask deploy after do_prepare_recipe_sysroot diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/tc-artifacts-image.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/tc-artifacts-image.bb new file mode 100644 index 000000000000..ded7404b57ad --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/tc-artifacts-image.bb @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2020 Arm Limited +# +SUMMARY = "Total Compute Images" +DESCRIPTION = "Build all the images required for Total Compute platform" +LICENSE = "Apache-2.0" + +COMPATIBLE_MACHINE = "(tc?)" + +inherit nopackages + +# The last image to be built is trusted-firmware-a +DEPENDS += " trusted-firmware-a" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-juno.inc b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-juno.inc new file mode 100644 index 000000000000..ea2faceb4aec --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-juno.inc @@ -0,0 +1,16 @@ +# juno specific SCP configuration + +COMPATIBLE_MACHINE = "juno" + +SCP_PLATFORM = "juno" +FW_TARGETS = "scp" +FW_INSTALL:append = " romfw_bypass" + +do_install:append() { + for TYPE in ${FW_INSTALL}; do + if [ "$TYPE" = "romfw_bypass" ]; then + install -D "${B}/${TYPE}/${FW_TARGETS}/bin/${SCP_PLATFORM}-bl1-bypass.bin" "${D}/firmware/${FW}_${TYPE}.bin" + install -D "${B}/${TYPE}/${FW_TARGETS}/bin/${SCP_PLATFORM}-bl1-bypass" "${D}/firmware/${FW}_${TYPE}.elf" + fi + done +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-n1sdp.inc b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-n1sdp.inc new file mode 100644 index 000000000000..85f89a011637 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-n1sdp.inc @@ -0,0 +1,39 @@ +# N1SDP specific SCP configurations and build instructions + +SCP_PLATFORM = "n1sdp" +SCP_LOG_LEVEL = "INFO" + +SRCREV = "de7e464ecd77130147103cf48328099c2d0e6289" +PV .= "+git${SRCPV}" + +COMPATIBLE_MACHINE:n1sdp = "n1sdp" + +DEPENDS += "fiptool-native" +DEPENDS += "trusted-firmware-a" +DEPENDS += "n1sdp-board-firmware" + +# The n1sdp sensor library is needed for building SCP N1SDP Platform +# https://github.com/ARM-software/SCP-firmware/tree/master/product/n1sdp +EXTRA_OECMAKE:append = " \ + -DSCP_N1SDP_SENSOR_LIB_PATH=${RECIPE_SYSROOT}/n1sdp-board-firmware_source/LIB/sensor.a \ +" + +do_install:append() { + fiptool \ + create \ + --scp-fw "${D}/firmware/scp_ramfw.bin" \ + --blob uuid=cfacc2c4-15e8-4668-82be-430a38fad705,file="${RECIPE_SYSROOT}/firmware/bl1.bin" \ + "scp_fw.bin" + + # This UUID is FIP_UUID_MCP_BL2 in SCP-Firmware. + fiptool \ + create \ + --blob uuid=54464222-a4cf-4bf8-b1b6-cee7dade539e,file="${D}/firmware/mcp_ramfw.bin" \ + "mcp_fw.bin" + + install "scp_fw.bin" "${D}/firmware/scp_fw.bin" + install "mcp_fw.bin" "${D}/firmware/mcp_fw.bin" + + ln -sf "scp_romfw.bin" "${D}/firmware/scp_rom.bin" + ln -sf "mcp_romfw.bin" "${D}/firmware/mcp_rom.bin" +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-sgi575.inc b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-sgi575.inc new file mode 100644 index 000000000000..e1b0a854af6c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-sgi575.inc @@ -0,0 +1,6 @@ +# SGI575 specific SCP configurations and build instructions + +SCP_PLATFORM = "sgi575" +SCP_LOG_LEVEL = "INFO" + +COMPATIBLE_MACHINE:sgi575 = "sgi575" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc.inc b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc.inc new file mode 100644 index 000000000000..3cbadad88d3f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc.inc @@ -0,0 +1,6 @@ +# TC specific SCP configuration + +COMPATIBLE_MACHINE = "(tc1)" + +SCP_PLATFORM:tc1 = "tc1" +FW_TARGETS = "scp" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware_2.10.%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware_2.10.%.bbappend new file mode 100644 index 000000000000..bb1a48c76a06 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware_2.10.%.bbappend @@ -0,0 +1,10 @@ +# Include machine specific SCP configurations + +MACHINE_SCP_REQUIRE ?= "" + +MACHINE_SCP_REQUIRE:juno = "scp-firmware-juno.inc" +MACHINE_SCP_REQUIRE:n1sdp = "scp-firmware-n1sdp.inc" +MACHINE_SCP_REQUIRE:sgi575 = "scp-firmware-sgi575.inc" +MACHINE_SCP_REQUIRE:tc = "scp-firmware-tc.inc" + +require ${MACHINE_SCP_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0001-Fix-FF-A-version-in-SPMC-manifest.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0001-Fix-FF-A-version-in-SPMC-manifest.patch new file mode 100644 index 000000000000..016de8d3de77 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0001-Fix-FF-A-version-in-SPMC-manifest.patch @@ -0,0 +1,34 @@ +Upstream-Status: Inappropriate +Signed-off-by: Emekcan Aras + +From a31aee0988ef64724ec5866f10709f51f8cb3237 Mon Sep 17 00:00:00 2001 +From: emeara01 +Date: Wed, 11 May 2022 14:37:06 +0100 +Subject: [PATCH] Fix FF-A version in SPMC manifest + +OPTEE does not support FF-A version 1.1 in SPMC at the moment. +This commit corrects the FF-A version in corstone1000_spmc_manifest.dts. +This patch will not be upstreamed and will be dropped once +OPTEE version is updated for Corstone1000. + +Signed-off-by: Emekcan Aras +--- + .../corstone1000/common/fdts/corstone1000_spmc_manifest.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +index 8e49ab83f..5baa1b115 100644 +--- a/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts ++++ b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +@@ -20,7 +20,7 @@ + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; +- min_ver = <0x1>; ++ min_ver = <0x0>; + exec_state = <0x0>; + load_address = <0x0 0x2002000>; + entrypoint = <0x0 0x2002000>; +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0001-plat-tc-Increase-maximum-BL2-size.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0001-plat-tc-Increase-maximum-BL2-size.patch new file mode 100644 index 000000000000..74ab3612c1b0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0001-plat-tc-Increase-maximum-BL2-size.patch @@ -0,0 +1,43 @@ +From 008cfc6457c239466ca62610d59aaf1a78f6b2f6 Mon Sep 17 00:00:00 2001 +From: Tudor Cretu +Date: Fri, 21 May 2021 14:56:37 +0000 +Subject: [PATCH 1/7] plat: tc: Increase maximum BL2 size. + +BL2 size gets increased due to the firmware update changes. +Increase the MAX_BL2_SIZE by 8Kb. + +Signed-off-by: Tudor Cretu +Change-Id: I1cb28b0eb7f834426873ff9f4c40bd496413806f +Upstream-Status: Pending [Not submitted to upstream yet] +--- + plat/arm/board/tc/include/platform_def.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h +index 745d91cab..cd77773aa 100644 +--- a/plat/arm/board/tc/include/platform_def.h ++++ b/plat/arm/board/tc/include/platform_def.h +@@ -120,9 +120,9 @@ + * little space for growth. + */ + #if TRUSTED_BOARD_BOOT +-# define PLAT_ARM_MAX_BL2_SIZE 0x20000 ++# define PLAT_ARM_MAX_BL2_SIZE 0x25000 + #else +-# define PLAT_ARM_MAX_BL2_SIZE 0x14000 ++# define PLAT_ARM_MAX_BL2_SIZE 0x19000 + #endif + + /* +@@ -130,7 +130,7 @@ + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +-#define PLAT_ARM_MAX_BL31_SIZE 0x3F000 ++#define PLAT_ARM_MAX_BL31_SIZE 0x4F000 + + /* + * Size of cacheable stacks +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0002-Makefile-add-trusty_sp_fw_config-build-option.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0002-Makefile-add-trusty_sp_fw_config-build-option.patch new file mode 100644 index 000000000000..75cabdd8d1e0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0002-Makefile-add-trusty_sp_fw_config-build-option.patch @@ -0,0 +1,46 @@ +From 2f8b0cc6be3787717247d1c02a45181a5ac6f125 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Mon, 11 Apr 2022 14:36:54 +0100 +Subject: [PATCH 2/7] Makefile: add trusty_sp_fw_config build option + +Signed-off-by: Arunachalam Ganapathy +Change-Id: Ief90ae9113d32265ee2200f35f3e517b7b9a4bea +Upstream-Status: Pending [Not submitted to upstream yet] +--- + Makefile | 4 ++++ + docs/plat/arm/arm-build-options.rst | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/Makefile b/Makefile +index 3941f8698..a20d647a2 100644 +--- a/Makefile ++++ b/Makefile +@@ -531,6 +531,10 @@ ifneq (${SPD},none) + DTC_CPPFLAGS += -DOPTEE_SP_FW_CONFIG + endif + ++ ifeq ($(findstring trusty_sp,$(ARM_SPMC_MANIFEST_DTS)),trusty_sp) ++ DTC_CPPFLAGS += -DTRUSTY_SP_FW_CONFIG ++ endif ++ + ifeq ($(TS_SP_FW_CONFIG),1) + DTC_CPPFLAGS += -DTS_SP_FW_CONFIG + endif +diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst +index 339ebbe33..3c9a41fb8 100644 +--- a/docs/plat/arm/arm-build-options.rst ++++ b/docs/plat/arm/arm-build-options.rst +@@ -107,6 +107,10 @@ Arm Platform Build Options + device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest + file name contains pattern optee_sp. + ++- ``TRUSTY_SP_FW_CONFIG``: DTC build flag to include Trusty as SP in ++ tb_fw_config device tree. This flag is defined only when ++ ``ARM_SPMC_MANIFEST_DTS`` manifest file name contains pattern trusty_sp. ++ + - ``TS_SP_FW_CONFIG``: DTC build flag to include Trusted Services (Crypto and + internal-trusted-storage) as SP in tb_fw_config device tree. + +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0003-fix-plat-arm-increase-sp-max-image-size.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0003-fix-plat-arm-increase-sp-max-image-size.patch new file mode 100644 index 000000000000..6807191e6c5c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0003-fix-plat-arm-increase-sp-max-image-size.patch @@ -0,0 +1,30 @@ +From 0060b1a4fbe3bc9992f59a2d4cb986821f7bcf13 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Mon, 11 Apr 2022 18:31:01 +0100 +Subject: [PATCH 3/7] fix(plat/arm): increase sp max image size + +Increase ARM_SP_MAX_SIZE to support Trusty image. + +Signed-off-by: Arunachalam Ganapathy +Change-Id: I9ef9e755769445aee998062a7fba508fad50b33e +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/plat/arm/common/fconf_arm_sp_getter.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h +index aa628dfd3..3ed953d1c 100644 +--- a/include/plat/arm/common/fconf_arm_sp_getter.h ++++ b/include/plat/arm/common/fconf_arm_sp_getter.h +@@ -13,7 +13,7 @@ + /* arm_sp getter */ + #define arm__sp_getter(prop) arm_sp.prop + +-#define ARM_SP_MAX_SIZE U(0xb0000) ++#define ARM_SP_MAX_SIZE U(0x2000000) + #define ARM_SP_OWNER_NAME_LEN U(8) + + struct arm_sp_t { +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0004-fix-plat-tc-increase-tc_tzc_dram1_size.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0004-fix-plat-tc-increase-tc_tzc_dram1_size.patch new file mode 100644 index 000000000000..aec8be0c60d5 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0004-fix-plat-tc-increase-tc_tzc_dram1_size.patch @@ -0,0 +1,69 @@ +From 000e19d360a5ad9abd7d823af86a364bac2afc58 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Mon, 11 Apr 2022 17:38:17 +0100 +Subject: [PATCH 4/7] fix(plat/tc): increase tc_tzc_dram1_size + +Increase TC_TZC_DRAM1_SIZE for Trusty image and its memory size. +Update OP-TEE reserved memory range in DTS + +Signed-off-by: Arunachalam Ganapathy +Change-Id: Iad433c3c155f28860b15bde2398df653487189dd +Upstream-Status: Pending [Not submitted to upstream yet] +--- + fdts/tc.dts | 4 ++-- + plat/arm/board/tc/include/platform_def.h | 10 ++++++---- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fdts/tc.dts b/fdts/tc.dts +index 20992294b..af64504a4 100644 +--- a/fdts/tc.dts ++++ b/fdts/tc.dts +@@ -213,8 +213,8 @@ + linux,cma-default; + }; + +- optee@0xfce00000 { +- reg = <0x00000000 0xfce00000 0 0x00200000>; ++ optee@0xf8e00000 { ++ reg = <0x00000000 0xf8e00000 0 0x00200000>; + no-map; + }; + }; +diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h +index cd77773aa..35d8fd24e 100644 +--- a/plat/arm/board/tc/include/platform_def.h ++++ b/plat/arm/board/tc/include/platform_def.h +@@ -31,7 +31,7 @@ + */ + #define TC_TZC_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \ + TC_TZC_DRAM1_SIZE) +-#define TC_TZC_DRAM1_SIZE UL(0x02000000) /* 32 MB */ ++#define TC_TZC_DRAM1_SIZE UL(0x06000000) /* 96 MB */ + #define TC_TZC_DRAM1_END (TC_TZC_DRAM1_BASE + \ + TC_TZC_DRAM1_SIZE - 1) + +@@ -68,7 +68,9 @@ + * max size of BL32 image. + */ + #if defined(SPD_spmd) +-#define PLAT_ARM_SPMC_BASE TC_TZC_DRAM1_BASE ++#define TC_EL2SPMC_LOAD_ADDR (TC_TZC_DRAM1_BASE + 0x04000000) ++ ++#define PLAT_ARM_SPMC_BASE TC_EL2SPMC_LOAD_ADDR + #define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */ + #endif + +@@ -259,8 +261,8 @@ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT)) + + /* +- * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to +- * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as ++ * The first region below, TC_TZC_DRAM1_BASE (0xf9000000) to ++ * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 112 MB of DRAM as + * secure. The second and third regions gives non secure access to rest of DRAM. + */ + #define TC_TZC_REGIONS_DEF \ +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0005-feat-plat-tc-add-spmc-manifest-with-trusty-sp.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0005-feat-plat-tc-add-spmc-manifest-with-trusty-sp.patch new file mode 100644 index 000000000000..0b34683ee265 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0005-feat-plat-tc-add-spmc-manifest-with-trusty-sp.patch @@ -0,0 +1,169 @@ +From a04466ceb81a04c5179e8064837c34a89c2b11bd Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Mon, 11 Apr 2022 14:43:15 +0100 +Subject: [PATCH 5/7] feat(plat/tc): add spmc manifest with trusty sp + +Add SPMC manifest with Trusty SP. Define Trusty's load address, +vcpu count, memory size. + +Signed-off-by: Arunachalam Ganapathy +Change-Id: If4363580a478776d233f7f391a30e1cb345453c2 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + .../tc/fdts/tc_spmc_trusty_sp_manifest.dts | 120 ++++++++++++++++++ + plat/arm/board/tc/fdts/tc_tb_fw_config.dts | 7 +- + 2 files changed, 126 insertions(+), 1 deletion(-) + create mode 100644 plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts + +diff --git a/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts +new file mode 100644 +index 000000000..e2ea7b811 +--- /dev/null ++++ b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2022, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/dts-v1/; ++ ++/ { ++ compatible = "arm,ffa-core-manifest-1.0"; ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ attribute { ++ spmc_id = <0x8000>; ++ maj_ver = <0x1>; ++ min_ver = <0x1>; ++ exec_state = <0x0>; ++ load_address = <0x0 0xfd000000>; ++ entrypoint = <0x0 0xfd000000>; ++ binary_size = <0x80000>; ++ }; ++ ++ hypervisor { ++ compatible = "hafnium,hafnium"; ++ vm1 { ++ is_ffa_partition; ++ debug_name = "trusty"; ++ load_address = <0xf901f000>; ++ vcpu_count = <8>; ++ mem_size = <0x3f00000>; /* 64MB TZC DRAM - 1MB align */ ++ }; ++#ifdef TS_SP_FW_CONFIG ++ vm2 { ++ is_ffa_partition; ++ debug_name = "internal-trusted-storage"; ++ load_address = <0xfee00000>; ++ vcpu_count = <1>; ++ mem_size = <2097152>; /* 2MB TZC DRAM */ ++ }; ++ vm3 { ++ is_ffa_partition; ++ debug_name = "crypto"; ++ load_address = <0xfec00000>; ++ vcpu_count = <1>; ++ mem_size = <2097152>; /* 2MB TZC DRAM */ ++ }; ++#endif ++ }; ++ ++ cpus { ++ #address-cells = <0x2>; ++ #size-cells = <0x0>; ++ ++ CPU0:cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x0>; ++ enable-method = "psci"; ++ }; ++ ++ /* ++ * SPMC (Hafnium) requires secondary cpu nodes are declared in ++ * descending order ++ */ ++ CPU7:cpu@700 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x700>; ++ enable-method = "psci"; ++ }; ++ ++ CPU6:cpu@600 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x600>; ++ enable-method = "psci"; ++ }; ++ ++ CPU5:cpu@500 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x500>; ++ enable-method = "psci"; ++ }; ++ ++ CPU4:cpu@400 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x400>; ++ enable-method = "psci"; ++ }; ++ ++ CPU3:cpu@300 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x300>; ++ enable-method = "psci"; ++ }; ++ ++ CPU2:cpu@200 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x200>; ++ enable-method = "psci"; ++ }; ++ ++ CPU1:cpu@100 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x100>; ++ enable-method = "psci"; ++ }; ++ }; ++ ++ /* 96MB of TC_TZC_DRAM1_BASE */ ++ memory@f9000000 { ++ device_type = "memory"; ++ reg = <0x0 0xf9000000 0x6000000>; ++ }; ++}; +diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +index 4c6ccef25..a72772fb3 100644 +--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts ++++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2020-2021, Arm Limited. All rights reserved. ++ * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -47,6 +47,11 @@ + uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b"; + load-address = <0xfd280000>; + }; ++#elif TRUSTY_SP_FW_CONFIG ++ trusty { ++ uuid = "40ee25f0-a2bc-304c-8c4c-a173c57d8af1"; ++ load-address = <0xf901f000>; ++ }; + #else + cactus-primary { + uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb"; +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0006-feat-plat-tc-update-dts-with-trusty-compatible-strin.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0006-feat-plat-tc-update-dts-with-trusty-compatible-strin.patch new file mode 100644 index 000000000000..e2bfb2c5f550 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0006-feat-plat-tc-update-dts-with-trusty-compatible-strin.patch @@ -0,0 +1,50 @@ +From 96151af7eed28d63fdaa1ac6de2d14a9c71f1d4a Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Wed, 30 Mar 2022 12:14:49 +0000 +Subject: [PATCH 6/7] feat(plat/tc): update dts with trusty compatible string + +Signed-off-by: Arunachalam Ganapathy +Change-Id: Ic6661df479e114bf3f464165c14df5fa02dc0139 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + fdts/tc.dts | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/fdts/tc.dts b/fdts/tc.dts +index af64504a4..dc86958bf 100644 +--- a/fdts/tc.dts ++++ b/fdts/tc.dts +@@ -555,4 +555,30 @@ + compatible = "arm,trace-buffer-extension"; + interrupts = <1 2 4>; + }; ++ ++ trusty { ++ #size-cells = <0x02>; ++ #address-cells = <0x02>; ++ ranges = <0x00>; ++ compatible = "android,trusty-v1"; ++ ++ virtio { ++ compatible = "android,trusty-virtio-v1"; ++ }; ++ ++ test { ++ compatible = "android,trusty-test-v1"; ++ }; ++ ++ log { ++ compatible = "android,trusty-log-v1"; ++ }; ++ ++ irq { ++ ipi-range = <0x08 0x0f 0x08>; ++ interrupt-ranges = <0x00 0x0f 0x00 0x10 0x1f 0x01 0x20 0x3f 0x02>; ++ interrupt-templates = <0x01 0x00 0x8001 0x01 0x01 0x04 0x8001 0x01 0x00 0x04>; ++ compatible = "android,trusty-irq-v1"; ++ }; ++ }; + }; +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0007-feat-arm-tc-Update-trusty-load-address-in-dts-files.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0007-feat-arm-tc-Update-trusty-load-address-in-dts-files.patch new file mode 100644 index 000000000000..c5a25e9a1a79 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0007-feat-arm-tc-Update-trusty-load-address-in-dts-files.patch @@ -0,0 +1,44 @@ +From ea9556a14bec0249ac6e01e4a55cbb04fd15b51a Mon Sep 17 00:00:00 2001 +From: Rupinderjit Singh +Date: Wed, 27 Jul 2022 09:23:58 +0100 +Subject: [PATCH] feat(arm/tc): Update trusty load-address in dts files. + +Change is required to align with sp header size change from 0x1000 to 0x4000 + +Signed-off-by: Rupinderjit Singh +Change-Id: Ieeaa7450196b33ecff1612cf3b55cf173a7941e0 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts | 2 +- + plat/arm/board/tc/fdts/tc_tb_fw_config.dts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts +index e2ea7b811..66a686c9a 100644 +--- a/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts ++++ b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts +@@ -25,7 +25,7 @@ + vm1 { + is_ffa_partition; + debug_name = "trusty"; +- load_address = <0xf901f000>; ++ load_address = <0xf901c000>; + vcpu_count = <8>; + mem_size = <0x3f00000>; /* 64MB TZC DRAM - 1MB align */ + }; +diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +index a72772fb3..a5bb520fe 100644 +--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts ++++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +@@ -50,7 +50,7 @@ + #elif TRUSTY_SP_FW_CONFIG + trusty { + uuid = "40ee25f0-a2bc-304c-8c4c-a173c57d8af1"; +- load-address = <0xf901f000>; ++ load-address = <0xf901c000>; + }; + #else + cactus-primary { +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0008-feat-plat-tc-add-firmware-update-secure-partition.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0008-feat-plat-tc-add-firmware-update-secure-partition.patch new file mode 100644 index 000000000000..d36d95910cf5 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0008-feat-plat-tc-add-firmware-update-secure-partition.patch @@ -0,0 +1,63 @@ +From 16f183e3c09d64fee92638ea9d0017ac7973ddf8 Mon Sep 17 00:00:00 2001 +From: Tudor Cretu +Date: Fri, 24 Sep 2021 12:09:53 +0000 +Subject: [PATCH 1/2] feat(plat/tc): add firmware update secure partition + +Firmware update is a trusted service secure partition that implements +the PSA firmware update specification. It executes in the secure world +in total compute platform. + +Signed-off-by: Davidson K +Signed-off-by: Tudor Cretu +Change-Id: I6223d247b078de8c03b068185bf120b3d502f500 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts | 9 ++++++++- + plat/arm/board/tc/fdts/tc_tb_fw_config.dts | 4 ++++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts +index 92e2ddda6..23ad06888 100644 +--- a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts ++++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts +@@ -28,7 +28,7 @@ + load_address = <0xfd280000>; + vcpu_count = <8>; + #ifdef TS_SP_FW_CONFIG +- mem_size = <26738688>; /* 25MB TZC DRAM */ ++ mem_size = <20447232>; /* 19MB TZC DRAM */ + #else + mem_size = <30928896>; /* 29MB TZC DRAM */ + #endif +@@ -48,6 +48,13 @@ + vcpu_count = <1>; + mem_size = <2097152>; /* 2MB TZC DRAM */ + }; ++ vm4 { ++ is_ffa_partition; ++ debug_name = "firmware-update"; ++ load_address = <0xfe600000>; ++ vcpu_count = <1>; ++ mem_size = <6291456>; /* 6MB TZC DRAM */ ++ }; + #endif + }; + +diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +index a5bb520fe..2c640b363 100644 +--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts ++++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +@@ -41,6 +41,10 @@ + uuid = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"; + load-address = <0xfec00000>; + }; ++ firmware-update { ++ uuid = "6823a838-1b06-470e-9774-0cce8bfb53fd"; ++ load-address = <0xfe600000>; ++ }; + #endif + #if OPTEE_SP_FW_CONFIG + op-tee { +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0009-feat-plat-tc-reserve-4-MB-for-stmm-communication-use.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0009-feat-plat-tc-reserve-4-MB-for-stmm-communication-use.patch new file mode 100644 index 000000000000..f20f9480a088 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/0009-feat-plat-tc-reserve-4-MB-for-stmm-communication-use.patch @@ -0,0 +1,35 @@ +From a8cdd6c67d26c15642338a45279db5e39cf4e565 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Fri, 3 Jun 2022 18:16:31 +0530 +Subject: [PATCH 2/2] feat(plat/tc): reserve 4 MB for stmm communication used + for firmware update + +The firmware update secure partition and u-boot communicates using +the stmm communication layer and it needs a dedicated memory region. + +Signed-off-by: Davidson K +Change-Id: I8d4da5c26843d225983dcaee0757694a6d43234c +Upstream-Status: Pending [Not submitted to upstream yet] +--- + fdts/tc.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fdts/tc.dts b/fdts/tc.dts +index dc86958bf..cb504c4a2 100644 +--- a/fdts/tc.dts ++++ b/fdts/tc.dts +@@ -217,6 +217,11 @@ + reg = <0x00000000 0xf8e00000 0 0x00200000>; + no-map; + }; ++ ++ fwu_mm@0xfca00000 { ++ reg = <0x00000000 0xfca00000 0 0x00400000>; ++ no-map; ++ }; + }; + + psci { +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/generate_metadata.py b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/generate_metadata.py new file mode 100644 index 000000000000..f3670ce1d14a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/tc/generate_metadata.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import argparse +import uuid +import zlib + +def main(metadata_file, img_type_uuids, location_uuids, img_uuids): + def add_field_to_metadata(value): + # Write the integer values to file in little endian representation + with open(metadata_file, "ab") as fp: + fp.write(value.to_bytes(4, byteorder='little')) + + def add_uuid_to_metadata(uuid_str): + # Validate UUID string and write to file in little endian representation + uuid_val = uuid.UUID(uuid_str) + with open(metadata_file, "ab") as fp: + fp.write(uuid_val.bytes_le) + + # Fill metadata preamble + add_field_to_metadata(1) #version=1 + add_field_to_metadata(0) #active_index=0 + add_field_to_metadata(0) #previous_active_index=0 + + for img_type_uuid, location_uuid in zip(img_type_uuids, location_uuids): + # Fill metadata image entry + add_uuid_to_metadata(img_type_uuid) # img_type_uuid + add_uuid_to_metadata(location_uuid) # location_uuid + + for img_uuid in img_uuids: + # Fill metadata bank image info + add_uuid_to_metadata(img_uuid) # image unique bank_uuid + add_field_to_metadata(1) # accepted=1 + add_field_to_metadata(0) # reserved (MBZ) + + # Prepend CRC32 + with open(metadata_file, 'rb+') as fp: + content = fp.read() + crc = zlib.crc32(content) + fp.seek(0) + fp.write(crc.to_bytes(4, byteorder='little') + content) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--metadata_file', required=True, + help='Output binary file to store the metadata') + parser.add_argument('--img_type_uuids', type=str, nargs='+', required=True, + help='A list of UUIDs identifying the image types') + parser.add_argument('--location_uuids', type=str, nargs='+', required=True, + help='A list of UUIDs of the storage volumes where the images are located. ' + 'Must have the same length as img_type_uuids.') + parser.add_argument('--img_uuids', type=str, nargs='+', required=True, + help='A list UUIDs of the images in a firmware bank') + + args = parser.parse_args() + + if len(args.img_type_uuids) != len(args.location_uuids): + parser.print_help() + raise argparse.ArgumentError(None, 'Arguments img_type_uuids and location_uuids must have the same length.') + + main(args.metadata_file, args.img_type_uuids, args.location_uuids, args.img_uuids) diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_2.7.0.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_2.7.0.bbappend new file mode 100644 index 000000000000..ff22ff12de81 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_2.7.0.bbappend @@ -0,0 +1,3 @@ +# Machine specific TFAs + +COMPATIBLE_MACHINE:corstone1000 = "corstone1000" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc new file mode 100644 index 000000000000..3034680d319f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc @@ -0,0 +1,39 @@ +# Corstone1000 64-bit machines specific TFA support + +COMPATIBLE_MACHINE = "(corstone1000)" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files/corstone1000:" + +SRC_URI:append = " \ + file://0001-Fix-FF-A-version-in-SPMC-manifest.patch \ + " + +TFA_DEBUG = "1" +TFA_UBOOT ?= "1" +TFA_MBEDTLS = "1" +TFA_BUILD_TARGET = "bl2 bl31 fip" + +# Enabling Secure-EL1 Payload Dispatcher (SPD) +TFA_SPD = "spmd" +# Cortex-A35 supports Armv8.0-A (no S-EL2 execution state). +# So, the SPD SPMC component should run at the S-EL1 execution state +TFA_SPMD_SPM_AT_SEL2 = "0" + +# BL2 loads BL32 (optee). So, optee needs to be built first: +DEPENDS += "optee-os" + +EXTRA_OEMAKE:append = " \ + ARCH=aarch64 \ + TARGET_PLATFORM=${TFA_TARGET_PLATFORM} \ + ENABLE_STACK_PROTECTOR=strong \ + ENABLE_PIE=1 \ + BL2_AT_EL3=1 \ + CREATE_KEYS=1 \ + GENERATE_COT=1 \ + TRUSTED_BOARD_BOOT=1 \ + COT=tbbr \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL32=${RECIPE_SYSROOT}/lib/firmware/tee-pager_v2.bin \ + LOG_LEVEL=50 \ + " diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone500.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone500.inc new file mode 100644 index 000000000000..acd9e3dbfbf0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone500.inc @@ -0,0 +1,17 @@ +# Corstone-500 specific TFA support + +COMPATIBLE_MACHINE = "corstone500" +TFA_PLATFORM = "a5ds" +TFA_DEBUG = "1" +TFA_UBOOT = "1" +TFA_BUILD_TARGET = "all fip" +TFA_INSTALL_TARGET = "bl1.bin fip.bin" + +EXTRA_OEMAKE:append = " \ + ARCH=aarch32 \ + FVP_HW_CONFIG_DTS=fdts/a5ds.dts \ + ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min \ + ARM_CORTEX_A5=yes \ + ARM_XLAT_TABLES_LIB_V1=1 \ + " diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc new file mode 100644 index 000000000000..fdaadb9fc62c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc @@ -0,0 +1,12 @@ +# Armv7-A FVP specific TFA parameters + +COMPATIBLE_MACHINE = "fvp-base-arm32" +TFA_PLATFORM = "fvp" +TFA_UBOOT = "1" +TFA_BUILD_TARGET = "dtbs bl1 bl32 fip" + +EXTRA_OEMAKE:append = " \ + ARCH=aarch32 \ + AARCH32_SP=sp_min \ + " + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc new file mode 100644 index 000000000000..43340cdc7b17 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc @@ -0,0 +1,12 @@ +# FVP specific TFA parameters + +# +# Armv8-A Base Platform FVP +# + +COMPATIBLE_MACHINE = "fvp-base" +TFA_PLATFORM = "fvp" +TFA_DEBUG = "1" +TFA_MBEDTLS = "1" +TFA_UBOOT = "1" +TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-juno.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-juno.inc new file mode 100644 index 000000000000..3ddd8cb5f2b9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-juno.inc @@ -0,0 +1,13 @@ +# Juno specific TFA support + +COMPATIBLE_MACHINE = "juno" +TFA_PLATFORM = "juno" +TFA_DEBUG = "1" +TFA_MBEDTLS = "1" +TFA_UBOOT ?= "1" +TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip" + +# Juno needs the System Control Processor Firmware +DEPENDS += "virtual/control-processor-firmware" + +EXTRA_OEMAKE:append = " SCP_BL2=${RECIPE_SYSROOT}/firmware/scp_ramfw.bin" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-n1sdp.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-n1sdp.inc new file mode 100644 index 000000000000..9fb567fa74fd --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-n1sdp.inc @@ -0,0 +1,35 @@ +# N1SDP specific TFA support + +# Align with post-N1SDP-2022.06.22 refresh +SRCREV_tfa = "1309c6c805190bd376c0561597653f3f8ecd0f58" +PV .= "+git${SRCPV}" + +COMPATIBLE_MACHINE = "n1sdp" +TFA_PLATFORM = "n1sdp" +TFA_BUILD_TARGET = "all fip" +TFA_INSTALL_TARGET = "bl1 bl2 bl31 n1sdp-multi-chip n1sdp-single-chip n1sdp_fw_config n1sdp_tb_fw_config fip" +TFA_DEBUG = "1" +TFA_MBEDTLS = "1" +TFA_UBOOT = "0" +TFA_UEFI = "1" + +TFA_ROT_KEY= "plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem" + +# Enabling Secure-EL1 Payload Dispatcher (SPD) +TFA_SPD = "spmd" +# Cortex-A35 supports Armv8.0-A (no S-EL2 execution state). +# So, the SPD SPMC component should run at the S-EL1 execution state +TFA_SPMD_SPM_AT_SEL2 = "0" + +# BL2 loads BL32 (optee). So, optee needs to be built first: +DEPENDS += "optee-os" + +EXTRA_OEMAKE:append = "\ + TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 \ + CREATE_KEYS=1 \ + ARM_ROTPK_LOCATION="devel_rsa" \ + ROT_KEY="${TFA_ROT_KEY}" \ + BL32=${RECIPE_SYSROOT}/lib/firmware/tee-pager_v2.bin \ + BL33=${RECIPE_SYSROOT}/firmware/uefi.bin \ + " diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-sgi575.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-sgi575.inc new file mode 100644 index 000000000000..20904b34cb78 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-sgi575.inc @@ -0,0 +1,13 @@ +# SGI575 specific TFA support + +COMPATIBLE_MACHINE = "sgi575" +TFA_PLATFORM = "sgi575" +TFA_BUILD_TARGET = "all fip" +TFA_INSTALL_TARGET = "bl1 fip" +TFA_DEBUG = "1" +TFA_MBEDTLS = "1" +TFA_UBOOT = "0" +TFA_UEFI = "1" + +EXTRA_OEMAKE += "TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc new file mode 100644 index 000000000000..301f97c8fec8 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc @@ -0,0 +1,147 @@ +# TC0 specific TFA configuration + +# Intermediate SHA with 2.7 baseline version +SRCREV_tfa = "e95abc4c01822ef43e9e874d63d6596dc0b57279" +PV = "2.7+git${SRCPV}" + +DEPENDS += "scp-firmware util-linux-native gptfdisk-native" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files/tc:" +SRC_URI:append = " \ + file://0001-plat-tc-Increase-maximum-BL2-size.patch \ + file://0002-Makefile-add-trusty_sp_fw_config-build-option.patch \ + file://0003-fix-plat-arm-increase-sp-max-image-size.patch \ + file://0004-fix-plat-tc-increase-tc_tzc_dram1_size.patch \ + file://0005-feat-plat-tc-add-spmc-manifest-with-trusty-sp.patch \ + file://0006-feat-plat-tc-update-dts-with-trusty-compatible-strin.patch \ + file://0007-feat-arm-tc-Update-trusty-load-address-in-dts-files.patch \ + file://0008-feat-plat-tc-add-firmware-update-secure-partition.patch \ + file://0009-feat-plat-tc-reserve-4-MB-for-stmm-communication-use.patch \ + file://generate_metadata.py \ + " + +COMPATIBLE_MACHINE = "(tc?)" + +TFA_PLATFORM = "tc" +TFA_BUILD_TARGET = "all fip" +TFA_UBOOT = "1" +TFA_INSTALL_TARGET = "bl1 fip" +TFA_MBEDTLS = "1" +TFA_DEBUG = "1" + +TFA_SPD = "spmd" +TFA_SPMD_SPM_AT_SEL2 = "1" + +TFA_TARGET_PLATFORM:tc0 = "0" +TFA_TARGET_PLATFORM:tc1 = "1" + +EXTRA_OEMAKE += "TARGET_PLATFORM=${TFA_TARGET_PLATFORM}" + +# Set optee as SP. Set spmc manifest and sp layout file to optee +DEPENDS += "optee-os" + +TFA_SP_LAYOUT_FILE = "${RECIPE_SYSROOT}/lib/firmware/sp_layout.json" +TFA_ARM_SPMC_MANIFEST_DTS = "plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts" + +EXTRA_OEMAKE += "SCP_BL2=${RECIPE_SYSROOT}/firmware/scp_ramfw.bin" +EXTRA_OEMAKE += "TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem" +EXTRA_OEMAKE += "PSA_FWU_SUPPORT=1 ARM_GPT_SUPPORT=1" +EXTRA_OEMAKE += "CTX_INCLUDE_MTE_REGS=1" + +do_generate_gpt() { + gpt_image="${BUILD_DIR}/fip_gpt.bin" + fip_bin="${BUILD_DIR}/fip.bin" + # the FIP partition type is not standardized, so generate one + fip_type_uuid=`uuidgen --sha1 --namespace @dns --name "fip_type_uuid"` + # metadata partition type UUID, specified by the document: + # Platform Security Firmware Update for the A-profile Arm Architecture + # version: 1.0BET0 + metadata_type_uuid="8a7a84a0-8387-40f6-ab41-a8b9a5a60d23" + location_uuid=`uuidgen` + FIP_A_uuid=`uuidgen` + FIP_B_uuid=`uuidgen` + + # maximum FIP size 4MB. This is the current size of the FIP rounded up to an integer number of MB. + fip_max_size=4194304 + fip_bin_size=$(stat -c %s $fip_bin) + if [ $fip_max_size -lt $fip_bin_size ]; then + bberror "FIP binary ($fip_bin_size bytes) is larger than the GPT partition ($fip_max_size bytes)" + fi + + # maximum metadata size 512B. This is the current size of the metadata rounded up to an integer number of sectors. + metadata_max_size=512 + metadata_file="${BUILD_DIR}/metadata.bin" + python3 ${WORKDIR}/generate_metadata.py --metadata_file $metadata_file \ + --img_type_uuids $fip_type_uuid \ + --location_uuids $location_uuid \ + --img_uuids $FIP_A_uuid $FIP_B_uuid + + # create GPT image. The GPT contains 2 FIP partitions: FIP_A and FIP_B, and 2 metadata partitions: FWU-Metadata and Bkup-FWU-Metadata. + # the GPT layout is the following: + # ----------------------- + # Protective MBR + # ----------------------- + # Primary GPT Header + # ----------------------- + # FIP_A + # ----------------------- + # FIP_B + # ----------------------- + # FWU-Metadata + # ----------------------- + # Bkup-FWU-Metadata + # ----------------------- + # Secondary GPT Header + # ----------------------- + + sector_size=512 + gpt_header_size=33 # valid only for 512-byte sectors + num_sectors_fip=`expr $fip_max_size / $sector_size` + num_sectors_metadata=`expr $metadata_max_size / $sector_size` + start_sector_1=`expr 1 + $gpt_header_size` # size of MBR is 1 sector + start_sector_2=`expr $start_sector_1 + $num_sectors_fip` + start_sector_3=`expr $start_sector_2 + $num_sectors_fip` + start_sector_4=`expr $start_sector_3 + $num_sectors_metadata` + num_sectors_gpt=`expr $start_sector_4 + $num_sectors_metadata + $gpt_header_size` + gpt_size=`expr $num_sectors_gpt \* $sector_size` + + # create raw image + dd if=/dev/zero of=$gpt_image bs=$gpt_size count=1 + + # create the GPT layout + sgdisk $gpt_image \ + --set-alignment 1 \ + --disk-guid $location_uuid \ + \ + --new 1:$start_sector_1:+$num_sectors_fip \ + --change-name 1:FIP_A \ + --typecode 1:$fip_type_uuid \ + --partition-guid 1:$FIP_A_uuid \ + \ + --new 2:$start_sector_2:+$num_sectors_fip \ + --change-name 2:FIP_B \ + --typecode 2:$fip_type_uuid \ + --partition-guid 2:$FIP_B_uuid \ + \ + --new 3:$start_sector_3:+$num_sectors_metadata \ + --change-name 3:FWU-Metadata \ + --typecode 3:$metadata_type_uuid \ + \ + --new 4:$start_sector_4:+$num_sectors_metadata \ + --change-name 4:Bkup-FWU-Metadata \ + --typecode 4:$metadata_type_uuid + + # populate the GPT partitions + dd if=$fip_bin of=$gpt_image bs=$sector_size seek=$start_sector_1 count=$num_sectors_fip conv=notrunc + dd if=$fip_bin of=$gpt_image bs=$sector_size seek=$start_sector_2 count=$num_sectors_fip conv=notrunc + dd if=$metadata_file of=$gpt_image bs=$sector_size seek=$start_sector_3 count=$num_sectors_metadata conv=notrunc + dd if=$metadata_file of=$gpt_image bs=$sector_size seek=$start_sector_4 count=$num_sectors_metadata conv=notrunc +} + +addtask do_generate_gpt after do_compile before do_install + +do_install:append() { + install -m 0644 ${BUILD_DIR}/fip_gpt.bin ${D}/firmware/fip_gpt-tc.bin + ln -sf fip_gpt-tc.bin ${D}/firmware/fip_gpt.bin +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.7.%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.7.%.bbappend new file mode 100644 index 000000000000..09ed3f793afb --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.7.%.bbappend @@ -0,0 +1,15 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/files/:" + +# Machine specific TFAs + +MACHINE_TFA_REQUIRE ?= "" +MACHINE_TFA_REQUIRE:corstone500 = "trusted-firmware-a-corstone500.inc" +MACHINE_TFA_REQUIRE:corstone1000 = "trusted-firmware-a-corstone1000.inc" +MACHINE_TFA_REQUIRE:fvp-base = "trusted-firmware-a-fvp.inc" +MACHINE_TFA_REQUIRE:fvp-base-arm32 = "trusted-firmware-a-fvp-arm32.inc" +MACHINE_TFA_REQUIRE:juno = "trusted-firmware-a-juno.inc" +MACHINE_TFA_REQUIRE:n1sdp = "trusted-firmware-a-n1sdp.inc" +MACHINE_TFA_REQUIRE:sgi575 = "trusted-firmware-a-sgi575.inc" +MACHINE_TFA_REQUIRE:tc = "trusted-firmware-a-tc.inc" + +require ${MACHINE_TFA_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc new file mode 100644 index 000000000000..279109e02cc9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc @@ -0,0 +1,33 @@ +# Corstone1000 machines specific TFM support + +COMPATIBLE_MACHINE = "(corstone1000)" + +TFM_PLATFORM = "arm/corstone1000" + +TFM_DEBUG = "1" + +## Default is the MPS3 board +TFM_PLATFORM_IS_FVP ?= "FALSE" +EXTRA_OECMAKE += "-DPLATFORM_IS_FVP=${TFM_PLATFORM_IS_FVP}" +EXTRA_OECMAKE += "-DCC312_LEGACY_DRIVER_API_ENABLED=OFF" + +# libmetal +LICENSE += "& BSD-3-Clause" +LIC_FILES_CHKSUM += "file://../libmetal/LICENSE.md;md5=fe0b8a4beea8f0813b606d15a3df3d3c" +SRC_URI += "git://github.com/OpenAMP/libmetal.git;protocol=https;branch=main;name=libmetal;destsuffix=git/libmetal" +SRCREV_libmetal = "f252f0e007fbfb8b3a52b1d5901250ddac96baad" +EXTRA_OECMAKE += "-DLIBMETAL_SRC_PATH=${S}/../libmetal -DLIBMETAL_BIN_PATH=${B}/libmetal-build" + +# OpenAMP +LICENSE += "& BSD-2-Clause & BSD-3-Clause" +LIC_FILES_CHKSUM += "file://../openamp/LICENSE.md;md5=a8d8cf662ef6bf9936a1e1413585ecbf" +SRC_URI += "git://github.com/OpenAMP/open-amp.git;protocol=https;branch=main;name=openamp;destsuffix=git/openamp" +SRCREV_openamp = "347397decaa43372fc4d00f965640ebde042966d" +EXTRA_OECMAKE += "-DLIBOPENAMP_SRC_PATH=${S}/../openamp -DLIBOPENAMP_BIN_PATH=${B}/libopenamp-build" + + +do_install() { + install -D -p -m 0644 ${B}/install/outputs/tfm_s_signed.bin ${D}/firmware/tfm_s_signed.bin + install -D -p -m 0644 ${B}/install/outputs/bl2_signed.bin ${D}/firmware/bl2_signed.bin + install -D -p -m 0644 ${B}/install/outputs/bl1.bin ${D}/firmware/bl1.bin +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_1.7.%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_1.7.%.bbappend new file mode 100644 index 000000000000..ec0e483b97be --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_1.7.%.bbappend @@ -0,0 +1,6 @@ +# Machine specific configurations + +MACHINE_TFM_REQUIRE ?= "" +MACHINE_TFM_REQUIRE:corstone1000 = "trusted-firmware-m-1.7.0-corstone1000.inc" + +require ${MACHINE_TFM_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm64-smccc-add-support-for-SMCCCv1.2-x0-x17-registe.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm64-smccc-add-support-for-SMCCCv1.2-x0-x17-registe.patch new file mode 100644 index 000000000000..837f8a92b9b9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm64-smccc-add-support-for-SMCCCv1.2-x0-x17-registe.patch @@ -0,0 +1,211 @@ +From 584e4952dca726c3dc9df319dffb37a518b65c14 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 29 Jul 2022 13:06:19 +0100 +Subject: [PATCH 01/25] arm64: smccc: add support for SMCCCv1.2 x0-x17 + registers + +add support for x0-x17 registers used by the SMC calls + +In SMCCC v1.2 [1] arguments are passed in registers x1-x17. +Results are returned in x0-x17. + +This work is inspired from the following kernel commit: + +arm64: smccc: Add support for SMCCCv1.2 extended input/output registers + +[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token= + +Signed-off-by: Abdellatif El Khlifi +Reviewed-by: Jens Wiklander +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v7: + +* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS + +v4: + +* rename the commit title and improve description + new commit title: the current + +v3: + +* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2 + commit title: + arm64: smccc: add Xn registers support used by SMC calls +--- + arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++ + arch/arm/lib/asm-offsets.c | 14 +++++++++ + include/linux/arm-smccc.h | 43 ++++++++++++++++++++++++++ + 3 files changed, 110 insertions(+) + +diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S +index dc92b28777..ec6f299bc9 100644 +--- a/arch/arm/cpu/armv8/smccc-call.S ++++ b/arch/arm/cpu/armv8/smccc-call.S +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Copyright (c) 2015, Linaro Limited ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + #include + #include +@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc) + ENTRY(__arm_smccc_hvc) + SMCCC hvc + ENDPROC(__arm_smccc_hvc) ++ ++#ifdef CONFIG_ARM64 ++ ++ .macro SMCCC_1_2 instr ++ /* Save `res` and free a GPR that won't be clobbered */ ++ stp x1, x19, [sp, #-16]! ++ ++ /* Ensure `args` won't be clobbered while loading regs in next step */ ++ mov x19, x0 ++ ++ /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */ ++ ldp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] ++ ldp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] ++ ldp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] ++ ldp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] ++ ldp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] ++ ldp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] ++ ldp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] ++ ldp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] ++ ldp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] ++ ++ \instr #0 ++ ++ /* Load the `res` from the stack */ ++ ldr x19, [sp] ++ ++ /* Store the registers x0 - x17 into the result structure */ ++ stp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] ++ stp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] ++ stp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] ++ stp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] ++ stp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] ++ stp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] ++ stp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] ++ stp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] ++ stp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] ++ ++ /* Restore original x19 */ ++ ldp xzr, x19, [sp], #16 ++ ret ++ .endm ++ ++/* ++ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, ++ * struct arm_smccc_1_2_regs *res); ++ */ ++ENTRY(arm_smccc_1_2_smc) ++ SMCCC_1_2 smc ++ENDPROC(arm_smccc_1_2_smc) ++ ++#endif +diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c +index 22fd541f9a..db6d7ed234 100644 +--- a/arch/arm/lib/asm-offsets.c ++++ b/arch/arm/lib/asm-offsets.c +@@ -9,6 +9,9 @@ + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. ++ * ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #include +@@ -117,6 +120,17 @@ int main(void) + DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); + DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); + DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); ++#ifdef CONFIG_ARM64 ++ DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS, offsetof(struct arm_smccc_1_2_regs, a0)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS, offsetof(struct arm_smccc_1_2_regs, a2)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS, offsetof(struct arm_smccc_1_2_regs, a4)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS, offsetof(struct arm_smccc_1_2_regs, a6)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS, offsetof(struct arm_smccc_1_2_regs, a8)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS, offsetof(struct arm_smccc_1_2_regs, a10)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS, offsetof(struct arm_smccc_1_2_regs, a12)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS, offsetof(struct arm_smccc_1_2_regs, a14)); ++ DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS, offsetof(struct arm_smccc_1_2_regs, a16)); ++#endif + #endif + + return 0; +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index e1d09884a1..9105031d55 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Copyright (c) 2015, Linaro Limited ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + #ifndef __LINUX_ARM_SMCCC_H + #define __LINUX_ARM_SMCCC_H +@@ -70,6 +72,47 @@ struct arm_smccc_res { + unsigned long a3; + }; + ++#ifdef CONFIG_ARM64 ++/** ++ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call ++ * @a0-a17 argument values from registers 0 to 17 ++ */ ++struct arm_smccc_1_2_regs { ++ unsigned long a0; ++ unsigned long a1; ++ unsigned long a2; ++ unsigned long a3; ++ unsigned long a4; ++ unsigned long a5; ++ unsigned long a6; ++ unsigned long a7; ++ unsigned long a8; ++ unsigned long a9; ++ unsigned long a10; ++ unsigned long a11; ++ unsigned long a12; ++ unsigned long a13; ++ unsigned long a14; ++ unsigned long a15; ++ unsigned long a16; ++ unsigned long a17; ++}; ++ ++/** ++ * arm_smccc_1_2_smc() - make SMC calls ++ * @args: arguments passed via struct arm_smccc_1_2_regs ++ * @res: result values via struct arm_smccc_1_2_regs ++ * ++ * This function is used to make SMC calls following SMC Calling Convention ++ * v1.2 or above. The content of the supplied param are copied from the ++ * structure to registers prior to the SMC instruction. The return values ++ * are updated with the content from registers on return from the SMC ++ * instruction. ++ */ ++asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, ++ struct arm_smccc_1_2_regs *res); ++#endif ++ + /** + * struct arm_smccc_quirk - Contains quirk information + * @id: quirk identification +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-lib-uuid-introduce-uuid_str_to_le_bin-function.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-lib-uuid-introduce-uuid_str_to_le_bin-function.patch new file mode 100644 index 000000000000..1b043dd52d29 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-lib-uuid-introduce-uuid_str_to_le_bin-function.patch @@ -0,0 +1,132 @@ +From b226e6000de0b1f55d56c1193d1fde028d64abd3 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 4 Aug 2022 16:46:47 +0100 +Subject: [PATCH 02/25] lib: uuid: introduce uuid_str_to_le_bin function + +convert UUID string to little endian binary data + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + +* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms + +v7: + +* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin() +* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin() + by using same APIs + +v4: + +* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in + a standalone commit (the current) + +v3: + +* introduce ffa_uuid_str_to_bin (provided by + arm_ffa: introduce Arm FF-A low-level driver) +--- + include/uuid.h | 8 ++++++++ + lib/uuid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + +diff --git a/include/uuid.h b/include/uuid.h +index 4a4883d3b5..293a8eb0a5 100644 +--- a/include/uuid.h ++++ b/include/uuid.h +@@ -2,6 +2,8 @@ + /* + * Copyright (C) 2014 Samsung Electronics + * Przemyslaw Marczak ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + #ifndef __UUID_H__ + #define __UUID_H__ +@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin); + const char *uuid_guid_get_str(const unsigned char *guid_bin); + void gen_rand_uuid(unsigned char *uuid_bin); + void gen_rand_uuid_str(char *uuid_str, int str_format); ++ ++/** ++ * uuid_str_to_le_bin - Converts a UUID string to little endian binary data ++ */ ++int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin); ++ + #endif +diff --git a/lib/uuid.c b/lib/uuid.c +index 465e1ac38f..d29f561a70 100644 +--- a/lib/uuid.c ++++ b/lib/uuid.c +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright 2011 Calxeda, Inc. ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #include +@@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, + return 0; + } + ++/** ++ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data. ++ * @uuid_str: pointer to UUID string ++ * @uuid_bin: pointer to allocated array for little endian output [16B] ++ * ++ * UUID string is 36 characters (36 bytes): ++ * ++ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ++ * ++ * where x is a hexadecimal character. Fields are separated by '-'s. ++ * When converting to a little endian binary UUID, the string fields are reversed. ++ * ++ * Return: ++ * ++ * uuid_bin filled with little endian UUID data ++ * On success 0 is returned. Otherwise, failure code. ++ */ ++int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) ++{ ++ u16 tmp16; ++ u32 tmp32; ++ u64 tmp64; ++ ++ if (!uuid_str_valid(uuid_str) || !uuid_bin) ++ return -EINVAL; ++ ++ tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); ++ memcpy(uuid_bin, &tmp32, 4); ++ ++ tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); ++ memcpy(uuid_bin + 4, &tmp16, 2); ++ ++ tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); ++ memcpy(uuid_bin + 6, &tmp16, 2); ++ ++ tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL)); ++ memcpy(uuid_bin + 8, &tmp16, 2); ++ ++ tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16)); ++ memcpy(uuid_bin + 10, &tmp64, 6); ++ ++ return 0; ++} ++ + /* + * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID. + * +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-introduce-Arm-FF-A-low-level-driver.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-introduce-Arm-FF-A-low-level-driver.patch new file mode 100644 index 000000000000..774af445631e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-introduce-Arm-FF-A-low-level-driver.patch @@ -0,0 +1,2137 @@ +From 93e3267b19c5c5d27664ef133121db4b678ad72d Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Nov 2022 14:40:05 +0000 +Subject: [PATCH 03/25] arm_ffa: introduce Arm FF-A low-level driver + +Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0 + +The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1] +describes interfaces (ABIs) that standardize communication +between the Secure World and Normal World leveraging TrustZone +technology. + +This driver uses 64-bit registers as per SMCCCv1.2 spec and comes +on top of the SMCCC layer. The driver provides the FF-A ABIs needed for +querying the FF-A framework from the secure world. + +The driver uses SMC32 calling convention which means using the first +32-bit data of the Xn registers. + +All supported ABIs come with their 32-bit version except FFA_RXTX_MAP +which has 64-bit version supported. + +Both 32-bit and 64-bit direct messaging are supported which allows both +32-bit and 64-bit clients to use the FF-A bus. + +In U-Boot FF-A design, FF-A is considered as a discoverable bus. +The Secure World is considered as one entity to communicate with +using the FF-A bus. FF-A communication is handled by one device and +one instance (the bus). This FF-A driver takes care of all the +interactions between Normal world and Secure World. + +The driver exports its operations to be used by upper layers. + +Exported operations: + +- partition_info_get +- sync_send_receive +- rxtx_unmap + +For more details please refer to the driver documentation [2]. + +[1]: https://developer.arm.com/documentation/den0077/latest/ +[2]: doc/arch/arm64.ffa.rst + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + +* make ffa_get_partitions_info() second argument to be an SP count in both + modes +* update ffa_bus_prvdata_get() to return a pointer rather than a pointer + address +* remove packing from ffa_partition_info and ffa_send_direct_data structures +* pass the FF-A bus device to the bus operations + +v7: + +* add support for 32-bit direct messaging +* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin() +* improve the declaration of error handling mapping +* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported + +v6: + +* drop use of EFI runtime support (We decided with Linaro to add this later) +* drop discovery from initcalls (discovery will be on demand by FF-A users) +* set the alignment of the RX/TX buffers to the larger translation granule size +* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit +* update the documentation and move it to doc/arch/arm64.ffa.rst + +v4: + +* add doc/README.ffa.drv +* moving the FF-A driver work to drivers/firmware/arm-ffa +* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace + #if defined by #if CONFIG_IS_ENABLED +* improving error handling by mapping the FF-A errors to standard errors + and logs +* replacing panics with an error log and returning an error code +* improving features discovery in FFA_FEATURES by introducing + rxtx_min_pages private data field +* add ffa_remove and ffa_unbind functions +* improve how the driver behaves when bus discovery is done more than + once + +v3: + +* align the interfaces of the U-Boot FF-A driver with those in the linux + FF-A driver +* remove the FF-A helper layer +* make the U-Boot FF-A driver independent from EFI +* provide an optional config that enables copying the driver data to EFI + runtime section at ExitBootServices service +* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP} + +v2: + +* make FF-A bus discoverable using device_{bind, probe} APIs +* remove device tree support + +v1: + +* introduce FF-A bus driver with device tree support +--- + MAINTAINERS | 7 + + doc/arch/arm64.ffa.rst | 218 ++++ + doc/arch/index.rst | 1 + + drivers/Kconfig | 2 + + drivers/Makefile | 1 + + drivers/firmware/arm-ffa/Kconfig | 30 + + drivers/firmware/arm-ffa/Makefile | 6 + + drivers/firmware/arm-ffa/arm-ffa-uclass.c | 16 + + drivers/firmware/arm-ffa/arm_ffa_prv.h | 200 ++++ + drivers/firmware/arm-ffa/core.c | 1315 +++++++++++++++++++++ + include/arm_ffa.h | 97 ++ + include/dm/uclass-id.h | 4 + + 12 files changed, 1897 insertions(+) + create mode 100644 doc/arch/arm64.ffa.rst + create mode 100644 drivers/firmware/arm-ffa/Kconfig + create mode 100644 drivers/firmware/arm-ffa/Makefile + create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c + create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h + create mode 100644 drivers/firmware/arm-ffa/core.c + create mode 100644 include/arm_ffa.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 83346183ee..734fcb10c4 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -248,6 +248,13 @@ F: drivers/net/cortina_ni.h + F: drivers/net/phy/ca_phy.c + F: configs/cortina_presidio-asic-pnand_defconfig + ++ARM FF-A ++M: Abdellatif El Khlifi ++S: Maintained ++F: doc/arch/arm64.ffa.rst ++F: drivers/firmware/arm-ffa/ ++F: include/arm_ffa.h ++ + ARM FREESCALE IMX + M: Stefano Babic + M: Fabio Estevam +diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst +new file mode 100644 +index 0000000000..dfcec82e45 +--- /dev/null ++++ b/doc/arch/arm64.ffa.rst +@@ -0,0 +1,218 @@ ++.. SPDX-License-Identifier: GPL-2.0+ ++ ++Arm FF-A Driver ++=============== ++ ++Summary ++------- ++ ++FF-A stands for Firmware Framework for Arm A-profile processors. ++ ++FF-A specifies interfaces that enable a pair of software sandboxes to ++communicate with each other. A sandbox aka partition could ++be a VM in the Normal or Secure world, an application in S-EL0, or a ++Trusted OS in S-EL1. ++ ++This FF-A driver implements the interfaces to communicate with partitions in ++the Secure world aka Secure partitions (SPs). ++ ++The driver specifically focuses on communicating with SPs that isolate portions ++of EFI runtime services that must run in a protected environment which is ++inaccessible by the Host OS or Hypervisor. Examples of such services are ++set/get variables. ++ ++FF-A driver uses the SMC ABIs defined by the FF-A specification to: ++ ++- Discover the presence of SPs of interest ++- Access an SP's service through communication protocols ++ e.g. EFI MM communication protocol ++ ++At this stage of development the FF-A driver supports EFI boot time only. ++ ++Runtime support will be added in future developments. ++ ++FF-A and SMC specifications ++------------------------------------------- ++ ++The current implementation of the driver relies on FF-A specification v1.0 ++and uses SMC32 calling convention which means using the first 32-bit data of the ++Xn registers. ++ ++At this stage we only need the FF-A v1.0 features. ++ ++The driver has been tested with OP-TEE which supports SMC32 calling convention. ++ ++For more details please refer to the FF-A v1.0 spec: ++https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token= ++ ++Hypervisors are supported if they are configured to trap SMC calls. ++ ++The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification. ++ ++For more details please refer to the SMC Calling Convention v1.2 spec: ++https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token= ++ ++Supported hardware ++-------------------------------- ++ ++Aarch64 plaforms ++ ++Configuration ++---------------------- ++ ++CONFIG_ARM_FFA_TRANSPORT ++ Enables the FF-A bus driver. Turn this on if you want to use FF-A ++ communication. ++ ++CONFIG_SANDBOX_FFA ++ Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under ++ Sandbox and provides functional tests for FF-A. ++ ++FF-A ABIs under the hood ++--------------------------------------- ++ ++Invoking an FF-A ABI involves providing to the secure world/hypervisor the ++expected arguments from the ABI. ++ ++The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction ++is executed. ++ ++At the secure side level or hypervisor the ABI is handled at a higher exception ++level and the arguments are read and processed. ++ ++The response is put back through x0 to x7 registers and control is given back ++to the U-Boot FF-A driver (non-secure world). ++ ++The driver reads the response and processes it accordingly. ++ ++This methodology applies to all the FF-A ABIs in the driver. ++ ++FF-A bus discovery in U-Boot ++------------------------------------------- ++ ++When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on ++demand by the clients (users). ++ ++Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the ++discovery process. ++ ++ffa_bus_discover() creates, binds and probes the arm_ffa device using ++device_{bind, probe} APIs. ++ ++The discovery process consists in communicating with secure world (or hypervisor) ++and querying specific data. ++ ++The discovery process takes place during the arm_ffa device probing which is ++handled by ffa_probe(). ++ ++The FF-A bus discovery is successful and the bus is ready for use when these ++operations succeed: ++ ++- querying the FF-A framework version ++- querying from secure world the U-Boot endpoint ID ++- querying from secure world the RX/TX mapping features ++- mapping the RX/TX buffers ++- querying from secure world all the partitions information ++ ++Discovery failure results in a probing failure and the arm_ffa device is ++destroyed. ++ ++Requirements for clients ++------------------------------------- ++ ++When using the FF-A bus with EFI, clients must: ++ ++- Query SPs in EFI boot time mode using the service UUID. ++- Unmap RX/TX buffers before EFI runtime mode starts. ++ ++The RX/TX buffers are only available at EFI boot time. Querying partitions is ++done at boot time and data is cached for future use. ++ ++RX/TX buffers should be unmapped by the user before EFI runtime mode ++starts. The driver provides a bus operation for that: rxtx_unmap() ++ ++If RX/TX buffers created by U-Boot are not unmapped and by ++consequence becoming available at EFI runtime, secure world will get confused ++about RX/TX buffers ownership (U-Boot vs kernel). ++ ++When invoking FF-A direct messaging, clients should specify which ABI protocol ++they want to use (32-bit vs 64-bit). Selecting the protocol means using ++the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}. ++The calling convention stays the same: SMC32. ++ ++The bus driver layer ++------------------------------ ++ ++The driver comes on top of the SMCCC layer and is implemented in ++drivers/firmware/arm-ffa/core.c ++ ++The driver provides the following features: ++ ++- Support for the 32-bit version of the following ABIs: ++ ++FFA_VERSION ++FFA_ID_GET ++FFA_FEATURES ++FFA_PARTITION_INFO_GET ++FFA_RXTX_UNMAP ++FFA_RX_RELEASE ++FFA_RUN ++FFA_ERROR ++FFA_SUCCESS ++FFA_INTERRUPT ++FFA_MSG_SEND_DIRECT_REQ ++FFA_MSG_SEND_DIRECT_RESP ++ ++- Support for the 64-bit version of the following ABIs: ++ ++FFA_RXTX_MAP ++FFA_MSG_SEND_DIRECT_REQ ++FFA_MSG_SEND_DIRECT_RESP ++ ++- Processing the received data from the secure world/hypervisor and caching it ++ ++- Hiding from upper layers the FF-A protocol and registers details. Upper ++ layers focus on exchanged data, the driver takes care of how to transport ++ that to the secure world/hypervisor using FF-A ++ ++- The driver provides callbacks to be used by clients to access the FF-A bus: ++ ++partition_info_get ++sync_send_receive ++rxtx_unmap ++ ++- FF-A bus discovery makes sure FF-A framework is responsive and compatible ++ with the driver ++ ++- FF-A bus can be compiled and used without EFI ++ ++Using armffa command ++----------------------------------- ++ ++armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke ++its operations. ++ ++This provides a guidance to the client developers on how to call the FF-A bus ++interfaces. ++ ++Usage: ++ ++armffa ++ ++sub-commands: ++ ++ getpart ++ ++ lists the partition(s) info ++ ++ ping ++ ++ sends a data pattern to the specified partition ++ ++ devlist ++ ++ displays the arm_ffa device info ++ ++Contributors ++------------ ++ * Abdellatif El Khlifi +diff --git a/doc/arch/index.rst b/doc/arch/index.rst +index 792d9182c3..8d1ab0ad4e 100644 +--- a/doc/arch/index.rst ++++ b/doc/arch/index.rst +@@ -8,6 +8,7 @@ Architecture-specific doc + + arc + arm64 ++ arm64.ffa + m68k + mips + nios2 +diff --git a/drivers/Kconfig b/drivers/Kconfig +index 8b6fead351..b06b1ae481 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -6,6 +6,8 @@ source "drivers/core/Kconfig" + + source "drivers/adc/Kconfig" + ++source "drivers/firmware/arm-ffa/Kconfig" ++ + source "drivers/ata/Kconfig" + + source "drivers/axi/Kconfig" +diff --git a/drivers/Makefile b/drivers/Makefile +index eba9940231..c3bfad94ac 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -110,6 +110,7 @@ obj-y += iommu/ + obj-y += smem/ + obj-y += thermal/ + obj-$(CONFIG_TEE) += tee/ ++obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/ + obj-y += axi/ + obj-y += ufs/ + obj-$(CONFIG_W1) += w1/ +diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig +new file mode 100644 +index 0000000000..e4914b9bc7 +--- /dev/null ++++ b/drivers/firmware/arm-ffa/Kconfig +@@ -0,0 +1,30 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++config ARM_FFA_TRANSPORT ++ bool "Enable Arm Firmware Framework for Armv8-A driver" ++ depends on DM && ARM64 ++ select ARM_SMCCC ++ select LIB_UUID ++ select DEVRES ++ help ++ The Firmware Framework for Arm A-profile processors (FF-A) ++ describes interfaces (ABIs) that standardize communication ++ between the Secure World and Normal World leveraging TrustZone ++ technology. ++ ++ This driver is based on FF-A specification v1.0 and uses SMC32 ++ calling convention. ++ ++ FF-A specification: ++ ++ https://developer.arm.com/documentation/den0077/a/?lang=en ++ ++ In U-Boot FF-A design, FF-A is considered as a discoverable bus. ++ The Secure World is considered as one entity to communicate with ++ using the FF-A bus. ++ FF-A communication is handled by one device and one instance (the bus). ++ This FF-A driver takes care of all the interactions between Normal world ++ and Secure World. ++ ++ For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst ++ +diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile +new file mode 100644 +index 0000000000..043a8915be +--- /dev/null ++++ b/drivers/firmware/arm-ffa/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++# (C) Copyright 2022 ++# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com. ++ ++obj-y += arm-ffa-uclass.o core.o +diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +new file mode 100644 +index 0000000000..7d9695d289 +--- /dev/null ++++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++UCLASS_DRIVER(ffa) = { ++ .name = "ffa", ++ .id = UCLASS_FFA, ++}; +diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h +new file mode 100644 +index 0000000000..4eea7dc036 +--- /dev/null ++++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h +@@ -0,0 +1,200 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __ARM_FFA_PRV_H ++#define __ARM_FFA_PRV_H ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * This header is private. It is exclusively used by the FF-A driver ++ */ ++ ++/* FF-A core driver name */ ++#define FFA_DRV_NAME "arm_ffa" ++ ++/* FF-A driver version definitions */ ++ ++#define MAJOR_VERSION_MASK GENMASK(30, 16) ++#define MINOR_VERSION_MASK GENMASK(15, 0) ++#define GET_FFA_MAJOR_VERSION(x) \ ++ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x)))) ++#define GET_FFA_MINOR_VERSION(x) \ ++ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x)))) ++#define PACK_VERSION_INFO(major, minor) \ ++ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \ ++ FIELD_PREP(MINOR_VERSION_MASK, (minor))) ++ ++#define FFA_MAJOR_VERSION (1) ++#define FFA_MINOR_VERSION (0) ++#define FFA_VERSION_1_0 \ ++ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION) ++ ++/* Endpoint ID mask (u-boot endpoint ID) */ ++ ++#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0) ++#define GET_SELF_ENDPOINT_ID(x) \ ++ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x)))) ++ ++#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16) ++#define PREP_SELF_ENDPOINT_ID(x) \ ++ (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x))) ++ ++/* Partition endpoint ID mask (partition with which u-boot communicates with) */ ++ ++#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0) ++#define PREP_PART_ENDPOINT_ID(x) \ ++ (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x))) ++ ++/* ++ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver ++ */ ++ ++#define FFA_SMC(calling_convention, func_num) \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \ ++ ARM_SMCCC_OWNER_STANDARD, (func_num)) ++ ++#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num)) ++#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num)) ++ ++enum ffa_abis { ++ FFA_ERROR = 0x60, ++ FFA_SUCCESS = 0x61, ++ FFA_INTERRUPT = 0x62, ++ FFA_VERSION = 0x63, ++ FFA_FEATURES = 0x64, ++ FFA_RX_RELEASE = 0x65, ++ FFA_RXTX_MAP = 0x66, ++ FFA_RXTX_UNMAP = 0x67, ++ FFA_PARTITION_INFO_GET = 0x68, ++ FFA_ID_GET = 0x69, ++ FFA_RUN = 0x6D, ++ FFA_MSG_SEND_DIRECT_REQ = 0x6F, ++ FFA_MSG_SEND_DIRECT_RESP = 0x70, ++ ++ /* to be updated when adding new FFA IDs */ ++ FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/ ++ FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/ ++}; ++ ++enum ffa_abi_errcode { ++ NOT_SUPPORTED = 1, ++ INVALID_PARAMETERS, ++ NO_MEMORY, ++ BUSY, ++ INTERRUPTED, ++ DENIED, ++ RETRY, ++ ABORTED, ++ MAX_NUMBER_FFA_ERR ++}; ++ ++/* container structure and helper macros to map between an FF-A error and relevant error log */ ++struct ffa_abi_errmap { ++ char *err_str[MAX_NUMBER_FFA_ERR]; ++}; ++ ++#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1) ++#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID) ++ ++/* The FF-A SMC function definitions */ ++ ++typedef struct arm_smccc_1_2_regs ffa_value_t; ++typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res); ++ ++/* ++ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET ++ * @a1-4: 32-bit words access to the UUID data ++ * ++ */ ++struct ffa_partition_uuid { ++ u32 a1; /* w1 */ ++ u32 a2; /* w2 */ ++ u32 a3; /* w3 */ ++ u32 a4; /* w4 */ ++}; ++ ++/** ++ * enum ffa_rxtx_buf_sizes - minimum sizes supported ++ * for the RX/TX buffers ++ */ ++enum ffa_rxtx_buf_sizes { ++ RXTX_4K, ++ RXTX_64K, ++ RXTX_16K ++}; ++ ++/** ++ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses ++ * @rxbuf: virtual address of the RX buffer ++ * @txbuf: virtual address of the TX buffer ++ * @rxtx_min_pages: RX/TX buffers minimum size in pages ++ * ++ * Data structure hosting the virtual addresses of the mapped RX/TX buffers ++ * These addresses are used by the FF-A functions that use the RX/TX buffers ++ */ ++struct ffa_rxtxpair { ++ u64 rxbuf; /* virtual address */ ++ u64 txbuf; /* virtual address */ ++ size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */ ++}; ++ ++/** ++ * struct ffa_partition_desc - the secure partition descriptor ++ * @info: partition information ++ * @sp_uuid: the secure partition UUID ++ * ++ * Each partition has its descriptor containing the partitions information and the UUID ++ */ ++struct ffa_partition_desc { ++ struct ffa_partition_info info; ++ struct ffa_partition_uuid sp_uuid; ++}; ++ ++/** ++ * struct ffa_partitions - descriptors for all secure partitions ++ * @count: The number of partitions descriptors ++ * @descs The partitions descriptors table ++ * ++ * This data structure contains the partitions descriptors table ++ */ ++struct ffa_partitions { ++ u32 count; ++ struct ffa_partition_desc *descs; /* virtual address */ ++}; ++ ++/** ++ * struct ffa_prvdata - the driver private data structure ++ * ++ * @dev: The arm_ffa device under u-boot driver model ++ * @ffa_ops: The driver operations structure ++ * @fwk_version: FF-A framework version ++ * @id: u-boot endpoint ID ++ * @partitions: The partitions descriptors structure ++ * @pair: The RX/TX buffers pair ++ * @invoke_ffa_fn: The function executing the FF-A function ++ * ++ * The driver data structure hosting all resident data. ++ */ ++struct ffa_prvdata { ++ struct udevice *dev; ++ struct ffa_bus_ops ffa_ops; ++ u32 fwk_version; ++ u16 id; ++ struct ffa_partitions partitions; ++ struct ffa_rxtxpair pair; ++ invoke_ffa_fn_t invoke_ffa_fn; ++}; ++ ++/** ++ * ffa_bus_prvdata_get - bus driver private data getter ++ */ ++struct ffa_prvdata *ffa_bus_prvdata_get(void); ++ ++#endif +diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c +new file mode 100644 +index 0000000000..0b1f8e6a07 +--- /dev/null ++++ b/drivers/firmware/arm-ffa/core.c +@@ -0,0 +1,1315 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include "arm_ffa_prv.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++/** ++ * The device private data structure containing all the ++ * data read from secure world ++ */ ++struct ffa_prvdata *ffa_priv_data; ++ ++/* Error mapping declarations */ ++ ++int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = { ++ [NOT_SUPPORTED] = -EOPNOTSUPP, ++ [INVALID_PARAMETERS] = -EINVAL, ++ [NO_MEMORY] = -ENOMEM, ++ [BUSY] = -EBUSY, ++ [INTERRUPTED] = -EINTR, ++ [DENIED] = -EACCES, ++ [RETRY] = -EAGAIN, ++ [ABORTED] = -ECANCELED, ++}; ++ ++struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = { ++ [FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: A Firmware Framework implementation does not exist", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", ++ [INVALID_PARAMETERS] = ++ "INVALID_PARAMETERS: Unrecognized UUID", ++ [NO_MEMORY] = ++ "NO_MEMORY: Results cannot fit in RX buffer of the caller", ++ [BUSY] = ++ "BUSY: RX buffer of the caller is not free", ++ [DENIED] = ++ "DENIED: Callee is not in a state to handle this request", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance", ++ [INVALID_PARAMETERS] = ++ "INVALID_PARAMETERS: No buffer pair registered on behalf of the caller", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance", ++ [DENIED] = ++ "DENIED: Caller did not have ownership of the RX buffer", ++ }, ++ }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = { ++ { ++ [NOT_SUPPORTED] = ++ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", ++ [INVALID_PARAMETERS] = ++ "INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded", ++ [NO_MEMORY] = ++ "NO_MEMORY: Not enough memory", ++ [DENIED] = ++ "DENIED: Buffer pair already registered", ++ }, ++ }, ++}; ++ ++/** ++ * ffa_to_std_errno - convert FF-A error code to standard error code ++ * @ffa_errno: Error code returned by the FF-A ABI ++ * ++ * This function maps the given FF-A error code as specified ++ * by the spec to a u-boot standard error code. ++ * ++ * Return: ++ * ++ * The standard error code on success. . Otherwise, failure ++ */ ++int ffa_to_std_errno(int ffa_errno) ++{ ++ int err_idx = -ffa_errno; ++ ++ /* map the FF-A error code to the standard u-boot error code */ ++ if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR) ++ return ffa_to_std_errmap[err_idx]; ++ return -EINVAL; ++} ++ ++/** ++ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI ++ * @ffa_id: FF-A ABI ID ++ * @ffa_errno: Error code returned by the FF-A ABI ++ * ++ * This function maps the FF-A error code to the error log relevant to the ++ * selected FF-A ABI. Then the error log is printed. ++ * ++ * Return: ++ * ++ * 0 on success. . Otherwise, failure ++ */ ++int ffa_print_error_log(u32 ffa_id, int ffa_errno) ++{ ++ int err_idx = -ffa_errno, abi_idx = 0; ++ ++ /* map the FF-A error code to the corresponding error log */ ++ ++ if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR) ++ return -EINVAL; ++ ++ if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID) ++ return -EINVAL; ++ ++ abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id); ++ if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT) ++ return -EINVAL; ++ ++ if (!err_msg_map[abi_idx].err_str[err_idx]) ++ return -EINVAL; ++ ++ ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]); ++ ++ return 0; ++} ++ ++/* ++ * Driver core functions ++ */ ++ ++/** ++ * ffa_remove_device - removes the arm_ffa device ++ * @dev: the device to be removed ++ * ++ * This function makes sure the arm_ffa device is removed ++ * No need to free the kmalloced data when the device is destroyed. ++ * It's automatically done by devm management by ++ * device_remove() -> device_free() -> devres_release_probe(). ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_remove_device(struct udevice *dev) ++{ ++ int ret; ++ ++ if (!dev) { ++ ffa_err("no udevice found"); ++ return -ENODEV; ++ } ++ ++ ret = device_remove(dev, DM_REMOVE_NORMAL); ++ if (ret) { ++ ffa_err("unable to remove. err:%d\n", ret); ++ return ret; ++ } ++ ++ ffa_info("device removed and freed"); ++ ++ ret = device_unbind(dev); ++ if (ret) { ++ ffa_err("unable to unbind. err:%d\n", ret); ++ return ret; ++ } ++ ++ ffa_info("device unbound"); ++ ++ return 0; ++} ++ ++/** ++ * ffa_device_get - create, bind and probe the arm_ffa device ++ * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created ++ * successfully) ++ * ++ * This function makes sure the arm_ffa device is ++ * created, bound to this driver, probed and ready to use. ++ * Arm FF-A transport is implemented through a single U-Boot ++ * device managing the FF-A bus (arm_ffa). ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_device_get(struct udevice **pdev) ++{ ++ int ret; ++ struct udevice *dev = NULL; ++ ++ ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(), ++ &dev); ++ if (ret) ++ return ret; ++ ++ /* The FF-A bus discovery succeeds when probing is successful */ ++ ret = device_probe(dev); ++ if (ret) { ++ ffa_err("arm_ffa device probing failed"); ++ ffa_remove_device(dev); ++ return ret; ++ } ++ ++ if (pdev) ++ *pdev = dev; ++ ++ return 0; ++} ++ ++/** ++ * ffa_get_version - FFA_VERSION handler function ++ * ++ * This function implements FFA_VERSION FF-A function ++ * to get from the secure world the FF-A framework version ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_get_version(void) ++{ ++ u16 major, minor; ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0, ++ }, &res); ++ ++ ffa_errno = res.a0; ++ if (ffa_errno < 0) { ++ ffa_print_error_log(FFA_VERSION, ffa_errno); ++ return ffa_to_std_errno(ffa_errno); ++ } ++ ++ major = GET_FFA_MAJOR_VERSION(res.a0); ++ minor = GET_FFA_MINOR_VERSION(res.a0); ++ ++ ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d", ++ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); ++ ++ if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) { ++ ffa_info("Versions are compatible "); ++ ++ ffa_priv_data->fwk_version = res.a0; ++ ++ return 0; ++ } ++ ++ ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n", ++ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); ++ ++ return -EPROTONOSUPPORT; ++} ++ ++/** ++ * ffa_get_endpoint_id - FFA_ID_GET handler function ++ * ++ * This function implements FFA_ID_GET FF-A function ++ * to get from the secure world u-boot endpoint ID ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_get_endpoint_id(void) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_ID_GET), ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { ++ ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2); ++ ffa_info("endpoint ID is %u", ffa_priv_data->id); ++ ++ return 0; ++ } ++ ++ ffa_errno = res.a2; ++ ++ ffa_print_error_log(FFA_ID_GET, ffa_errno); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers ++ * @prop_field: properties field obtained from FFA_FEATURES ABI ++ * ++ * This function sets the minimum number of pages ++ * in each of the RX/TX buffers in the private data structure ++ * ++ * Return: ++ * ++ * buf_4k_pages points to the returned number of pages ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field) ++{ ++ if (!ffa_priv_data) ++ return -EINVAL; ++ ++ switch (prop_field) { ++ case RXTX_4K: ++ ffa_priv_data->pair.rxtx_min_pages = 1; ++ break; ++ case RXTX_16K: ++ ffa_priv_data->pair.rxtx_min_pages = 4; ++ break; ++ case RXTX_64K: ++ ffa_priv_data->pair.rxtx_min_pages = 16; ++ break; ++ default: ++ ffa_err("RX/TX buffer size not supported"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument ++ * ++ * This function implements FFA_FEATURES FF-A function ++ * to retrieve the FFA_RXTX_MAP features ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_get_rxtx_map_features(void) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_FEATURES), ++ .a1 = FFA_SMC_64(FFA_RXTX_MAP), ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) ++ return ffa_set_rxtx_buffers_pages_cnt(res.a2); ++ ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_FEATURES, ffa_errno); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_free_rxtx_buffers - frees the RX/TX buffers ++ * ++ * This function frees the RX/TX buffers ++ * ++ */ ++static void ffa_free_rxtx_buffers(void) ++{ ++ ffa_info("Freeing RX/TX buffers"); ++ ++ if (ffa_priv_data->pair.rxbuf) { ++ free((void *)ffa_priv_data->pair.rxbuf); ++ ffa_priv_data->pair.rxbuf = 0; ++ } ++ ++ if (ffa_priv_data->pair.txbuf) { ++ free((void *)ffa_priv_data->pair.txbuf); ++ ffa_priv_data->pair.txbuf = 0; ++ } ++} ++ ++/** ++ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers ++ * ++ * This function is used by ffa_map_rxtx_buffers to allocate ++ * the RX/TX buffers before mapping them. The allocated memory is physically ++ * contiguous since memalign ends up calling malloc which allocates ++ * contiguous memory in u-boot. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_alloc_rxtx_buffers(void) ++{ ++ u64 bytes; ++ ++ ffa_info("Using %lu 4KB page(s) for RX/TX buffers size", ++ ffa_priv_data->pair.rxtx_min_pages); ++ ++ bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K; ++ ++ /* ++ * The alignment of the RX and TX buffers must be equal ++ * to the larger translation granule size ++ */ ++ ++ ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes); ++ if (!ffa_priv_data->pair.rxbuf) { ++ ffa_err("failure to allocate RX buffer"); ++ return -ENOBUFS; ++ } ++ ++ ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf); ++ ++ ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes); ++ if (!ffa_priv_data->pair.txbuf) { ++ free((void *)ffa_priv_data->pair.rxbuf); ++ ffa_priv_data->pair.rxbuf = 0; ++ ffa_err("failure to allocate the TX buffer"); ++ return -ENOBUFS; ++ } ++ ++ ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf); ++ ++ /* ++ * make sure the buffers are cleared before use ++ */ ++ memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes); ++ memset((void *)ffa_priv_data->pair.txbuf, 0, bytes); ++ ++ return 0; ++} ++ ++/** ++ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function ++ * ++ * This function implements FFA_RXTX_MAP FF-A function ++ * to map the RX/TX buffers ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_map_rxtx_buffers(void) ++{ ++ int ret; ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ret = ffa_alloc_rxtx_buffers(); ++ if (ret) ++ return ret; ++ ++ /* ++ * we need to pass the physical addresses of the RX/TX buffers ++ * in u-boot physical/virtual mapping is 1:1 ++ * no need to convert from virtual to physical ++ */ ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_64(FFA_RXTX_MAP), ++ .a1 = ffa_priv_data->pair.txbuf, ++ .a2 = ffa_priv_data->pair.rxbuf, ++ .a3 = ffa_priv_data->pair.rxtx_min_pages, ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { ++ ffa_info("RX/TX buffers mapped"); ++ return 0; ++ } ++ ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_RXTX_MAP, ffa_errno); ++ ++ ffa_free_rxtx_buffers(); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function ++ * @dev: The arm_ffa bus device ++ * ++ * This function implements FFA_RXTX_UNMAP FF-A function ++ * to unmap the RX/TX buffers ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_unmap_rxtx_buffers(struct udevice *dev) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_RXTX_UNMAP), ++ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id), ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { ++ ffa_free_rxtx_buffers(); ++ return 0; ++ } ++ ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function ++ * ++ * This function invokes FFA_RX_RELEASE FF-A function ++ * to release the ownership of the RX buffer ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_release_rx_buffer(void) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_RX_RELEASE), ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) ++ return 0; ++ ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_RX_RELEASE, ffa_errno); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_uuid_are_identical - checks whether two given UUIDs are identical ++ * @uuid1: first UUID ++ * @uuid2: second UUID ++ * ++ * This function is used by ffa_read_partitions_info to search ++ * for a UUID in the partitions descriptors table ++ * ++ * Return: ++ * ++ * 1 when UUIDs match. Otherwise, 0 ++ */ ++bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1, ++ const struct ffa_partition_uuid *uuid2) ++{ ++ if (!uuid1 || !uuid2) ++ return 0; ++ ++ return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)); ++} ++ ++/** ++ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET ++ * and saves it in the private structure ++ * @count: The number of partitions queried ++ * @part_uuid: Pointer to the partition(s) UUID ++ * ++ * This function reads the partitions information ++ * returned by the FFA_PARTITION_INFO_GET and saves it in the private ++ * data structure. ++ * ++ * Return: ++ * ++ * The private data structure is updated with the partition(s) information ++ * 0 is returned on success. Otherwise, failure ++ */ ++static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid) ++{ ++ if (!count) { ++ ffa_err("no partition detected"); ++ return -ENODATA; ++ } ++ ++ ffa_info("Reading partitions data from the RX buffer"); ++ ++ if (!part_uuid) { ++ /* ++ * querying information of all partitions ++ */ ++ u64 buf_bytes; ++ u64 data_bytes; ++ u32 desc_idx; ++ struct ffa_partition_info *parts_info; ++ ++ data_bytes = count * sizeof(struct ffa_partition_desc); ++ ++ buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K; ++ ++ if (data_bytes > buf_bytes) { ++ ffa_err("partitions data size exceeds the RX buffer size:"); ++ ffa_err(" sizes in bytes: data %llu , RX buffer %llu ", ++ data_bytes, ++ buf_bytes); ++ ++ return -ENOMEM; ++ } ++ ++ ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes, ++ __GFP_ZERO); ++ if (!ffa_priv_data->partitions.descs) { ++ ffa_err("cannot allocate partitions data buffer"); ++ return -ENOMEM; ++ } ++ ++ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf; ++ ++ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) { ++ ffa_priv_data->partitions.descs[desc_idx].info = ++ parts_info[desc_idx]; ++ ++ ffa_info("Partition ID %x : info cached", ++ ffa_priv_data->partitions.descs[desc_idx].info.id); ++ } ++ ++ ffa_priv_data->partitions.count = count; ++ ++ ffa_info("%d partition(s) found and cached", count); ++ ++ } else { ++ u32 rx_desc_idx, cached_desc_idx; ++ struct ffa_partition_info *parts_info; ++ u8 desc_found; ++ ++ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf; ++ ++ /* ++ * search for the SP IDs read from the RX buffer ++ * in the already cached SPs. ++ * Update the UUID when ID found. ++ */ ++ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) { ++ desc_found = 0; ++ ++ /* ++ * search the current ID in the cached partitions ++ */ ++ for (cached_desc_idx = 0; ++ cached_desc_idx < ffa_priv_data->partitions.count; ++ cached_desc_idx++) { ++ /* ++ * save the UUID ++ */ ++ if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id == ++ parts_info[rx_desc_idx].id) { ++ ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid = ++ *part_uuid; ++ ++ desc_found = 1; ++ break; ++ } ++ } ++ ++ if (!desc_found) ++ return -ENODATA; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data ++ * ++ * @part_uuid: Pointer to the partition(s) UUID ++ * @pcount: Pointer to the number of partitions variable filled when querying ++ * ++ * This function executes the FFA_PARTITION_INFO_GET ++ * to query the partitions data. Then, it calls ffa_read_partitions_info ++ * to save the data in the private data structure. ++ * ++ * After reading the data the RX buffer is released using ffa_release_rx_buffer ++ * ++ * Return: ++ * ++ * When part_uuid is NULL, all partitions data are retrieved from secure world ++ * When part_uuid is non NULL, data for partitions matching the given UUID are ++ * retrieved and the number of partitions is returned ++ * 0 is returned on success. Otherwise, failure ++ */ ++static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid, ++ u32 *pcount) ++{ ++ struct ffa_partition_uuid query_uuid = {0}; ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ ++ /* ++ * If a UUID is specified. Information for one or more ++ * partitions in the system is queried. Otherwise, information ++ * for all installed partitions is queried ++ */ ++ ++ if (part_uuid) { ++ if (!pcount) ++ return -EINVAL; ++ ++ query_uuid = *part_uuid; ++ } else if (pcount) { ++ return -EINVAL; ++ } ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET), ++ .a1 = query_uuid.a1, ++ .a2 = query_uuid.a2, ++ .a3 = query_uuid.a3, ++ .a4 = query_uuid.a4, ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { ++ int ret; ++ ++ /* ++ * res.a2 contains the count of partition information descriptors ++ * populated in the RX buffer ++ */ ++ if (res.a2) { ++ ret = ffa_read_partitions_info((u32)res.a2, part_uuid); ++ if (ret) { ++ ffa_err("failed to read partition(s) data , error (%d)", ret); ++ ffa_release_rx_buffer(); ++ return -EINVAL; ++ } ++ } ++ ++ /* ++ * return the SP count (when querying using a UUID) ++ */ ++ if (pcount) ++ *pcount = (u32)res.a2; ++ ++ /* ++ * After calling FFA_PARTITION_INFO_GET the buffer ownership ++ * is assigned to the consumer (u-boot). So, we need to give ++ * the ownership back to the SPM or hypervisor ++ */ ++ ret = ffa_release_rx_buffer(); ++ ++ return ret; ++ } ++ ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno); ++ ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function ++ * ++ * The passed arguments: ++ * Mode 1: When getting from the driver the number of ++ * secure partitions: ++ * @uuid_str: pointer to the UUID string ++ * @sp_count: pointer to the variable that contains the number of partitions ++ * The variable will be set by the driver ++ * @buffer: NULL ++ * ++ * Mode 2: When requesting the driver to return the ++ * partitions information: ++ * @dev: The arm_ffa bus device ++ * @uuid_str: pointer to the UUID string ++ * @sp_count: pointer to the variable that contains the number of empty partition descriptors ++ * The variable will be read by the driver ++ * @buffer: pointer to SPs information buffer ++ * (allocated by the client and contains empty @sp_count descriptors). ++ * The buffer will be filled by the driver ++ * ++ * This function queries the secure partition data from ++ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET ++ * FF-A function to query the partition information from secure world. ++ * ++ * A client of the FF-A driver should know the UUID of the service it wants to ++ * access. It should use the UUID to request the FF-A driver to provide the ++ * partition(s) information of the service. The FF-A driver uses ++ * PARTITION_INFO_GET to obtain this information. This is implemented through ++ * ffa_get_partitions_info function. ++ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through ++ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information. ++ * They are not saved (already done). We only update the UUID in the cached area. ++ * This assumes that partitions data does not change in the secure world. ++ * Otherwise u-boot will have an outdated partition data. The benefit of caching ++ * the information in the FF-A driver is to accommodate discovery after ++ * ExitBootServices(). ++ * ++ * When invoked through a client request, ffa_get_partitions_info should be ++ * called twice. First call is to get from the driver the number of secure ++ * partitions (SPs) associated to a particular UUID. ++ * Then, the caller (client) allocates the buffer to host the SPs data and ++ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated ++ * buffer. ++ * ++ * To achieve the mechanism described above, ffa_get_partitions_info uses the ++ * following functions: ++ * ffa_read_partitions_info ++ * ffa_query_partitions_info ++ * ++ * Return: ++ * ++ * @sp_count: When pointing to the number of partitions variable, the number is ++ * set by the driver. ++ * When pointing to the partitions information buffer size, the buffer will be ++ * filled by the driver. ++ * ++ * On success 0 is returned. Otherwise, failure ++ */ ++static int ffa_get_partitions_info(struct udevice *dev, const char *uuid_str, ++ u32 *sp_count, struct ffa_partition_info *buffer) ++{ ++ /* ++ * fill_data: ++ * 0: return the SP count ++ * 1: fill SP data and return it to the caller ++ */ ++ bool fill_data = 0; ++ u32 desc_idx, client_desc_idx; ++ struct ffa_partition_uuid part_uuid = {0}; ++ u32 sp_found = 0; ++ ++ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) { ++ ffa_err("no partition installed"); ++ return -EINVAL; ++ } ++ ++ if (!uuid_str) { ++ ffa_err("no UUID provided"); ++ return -EINVAL; ++ } ++ ++ if (!sp_count) { ++ ffa_err("no size/count provided"); ++ return -EINVAL; ++ } ++ ++ if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) { ++ ffa_err("invalid UUID"); ++ return -EINVAL; ++ } ++ ++ if (!buffer) { ++ /* Mode 1: getting the number of secure partitions */ ++ ++ fill_data = 0; ++ ++ ffa_info("Preparing for checking partitions count"); ++ ++ } else if (*sp_count) { ++ /* Mode 2: retrieving the partitions information */ ++ ++ fill_data = 1; ++ ++ client_desc_idx = 0; ++ ++ ffa_info("Preparing for filling partitions info"); ++ ++ } else { ++ ffa_err("invalid function arguments provided"); ++ return -EINVAL; ++ } ++ ++ ffa_info("Searching partitions using the provided UUID"); ++ ++ /* ++ * search in the cached partitions ++ */ ++ for (desc_idx = 0; ++ desc_idx < ffa_priv_data->partitions.count; ++ desc_idx++) { ++ if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid, ++ &part_uuid)) { ++ ffa_info("Partition ID %x matches the provided UUID", ++ ffa_priv_data->partitions.descs[desc_idx].info.id); ++ ++ sp_found++; ++ ++ if (fill_data) { ++ /* ++ * trying to fill the partition info in the input buffer ++ */ ++ ++ if (client_desc_idx < *sp_count) { ++ buffer[client_desc_idx++] = ++ ffa_priv_data->partitions.descs[desc_idx].info; ++ continue; ++ } ++ ++ ffa_err("failed to fill the current descriptor client buffer full"); ++ return -ENOBUFS; ++ } ++ } ++ } ++ ++ if (!sp_found) { ++ int ret; ++ ++ ffa_info("No partition found. Querying framework ..."); ++ ++ ret = ffa_query_partitions_info(&part_uuid, &sp_found); ++ ++ if (ret == 0) { ++ if (!fill_data) { ++ *sp_count = sp_found; ++ ++ ffa_info("Number of partition(s) found matching the UUID: %d", ++ sp_found); ++ } else { ++ /* ++ * If SPs data detected, they are already in the private data ++ * structure, retry searching SP data again to return them ++ * to the caller ++ */ ++ if (sp_found) ++ ret = ffa_get_partitions_info(dev, uuid_str, sp_count, ++ buffer); ++ else ++ ret = -ENODATA; ++ } ++ } ++ ++ return ret; ++ } ++ ++ /* partition(s) found */ ++ if (!fill_data) ++ *sp_count = sp_found; ++ ++ return 0; ++} ++ ++/** ++ * ffa_cache_partitions_info - Queries and saves all secure partitions data ++ * ++ * This function invokes FFA_PARTITION_INFO_GET FF-A ++ * function to query from secure world all partitions information. ++ * ++ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument. ++ * All installed partitions information are returned. We cache them in the ++ * resident private data structure and we keep the UUID field empty ++ * (in FF-A 1.0 UUID is not provided by the partition descriptor) ++ * ++ * This function is called at the device probing level. ++ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_cache_partitions_info(void) ++{ ++ return ffa_query_partitions_info(NULL, NULL); ++} ++ ++/** ++ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function ++ * @dev: The arm_ffa bus device ++ * @dst_part_id: destination partition ID ++ * @msg: pointer to the message data preallocated by the client (in/out) ++ * @is_smc64: select 64-bit or 32-bit FF-A ABI ++ * ++ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * FF-A functions. ++ * ++ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition. ++ * The response from the secure partition is handled by reading the ++ * FFA_MSG_SEND_DIRECT_RESP arguments. ++ * ++ * The maximum size of the data that can be exchanged is 40 bytes which is ++ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0 ++ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id, ++ struct ffa_send_direct_data *msg, bool is_smc64) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ u64 req_mode, resp_mode; ++ ++ if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn) ++ return -EINVAL; ++ ++ /* No partition installed */ ++ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) ++ return -ENODEV; ++ ++ if (is_smc64) { ++ req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ); ++ resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP); ++ } else { ++ req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ); ++ resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP); ++ } ++ ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = req_mode, ++ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) | ++ PREP_PART_ENDPOINT_ID(dst_part_id), ++ .a2 = 0, ++ .a3 = msg->data0, ++ .a4 = msg->data1, ++ .a5 = msg->data2, ++ .a6 = msg->data3, ++ .a7 = msg->data4, ++ }, &res); ++ ++ while (res.a0 == FFA_SMC_32(FFA_INTERRUPT)) ++ ffa_priv_data->invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_RUN), ++ .a1 = res.a1, ++ }, &res); ++ ++ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { ++ /* Message sent with no response */ ++ return 0; ++ } ++ ++ if (res.a0 == resp_mode) { ++ /* ++ * Message sent with response ++ * extract the return data ++ */ ++ msg->data0 = res.a3; ++ msg->data1 = res.a4; ++ msg->data2 = res.a5; ++ msg->data3 = res.a6; ++ msg->data4 = res.a7; ++ ++ return 0; ++ } ++ ++ ffa_errno = res.a2; ++ return ffa_to_std_errno(ffa_errno); ++} ++ ++/** ++ * __arm_ffa_fn_smc - SMC wrapper ++ * @args: FF-A ABI arguments to be copied to Xn registers ++ * @res: FF-A ABI return data to be copied from Xn registers ++ * ++ * Calls low level SMC assembly function ++ * ++ * Return: void ++ */ ++void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) ++{ ++ arm_smccc_1_2_smc(&args, res); ++} ++ ++/** ++ * ffa_set_smc_conduit - Set the SMC conduit ++ * ++ * This function selects the SMC conduit by setting the driver invoke function ++ * to SMC assembly function ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_set_smc_conduit(void) ++{ ++ ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc; ++ ++ if (!ffa_priv_data->invoke_ffa_fn) { ++ ffa_err("failure to set the invoke function"); ++ return -EINVAL; ++ } ++ ++ ffa_info("Conduit is SMC"); ++ ++ return 0; ++} ++ ++/** ++ * ffa_set_bus_ops - Set the bus driver operations ++ * ++ * Setting the driver callbacks. ++ * ++ */ ++static void ffa_set_bus_ops(void) ++{ ++ ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info; ++ ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req; ++ ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers; ++} ++ ++/** ++ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device ++ * @dev: the arm_ffa device ++ * ++ * This function creates the main data structure embedding all the driver data. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_alloc_prvdata(struct udevice *dev) ++{ ++ if (!dev) { ++ ffa_err("no udevice found"); ++ return -ENODEV; ++ } ++ ++ /* The device is registered with the DM. Let's create the driver main data structure*/ ++ ++ ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO); ++ if (!ffa_priv_data) { ++ ffa_err("can not allocate the driver main data structure"); ++ return -ENOMEM; ++ } ++ ++ ffa_priv_data->dev = dev; ++ ++ return 0; ++} ++ ++/** ++ * ffa_probe - The driver probe function ++ * @dev: the arm_ffa device ++ * ++ * Probing is done at boot time and triggered by the uclass device discovery. ++ * At probe level the following actions are done: ++ * - setting the conduit ++ * - querying the FF-A framework version ++ * - querying from secure world the u-boot endpoint ID ++ * - querying from secure world the supported features of FFA_RXTX_MAP ++ * - mapping the RX/TX buffers ++ * - querying from secure world all the partitions information ++ * ++ * All data queried from secure world is saved in the resident private data structure. ++ * ++ * The probe will fail if either FF-A framework is not detected or the ++ * FF-A requests are not behaving correctly. This ensures that the ++ * driver is not installed and its operations are not exported to the clients. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_probe(struct udevice *dev) ++{ ++ int ret; ++ ++ ret = ffa_alloc_prvdata(dev); ++ if (ret != 0) ++ return ret; ++ ++ ffa_set_bus_ops(); ++ ++ ret = ffa_set_smc_conduit(); ++ if (ret != 0) ++ return ret; ++ ++ ret = ffa_get_version(); ++ if (ret != 0) ++ return ret; ++ ++ ret = ffa_get_endpoint_id(); ++ if (ret != 0) ++ return ret; ++ ++ ret = ffa_get_rxtx_map_features(); ++ if (ret != 0) ++ return ret; ++ ++ ret = ffa_map_rxtx_buffers(); ++ if (ret != 0) ++ return ret; ++ ++ ret = ffa_cache_partitions_info(); ++ if (ret != 0) { ++ ffa_free_rxtx_buffers(); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ffa_remove - The driver remove function ++ * @dev: the arm_ffa device ++ * When the device is about to be removed , unmap the RX/TX buffers and free the memory ++ * Return: ++ * ++ * 0 on success. ++ */ ++static int ffa_remove(struct udevice *dev) ++{ ++ ffa_info("removing the device"); ++ ++ ffa_unmap_rxtx_buffers(dev); ++ ++ if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf) ++ ffa_free_rxtx_buffers(); ++ ++ return 0; ++} ++ ++/** ++ * ffa_unbind - The driver unbind function ++ * @dev: the arm_ffa device ++ * After the device is removed and memory freed the device is unbound ++ * Return: ++ * ++ * 0 on success. ++ */ ++static int ffa_unbind(struct udevice *dev) ++{ ++ ffa_info("unbinding the device , private data already released"); ++ ++ ffa_priv_data = NULL; ++ ++ return 0; ++} ++ ++/** ++ * ffa_bus_ops_get - bus driver operations getter ++ * ++ * Return: ++ * This function returns a pointer to the driver operations structure ++ */ ++const struct ffa_bus_ops *ffa_bus_ops_get(void) ++{ ++ return &ffa_priv_data->ffa_ops; ++} ++ ++/** ++ * ffa_bus_prvdata_get - bus driver private data getter ++ * ++ * Return: ++ * This function returns a pointer to the main private data structure ++ */ ++struct ffa_prvdata *ffa_bus_prvdata_get(void) ++{ ++ return ffa_priv_data; ++} ++ ++/** ++ * ffa_bus_discover - discover FF-A bus and probe arm_ffa device ++ * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created ++ * successfully) ++ * ++ * This function makes sure the FF-A bus is discoverable. ++ * When probing succeeds FF-A discovery is done. The arm_ffa device is ready to use. ++ * ++ * When the bus was already discovered successfully the discovery will not run again. ++ * ++ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A ++ * communication. ++ * All FF-A clients should use the arm_ffa device to use the FF-A transport. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_bus_discover(struct udevice **pdev) ++{ ++ int ret = 0; ++ ++ if (!ffa_priv_data) { ++ ret = ffa_device_get(pdev); ++ ++ return ret; ++} ++ ++/** ++ * Declaring the arm_ffa driver under UCLASS_FFA ++ */ ++ ++U_BOOT_DRIVER(arm_ffa) = { ++ .name = FFA_DRV_NAME, ++ .id = UCLASS_FFA, ++ .probe = ffa_probe, ++ .remove = ffa_remove, ++ .unbind = ffa_unbind, ++}; +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +new file mode 100644 +index 0000000000..74b16174c2 +--- /dev/null ++++ b/include/arm_ffa.h +@@ -0,0 +1,97 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __ARM_FFA_H ++#define __ARM_FFA_H ++ ++#include ++ ++/* ++ * This header is public. It can be used by clients to access ++ * data structures and definitions they need ++ */ ++ ++/* ++ * Macros for displaying logs ++ */ ++ ++#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__) ++#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__) ++ ++/* ++ * struct ffa_partition_info - Partition information descriptor ++ * @id: Partition ID ++ * @exec_ctxt: Execution context count ++ * @properties: Partition properties ++ * ++ * Data structure containing information about partitions instantiated in the system ++ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET ++ */ ++struct ffa_partition_info { ++ u16 id; ++ u16 exec_ctxt; ++/* partition supports receipt of direct requests */ ++#define FFA_PARTITION_DIRECT_RECV BIT(0) ++/* partition can send direct requests. */ ++#define FFA_PARTITION_DIRECT_SEND BIT(1) ++/* partition can send and receive indirect messages. */ ++#define FFA_PARTITION_INDIRECT_MSG BIT(2) ++ u32 properties; ++}; ++ ++/* ++ * struct ffa_send_direct_data - Data structure hosting the data ++ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * @data0-4: Data read/written from/to x3-x7 registers ++ * ++ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ ++ * or read from FFA_MSG_SEND_DIRECT_RESP ++ */ ++ ++/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */ ++struct ffa_send_direct_data { ++ unsigned long data0; /* w3/x3 */ ++ unsigned long data1; /* w4/x4 */ ++ unsigned long data2; /* w5/x5 */ ++ unsigned long data3; /* w6/x6 */ ++ unsigned long data4; /* w7/x7 */ ++}; ++ ++struct udevice; ++ ++/** ++ * struct ffa_bus_ops - The driver operations structure ++ * @partition_info_get: callback for the FFA_PARTITION_INFO_GET ++ * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ ++ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP ++ * ++ * The data structure providing all the operations supported by the driver. ++ * This structure is EFI runtime resident. ++ */ ++struct ffa_bus_ops { ++ int (*partition_info_get)(struct udevice *dev, const char *uuid_str, ++ u32 *sp_count, struct ffa_partition_info *buffer); ++ int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id, ++ struct ffa_send_direct_data *msg, ++ bool is_smc64); ++ int (*rxtx_unmap)(struct udevice *dev); ++}; ++ ++/** ++ * The device driver and the Uclass driver public functions ++ */ ++ ++/** ++ * ffa_bus_ops_get - driver operations getter ++ */ ++const struct ffa_bus_ops *ffa_bus_ops_get(void); ++ ++/** ++ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device ++ */ ++int ffa_bus_discover(struct udevice **pdev); ++ ++#endif +diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h +index a432e43871..5dd698b7a9 100644 +--- a/include/dm/uclass-id.h ++++ b/include/dm/uclass-id.h +@@ -4,6 +4,9 @@ + * + * (C) Copyright 2012 + * Pavel Herrmann ++ * ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #ifndef _DM_UCLASS_ID_H +@@ -55,6 +58,7 @@ enum uclass_id { + UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */ + UCLASS_ETH, /* Ethernet device */ + UCLASS_ETH_PHY, /* Ethernet PHY device */ ++ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ + UCLASS_FIRMWARE, /* Firmware */ + UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ + UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-efi-unmap-RX-TX-buffers.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-efi-unmap-RX-TX-buffers.patch new file mode 100644 index 000000000000..f20cc28ebba1 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-efi-unmap-RX-TX-buffers.patch @@ -0,0 +1,73 @@ +From 3035651bfc0dcdfd48d28acff6efe2f29bbe9439 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 6 Oct 2022 15:04:25 +0100 +Subject: [PATCH 04/25] arm_ffa: efi: unmap RX/TX buffers + +unmap RX/TX buffers at ExitBootServices() + +Unmapping the RX/TX buffers created by u-boot is needed before EFI +runtime. + +At EFI runtime the linux kernel takes care of allocating its own RX/TX +buffers and registering them with the secure world. + +Secure world should be using the RX/TX buffers created by the kernel. +So, RX/TX buffers created by u-boot must be unmapped. + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: pass NULL device pointer to the FF-A bus operation +v7: replace debug() by log_err() +--- + lib/efi_loader/efi_boottime.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index 6f7333638a..caa64028be 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -3,6 +3,9 @@ + * EFI application boot time services + * + * Copyright (c) 2016 Alexander Graf ++ * ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #include +@@ -23,6 +26,10 @@ + #include + #include + ++#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) ++#include ++#endif ++ + DECLARE_GLOBAL_DATA_PTR; + + /* Task priority level */ +@@ -2178,6 +2185,12 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + } + ++#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) ++ /* unmap FF-A RX/TX buffers */ ++ if (ffa_bus_ops_get()->rxtx_unmap(NULL)) ++ log_err("Can't unmap FF-A RX/TX buffers\n"); ++#endif ++ + /* Patch out unsupported runtime function */ + efi_runtime_detach(); + +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-introduce-armffa-command.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-introduce-armffa-command.patch new file mode 100644 index 000000000000..44afdd56f0af --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-introduce-armffa-command.patch @@ -0,0 +1,362 @@ +From e9ec690a3f0d34631729a17c1734d66111e768e1 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 6 Jun 2022 12:46:38 +0100 +Subject: [PATCH 05/25] arm_ffa: introduce armffa command + +Provide armffa command showcasing the use of the FF-A driver + +The armffa command allows to query secure partitions data from +the secure world and exchanging messages with the partitions +using 64-bit FF-A direct messaging. + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + +* update partition_info_get() second argument to be an SP count +* pass NULL device pointer to the FF-A bus discovery and operations + +v7: + +* adapt do_ffa_dev_list() following the recent update on + uclass_first_device/uclass_next_device functions (they return void now) +* set armffa command to use 64-bit direct messaging + +v4: + +* remove pattern data in do_ffa_msg_send_direct_req + +v3: + +* use the new driver interfaces (partition_info_get, sync_send_receive) + in armffa command + +v2: + +* replace use of ffa_helper_init_device function by + ffa_helper_bus_discover + +v1: + +* introduce armffa command +--- + MAINTAINERS | 1 + + cmd/Kconfig | 10 ++ + cmd/Makefile | 2 + + cmd/armffa.c | 237 +++++++++++++++++++++++++++++++ + drivers/firmware/arm-ffa/Kconfig | 1 + + 5 files changed, 251 insertions(+) + create mode 100644 cmd/armffa.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 734fcb10c4..d50bdddea8 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -251,6 +251,7 @@ F: configs/cortina_presidio-asic-pnand_defconfig + ARM FF-A + M: Abdellatif El Khlifi + S: Maintained ++F: cmd/armffa.c + F: doc/arch/arm64.ffa.rst + F: drivers/firmware/arm-ffa/ + F: include/arm_ffa.h +diff --git a/cmd/Kconfig b/cmd/Kconfig +index 0e0be94f41..013d4c3da7 100644 +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -912,6 +912,16 @@ endmenu + + menu "Device access commands" + ++config CMD_ARMFFA ++ bool "Arm FF-A test command" ++ depends on ARM_FFA_TRANSPORT ++ help ++ Provides a test command for the Arm FF-A driver ++ supported options: ++ - Listing the partition(s) info ++ - Sending a data pattern to the specified partition ++ - Displaying the arm_ffa device info ++ + config CMD_ARMFLASH + #depends on FLASH_CFI_DRIVER + bool "armflash" +diff --git a/cmd/Makefile b/cmd/Makefile +index 6e87522b62..979c6d59df 100644 +--- a/cmd/Makefile ++++ b/cmd/Makefile +@@ -12,6 +12,8 @@ obj-y += panic.o + obj-y += version.o + + # command ++ ++obj-$(CONFIG_CMD_ARMFFA) += armffa.o + obj-$(CONFIG_CMD_ACPI) += acpi.o + obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o + obj-$(CONFIG_CMD_AES) += aes.o +diff --git a/cmd/armffa.c b/cmd/armffa.c +new file mode 100644 +index 0000000000..d2e8687bfb +--- /dev/null ++++ b/cmd/armffa.c +@@ -0,0 +1,237 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand ++ * @cmdtp: Command Table ++ * @flag: flags ++ * @argc: number of arguments ++ * @argv: arguments ++ * ++ * This function queries the secure partition information which the UUID is provided ++ * as an argument. The function uses the arm_ffa driver partition_info_get operation ++ * to retrieve the data. ++ * The input UUID string is expected to be in big endian format. ++ * ++ * Return: ++ * ++ * CMD_RET_SUCCESS: on success, otherwise failure ++ */ ++static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ u32 count = 0; ++ int ret; ++ struct ffa_partition_info *parts_info; ++ u32 info_idx; ++ ++ if (argc != 1) ++ return -EINVAL; ++ ++ /* Mode 1: getting the number of secure partitions */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, NULL); ++ if (ret != 0) { ++ ffa_err("Failure in querying partitions count (error code: %d)", ret); ++ return ret; ++ } ++ ++ if (!count) { ++ ffa_info("No secure partition found"); ++ return ret; ++ } ++ ++ /* ++ * pre-allocate a buffer to be filled by the driver ++ * with ffa_partition_info structs ++ */ ++ ++ ffa_info("Pre-allocating %d partition(s) info structures", count); ++ ++ parts_info = calloc(count, sizeof(struct ffa_partition_info)); ++ if (!parts_info) ++ return -EINVAL; ++ ++ /* ++ * ask the driver to fill the buffer with the SPs info ++ */ ++ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, parts_info); ++ if (ret != 0) { ++ ffa_err("Failure in querying partition(s) info (error code: %d)", ret); ++ free(parts_info); ++ return ret; ++ } ++ ++ /* ++ * SPs found , show the partition information ++ */ ++ for (info_idx = 0; info_idx < count ; info_idx++) { ++ ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x", ++ parts_info[info_idx].id, ++ parts_info[info_idx].exec_ctxt, ++ parts_info[info_idx].properties); ++ } ++ ++ free(parts_info); ++ ++ return 0; ++} ++ ++/** ++ * do_ffa_msg_send_direct_req - implementation of the ping subcommand ++ * @cmdtp: Command Table ++ * @flag: flags ++ * @argc: number of arguments ++ * @argv: arguments ++ * ++ * This function sends data to the secure partition which the ID is provided ++ * as an argument. The function uses the arm_ffa driver sync_send_receive operation ++ * to send data. ++ * ++ * Return: ++ * ++ * CMD_RET_SUCCESS: on success, otherwise failure ++ */ ++int do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct ffa_send_direct_data msg = { ++ .data0 = 0xaaaaaaaa, ++ .data1 = 0xbbbbbbbb, ++ .data2 = 0xcccccccc, ++ .data3 = 0xdddddddd, ++ .data4 = 0xeeeeeeee, ++ }; ++ u16 part_id; ++ int ret; ++ ++ if (argc != 1) ++ return -EINVAL; ++ ++ errno = 0; ++ part_id = strtoul(argv[0], NULL, 16); ++ ++ if (errno) { ++ ffa_err("Invalid partition ID"); ++ return -EINVAL; ++ } ++ ++ ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1); ++ if (ret == 0) { ++ u8 cnt; ++ ++ ffa_info("SP response:\n[LSB]"); ++ for (cnt = 0; ++ cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); ++ cnt++) ++ ffa_info("0x%llx", ((u64 *)&msg)[cnt]); ++ } else { ++ ffa_err("Sending direct request error (%d)", ret); ++ } ++ ++ return ret; ++} ++ ++/** ++ *do_ffa_dev_list - implementation of the devlist subcommand ++ * @cmdtp: [in] Command Table ++ * @flag: flags ++ * @argc: number of arguments ++ * @argv: arguments ++ * ++ * This function queries the devices belonging to the UCLASS_FFA ++ * class. Currently, one device is expected to show up: the arm_ffa device ++ * ++ * Return: ++ * ++ * CMD_RET_SUCCESS: on success, otherwise failure ++ */ ++int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ++{ ++ struct udevice *dev = NULL; ++ int i; ++ ++ ffa_info("arm_ffa uclass entries:"); ++ ++ for (i = 0, uclass_first_device(UCLASS_FFA, &dev); ++ dev; ++ uclass_next_device(&dev), i++) { ++ ffa_info("entry %d - instance %08x, ops %08x, plat %08x", ++ i, ++ (u32)map_to_sysmem(dev), ++ (u32)map_to_sysmem(dev->driver->ops), ++ (u32)map_to_sysmem(dev_get_plat(dev))); ++ } ++ ++ return 0; ++} ++ ++static struct cmd_tbl armffa_commands[] = { ++ U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""), ++ U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""), ++ U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""), ++}; ++ ++/** ++ * do_armffa - the armffa command main function ++ * @cmdtp: Command Table ++ * @flag: flags ++ * @argc: number of arguments ++ * @argv: arguments ++ * ++ * This function identifies which armffa subcommand to run. ++ * Then, it makes sure the arm_ffa device is probed and ++ * ready for use. ++ * Then, it runs the subcommand. ++ * ++ * Return: ++ * ++ * CMD_RET_SUCCESS: on success, otherwise failure ++ */ ++static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ++{ ++ struct cmd_tbl *armffa_cmd; ++ int ret; ++ ++ if (argc < 2) ++ return CMD_RET_USAGE; ++ ++ armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands)); ++ ++ argc -= 2; ++ argv += 2; ++ ++ if (!armffa_cmd || argc > armffa_cmd->maxargs) ++ return CMD_RET_USAGE; ++ ++ ret = ffa_bus_discover(NULL); ++ if (ret != 0) ++ return cmd_process_error(cmdtp, ret); ++ ++ if (!ffa_bus_ops_get()) ++ return -EINVAL; ++ ++ ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv); ++ ++ return cmd_process_error(armffa_cmd, ret); ++} ++ ++U_BOOT_CMD(armffa, 4, 1, do_armffa, ++ "Arm FF-A operations test command", ++ "getpart \n" ++ " - lists the partition(s) info\n" ++ "ping \n" ++ " - sends a data pattern to the specified partition\n" ++ "devlist\n" ++ " - displays the arm_ffa device info\n"); +diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig +index e4914b9bc7..be4df89d23 100644 +--- a/drivers/firmware/arm-ffa/Kconfig ++++ b/drivers/firmware/arm-ffa/Kconfig +@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT + bool "Enable Arm Firmware Framework for Armv8-A driver" + depends on DM && ARM64 + select ARM_SMCCC ++ select CMD_ARMFFA + select LIB_UUID + select DEVRES + help +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch new file mode 100644 index 000000000000..9d86dd5cdbd2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch @@ -0,0 +1,1176 @@ +From 6d28dcdc36ad87b6987c7f920e06165c74eca59d Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Nov 2022 14:44:36 +0000 +Subject: [PATCH 06/25] arm_ffa: introduce the FF-A Sandbox driver + +Provide a Sandbox driver to emulate the FF-A ABIs + +The emulated ABIs are those supported by the FF-A core driver +and according to FF-A specification v1.0. + +The Sandbox driver provides operations allowing the test +application to read the status of all the inspected ABIs +and perform functional tests based on that. + +sandbox driver supports only 64-bit direct messaging. + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: update ffa_bus_prvdata_get() to return a pointer rather than + a pointer address + +v7: state that sandbox driver supports only 64-bit direct messaging + +v4: align sandbox driver with the new FF-A driver interfaces + and new way of error handling + +v1: introduce the sandbox driver +--- + MAINTAINERS | 1 + + configs/sandbox64_defconfig | 2 + + configs/sandbox_defconfig | 2 + + doc/arch/sandbox.rst | 1 + + drivers/firmware/arm-ffa/Kconfig | 9 +- + drivers/firmware/arm-ffa/Makefile | 1 + + drivers/firmware/arm-ffa/arm_ffa_prv.h | 15 +- + drivers/firmware/arm-ffa/core.c | 22 +- + drivers/firmware/arm-ffa/sandbox.c | 659 ++++++++++++++++++ + .../firmware/arm-ffa/sandbox_arm_ffa_prv.h | 144 ++++ + include/arm_ffa.h | 2 +- + include/sandbox_arm_ffa.h | 91 +++ + lib/efi_loader/efi_boottime.c | 2 +- + 13 files changed, 938 insertions(+), 13 deletions(-) + create mode 100644 drivers/firmware/arm-ffa/sandbox.c + create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h + create mode 100644 include/sandbox_arm_ffa.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index d50bdddea8..23cebbd526 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -255,6 +255,7 @@ F: cmd/armffa.c + F: doc/arch/arm64.ffa.rst + F: drivers/firmware/arm-ffa/ + F: include/arm_ffa.h ++F: include/sandbox_arm_ffa.h + + ARM FREESCALE IMX + M: Stefano Babic +diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig +index 290d1506c2..36e6448968 100644 +--- a/configs/sandbox64_defconfig ++++ b/configs/sandbox64_defconfig +@@ -248,3 +248,5 @@ CONFIG_TEST_FDTDEC=y + CONFIG_UNIT_TEST=y + CONFIG_UT_TIME=y + CONFIG_UT_DM=y ++CONFIG_ARM_FFA_TRANSPORT=y ++CONFIG_SANDBOX_FFA=y +\ No newline at end of file +diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig +index ab5d3f19bf..8bf3848788 100644 +--- a/configs/sandbox_defconfig ++++ b/configs/sandbox_defconfig +@@ -328,3 +328,5 @@ CONFIG_TEST_FDTDEC=y + CONFIG_UNIT_TEST=y + CONFIG_UT_TIME=y + CONFIG_UT_DM=y ++CONFIG_ARM_FFA_TRANSPORT=y ++CONFIG_SANDBOX_FFA=y +\ No newline at end of file +diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst +index 068d4a3be4..5d7e1b2c48 100644 +--- a/doc/arch/sandbox.rst ++++ b/doc/arch/sandbox.rst +@@ -203,6 +203,7 @@ Supported Drivers + + U-Boot sandbox supports these emulations: + ++- Arm FF-A + - Block devices + - Chrome OS EC + - GPIO +diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig +index be4df89d23..b86f16d778 100644 +--- a/drivers/firmware/arm-ffa/Kconfig ++++ b/drivers/firmware/arm-ffa/Kconfig +@@ -2,8 +2,8 @@ + + config ARM_FFA_TRANSPORT + bool "Enable Arm Firmware Framework for Armv8-A driver" +- depends on DM && ARM64 +- select ARM_SMCCC ++ depends on DM && (ARM64 || SANDBOX) ++ select ARM_SMCCC if !SANDBOX + select CMD_ARMFFA + select LIB_UUID + select DEVRES +@@ -29,3 +29,8 @@ config ARM_FFA_TRANSPORT + + For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst + ++config SANDBOX_FFA ++ bool "FF-A Sandbox driver" ++ depends on ARM_FFA_TRANSPORT && SANDBOX ++ help ++ This emulates the FF-A handling under Sandbox and allows to test the FF-A driver +diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile +index 043a8915be..0d21d6b47a 100644 +--- a/drivers/firmware/arm-ffa/Makefile ++++ b/drivers/firmware/arm-ffa/Makefile +@@ -4,3 +4,4 @@ + # Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com. + + obj-y += arm-ffa-uclass.o core.o ++obj-$(CONFIG_SANDBOX_FFA) += sandbox.o +diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h +index 4eea7dc036..bbc8b87069 100644 +--- a/drivers/firmware/arm-ffa/arm_ffa_prv.h ++++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h +@@ -19,6 +19,16 @@ + /* FF-A core driver name */ + #define FFA_DRV_NAME "arm_ffa" + ++/* The FF-A SMC function definitions */ ++ ++#if CONFIG_IS_ENABLED(SANDBOX_FFA) ++#include "sandbox_arm_ffa.h" ++#else ++typedef struct arm_smccc_1_2_regs ffa_value_t; ++#endif ++ ++typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res); ++ + /* FF-A driver version definitions */ + + #define MAJOR_VERSION_MASK GENMASK(30, 16) +@@ -103,11 +113,6 @@ struct ffa_abi_errmap { + #define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1) + #define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID) + +-/* The FF-A SMC function definitions */ +- +-typedef struct arm_smccc_1_2_regs ffa_value_t; +-typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res); +- + /* + * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET + * @a1-4: 32-bit words access to the UUID data +diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c +index 0b1f8e6a07..560603b28b 100644 +--- a/drivers/firmware/arm-ffa/core.c ++++ b/drivers/firmware/arm-ffa/core.c +@@ -1072,6 +1072,7 @@ static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id, + return ffa_to_std_errno(ffa_errno); + } + ++#if !CONFIG_IS_ENABLED(SANDBOX_FFA) + /** + * __arm_ffa_fn_smc - SMC wrapper + * @args: FF-A ABI arguments to be copied to Xn registers +@@ -1085,6 +1086,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) + { + arm_smccc_1_2_smc(&args, res); + } ++#endif + + /** + * ffa_set_smc_conduit - Set the SMC conduit +@@ -1098,7 +1100,12 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) + */ + static int ffa_set_smc_conduit(void) + { +- ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc; ++#if CONFIG_IS_ENABLED(SANDBOX_FFA) ++ ffa_priv_data->invoke_ffa_fn = sandbox_arm_ffa_smccc_smc; ++ ffa_info("Using SMC emulation"); ++#else ++ ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc; ++#endif + + if (!ffa_priv_data->invoke_ffa_fn) { + ffa_err("failure to set the invoke function"); +@@ -1275,17 +1282,18 @@ struct ffa_prvdata *ffa_bus_prvdata_get(void) + } + + /** +- * ffa_bus_discover - discover FF-A bus and probe arm_ffa device ++ * ffa_bus_discover - discover FF-A bus and probe arm_ffa and sandbox_arm_ffa devices + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created + * successfully) + * + * This function makes sure the FF-A bus is discoverable. +- * When probing succeeds FF-A discovery is done. The arm_ffa device is ready to use. ++ * When probing succeeds FF-A discovery is done. The arm_ffa and sandbox_arm_ffa devices ++ * are ready to use. + * + * When the bus was already discovered successfully the discovery will not run again. + * + * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A +- * communication. ++ * communication. In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver. + * All FF-A clients should use the arm_ffa device to use the FF-A transport. + * + * Return: +@@ -1299,6 +1307,12 @@ int ffa_bus_discover(struct udevice **pdev) + if (!ffa_priv_data) { + ret = ffa_device_get(pdev); + ++#if CONFIG_IS_ENABLED(SANDBOX_FFA) ++ if (ret == 0) ++ ret = sandbox_ffa_device_get(); ++#endif ++ } ++ + return ret; + } + +diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c +new file mode 100644 +index 0000000000..16f1ca926e +--- /dev/null ++++ b/drivers/firmware/arm-ffa/sandbox.c +@@ -0,0 +1,659 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include "sandbox_arm_ffa_prv.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++/** ++ * The device private data structure containing all the emulated secure world data ++ */ ++static struct sandbox_ffa_prvdata sandbox_ffa_priv_data = {0}; ++ ++/* The partitions (SPs) table */ ++static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = { ++ { ++ .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 }, ++ .sp_uuid = { ++ .a1 = SANDBOX_SERVICE1_UUID_A1, ++ .a2 = SANDBOX_SERVICE1_UUID_A2, ++ .a3 = SANDBOX_SERVICE1_UUID_A3, ++ .a4 = SANDBOX_SERVICE1_UUID_A4, ++ } ++ }, ++ { ++ .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 }, ++ .sp_uuid = { ++ .a1 = SANDBOX_SERVICE2_UUID_A1, ++ .a2 = SANDBOX_SERVICE2_UUID_A2, ++ .a3 = SANDBOX_SERVICE2_UUID_A3, ++ .a4 = SANDBOX_SERVICE2_UUID_A4, ++ } ++ }, ++ { ++ .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 }, ++ .sp_uuid = { ++ .a1 = SANDBOX_SERVICE1_UUID_A1, ++ .a2 = SANDBOX_SERVICE1_UUID_A2, ++ .a3 = SANDBOX_SERVICE1_UUID_A3, ++ .a4 = SANDBOX_SERVICE1_UUID_A4, ++ } ++ }, ++ { ++ .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 }, ++ .sp_uuid = { ++ .a1 = SANDBOX_SERVICE2_UUID_A1, ++ .a2 = SANDBOX_SERVICE2_UUID_A2, ++ .a3 = SANDBOX_SERVICE2_UUID_A3, ++ .a4 = SANDBOX_SERVICE2_UUID_A4, ++ } ++ } ++ ++}; ++ ++/* ++ * Driver functions ++ */ ++ ++/** ++ * sandbox_ffa_get_device - probes the sandbox_arm_ffa device ++ * ++ * This function makes sure the sandbox_arm_ffa device is probed ++ * This function makes sure the sandbox_arm_ffa device is ++ * created, bound to this driver, probed and ready to use. ++ * ++ * sandbox_arm_ffa depends on arm_ffa device. This dependency is ++ * handled by ffa_bus_discover function. arm_ffa is probed first then ++ * sandbox_arm_ffa. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int sandbox_ffa_device_get(void) ++{ ++ int ret; ++ ++ if (sandbox_ffa_priv_data.dev) ++ return 0; ++ ++ ret = device_bind(dm_root(), ++ DM_DRIVER_GET(sandbox_arm_ffa), ++ FFA_SANDBOX_DRV_NAME, ++ NULL, ++ ofnode_null(), ++ &sandbox_ffa_priv_data.dev); ++ if (ret) { ++ sandbox_ffa_priv_data.dev = NULL; ++ return ret; ++ } ++ ++ ret = device_probe(sandbox_ffa_priv_data.dev); ++ if (ret) { ++ ffa_err("[Sandbox] can not probe the device"); ++ device_unbind(sandbox_ffa_priv_data.dev); ++ sandbox_ffa_priv_data.dev = NULL; ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_version - Emulated FFA_VERSION handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_VERSION FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_version) ++{ ++ sandbox_ffa_priv_data.fwk_version = FFA_VERSION_1_0; ++ res->a0 = sandbox_ffa_priv_data.fwk_version; ++ ++ /* x1-x7 MBZ */ ++ memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_id_get - Emulated FFA_ID_GET handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_ID_GET FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_id_get) ++{ ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a1 = 0; ++ ++ sandbox_ffa_priv_data.id = NS_PHYS_ENDPOINT_ID; ++ res->a2 = sandbox_ffa_priv_data.id; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_features - Emulated FFA_FEATURES handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_FEATURES FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_features) ++{ ++ if (pargs->a1 == FFA_SMC_64(FFA_RXTX_MAP)) { ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = RXTX_BUFFERS_MIN_SIZE; ++ res->a3 = 0; ++ /* x4-x7 MBZ */ ++ memset(FFA_X4X7_MBZ_REG_START, ++ 0, FFA_X4X7_MBZ_CNT * sizeof(unsigned long)); ++ } else { ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a2 = FFA_ERR_STAT_NOT_SUPPORTED; ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, ++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ffa_err("[Sandbox] FF-A interface 0x%lx not implemented", pargs->a1); ++ } ++ ++ res->a1 = 0; ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_partition_info_get - Emulated FFA_PARTITION_INFO_GET handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_PARTITION_INFO_GET FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_partition_info_get) ++{ ++ struct ffa_partition_info *rxbuf_desc_info = NULL; ++ u32 descs_cnt; ++ u32 descs_size_bytes; ++ ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ ++ if (!sandbox_ffa_priv_data.pair.rxbuf) { ++ res->a2 = FFA_ERR_STAT_DENIED; ++ goto cleanup; ++ } ++ ++ if (sandbox_ffa_priv_data.pair_info.rxbuf_owned) { ++ res->a2 = FFA_ERR_STAT_BUSY; ++ goto cleanup; ++ } ++ ++ if (!sandbox_ffa_priv_data.partitions.descs) { ++ sandbox_ffa_priv_data.partitions.descs = sandbox_partitions; ++ sandbox_ffa_priv_data.partitions.count = SANDBOX_PARTITIONS_CNT; ++ } ++ ++ descs_size_bytes = SANDBOX_PARTITIONS_CNT * sizeof(struct ffa_partition_desc); ++ ++ /* Abort if the RX buffer size is smaller than the descriptors buffer size */ ++ if ((sandbox_ffa_priv_data.pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) { ++ res->a2 = FFA_ERR_STAT_NO_MEMORY; ++ goto cleanup; ++ } ++ ++ rxbuf_desc_info = (struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf; ++ ++ /* No UUID specified. Return the information of all partitions */ ++ if (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->a4) { ++ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) ++ *(rxbuf_desc_info++) = ++ sandbox_ffa_priv_data.partitions.descs[descs_cnt].info; ++ ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = SANDBOX_PARTITIONS_CNT; ++ /* transfer ownership to the consumer: the non secure world */ ++ sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1; ++ ++ goto cleanup; ++ } ++ ++ /* ++ * A UUID is specified. Return the information of all partitions matching ++ * the UUID ++ */ ++ ++ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) ++ if (pargs->a1 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a1 && ++ pargs->a2 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a2 && ++ pargs->a3 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a3 && ++ pargs->a4 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a4) { ++ *(rxbuf_desc_info++) = ++ sandbox_ffa_priv_data.partitions.descs[descs_cnt].info; ++ } ++ ++ if (rxbuf_desc_info != ((struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf)) { ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ /* store the partitions count */ ++ res->a2 = (unsigned long) ++ (rxbuf_desc_info - (struct ffa_partition_info *) ++ sandbox_ffa_priv_data.pair.rxbuf); ++ ++ /* transfer ownership to the consumer: the non secure world */ ++ sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1; ++ } else { ++ /* Unrecognized UUID */ ++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; ++ } ++ ++cleanup: ++ ++ ffa_err("[Sandbox] FFA_PARTITION_INFO_GET (%ld)", res->a2); ++ ++ res->a1 = 0; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_rxtx_map - Emulated FFA_RXTX_MAP handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_RXTX_MAP FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_rxtx_map) ++{ ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ ++ if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) { ++ res->a2 = FFA_ERR_STAT_DENIED; ++ goto feedback; ++ } ++ ++ if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) { ++ sandbox_ffa_priv_data.pair.txbuf = pargs->a1; ++ sandbox_ffa_priv_data.pair.rxbuf = pargs->a2; ++ sandbox_ffa_priv_data.pair_info.rxtx_buf_size = pargs->a3; ++ sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 1; ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = 0; ++ goto feedback; ++ } ++ ++ if (!pargs->a1 || !pargs->a2) ++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; ++ else ++ res->a2 = FFA_ERR_STAT_NO_MEMORY; ++ ++ ffa_err("[Sandbox] error in FFA_RXTX_MAP arguments (%d)", (int)res->a2); ++ ++feedback: ++ ++ res->a1 = 0; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, ++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_rxtx_unmap - Emulated FFA_RXTX_UNMAP handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_RXTX_UNMAP FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_rxtx_unmap) ++{ ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; ++ ++ if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != sandbox_ffa_priv_data.id) ++ goto feedback; ++ ++ if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) { ++ sandbox_ffa_priv_data.pair.txbuf = 0; ++ sandbox_ffa_priv_data.pair.rxbuf = 0; ++ sandbox_ffa_priv_data.pair_info.rxtx_buf_size = 0; ++ sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 0; ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = 0; ++ goto feedback; ++ } ++ ++ ffa_err("[Sandbox] No buffer pair registered on behalf of the caller"); ++ ++feedback: ++ ++ res->a1 = 0; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, ++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_rx_release - Emulated FFA_RX_RELEASE handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_RX_RELEASE FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_rx_release) ++{ ++ if (!sandbox_ffa_priv_data.pair_info.rxbuf_owned) { ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a2 = FFA_ERR_STAT_DENIED; ++ } else { ++ sandbox_ffa_priv_data.pair_info.rxbuf_owned = 0; ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = 0; ++ } ++ ++ res->a1 = 0; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, ++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_sp_valid - Checks SP validity ++ * @part_id: partition ID to check ++ * ++ * This is the function searches the input ID in the descriptors table. ++ * ++ * Return: ++ * ++ * 1 on success (Partition found). Otherwise, failure ++ */ ++static int sandbox_ffa_sp_valid(u16 part_id) ++{ ++ u32 descs_cnt; ++ ++ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) ++ if (sandbox_ffa_priv_data.partitions.descs[descs_cnt].info.id == part_id) ++ return 1; ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_msg_send_direct_req - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function ++ * @{a0-a7} , res: The SMC call arguments and return structure. ++ * ++ * This is the function that emulates FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * FF-A functions. Only SMC 64-bit is supported in Sandbox. ++ * ++ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not supported. ++ * In case of success FFA_MSG_SEND_DIRECT_RESP is returned with default pattern data (0xff). ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req) ++{ ++ u16 part_id; ++ ++ part_id = GET_DST_SP_ID(pargs->a1); ++ ++ if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != sandbox_ffa_priv_data.id) || ++ !sandbox_ffa_sp_valid(part_id) || ++ pargs->a2) { ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a1 = 0; ++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; ++ ++ /* x3-x7 MBZ */ ++ memset(FFA_X3_MBZ_REG_START, ++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); ++ ++ return 0; ++ } ++ ++ res->a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP); ++ ++ res->a1 = PREP_SRC_SP_ID(part_id) | ++ PREP_NS_PHYS_ENDPOINT_ID(sandbox_ffa_priv_data.id); ++ ++ res->a2 = 0; ++ ++ /* ++ * return 0xff bytes as a response ++ */ ++ res->a3 = 0xffffffffffffffff; ++ res->a4 = 0xffffffffffffffff; ++ res->a5 = 0xffffffffffffffff; ++ res->a6 = 0xffffffffffffffff; ++ res->a7 = 0xffffffffffffffff; ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_get_prv_data - Returns the pointer to FF-A core pivate data ++ * @func_data: Pointer to the FF-A function arguments container structure ++ * ++ * This is the handler that returns the address of the FF-A core pivate data. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_get_prv_data(struct ffa_sandbox_data *func_data) ++{ ++ if (!func_data) ++ return -EINVAL; ++ ++ if (!func_data->data0 || func_data->data0_size != sizeof(struct ffa_prvdata *)) ++ return -EINVAL; ++ ++ if (!func_data->data1 || func_data->data1_size != sizeof(struct sandbox_ffa_prvdata *)) ++ return -EINVAL; ++ ++ *((struct ffa_prvdata **)func_data->data0) = ffa_bus_prvdata_get(); ++ *((struct sandbox_ffa_prvdata **)func_data->data1) = &sandbox_ffa_priv_data; ++ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_get_rxbuf_flags - Reading the mapping/ownership flags ++ * @queried_func_id: The FF-A function to be queried ++ * @func_data: Pointer to the FF-A function arguments container structure ++ * ++ * This is the handler that queries the status flags of the following emulated ABIs: ++ * FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_get_rxbuf_flags(u32 queried_func_id, struct ffa_sandbox_data *func_data) ++{ ++ if (!func_data) ++ return -EINVAL; ++ ++ if (!func_data->data0 || func_data->data0_size != sizeof(u8)) ++ return -EINVAL; ++ ++ switch (queried_func_id) { ++ case FFA_RXTX_MAP: ++ case FFA_RXTX_UNMAP: ++ *((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_mapped; ++ return 0; ++ case FFA_RX_RELEASE: ++ *((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_owned; ++ return 0; ++ default: ++ ffa_err("[Sandbox] The querried FF-A interface flag (%d) undefined", ++ queried_func_id); ++ return -EINVAL; ++ } ++} ++ ++/** ++ * sandbox_ffa_query_core_state - The driver dispatcher function ++ * @queried_func_id: The FF-A function to be queried ++ * @func_data: Pointer to the FF-A function arguments container structure ++ * ++ * Queries the status of FF-A ABI specified in the input argument. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int sandbox_ffa_query_core_state(u32 queried_func_id, struct ffa_sandbox_data *func_data) ++{ ++ switch (queried_func_id) { ++ case FFA_VERSION: ++ case FFA_ID_GET: ++ case FFA_FEATURES: ++ return sandbox_ffa_get_prv_data(func_data); ++ case FFA_RXTX_MAP: ++ case FFA_RXTX_UNMAP: ++ case FFA_RX_RELEASE: ++ return sandbox_ffa_get_rxbuf_flags(queried_func_id, func_data); ++ default: ++ ffa_err("[Sandbox] The querried FF-A interface (%d) undefined", queried_func_id); ++ return -EINVAL; ++ } ++} ++ ++/** ++ * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation ++ * @args: the SMC call arguments ++ * @res: the SMC call returned data ++ * ++ * Sandbox driver emulates the FF-A ABIs SMC call using this function. ++ * The emulated FF-A ABI is identified and invoked. ++ * FF-A emulation is based on the FF-A specification 1.0 ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure. ++ * FF-A protocol error codes are returned using the registers arguments as described ++ * by the specification ++ */ ++void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res) ++{ ++ int ret = 0; ++ ++ switch (args.a0) { ++ case FFA_SMC_32(FFA_VERSION): ++ ret = sandbox_ffa_version(&args, res); ++ break; ++ case FFA_SMC_32(FFA_PARTITION_INFO_GET): ++ ret = sandbox_ffa_partition_info_get(&args, res); ++ break; ++ case FFA_SMC_32(FFA_RXTX_UNMAP): ++ ret = sandbox_ffa_rxtx_unmap(&args, res); ++ break; ++ case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ): ++ ret = sandbox_ffa_msg_send_direct_req(&args, res); ++ break; ++ case FFA_SMC_32(FFA_ID_GET): ++ ret = sandbox_ffa_id_get(&args, res); ++ break; ++ case FFA_SMC_32(FFA_FEATURES): ++ ret = sandbox_ffa_features(&args, res); ++ break; ++ case FFA_SMC_64(FFA_RXTX_MAP): ++ ret = sandbox_ffa_rxtx_map(&args, res); ++ break; ++ case FFA_SMC_32(FFA_RX_RELEASE): ++ ret = sandbox_ffa_rx_release(&args, res); ++ break; ++ default: ++ ffa_err("[Sandbox] Undefined FF-A interface (0x%lx)", args.a0); ++ } ++ ++ if (ret != 0) ++ ffa_err("[Sandbox] FF-A ABI internal failure (%d)", ret); ++} ++ ++/** ++ * sandbox_ffa_probe - The driver probe function ++ * @dev: the sandbox_arm_ffa device ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_probe(struct udevice *dev) ++{ ++ return 0; ++} ++ ++/** ++ * sandbox_ffa_remove - The driver remove function ++ * @dev: the sandbox_arm_ffa device ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_remove(struct udevice *dev) ++{ ++ ffa_info("[Sandbox] removing the device"); ++ memset(&sandbox_ffa_priv_data, 0, sizeof(sandbox_ffa_priv_data)); ++ return 0; ++} ++ ++/** ++ * Declaring the sandbox_arm_ffa driver under UCLASS_FFA ++ */ ++U_BOOT_DRIVER(sandbox_arm_ffa) = { ++ .name = FFA_SANDBOX_DRV_NAME, ++ .id = UCLASS_FFA, ++ .probe = sandbox_ffa_probe, ++ .remove = sandbox_ffa_remove, ++}; +diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h +new file mode 100644 +index 0000000000..4db57f5092 +--- /dev/null ++++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __SANDBOX_ARM_FFA_PRV_H ++#define __SANDBOX_ARM_FFA_PRV_H ++ ++#include "arm_ffa_prv.h" ++#include ++ ++/* ++ * This header is private. It is exclusively used by the Sandbox FF-A driver ++ */ ++ ++/* FF-A core driver name */ ++#define FFA_SANDBOX_DRV_NAME "sandbox_arm_ffa" ++ ++/* FF-A ABIs internal error codes (as defined by the spec) */ ++ ++#define FFA_ERR_STAT_NOT_SUPPORTED -1 ++#define FFA_ERR_STAT_INVALID_PARAMETERS -2 ++#define FFA_ERR_STAT_NO_MEMORY -3 ++#define FFA_ERR_STAT_BUSY -4 ++#define FFA_ERR_STAT_DENIED -6 ++ ++/* Providing Arm SMCCC declarations to sandbox */ ++ ++#define ARM_SMCCC_FAST_CALL 1UL ++#define ARM_SMCCC_OWNER_STANDARD 4 ++#define ARM_SMCCC_SMC_32 0 ++#define ARM_SMCCC_SMC_64 1 ++#define ARM_SMCCC_TYPE_SHIFT 31 ++#define ARM_SMCCC_CALL_CONV_SHIFT 30 ++#define ARM_SMCCC_OWNER_MASK 0x3F ++#define ARM_SMCCC_OWNER_SHIFT 24 ++#define ARM_SMCCC_FUNC_MASK 0xFFFF ++ ++#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ ++ (((type) << ARM_SMCCC_TYPE_SHIFT) | \ ++ ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ ++ (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ ++ ((func_num) & ARM_SMCCC_FUNC_MASK)) ++ ++/* Non-secure physical FF-A instance */ ++#define NS_PHYS_ENDPOINT_ID (0) ++ ++#define GET_NS_PHYS_ENDPOINT_ID_MASK GENMASK(31, 16) ++#define GET_NS_PHYS_ENDPOINT_ID(x) \ ++ ((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x)))) ++ ++/* Helper macro for reading the destination partition ID */ ++#define GET_DST_SP_ID_MASK GENMASK(15, 0) ++#define GET_DST_SP_ID(x) \ ++ ((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x)))) ++ ++/* Helper macro for setting the source partition ID */ ++#define PREP_SRC_SP_ID_MASK GENMASK(31, 16) ++#define PREP_SRC_SP_ID(x) \ ++ (FIELD_PREP(PREP_SRC_SP_ID_MASK, (x))) ++ ++/* Helper macro for setting the destination endpoint ID */ ++#define PREP_NS_PHYS_ENDPOINT_ID_MASK GENMASK(15, 0) ++#define PREP_NS_PHYS_ENDPOINT_ID(x) \ ++ (FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x))) ++ ++/* RX/TX buffers minimum size */ ++#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K) ++#define RXTX_BUFFERS_MIN_PAGES (1) ++ ++/* MBZ registers info */ ++ ++/* x1-x7 MBZ */ ++#define FFA_X1X7_MBZ_CNT (7) ++#define FFA_X1X7_MBZ_REG_START (&res->a1) ++ ++/* x4-x7 MBZ */ ++#define FFA_X4X7_MBZ_CNT (4) ++#define FFA_X4X7_MBZ_REG_START (&res->a4) ++ ++/* x3-x7 MBZ */ ++#define FFA_X3X7_MBZ_CNT (5) ++#define FFA_X3_MBZ_REG_START (&res->a3) ++ ++/* secure partitions count */ ++#define SANDBOX_PARTITIONS_CNT (4) ++ ++/* service 1 UUID binary data (little-endian format) */ ++#define SANDBOX_SERVICE1_UUID_A1 0xed32d533 ++#define SANDBOX_SERVICE1_UUID_A2 0x99e64209 ++#define SANDBOX_SERVICE1_UUID_A3 0x9cc02d72 ++#define SANDBOX_SERVICE1_UUID_A4 0xcdd998a7 ++ ++/* service 2 UUID binary data (little-endian format) */ ++#define SANDBOX_SERVICE2_UUID_A1 0xed32d544 ++#define SANDBOX_SERVICE2_UUID_A2 0x99e64209 ++#define SANDBOX_SERVICE2_UUID_A3 0x9cc02d72 ++#define SANDBOX_SERVICE2_UUID_A4 0xcdd998a7 ++ ++/** ++ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags ++ * @rxbuf_owned: RX buffer ownership flag (the owner is non secure world: the consumer) ++ * @rxbuf_mapped: RX buffer mapping flag ++ * @txbuf_owned TX buffer ownership flag ++ * @txbuf_mapped: TX buffer mapping flag ++ * @rxtx_buf_size: RX/TX buffers size as set by the FF-A core driver ++ * ++ * Data structure hosting the ownership/mapping flags of the RX/TX buffers ++ * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0. ++ */ ++struct ffa_rxtxpair_info { ++ u8 rxbuf_owned; ++ u8 rxbuf_mapped; ++ u8 txbuf_owned; ++ u8 txbuf_mapped; ++ u32 rxtx_buf_size; ++}; ++ ++/** ++ * struct sandbox_ffa_prvdata - the driver private data structure ++ * ++ * @dev: The arm_ffa device under u-boot driver model ++ * @fwk_version: FF-A framework version ++ * @id: u-boot endpoint ID ++ * @partitions: The partitions descriptors structure ++ * @pair: The RX/TX buffers pair ++ * @pair_info: The RX/TX buffers pair flags and size ++ * @conduit: The selected conduit ++ * ++ * The driver data structure hosting all the emulated secure world data. ++ */ ++struct sandbox_ffa_prvdata { ++ struct udevice *dev; ++ u32 fwk_version; ++ u16 id; ++ struct ffa_partitions partitions; ++ struct ffa_rxtxpair pair; ++ struct ffa_rxtxpair_info pair_info; ++}; ++ ++#define SANDBOX_SMC_FFA_ABI(ffabi) static int sandbox_##ffabi(ffa_value_t *pargs, ffa_value_t *res) ++ ++#endif +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +index 74b16174c2..b88904fe50 100644 +--- a/include/arm_ffa.h ++++ b/include/arm_ffa.h +@@ -90,7 +90,7 @@ struct ffa_bus_ops { + const struct ffa_bus_ops *ffa_bus_ops_get(void); + + /** +- * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device ++ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa and sandbox_arm_ffa devices + */ + int ffa_bus_discover(struct udevice **pdev); + +diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h +new file mode 100644 +index 0000000000..d5df16f282 +--- /dev/null ++++ b/include/sandbox_arm_ffa.h +@@ -0,0 +1,91 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __SANDBOX_ARM_FFA_H ++#define __SANDBOX_ARM_FFA_H ++ ++#include ++ ++/** ++ * struct sandbox_smccc_1_2_regs - Arguments for or Results from emulated SMC call ++ * @a0-a17 argument values from registers 0 to 17 ++ */ ++struct sandbox_smccc_1_2_regs { ++ unsigned long a0; ++ unsigned long a1; ++ unsigned long a2; ++ unsigned long a3; ++ unsigned long a4; ++ unsigned long a5; ++ unsigned long a6; ++ unsigned long a7; ++ unsigned long a8; ++ unsigned long a9; ++ unsigned long a10; ++ unsigned long a11; ++ unsigned long a12; ++ unsigned long a13; ++ unsigned long a14; ++ unsigned long a15; ++ unsigned long a16; ++ unsigned long a17; ++}; ++ ++typedef struct sandbox_smccc_1_2_regs ffa_value_t; ++ ++/* UUIDs of services supported by the sandbox driver */ ++#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" ++#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0" ++#define SANDBOX_SP1_ID 0x1245 ++#define SANDBOX_SP2_ID 0x9836 ++#define SANDBOX_SP3_ID 0x6452 ++#define SANDBOX_SP4_ID 0x7814 ++ ++/* invalid service UUID (no matching SP) */ ++#define SANDBOX_SERVICE3_UUID "55d532ed-0942-e699-722d-c09ca798d9cd" ++ ++/* invalid service UUID (invalid UUID string format) */ ++#define SANDBOX_SERVICE4_UUID "32ed-0942-e699-722d-c09ca798d9cd" ++ ++#define SANDBOX_SP_COUNT_PER_VALID_SERVICE 2 ++ ++/** ++ * struct ffa_sandbox_data - generic data structure used to exchange ++ * data between test cases and the sandbox driver ++ * @data0_size: size of the first argument ++ * @data0: pointer to the first argument ++ * @data1_size>: size of the second argument ++ * @data1: pointer to the second argument ++ * ++ * Using this structure sandbox test cases can pass various types of data with different sizes. ++ */ ++struct ffa_sandbox_data { ++ u32 data0_size; /* size of the first argument */ ++ void *data0; /* pointer to the first argument */ ++ u32 data1_size; /* size of the second argument */ ++ void *data1; /* pointer to the second argument */ ++}; ++ ++/** ++ * The sandbox driver public functions ++ */ ++ ++/** ++ * sandbox_ffa_query_core_state - Queries the status of FF-A ABIs ++ */ ++int sandbox_ffa_query_core_state(u32 queried_func_id, struct ffa_sandbox_data *func_data); ++ ++/** ++ * sandbox_ffa_get_device - create, bind and probe the sandbox_arm_ffa device ++ */ ++int sandbox_ffa_device_get(void); ++ ++/** ++ * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation ++ */ ++void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res); ++ ++#endif +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index caa64028be..1099ccc800 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -2185,7 +2185,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + } + +-#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) ++#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) && !CONFIG_IS_ENABLED(SANDBOX_FFA) + /* unmap FF-A RX/TX buffers */ + if (ffa_bus_ops_get()->rxtx_unmap(NULL)) + log_err("Can't unmap FF-A RX/TX buffers\n"); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-introduce-Sandbox-test-cases-for-UCLASS_FFA.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-introduce-Sandbox-test-cases-for-UCLASS_FFA.patch new file mode 100644 index 000000000000..62f6e4341fb2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-introduce-Sandbox-test-cases-for-UCLASS_FFA.patch @@ -0,0 +1,471 @@ +From de26427c9f9b450ab4a18352fa51f46b3b585bc1 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 6 Jun 2022 17:26:06 +0100 +Subject: [PATCH 07/25] arm_ffa: introduce Sandbox test cases for UCLASS_FFA + +Add functional test cases for the FF-A core driver + +These tests rely on the FF-A Sandbox driver which helps in + inspecting the FF-A core driver. + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + + * update partition_info_get() second argument to be an SP count + * pass NULL device pointer to the FF-A bus discovery and operations + +v7: set the tests to use 64-bit direct messaging + +v4: align sandbox tests with the new FF-A driver interfaces + and new way of error handling + +v1: introduce sandbox tests +--- + MAINTAINERS | 1 + + test/dm/Makefile | 2 + + test/dm/ffa.c | 392 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 395 insertions(+) + create mode 100644 test/dm/ffa.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 23cebbd526..e682db8d8f 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -256,6 +256,7 @@ F: doc/arch/arm64.ffa.rst + F: drivers/firmware/arm-ffa/ + F: include/arm_ffa.h + F: include/sandbox_arm_ffa.h ++F: test/dm/ffa.c + + ARM FREESCALE IMX + M: Stefano Babic +diff --git a/test/dm/Makefile b/test/dm/Makefile +index 7543df8823..e5a791768e 100644 +--- a/test/dm/Makefile ++++ b/test/dm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0+ + # + # Copyright (c) 2013 Google, Inc ++# (C) Copyright 2022 ARM Limited + + obj-$(CONFIG_UT_DM) += test-dm.o + +@@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o + obj-$(CONFIG_ACPI_PMC) += pmc.o + obj-$(CONFIG_DM_PMIC) += pmic.o + obj-$(CONFIG_DM_PWM) += pwm.o ++obj-$(CONFIG_SANDBOX_FFA) += ffa.o + obj-$(CONFIG_QFW) += qfw.o + obj-$(CONFIG_RAM) += ram.o + obj-y += regmap.o +diff --git a/test/dm/ffa.c b/test/dm/ffa.c +new file mode 100644 +index 0000000000..128d8626a7 +--- /dev/null ++++ b/test/dm/ffa.c +@@ -0,0 +1,392 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Functional tests for UCLASS_FFA class ++ * ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h" ++#include ++#include ++#include ++ ++/* Macros */ ++ ++#define LOG_MSG_SZ (100) ++#define LOG_CMD_SZ (LOG_MSG_SZ * 2) ++ ++/* Functional tests for the UCLASS_FFA */ ++ ++static int dm_test_ffa_log(struct unit_test_state *uts, char *msg) ++{ ++ char cmd[LOG_CMD_SZ] = {0}; ++ ++ console_record_reset(); ++ ++ snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg); ++ run_command(cmd, 0); ++ ++ ut_assert_console_end(); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata, ++ struct unit_test_state *uts) ++{ ++ if (prvdata->fwk_version != sdx_prvdata->fwk_version) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, ++ "[%s]: Error: framework version: core = 0x%x , sandbox = 0x%x", __func__, ++ prvdata->fwk_version, ++ sdx_prvdata->fwk_version); ++ ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts) ++{ ++ if (prvdata->id) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, ++ "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts) ++{ ++ if (!prvdata->dev) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts) ++{ ++ if (!sdx_prvdata->dev) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts) ++{ ++ if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__, ++ prvdata->pair.rxbuf, ++ prvdata->pair.txbuf); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts) ++{ ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ if (prvdata->pair.rxtx_min_pages != RXTX_4K && ++ prvdata->pair.rxtx_min_pages != RXTX_16K && ++ prvdata->pair.rxtx_min_pages != RXTX_64K) { ++ snprintf(msg, ++ LOG_MSG_SZ, ++ "[%s]: Error: FFA_RXTX_MAP features = 0x%lx", ++ __func__, ++ prvdata->pair.rxtx_min_pages); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static int check_rxbuf_mapped_flag(u32 queried_func_id, ++ u8 rxbuf_mapped, ++ struct unit_test_state *uts) ++{ ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ switch (queried_func_id) { ++ case FFA_RXTX_MAP: ++ { ++ if (rxbuf_mapped) ++ return CMD_RET_SUCCESS; ++ break; ++ } ++ case FFA_RXTX_UNMAP: ++ { ++ if (!rxbuf_mapped) ++ return CMD_RET_SUCCESS; ++ break; ++ } ++ default: ++ return CMD_RET_FAILURE; ++ } ++ ++ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__, ++ (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP")); ++ dm_test_ffa_log(uts, msg); ++ ++ return CMD_RET_FAILURE; ++} ++ ++static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts) ++{ ++ if (rxbuf_owned) { ++ char msg[LOG_MSG_SZ] = {0}; ++ ++ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__); ++ dm_test_ffa_log(uts, msg); ++ return CMD_RET_FAILURE; ++ } ++ return CMD_RET_SUCCESS; ++} ++ ++static int test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts) ++{ ++ struct ffa_send_direct_data msg = {0}; ++ u8 cnt; ++ ++ ut_assertok(ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1)); ++ ++ for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++) ++ ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static int test_partitions_and_comms(const char *service_uuid, ++ struct sandbox_ffa_prvdata *sdx_prvdata, ++ struct unit_test_state *uts) ++{ ++ u32 count = 0; ++ struct ffa_partition_info *parts_info; ++ u32 info_idx, exp_info_idx; ++ int ret; ++ ++ /* ++ * get from the driver the count of the SPs matching the UUID ++ */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, service_uuid, &count, NULL); ++ /* make sure partitions are detected */ ++ ut_assertok(ret != 0); ++ ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE); ++ ++ /* ++ * pre-allocate a buffer to be filled by the driver ++ * with ffa_partition_info structs ++ */ ++ ++ parts_info = calloc(count, sizeof(struct ffa_partition_info)); ++ ut_assertok(!parts_info); ++ ++ /* ++ * ask the driver to fill the buffer with the SPs info ++ */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, service_uuid, &count, parts_info); ++ if (ret != 0) { ++ free(parts_info); ++ ut_assertok(ret != 0); ++ } ++ ++ /* ++ * SPs found , verify the partitions information ++ */ ++ ++ ret = CMD_RET_FAILURE; ++ ++ for (info_idx = 0; info_idx < count ; info_idx++) { ++ for (exp_info_idx = 0; ++ exp_info_idx < sdx_prvdata->partitions.count; ++ exp_info_idx++) { ++ if (parts_info[info_idx].id == ++ sdx_prvdata->partitions.descs[exp_info_idx].info.id) { ++ ret = memcmp(&parts_info[info_idx], ++ &sdx_prvdata->partitions.descs[exp_info_idx] ++ .info, ++ sizeof(struct ffa_partition_info)); ++ if (ret) ++ free(parts_info); ++ ut_assertok(ret != 0); ++ /* send and receive data from the current partition */ ++ test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts); ++ } ++ ret = CMD_RET_SUCCESS; ++ } ++ } ++ ++ free(parts_info); ++ ++ /* Verify expected partitions found in the emulated secure world*/ ++ ut_assertok(ret != CMD_RET_SUCCESS); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static int dm_test_ffa_ack(struct unit_test_state *uts) ++{ ++ struct ffa_prvdata *prvdata = NULL; ++ struct sandbox_ffa_prvdata *sdx_prvdata = NULL; ++ struct ffa_sandbox_data func_data = {0}; ++ u8 rxbuf_flag = 0; ++ const char *svc1_uuid = SANDBOX_SERVICE1_UUID; ++ const char *svc2_uuid = SANDBOX_SERVICE2_UUID; ++ int ret; ++ ++ /* test probing FF-A devices */ ++ ut_assertok(ffa_bus_discover(NULL)); ++ ++ /* get a pointer to the FF-A core and sandbox drivers private data */ ++ func_data.data0 = &prvdata; ++ func_data.data0_size = sizeof(prvdata); ++ func_data.data1 = &sdx_prvdata; ++ func_data.data1_size = sizeof(sdx_prvdata); ++ ++ ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data)); ++ ++ /* make sure private data pointers are retrieved */ ++ ut_assertok(prvdata == 0); ++ ut_assertok(sdx_prvdata == 0); ++ ++ /* make sure dev devices created */ ++ ut_assertok(check_core_dev(prvdata, uts)); ++ ut_assertok(check_sandbox_dev(sdx_prvdata, uts)); ++ ++ /* test FFA_VERSION */ ++ ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts)); ++ ++ /* test FFA_ID_GET */ ++ ut_assertok(check_endpoint_id(prvdata, uts)); ++ ++ /* test FFA_FEATURES */ ++ ut_assertok(check_features(prvdata, uts)); ++ ++ /* test core RX/TX buffers */ ++ ut_assertok(check_rxtxbuf(prvdata, uts)); ++ ++ /* test FFA_RXTX_MAP */ ++ func_data.data0 = &rxbuf_flag; ++ func_data.data0_size = sizeof(rxbuf_flag); ++ ++ rxbuf_flag = 0; ++ ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data)); ++ ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts)); ++ ++ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ ++ ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts); ++ ut_assertok(ret != CMD_RET_SUCCESS); ++ ++ /* test FFA_RX_RELEASE */ ++ rxbuf_flag = 1; ++ ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data)); ++ ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts)); ++ ++ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ ++ ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts); ++ ut_assertok(ret != CMD_RET_SUCCESS); ++ ++ /* test FFA_RX_RELEASE */ ++ rxbuf_flag = 1; ++ ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data)); ++ ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts)); ++ ++ /* test FFA_RXTX_UNMAP */ ++ ut_assertok(ffa_bus_ops_get()->rxtx_unmap(NULL)); ++ ++ rxbuf_flag = 1; ++ ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data)); ++ ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts)); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); ++ ++static int dm_test_ffa_nack(struct unit_test_state *uts) ++{ ++ struct ffa_prvdata *prvdata = NULL; ++ struct sandbox_ffa_prvdata *sdx_prvdata = NULL; ++ struct ffa_sandbox_data func_data = {0}; ++ const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID; ++ const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID; ++ const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID; ++ struct ffa_send_direct_data msg = {0}; ++ int ret; ++ u32 count = 0; ++ u16 part_id = 0; ++ ++ /* test probing FF-A devices */ ++ ut_assertok(ffa_bus_discover(NULL)); ++ ++ /* get a pointer to the FF-A core and sandbox drivers private data */ ++ func_data.data0 = &prvdata; ++ func_data.data0_size = sizeof(prvdata); ++ func_data.data1 = &sdx_prvdata; ++ func_data.data1_size = sizeof(sdx_prvdata); ++ ++ ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data)); ++ ++ /* make sure private data pointers are retrieved */ ++ ut_assertok(prvdata == 0); ++ ut_assertok(sdx_prvdata == 0); ++ ++ /* make sure dev devices created */ ++ ut_assertok(check_core_dev(prvdata, uts)); ++ ut_assertok(check_sandbox_dev(sdx_prvdata, uts)); ++ ++ /* query partitions count using invalid arguments */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid, NULL, NULL); ++ ut_assertok(ret != -EINVAL); ++ ++ /* query partitions count using an invalid UUID string */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid_str, &count, NULL); ++ ut_assertok(ret != -EINVAL); ++ ++ /* query partitions count using an invalid UUID (no matching SP) */ ++ count = 0; ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid, &count, NULL); ++ ut_assertok(count != 0); ++ ++ /* query partitions count using a valid UUID */ ++ count = 0; ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, valid_svc_uuid, &count, NULL); ++ /* make sure partitions are detected */ ++ ut_assertok(ret != 0); ++ ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE); ++ ++ /* send data to an invalid partition */ ++ ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1); ++ ut_assertok(ret != -EINVAL); ++ ++ /* send data to a valid partition */ ++ part_id = prvdata->partitions.descs[0].info.id; ++ ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1); ++ ut_assertok(ret != 0); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-introduce-armffa-command-Sandbox-test.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-introduce-armffa-command-Sandbox-test.patch new file mode 100644 index 000000000000..db0d4b0b729d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-introduce-armffa-command-Sandbox-test.patch @@ -0,0 +1,104 @@ +From 5507189fe37f1243d685c59ea52fa5643d3cc50c Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Nov 2022 14:48:34 +0000 +Subject: [PATCH 08/25] arm_ffa: introduce armffa command Sandbox test + +Add Sandbox test for the armffa command + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v4: drop use of helper APIs + +v1: introduce armffa command sandbox test +--- + MAINTAINERS | 1 + + test/cmd/Makefile | 2 ++ + test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 42 insertions(+) + create mode 100644 test/cmd/armffa.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index e682db8d8f..72f01769c9 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -256,6 +256,7 @@ F: doc/arch/arm64.ffa.rst + F: drivers/firmware/arm-ffa/ + F: include/arm_ffa.h + F: include/sandbox_arm_ffa.h ++F: test/cmd/armffa.c + F: test/dm/ffa.c + + ARM FREESCALE IMX +diff --git a/test/cmd/Makefile b/test/cmd/Makefile +index c331757425..19e9d0a995 100644 +--- a/test/cmd/Makefile ++++ b/test/cmd/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0+ + # + # Copyright (c) 2013 Google, Inc ++# (C) Copyright 2022 ARM Limited + + ifdef CONFIG_HUSH_PARSER + obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o +@@ -13,3 +14,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o + obj-$(CONFIG_CMD_PINMUX) += pinmux.o + obj-$(CONFIG_CMD_PWM) += pwm.o + obj-$(CONFIG_CMD_SETEXPR) += setexpr.o ++obj-$(CONFIG_SANDBOX_FFA) += armffa.o +diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c +new file mode 100644 +index 0000000000..e04363ba63 +--- /dev/null ++++ b/test/cmd/armffa.c +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Test for armffa command ++ * ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PING_CMD_SIZE 19 ++ ++/* Basic test of 'armffa' command */ ++static int dm_test_armffa_cmd(struct unit_test_state *uts) ++{ ++ char ping_cmd[PING_CMD_SIZE] = {0}; ++ ++ ut_assertok(ffa_bus_discover(NULL)); ++ ++ /* armffa getpart */ ++ ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0)); ++ ++ snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID); ++ ++ /* armffa ping */ ++ ut_assertok(run_command(ping_cmd, 0)); ++ ++ /* armffa devlist */ ++ ut_assertok(run_command("armffa devlist", 0)); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-efi-introduce-FF-A-MM-communication.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-efi-introduce-FF-A-MM-communication.patch new file mode 100644 index 000000000000..e9ffd6bb9fe5 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-efi-introduce-FF-A-MM-communication.patch @@ -0,0 +1,498 @@ +From cefc1d101c62e62e66f9cbf1775defde7d2c3d27 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 15 Aug 2022 15:12:49 +0100 +Subject: [PATCH 09/25] arm_ffa: efi: introduce FF-A MM communication + +Add MM communication support using FF-A transport + +This feature allows accessing MM partitions services through +EFI MM communication protocol. MM partitions such as StandAlonneMM +or smm-gateway secure partitions which reside in secure world. + +An MM shared buffer and a door bell event are used to exchange +the data. + +The data is used by EFI services such as GetVariable()/SetVariable() +and copied from the communication buffer to the MM shared buffer. + +The secure partition is notified about availability of data in the +MM shared buffer by an FF-A message (door bell). + +On such event, MM SP can read the data and updates the MM shared +buffer with the response data. + +The response data is copied back to the communication buffer and +consumed by the EFI subsystem. + +MM communication protocol supports FF-A 64-bit direct messaging. + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Gowtham Suresh Kumar +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + +* isolate the compilation choices between FF-A and OP-TEE +* update partition_info_get() second argument to be an SP count +* pass NULL device pointer to the FF-A bus discovery and operations + +v7: + +* set the MM door bell event to use 64-bit direct messaging +* issue a compile time error when one of these macros are not found : + FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR +* make mm_sp_svc_uuid static +* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails +* improve use of unmap_sysmem() in ffa_mm_communicate() + +v6: + +* add FF-A runtime discovery at MM communication level +* drop EFI runtime support for FF-A MM communication +* revert the changes in include/mm_communication.h for + efi_mm_communicate_header and smm_variable_access structures + +v4: + +* use the new FF-A driver interfaces +* discover MM partitions at runtime +* copy FF-A driver private data to EFI runtime section at + ExitBootServices() +* drop use of FFA_ERR_STAT_SUCCESS error code +* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES + in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore +* revert the error log in mm_communicate() in case of failure +* remove packed attribute from efi_mm_communicate_header and + smm_variable_communicate_header + +v2: + +* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings + +v1: + +* introduce FF-A MM communication +--- + include/mm_communication.h | 5 + + lib/efi_loader/Kconfig | 14 +- + lib/efi_loader/efi_variable_tee.c | 294 +++++++++++++++++++++++++++++- + 3 files changed, 307 insertions(+), 6 deletions(-) + +diff --git a/include/mm_communication.h b/include/mm_communication.h +index e65fbde60d..d409bed777 100644 +--- a/include/mm_communication.h ++++ b/include/mm_communication.h +@@ -6,6 +6,8 @@ + * Copyright (c) 2017, Intel Corporation. All rights reserved. + * Copyright (C) 2020 Linaro Ltd. + * Copyright (C) 2020 Linaro Ltd. ++ * (C) Copyright 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #ifndef _MM_COMMUNICATION_H_ +@@ -13,6 +15,9 @@ + + #include + ++/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ ++#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" ++ + /* + * Interface to the pseudo Trusted Application (TA), which provides a + * communication channel with the Standalone MM (Management Mode) +diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig +index b8fb2701a7..d292f57244 100644 +--- a/lib/efi_loader/Kconfig ++++ b/lib/efi_loader/Kconfig +@@ -61,13 +61,23 @@ config EFI_VARIABLE_FILE_STORE + stored as file /ubootefi.var on the EFI system partition. + + config EFI_MM_COMM_TEE +- bool "UEFI variables storage service via OP-TEE" +- depends on OPTEE ++ bool "UEFI variables storage service via the trusted world" ++ depends on OPTEE || ARM_FFA_TRANSPORT + help ++ Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). ++ When using the u-boot OP-TEE driver, StandAlonneMM is supported. ++ When using the u-boot FF-A driver any MM SP is supported. ++ + If OP-TEE is present and running StandAloneMM, dispatch all UEFI + variable related operations to that. The application will verify, + authenticate and store the variables on an RPMB. + ++ When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related ++ operations to the MM SP running in the secure world. ++ A door bell mechanism is used to notify the SP when there is data in the shared ++ MM buffer. The data is copied by u-boot to the shared buffer before issuing ++ the door bell event. ++ + config EFI_VARIABLE_NO_STORE + bool "Don't persist non-volatile UEFI variables" + help +diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c +index dfef18435d..3933a24e8c 100644 +--- a/lib/efi_loader/efi_variable_tee.c ++++ b/lib/efi_loader/efi_variable_tee.c +@@ -4,9 +4,12 @@ + * + * Copyright (C) 2019 Linaro Ltd. + * Copyright (C) 2019 Linaro Ltd. ++ * Copyright (C) 2022 ARM Limited ++ * Abdellatif El Khlifi + */ + + #include ++#include + #include + #include + #include +@@ -15,6 +18,36 @@ + #include + #include + ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ ++#include ++#include ++#include ++ ++#ifndef FFA_SHARED_MM_BUFFER_SIZE ++#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/.h" ++#define FFA_SHARED_MM_BUFFER_SIZE 0 ++#endif ++ ++#ifndef FFA_SHARED_MM_BUFFER_OFFSET ++#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/.h" ++#define FFA_SHARED_MM_BUFFER_OFFSET 0 ++#endif ++ ++#ifndef FFA_SHARED_MM_BUFFER_ADDR ++#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/.h" ++#define FFA_SHARED_MM_BUFFER_ADDR 0 ++#endif ++ ++/* MM return codes */ ++#define MM_SUCCESS (0) ++ ++static const char *mm_sp_svc_uuid = MM_SP_UUID; ++ ++static u16 mm_sp_id; ++ ++#endif ++ + extern struct efi_var_file __efi_runtime_data *efi_var_buf; + static efi_uintn_t max_buffer_size; /* comm + var + func + data */ + static efi_uintn_t max_payload_size; /* func + data */ +@@ -24,6 +57,7 @@ struct mm_connection { + u32 session; + }; + ++#if (IS_ENABLED(CONFIG_OPTEE)) + /** + * get_connection() - Retrieve OP-TEE session for a specific UUID. + * +@@ -143,13 +177,248 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) + + return ret; + } ++#endif ++ ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) + + /** +- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send ++ * ffa_notify_mm_sp() - Announce there is data in the shared buffer ++ * ++ * Notifies the MM partition in the trusted world that ++ * data is available in the shared buffer. ++ * This is a blocking call during which trusted world has exclusive access ++ * to the MM shared buffer. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int ffa_notify_mm_sp(void) ++{ ++ struct ffa_send_direct_data msg = {0}; ++ int ret; ++ int sp_event_ret = -1; ++ ++ if (!ffa_bus_ops_get()) ++ return -EINVAL; ++ ++ msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */ ++ ++ ret = ffa_bus_ops_get()->sync_send_receive(NULL, mm_sp_id, &msg, 1); ++ if (ret != 0) ++ return ret; ++ ++ sp_event_ret = msg.data0; /* x3 */ ++ ++ if (sp_event_ret == MM_SUCCESS) ++ return 0; ++ ++ /* ++ * Failure to notify the MM SP ++ */ ++ ++ return -EACCES; ++} ++ ++/** ++ * ffa_discover_mm_sp_id() - Query the MM partition ID ++ * ++ * Use the FF-A driver to get the MM partition ID. ++ * If multiple partitions are found, use the first one. ++ * This is a boot time function. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int ffa_discover_mm_sp_id(void) ++{ ++ u32 count = 0; ++ int ret; ++ struct ffa_partition_info *parts_info; ++ ++ if (!ffa_bus_ops_get()) ++ return -EINVAL; ++ ++ /* ++ * get from the driver the count of the SPs matching the UUID ++ */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, mm_sp_svc_uuid, &count, NULL); ++ if (ret != 0) { ++ log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret); ++ return ret; ++ } ++ ++ if (!count) { ++ log_info("EFI: No MM partition found\n"); ++ return ret; ++ } ++ ++ /* ++ * pre-allocate a buffer to be filled by the driver ++ * with ffa_partition_info structs ++ */ ++ ++ log_info("EFI: Pre-allocating %d partition(s) info structures\n", count); ++ ++ parts_info = calloc(count, sizeof(*parts_info)); ++ if (!parts_info) ++ return -ENOMEM; ++ ++ /* ++ * ask the driver to fill the ++ * buffer with the SPs info ++ */ ++ ret = ffa_bus_ops_get()->partition_info_get(NULL, mm_sp_svc_uuid, &count, parts_info); ++ if (ret) { ++ log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret); ++ free(parts_info); ++ return ret; ++ } ++ ++ /* ++ * MM SPs found , use the first one ++ */ ++ ++ mm_sp_id = parts_info[0].id; ++ ++ log_info("EFI: MM partition ID 0x%x\n", mm_sp_id); ++ ++ free(parts_info); ++ ++ return 0; ++} ++ ++/** ++ * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A ++ * @comm_buf: locally allocated communication buffer used for rx/tx ++ * @dsize: communication buffer size ++ * ++ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE ++ * that there is data to read from the shared buffer. ++ * Communication with the MM SP is performed using FF-A transport. ++ * On the event, MM SP can read the data from the buffer and ++ * update the MM shared buffer with response data. ++ * The response data is copied back to the communication buffer. ++ * ++ * Return: ++ * ++ * EFI status code ++ */ ++static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size) ++{ ++ ulong tx_data_size; ++ int ffa_ret; ++ efi_status_t efi_ret; ++ struct efi_mm_communicate_header *mm_hdr; ++ void *virt_shared_buf; ++ ++ if (!comm_buf) ++ return EFI_INVALID_PARAMETER; ++ ++ /* Discover MM partition ID at boot time */ ++ if (!mm_sp_id && ffa_discover_mm_sp_id() != 0) { ++ log_err("EFI: Failure to discover MM partition ID at boot time\n"); ++ return EFI_UNSUPPORTED; ++ } ++ ++ mm_hdr = (struct efi_mm_communicate_header *)comm_buf; ++ tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t); ++ ++ if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE) ++ return EFI_INVALID_PARAMETER; ++ ++ /* Copy the data to the shared buffer */ ++ ++ virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0); ++ memcpy(virt_shared_buf, comm_buf, tx_data_size); ++ ++ /* ++ * The secure world might have cache disabled for ++ * the device region used for shared buffer (which is the case for Optee). ++ * In this case, the secure world reads the data from DRAM. ++ * Let's flush the cache so the DRAM is updated with the latest data. ++ */ ++ #ifdef CONFIG_ARM64 ++ invalidate_dcache_all(); ++ #endif ++ ++ /* Announce there is data in the shared buffer */ ++ ++ ffa_ret = ffa_notify_mm_sp(); ++ ++ switch (ffa_ret) { ++ case 0: ++ { ++ ulong rx_data_size; ++ /* Copy the MM SP response from the shared buffer to the communication buffer */ ++ rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len + ++ sizeof(efi_guid_t) + ++ sizeof(size_t); ++ ++ if (rx_data_size > comm_buf_size) { ++ efi_ret = EFI_OUT_OF_RESOURCES; ++ break; ++ } ++ ++ memcpy(comm_buf, virt_shared_buf, rx_data_size); ++ efi_ret = EFI_SUCCESS; ++ break; ++ } ++ case -EINVAL: ++ efi_ret = EFI_DEVICE_ERROR; ++ break; ++ case -EPERM: ++ efi_ret = EFI_INVALID_PARAMETER; ++ break; ++ case -EACCES: ++ efi_ret = EFI_ACCESS_DENIED; ++ break; ++ case -EBUSY: ++ efi_ret = EFI_OUT_OF_RESOURCES; ++ break; ++ default: ++ efi_ret = EFI_ACCESS_DENIED; ++ } ++ ++ unmap_sysmem(virt_shared_buf); ++ return efi_ret; ++} ++#endif ++ ++/** ++ * select_ffa_mm_comms() - checks FF-A support availability ++ * ++ * Making sure FF-A is compiled in. If that's the case try to discover ++ * the FF-A bus. ++ * ++ * Return: ++ * ++ * 0: FF-A ready for use. Otherwise, failure ++ */ ++static efi_status_t select_ffa_mm_comms(void) ++{ ++ efi_status_t ret = EFI_UNSUPPORTED; ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ ret = ffa_bus_discover(NULL); ++ if (ret) ++ ret = EFI_NOT_READY; ++#endif ++ return ret; ++} ++ ++/** ++ * mm_communicate() - Adjust the communication buffer to the MM SP and send + * it to OP-TEE + * +- * @comm_buf: locally allocted communcation buffer ++ * @comm_buf: locally allocated communication buffer + * @dsize: buffer size ++ * ++ * The SP (also called partition) can be any MM SP such as StandAlonneMM or smm-gateway. ++ * The comm_buf format is the same for both partitions. ++ * When using the u-boot OP-TEE driver, StandAlonneMM is supported. ++ * When using the u-boot FF-A driver, any MM SP is supported. ++ * + * Return: status code + */ + static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) +@@ -162,7 +431,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; + +- ret = optee_mm_communicate(comm_buf, dsize); ++ ret = select_ffa_mm_comms(); ++ if (ret != EFI_SUCCESS) { ++#if (IS_ENABLED(CONFIG_OPTEE)) ++ ret = optee_mm_communicate(comm_buf, dsize); ++#endif ++ } else { ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ ret = ffa_mm_communicate(comm_buf, dsize); ++#endif ++ } ++ + if (ret != EFI_SUCCESS) { + log_err("%s failed!\n", __func__); + return ret; +@@ -258,6 +537,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size) + goto out; + } + *size = var_payload->size; ++ ++ #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ if (*size > FFA_SHARED_MM_BUFFER_SIZE) ++ *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE - ++ MM_VARIABLE_COMMUNICATE_SIZE; ++ #endif ++ + /* + * There seems to be a bug in EDK2 miscalculating the boundaries and + * size checks, so deduct 2 more bytes to fulfill this requirement. Fix +@@ -697,7 +983,7 @@ void efi_variables_boot_exit_notify(void) + ret = EFI_NOT_FOUND; + + if (ret != EFI_SUCCESS) +- log_err("Unable to notify StMM for ExitBootServices\n"); ++ log_err("Unable to notify the MM partition for ExitBootServices\n"); + free(comm_buf); + + /* +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-arm_ffa-efi-corstone1000-enable-MM-communication.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-arm_ffa-efi-corstone1000-enable-MM-communication.patch new file mode 100644 index 000000000000..1dfc19b1c6d3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-arm_ffa-efi-corstone1000-enable-MM-communication.patch @@ -0,0 +1,76 @@ +From 46cadb787a3b13da39419706fae7d1ba703f4b68 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 23 Sep 2022 15:17:21 +0100 +Subject: [PATCH 10/25] arm_ffa: efi: corstone1000: enable MM communication + +turn on EFI MM communication + +On corstone1000 platform MM communication between u-boot +and the secure world (Optee) is done using the FF-A bus. + +Signed-off-by: Abdellatif El Khlifi +Cc: Tom Rini +Cc: Simon Glass +Cc: Ilias Apalodimas +Cc: Jens Wiklander +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] + +Changelog: +=============== + +v8: + +* drop OP-TEE configs from Corstone-1000 defconfig + +v7: + +* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and + FFA_SHARED_MM_BUFFER_OFFSET +* update FFA_SHARED_MM_BUFFER_ADDR value + +v6: + +* corstone-1000: enable optee driver +* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig + +v4: + +* corstone-1000: turn on EFI MM communication +--- + configs/corstone1000_defconfig | 2 ++ + include/configs/corstone1000.h | 9 +++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index ed2e0fe70a..c26f99e7e5 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y + CONFIG_USB=y + CONFIG_USB_ISP1760=y + CONFIG_ERRNO_STR=y ++CONFIG_EFI_MM_COMM_TEE=y ++CONFIG_ARM_FFA_TRANSPORT=y +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 8e0230c135..0362d29ac2 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -14,6 +14,15 @@ + + #include + ++#define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */ ++ ++/* ++ * shared buffer physical address used for communication between ++ * u-boot and the MM SP ++ */ ++#define FFA_SHARED_MM_BUFFER_ADDR 0x02000000UL ++#define FFA_SHARED_MM_BUFFER_OFFSET 0 ++ + #define V2M_BASE 0x80000000 + + #define CONFIG_PL011_CLOCK 50000000 +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-introduce-EFI-capsule-update.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-introduce-EFI-capsule-update.patch new file mode 100644 index 000000000000..57f1b9a202db --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-introduce-EFI-capsule-update.patch @@ -0,0 +1,366 @@ +From 7702c4aeda51011be95ecbaab0dc2e7373d04286 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Nov 2022 15:11:27 +0000 +Subject: [PATCH 11/25] efi: corstone1000: introduce EFI capsule update + +This commit provides capsule update feature for Corstone1000. + +This feature is available before and after ExitBootServices(). + +A platform specific capsule buffer is allocated. This buffer +is physically contiguous and allocated at the start of the DDR +memory after u-boot relocation to the end of DDR. + +The capsule buffer is shared between u-boot and the secure world. +On UpdateCapsule() , capsule data is copied to the buffer +and a buffer ready event is generated using FF-A transport. + +On ExitBootServices() a kernel started event is sent to the +SE Proxy FW update service. This event is generated on each boot. + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + board/armltd/corstone1000/corstone1000.c | 4 + + configs/corstone1000_defconfig | 3 + + include/configs/corstone1000.h | 18 ++++ + include/efi_loader.h | 4 +- + lib/efi_loader/efi_boottime.c | 36 +++++++ + lib/efi_loader/efi_capsule.c | 124 ++++++++++++++++++++++- + lib/efi_loader/efi_setup.c | 15 +++ + 7 files changed, 200 insertions(+), 4 deletions(-) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 4f4b96a095..76816f8f4e 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -66,6 +66,10 @@ static struct mm_region corstone1000_mem_map[] = { + + struct mm_region *mem_map = corstone1000_mem_map; + ++void set_dfu_alt_info(char *interface, char *devstr) ++{ ++} ++ + int board_init(void) + { + return 0; +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index c26f99e7e5..c72d027711 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -54,3 +54,6 @@ CONFIG_USB_ISP1760=y + CONFIG_ERRNO_STR=y + CONFIG_EFI_MM_COMM_TEE=y + CONFIG_ARM_FFA_TRANSPORT=y ++CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y ++CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y ++CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 0362d29ac2..4d20090c9b 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -14,6 +14,24 @@ + + #include + ++/* The SE Proxy partition ID*/ ++#define CORSTONE1000_SEPROXY_PART_ID (0x8002) ++ ++/* Update service ID provided by the SE Proxy secure partition*/ ++#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4) ++ ++/* Notification events used with SE Proxy update service */ ++#define CORSTONE1000_BUFFER_READY_EVT (0x1) ++#define CORSTONE1000_KERNEL_STARTED_EVT (0x2) ++ ++/* Size in 4KB pages of the EFI capsule buffer */ ++#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */ ++ ++/* Capsule GUID */ ++#define EFI_CORSTONE1000_CAPSULE_ID_GUID \ ++ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \ ++ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e) ++ + #define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */ + + /* +diff --git a/include/efi_loader.h b/include/efi_loader.h +index 545ba06d94..773c4f6310 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -993,11 +993,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit; + extern const struct efi_firmware_management_protocol efi_fmp_raw; + + /* Capsule update */ +-efi_status_t EFIAPI efi_update_capsule( ++efi_status_t __efi_runtime EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list); +-efi_status_t EFIAPI efi_query_capsule_caps( ++efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index 1099ccc800..d9eed33ac8 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -2103,6 +2103,33 @@ static void efi_exit_caches(void) + #endif + } + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++/** ++ * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service ++ * ++ * This function notifies the SE Proxy update service that the kernel has already started ++ * ++ * Return: ++ * ++ * 0: on success, otherwise failure ++ */ ++static int efi_corstone1000_kernel_started_event(void) ++{ ++ struct ffa_send_direct_data msg = {0}; ++ ++ log_debug("[%s]\n", __func__); ++ ++ /* ++ * setting the kernel started event arguments ++ */ ++ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */ ++ msg.data2 = CORSTONE1000_KERNEL_STARTED_EVT; /* x5 */ ++ ++ return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg, 0); ++} ++ ++#endif ++ + /** + * efi_exit_boot_services() - stop all boot services + * @image_handle: handle of the loaded image +@@ -2209,6 +2236,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + /* Recalculate CRC32 */ + efi_update_table_header_crc32(&systab.hdr); + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ /* Notifying SE Proxy FW update service */ ++ ffa_ret = efi_corstone1000_kernel_started_event(); ++ if (ffa_ret) ++ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); ++ else ++ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); ++#endif ++ + /* Give the payload some time to boot */ + efi_set_watchdog(0); + WATCHDOG_RESET(); +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index a6b98f066a..636b61f0ad 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -25,6 +25,14 @@ + #include + #include + ++#ifdef CONFIG_TARGET_CORSTONE1000 ++#include ++#include ++ ++void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */ ++efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID; ++#endif ++ + DECLARE_GLOBAL_DATA_PTR; + + const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; +@@ -512,6 +520,78 @@ static efi_status_t efi_capsule_update_firmware( + } + #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */ + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ ++/** ++ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer ++ * @capsule_image_size: The capsule data (header + payload) ++ * ++ * This function allocates the physically contiguous buffer shared between u-boot ++ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer ++ * and a door bell event is generated. ++ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated ++ * to the end of DDR. ++ * ++ * Return: ++ * ++ * 0: on success, otherwise failure ++ */ ++efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void) ++{ ++ efi_status_t efi_ret; ++ u64 ram_base = CONFIG_SYS_SDRAM_BASE; ++ ++ log_debug("[%s]\n", __func__); ++ ++ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS, ++ EFI_RUNTIME_SERVICES_DATA, ++ CORSTONE1000_CAPSULE_BUFFER_SIZE, ++ &ram_base); ++ ++ if (efi_ret != EFI_SUCCESS) { ++ corstone1000_capsule_buf = NULL; ++ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n" ++ , (int)efi_ret); ++ return efi_ret; ++ } ++ ++ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n" ++ , (unsigned int)ram_base, ++ CORSTONE1000_CAPSULE_BUFFER_SIZE); ++ ++ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0); ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ * efi_corstone1000_buffer_ready_event - issue door bell event ++ * @capsule_image_size: The capsule data (header + payload) ++ * ++ * This function notifies the SE Proxy update service that capsule data is available ++ * in the capsule shared buffer. ++ * ++ * Return: ++ * ++ * 0: on success, otherwise failure ++ */ ++static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size) ++{ ++ struct ffa_send_direct_data msg = {0}; ++ ++ log_debug("[%s]\n", __func__); ++ ++ /* ++ * setting the buffer ready event arguments ++ */ ++ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */ ++ msg.data1 = capsule_image_size; /* x4 */ ++ msg.data2 = CORSTONE1000_BUFFER_READY_EVT; /* x5 */ ++ ++ return ffa_bus_ops_get()->sync_send_receive(NULL, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); ++} ++#endif ++ + /** + * efi_update_capsule() - process information from operating system + * @capsule_header_array: Array of virtual address pointers +@@ -525,7 +605,7 @@ static efi_status_t efi_capsule_update_firmware( + * + * Return: status code + */ +-efi_status_t EFIAPI efi_update_capsule( ++efi_status_t __efi_runtime EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +@@ -542,6 +622,13 @@ efi_status_t EFIAPI efi_update_capsule( + goto out; + } + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ if (capsule_count != 1 || !corstone1000_capsule_buf) { ++ ret = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++#endif ++ + ret = EFI_SUCCESS; + for (i = 0, capsule = *capsule_header_array; i < capsule_count; + i++, capsule = *(++capsule_header_array)) { +@@ -554,6 +641,39 @@ efi_status_t EFIAPI efi_update_capsule( + + log_debug("Capsule[%d] (guid:%pUs)\n", + i, &capsule->capsule_guid); ++ ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) { ++ ret = EFI_INVALID_PARAMETER; ++ log_err("Corstone1000: Invalid capsule GUID\n"); ++ goto out; ++ } ++ ++ if (efi_size_in_pages(capsule->capsule_image_size) > ++ CORSTONE1000_CAPSULE_BUFFER_SIZE) { ++ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n"); ++ ret = EFI_BUFFER_TOO_SMALL; ++ goto out; ++ } ++ ++ /* copy the data to the contiguous buffer */ ++ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size); ++ ++ /* invalidate the data cache */ ++ invalidate_dcache_all(); ++ ++ /* issue buffer ready event */ ++ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size); ++ if (ret) { ++ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret); ++ ret = EFI_DEVICE_ERROR; ++ } else { ++ ret = EFI_SUCCESS; ++ } ++ ++ goto out; ++#endif ++ + if (!guidcmp(&capsule->capsule_guid, + &efi_guid_firmware_management_capsule_id)) { + ret = efi_capsule_update_firmware(capsule); +@@ -592,7 +712,7 @@ out: + * + * Return: status code + */ +-efi_status_t EFIAPI efi_query_capsule_caps( ++efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, +diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c +index c633fcd91e..443f409906 100644 +--- a/lib/efi_loader/efi_setup.c ++++ b/lib/efi_loader/efi_setup.c +@@ -16,6 +16,13 @@ + + efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++/** ++ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer ++ */ ++extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void); ++#endif ++ + /* + * Allow unaligned memory access. + * +@@ -128,6 +135,14 @@ static efi_status_t efi_init_capsule(void) + { + efi_status_t ret = EFI_SUCCESS; + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ ret = efi_corstone1000_alloc_capsule_shared_buf(); ++ if (ret != EFI_SUCCESS) { ++ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); ++ return ret; ++ } ++#endif ++ + if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) { + ret = efi_set_variable_int(u"CapsuleMax", + &efi_guid_capsule_report, +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch new file mode 100644 index 000000000000..9b12ee9ad445 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch @@ -0,0 +1,31 @@ +From 71162273e8a6b28a6aaf8635cff752419d09a293 Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Fri, 4 Mar 2022 15:56:09 +0000 +Subject: [PATCH 12/25] arm: corstone1000: fix unrecognized filesystem type + +Some usb sticks are not recognized by usb, just add a +delay before checking status. + +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + common/usb_storage.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/common/usb_storage.c b/common/usb_storage.c +index eaa31374ef..79cf4297d4 100644 +--- a/common/usb_storage.c ++++ b/common/usb_storage.c +@@ -784,6 +784,9 @@ static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us) + st: + retry = 0; + again: ++ if (srb->cmd[0] == SCSI_TST_U_RDY) ++ mdelay(100); ++ + debug("STATUS phase\n"); + result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE, + &actlen, USB_CNTL_TIMEOUT*5); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_capsule-corstone1000-pass-interface-id-and-buffe.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_capsule-corstone1000-pass-interface-id-and-buffe.patch new file mode 100644 index 000000000000..9334b804fe2d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_capsule-corstone1000-pass-interface-id-and-buffe.patch @@ -0,0 +1,74 @@ +From f8ccaf53dec63d57bab2f86b822f9fb3ed06d132 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Fri, 10 Dec 2021 20:03:35 +0000 +Subject: [PATCH 13/25] efi_capsule: corstone1000: pass interface id and buffer + event id using register w4 + +Initially the interface/event IDs are passed to the SP using register +w3 and w5. + +Now the SE proxy SP requires this arguments to be in register w4. + +This change is to pass interface ID(31:16) and event ID(15:0) +to SE proxy SP to trigger an event to secure enclave about +firmware update. + +Signed-off-by: Vishnu Banavath +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/configs/corstone1000.h | 6 ++++++ + lib/efi_loader/efi_capsule.c | 11 +++++++---- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 4d20090c9b..77f96e87a1 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -24,6 +24,12 @@ + #define CORSTONE1000_BUFFER_READY_EVT (0x1) + #define CORSTONE1000_KERNEL_STARTED_EVT (0x2) + ++#define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16) ++#define PREP_SEPROXY_SVC_ID(x) (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x))) ++ ++#define PREP_SEPROXY_EVT_MASK GENMASK(15, 0) ++#define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x))) ++ + /* Size in 4KB pages of the EFI capsule buffer */ + #define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */ + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index 636b61f0ad..c22b9b5aa0 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -28,6 +28,8 @@ + #ifdef CONFIG_TARGET_CORSTONE1000 + #include + #include ++#include ++#include + + void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */ + efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID; +@@ -582,11 +584,12 @@ static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_s + log_debug("[%s]\n", __func__); + + /* +- * setting the buffer ready event arguments ++ * setting the buffer ready event arguments in register w4: ++ * - capsule update interface ID (31:16) ++ * - the buffer ready event ID (15:0) + */ +- msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */ +- msg.data1 = capsule_image_size; /* x4 */ +- msg.data2 = CORSTONE1000_BUFFER_READY_EVT; /* x5 */ ++ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | ++ PREP_SEPROXY_EVT(CORSTONE1000_BUFFER_READY_EVT); /* w4 */ + + return ffa_bus_ops_get()->sync_send_receive(NULL, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); + } +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_boottime-corstone1000-pass-interface-id-and-kern.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_boottime-corstone1000-pass-interface-id-and-kern.patch new file mode 100644 index 000000000000..a8d2c817e3d3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_boottime-corstone1000-pass-interface-id-and-kern.patch @@ -0,0 +1,58 @@ +From e4e7ccc77a4e6930a768cc1c1f6daf8907ac16c3 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Fri, 10 Dec 2021 20:10:41 +0000 +Subject: [PATCH 14/25] efi_boottime: corstone1000: pass interface id and + kernel event id using register w4 + +Initially the interface/event IDs are passed to the SP using register +w3 and w5. + +Now the SE proxy SP requires this arguments to be in register w4. + +This change is to pass interface ID(31:16) and kernel started +event ID(15:0) to SE proxy SP to trigger an event to +secure enclave just before ExitbootService(). + +Signed-off-by: Vishnu Banavath +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_boottime.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index d9eed33ac8..88f2d050be 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -30,6 +30,11 @@ + #include + #endif + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++#include ++#include ++#endif ++ + DECLARE_GLOBAL_DATA_PTR; + + /* Task priority level */ +@@ -2120,10 +2125,12 @@ static int efi_corstone1000_kernel_started_event(void) + log_debug("[%s]\n", __func__); + + /* +- * setting the kernel started event arguments ++ * setting the kernel started event arguments: ++ * setting capsule update interface ID(31:16) ++ * the kernel started event ID(15:0) + */ +- msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */ +- msg.data2 = CORSTONE1000_KERNEL_STARTED_EVT; /* x5 */ ++ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | ++ PREP_SEPROXY_EVT(CORSTONE1000_KERNEL_STARTED_EVT); /* w4 */ + + return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg, 0); + } +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-corstone1000-remove-guid-check-from-corst.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-corstone1000-remove-guid-check-from-corst.patch new file mode 100644 index 000000000000..d028e3eda7a1 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-corstone1000-remove-guid-check-from-corst.patch @@ -0,0 +1,53 @@ +From caf6c4ec65fd0a5e945dd790f2369acd163d1daf Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Sat, 11 Dec 2021 13:23:55 +0000 +Subject: [PATCH 15/25] efi_loader: corstone1000: remove guid check from + corstone1000 config option + +Use generic fmp guid and no separte check is required for +CORSTONE1000 target. + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_capsule.c | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index c22b9b5aa0..0eee3c2d4c 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -646,12 +646,6 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( + i, &capsule->capsule_guid); + + #if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) +- if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) { +- ret = EFI_INVALID_PARAMETER; +- log_err("Corstone1000: Invalid capsule GUID\n"); +- goto out; +- } +- + if (efi_size_in_pages(capsule->capsule_image_size) > + CORSTONE1000_CAPSULE_BUFFER_SIZE) { + log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n"); +@@ -677,15 +671,7 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( + goto out; + #endif + +- if (!guidcmp(&capsule->capsule_guid, +- &efi_guid_firmware_management_capsule_id)) { +- ret = efi_capsule_update_firmware(capsule); +- } else { +- log_err("Unsupported capsule type: %pUs\n", +- &capsule->capsule_guid); +- ret = EFI_UNSUPPORTED; +- } +- ++ ret = efi_capsule_update_firmware(capsule); + if (ret != EFI_SUCCESS) + goto out; + } +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch new file mode 100644 index 000000000000..934476ba4cbf --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch @@ -0,0 +1,37 @@ +From 41a2c8bb23e587e9abe7b8bc62db1a93c0e5d841 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Fri, 17 Dec 2021 19:49:02 +0000 +Subject: [PATCH 16/25] efi_loader: populate ESRT table if EFI_ESRT config + option is set + +This change is to call efi_esrt_populate function if CONFIG_EFI_ESRT +is set. This will populte esrt table with firmware image info + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_capsule.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index 0eee3c2d4c..94dc0dfe3d 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -668,6 +668,13 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( + ret = EFI_SUCCESS; + } + ++ if (IS_ENABLED(CONFIG_EFI_ESRT)) { ++ /* Rebuild the ESRT to reflect any updated FW images. */ ++ ret = efi_esrt_populate(); ++ if (ret != EFI_SUCCESS) ++ log_warning("EFI Capsule: failed to update ESRT\n"); ++ } ++ + goto out; + #endif + +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-efi_firmware-add-get_image_info-for-corstone1000.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-efi_firmware-add-get_image_info-for-corstone1000.patch new file mode 100644 index 000000000000..2c0ad2507771 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-efi_firmware-add-get_image_info-for-corstone1000.patch @@ -0,0 +1,122 @@ +From 323df950c63af6d1a9ba5bd16f4f9d9348e9afc2 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Fri, 17 Dec 2021 19:50:25 +0000 +Subject: [PATCH 17/25] efi_firmware: add get_image_info for corstone1000 + +This change is to populate get_image_info which eventually +will be populated in ESRT table + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_firmware.c | 71 ++++++++++++++++++++++++++++++++++- + 1 file changed, 70 insertions(+), 1 deletion(-) + +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index 30cafd15ca..af43d4502f 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -17,11 +17,69 @@ + + #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') + ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID \ ++ EFI_GUID(0xe2bb9c06, 0x70e9, 0x4b14, 0x97, 0xa3, \ ++ 0x5a, 0x79, 0x13, 0x17, 0x6e, 0x3f) ++ ++ const efi_guid_t efi_firmware_image_type_uboot_raw = ++ EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID; ++ ++static efi_status_t efi_corstone1000_img_info_get ( ++ efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name, ++ const efi_guid_t *image_type) ++{ ++ int i = 0; ++ ++ *image_info_size = sizeof(*image_info); ++ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; ++ *descriptor_count = 1;//dfu_num; ++ *descriptor_size = sizeof(*image_info); ++ if (package_version) ++ *package_version = 0xffffffff; /* not supported */ ++ if(package_version_name) ++ *package_version_name = NULL; /* not supported */ ++ ++ if(image_info == NULL) { ++ log_warning("image_info is null\n"); ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ image_info[i].image_index = i; ++ image_info[i].image_type_id = *image_type; ++ image_info[i].image_id = 0; ++ image_info[i].image_id_name = "wic"; ++ image_info[i].version = 1; ++ image_info[i].version_name = NULL; ++ image_info[i].size = 0x1000; ++ image_info[i].attributes_supported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ image_info[i].attributes_setting = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; ++ /* Check if the capsule authentication is enabled */ ++ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) ++ image_info[0].attributes_setting |= ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ image_info[i].lowest_supported_image_version = 0; ++ image_info[i].last_attempt_version = 0; ++ image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; ++ image_info[i].hardware_instance = 1; ++ image_info[i].dependencies = NULL; ++ ++ return EFI_SUCCESS; ++} ++#endif ++ + /** + * struct fmp_payload_header - EDK2 header for the FMP payload + * + * This structure describes the header which is preprended to the +- * FMP payload by the edk2 capsule generation scripts. ++ * FMP payload by the edk1 capsule generation scripts. + * + * @signature: Header signature used to identify the header + * @header_size: Size of the structure +@@ -285,10 +343,18 @@ efi_status_t EFIAPI efi_firmware_get_image_info( + !descriptor_size || !package_version || !package_version_name)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++ ret = efi_corstone1000_img_info_get(image_info_size, image_info, ++ descriptor_version, descriptor_count, ++ descriptor_size, ++ package_version, package_version_name, ++ &efi_firmware_image_type_uboot_raw); ++#else + ret = efi_fill_image_desc_array(image_info_size, image_info, + descriptor_version, descriptor_count, + descriptor_size, package_version, + package_version_name); ++#endif + + return EFI_EXIT(ret); + } +@@ -401,6 +467,9 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( + if (status != EFI_SUCCESS) + return EFI_EXIT(status); + ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++ return EFI_EXIT(EFI_SUCCESS); ++#endif + if (dfu_write_by_alt(image_index - 1, (void *)image, image_size, + NULL, NULL)) + return EFI_EXIT(EFI_DEVICE_ERROR); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-efi_loader-send-bootcomplete-message-to-secure-encla.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-efi_loader-send-bootcomplete-message-to-secure-encla.patch new file mode 100644 index 000000000000..e95609a38dde --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-efi_loader-send-bootcomplete-message-to-secure-encla.patch @@ -0,0 +1,183 @@ +From 7bf9c380c63726b7de8316e9c743cb06c9bc7842 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Mon, 15 Aug 2022 15:46:18 +0100 +Subject: [PATCH 18/25] efi_loader: send bootcomplete message to secure enclave + +On corstone1000 platform, Secure Enclave will be expecting +an event from uboot when it performs capsule update. Previously, +an event is sent at exitbootservice level. This will create a problem +when user wants to interrupt at UEFI shell, hence, it is required +to send an uboot efi initialized event at efi sub-system initialization +stage. + +Signed-off-by: Rui Miguel Silva +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/configs/corstone1000.h | 2 +- + lib/efi_loader/efi_boottime.c | 43 ---------------------------------- + lib/efi_loader/efi_firmware.c | 2 +- + lib/efi_loader/efi_setup.c | 39 ++++++++++++++++++++++++++++++ + 4 files changed, 41 insertions(+), 45 deletions(-) + +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 77f96e87a1..4cf1170ffb 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -22,7 +22,7 @@ + + /* Notification events used with SE Proxy update service */ + #define CORSTONE1000_BUFFER_READY_EVT (0x1) +-#define CORSTONE1000_KERNEL_STARTED_EVT (0x2) ++#define CORSTONE1000_UBOOT_EFI_STARTED_EVT (0x2) + + #define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16) + #define PREP_SEPROXY_SVC_ID(x) (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x))) +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index 88f2d050be..1099ccc800 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -30,11 +30,6 @@ + #include + #endif + +-#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) +-#include +-#include +-#endif +- + DECLARE_GLOBAL_DATA_PTR; + + /* Task priority level */ +@@ -2108,35 +2103,6 @@ static void efi_exit_caches(void) + #endif + } + +-#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) +-/** +- * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service +- * +- * This function notifies the SE Proxy update service that the kernel has already started +- * +- * Return: +- * +- * 0: on success, otherwise failure +- */ +-static int efi_corstone1000_kernel_started_event(void) +-{ +- struct ffa_send_direct_data msg = {0}; +- +- log_debug("[%s]\n", __func__); +- +- /* +- * setting the kernel started event arguments: +- * setting capsule update interface ID(31:16) +- * the kernel started event ID(15:0) +- */ +- msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | +- PREP_SEPROXY_EVT(CORSTONE1000_KERNEL_STARTED_EVT); /* w4 */ +- +- return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg, 0); +-} +- +-#endif +- + /** + * efi_exit_boot_services() - stop all boot services + * @image_handle: handle of the loaded image +@@ -2243,15 +2209,6 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + /* Recalculate CRC32 */ + efi_update_table_header_crc32(&systab.hdr); + +-#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) +- /* Notifying SE Proxy FW update service */ +- ffa_ret = efi_corstone1000_kernel_started_event(); +- if (ffa_ret) +- debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); +- else +- debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); +-#endif +- + /* Give the payload some time to boot */ + efi_set_watchdog(0); + WATCHDOG_RESET(); +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index af43d4502f..25f427b936 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -47,7 +47,7 @@ static efi_status_t efi_corstone1000_img_info_get ( + *package_version_name = NULL; /* not supported */ + + if(image_info == NULL) { +- log_warning("image_info is null\n"); ++ log_info("image_info is null\n"); + return EFI_BUFFER_TOO_SMALL; + } + +diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c +index 443f409906..c154eb0e9d 100644 +--- a/lib/efi_loader/efi_setup.c ++++ b/lib/efi_loader/efi_setup.c +@@ -17,6 +17,9 @@ + efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; + + #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++#include ++#include ++#include + /** + * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer + */ +@@ -126,6 +129,34 @@ static efi_status_t efi_init_secure_boot(void) + } + #endif /* CONFIG_EFI_SECURE_BOOT */ + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++/** ++ * efi_corstone1000_uboot-efi_started_event - notifies SE Proxy FW update service ++ * ++ * This function notifies the SE Proxy update service that uboot efi has already started ++ * ++ * Return: ++ * ++ * 0: on success, otherwise failure ++ * */ ++static int efi_corstone1000_uboot_efi_started_event(void) ++{ ++ struct ffa_send_direct_data msg = {0}; ++ ++ log_debug("[%s]\n", __func__); ++ ++ /* ++ * setting the kernel started event arguments: ++ * setting capsule update interface ID(31:16) ++ * the kernel started event ID(15:0) ++ */ ++ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | ++ PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); /* w4 */ ++ ++ return ffa_bus_ops_get()->sync_send_receive(NULL, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); ++} ++#endif ++ + /** + * efi_init_capsule - initialize capsule update state + * +@@ -136,6 +167,14 @@ static efi_status_t efi_init_capsule(void) + efi_status_t ret = EFI_SUCCESS; + + #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ int ffa_ret; ++ ++ ffa_ret = efi_corstone1000_uboot_efi_started_event(); ++ if (ffa_ret) ++ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); ++ else ++ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); ++ + ret = efi_corstone1000_alloc_capsule_shared_buf(); + if (ret != EFI_SUCCESS) { + printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-efi_loader-fix-null-pointer-exception-with-get_image.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-efi_loader-fix-null-pointer-exception-with-get_image.patch new file mode 100644 index 000000000000..e9bf495f5c3c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-efi_loader-fix-null-pointer-exception-with-get_image.patch @@ -0,0 +1,63 @@ +From 28e7a47c7021b7d321bb6e4dbe1bd7d2ceb8aa6d Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Fri, 14 Jan 2022 15:24:18 +0000 +Subject: [PATCH 19/25] efi_loader: fix null pointer exception with + get_image_info + +get_img_info API implemented for corstone1000 target does not +check the input attributes and as a result uboot crash's with +null pointer access. This change is to fix the null pointer +exception. + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_firmware.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index 25f427b936..28d9a19edb 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -38,26 +38,29 @@ static efi_status_t efi_corstone1000_img_info_get ( + int i = 0; + + *image_info_size = sizeof(*image_info); +- *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; +- *descriptor_count = 1;//dfu_num; +- *descriptor_size = sizeof(*image_info); ++ if(descriptor_version) ++ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; ++ if(descriptor_count) ++ *descriptor_count = 1; ++ if(descriptor_size) ++ *descriptor_size = sizeof(*image_info); + if (package_version) + *package_version = 0xffffffff; /* not supported */ + if(package_version_name) + *package_version_name = NULL; /* not supported */ + + if(image_info == NULL) { +- log_info("image_info is null\n"); ++ log_debug("image_info is null\n"); + return EFI_BUFFER_TOO_SMALL; + } + +- image_info[i].image_index = i; ++ image_info[i].image_index = 1; + image_info[i].image_type_id = *image_type; + image_info[i].image_id = 0; +- image_info[i].image_id_name = "wic"; +- image_info[i].version = 1; ++ image_info[i].image_id_name = L"wic image"; ++ image_info[i].version = 0; + image_info[i].version_name = NULL; +- image_info[i].size = 0x1000; ++ image_info[i].size = 0; + image_info[i].attributes_supported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; + image_info[i].attributes_setting = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-arm-corstone1000-add-mmc-for-fvp.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-arm-corstone1000-add-mmc-for-fvp.patch new file mode 100644 index 000000000000..87432599159c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-arm-corstone1000-add-mmc-for-fvp.patch @@ -0,0 +1,99 @@ +From d662633cb8e90144969790b8abf047a3f777e47a Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Wed, 30 Nov 2022 15:37:22 +0000 +Subject: [PATCH 20/25] arm:corstone1000: add mmc for fvp + +Enable support mmc/sdcard for the corstone1000 FVP. + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + board/armltd/corstone1000/corstone1000.c | 28 +++++++++++++++++++----- + configs/corstone1000_defconfig | 8 ++++++- + include/configs/corstone1000.h | 4 +++- + 3 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 76816f8f4e..d6ca6e8961 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -38,19 +38,35 @@ static struct mm_region corstone1000_mem_map[] = { + }, { + /* USB */ + .virt = 0x40200000UL, +- .phys = 0x40200000UL, ++ .phys = 0x40200000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ /* MMC0 */ ++ .virt = 0x40300000UL, ++ .phys = 0x40300000UL, + .size = 0x00100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | +- PTE_BLOCK_NON_SHARE | +- PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* ethernet */ + .virt = 0x40100000UL, +- .phys = 0x40100000UL, ++ .phys = 0x40100000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ /* MMC1 */ ++ .virt = 0x50000000UL, ++ .phys = 0x50000000UL, + .size = 0x00100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | +- PTE_BLOCK_NON_SHARE | +- PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* OCVM */ + .virt = 0x80000000UL, +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index c72d027711..336da67a8d 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -40,7 +40,13 @@ CONFIG_VERSION_VARIABLE=y + CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_REGMAP=y + CONFIG_MISC=y +-# CONFIG_MMC is not set ++CONFIG_CLK=y ++CONFIG_CMD_MMC=y ++CONFIG_DM_MMC=y ++CONFIG_ARM_PL180_MMCI=y ++CONFIG_MMC_SDHCI_ADMA_HELPERS=y ++CONFIG_MMC_WRITE=y ++CONFIG_DM_GPIO=y + CONFIG_PHYLIB=y + CONFIG_PHY_SMSC=y + CONFIG_SMC911X=y +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 4cf1170ffb..1f28a0f6c0 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -58,7 +58,9 @@ + #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + + #define BOOT_TARGET_DEVICES(func) \ +- func(USB, usb, 0) ++ func(USB, usb, 0) \ ++ func(MMC, mmc, 0) \ ++ func(MMC, mmc, 1) + + #include + +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-compressed-kernel-support.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-compressed-kernel-support.patch new file mode 100644 index 000000000000..d2375239156a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-compressed-kernel-support.patch @@ -0,0 +1,33 @@ +From 37ee9a07d168b43bde17b2ce3dbf637905af5bf2 Mon Sep 17 00:00:00 2001 +From: Jon Mason +Date: Wed, 30 Nov 2022 18:59:59 +0000 +Subject: [PATCH 21/25] corstone1000: add compressed kernel support + +The corstone1000 kernel has become too large to fit in the available +storage. Swtiching to a compressed kernel avoids the problem, but +requires uncompressing it. Add this decompression to the default boot +instructions. + +Signed-off-by: Jon Mason +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + configs/corstone1000_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 336da67a8d..eeb207aa5f 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -15,7 +15,7 @@ CONFIG_FIT=y + CONFIG_BOOTDELAY=3 + CONFIG_USE_BOOTARGS=y + CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" +-CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; loadm $kernel_addr $kernel_addr_r 0xc00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" ++CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r 0xf00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" + CONFIG_CONSOLE_RECORD=y + CONFIG_LOGLEVEL=7 + # CONFIG_DISPLAY_CPUINFO is not set +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-Introduce-external-sys-driver-to-device-tree.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-Introduce-external-sys-driver-to-device-tree.patch new file mode 100644 index 000000000000..91af42624b56 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-Introduce-external-sys-driver-to-device-tree.patch @@ -0,0 +1,34 @@ +From a3fae205de2fd6d2abdb8afca6475267c16e9e29 Mon Sep 17 00:00:00 2001 +From: Emekcan +Date: Wed, 30 Nov 2022 19:02:26 +0000 +Subject: [PATCH 22/25] Introduce external sys driver to device-tree + +It adds external sys driver binding to u-boot +device tree. + +Signed-off-by: Emekcan Aras +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/corstone1000.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi +index 4e46826f88..2c7185e139 100644 +--- a/arch/arm/dts/corstone1000.dtsi ++++ b/arch/arm/dts/corstone1000.dtsi +@@ -160,5 +160,12 @@ + secure-status = "okay"; /* secure-world-only */ + status = "disabled"; + }; ++ ++ extsys0: extsys@1A010310 { ++ compatible = "arm,extsys_ctrl"; ++ reg = <0x1A010310 0x4>, ++ <0x1A010314 0X4>; ++ reg-names = "rstreg", "streg"; ++ }; + }; + }; +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-Add-mhu-and-rpmsg-client-to-u-boot-device-tree.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-Add-mhu-and-rpmsg-client-to-u-boot-device-tree.patch new file mode 100644 index 000000000000..04cbf764bc61 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-Add-mhu-and-rpmsg-client-to-u-boot-device-tree.patch @@ -0,0 +1,79 @@ +From 55e2bc835be50b23ef04066b950bbe75c0065d19 Mon Sep 17 00:00:00 2001 +From: Emekcan +Date: Mon, 12 Sep 2022 15:47:06 +0100 +Subject: [PATCH 23/25] Add mhu and rpmsg client to u-boot device tree + +Adds external system controller and mhu driver to u-boot +device tree. This enables communication between host and +the external system. + +Signed-off-by: Emekcan Aras +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/corstone1000.dtsi | 50 ++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi +index 2c7185e139..61e0c33247 100644 +--- a/arch/arm/dts/corstone1000.dtsi ++++ b/arch/arm/dts/corstone1000.dtsi +@@ -161,6 +161,56 @@ + status = "disabled"; + }; + ++ mbox_es0mhu0_tx: mhu@1b000000 { ++ compatible = "arm,mhuv2-tx","arm,primecell"; ++ reg = <0x1b000000 0x1000>; ++ clocks = <&refclk100mhz>; ++ clock-names = "apb_pclk"; ++ interrupts = ; ++ #mbox-cells = <2>; ++ arm,mhuv2-protocols = <1 1>; ++ mbox-name = "arm-es0-mhu0_tx"; ++ }; ++ ++ mbox_es0mhu0_rx: mhu@1b010000 { ++ compatible = "arm,mhuv2-rx","arm,primecell"; ++ reg = <0x1b010000 0x1000>; ++ clocks = <&refclk100mhz>; ++ clock-names = "apb_pclk"; ++ interrupts = ; ++ #mbox-cells = <2>; ++ arm,mhuv2-protocols = <1 1>; ++ mbox-name = "arm-es0-mhu0_rx"; ++ }; ++ ++ mbox_es0mhu1_tx: mhu@1b020000 { ++ compatible = "arm,mhuv2-tx","arm,primecell"; ++ reg = <0x1b020000 0x1000>; ++ clocks = <&refclk100mhz>; ++ clock-names = "apb_pclk"; ++ interrupts = ; ++ #mbox-cells = <2>; ++ arm,mhuv2-protocols = <1 1>; ++ mbox-name = "arm-es0-mhu1_tx"; ++ }; ++ ++ mbox_es0mhu1_rx: mhu@1b030000 { ++ compatible = "arm,mhuv2-rx","arm,primecell"; ++ reg = <0x1b030000 0x1000>; ++ clocks = <&refclk100mhz>; ++ clock-names = "apb_pclk"; ++ interrupts = ; ++ #mbox-cells = <2>; ++ arm,mhuv2-protocols = <1 1>; ++ mbox-name = "arm-es0-mhu1_rx"; ++ }; ++ ++ client { ++ compatible = "arm,client"; ++ mboxes = <&mbox_es0mhu0_tx 0 0>, <&mbox_es0mhu1_tx 0 0>, <&mbox_es0mhu0_rx 0 0>, <&mbox_es0mhu1_rx 0 0>; ++ mbox-names = "es0mhu0_tx", "es0mhu1_tx", "es0mhu0_rx", "es0mhu1_rx"; ++ }; ++ + extsys0: extsys@1A010310 { + compatible = "arm,extsys_ctrl"; + reg = <0x1A010310 0x4>, +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-arm-corstone1000-esrt-support.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-arm-corstone1000-esrt-support.patch new file mode 100644 index 000000000000..160ff8a41dd7 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-arm-corstone1000-esrt-support.patch @@ -0,0 +1,224 @@ +From 475f787ba7351282ca3ce0fcf9badc01821cd8a3 Mon Sep 17 00:00:00 2001 +From: Satish Kumar +Date: Wed, 30 Nov 2022 19:11:43 +0000 +Subject: [PATCH 24/25] arm/corstone1000: esrt support + +The implementation is platform specific and would require +change in future. + +The patch should not be upstreamed as it is to the u-boot. +Redesign of FMP protocol for ESRT and Capsule Update interface +is to be considered in the future. + +Signed-off-by: Satish Kumar +Upstream-Status: Inappropriate [Redesign of FMP protocol for ESRT and Capsule update interface is required] +--- + include/efi_api.h | 2 +- + lib/efi_loader/efi_firmware.c | 133 ++++++++++++++++++++++++++++++++++ + lib/efi_loader/efi_setup.c | 17 +++-- + 3 files changed, 143 insertions(+), 9 deletions(-) + +diff --git a/include/efi_api.h b/include/efi_api.h +index 9bb0d44ac8..fcf2643e14 100644 +--- a/include/efi_api.h ++++ b/include/efi_api.h +@@ -2030,7 +2030,7 @@ struct efi_firmware_image_descriptor { + u32 last_attempt_status; + u64 hardware_instance; + efi_firmware_image_dep_t *dependencies; +-}; ++} __packed; + + struct efi_firmware_management_protocol { + efi_status_t (EFIAPI *get_image_info)( +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index 28d9a19edb..aa4af8036b 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -14,6 +14,7 @@ + #include + + #include ++#include + + #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') + +@@ -416,8 +417,140 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( + return EFI_EXIT(EFI_SUCCESS); + } + ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++ ++/** ++ * efi_firmware_corstone1000_get_image_info - return information about the current ++ firmware image ++ * @this: Protocol instance ++ * @image_info_size: Size of @image_info ++ * @image_info: Image information ++ * @descriptor_version: Pointer to version number ++ * @descriptor_count: Pointer to number of descriptors ++ * @descriptor_size: Pointer to descriptor size ++ * package_version: Package version ++ * package_version_name: Package version's name ++ * ++ * Return information bout the current firmware image in @image_info. ++ * @image_info will consist of a number of descriptors. ++ * Each descriptor will be created based on efi fetched variable. ++ * ++ * Return status code ++ */ ++static ++efi_status_t EFIAPI efi_firmware_corstone1000_get_image_info( ++ struct efi_firmware_management_protocol *this, ++ efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name) ++{ ++ efi_uintn_t var_size; ++ efi_status_t ret = EFI_SUCCESS; ++ efi_uintn_t image_info_size_var = 0; ++ efi_uintn_t image_info_name_size_var; ++ efi_uintn_t image_info_version_size_var; ++ u8 *runner = (u8 *)image_info; ++ u16 fmp_image_name[14] = {'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '1', '\0'}; ++ u16 fmp_version_name[16] = {'F', 'm', 'p', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '1', '\0'}; ++ ++ EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, ++ image_info_size, image_info, ++ descriptor_version, descriptor_count, descriptor_size, ++ package_version, package_version_name); ++ ++ if (!image_info_size) ++ return EFI_EXIT(EFI_INVALID_PARAMETER); ++ ++ if (*image_info_size && ++ (!image_info || !descriptor_version || !descriptor_count || ++ !descriptor_size || !package_version || !package_version_name)) ++ return EFI_EXIT(EFI_INVALID_PARAMETER); ++ ++ var_size = sizeof(*descriptor_version); ++ ret = efi_get_variable(u"FmpDescriptorVersion", ++ &efi_guid_firmware_management_protocol, NULL, ++ &var_size, descriptor_version); ++ if (ret != EFI_SUCCESS) ++ return EFI_EXIT(ret); ++ ++ if (*descriptor_version != EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) ++ return EFI_EXIT(EFI_UNSUPPORTED); ++ ++ var_size = sizeof(image_info_size_var); ++ ret = efi_get_variable(u"FmpImageInfoSize", ++ &efi_guid_firmware_management_protocol, NULL, ++ &var_size, &image_info_size_var); ++ if (ret != EFI_SUCCESS) ++ return EFI_EXIT(ret); ++ ++ if (*image_info_size < image_info_size_var) { ++ *image_info_size = image_info_size_var; ++ return EFI_EXIT(EFI_BUFFER_TOO_SMALL); ++ } ++ ++ image_info_name_size_var = image_info_size_var; ++ ++ var_size = sizeof(*descriptor_count); ++ ret = efi_get_variable(u"FmpDescriptorCount", ++ &efi_guid_firmware_management_protocol, NULL, ++ &var_size, descriptor_count); ++ if (ret != EFI_SUCCESS) { ++ return EFI_EXIT(ret); ++ } ++ ++ ret = efi_get_variable(u"FmpImageInfo", ++ &efi_guid_firmware_management_protocol, NULL, ++ &image_info_size_var, image_info); ++ if (ret != EFI_SUCCESS) ++ return EFI_EXIT(ret); ++ ++ runner += image_info_size_var; ++ ++ image_info_name_size_var -= image_info_size_var; ++ image_info_version_size_var = image_info_name_size_var; ++ ++ /* Consider changing the string modfication logic */ ++ fmp_image_name[12] = '0' + (u16)image_info->image_id; ++ ret = efi_get_variable(fmp_image_name, ++ &efi_guid_firmware_management_protocol, NULL, ++ &image_info_name_size_var, runner); ++ if (ret != EFI_SUCCESS) ++ return EFI_EXIT(ret); ++ ++ image_info_version_size_var -= image_info_name_size_var; ++ image_info->image_id_name = runner; ++ runner += image_info_name_size_var; ++ ++ /* Consider changing the string modfication logic */ ++ fmp_version_name[14] = '0' + (u16)image_info->image_id; ++ ret = efi_get_variable(fmp_version_name, ++ &efi_guid_firmware_management_protocol, NULL, ++ &image_info_version_size_var, runner); ++ if (ret != EFI_SUCCESS) ++ return EFI_EXIT(ret); ++ ++ image_info->version_name = runner; ++ ++ *image_info_size = image_info_size_var; ++ ++ *package_version = 0xffffffff; /* not supported */ ++ *package_version_name = NULL; /* not supported */ ++ ++ return EFI_EXIT(ret); ++} ++ ++#endif ++ + const struct efi_firmware_management_protocol efi_fmp_fit = { ++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) ++ .get_image_info = efi_firmware_corstone1000_get_image_info, ++#else + .get_image_info = efi_firmware_get_image_info, ++#endif + .get_image = efi_firmware_get_image_unsupported, + .set_image = efi_firmware_fit_set_image, + .check_image = efi_firmware_check_image_unsupported, +diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c +index c154eb0e9d..63329bbff8 100644 +--- a/lib/efi_loader/efi_setup.c ++++ b/lib/efi_loader/efi_setup.c +@@ -167,14 +167,6 @@ static efi_status_t efi_init_capsule(void) + efi_status_t ret = EFI_SUCCESS; + + #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) +- int ffa_ret; +- +- ffa_ret = efi_corstone1000_uboot_efi_started_event(); +- if (ffa_ret) +- debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); +- else +- debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); +- + ret = efi_corstone1000_alloc_capsule_shared_buf(); + if (ret != EFI_SUCCESS) { + printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); +@@ -308,6 +300,15 @@ efi_status_t efi_init_obj_list(void) + if (ret != EFI_SUCCESS) + goto out; + ++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) ++ int ffa_ret; ++ ffa_ret = efi_corstone1000_uboot_efi_started_event(); ++ if (ffa_ret) ++ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); ++ else ++ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); ++#endif ++ + /* Initialize variable services */ + ret = efi_init_variables(); + if (ret != EFI_SUCCESS) +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-efi_setup-discover-FF-A-bus-before-raising-EFI-start.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-efi_setup-discover-FF-A-bus-before-raising-EFI-start.patch new file mode 100644 index 000000000000..6c177864ffa3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-efi_setup-discover-FF-A-bus-before-raising-EFI-start.patch @@ -0,0 +1,50 @@ +From de5994cda7a35317f12dc1cedb28cae1b932283a Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 30 Nov 2022 19:14:52 +0000 +Subject: [PATCH 25/25] efi_setup: discover FF-A bus before raising EFI started + event + +add FF-A discovery to efi_corstone1000_uboot_efi_started_event() + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + lib/efi_loader/efi_setup.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c +index 63329bbff8..cf8abe3af0 100644 +--- a/lib/efi_loader/efi_setup.c ++++ b/lib/efi_loader/efi_setup.c +@@ -142,9 +142,16 @@ static efi_status_t efi_init_secure_boot(void) + static int efi_corstone1000_uboot_efi_started_event(void) + { + struct ffa_send_direct_data msg = {0}; ++ int ret; + + log_debug("[%s]\n", __func__); + ++ ret = ffa_bus_discover(NULL); ++ if (ret != 0) { ++ log_err("failure to discover FF-A bus\n"); ++ return ret; ++ } ++ + /* + * setting the kernel started event arguments: + * setting capsule update interface ID(31:16) +@@ -304,9 +311,9 @@ efi_status_t efi_init_obj_list(void) + int ffa_ret; + ffa_ret = efi_corstone1000_uboot_efi_started_event(); + if (ffa_ret) +- debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); ++ log_err("Failure to notify SE Proxy FW update service\n"); + else +- debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); ++ debug("SE Proxy FW update service notified\n"); + #endif + + /* Initialize variable services */ +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-enable-distro-booting-command.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-enable-distro-booting-command.patch new file mode 100644 index 000000000000..a88180da8790 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-enable-distro-booting-command.patch @@ -0,0 +1,27 @@ +From 15778524604652db60f704a772b6815d0f4305bf Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 5 Dec 2022 17:02:32 +0000 +Subject: [PATCH] corstone1000: enable distro booting command + +enable distro_bootcmd + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/configs/corstone1000.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 1f28a0f6c0..548856b970 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -64,5 +64,6 @@ + + #include + ++#define CONFIG_EXTRA_ENV_SETTINGS BOOTENV + + #endif +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0001-armv7-adding-generic-timer-access-through-MMIO.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0001-armv7-adding-generic-timer-access-through-MMIO.patch new file mode 100644 index 000000000000..2cdafac524df --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0001-armv7-adding-generic-timer-access-through-MMIO.patch @@ -0,0 +1,140 @@ +From 787a802afb8c05fcb5117c1cbb612c51554aad24 Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Wed, 18 Dec 2019 21:52:34 +0000 +Subject: [PATCH 1/2] armv7: adding generic timer access through MMIO + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Abdellatif El Khlifi + +This driver enables the ARMv7 generic timer. + +The access to the timer registers is through memory mapping (MMIO). + +This driver can be used by u-boot to access to the timer through MMIO +when arch_timer is not available in the core (access using system +instructions not possible), for example, in case of Cortex-A5. + +This driver configures and enables the generic timer at +the u-boot initcall level (timer_init) before u-boot relocation. + +Signed-off-by: Rui Miguel Silva +Signed-off-by: Abdellatif El Khlifi + +%% original patch: 0001-armv7-adding-generic-timer-access-through-MMIO.patch + +Signed-off-by: Rui Miguel Silva +--- + arch/arm/cpu/armv7/Makefile | 1 + + arch/arm/cpu/armv7/mmio_timer.c | 75 +++++++++++++++++++++++++++++++++ + scripts/config_whitelist.txt | 1 + + 3 files changed, 77 insertions(+) + create mode 100644 arch/arm/cpu/armv7/mmio_timer.c + +diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile +index bfbd85ae64ef..1a0a24e53110 100644 +--- a/arch/arm/cpu/armv7/Makefile ++++ b/arch/arm/cpu/armv7/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_ARMV7_PSCI) += psci.o psci-common.o + obj-$(CONFIG_IPROC) += iproc-common/ + obj-$(CONFIG_KONA) += kona-common/ + obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o ++obj-$(CONFIG_SYS_MMIO_TIMER) += mmio_timer.o + + ifneq (,$(filter s5pc1xx exynos,$(SOC))) + obj-y += s5p-common/ +diff --git a/arch/arm/cpu/armv7/mmio_timer.c b/arch/arm/cpu/armv7/mmio_timer.c +new file mode 100644 +index 000000000000..edd806e06e42 +--- /dev/null ++++ b/arch/arm/cpu/armv7/mmio_timer.c +@@ -0,0 +1,75 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (c) 2019, Arm Limited. All rights reserved. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define CNTCTLBASE 0x1a020000UL ++#define CNTREADBASE 0x1a030000UL ++#define CNTEN (1 << 0) ++#define CNTFCREQ (1 << 8) ++ ++static inline uint32_t mmio_read32(uintptr_t addr) ++{ ++ return *(volatile uint32_t*)addr; ++} ++ ++static inline void mmio_write32(uintptr_t addr, uint32_t data) ++{ ++ *(volatile uint32_t*)addr = data; ++} ++ ++int timer_init(void) ++{ ++ /* calculate the frequency in ms */ ++ gd->arch.timer_rate_hz = COUNTER_FREQUENCY / CONFIG_SYS_HZ; ++ ++ /* configure CNTFID0 register: set the base frequency */ ++ mmio_write32(CNTCTLBASE + 0x20, COUNTER_FREQUENCY); ++ ++ /* ++ * configure CNTCR register: ++ * enable the generic counter and; ++ * select the first frequency entry ++ */ ++ mmio_write32(CNTCTLBASE, CNTFCREQ | CNTEN); ++ ++ return 0; ++} ++ ++unsigned long long get_ticks(void) ++{ ++ return (((u64)(mmio_read32(CNTREADBASE + 0x4)) << 32) | ++ mmio_read32(CNTREADBASE)); ++} ++ ++ulong get_timer(ulong base) ++{ ++ return lldiv(get_ticks(), gd->arch.timer_rate_hz) - base; ++} ++ ++void __udelay(unsigned long usec) ++{ ++ unsigned long endtime; ++ ++ endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz, ++ 1000UL); ++ ++ endtime += get_ticks(); ++ ++ while (get_ticks() < endtime) ++ ; ++} ++ ++ulong get_tbclk(void) ++{ ++ return gd->arch.timer_rate_hz; ++} +diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt +index f505722f6b04..e0df0026c985 100644 +--- a/scripts/config_whitelist.txt ++++ b/scripts/config_whitelist.txt +@@ -900,6 +900,7 @@ CONFIG_SYS_MMC_U_BOOT_DST + CONFIG_SYS_MMC_U_BOOT_OFFS + CONFIG_SYS_MMC_U_BOOT_SIZE + CONFIG_SYS_MMC_U_BOOT_START ++CONFIG_SYS_MMIO_TIMER + CONFIG_SYS_MONITOR_LEN + CONFIG_SYS_MONITOR_SEC + CONFIG_SYS_MOR_VAL +-- +2.38.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0002-board-arm-add-corstone500-board.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0002-board-arm-add-corstone500-board.patch new file mode 100644 index 000000000000..f76f449cb6d3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone500/0002-board-arm-add-corstone500-board.patch @@ -0,0 +1,299 @@ +From 70cf3f7498e98a98b21804f577f3b850018894da Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Wed, 8 Jan 2020 09:48:11 +0000 +Subject: [PATCH 2/2] board: arm: add corstone500 board + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Abdellatif El Khlifi + +Add support for the Arm corstone500 platform, with a cortex-a5 +chip, add the default configuration, initialization and +makefile for this system. + +Signed-off-by: Rui Miguel Silva +--- + arch/arm/Kconfig | 10 +++ + board/armltd/corstone500/Kconfig | 12 +++ + board/armltd/corstone500/Makefile | 8 ++ + board/armltd/corstone500/corstone500.c | 48 ++++++++++++ + configs/corstone500_defconfig | 41 ++++++++++ + include/configs/corstone500.h | 102 +++++++++++++++++++++++++ + 6 files changed, 221 insertions(+) + create mode 100644 board/armltd/corstone500/Kconfig + create mode 100644 board/armltd/corstone500/Makefile + create mode 100644 board/armltd/corstone500/corstone500.c + create mode 100644 configs/corstone500_defconfig + create mode 100644 include/configs/corstone500.h + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 82cd456f51f1..a925e7759ee8 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1349,6 +1349,15 @@ config TARGET_CORSTONE1000 + select PL01X_SERIAL + select DM + ++config TARGET_CORSTONE500 ++ bool "Support Corstone500" ++ select CPU_V7A ++ select SEMIHOSTING ++ select PL01X_SERIAL ++ help ++ This enables support for Corstone500 ARM which is a ++ Cortex-A5 system ++ + config TARGET_TOTAL_COMPUTE + bool "Support Total Compute Platform" + select ARM64 +@@ -2302,6 +2311,7 @@ source "board/bosch/shc/Kconfig" + source "board/bosch/guardian/Kconfig" + source "board/Marvell/octeontx/Kconfig" + source "board/Marvell/octeontx2/Kconfig" ++source "board/armltd/corstone500/Kconfig" + source "board/armltd/vexpress/Kconfig" + source "board/armltd/vexpress64/Kconfig" + source "board/cortina/presidio-asic/Kconfig" +diff --git a/board/armltd/corstone500/Kconfig b/board/armltd/corstone500/Kconfig +new file mode 100644 +index 000000000000..8e689bd1fdc8 +--- /dev/null ++++ b/board/armltd/corstone500/Kconfig +@@ -0,0 +1,12 @@ ++if TARGET_CORSTONE500 ++ ++config SYS_BOARD ++ default "corstone500" ++ ++config SYS_VENDOR ++ default "armltd" ++ ++config SYS_CONFIG_NAME ++ default "corstone500" ++ ++endif +diff --git a/board/armltd/corstone500/Makefile b/board/armltd/corstone500/Makefile +new file mode 100644 +index 000000000000..6598fdd3ae0d +--- /dev/null ++++ b/board/armltd/corstone500/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++# (C) Copyright 2022 ARM Limited ++# (C) Copyright 2022 Linaro ++# Rui Miguel Silva ++# ++ ++obj-y := corstone500.o +diff --git a/board/armltd/corstone500/corstone500.c b/board/armltd/corstone500/corstone500.c +new file mode 100644 +index 000000000000..e878f5c6a521 +--- /dev/null ++++ b/board/armltd/corstone500/corstone500.c +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * (C) Copyright 2022 Linaro ++ * Rui Miguel Silva ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static const struct pl01x_serial_plat serial_platdata = { ++ .base = V2M_UART0, ++ .type = TYPE_PL011, ++ .clock = CONFIG_PL011_CLOCK, ++}; ++ ++U_BOOT_DRVINFO(corstone500_serials) = { ++ .name = "serial_pl01x", ++ .plat = &serial_platdata, ++}; ++ ++int board_init(void) ++{ ++ return 0; ++} ++ ++int dram_init(void) ++{ ++ gd->ram_size = PHYS_SDRAM_1_SIZE; ++ ++ return 0; ++} ++ ++int dram_init_banksize(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return 0; ++} ++ ++void reset_cpu(ulong addr) ++{ ++} ++ +diff --git a/configs/corstone500_defconfig b/configs/corstone500_defconfig +new file mode 100644 +index 000000000000..e475cbe7e40d +--- /dev/null ++++ b/configs/corstone500_defconfig +@@ -0,0 +1,41 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_TARGET_CORSTONE500=y ++CONFIG_SYS_TEXT_BASE=0x88000000 ++CONFIG_SYS_MALLOC_LEN=0x840000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x40000 ++CONFIG_SYS_PROMPT="corstone500# " ++CONFIG_IDENT_STRING=" corstone500 aarch32" ++CONFIG_SYS_LOAD_ADDR=0x90000000 ++CONFIG_SYS_MEMTEST_START=0x80000000 ++CONFIG_SYS_MEMTEST_END=0xff000000 ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000 ++CONFIG_SUPPORT_RAW_INITRD=y ++CONFIG_BOOTDELAY=1 ++CONFIG_USE_BOOTARGS=y ++CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1a200000 root=/dev/ram0 rw loglevel=9" ++# CONFIG_DISPLAY_CPUINFO is not set ++# CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_HUSH_PARSER=y ++# CONFIG_CMD_CONSOLE is not set ++CONFIG_CMD_BOOTZ=y ++# CONFIG_CMD_XIMG is not set ++# CONFIG_CMD_EDITENV is not set ++# CONFIG_CMD_ENV_EXISTS is not set ++CONFIG_CMD_MEMTEST=y ++CONFIG_CMD_ARMFLASH=y ++# CONFIG_CMD_LOADS is not set ++# CONFIG_CMD_ITEST is not set ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_DHCP=y ++# CONFIG_CMD_NFS is not set ++CONFIG_CMD_MII=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_FAT=y ++CONFIG_DM=y ++CONFIG_MTD_NOR_FLASH=y ++CONFIG_DM_SERIAL=y ++CONFIG_OF_LIBFDT=y +diff --git a/include/configs/corstone500.h b/include/configs/corstone500.h +new file mode 100644 +index 000000000000..416f5fa4399d +--- /dev/null ++++ b/include/configs/corstone500.h +@@ -0,0 +1,102 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2022 ARM Limited ++ * (C) Copyright 2022 Linaro ++ * Rui Miguel Silva ++ * ++ * Configuration for Cortex-A5 Corstone500. Parts were derived from other ARM ++ * configurations. ++ */ ++ ++#ifndef __CORSTONE500_H ++#define __CORSTONE500_H ++ ++/* Generic Timer Definitions */ ++#define CONFIG_SYS_HZ_CLOCK 7500000 ++#define CONFIG_SYS_HZ 1000 ++#define COUNTER_FREQUENCY CONFIG_SYS_HZ_CLOCK ++ ++#ifdef CONFIG_CORSTONE500_MEMORY_MAP_EXTENDED ++#define V2M_SRAM0 0x00010000 ++#define V2M_SRAM1 0x02200000 ++#define V2M_QSPI 0x0a800000 ++#else ++#define V2M_SRAM0 0x00000000 ++#define V2M_SRAM1 0x02000000 ++#define V2M_QSPI 0x08000000 ++#endif ++ ++#define V2M_DEBUG 0x10000000 ++#define V2M_BASE_PERIPH 0x1a000000 ++#define V2M_A5_PERIPH 0x1c000000 ++#define V2M_L2CC_PERIPH 0x1c010000 ++ ++#define V2M_MASTER_EXPANSION0 0x40000000 ++#define V2M_MASTER_EXPANSION1 0x60000000 ++ ++#define V2M_BASE 0x80000000 ++ ++#define V2M_PERIPH_OFFSET(x) (x << 16) ++ ++#define V2M_SYSID (V2M_BASE_PERIPH) ++#define V2M_SYCTL (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(1)) ++#define V2M_COUNTER_CTL (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(2)) ++#define V2M_COUNTER_READ (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(3)) ++#define V2M_TIMER_CTL (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(4)) ++#define V2M_TIMER0 (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(5)) ++ ++#define V2M_WATCHDOG_CTL (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(16)) ++#define V2M_WATCHDOG_REFRESH (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(17)) ++ ++#define V2M_UART0 (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(32)) ++#define V2M_UART1 (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(33)) ++ ++#define V2M_RTC (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(34)) ++#define V2M_TRNG (V2M_BASE_PERIPH + V2M_PERIPH_OFFSET(35)) ++ ++/* PL011 Serial Configuration */ ++#define CONFIG_CONS_INDEX 0 ++#define CONFIG_PL011_CLOCK 7500000 ++ ++/* Physical Memory Map */ ++#define PHYS_SDRAM_1 (V2M_BASE) ++ ++/* Top 16MB reserved for secure world use */ ++#define DRAM_SEC_SIZE 0x01000000 ++#define PHYS_SDRAM_1_SIZE (0x80000000 - DRAM_SEC_SIZE) ++ ++/* Miscellaneous configurable options */ ++#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 ++ ++#define CONFIG_SYS_MMIO_TIMER ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "kernel_name=Image\0" \ ++ "kernel_addr=0x80f00000\0" \ ++ "initrd_name=ramdisk.img\0" \ ++ "initrd_addr=0x84000000\0" \ ++ "fdt_name=devtree.dtb\0" \ ++ "fdt_addr=0x83000000\0" \ ++ "fdt_high=0xffffffff\0" \ ++ "initrd_high=0xffffffff\0" ++ ++#define CONFIG_BOOTCOMMAND "echo copy to RAM...; " \ ++ "cp.b 0x80100000 $kernel_addr 0xb00000; " \ ++ "cp.b 0x80d00000 $initrd_addr 0x800000; " \ ++ "bootz $kernel_addr $initrd_addr:0x800000 $fdt_addr" ++ ++/* Monitor Command Prompt */ ++#define CONFIG_SYS_FLASH_BASE 0x80000000 ++/* Store environment at top of flash */ ++#define CONFIG_ENV_ADDR 0x0a7c0000 ++#define CONFIG_ENV_SECT_SIZE 0x0040000 ++ ++#define CONFIG_SYS_FLASH_CFI 1 ++#define CONFIG_FLASH_CFI_DRIVER 1 ++#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_32BIT ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++ ++#define CONFIG_SYS_FLASH_EMPTY_INFO /* flinfo indicates empty blocks */ ++#define FLASH_MAX_SECTOR_SI 0x00040000 ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#endif +-- +2.38.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch new file mode 100644 index 000000000000..5138335eb48c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch @@ -0,0 +1,184 @@ +From 424d186ab0a0c4dd62dfb13ac87e8d1fd26c101e Mon Sep 17 00:00:00 2001 +From: Anders Dellien +Date: Thu, 23 Jul 2020 17:32:55 +0100 +Subject: [PATCH 1/2] Add vexpress_aemv8a_aarch32 variant + +The ARM AEMv8 FVP model can be run in Aarch64 or Aarch32 mode. Aarch32 +support is enable per-CPU when launching the model, eg: + +-C cluster0.cpu0.CONFIG64=0 + +This patch adds a new defconfig and some variant specific selections in +vexpress_armv8a.h. + +This patch is co-authored with Soby Mathew . + +Upstream-Status: Denied + +For upstream discussion, please visit +https://www.mail-archive.com/u-boot@lists.denx.de/msg233429.html + +Signed-off-by: Ryan Harkin +Signed-off-by: Asha R +Signed-off-by: Anders Dellien +--- + arch/arm/Kconfig | 5 +++ + board/armltd/vexpress64/Kconfig | 2 +- + configs/vexpress_aemv8a_aarch32_defconfig | 40 ++++++++++++++++++ + include/configs/vexpress_aemv8.h | 50 +++++++++++++++-------- + 4 files changed, 80 insertions(+), 17 deletions(-) + create mode 100644 configs/vexpress_aemv8a_aarch32_defconfig + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 4567c183fb84..99cc414d6760 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1250,6 +1250,11 @@ config TARGET_VEXPRESS64_BASE_FVP + select PL01X_SERIAL + select SEMIHOSTING + ++config TARGET_VEXPRESS64_BASE_FVP_AARCH32 ++ bool "Support Versatile Express ARMv8a 32-bit FVP BASE model" ++ select CPU_V7A ++ select SEMIHOSTING ++ + config TARGET_VEXPRESS64_JUNO + bool "Support Versatile Express Juno Development Platform" + select ARM64 +diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig +index 4aab3f092ecb..0a5e3fcc004a 100644 +--- a/board/armltd/vexpress64/Kconfig ++++ b/board/armltd/vexpress64/Kconfig +@@ -1,4 +1,4 @@ +-if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO ++if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO || TARGET_VEXPRESS64_BASE_FVP_AARCH32 + + config SYS_BOARD + default "vexpress64" +diff --git a/configs/vexpress_aemv8a_aarch32_defconfig b/configs/vexpress_aemv8a_aarch32_defconfig +new file mode 100644 +index 000000000000..9c5c3367ec4d +--- /dev/null ++++ b/configs/vexpress_aemv8a_aarch32_defconfig +@@ -0,0 +1,40 @@ ++CONFIG_ARM=y ++CONFIG_SYS_ARCH_TIMER=y ++CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32=y ++CONFIG_SYS_TEXT_BASE=0x88000000 ++CONFIG_SYS_MALLOC_F_LEN=0x2000 ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_IDENT_STRING=" vexpress_aemv8a fvp aarch32" ++CONFIG_REMAKE_ELF=y ++CONFIG_SYS_LOAD_ADDR=0x90000000 ++CONFIG_BOOTDELAY=1 ++CONFIG_USE_BOOTARGS=y ++CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 systemd.log_target=null root=/dev/vda1 rw androidboot.hardware=fvpbase rootwait loglevel=9" ++# CONFIG_DISPLAY_CPUINFO is not set ++# CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_PROMPT="fvp32# " ++# CONFIG_CMD_CONSOLE is not set ++CONFIG_CMD_BOOTZ=y ++# CONFIG_CMD_XIMG is not set ++# CONFIG_CMD_EDITENV is not set ++# CONFIG_CMD_ENV_EXISTS is not set ++CONFIG_CMD_MEMTEST=y ++CONFIG_CMD_ARMFLASH=y ++# CONFIG_CMD_LOADS is not set ++# CONFIG_CMD_ITEST is not set ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_DHCP=y ++# CONFIG_CMD_NFS is not set ++CONFIG_CMD_MII=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_FAT=y ++CONFIG_DM=y ++CONFIG_MTD_NOR_FLASH=y ++CONFIG_FLASH_CFI_DRIVER=y ++CONFIG_SYS_FLASH_CFI=y ++CONFIG_DM_SERIAL=y ++CONFIG_PL01X_SERIAL=y ++CONFIG_OF_LIBFDT=y ++CONFIG_REMAKE_ELF=y +diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h +index f0c5ceb3849a..854fbb41bfc1 100644 +--- a/include/configs/vexpress_aemv8.h ++++ b/include/configs/vexpress_aemv8.h +@@ -86,7 +86,7 @@ + #endif + #endif /* !CONFIG_GICV3 */ + +-#if defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) && !defined(CONFIG_DM_ETH) ++#if (defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) || defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32)) && !defined(CONFIG_DM_ETH) + /* The Vexpress64 BASE_FVP simulator uses SMSC91C111 */ + #define CONFIG_SMC91111 1 + #define CONFIG_SMC91111_BASE (V2M_PA_BASE + 0x01A000000) +@@ -114,7 +114,7 @@ + #ifdef CONFIG_TARGET_VEXPRESS64_JUNO + #define PHYS_SDRAM_2 (0x880000000) + #define PHYS_SDRAM_2_SIZE 0x180000000 +-#elif CONFIG_NR_DRAM_BANKS == 2 ++#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP && CONFIG_NR_DRAM_BANKS == 2 + #define PHYS_SDRAM_2 (0x880000000) + #define PHYS_SDRAM_2_SIZE 0x80000000 + #endif +@@ -171,23 +171,41 @@ + "fdt_addr_r=0x80000000\0" \ + BOOTENV + +-#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP ++#elif defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) || \ ++ defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32) + +-#define VEXPRESS_KERNEL_ADDR 0x80080000 +-#define VEXPRESS_FDT_ADDR 0x8fc00000 +-#define VEXPRESS_BOOT_ADDR 0x8fd00000 +-#define VEXPRESS_RAMDISK_ADDR 0x8fe00000 ++#define VEXPRESS_KERNEL_ADDR 0x80080000 ++#define VEXPRESS_FDT_ADDR 0x8fc00000 ++#define VEXPRESS_BOOT_ADDR 0x8fd00000 ++#define VEXPRESS_RAMDISK_ADDR 0x8fe00000 + +-#define CONFIG_EXTRA_ENV_SETTINGS \ ++#define CONFIG_EXTRA_ENV_SETTINGS \ + "kernel_name=Image\0" \ +- "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \ +- "ramdisk_name=ramdisk.img\0" \ +- "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \ +- "fdtfile=devtree.dtb\0" \ +- "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \ +- "boot_name=boot.img\0" \ +- "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0" +- ++ "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \ ++ "ramdisk_name=ramdisk.img\0" \ ++ "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \ ++ "fdtfile=devtree.dtb\0" \ ++ "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \ ++ "boot_name=boot.img\0" \ ++ "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0" ++ ++#ifndef CONFIG_BOOTCOMMAND ++#define CONFIG_BOOTCOMMAND "if smhload ${boot_name} ${boot_addr_r}; then " \ ++ " set bootargs; " \ ++ " abootimg addr ${boot_addr_r}; " \ ++ " abootimg get dtb --index=0 fdt_addr_r; " \ ++ " bootm ${boot_addr_r} ${boot_addr_r} " \ ++ " ${fdt_addr_r}; " \ ++ "else; " \ ++ " smhload ${kernel_name} ${kernel_addr_r}; " \ ++ " smhload ${fdtfile} ${fdt_addr_r}; " \ ++ " smhload ${ramdisk_name} ${initrd_addr_r} "\ ++ " initrd_end; " \ ++ " fdt addr ${fdt_addr_r}; fdt resize; " \ ++ " fdt chosen ${ramdisk_addr_r} ${initrd_end}; " \ ++ " bootz $kernel_addr_r - $fdt_addr_r; " \ ++ "fi" ++#endif + #endif + + /* Monitor Command Prompt */ +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch new file mode 100644 index 000000000000..d916d4206175 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch @@ -0,0 +1,111 @@ +From e896d48c57d272327410416887f34ac0db550390 Mon Sep 17 00:00:00 2001 +From: Jon Mason +Date: Mon, 13 Jun 2022 10:59:53 -0400 +Subject: [PATCH 2/2] Revert "vexpress64: Enable OF_CONTROL and OF_BOARD for + VExpress64" + +This patch only works for aarch64 (as the 'x' registers are not +available for ARMv7). Since this platform is ARMv7 in the previous +patch, this either needs to be changed or removed. I opted to remove +it, as it doesn't seem to be necessary to boot the virtual hardware. +Given that the previous patch was rejected upstream, it is not +appropriate to fix this upstream. + +Upstream-Status: Inappropriate +Signed-off-by: Jon Mason + +This reverts commit 2661397464e47d45cd25bbc5e6b9de7594b3268d. +--- + board/armltd/vexpress64/Makefile | 2 +- + board/armltd/vexpress64/lowlevel_init.S | 12 ------------ + board/armltd/vexpress64/vexpress64.c | 26 ------------------------- + 3 files changed, 1 insertion(+), 39 deletions(-) + delete mode 100644 board/armltd/vexpress64/lowlevel_init.S + +diff --git a/board/armltd/vexpress64/Makefile b/board/armltd/vexpress64/Makefile +index 1878fbed4ec9..868dc4f629f2 100644 +--- a/board/armltd/vexpress64/Makefile ++++ b/board/armltd/vexpress64/Makefile +@@ -3,5 +3,5 @@ + # (C) Copyright 2000-2004 + # Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +-obj-y := vexpress64.o lowlevel_init.o ++obj-y := vexpress64.o + obj-$(CONFIG_TARGET_VEXPRESS64_JUNO) += pcie.o +diff --git a/board/armltd/vexpress64/lowlevel_init.S b/board/armltd/vexpress64/lowlevel_init.S +deleted file mode 100644 +index 3dcfb85d0e9a..000000000000 +--- a/board/armltd/vexpress64/lowlevel_init.S ++++ /dev/null +@@ -1,12 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * (C) Copyright 2021 Arm Limited +- */ +- +-.global save_boot_params +-save_boot_params: +- +- adr x8, prior_stage_fdt_address +- str x0, [x8] +- +- b save_boot_params_ret +diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c +index 5e22e89824ee..cedab86d984b 100644 +--- a/board/armltd/vexpress64/vexpress64.c ++++ b/board/armltd/vexpress64/vexpress64.c +@@ -92,15 +92,7 @@ int dram_init_banksize(void) + return 0; + } + +-/* Assigned in lowlevel_init.S +- * Push the variable into the .data section so that it +- * does not get cleared later. +- */ +-unsigned long __section(".data") prior_stage_fdt_address; +- + #ifdef CONFIG_OF_BOARD +- +-#ifdef CONFIG_TARGET_VEXPRESS64_JUNO + #define JUNO_FLASH_SEC_SIZE (256 * 1024) + static phys_addr_t find_dtb_in_nor_flash(const char *partname) + { +@@ -145,11 +137,9 @@ static phys_addr_t find_dtb_in_nor_flash(const char *partname) + + return ~0; + } +-#endif + + void *board_fdt_blob_setup(int *err) + { +-#ifdef CONFIG_TARGET_VEXPRESS64_JUNO + phys_addr_t fdt_rom_addr = find_dtb_in_nor_flash(CONFIG_JUNO_DTB_PART); + + *err = 0; +@@ -159,22 +149,6 @@ void *board_fdt_blob_setup(int *err) + } + + return (void *)fdt_rom_addr; +-#endif +- +-#ifdef VEXPRESS_FDT_ADDR +- if (fdt_magic(VEXPRESS_FDT_ADDR) == FDT_MAGIC) { +- *err = 0; +- return (void *)VEXPRESS_FDT_ADDR; +- } +-#endif +- +- if (fdt_magic(prior_stage_fdt_address) == FDT_MAGIC) { +- *err = 0; +- return (void *)prior_stage_fdt_address; +- } +- +- *err = -ENXIO; +- return NULL; + } + #endif + +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg new file mode 100644 index 000000000000..716600f482aa --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg @@ -0,0 +1,3 @@ +CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda1 rw rootwait" +# Our FVP support CRC instructions +CONFIG_ARM64_CRC32=y diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch new file mode 100644 index 000000000000..dd6b77d3a521 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch @@ -0,0 +1,259 @@ +From e90aa7853ae32cb03c86249a6c572ec88cdebaa2 Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Wed, 26 May 2021 17:41:10 +0100 +Subject: [PATCH 1/9] armv8: Add ARMv8 MPU configuration logic + +Detect whether an MMU is present at the current exception level. If +not, initialize the MPU instead of the MMU during init, and clear the +MPU regions before transition to Linux. + +The MSA in use at EL1&0 may be configurable but can only by determined +by inspecting VTCR_EL2 at EL2, so assume that there is an MMU for +backwards compatibility. + +Provide a default (blank) MPU memory map, which can be overridden by +board configurations. + +Issue-Id: SCM-2443 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Change-Id: I0ee3879f9d7f03fe940664b3551c68eeaa458d17 +--- + arch/arm/cpu/armv8/cache_v8.c | 101 ++++++++++++++++++++++++++++++- + arch/arm/include/asm/armv8/mpu.h | 59 ++++++++++++++++++ + arch/arm/include/asm/system.h | 19 ++++++ + 3 files changed, 176 insertions(+), 3 deletions(-) + create mode 100644 arch/arm/include/asm/armv8/mpu.h + +diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c +index e4736e5643..798aed8058 100644 +--- a/arch/arm/cpu/armv8/cache_v8.c ++++ b/arch/arm/cpu/armv8/cache_v8.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + DECLARE_GLOBAL_DATA_PTR; + +@@ -385,6 +386,91 @@ __weak u64 get_page_table_size(void) + return size; + } + ++static void mpu_clear_regions(void) ++{ ++ int i; ++ ++ for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { ++ setup_el2_mpu_region(i, 0, 0); ++ } ++} ++ ++static struct mpu_region default_mpu_mem_map[] = {{0,}}; ++__weak struct mpu_region *mpu_mem_map = default_mpu_mem_map; ++ ++static void mpu_setup(void) ++{ ++ int i; ++ ++ if (current_el() != 2) { ++ panic("MPU configuration is only supported at EL2"); ++ } ++ ++ set_sctlr(get_sctlr() & ~(CR_M | CR_WXN)); ++ ++ asm volatile("msr MAIR_EL2, %0" : : "r" MEMORY_ATTRIBUTES); ++ ++ for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { ++ setup_el2_mpu_region(i, ++ PRBAR_ADDRESS(mpu_mem_map[i].start) ++ | PRBAR_OUTER_SH | PRBAR_AP_RW_ANY, ++ PRLAR_ADDRESS(mpu_mem_map[i].end) ++ | mpu_mem_map[i].attrs | PRLAR_EN_BIT ++ ); ++ } ++ ++ set_sctlr(get_sctlr() | CR_M); ++} ++ ++static bool el_has_mmu(void) ++{ ++ if (current_el() < 2) { ++ // We have no way of knowing, so assuming we have an MMU ++ return true; ++ } ++ ++ uint64_t id_aa64mmfr0; ++ asm volatile("mrs %0, id_aa64mmfr0_el1" ++ : "=r" (id_aa64mmfr0) : : "cc"); ++ uint64_t msa = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_MASK; ++ uint64_t msa_frac = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_FRAC_MASK; ++ ++ switch (msa) { ++ case ID_AA64MMFR0_EL1_MSA_VMSA: ++ /* ++ * VMSA supported in all translation regimes. ++ * No support for PMSA. ++ */ ++ return true; ++ case ID_AA64MMFR0_EL1_MSA_USE_FRAC: ++ /* See MSA_frac for the supported MSAs. */ ++ switch (msa_frac) { ++ case ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA: ++ /* ++ * PMSA not supported in any translation ++ * regime. ++ */ ++ return true; ++ case ID_AA64MMFR0_EL1_MSA_FRAC_VMSA: ++ /* ++ * PMSA supported in all translation ++ * regimes. No support for VMSA. ++ */ ++ case ID_AA64MMFR0_EL1_MSA_FRAC_PMSA: ++ /* ++ * PMSA supported in all translation ++ * regimes. ++ */ ++ return false; ++ default: ++ panic("Unsupported id_aa64mmfr0_el1 " \ ++ "MSA_frac value"); ++ } ++ default: ++ panic("Unsupported id_aa64mmfr0_el1 MSA value"); ++ } ++} ++ + void setup_pgtables(void) + { + int i; +@@ -499,8 +585,13 @@ void dcache_enable(void) + /* The data cache is not active unless the mmu is enabled */ + if (!(get_sctlr() & CR_M)) { + invalidate_dcache_all(); +- __asm_invalidate_tlb_all(); +- mmu_setup(); ++ ++ if (el_has_mmu()) { ++ __asm_invalidate_tlb_all(); ++ mmu_setup(); ++ } else { ++ mpu_setup(); ++ } + } + + set_sctlr(get_sctlr() | CR_C); +@@ -519,7 +610,11 @@ void dcache_disable(void) + set_sctlr(sctlr & ~(CR_C|CR_M)); + + flush_dcache_all(); +- __asm_invalidate_tlb_all(); ++ ++ if (el_has_mmu()) ++ __asm_invalidate_tlb_all(); ++ else ++ mpu_clear_regions(); + } + + int dcache_status(void) +diff --git a/arch/arm/include/asm/armv8/mpu.h b/arch/arm/include/asm/armv8/mpu.h +new file mode 100644 +index 0000000000..8de627cafd +--- /dev/null ++++ b/arch/arm/include/asm/armv8/mpu.h +@@ -0,0 +1,59 @@ ++/* ++ * SPDX-License-Identifier: GPL-2.0+ ++ * ++ * (C) Copyright 2021 Arm Limited ++ */ ++ ++#ifndef _ASM_ARMV8_MPU_H_ ++#define _ASM_ARMV8_MPU_H_ ++ ++#include ++#include ++ ++#define PRSELR_EL2 S3_4_c6_c2_1 ++#define PRBAR_EL2 S3_4_c6_c8_0 ++#define PRLAR_EL2 S3_4_c6_c8_1 ++#define MPUIR_EL2 S3_4_c0_c0_4 ++ ++#define PRBAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) ++ ++/* Access permissions */ ++#define PRBAR_AP(val) (((val) & 0x3) << 2) ++#define PRBAR_AP_RW_HYP PRBAR_AP(0x0) ++#define PRBAR_AP_RW_ANY PRBAR_AP(0x1) ++#define PRBAR_AP_RO_HYP PRBAR_AP(0x2) ++#define PRBAR_AP_RO_ANY PRBAR_AP(0x3) ++ ++/* Shareability */ ++#define PRBAR_SH(val) (((val) & 0x3) << 4) ++#define PRBAR_NON_SH PRBAR_SH(0x0) ++#define PRBAR_OUTER_SH PRBAR_SH(0x2) ++#define PRBAR_INNER_SH PRBAR_SH(0x3) ++ ++/* Memory attribute (MAIR idx) */ ++#define PRLAR_ATTRIDX(val) (((val) & 0x7) << 1) ++#define PRLAR_EN_BIT (0x1) ++#define PRLAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) ++ ++#ifndef __ASSEMBLY__ ++ ++static inline void setup_el2_mpu_region(uint8_t region, uint64_t base, uint64_t limit) ++{ ++ asm volatile("msr " __stringify(PRSELR_EL2) ", %0" : : "r" (region)); ++ asm volatile("msr " __stringify(PRBAR_EL2) ", %0" : : "r" (base)); ++ asm volatile("msr " __stringify(PRLAR_EL2) ", %0" : : "r" (limit)); ++ ++ asm volatile("isb"); ++} ++ ++#endif ++ ++struct mpu_region { ++ u64 start; ++ u64 end; ++ u64 attrs; ++}; ++ ++extern struct mpu_region *mpu_mem_map; ++ ++#endif /* _ASM_ARMV8_MPU_H_ */ +diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h +index 87d1c77e8b..4510db98a2 100644 +--- a/arch/arm/include/asm/system.h ++++ b/arch/arm/include/asm/system.h +@@ -95,6 +95,25 @@ + auth algorithm */ + #define ID_AA64ISAR1_EL1_APA (0xF << 4) /* QARMA address auth algorithm */ + ++/* ++ * ID_AA64MMFR0_EL1 bits definitions ++ */ ++#define ID_AA64MMFR0_EL1_MSA_FRAC_MASK (0xFUL << 52) /* Memory system ++ architecture ++ frac */ ++#define ID_AA64MMFR0_EL1_MSA_FRAC_VMSA (0x2UL << 52) /* EL1&0 supports ++ VMSA */ ++#define ID_AA64MMFR0_EL1_MSA_FRAC_PMSA (0x1UL << 52) /* EL1&0 only ++ supports PMSA*/ ++#define ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA (0x0UL << 52) /* No PMSA ++ support */ ++#define ID_AA64MMFR0_EL1_MSA_MASK (0xFUL << 48) /* Memory system ++ architecture */ ++#define ID_AA64MMFR0_EL1_MSA_USE_FRAC (0xFUL << 48) /* Use MSA_FRAC */ ++#define ID_AA64MMFR0_EL1_MSA_VMSA (0x0UL << 48) /* Memory system ++ architecture ++ is VMSA */ ++ + /* + * ID_AA64PFR0_EL1 bits definitions + */ +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch new file mode 100644 index 000000000000..b8cab45e407e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch @@ -0,0 +1,61 @@ +From 181f5efb401ffaa5ab0898b07a976796f75e502a Mon Sep 17 00:00:00 2001 +From: Qi Feng +Date: Tue, 26 Jul 2022 18:13:23 +0800 +Subject: [PATCH 2/9] vexpress64: add MPU memory map for the BASER_FVP + +The previous patch added support for initializing an Armv8 MPU. There is only an +MPU at S-EL2 on the BASER_FVP, so add a platform-specific MPU memory map. + +See https://developer.arm.com/documentation/100964/1117/Base-Platform/Base---memory/BaseR-Platform-memory-map + +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Signed-off-by: Qi Feng +--- + board/armltd/vexpress64/vexpress64.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c +index af326dc6f4..2310d18eb7 100644 +--- a/board/armltd/vexpress64/vexpress64.c ++++ b/board/armltd/vexpress64/vexpress64.c +@@ -19,6 +19,7 @@ + #include + #include "pcie.h" + #include ++#include + #ifdef CONFIG_VIRTIO_NET + #include + #include +@@ -37,6 +38,27 @@ U_BOOT_DRVINFO(vexpress_serials) = { + .plat = &serial_plat, + }; + ++static struct mpu_region vexpress64_aemv8r_mem_map[] = { ++ { ++ .start = 0x0UL, ++ .end = 0x7fffffffUL, ++ .attrs = PRLAR_ATTRIDX(MT_NORMAL) ++ }, { ++ .start = 0x80000000UL, ++ .end = 0xffffffffUL, ++ .attrs = PRLAR_ATTRIDX(MT_DEVICE_NGNRNE) ++ }, { ++ .start = 0x100000000UL, ++ .end = 0xffffffffffUL, ++ .attrs = PRLAR_ATTRIDX(MT_NORMAL) ++ }, { ++ /* List terminator */ ++ 0, ++ } ++}; ++ ++struct mpu_region *mpu_mem_map = vexpress64_aemv8r_mem_map; ++ + static struct mm_region vexpress64_mem_map[] = { + { + .virt = V2M_PA_BASE, +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch new file mode 100644 index 000000000000..caabf804b2f2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch @@ -0,0 +1,107 @@ +From 07cc3e4af3def76d92faf39712d4fd8717b21d2b Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Fri, 10 Dec 2021 11:41:19 +0000 +Subject: [PATCH 3/9] armv8: Allow disabling exception vectors on non-SPL + builds + +On the BASER_FVP, U-Boot shares EL2 with another bootloader, so we do +not wish to overide the exception vector, but we are also not using an +SPL build. + +Therefore, add ARMV8_EXCEPTION_VECTORS, which disables exception vectors +in a similar way to ARMV8_SPL_EXCEPTION_VECTORS. + +Rename ARMV8_SPL_EXCEPTION_VECTORS -> SPL_ARMV8_EXCEPTION_VECTORS so +that both config flags be be targeted using CONFIG_IS_ENABLED. + +Issue-Id: SCM-3728 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Change-Id: I0cf0fc6d7ef4d45791411cf1f67c65e198cc8b2b +--- + arch/arm/cpu/armv8/Kconfig | 10 ++++++++-- + arch/arm/cpu/armv8/Makefile | 6 ++---- + arch/arm/cpu/armv8/start.S | 4 ++-- + configs/vexpress_aemv8r_defconfig | 1 + + 4 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index 1305238c9d..dec4be0e30 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -1,8 +1,8 @@ + if ARM64 + +-config ARMV8_SPL_EXCEPTION_VECTORS ++config ARMV8_EXCEPTION_VECTORS + bool "Install crash dump exception vectors" +- depends on SPL ++ default y + help + The default exception vector table is only used for the crash + dump, but still takes quite a lot of space in the image size. +@@ -10,6 +10,12 @@ config ARMV8_SPL_EXCEPTION_VECTORS + Say N here if you are running out of code space in the image + and want to save some space at the cost of less debugging info. + ++config SPL_ARMV8_EXCEPTION_VECTORS ++ bool "Install crash dump exception vectors in the SPL" ++ depends on SPL ++ help ++ Same as ARMV8_EXCEPTION_VECTORS, but for SPL builds ++ + config ARMV8_MULTIENTRY + bool "Enable multiple CPUs to enter into U-Boot" + +diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile +index 2e4bf9e038..001a31cae7 100644 +--- a/arch/arm/cpu/armv8/Makefile ++++ b/arch/arm/cpu/armv8/Makefile +@@ -13,10 +13,8 @@ ifndef CONFIG_$(SPL_)SYS_DCACHE_OFF + obj-y += cache_v8.o + obj-y += cache.o + endif +-ifdef CONFIG_SPL_BUILD +-obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o +-else +-obj-y += exceptions.o ++obj-$(CONFIG_$(SPL_)ARMV8_EXCEPTION_VECTORS) += exceptions.o ++ifndef CONFIG_SPL_BUILD + obj-y += exception_level.o + endif + obj-y += tlb.o +diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S +index 28f0df13f0..f831e77af3 100644 +--- a/arch/arm/cpu/armv8/start.S ++++ b/arch/arm/cpu/armv8/start.S +@@ -104,7 +104,7 @@ pie_skip_reloc: + pie_fixup_done: + #endif + +-#if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) ++#if CONFIG_IS_ENABLED(ARMV8_EXCEPTION_VECTORS) + .macro set_vbar, regname, reg + msr \regname, \reg + .endm +@@ -354,7 +354,7 @@ ENDPROC(smp_kick_all_cpus) + /*-----------------------------------------------------------------------*/ + + ENTRY(c_runtime_cpu_setup) +-#if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) ++#if CONFIG_IS_ENABLED(ARMV8_EXCEPTION_VECTORS) + /* Relocate vBAR */ + adr x0, vectors + switch_el x1, 3f, 2f, 1f +diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig +index 495eb1dee3..683d983c36 100644 +--- a/configs/vexpress_aemv8r_defconfig ++++ b/configs/vexpress_aemv8r_defconfig +@@ -16,3 +16,4 @@ CONFIG_SYS_CBSIZE=512 + CONFIG_SYS_PBSIZE=541 + # CONFIG_MMC is not set + CONFIG_VIRTIO_MMIO=y ++CONFIG_ARMV8_EXCEPTION_VECTORS=n +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch new file mode 100644 index 000000000000..81758fce711f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch @@ -0,0 +1,142 @@ +From 30405f59881c73946b6b0ffdbf25804f9fbf1585 Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Wed, 14 Jul 2021 12:44:27 +0100 +Subject: [PATCH 4/9] armv8: ARMV8_SWITCH_TO_EL1 improvements + +Convert CONFIG_ARMV8_SWITCH_TO_EL1 to a Kconfig variable. + +Add support for switching to EL1 to bootefi. + +Add the environment variable armv8_switch_to_el1 to allow configuring +whether to switch to EL1 at runtime. This overrides the compile-time +option. + +Issue-Id: SCM-3728 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Change-Id: If98478148d6d8d1f732acac5439276700614815f +--- + arch/arm/cpu/armv8/exception_level.c | 21 ++++++++++++++-- + arch/arm/lib/bootm.c | 36 ++++++++++++++++------------ + configs/vexpress_aemv8r_defconfig | 1 + + 3 files changed, 41 insertions(+), 17 deletions(-) + +diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c +index b11936548f..4aad1550f4 100644 +--- a/arch/arm/cpu/armv8/exception_level.c ++++ b/arch/arm/cpu/armv8/exception_level.c +@@ -40,19 +40,36 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) + * trusted firmware being one embodiment). The operating system shall be + * started at exception level EL2. So here we check the exception level + * and switch it if necessary. ++ * ++ * If armv8_switch_to_el1 (config or env var) is enabled, also switch to EL1 ++ * before booting the operating system. + */ + void switch_to_non_secure_mode(void) + { + struct jmp_buf_data non_secure_jmp; + + /* On AArch64 we need to make sure we call our payload in < EL3 */ +- if (current_el() == 3) { ++ ++ int switch_to_el1 = env_get_yesno("armv8_switch_to_el1"); ++#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 ++ if (switch_to_el1 == -1) { ++ switch_to_el1 = 1; ++ } ++#endif ++ ++ if (current_el() > 2) { + if (setjmp(&non_secure_jmp)) + return; + dcache_disable(); /* flush cache before switch to EL2 */ +- + /* Move into EL2 and keep running there */ + armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0, + (uintptr_t)entry_non_secure, ES_TO_AARCH64); ++ } else if (switch_to_el1 == 1 && current_el() > 1) { ++ if (setjmp(&non_secure_jmp)) ++ return; ++ dcache_disable(); /* flush cache before switch to EL1 */ ++ /* Move into EL1 and keep running there */ ++ armv8_switch_to_el1((uintptr_t)&non_secure_jmp, 0, 0, 0, ++ (uintptr_t)entry_non_secure, ES_TO_AARCH64); + } + } +diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c +index 9f086f3b90..b044aeca88 100644 +--- a/arch/arm/lib/bootm.c ++++ b/arch/arm/lib/bootm.c +@@ -270,7 +270,6 @@ __weak void update_os_arch_secondary_cores(uint8_t os_arch) + { + } + +-#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + static void switch_to_el1(void) + { + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && +@@ -285,7 +284,6 @@ static void switch_to_el1(void) + ES_TO_AARCH64); + } + #endif +-#endif + + /* Subcommand: GO */ + static void boot_jump_linux(bootm_headers_t *images, int flag) +@@ -312,21 +310,29 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) + + update_os_arch_secondary_cores(images->os.arch); + ++ int armv8_switch_to_el1 = env_get_yesno("armv8_switch_to_el1"); + #ifdef CONFIG_ARMV8_SWITCH_TO_EL1 +- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, +- (u64)switch_to_el1, ES_TO_AARCH64); +-#else +- if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && +- (images->os.arch == IH_ARCH_ARM)) +- armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, +- (u64)images->ft_addr, 0, +- (u64)images->ep, +- ES_TO_AARCH32); +- else +- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, +- images->ep, +- ES_TO_AARCH64); ++ if (armv8_switch_to_el1 == -1) { ++ armv8_switch_to_el1 = 1; ++ } + #endif ++ if (armv8_switch_to_el1 == 1) { ++ armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, ++ (u64)switch_to_el1, ES_TO_AARCH64); ++ } else { ++ if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && ++ (images->os.arch == IH_ARCH_ARM)) ++ armv8_switch_to_el2(0, ++ (u64)gd->bd->bi_arch_number, ++ (u64)images->ft_addr, 0, ++ (u64)images->ep, ++ ES_TO_AARCH32); ++ else ++ armv8_switch_to_el2((u64)images->ft_addr, ++ 0, 0, 0, ++ images->ep, ++ ES_TO_AARCH64); ++ } + } + #else + unsigned long machid = gd->bd->bi_arch_number; +diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig +index 683d983c36..6044f82b00 100644 +--- a/configs/vexpress_aemv8r_defconfig ++++ b/configs/vexpress_aemv8r_defconfig +@@ -17,3 +17,4 @@ CONFIG_SYS_PBSIZE=541 + # CONFIG_MMC is not set + CONFIG_VIRTIO_MMIO=y + CONFIG_ARMV8_EXCEPTION_VECTORS=n ++CONFIG_ARMV8_SWITCH_TO_EL1=y +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch new file mode 100644 index 000000000000..f64db3bf4649 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch @@ -0,0 +1,83 @@ +From a6daca56b77d7f1b26483f10eb33ebdd6e157d3e Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Fri, 10 Dec 2021 16:37:26 +0000 +Subject: [PATCH 5/9] armv8: Make disabling HVC configurable when switching to + EL1 + +On the BASER_FVP there is no EL3, so HVC is used to provide PSCI +services. Therefore we cannot disable hypercalls. + +Create CONFIG_ARMV8_DISABLE_HVC (dependent on CONFIG_ARMV8_TO_EL1) to +control whether to disable HVC exceptions in HCR_EL2->HCD + +Issue-Id: SCM-3728 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Change-Id: I463d82f1db8a3cafcab40a9c0c208753569cc300 +--- + arch/arm/cpu/armv8/Kconfig | 9 +++++++++ + arch/arm/include/asm/macro.h | 10 ++++++++-- + configs/vexpress_aemv8r_defconfig | 1 + + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index dec4be0e30..95c03487a2 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -208,4 +208,13 @@ config ARMV8_CE_SHA256 + + endif + ++config ARMV8_DISABLE_HVC ++ bool "Disable HVC calls before switching to EL1" ++ depends on ARMV8_SWITCH_TO_EL1 ++ default y ++ help ++ If switching to EL1 before loading the operating system, disable taking ++ hypercalls back to EL2. May be disabled if, for example, PSCI services are ++ running at EL2. ++ + endif +diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h +index 1a1edc9870..7167739210 100644 +--- a/arch/arm/include/asm/macro.h ++++ b/arch/arm/include/asm/macro.h +@@ -296,9 +296,12 @@ lr .req x30 + ldr \tmp2, =(ID_AA64ISAR1_EL1_GPI | ID_AA64ISAR1_EL1_GPA | \ + ID_AA64ISAR1_EL1_API | ID_AA64ISAR1_EL1_APA) + tst \tmp, \tmp2 +- mov \tmp2, #(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS) ++ mov \tmp2, #(HCR_EL2_RW_AARCH64) + orr \tmp, \tmp2, #(HCR_EL2_APK | HCR_EL2_API) + csel \tmp, \tmp2, \tmp, eq ++#ifdef CONFIG_ARMV8_DISABLE_HVC ++ orr \tmp, \tmp, #(HCR_EL2_HCD_DIS) ++#endif + msr hcr_el2, \tmp + + /* Return to the EL1_SP1 mode from EL2 */ +@@ -311,7 +314,10 @@ lr .req x30 + + 1: + /* Initialize HCR_EL2 */ +- ldr \tmp, =(HCR_EL2_RW_AARCH32 | HCR_EL2_HCD_DIS) ++ ldr \tmp, =(HCR_EL2_RW_AARCH32) ++#ifdef CONFIG_ARMV8_DISABLE_HVC ++ orr \tmp, \tmp, #(HCR_EL2_HCD_DIS) ++#endif + msr hcr_el2, \tmp + + /* Return to AArch32 Supervisor mode from EL2 */ +diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig +index 6044f82b00..6226f6b2c1 100644 +--- a/configs/vexpress_aemv8r_defconfig ++++ b/configs/vexpress_aemv8r_defconfig +@@ -18,3 +18,4 @@ CONFIG_SYS_PBSIZE=541 + CONFIG_VIRTIO_MMIO=y + CONFIG_ARMV8_EXCEPTION_VECTORS=n + CONFIG_ARMV8_SWITCH_TO_EL1=y ++CONFIG_ARMV8_DISABLE_HVC=n +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch new file mode 100644 index 000000000000..ebbc939c0523 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch @@ -0,0 +1,32 @@ +From 862d3f1ac66a75cdf48adbdebd8adbaf671a9366 Mon Sep 17 00:00:00 2001 +From: Qi Feng +Date: Thu, 28 Jul 2022 17:47:18 +0800 +Subject: [PATCH 6/9] vexpress64: Do not set COUNTER_FREQUENCY + +VExpress boards normally run as a second-stage bootloader so should not +need to modify CNTFRQ_EL0. On the BASER_FVP, U-Boot can modify it if +running at EL2, but shouldn't because it might be different from the +value being used by the first-stage bootloader (which might be +providing PSCI services). + +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Signed-off-by: Qi Feng +--- + configs/vexpress_aemv8r_defconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig +index 6226f6b2c1..b902a6a7d9 100644 +--- a/configs/vexpress_aemv8r_defconfig ++++ b/configs/vexpress_aemv8r_defconfig +@@ -1,5 +1,4 @@ + CONFIG_ARM=y +-CONFIG_COUNTER_FREQUENCY=24000000 + CONFIG_ARCH_VEXPRESS64=y + CONFIG_NR_DRAM_BANKS=2 + CONFIG_DEFAULT_DEVICE_TREE="arm_fvp" +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch new file mode 100644 index 000000000000..8c09ed2b74d7 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch @@ -0,0 +1,27 @@ +From 32beea722c1167c9b33f1ecfdc28d360cabd6823 Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Tue, 22 Feb 2022 15:32:51 +0000 +Subject: [PATCH 7/9] vexpress64: Enable LIBFDT_OVERLAY in the vexpress_aemv8r + defconfig + +Issue-Id: SCM-3874 +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Signed-off-by: Peter Hoyes +Change-Id: Ide0532cf2de89f1bca9c8d4bd2ed0c1a1c57599f +--- + configs/vexpress_aemv8r_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig +index b902a6a7d9..a58a9db385 100644 +--- a/configs/vexpress_aemv8r_defconfig ++++ b/configs/vexpress_aemv8r_defconfig +@@ -18,3 +18,4 @@ CONFIG_VIRTIO_MMIO=y + CONFIG_ARMV8_EXCEPTION_VECTORS=n + CONFIG_ARMV8_SWITCH_TO_EL1=y + CONFIG_ARMV8_DISABLE_HVC=n ++CONFIG_OF_LIBFDT_OVERLAY=y +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch new file mode 100644 index 000000000000..8be14ee85a97 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch @@ -0,0 +1,105 @@ +From 01490ab8deb0f0b61eeb55a02ee5ea430cfe7eee Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Wed, 18 May 2022 15:24:19 +0100 +Subject: [PATCH 8/9] armv8: Allow PRBAR MPU attributes to be configured + +In a previous patch, support was added to initialize an S-EL2 MPU on +armv8r64 machines. This implementation allowed the PRLAR attribute +index to be configured, but not the shareability and access permission +attributes in PRBAR. These attributes were hard-coded as "outer +shareable" and "read/write at EL1 and EL0". + +Add separate prlar_attrs and prbar_attrs to the MPU region struct so +that these attributes can be configured on a per-region basis. + +For the BASER_FVP, ensure the MPU memory attributes match those in the +existing vexpress64 board MMU configuration ("non shareable" for device +memory and "inner shareable" for normal memory). + +Issue-Id: SCM-4641 +Signed-off-by: Peter Hoyes +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Change-Id: I6b72aead91ad12412262aa32c61a53e12eab3984 +--- + arch/arm/cpu/armv8/cache_v8.c | 12 ++++++++---- + arch/arm/include/asm/armv8/mpu.h | 3 ++- + board/armltd/vexpress64/vexpress64.c | 9 ++++++--- + 3 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c +index 798aed8058..e336339281 100644 +--- a/arch/arm/cpu/armv8/cache_v8.c ++++ b/arch/arm/cpu/armv8/cache_v8.c +@@ -390,7 +390,9 @@ static void mpu_clear_regions(void) + { + int i; + +- for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { ++ for (i = 0; mpu_mem_map[i].end || ++ mpu_mem_map[i].prbar_attrs || ++ mpu_mem_map[i].prlar_attrs; i++) { + setup_el2_mpu_region(i, 0, 0); + } + } +@@ -410,12 +412,14 @@ static void mpu_setup(void) + + asm volatile("msr MAIR_EL2, %0" : : "r" MEMORY_ATTRIBUTES); + +- for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { ++ for (i = 0; mpu_mem_map[i].end || ++ mpu_mem_map[i].prbar_attrs || ++ mpu_mem_map[i].prlar_attrs; i++) { + setup_el2_mpu_region(i, + PRBAR_ADDRESS(mpu_mem_map[i].start) +- | PRBAR_OUTER_SH | PRBAR_AP_RW_ANY, ++ | mpu_mem_map[i].prbar_attrs, + PRLAR_ADDRESS(mpu_mem_map[i].end) +- | mpu_mem_map[i].attrs | PRLAR_EN_BIT ++ | mpu_mem_map[i].prlar_attrs | PRLAR_EN_BIT + ); + } + +diff --git a/arch/arm/include/asm/armv8/mpu.h b/arch/arm/include/asm/armv8/mpu.h +index 8de627cafd..dd4c689ea6 100644 +--- a/arch/arm/include/asm/armv8/mpu.h ++++ b/arch/arm/include/asm/armv8/mpu.h +@@ -51,7 +51,8 @@ static inline void setup_el2_mpu_region(uint8_t region, uint64_t base, uint64_t + struct mpu_region { + u64 start; + u64 end; +- u64 attrs; ++ u64 prbar_attrs; ++ u64 prlar_attrs; + }; + + extern struct mpu_region *mpu_mem_map; +diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c +index 2310d18eb7..531fa4d618 100644 +--- a/board/armltd/vexpress64/vexpress64.c ++++ b/board/armltd/vexpress64/vexpress64.c +@@ -42,15 +42,18 @@ static struct mpu_region vexpress64_aemv8r_mem_map[] = { + { + .start = 0x0UL, + .end = 0x7fffffffUL, +- .attrs = PRLAR_ATTRIDX(MT_NORMAL) ++ .prbar_attrs = PRBAR_INNER_SH | PRBAR_AP_RW_ANY, ++ .prlar_attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + .start = 0x80000000UL, + .end = 0xffffffffUL, +- .attrs = PRLAR_ATTRIDX(MT_DEVICE_NGNRNE) ++ .prbar_attrs = PRBAR_OUTER_SH | PRBAR_AP_RW_ANY, ++ .prlar_attrs = PRLAR_ATTRIDX(MT_DEVICE_NGNRNE) + }, { + .start = 0x100000000UL, + .end = 0xffffffffffUL, +- .attrs = PRLAR_ATTRIDX(MT_NORMAL) ++ .prbar_attrs = PRBAR_INNER_SH | PRBAR_AP_RW_ANY, ++ .prlar_attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + /* List terminator */ + 0, +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch new file mode 100644 index 000000000000..0e0a248136dd --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch @@ -0,0 +1,63 @@ +From 0f15f6b02825b042ddc1d753f62cf87f30b1fe12 Mon Sep 17 00:00:00 2001 +From: Peter Hoyes +Date: Thu, 19 May 2022 09:02:32 +0100 +Subject: [PATCH 9/9] armv8: Enable icache when switching exception levels in + bootefi + +bootefi calls the function switch_to_non_secure_mode before calling the +UEFI payload to handle the case where U-Boot is running at EL3. + +For AArch64, the UEFI specification states that: + The core will be configured as follows: + * MMU enabled + * Instruction and data caches enabled + +These requirements should be followed when switching exception levels +for EFI applications. + +This function already disables and re-enables the data cache prior to +switching exception levels, but omits the instruction cache, meaning +the function returns with the instruction cache disabled at the new +exception level. Fix this by calling icache_disable prior to switching +exception levels and icache_enable afterwards. + +Issue-Id: SCM-4641 +Signed-off-by: Peter Hoyes +Upstream-Status: Inappropriate [other] + Implementation pending further discussion +Change-Id: I678cd5ba39b56e124ab7854608289cd14651ce65 +--- + arch/arm/cpu/armv8/exception_level.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c +index 4aad1550f4..0a3e5428e7 100644 +--- a/arch/arm/cpu/armv8/exception_level.c ++++ b/arch/arm/cpu/armv8/exception_level.c +@@ -27,6 +27,7 @@ + static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) + { + dcache_enable(); ++ icache_enable(); + debug("Reached non-secure mode\n"); + + /* Restore stack and registers saved in switch_to_non_secure_mode() */ +@@ -61,6 +62,7 @@ void switch_to_non_secure_mode(void) + if (setjmp(&non_secure_jmp)) + return; + dcache_disable(); /* flush cache before switch to EL2 */ ++ icache_disable(); + /* Move into EL2 and keep running there */ + armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0, + (uintptr_t)entry_non_secure, ES_TO_AARCH64); +@@ -68,6 +70,7 @@ void switch_to_non_secure_mode(void) + if (setjmp(&non_secure_jmp)) + return; + dcache_disable(); /* flush cache before switch to EL1 */ ++ icache_disable(); + /* Move into EL1 and keep running there */ + armv8_switch_to_el1((uintptr_t)&non_secure_jmp, 0, 0, 0, + (uintptr_t)entry_non_secure, ES_TO_AARCH64); +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/juno/0001-configs-vexpress-modify-to-boot-compressed-initramfs.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/juno/0001-configs-vexpress-modify-to-boot-compressed-initramfs.patch new file mode 100644 index 000000000000..0967df76dd87 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/juno/0001-configs-vexpress-modify-to-boot-compressed-initramfs.patch @@ -0,0 +1,27 @@ +From 726f8b4dbd3c5b1873aad531d5e26af3acd9b9ca Mon Sep 17 00:00:00 2001 +From: Jon Mason +Date: Mon, 19 Dec 2022 11:36:04 -0500 +Subject: [PATCH] configs: vexpress: modify to boot compressed initramfs + +Signed-off-by: Jon Mason +Upstream-Status: Inappropriate +--- + include/configs/vexpress_aemv8.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h +index 0c11b6b3331e..4ba4bebfbbae 100644 +--- a/include/configs/vexpress_aemv8.h ++++ b/include/configs/vexpress_aemv8.h +@@ -192,8 +192,10 @@ + #define VEXPRESS_RAMDISK_ADDR 0x8fe00000 + + #define EXTRA_ENV_NAMES \ ++ "kernel_comp_addr_r=0x90000000\0" \ ++ "kernel_comp_size=0x3000000\0" \ + "kernel_name=norkern\0" \ +- "kernel_alt_name=Image\0" \ ++ "kernel_alt_name=Image.gz\0" \ + "ramdisk_name=ramdisk.img\0" \ + "fdtfile=board.dtb\0" \ + "fdt_alt_name=juno\0" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0001-arm-total_compute-update-secure-dram-size.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0001-arm-total_compute-update-secure-dram-size.patch new file mode 100644 index 000000000000..85b14b03e824 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0001-arm-total_compute-update-secure-dram-size.patch @@ -0,0 +1,33 @@ +From f7c24393604e45012447b16aaa95eb5e7224ba07 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Tue, 12 Apr 2022 12:43:49 +0100 +Subject: [PATCH] arm: total_compute: update secure dram size + +Update secure DRAM size as it is increased by 64MB for additional +secure partitions. + +Signed-off-by: Arunachalam Ganapathy +Change-Id: Id8ce99c7a5330d3c28d473009c4db04141e6fa4d +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/configs/total_compute.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/configs/total_compute.h b/include/configs/total_compute.h +index 0324b1e1b217..62bdb4f6a3ae 100644 +--- a/include/configs/total_compute.h ++++ b/include/configs/total_compute.h +@@ -23,8 +23,8 @@ + + /* Physical Memory Map */ + #define PHYS_SDRAM_1 0x80000000 +-/* Top 48MB reserved for secure world use */ +-#define DRAM_SEC_SIZE 0x03000000 ++/* Top 112MB reserved for secure world use */ ++#define DRAM_SEC_SIZE 0x07000000 + #define PHYS_SDRAM_1_SIZE 0x80000000 - DRAM_SEC_SIZE + #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0002-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0002-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch new file mode 100644 index 000000000000..7749858188df --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0002-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch @@ -0,0 +1,2611 @@ +From 42fd69fb5ec0c441b3d31ec544ed03bedab28d45 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 16 Nov 2021 12:34:52 +0000 +Subject: [PATCH 2/7] arm_ffa: introducing Arm FF-A low-level driver + +This driver implements Arm Firmware Framework for Armv8-A on u-boot + +The Firmware Framework for Arm A-profile processors (FF-A) +describes interfaces (ABIs) that standardize communication +between the Secure World and Normal World leveraging TrustZone +technology. + +This driver is based on FF-A specification v1.0 and uses SMC32 +calling convention. + +FF-A specification: + +https://developer.arm.com/documentation/den0077/a/?lang=en + +The driver provides helper FF-A interfaces for user layers. +These helper functions allow clients to pass data and select the +FF-A function to use for the communication with secure world. + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Rui Miguel Silva +Upstream-Status: Submitted [https://patchwork.ozlabs.org/project/uboot/patch/20220801172053.20163-4-abdellatif.elkhlifi@arm.com/] +--- + MAINTAINERS | 8 + + arch/arm/cpu/armv8/smccc-call.S | 27 + + arch/arm/lib/asm-offsets.c | 6 + + common/board_r.c | 6 + + drivers/Kconfig | 2 + + drivers/Makefile | 1 + + drivers/arm-ffa/Kconfig | 26 + + drivers/arm-ffa/Makefile | 3 + + drivers/arm-ffa/arm-ffa-uclass.c | 67 ++ + drivers/arm-ffa/arm_ffa_prv.h | 199 ++++ + drivers/arm-ffa/core.c | 1484 ++++++++++++++++++++++++++++++ + include/arm_ffa.h | 191 ++++ + include/arm_ffa_helper.h | 45 + + include/dm/uclass-id.h | 1 + + include/linux/arm-smccc.h | 28 +- + lib/Kconfig | 1 + + lib/Makefile | 1 + + lib/arm-ffa/Kconfig | 6 + + lib/arm-ffa/Makefile | 8 + + lib/arm-ffa/arm_ffa_helper.c | 188 ++++ + lib/efi_loader/efi_boottime.c | 17 + + 21 files changed, 2314 insertions(+), 1 deletion(-) + create mode 100644 drivers/arm-ffa/Kconfig + create mode 100644 drivers/arm-ffa/Makefile + create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c + create mode 100644 drivers/arm-ffa/arm_ffa_prv.h + create mode 100644 drivers/arm-ffa/core.c + create mode 100644 include/arm_ffa.h + create mode 100644 include/arm_ffa_helper.h + create mode 100644 lib/arm-ffa/Kconfig + create mode 100644 lib/arm-ffa/Makefile + create mode 100644 lib/arm-ffa/arm_ffa_helper.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 96582fc677..14307e6da6 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -232,6 +232,14 @@ F: board/CZ.NIC/ + F: configs/turris_*_defconfig + F: include/configs/turris_*.h + ++ARM FF-A ++M: Abdellatif El Khlifi ++S: Maintained ++F: drivers/arm-ffa/ ++F: include/arm_ffa.h ++F: include/arm_ffa_helper.h ++F: lib/arm-ffa/ ++ + ARM FREESCALE IMX + M: Stefano Babic + M: Fabio Estevam +diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S +index dc92b28777..ffc39c9fef 100644 +--- a/arch/arm/cpu/armv8/smccc-call.S ++++ b/arch/arm/cpu/armv8/smccc-call.S +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Copyright (c) 2015, Linaro Limited ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi + */ + #include + #include +@@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc) + ENTRY(__arm_smccc_hvc) + SMCCC hvc + ENDPROC(__arm_smccc_hvc) ++ ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ ++ .macro FFASMCCC instr ++ .cfi_startproc ++ \instr #0 ++ ldr x9, [sp] ++ stp x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS] ++ stp x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS] ++ stp x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS] ++ stp x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS] ++ ret ++ .cfi_endproc ++ .endm ++ ++/* ++ * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, ++ * unsigned long a3, unsigned long a4, unsigned long a5, ++ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) ++ */ ++ENTRY(__arm_ffa_smccc_smc) ++ FFASMCCC smc ++ENDPROC(__arm_ffa_smccc_smc) ++ ++#endif +diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c +index 22fd541f9a..45eca83a47 100644 +--- a/arch/arm/lib/asm-offsets.c ++++ b/arch/arm/lib/asm-offsets.c +@@ -9,6 +9,8 @@ + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. ++ * ++ * (C) Copyright 2021 ARM Limited + */ + + #include +@@ -115,6 +117,10 @@ int main(void) + #ifdef CONFIG_ARM_SMCCC + DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0)); + DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++ DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4)); ++ DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6)); ++#endif + DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); + DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); + #endif +diff --git a/common/board_r.c b/common/board_r.c +index c24d9b4e22..af20f38b10 100644 +--- a/common/board_r.c ++++ b/common/board_r.c +@@ -61,6 +61,9 @@ + #include + #include + #include ++#ifdef CONFIG_ARM_FFA_TRANSPORT ++#include ++#endif + + DECLARE_GLOBAL_DATA_PTR; + +@@ -770,6 +773,9 @@ static init_fnc_t init_sequence_r[] = { + INIT_FUNC_WATCHDOG_RESET + initr_net, + #endif ++#ifdef CONFIG_ARM_FFA_TRANSPORT ++ ffa_helper_init_device, ++#endif + #ifdef CONFIG_POST + initr_post, + #endif +diff --git a/drivers/Kconfig b/drivers/Kconfig +index b26ca8cf70..e83c23789d 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -6,6 +6,8 @@ source "drivers/core/Kconfig" + + source "drivers/adc/Kconfig" + ++source "drivers/arm-ffa/Kconfig" ++ + source "drivers/ata/Kconfig" + + source "drivers/axi/Kconfig" +diff --git a/drivers/Makefile b/drivers/Makefile +index 4e7cf28440..6671d2a604 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -107,6 +107,7 @@ obj-y += iommu/ + obj-y += smem/ + obj-y += thermal/ + obj-$(CONFIG_TEE) += tee/ ++obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/ + obj-y += axi/ + obj-y += ufs/ + obj-$(CONFIG_W1) += w1/ +diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig +new file mode 100644 +index 0000000000..d71444c1fa +--- /dev/null ++++ b/drivers/arm-ffa/Kconfig +@@ -0,0 +1,26 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++config ARM_FFA_TRANSPORT ++ bool "Enable Arm Firmware Framework for Armv8-A driver" ++ depends on DM && ARM64 ++ select ARM_SMCCC ++ select LIB_UUID ++ select ARM_FFA_TRANSPORT_HELPERS ++ select CMD_ARMFFA ++ help ++ The Firmware Framework for Arm A-profile processors (FF-A) ++ describes interfaces (ABIs) that standardize communication ++ between the Secure World and Normal World leveraging TrustZone ++ technology. ++ ++ This driver is based on FF-A specification v1.0 and uses SMC32 ++ calling convention. ++ ++ FF-A specification: ++ ++ https://developer.arm.com/documentation/den0077/a/?lang=en ++ ++ In u-boot FF-A design, the Secure World is considered as one ++ entity to communicate with. FF-A communication is handled by ++ one device and one instance. This device takes care of ++ all the interactions between Normal world and Secure World. +diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile +new file mode 100644 +index 0000000000..9fb5bea522 +--- /dev/null ++++ b/drivers/arm-ffa/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++ ++obj-y += arm-ffa-uclass.o core.o +diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c +new file mode 100644 +index 0000000000..43f6066281 +--- /dev/null ++++ b/drivers/arm-ffa/arm-ffa-uclass.c +@@ -0,0 +1,67 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++UCLASS_DRIVER(ffa) = { ++ .name = "ffa", ++ .id = UCLASS_FFA, ++}; ++ ++/** ++ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher ++ * @func_id: The FF-A function to be used ++ * @func_data: Pointer to the FF-A function arguments ++ * container structure. This also includes ++ * pointers to the returned data needed by ++ * clients. ++ * ++ * This runtime function passes the FF-A function ID and its arguments to ++ * the FF-A driver dispatcher. ++ * This function is called by the FF-A helper functions. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data) ++{ ++ if (!ffa_device_get_ops()->invoke_func) ++ return -EINVAL; ++ ++ return ffa_device_get_ops()->invoke_func(func_id, func_data); ++} ++ ++/** ++ * ffa_init_device - probes the arm_ffa device ++ * ++ * This boot time function makes sure the arm_ffa device is probed ++ * and ready for use. ++ * This function is called automatically at initcalls ++ * level (after u-boot relocation). ++ * ++ * Arm FF-A transport is implemented through a single u-boot ++ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA. ++ * All FF-A clients should use the arm_ffa device to use the FF-A ++ * transport. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int ffa_init_device(void) ++{ ++ ffa_dbg("[%s]", __func__); ++ ++ return ffa_get_device(); ++} +diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h +new file mode 100644 +index 0000000000..38ea4ba83e +--- /dev/null ++++ b/drivers/arm-ffa/arm_ffa_prv.h +@@ -0,0 +1,199 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __ARM_FFA_PRV_H ++#define __ARM_FFA_PRV_H ++ ++#include ++#include ++#include ++ ++/* ++ * This header is private. It is exclusively used by the FF-A driver ++ */ ++ ++/* FF-A driver version definitions */ ++ ++#define MAJOR_VERSION_MASK GENMASK(30, 16) ++#define MINOR_VERSION_MASK GENMASK(15, 0) ++#define GET_FFA_MAJOR_VERSION(x) \ ++ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x)))) ++#define GET_FFA_MINOR_VERSION(x) \ ++ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x)))) ++#define PACK_VERSION_INFO(major, minor) \ ++ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \ ++ FIELD_PREP(MINOR_VERSION_MASK, (minor))) ++ ++#define FFA_MAJOR_VERSION (1) ++#define FFA_MINOR_VERSION (0) ++#define FFA_VERSION_1_0 \ ++ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION) ++ ++/* Endpoint ID mask (u-boot endpoint ID) */ ++ ++#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0) ++#define GET_SELF_ENDPOINT_ID(x) \ ++ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x)))) ++ ++#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16) ++#define PREP_SELF_ENDPOINT_ID(x) \ ++ ((u16)(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))) ++ ++/* Partition endpoint ID mask (partition with which u-boot communicates with) */ ++ ++#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0) ++#define PREP_PART_ENDPOINT_ID(x) \ ++ ((u16)(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))) ++ ++/* The FF-A SMC function prototype definition */ ++ ++typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1, ++ unsigned long a2, unsigned long a3, unsigned long a4, ++ unsigned long a5, unsigned long a6, unsigned long a7, ++ struct arm_smccc_res *res); ++ ++/** ++ * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver ++ * Currently only SMC32 is supported. ++ */ ++enum ffa_conduit { ++ FFA_CONDUIT_SMC = 0, ++}; ++ ++/** ++ * FFA_DECLARE_ARGS - FF-A functions local variables ++ * @a0-a7: local variables used to set registers x0-x7 ++ * @res: the structure hosting the FF-A function return data ++ * ++ * A helper macro for declaring local variables for the FF-A functions arguments. ++ * The x0-x7 registers are used to exchange data with the secure world. ++ * But, only the bottom 32-bit of thes registers contains the data. ++ */ ++#define FFA_DECLARE_ARGS \ ++ unsigned long a0 = 0; \ ++ unsigned long a1 = 0; \ ++ unsigned long a2 = 0; \ ++ unsigned long a3 = 0; \ ++ unsigned long a4 = 0; \ ++ unsigned long a5 = 0; \ ++ unsigned long a6 = 0; \ ++ unsigned long a7 = 0; \ ++ struct arm_smccc_res res = {0} ++ ++/* FF-A error codes */ ++#define FFA_ERR_STAT_NOT_SUPPORTED (-1) ++#define FFA_ERR_STAT_INVALID_PARAMETERS (-2) ++#define FFA_ERR_STAT_NO_MEMORY (-3) ++#define FFA_ERR_STAT_BUSY (-4) ++#define FFA_ERR_STAT_INTERRUPTED (-5) ++#define FFA_ERR_STAT_DENIED (-6) ++#define FFA_ERR_STAT_RETRY (-7) ++#define FFA_ERR_STAT_ABORTED (-8) ++ ++/** ++ * struct ffa_features_desc - FF-A functions features ++ * @func_id: FF-A function ++ * @field1: features read from register w2 ++ * @field2: features read from register w3 ++ * ++ * Data structure describing the features of the FF-A functions queried by ++ * FFA_FEATURES ++ */ ++struct ffa_features_desc { ++ u32 func_id; ++ u32 field1; ++ u32 field2; ++}; ++ ++/** ++ * enum ffa_rxtx_buf_sizes - minimum sizes supported ++ * for the RX/TX buffers ++ */ ++enum ffa_rxtx_buf_sizes { ++ RXTX_4K, ++ RXTX_64K, ++ RXTX_16K ++}; ++ ++/* ++ * Number of the FF-A interfaces features descriptors ++ * currently only FFA_RXTX_MAP descriptor is supported ++ */ ++#define FFA_FEATURE_DESC_CNT (1) ++ ++/** ++ * struct ffa_pdata - platform data for the arm_ffa device ++ * @conduit: The FF-A conduit used ++ * ++ * Platform data structure read from the device tree ++ */ ++struct ffa_pdata { ++ enum ffa_conduit conduit; ++}; ++ ++/** ++ * struct ffa_rxtxpair - structure hosting the RX/TX buffers physical addresses ++ * @rxbuf: physical address of the RX buffer ++ * @txbuf: physical address of the TX buffer ++ * ++ * Data structure hosting the physical addresses of the mapped RX/TX buffers ++ * These physical address are used by the FF-A functions that use the RX/TX buffers ++ */ ++struct ffa_rxtxpair { ++ u64 rxbuf; /* physical address */ ++ u64 txbuf; /* physical address */ ++}; ++ ++/** ++ * struct ffa_partition_desc - the secure partition descriptor ++ * @info: partition information ++ * @UUID: UUID ++ * ++ * Each partition has its descriptor containing the partitions information and the UUID ++ */ ++struct ffa_partition_desc { ++ struct ffa_partition_info info; ++ union ffa_partition_uuid UUID; ++}; ++ ++/** ++ * struct ffa_partitions - descriptors for all secure partitions ++ * @count: The number of partitions descriptors ++ * @descs The partitions descriptors table ++ * ++ * This data structure contains the partitions descriptors table ++ */ ++struct ffa_partitions { ++ u32 count; ++ struct ffa_partition_desc *descs; /* virtual address */ ++}; ++ ++/** ++ * struct ffa_prvdata - the driver private data structure ++ * ++ * @dev: The arm_ffa device under u-boot driver model ++ * @fwk_version: FF-A framework version ++ * @id: u-boot endpoint ID ++ * @partitions: The partitions descriptors structure ++ * @pair: The RX/TX buffers pair ++ * @conduit: The selected conduit ++ * @invoke_ffa_fn: The function executing the FF-A function ++ * @features: Table of the FF-A functions having features ++ * ++ * The driver data structure hosting all resident data. ++ */ ++struct ffa_prvdata { ++ struct udevice *dev; ++ u32 fwk_version; ++ u16 id; ++ struct ffa_partitions partitions; ++ struct ffa_rxtxpair pair; ++ enum ffa_conduit conduit; ++ invoke_ffa_fn_t invoke_ffa_fn; ++ struct ffa_features_desc features[FFA_FEATURE_DESC_CNT]; ++}; ++ ++#endif +diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c +new file mode 100644 +index 0000000000..98e2d2fa17 +--- /dev/null ++++ b/drivers/arm-ffa/core.c +@@ -0,0 +1,1484 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include "arm_ffa_prv.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++/** ++ * The device private data structure containing all the resident ++ * data read from secure world ++ */ ++struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0}; ++ ++/* ++ * Driver functions ++ */ ++ ++/** ++ * ffa_get_device - probes the arm_ffa device ++ * ++ * This boot time function makes sure the arm_ffa device is probed ++ * and ready for use. This is done using uclass_get_device. ++ * The arm_ffa driver belongs to UCLASS_FFA. ++ * This function should be called before using the driver. ++ * ++ * Arm FF-A transport is implemented through a single u-boot ++ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA. ++ * All FF-A clients should use the arm_ffa device to use the FF-A ++ * transport. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int ffa_get_device(void) ++{ ++ int ret; ++ int devnum = 0; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (ffa_priv_data.dev) ++ return FFA_ERR_STAT_SUCCESS; ++ ++ /* ++ * searching and probing the device ++ */ ++ ret = uclass_get_device(UCLASS_FFA, devnum, &ffa_priv_data.dev); ++ if (ret) { ++ ffa_err("can not find the device"); ++ ffa_priv_data.dev = NULL; ++ return -ENODEV; ++ } ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_get_version - FFA_VERSION handler function ++ * ++ * This is the boot time function that implements FFA_VERSION FF-A function ++ * to get from the secure world the FF-A framework version ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_get_version(void) ++{ ++ u16 major, minor; ++ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_VERSION; ++ a1 = FFA_VERSION_1_0; ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) { ++ ffa_err("A Firmware Framework implementation does not exist"); ++ return -EOPNOTSUPP; ++ } ++ ++ major = GET_FFA_MAJOR_VERSION(res.a0); ++ minor = GET_FFA_MINOR_VERSION(res.a0); ++ ++ ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d", ++ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); ++ ++ if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) { ++ ffa_info("Versions are compatible "); ++ ++ ffa_priv_data.fwk_version = res.a0; ++ ++ return FFA_ERR_STAT_SUCCESS; ++ } ++ ++ ffa_info("Versions are incompatible "); ++ return -EPROTONOSUPPORT; ++} ++ ++/** ++ * ffa_get_endpoint_id - FFA_ID_GET handler function ++ * ++ * This is the boot time function that implements FFA_ID_GET FF-A function ++ * to get from the secure world u-boot endpoint ID ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_get_endpoint_id(void) ++{ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_ID_GET; ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) { ++ ffa_err("This function is not implemented at this FF-A instance"); ++ return -EOPNOTSUPP; ++ } ++ ++ ffa_err("Undefined error code (%d)", ((int)res.a2)); ++ return -EINVAL; ++ } ++ case FFA_SUCCESS: ++ { ++ ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2); ++ ffa_info("endpoint ID is %u", ffa_priv_data.id); ++ ++ return FFA_ERR_STAT_SUCCESS; ++ } ++ default: ++ { ++ ffa_err("Undefined response function (0x%lx)", res.a0); ++ return -EINVAL; ++ } ++ } ++} ++ ++/** ++ * ffa_get_features_desc - returns the features descriptor of the specified ++ * FF-A function ++ * @func_id: the FF-A function which the features are to be retrieved ++ * ++ * This is a boot time function that searches the features descriptor of the ++ * specified FF-A function ++ * ++ * Return: ++ * ++ * When found, the address of the features descriptor is returned. Otherwise, NULL. ++ */ ++static struct ffa_features_desc *ffa_get_features_desc(u32 func_id) ++{ ++ u32 desc_idx; ++ ++ /* ++ * search for the descriptor of the selected FF-A interface ++ */ ++ for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++) ++ if (ffa_priv_data.features[desc_idx].func_id == func_id) ++ return &ffa_priv_data.features[desc_idx]; ++ ++ return NULL; ++} ++ ++/** ++ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP ++ * argument ++ * ++ * This is the boot time function that implements FFA_FEATURES FF-A function ++ * to retrieve the FFA_RXTX_MAP features ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_get_rxtx_map_features(void) ++{ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_FEATURES; ++ a1 = FFA_RXTX_MAP; ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) { ++ ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance"); ++ return -EOPNOTSUPP; ++ } ++ ++ ffa_err("Undefined error code (%d)", ((int)res.a2)); ++ return -EINVAL; ++ } ++ case FFA_SUCCESS: ++ { ++ u32 desc_idx; ++ ++ /* ++ * search for an empty descriptor ++ */ ++ for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++) ++ if (!ffa_priv_data.features[desc_idx].func_id) { ++ /* ++ * populate the descriptor with ++ * the interface features data ++ */ ++ ffa_priv_data.features[desc_idx].func_id = ++ FFA_RXTX_MAP; ++ ffa_priv_data.features[desc_idx].field1 = ++ res.a2; ++ ++ ffa_info("FFA_RXTX_MAP features data 0x%lx", ++ res.a2); ++ ++ return FFA_ERR_STAT_SUCCESS; ++ } ++ ++ ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full"); ++ return -ENOBUFS; ++ } ++ default: ++ { ++ ffa_err("Undefined response function (0x%lx)", ++ res.a0); ++ return -EINVAL; ++ } ++ } ++} ++ ++/** ++ * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors ++ * the minimum number of pages in each of the RX/TX ++ * buffers ++ * @buf_4k_pages: Pointer to the minimum number of pages ++ * ++ * This is the boot time function that returns the minimum number of pages ++ * in each of the RX/TX buffers ++ * ++ * Return: ++ * ++ * buf_4k_pages points to the returned number of pages ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages) ++{ ++ struct ffa_features_desc *desc = NULL; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!buf_4k_pages) ++ return -EINVAL; ++ ++ desc = ffa_get_features_desc(FFA_RXTX_MAP); ++ if (!desc) ++ return -EINVAL; ++ ++ ffa_dbg("FFA_RXTX_MAP descriptor found"); ++ ++ switch (desc->field1) { ++ case RXTX_4K: ++ *buf_4k_pages = 1; ++ break; ++ case RXTX_16K: ++ *buf_4k_pages = 4; ++ break; ++ case RXTX_64K: ++ *buf_4k_pages = 16; ++ break; ++ default: ++ ffa_err("RX/TX buffer size not supported"); ++ return -EINVAL; ++ } ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_free_rxtx_buffers - frees the RX/TX buffers ++ * @buf_4k_pages: the minimum number of pages in each of the RX/TX ++ * buffers ++ * ++ * This is the boot time function used to free the RX/TX buffers ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_free_rxtx_buffers(size_t buf_4k_pages) ++{ ++ efi_status_t free_rxbuf_ret, free_txbuf_ret; ++ ++ ffa_info("Freeing RX/TX buffers"); ++ ++ free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages); ++ free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages); ++ ++ if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) { ++ ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)", ++ free_rxbuf_ret, ++ free_txbuf_ret); ++ return -EINVAL; ++ } ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers ++ * @buf_4k_pages: the minimum number of pages in each of the RX/TX ++ * buffers ++ * ++ * This is the boot time function used by ffa_map_rxtx_buffers to allocate ++ * the RX/TX buffers before mapping them ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages) ++{ ++ ffa_dbg("[%s]", __func__); ++ ++#if CONFIG_IS_ENABLED(EFI_LOADER) ++ ++ efi_status_t efi_ret; ++ void *virt_txbuf; ++ void *virt_rxbuf; ++ ++ ffa_info("Using %lu 4KB page(s) for RX/TX buffers size", ++ buf_4k_pages); ++ ++ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, ++ EFI_BOOT_SERVICES_DATA, ++ buf_4k_pages, ++ &ffa_priv_data.pair.rxbuf); ++ ++ if (efi_ret != EFI_SUCCESS) { ++ ffa_priv_data.pair.rxbuf = 0; ++ ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)", ++ efi_ret); ++ ++ return -ENOBUFS; ++ } ++ ++ ffa_info("RX buffer at phys 0x%llx", ++ ffa_priv_data.pair.rxbuf); ++ ++ /* ++ * convert the RX buffer physical address to virtual address ++ */ ++ virt_rxbuf = (void *)map_sysmem((phys_addr_t)ffa_priv_data.pair.rxbuf, 0); ++ ++ /* ++ * make sure the buffer is clean before use ++ */ ++ memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K); ++ ++ unmap_sysmem(virt_rxbuf); ++ ++ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, ++ EFI_RUNTIME_SERVICES_DATA, ++ buf_4k_pages, ++ &ffa_priv_data.pair.txbuf); ++ ++ if (efi_ret != EFI_SUCCESS) { ++ ffa_dbg("FFA_RXTX_MAP: freeing RX buffer"); ++ efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages); ++ ffa_priv_data.pair.rxbuf = 0; ++ ffa_priv_data.pair.txbuf = 0; ++ ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)" ++ , efi_ret); ++ ++ return -ENOBUFS; ++ } ++ ++ ffa_info("TX buffer at phys 0x%llx", ++ ffa_priv_data.pair.txbuf); ++ ++ /* ++ * convert the TX buffer physical address to virtual address ++ */ ++ virt_txbuf = (void *)map_sysmem((phys_addr_t)ffa_priv_data.pair.txbuf, 0); ++ ++ /* ++ * make sure the buffer is clean before use ++ */ ++ memset(virt_txbuf, 0, buf_4k_pages * SZ_4K); ++ ++ unmap_sysmem(virt_txbuf); ++ ++ return FFA_ERR_STAT_SUCCESS; ++ ++#else ++ return -ENOBUFS; ++#endif ++} ++ ++/** ++ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function ++ * @buf_4k_pages: the minimum number of pages in each of the RX/TX ++ * buffers ++ * ++ * This is the boot time function that implements FFA_RXTX_MAP FF-A function ++ * to map the RX/TX buffers ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_map_rxtx_buffers(size_t buf_4k_pages) ++{ ++ int ret; ++ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ ret = ffa_alloc_rxtx_buffers(buf_4k_pages); ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ a0 = FFA_RXTX_MAP; ++ a1 = ffa_priv_data.pair.txbuf; ++ a2 = ffa_priv_data.pair.rxbuf; ++ a3 = buf_4k_pages; ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ switch (((int)res.a2)) { ++ case FFA_ERR_STAT_INVALID_PARAMETERS: ++ ffa_err("One or more fields in input parameters is incorrectly encoded"); ++ ret = -EPERM; ++ break; ++ case FFA_ERR_STAT_NO_MEMORY: ++ ffa_err("Not enough memory"); ++ ret = -ENOMEM; ++ break; ++ case FFA_ERR_STAT_DENIED: ++ ffa_err("Buffer pair already registered"); ++ ret = -EACCES; ++ break; ++ case FFA_ERR_STAT_NOT_SUPPORTED: ++ ffa_err("This function is not implemented at this FF-A instance"); ++ ret = -EOPNOTSUPP; ++ break; ++ default: ++ ffa_err("Undefined error (%d)", ++ ((int)res.a2)); ++ ret = -EINVAL; ++ } ++ break; ++ } ++ case FFA_SUCCESS: ++ ffa_info("RX/TX buffers mapped"); ++ return FFA_ERR_STAT_SUCCESS; ++ default: ++ ffa_err("Undefined response function (0x%lx)", ++ res.a0); ++ ret = -EINVAL; ++ } ++ ++ ffa_free_rxtx_buffers(buf_4k_pages); ++ ++ return ret; ++} ++ ++/** ++ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function ++ * ++ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function ++ * to unmap the RX/TX buffers ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_unmap_rxtx_buffers(void) ++{ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_RXTX_UNMAP; ++ a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id); ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) ++ panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n"); ++ else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS) ++ panic("[FFA] There is no buffer pair registered on behalf of the caller\n"); ++ else ++ panic("[FFA] Undefined error (%d)\n", ((int)res.a2)); ++ } ++ case FFA_SUCCESS: ++ { ++ size_t buf_4k_pages = 0; ++ int ret; ++ ++ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages); ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n"); ++ ++ ret = ffa_free_rxtx_buffers(buf_4k_pages); ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n"); ++ ++ ffa_info("RX/TX buffers unmapped and memory freed"); ++ ++ return FFA_ERR_STAT_SUCCESS; ++ } ++ default: ++ panic("[FFA] Undefined response function (0x%lx)", res.a0); ++ } ++} ++ ++/** ++ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function ++ * ++ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function ++ * to release the ownership of the RX buffer ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_release_rx_buffer(void) ++{ ++ FFA_DECLARE_ARGS; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_RX_RELEASE; ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) ++ panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n"); ++ else if (((int)res.a2) == FFA_ERR_STAT_DENIED) ++ panic("[FFA] Caller did not have ownership of the RX buffer\n"); ++ else ++ panic("[FFA] Undefined error (%d)\n", ((int)res.a2)); ++ } ++ case FFA_SUCCESS: ++ ffa_info("RX buffer released"); ++ return FFA_ERR_STAT_SUCCESS; ++ ++ default: ++ panic("[FFA] Undefined response function (0x%lx)\n", res.a0); ++ } ++} ++ ++/** ++ * ffa_uuid_are_identical - checks whether two given UUIDs are identical ++ * @uuid1: first UUID ++ * @uuid2: second UUID ++ * ++ * This is a boot time function used by ffa_read_partitions_info to search ++ * for a UUID in the partitions descriptors table ++ * ++ * Return: ++ * ++ * 1 when UUIDs match. Otherwise, 0 ++ */ ++int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1, ++ const union ffa_partition_uuid *uuid2) ++{ ++ if (!uuid1 || !uuid2) ++ return 0; ++ ++ return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid))); ++} ++ ++/** ++ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET ++ * and saves it in the private structure ++ * @count: The number of partitions queried ++ * @part_uuid: Pointer to the partition(s) UUID ++ * ++ * This is the boot time function that reads the partitions information ++ * returned by the FFA_PARTITION_INFO_GET and saves it in the private ++ * data structure. ++ * ++ * Return: ++ * ++ * The private data structure is updated with the partition(s) information ++ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure ++ */ ++static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid) ++{ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!count) { ++ ffa_err("No partition detected"); ++ return -ENODATA; ++ } ++ ++ ffa_info("Reading partitions data from the RX buffer"); ++ ++#if CONFIG_IS_ENABLED(EFI_LOADER) ++ ++ if (!part_uuid) { ++ /* ++ * querying information of all partitions ++ */ ++ u64 data_pages; ++ u64 data_bytes; ++ efi_status_t efi_ret; ++ size_t buf_4k_pages = 0; ++ u32 desc_idx; ++ struct ffa_partition_info *parts_info; ++ int ret; ++ ++ data_bytes = count * sizeof(struct ffa_partition_desc); ++ data_pages = efi_size_in_pages(data_bytes); ++ ++ /* ++ * get the RX buffer size in pages ++ */ ++ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages); ++ if (ret != FFA_ERR_STAT_SUCCESS) { ++ ffa_err("Can not get the RX buffer size (error %d)", ret); ++ return ret; ++ } ++ ++ if (data_pages > buf_4k_pages) { ++ ffa_err("Partitions data size exceeds the RX buffer size:"); ++ ffa_err(" Sizes in pages: data %llu , RX buffer %lu ", ++ data_pages, ++ buf_4k_pages); ++ ++ return -ENOMEM; ++ } ++ ++ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, ++ EFI_RUNTIME_SERVICES_DATA, ++ data_pages, ++ (u64 *)&ffa_priv_data.partitions.descs); ++ ++ if (efi_ret != EFI_SUCCESS) { ++ ffa_priv_data.partitions.descs = NULL; ++ ++ ffa_err("Cannot allocate partitions data buffer (EFI error 0x%lx)", ++ efi_ret); ++ ++ return -ENOBUFS; ++ } ++ ++ /* ++ * convert the descs buffer physical address ++ * to virtual address ++ * This virtual address should not be unmapped ++ * descs is expected to be a virtual address ++ */ ++ ffa_priv_data.partitions.descs = ++ (struct ffa_partition_desc *) ++ map_sysmem((phys_addr_t) ++ ffa_priv_data.partitions.descs, 0); ++ ++ /* ++ * make sure the buffer is clean before use ++ */ ++ memset(ffa_priv_data.partitions.descs, 0, ++ data_pages * SZ_4K); ++ ++ ffa_info("Copying %lld page(s) of partitions data from RX buffer", ++ data_pages); ++ ++ /* ++ * convert the RX buffer physical address to ++ * virtual address ++ */ ++ parts_info = (struct ffa_partition_info *) ++ map_sysmem((phys_addr_t) ++ ffa_priv_data.pair.rxbuf, 0); ++ ++ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) { ++ ffa_priv_data.partitions.descs[desc_idx].info = ++ parts_info[desc_idx]; ++ ++ ffa_info("Partition ID %x : info cached", ++ ffa_priv_data.partitions.descs[desc_idx].info.id); ++ } ++ unmap_sysmem(parts_info); ++ ++ ffa_priv_data.partitions.count = count; ++ ++ ffa_info("%d partition(s) found and cached", count); ++ ++ } else { ++ u32 rx_desc_idx, cached_desc_idx; ++ struct ffa_partition_info *parts_info; ++ u8 desc_found; ++ ++ /* ++ * convert the RX buffer physical address to virtual address ++ */ ++ parts_info = (struct ffa_partition_info *) ++ map_sysmem((phys_addr_t)ffa_priv_data.pair.rxbuf, 0); ++ ++ /* ++ * search for the SP IDs read from the RX buffer ++ * in the already cached SPs. ++ * Update the UUID when ID found. ++ */ ++ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) { ++ desc_found = 0; ++ ++ /* ++ * search the current ID in the cached partitions ++ */ ++ for (cached_desc_idx = 0; ++ cached_desc_idx < ffa_priv_data.partitions.count; ++ cached_desc_idx++) { ++ /* ++ * save the UUID ++ */ ++ if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id == ++ parts_info[rx_desc_idx].id) { ++ ffa_priv_data.partitions.descs[cached_desc_idx].UUID = ++ *part_uuid; ++ ++ desc_found = 1; ++ break; ++ } ++ } ++ ++ if (!desc_found) { ++ unmap_sysmem(parts_info); ++ return -ENODATA; ++ } ++ } ++ unmap_sysmem(parts_info); ++ } ++#else ++#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented" ++#endif ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET ++ * and saves partitions data ++ * @part_uuid: Pointer to the partition(s) UUID ++ * @pcount: Pointer to the number of partitions variable filled when querying ++ * ++ * This is the boot time function that executes the FFA_PARTITION_INFO_GET ++ * to query the partitions data. Then, it calls ffa_read_partitions_info ++ * to save the data in the private data structure. ++ * ++ * After reading the data the RX buffer is released using ffa_release_rx_buffer ++ * ++ * Return: ++ * ++ * When part_uuid is NULL, all partitions data are retrieved from secure world ++ * When part_uuid is non NULL, data for partitions matching the given UUID are ++ * retrieved and the number of partitions is returned ++ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure ++ */ ++static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid, ++ u32 *pcount) ++{ ++ unsigned long a0 = 0; ++ union ffa_partition_uuid query_uuid = {0}; ++ unsigned long a5 = 0; ++ unsigned long a6 = 0; ++ unsigned long a7 = 0; ++ struct arm_smccc_res res = {0}; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ a0 = FFA_PARTITION_INFO_GET; ++ ++ /* ++ * If a UUID is specified. Information for one or more ++ * partitions in the system is queried. Otherwise, information ++ * for all installed partitions is queried ++ */ ++ ++ if (part_uuid) { ++ if (!pcount) ++ return -EINVAL; ++ ++ query_uuid = *part_uuid; ++ } ++ ++ ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2, ++ query_uuid.words.a3, query_uuid.words.a4, ++ a5, a6, a7, &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ switch (((int)res.a2)) { ++ case FFA_ERR_STAT_INVALID_PARAMETERS: ++ ffa_err("Unrecognized UUID"); ++ return -EPERM; ++ case FFA_ERR_STAT_NO_MEMORY: ++ ffa_err("Results cannot fit in RX buffer of the caller"); ++ return -ENOMEM; ++ case FFA_ERR_STAT_DENIED: ++ ffa_err("Callee is not in a state to handle this request"); ++ return -EACCES; ++ case FFA_ERR_STAT_NOT_SUPPORTED: ++ ffa_err("This function is not implemented at this FF-A instance"); ++ return -EOPNOTSUPP; ++ case FFA_ERR_STAT_BUSY: ++ ffa_err("RX buffer of the caller is not free"); ++ return -EBUSY; ++ default: ++ ffa_err("Undefined error (%d)", ((int)res.a2)); ++ return -EINVAL; ++ } ++ } ++ case FFA_SUCCESS: ++ { ++ int ret; ++ ++ /* ++ * res.a2 contains the count of partition information descriptors ++ * populated in the RX buffer ++ */ ++ if (res.a2) { ++ ret = ffa_read_partitions_info(res.a2, part_uuid); ++ if (ret) ++ ffa_err("Failed to read partition(s) data , error (%d)", ret); ++ } ++ ++ /* ++ * return the SP count ++ */ ++ if (part_uuid) { ++ if (!ret) ++ *pcount = res.a2; ++ else ++ *pcount = 0; ++ } ++ /* ++ * After calling FFA_PARTITION_INFO_GET the buffer ownership ++ * is assigned to the consumer (u-boot). So, we need to give ++ * the ownership back to the secure world ++ */ ++ ret = ffa_release_rx_buffer(); ++ ++ if (!part_uuid && !res.a2) { ++ ffa_err("[FFA] no partition installed in the system"); ++ return -ENODEV; ++ } ++ ++ return ret; ++ } ++ default: ++ ffa_err("Undefined response function (0x%lx)", res.a0); ++ return -EINVAL; ++ } ++} ++ ++/** ++ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function ++ * @func_data: Pointer to the FF-A function arguments container structure. ++ * The passed arguments: ++ * Mode 1: When getting from the driver the number of ++ * secure partitions: ++ * @data0_size: UUID size ++ * @data0: pointer to the UUID (little endian) ++ * @data1_size: size of the number of partitions ++ * variable ++ * @data1: pointer to the number of partitions ++ * variable. The variable will be set ++ * by the driver ++ * Mode 2: When requesting the driver to return the ++ * partitions information: ++ * @data0_size: UUID size ++ * @data0: pointer to the UUID (little endian) ++ * @data1_size: size of the SPs information buffer ++ * @data1: pointer to SPs information buffer ++ * (allocated by the client). ++ * The buffer will be filled by the driver ++ * ++ * This is the boot time function that queries the secure partition data from ++ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET ++ * FF-A function to query the partition information from secure world. ++ * ++ * A client of the FF-A driver should know the UUID of the service it wants to ++ * access. It should use the UUID to request the FF-A driver to provide the ++ * partition(s) information of the service. The FF-A driver uses ++ * PARTITION_INFO_GET to obtain this information. This is implemented through ++ * ffa_get_partitions_info function. ++ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through ++ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information. ++ * They are not saved (already done). We only update the UUID in the cached area. ++ * This assumes that partitions data does not change in the secure world. ++ * Otherwise u-boot will have an outdated partition data. The benefit of caching ++ * the information in the FF-A driver is to accommodate discovery after ++ * ExitBootServices(). ++ * ++ * When invoked through a client request, ffa_get_partitions_info should be ++ * called twice. First call is to get from the driver the number of secure ++ * partitions (SPs) associated to a particular UUID. ++ * Then, the caller (client) allocates the buffer to host the SPs data and ++ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated ++ * buffer. ++ * ++ * To achieve the mechanism described above, ffa_get_partitions_info uses the ++ * following functions: ++ * ffa_read_partitions_info ++ * ffa_query_partitions_info ++ * ++ * Return: ++ * ++ * @data1: When pointing to the number of partitions variable, the number is ++ * set by the driver. ++ * When pointing to the partitions information buffer, the buffer will be ++ * filled by the driver. ++ * ++ * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure ++ */ ++static int ffa_get_partitions_info(struct ffa_interface_data *func_data) ++{ ++ /* ++ * fill_data: ++ * 0: return the SP count ++ * 1: fill SP data and return it to the caller ++ * -1: undefined mode ++ */ ++ int fill_data = -1; ++ u32 desc_idx, client_desc_idx; ++ union ffa_partition_uuid *part_uuid; ++ u32 client_desc_max_cnt; ++ u32 parts_found = 0; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!func_data) { ++ ffa_err("No function data provided"); ++ return -EINVAL; ++ } ++ ++ if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs) ++ panic("[FFA] No partition installed\n"); ++ ++ if (func_data->data0_size == sizeof(union ffa_partition_uuid) && ++ func_data->data0 && ++ func_data->data1_size == sizeof(u32) && ++ func_data->data1) { ++ /* ++ * data0 (in): pointer to UUID ++ * data1 (in): pointer to SP count ++ * Out: SP count returned in the count variable pointed by data1 ++ */ ++ ++ fill_data = 0; ++ ++ ffa_info("Preparing for checking partitions count"); ++ ++ } else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) && ++ func_data->data0 && ++ (func_data->data1_size >= sizeof(struct ffa_partition_info)) && ++ !(func_data->data1_size % sizeof(struct ffa_partition_info)) && ++ func_data->data1) { ++ /* ++ * data0 (in): pointer to UUID ++ * data1 (in): pointer to SPs descriptors buffer ++ * (created by the client) ++ * Out: SPs descriptors returned in the buffer ++ * pointed by data1 ++ */ ++ ++ fill_data = 1; ++ ++ client_desc_idx = 0; ++ ++ /* ++ * number of empty descriptors preallocated by the caller ++ */ ++ client_desc_max_cnt = ++ func_data->data1_size / sizeof(struct ffa_partition_info); ++ ++ ffa_info("Preparing for filling partitions info"); ++ ++ } else { ++ ffa_err("Invalid function arguments provided"); ++ return -EINVAL; ++ } ++ ++ part_uuid = (union ffa_partition_uuid *)func_data->data0; ++ ++ ffa_info("Searching partitions using the provided UUID"); ++ ++#ifdef DEBUG ++ { ++ u32 dbg_uuid_cnt; ++ ++ ffa_dbg("UUID: [LSB]"); ++ ++ for (dbg_uuid_cnt = 0 ; dbg_uuid_cnt < UUID_SIZE ; dbg_uuid_cnt++) ++ ffa_dbg(" %02x", part_uuid->bytes[dbg_uuid_cnt]); ++ } ++#endif ++ ++ /* ++ * search in the cached partitions ++ */ ++ for (desc_idx = 0; ++ desc_idx < ffa_priv_data.partitions.count; ++ desc_idx++) { ++ if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID, ++ part_uuid)) { ++ ffa_info("Partition ID %x matches the provided UUID", ++ ffa_priv_data.partitions.descs[desc_idx].info.id); ++ ++ parts_found++; ++ ++ if (fill_data) { ++ /* ++ * trying to fill the partition info in data1 ++ */ ++ ++ if (client_desc_idx < client_desc_max_cnt) { ++ ((struct ffa_partition_info *) ++ func_data->data1)[client_desc_idx++] = ++ ffa_priv_data.partitions.descs[desc_idx].info; ++ continue; ++ } ++ ++ ffa_err("Failed to fill the current descriptor client buffer full"); ++ return -ENOBUFS; ++ } ++ } ++ } ++ ++ if (!parts_found) { ++ int ret; ++ ++ ffa_info("No partition found. Querying framework ..."); ++ ++ ret = ffa_query_partitions_info(part_uuid, &parts_found); ++ ++ if (ret == FFA_ERR_STAT_SUCCESS) { ++ if (!fill_data) { ++ *((u32 *)func_data->data1) = parts_found; ++ ++ ffa_info("Number of partition(s) found matching the UUID: %d", ++ parts_found); ++ } else { ++ /* ++ * we want to read SPs info ++ */ ++ ++ /* ++ * If SPs data filled, retry searching SP info again ++ */ ++ if (parts_found) ++ ret = ffa_get_partitions_info(func_data); ++ else ++ ret = -ENODATA; ++ } ++ } ++ ++ return ret; ++ } ++ ++ /* partition(s) found */ ++ if (!fill_data) ++ *((u32 *)func_data->data1) = parts_found; ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_cache_partitions_info - Queries and saves all secure partitions data ++ * ++ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A ++ * function to query from secure world all partitions information. ++ * ++ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument. ++ * All installed partitions information are returned. We cache them in the ++ * resident private data structure and we keep the UUID field empty ++ * (in FF-A 1.0 UUID is not provided by the partition descriptor) ++ * ++ * This function is called at the device probing level. ++ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_cache_partitions_info(void) ++{ ++ ffa_dbg("[%s]", __func__); ++ return ffa_query_partitions_info(NULL, NULL); ++} ++ ++/** ++ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function ++ * @func_data: Pointer to the FF-A function arguments container structure. ++ * The passed arguments: ++ * @data0_size: partition ID size ++ * @data0: pointer to the partition ID ++ * @data1_size: exchanged data size ++ * @data1: pointer to the data buffer preallocated by ++ * the client (in/out) ++ * ++ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * FF-A functions. ++ * ++ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition. ++ * The response from the secure partition is handled by reading the ++ * FFA_MSG_SEND_DIRECT_RESP arguments. ++ * ++ * The maximum size of the data that can be exchanged is 20 bytes which is ++ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0 ++ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data ++ *func_data) ++{ ++ u16 dst_part_id; ++ unsigned long a0 = 0; ++ unsigned long a1 = 0; ++ unsigned long a2 = 0; ++ struct ffa_send_direct_data *msg; ++ struct arm_smccc_res res = {0}; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ if (!ffa_priv_data.invoke_ffa_fn) ++ panic("[FFA] no private data found\n"); ++ ++ if (!func_data) ++ return -EINVAL; ++ ++ if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs) ++ panic("[FFA] no partition installed\n"); ++ ++ if (func_data->data0_size != sizeof(u16) || ++ !func_data->data0 || ++ func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE || ++ !func_data->data1) { ++ ffa_err("Undefined interface parameters"); ++ return -EINVAL; ++ } ++ ++ dst_part_id = *((u16 *)func_data->data0); ++ msg = func_data->data1; ++ ++ ffa_dbg("Sending data to partition ID 0x%x", dst_part_id); ++ ++ a0 = FFA_MSG_SEND_DIRECT_REQ; ++ ++ a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) | ++ PREP_PART_ENDPOINT_ID(dst_part_id); ++ ++ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, ++ msg->a3, ++ msg->a4, ++ msg->a5, ++ msg->a6, ++ msg->a7, ++ &res); ++ ++ while (res.a0 == FFA_INTERRUPT) ++ ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1, ++ 0, 0, 0, 0, 0, 0, ++ &res); ++ ++ switch (res.a0) { ++ case FFA_ERROR: ++ { ++ switch (((int)res.a2)) { ++ case FFA_ERR_STAT_INVALID_PARAMETERS: ++ ffa_err("Invalid endpoint ID or non-zero reserved register"); ++ return -EPERM; ++ case FFA_ERR_STAT_ABORTED: ++ panic("[FFA] Message target ran into unexpected error and has aborted\n"); ++ case FFA_ERR_STAT_DENIED: ++ panic("[FFA] Callee is not in a state to handle this request\n"); ++ case FFA_ERR_STAT_NOT_SUPPORTED: ++ panic("[FFA] This function is not implemented at this FF-A instance\n"); ++ case FFA_ERR_STAT_BUSY: ++ panic("[FFA] Message target is busy\n"); ++ default: ++ panic("[FFA] Undefined error (%d)\n", ((int)res.a2)); ++ } ++ } ++ case FFA_SUCCESS: ++ ++ ffa_dbg("Message sent with no response"); ++ return FFA_ERR_STAT_SUCCESS; ++ ++ case FFA_MSG_SEND_DIRECT_RESP: ++ ++ ffa_dbg("Message sent with response"); ++ ++ /* ++ * extract the 32-bit wide return data ++ */ ++ msg->a3 = (u32)res.a3; ++ msg->a4 = (u32)res.a4; ++ msg->a5 = (u32)res.a5; ++ msg->a6 = (u32)res.a6; ++ msg->a7 = (u32)res.a7; ++ ++ return FFA_ERR_STAT_SUCCESS; ++ ++ default: ++ panic("[FFA] Undefined response function (0x%lx)\n", res.a0); ++ } ++} ++ ++/** ++ * invoke_ffa_drv_api - The driver dispatcher function ++ * @func_id: The FF-A function to be used ++ * @func_data: Pointer to the FF-A function arguments container ++ * structure. This also includes pointers to the ++ * returned data needed by clients. ++ * The dispatcher is a runtime function that selects the FF-A function handler ++ * based on the input FF-A function ID. ++ * The input arguments are passed to the handler function. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int __ffa_runtime invoke_ffa_drv_api(u32 func_id, ++ struct ffa_interface_data *func_data) ++{ ++ if (!ffa_priv_data.dev) ++ panic("[FFA] no device found\n"); ++ ++ switch (func_id) { ++ case FFA_PARTITION_INFO_GET: ++ return ffa_get_partitions_info(func_data); ++ case FFA_RXTX_UNMAP: ++ return ffa_unmap_rxtx_buffers(); ++ case FFA_MSG_SEND_DIRECT_REQ: ++ return ffa_msg_send_direct_req(func_data); ++ default: ++ ++ ffa_err("Undefined FF-A interface (%d)", func_id); ++ ++ return -EINVAL; ++ } ++} ++ ++/** ++ * ffa_init_private_data - Initialization of the private data ++ * @dev: the arm_ffa device ++ * ++ * This boot time function reads data from the platform data structure ++ * and populates the private data structure ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_init_private_data(struct udevice *dev) ++{ ++ struct ffa_pdata *pdata = dev_get_plat(dev); ++ ++ ffa_priv_data.conduit = pdata->conduit; ++ ++ if (ffa_priv_data.conduit == FFA_CONDUIT_SMC) { ++ ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc; ++ } else { ++ ffa_err("Undefined FF-A conduit (%d)", ffa_priv_data.conduit); ++ return -EINVAL; ++ } ++ ++ ffa_info("Conduit is %s", ++ ((ffa_priv_data.conduit == FFA_CONDUIT_SMC) ? ++ "SMC" : "NOT SUPPORTED")); ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_probe - The driver probe function ++ * @dev: the arm_ffa device ++ * ++ * Probing is done at boot time and triggered by the uclass device discovery. ++ * At probe level the following actions are done: ++ * - initialization of the driver private data structure ++ * - querying from secure world the FF-A framework version ++ * - querying from secure world the u-boot endpoint ID ++ * - querying from secure world the supported features of the specified FF-A calls ++ * - mapping the RX/TX buffers ++ * - querying from secure world all the partitions information ++ * ++ * All data queried from secure world is saved in the resident private data structure. ++ * ++ * The probe will fail if either FF-A framework is not detected or the ++ * FF-A requests are not behaving correctly. This ensures that the ++ * driver is not installed and its operations are not exported to the clients. ++ * However, once the driver is successfully probed and an FF-A anomaly is ++ * detected when clients invoke the driver operations, the driver cause ++ * u-boot to panic because the client would not know what to do in such conditions. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_probe(struct udevice *dev) ++{ ++ int ret; ++ size_t buf_4k_pages = 0; ++ ++ ffa_dbg("[%s]: initializing the FF-A driver", __func__); ++ ++ ret = ffa_init_private_data(dev); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_get_version(); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_get_endpoint_id(); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_get_rxtx_map_features(); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_map_rxtx_buffers(buf_4k_pages); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) ++ return ret; ++ ++ ret = ffa_cache_partitions_info(); ++ ++ if (ret != FFA_ERR_STAT_SUCCESS) { ++ ffa_free_rxtx_buffers(buf_4k_pages); ++ return ret; ++ } ++ ++ ffa_dbg("[%s]: initialization done", __func__); ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_of_to_plat - Reads the device tree node ++ * @dev: the arm_ffa device ++ * ++ * This boot time function reads data from the device tree node and populates ++ * the platform data structure ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++static int ffa_of_to_plat(struct udevice *dev) ++{ ++ struct ffa_pdata *pdata = dev_get_plat(dev); ++ const char *conduit; ++ ++ ffa_dbg("[%s]", __func__); ++ ++ conduit = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "method", NULL); ++ ++ if (strcmp("smc", conduit)) { ++ ffa_err("Unsupported conduit"); ++ return -EINVAL; ++ } ++ ++ pdata->conduit = FFA_CONDUIT_SMC; ++ ++ return FFA_ERR_STAT_SUCCESS; ++} ++ ++/** ++ * ffa_drv_ops - The driver operations runtime structure ++ * @invoke_func: The driver dispatcher ++ */ ++struct ffa_ops __ffa_runtime_data ffa_drv_ops = { ++ .invoke_func = invoke_ffa_drv_api ++}; ++ ++/** ++ * ffa_device_get_ops - driver operations getter ++ * ++ * Return: ++ * This runtime function returns a pointer to the driver operations structure ++ */ ++const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void) ++{ ++ return &ffa_drv_ops; ++} ++ ++/** ++ * Defining the device tree compatible string ++ */ ++ ++static const struct udevice_id ffa_match_id[] = { ++ {"arm,ffa", 0}, ++ {}, ++}; ++ ++/** ++ * Declaring the arm_ffa driver under UCLASS_FFA ++ */ ++ ++U_BOOT_DRIVER(arm_ffa) = { ++ .name = "arm_ffa", ++ .of_match = ffa_match_id, ++ .id = UCLASS_FFA, ++ .of_to_plat = ffa_of_to_plat, ++ .probe = ffa_probe, ++ .plat_auto = sizeof(struct ffa_pdata), ++}; +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +new file mode 100644 +index 0000000000..313f46f747 +--- /dev/null ++++ b/include/arm_ffa.h +@@ -0,0 +1,191 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __ARM_FFA_H ++#define __ARM_FFA_H ++ ++#include ++#include ++ ++/* ++ * This header is public. It can be used by clients to access ++ * data structures and definitions they need ++ */ ++ ++/* ++ * Macros for displaying logs ++ */ ++ ++#define ffa_dbg(fmt, ...) pr_debug("[FFA] " fmt "\n", ##__VA_ARGS__) ++#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__) ++#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__) ++ ++/* ++ * The driver operations success error code ++ */ ++#define FFA_ERR_STAT_SUCCESS (0) ++ ++#if CONFIG_IS_ENABLED(EFI_LOADER) ++ ++#include ++ ++/* ++ * __ffa_runtime_data and __ffa_runtime - controls whether data/code are ++ * available after calling the EFI ExitBootServices service. ++ * Data/code tagged with these keywords are resident (available at boot time and ++ * at runtime) ++ */ ++ ++#define __ffa_runtime_data __efi_runtime_data ++#define __ffa_runtime __efi_runtime ++ ++#else ++ ++#define __ffa_runtime_data ++#define __ffa_runtime ++ ++#endif ++ ++/* ++ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver ++ */ ++ ++#define FFA_SMC(calling_convention, func_num) \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \ ++ ARM_SMCCC_OWNER_STANDARD, (func_num)) ++ ++#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num)) ++ ++#define FFA_VERSION FFA_SMC_32(0x63) ++#define FFA_ID_GET FFA_SMC_32(0x69) ++#define FFA_FEATURES FFA_SMC_32(0x64) ++#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68) ++#define FFA_RXTX_MAP FFA_SMC_32(0x66) ++#define FFA_RXTX_UNMAP FFA_SMC_32(0x67) ++#define FFA_RX_RELEASE FFA_SMC_32(0x65) ++#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F) ++#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_32(0x70) ++#define FFA_RUN FFA_SMC_32(0x6D) ++#define FFA_ERROR FFA_SMC_32(0x60) ++#define FFA_SUCCESS FFA_SMC_32(0x61) ++#define FFA_INTERRUPT FFA_SMC_32(0x62) ++ ++/* ++ * struct ffa_partition_info - Partition information descriptor ++ * @id: Partition ID ++ * @exec_ctxt: Execution context count ++ * @properties: Partition properties ++ * ++ * Data structure containing information about partitions instantiated in the system ++ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET ++ */ ++struct __packed ffa_partition_info { ++ u16 id; ++ u16 exec_ctxt; ++/* partition supports receipt of direct requests */ ++#define FFA_PARTITION_DIRECT_RECV BIT(0) ++/* partition can send direct requests. */ ++#define FFA_PARTITION_DIRECT_SEND BIT(1) ++/* partition can send and receive indirect messages. */ ++#define FFA_PARTITION_INDIRECT_MSG BIT(2) ++ u32 properties; ++}; ++ ++/* ++ * struct ffa_send_direct_data - Data structure hosting the data ++ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * @a3-a7: Data read/written from/to w3-w7 registers ++ * ++ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ ++ * or read from FFA_MSG_SEND_DIRECT_RESP ++ */ ++struct __packed ffa_send_direct_data { ++ u32 a3; /* w3 */ ++ u32 a4; /* w4 */ ++ u32 a5; /* w5 */ ++ u32 a6; /* w6 */ ++ u32 a7; /* w7 */ ++}; ++ ++#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data)) ++ ++/* UUID data size */ ++#define UUID_SIZE (16) ++ ++/* ++ * union ffa_partition_uuid - Data union hosting the UUID ++ * transmitted by FFA_PARTITION_INFO_GET ++ * @words: data structure giving 32-bit words access to the UUID data ++ * @bytes: data structure giving byte access to the UUID data ++ * ++ * The structure holds little-endian UUID data. ++ */ ++union ffa_partition_uuid { ++ struct __packed words { ++ u32 a1; /* w1 */ ++ u32 a2; /* w2 */ ++ u32 a3; /* w3 */ ++ u32 a4; /* w4 */ ++ } words; ++ u8 bytes[UUID_SIZE]; ++}; ++ ++/** ++ * struct ffa_interface_data - generic FF-A interface data structure used to exchange ++ * data between user layers and the driver ++ * @data0_size: size of the first argument ++ * @data0: pointer to the first argument ++ * @data1_size>: size of the second argument ++ * @data1: pointer to the second argument ++ * ++ * Using this structure user layers can pass various types of data with different sizes. ++ * The driver internal functions can detect the nature of this data, verfy compliance ++ * then execute the request when appropriate. ++ */ ++struct ffa_interface_data { ++ u32 data0_size; /* size of the first argument */ ++ void *data0; /* pointer to the first argument */ ++ u32 data1_size; /* size of the second argument */ ++ void *data1; /* pointer to the second argument */ ++}; ++ ++/** ++ * struct ffa_ops - The driver operations structure ++ * @invoke_func: function pointer to the invoke function ++ * ++ * The data structure providing all the operations supported by the driver. ++ * This structure is resident. ++ */ ++struct ffa_ops { ++ /* the driver dispatcher */ ++ int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data); ++}; ++ ++/** ++ * The device driver and the Uclass driver public functions ++ */ ++ ++/** ++ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher ++ */ ++int __ffa_runtime ffa_get_invoke_func(u32 func_id, ++ struct ffa_interface_data *func_data); ++ ++/** ++ * ffa_device_get_ops - driver operations getter ++ */ ++const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void); ++ ++/** ++ * ffa_get_device - probes the arm_ffa device ++ */ ++int ffa_get_device(void); ++ ++/** ++ * ffa_init_device - probes the arm_ffa device ++ */ ++int ffa_init_device(void); ++#endif +diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h +new file mode 100644 +index 0000000000..0e143e5451 +--- /dev/null ++++ b/include/arm_ffa_helper.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#ifndef __ARM_FFA_HELPER_H ++#define __ARM_FFA_HELPER_H ++ ++#include ++ ++/* ++ * This header is public. Including this header provides all data structures ++ * and definitions needed by clients to use the FF-A transport driver ++ * ++ * It also provides helper functions allowing to pass data and invoke FF-A functions ++ */ ++ ++/** ++ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET ++ */ ++int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data); ++ ++/** ++ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP ++ */ ++int ffa_helper_unmap_rxtx_buffers(void); ++ ++/** ++ * ffa_helper_msg_send_direct_req - Wrapper function for ++ * FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ */ ++int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data ++ *func_data); ++ ++/** ++ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device ++ */ ++int ffa_helper_init_device(void); ++ ++/** ++ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer ++ */ ++int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin); ++#endif +diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h +index 0e26e1d138..a1181b8f48 100644 +--- a/include/dm/uclass-id.h ++++ b/include/dm/uclass-id.h +@@ -52,6 +52,7 @@ enum uclass_id { + UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */ + UCLASS_ETH, /* Ethernet device */ + UCLASS_ETH_PHY, /* Ethernet PHY device */ ++ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ + UCLASS_FIRMWARE, /* Firmware */ + UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ + UCLASS_GPIO, /* Bank of general-purpose I/O pins */ +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index 7f2be23394..54980a130f 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Copyright (c) 2015, Linaro Limited ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi + */ + #ifndef __LINUX_ARM_SMCCC_H + #define __LINUX_ARM_SMCCC_H +@@ -57,13 +59,17 @@ + #include + /** + * struct arm_smccc_res - Result from SMC/HVC call +- * @a0-a3 result values from registers 0 to 3 ++ * @a0-a7 result values from registers 0 to 7 + */ + struct arm_smccc_res { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; ++ unsigned long a4; ++ unsigned long a5; ++ unsigned long a6; ++ unsigned long a7; + }; + + /** +@@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, + unsigned long a5, unsigned long a6, unsigned long a7, + struct arm_smccc_res *res, struct arm_smccc_quirk *quirk); + ++#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) ++/** ++ * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport ++ * @a0-a7: arguments passed in 64-bit registers x0 to x7 ++ * @res: result values from 64-bit registers x0 to x7 ++ * ++ * This function is used to make SMC calls following SMC32 Calling Convention. ++ * The content of the supplied parameters is copied to registers x0 to x7 prior ++ * to the SMC instruction. The SMC call return data is 32-bit data read from ++ * registers x0 tp x7. ++ */ ++asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, ++ unsigned long a2, unsigned long a3, unsigned long a4, ++ unsigned long a5, unsigned long a6, unsigned long a7, ++ struct arm_smccc_res *res); ++ ++#define arm_ffa_smccc_smc __arm_ffa_smccc_smc ++ ++#endif ++ + #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL) + + #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__) +diff --git a/lib/Kconfig b/lib/Kconfig +index 3c6fa99b1a..473821b882 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -810,6 +810,7 @@ config SMBIOS_PARSER + source lib/efi/Kconfig + source lib/efi_loader/Kconfig + source lib/optee/Kconfig ++source lib/arm-ffa/Kconfig + + config TEST_FDTDEC + bool "enable fdtdec test" +diff --git a/lib/Makefile b/lib/Makefile +index 11b03d1cbe..8e6fad6130 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/ + obj-$(CONFIG_EFI_LOADER) += efi_driver/ + obj-$(CONFIG_EFI_LOADER) += efi_loader/ + obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ ++obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/ + obj-$(CONFIG_LZMA) += lzma/ + obj-$(CONFIG_BZIP2) += bzip2/ + obj-$(CONFIG_TIZEN) += tizen/ +diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig +new file mode 100644 +index 0000000000..79acbc5a8f +--- /dev/null ++++ b/lib/arm-ffa/Kconfig +@@ -0,0 +1,6 @@ ++config ARM_FFA_TRANSPORT_HELPERS ++ bool "Enable interface helpers for Arm Firmware Framework for Armv8-A" ++ depends on ARM_FFA_TRANSPORT ++ help ++ User layers call FF-A interfaces using helper functions which ++ pass the data and the FF-A function ID to the low level driver +diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile +new file mode 100644 +index 0000000000..c30c0f3981 +--- /dev/null ++++ b/lib/arm-ffa/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++# (C) Copyright 2021 Abdellatif El Khlifi ++# ++ ++# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set ++ ++obj-y += arm_ffa_helper.o +diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c +new file mode 100644 +index 0000000000..623899d380 +--- /dev/null ++++ b/lib/arm-ffa/arm_ffa_helper.c +@@ -0,0 +1,188 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 ARM Limited ++ * Abdellatif El Khlifi ++ */ ++ ++#include ++#include ++#include ++ ++/** ++ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET ++ * ++ * @func_data: Pointer to the FF-A function arguments container ++ * structure. ++ * The passed arguments: ++ * Mode 1: When getting from the driver the number of ++ * secure partitions: ++ * @data0_size: UUID size ++ * @data0: pointer to the UUID (little endian) ++ * @data1_size: size of the number of partitions ++ * variable ++ * @data1: pointer to the number of partitions ++ * variable. The variable will be set ++ * by the driver ++ * Mode 2: When requesting the driver to return the ++ * partitions information: ++ * @data0_size: UUID size ++ * @data0: pointer to the UUID (little endian) ++ * @data1_size: size of the SPs information buffer ++ * @data1: pointer to SPs information buffer ++ * (allocated by the client). ++ * The buffer will be filled by the driver ++ * ++ * This is the boot time function used by clients who wants to get from secure ++ * world the partition(s) information. ++ * ++ * A client of the FF-A driver should know the UUID of the service it wants to ++ * access. It should use the UUID to request the FF-A driver to provide the ++ * partition(s) information of the service. The client should use ++ * ffa_helper_get_partitions_info to pass the UUID information to the driver ++ * which uses PARTITION_INFO_GET to obtain the partition(s) information. ++ * ++ * ffa_helper_get_partitions_info should be called twice. First call is to get ++ * from the driver the number of secure partitions (SPs) associated to a ++ * particular UUID. Then, the caller (client) allocates the buffer to host the ++ * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the ++ * pre-allocated buffer. ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data) ++{ ++ return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data); ++} ++ ++/** ++ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP ++ * ++ * This is the boot time function that allows clients to unmap the RX/TX ++ * buffers ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int ffa_helper_unmap_rxtx_buffers(void) ++{ ++ return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL); ++} ++ ++/** ++ * ffa_helper_msg_send_direct_req - Wrapper function for ++ * FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * @func_data: Pointer to the FF-A function arguments container structure. ++ * The passed arguments: ++ * @data0_size: partition ID size ++ * @data0: pointer to the partition ID ++ * @data1_size: exchanged data size ++ * @data1: pointer to the data buffer preallocated by the client (in/out) ++ * ++ * This is the runtime function that allows clients to send data to the secure ++ * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the ++ * data to the secure partition. The response from the secure partition is ++ * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned ++ * to ffa_helper_msg_send_direct_req through @func_data ++ * ++ * The maximum size of the data that can be exchanged is 20 bytes which is ++ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0 ++ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP} ++ * ++ * The client should pre-allocate a buffer pointed by @data1 which the size ++ * is sizeof(struct ffa_send_direct_data) ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data ++ *func_data) ++{ ++ return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data); ++} ++ ++/** ++ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device ++ * ++ * This boot time function should be called to probe the arm_ffa device so ++ * it becomes ready for use. ++ * To achieve that, this function is called automatically at initcalls ++ * level (after u-boot relocation). ++ * ++ * Return: ++ * ++ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure ++ */ ++int ffa_helper_init_device(void) ++{ ++ return ffa_init_device(); ++} ++ ++/** ++ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer ++ * @uuid_str: UUID string in big endian format (36 bytes wide + '/0') ++ * @uuid_bin: preallocated 16 bytes UUID buffer in little endian format ++ * ++ * UUID binary format used by the FF-A framework (16 bytes): ++ * ++ * [LSB] 4B-2B-2B-2B-6B (little endian data fields) ++ * ++ * UUID string is 36 length of characters (36 bytes): ++ * ++ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ++ * be be be be be ++ * ++ * where x is a hexadecimal character. Fields are separated by '-'s. ++ * When converting to a binary UUID, these endianness rules apply: ++ * be: means the field in the string is considered a big endian hex number ++ * and should be converted to little endian binary format ++ * ++ * Return: ++ * ++ * uuid_bin filled with little endian UUID data ++ * On success 0 is returned. Otherwise, failure code. ++ */ ++int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin) ++{ ++ u16 tmp16 = 0; ++ u32 tmp32 = 0; ++ u64 tmp64 = 0; ++ ++ if (!uuid_str_valid(uuid_str) || !uuid_bin) ++ return -EINVAL; ++ ++ /* ++ * reverse bytes from big to little endian ++ */ ++ tmp32 = simple_strtoul(uuid_str, NULL, 16); ++ memcpy(uuid_bin, &tmp32, 4); ++ ++ /* ++ * reverse bytes from big to little endian ++ */ ++ tmp16 = simple_strtoul(uuid_str + 9, NULL, 16); ++ memcpy(uuid_bin + 4, &tmp16, 2); ++ ++ /* ++ * reverse bytes from big to little endian ++ */ ++ tmp16 = simple_strtoul(uuid_str + 14, NULL, 16); ++ memcpy(uuid_bin + 6, &tmp16, 2); ++ ++ /* ++ * reverse bytes from big to little endian ++ */ ++ tmp16 = simple_strtoul(uuid_str + 19, NULL, 16); ++ memcpy(uuid_bin + 8, &tmp16, 2); ++ ++ /* ++ * reverse bytes from big to little endian ++ */ ++ tmp64 = simple_strtoull(uuid_str + 24, NULL, 16); ++ memcpy(uuid_bin + 10, (char *)&tmp64, 6); ++ ++ return 0; ++} +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index 5bcb8253ed..cffa2c69d6 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -23,6 +23,10 @@ + #include + #include + ++#if defined(CONFIG_ARM_FFA_TRANSPORT) ++#include ++#endif ++ + DECLARE_GLOBAL_DATA_PTR; + + /* Task priority level */ +@@ -2114,6 +2118,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + struct efi_event *evt, *next_event; + efi_status_t ret = EFI_SUCCESS; + ++#if defined(CONFIG_ARM_FFA_TRANSPORT) ++ int ffa_ret; ++#endif ++ + EFI_ENTRY("%p, %zx", image_handle, map_key); + + /* Check that the caller has read the current memory map */ +@@ -2174,6 +2182,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + } + ++#if defined(CONFIG_ARM_FFA_TRANSPORT) ++ /* unmap FF-A RX/TX buffers */ ++ ffa_ret = ffa_helper_unmap_rxtx_buffers(); ++ if (ffa_ret) ++ debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n"); ++ else ++ debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n"); ++#endif ++ + /* Patch out unsupported runtime function */ + efi_runtime_detach(); + +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0003-arm-total_compute-enable-psci.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0003-arm-total_compute-enable-psci.patch new file mode 100644 index 000000000000..da8d3f00537d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0003-arm-total_compute-enable-psci.patch @@ -0,0 +1,30 @@ +From 8dd3e03bd83939746b6a849dce37435ea7581032 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Thu, 14 Jul 2022 19:35:41 +0530 +Subject: [PATCH 3/7] arm: total_compute: enable psci + +psci is used for system reset + +Signed-off-by: Davidson K +Change-Id: Iff4f769dc5e64b6000e892d77a011102b090acfd +Upstream-Status: Submitted [https://patchwork.ozlabs.org/project/uboot/patch/20220809102652.23776-1-davidson.kumaresan@arm.com/] +--- + arch/arm/dts/total_compute.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/dts/total_compute.dts b/arch/arm/dts/total_compute.dts +index 4399269a44..96edacda0b 100644 +--- a/arch/arm/dts/total_compute.dts ++++ b/arch/arm/dts/total_compute.dts +@@ -45,4 +45,8 @@ + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; ++ psci { ++ compatible = "arm,psci-1.0", "arm,psci-0.2"; ++ method = "smc"; ++ }; + }; +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0004-arm_ffa-rxtx_map-should-use-64-bit-calls.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0004-arm_ffa-rxtx_map-should-use-64-bit-calls.patch new file mode 100644 index 000000000000..fb1e9ea9f8f0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0004-arm_ffa-rxtx_map-should-use-64-bit-calls.patch @@ -0,0 +1,37 @@ +From 6eee50e5376356b1faeb30507b411120a8b5c7d1 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Mon, 6 Jun 2022 15:13:15 +0530 +Subject: [PATCH 4/7] arm_ffa: rxtx_map should use 64 bit calls + +rxtx_map deals with the 64 bit addresses and hence the 64 bit calls +should be used + +Signed-off-by: Davidson K +Change-Id: Iec1251266e61139767588d683d60bada1ed10abe +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/arm_ffa.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +index 313f46f747..9627107079 100644 +--- a/include/arm_ffa.h ++++ b/include/arm_ffa.h +@@ -58,12 +58,13 @@ + ARM_SMCCC_OWNER_STANDARD, (func_num)) + + #define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num)) ++#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num)) + + #define FFA_VERSION FFA_SMC_32(0x63) + #define FFA_ID_GET FFA_SMC_32(0x69) + #define FFA_FEATURES FFA_SMC_32(0x64) + #define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68) +-#define FFA_RXTX_MAP FFA_SMC_32(0x66) ++#define FFA_RXTX_MAP FFA_SMC_64(0x66) + #define FFA_RXTX_UNMAP FFA_SMC_32(0x67) + #define FFA_RX_RELEASE FFA_SMC_32(0x65) + #define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F) +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0005-efi_firmware-add-new-fmp-driver-that-supports-arm-fw.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0005-efi_firmware-add-new-fmp-driver-that-supports-arm-fw.patch new file mode 100644 index 000000000000..159b048a062a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0005-efi_firmware-add-new-fmp-driver-that-supports-arm-fw.patch @@ -0,0 +1,993 @@ +From 6d26058401bce6012173b5341cdf4de72772a1c2 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Mon, 6 Jun 2022 13:19:07 +0530 +Subject: [PATCH 5/7] efi_firmware: add new fmp driver that supports arm fwu + specification + +This fmp driver communicates to the firmware update secure partition +executing in the secure world which is an implementation of the arm +psa specification for the firmware update. The communication to the +firmware update secure partition is based on stmm and arm ff-a framework. + +It implements only the get_image_info and set_image api. + +Signed-off-by: Davidson K +Change-Id: I94c2cad210c32a60a8a0594cacf530b68ab6a09d +Upstream-Status: Pending [Not submitted to upstream yet] +--- + include/efi_firmware_arm_psa.h | 218 +++++++++++ + include/efi_loader.h | 1 + + lib/efi_loader/Kconfig | 9 + + lib/efi_loader/Makefile | 1 + + lib/efi_loader/efi_capsule.c | 8 + + lib/efi_loader/efi_firmware.c | 134 +++++++ + lib/efi_loader/efi_firmware_arm_psa.c | 520 ++++++++++++++++++++++++++ + 7 files changed, 891 insertions(+) + create mode 100644 include/efi_firmware_arm_psa.h + create mode 100644 lib/efi_loader/efi_firmware_arm_psa.c + +diff --git a/include/efi_firmware_arm_psa.h b/include/efi_firmware_arm_psa.h +new file mode 100644 +index 0000000000..82f932066c +--- /dev/null ++++ b/include/efi_firmware_arm_psa.h +@@ -0,0 +1,218 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (C) 2022 Arm Limited ++ */ ++ ++#ifndef _EFI_FIRMWARE_ARM_PSA_H ++#define _EFI_FIRMWARE_ARM_PSA_H ++ ++#include ++#include ++#include ++ ++#define PSA_FWU_DIRECTORY_UUID \ ++ EFI_GUID(0xdeee58d9, 0x5147, 0x4ad3, \ ++ 0xa2, 0x90, 0x77, 0x66, 0x6e, 0x23, 0x41, 0xa5) ++ ++#define PSA_FWU_SP_UUID \ ++ EFI_GUID(0x6823a838, 0x1b06, 0x470e, \ ++ 0x97, 0x74, 0x0c, 0xce, 0x8b, 0xfb, 0x53, 0xfd) ++ ++#define FFA_FWU_SP_UUID \ ++ {0x68, 0x23, 0xa8, 0x38, 0x1b, 0x06, 0x47, \ ++ 0x0e, 0x97, 0x74, 0x0c, 0xce, 0x8b, 0xfb, 0x53, 0xfd} ++ ++#define FWU_DISCOVER 0 ++#define FWU_BEGIN_STAGING 1 ++#define FWU_END_STAGING 2 ++#define FWU_CANCEL_STAGING 3 ++#define FWU_OPEN 4 ++#define FWU_WRITE_STREAM 5 ++#define FWU_READ_STREAM 6 ++#define FWU_COMMIT 7 ++#define FWU_ACCEPT_IMAGE 9 ++#define FWU_SELECT_PREVIOUS 10 ++ ++#define FWU_SUCCESS 0 ++#define FWU_UNKNOWN ((int32_t)-1) ++#define FWU_BUSY ((int32_t)-2) ++#define FWU_OUT_OF_BOUNDS ((int32_t)-3) ++#define FWU_AUTH_FAIL ((int32_t)-4) ++#define FWU_NO_PERMISSION ((int32_t)-5) ++#define FWU_DENIED ((int32_t)-6) ++#define FWU_RESUME ((int32_t)-7) ++ ++#define MAX_IMAGES 5 ++ ++typedef int32_t fwu_status_t; ++ ++struct fwu_image_info_entry { ++ efi_guid_t image_guid; ++ uint32_t client_permissions; ++ uint32_t img_max_size; ++ uint32_t lowest_acceptable_version; ++ uint32_t img_version; ++ uint32_t accepted; ++ uint32_t reserved; ++}__packed; ++ ++struct fwu_image_directory { ++ uint32_t directory_version; ++ uint32_t num_images; ++ uint32_t active_index; ++ uint32_t boot_index; ++ struct fwu_image_info_entry entries[MAX_IMAGES]; ++}__packed; ++ ++int __efi_runtime arm_psa_get_image_info( ++ efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name ++); ++ ++int __efi_runtime arm_psa_update( ++ const void *image, ++ u8 image_index, ++ efi_uintn_t image_size ++); ++ ++struct mm_fwu_discover_arg { ++ uint32_t func_id; ++}__packed; ++ ++struct mm_fwu_discover_ret { ++ uint32_t status; ++ uint8_t version_major; ++ uint8_t version_minor; ++ uint16_t num_func; ++ uint8_t function_presence[]; ++}__packed; ++ ++struct mm_fwu_begin_staging_arg { ++ uint32_t func_id; ++}__packed; ++ ++struct mm_fwu_begin_staging_ret { ++ uint32_t status; ++}__packed; ++ ++struct mm_fwu_end_staging_arg { ++ uint32_t func_id; ++}__packed; ++ ++struct mm_fwu_end_staging_ret { ++ uint32_t status; ++}__packed; ++ ++struct mm_fwu_cancel_staging_arg { ++ uint32_t func_id; ++}__packed; ++ ++struct mm_fwu_cancel_staging_ret { ++ uint32_t status; ++}__packed; ++ ++struct mm_fwu_open_arg { ++ uint32_t func_id; ++ efi_guid_t image_guid; ++}__packed; ++ ++struct mm_fwu_open_ret { ++ uint32_t status; ++ uint32_t handle; ++}__packed; ++ ++struct mm_fwu_write_stream_arg { ++ uint32_t func_id; ++ uint32_t handle; ++ uint32_t data_len; ++ uint8_t payload[]; ++}__packed; ++ ++struct mm_fwu_write_stream_ret { ++ uint32_t status; ++}; ++ ++struct mm_fwu_read_stream_arg { ++ uint32_t func_id; ++ uint32_t handle; ++}__packed; ++ ++struct mm_fwu_read_stream_ret { ++ uint32_t status; ++ uint32_t read_bytes; ++ uint32_t total_bytes; ++ uint8_t payload[]; ++}__packed; ++ ++struct mm_fwu_commit_arg { ++ uint32_t func_id; ++ uint32_t handle; ++ uint32_t acceptance_req; ++ uint32_t max_atomic_len; ++}__packed; ++ ++struct mm_fwu_commit_ret { ++ uint32_t status; ++ uint32_t progress; ++ uint32_t total_work; ++}__packed; ++ ++struct mm_fwu_accept_arg { ++ uint32_t func_id; ++ uint32_t reserved; ++ efi_guid_t image_type_uuid; ++}__packed; ++ ++struct mm_fwu_accept_ret { ++ uint32_t status; ++}; ++ ++struct mm_fwu_select_previous_arg { ++ uint32_t func_id; ++}__packed; ++ ++struct mm_fwu_select_previous_ret { ++ uint32_t status; ++}__packed; ++ ++inline static void *get_fwu_hdr(struct efi_mm_communicate_header *mm_hdr) ++{ ++ const efi_guid_t fwu_sp_guid = PSA_FWU_SP_UUID; ++ guidcpy(&mm_hdr->header_guid, &fwu_sp_guid); ++ return mm_hdr->data; ++} ++ ++#define GET_HDR(name) \ ++static inline struct mm_fwu_##name * \ ++get_fwu_##name (struct efi_mm_communicate_header *mm_hdr) \ ++{ \ ++ return (struct mm_fwu_##name *)get_fwu_hdr(mm_hdr); \ ++} \ ++ ++GET_HDR(discover_arg) ++GET_HDR(discover_ret) ++GET_HDR(begin_staging_arg) ++GET_HDR(begin_staging_ret) ++GET_HDR(end_staging_arg) ++GET_HDR(end_staging_ret) ++GET_HDR(cancel_staging_arg) ++GET_HDR(cancel_staging_ret) ++GET_HDR(open_arg) ++GET_HDR(open_ret) ++GET_HDR(write_stream_arg) ++GET_HDR(write_stream_ret) ++GET_HDR(read_stream_arg) ++GET_HDR(read_stream_ret) ++GET_HDR(commit_arg) ++GET_HDR(commit_ret) ++GET_HDR(accept_arg) ++GET_HDR(accept_ret) ++GET_HDR(select_previous_arg) ++GET_HDR(select_previous_ret) ++ ++#endif /* _EFI_FIRMWARE_ARM_PSA_H */ +diff --git a/include/efi_loader.h b/include/efi_loader.h +index af36639ec6..7327c87497 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -961,6 +961,7 @@ u16 *efi_create_indexed_name(u16 *buffer, size_t buffer_size, const char *name, + + extern const struct efi_firmware_management_protocol efi_fmp_fit; + extern const struct efi_firmware_management_protocol efi_fmp_raw; ++extern const struct efi_firmware_management_protocol efi_fmp_arm_psa; + + /* Capsule update */ + efi_status_t EFIAPI efi_update_capsule( +diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig +index e5e35fe51f..f99d436f16 100644 +--- a/lib/efi_loader/Kconfig ++++ b/lib/efi_loader/Kconfig +@@ -168,6 +168,15 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT + Select this option if you want to enable capsule-based + firmware update using Firmware Management Protocol. + ++config EFI_CAPSULE_FIRMWARE_ARM_PSA ++ bool "FMP driver for ARM PSA FWU specification" ++ depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT ++ select EFI_CAPSULE_FIRMWARE ++ help ++ Select this option if you want to enable firmware management protocol ++ driver that supports the ARM PSA firmware update specification as ++ mentioned in https://developer.arm.com/documentation/den0118/a/ ++ + config EFI_CAPSULE_FIRMWARE_FIT + bool "FMP driver for FIT images" + depends on FIT +diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile +index 034d26cf01..f986ac6417 100644 +--- a/lib/efi_loader/Makefile ++++ b/lib/efi_loader/Makefile +@@ -38,6 +38,7 @@ obj-y += efi_boottime.o + obj-y += efi_helper.o + obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o + obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o ++obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA) += efi_firmware_arm_psa.o + obj-y += efi_console.o + obj-y += efi_device_path.o + obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index f00440163d..3154fc51d3 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -1041,6 +1041,14 @@ efi_status_t __weak efi_load_capsule_drivers(void) + &efi_fmp_raw, NULL)); + } + ++ if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA)) { ++ handle = NULL; ++ ret = EFI_CALL(efi_install_multiple_protocol_interfaces( ++ &handle, ++ &efi_guid_firmware_management_protocol, ++ &efi_fmp_arm_psa, NULL)); ++ } ++ + return ret; + } + +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index a5ff32f121..3356559af8 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -478,3 +479,136 @@ const struct efi_firmware_management_protocol efi_fmp_raw = { + .set_package_info = efi_firmware_set_package_info_unsupported, + }; + #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */ ++ ++#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA ++/* ++ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update ++ * method that supports the arm psa firmware update specification. ++ */ ++ ++/** ++ * efi_firmware_arm_psa_get_image_info - return information about the ++ * current firmware image ++ * @this: Protocol instance ++ * @image_info_size: Size of @image_info ++ * @image_info: Image information ++ * @descriptor_version: Pointer to version number ++ * @descriptor_count: Pointer to number of descriptors ++ * @descriptor_size: Pointer to descriptor size ++ * package_version: Package version ++ * package_version_name: Package version's name ++ * ++ * Return information bout the current firmware image in @image_info. ++ * @image_info will consist of a number of descriptors. ++ * ++ * Return status code ++ */ ++ ++static ++efi_status_t EFIAPI efi_firmware_arm_psa_get_image_info( ++ struct efi_firmware_management_protocol *this, ++ efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name) ++{ ++ int ret; ++ ++ EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, ++ image_info_size, image_info, ++ descriptor_version, descriptor_count, descriptor_size, ++ package_version, package_version_name); ++ ++ if (!image_info_size) ++ return EFI_EXIT(EFI_INVALID_PARAMETER); ++ ++ if (*image_info_size && ++ (!image_info || !descriptor_version || !descriptor_count || ++ !descriptor_size || !package_version || !package_version_name)) ++ return EFI_EXIT(EFI_INVALID_PARAMETER); ++ ++ ret = arm_psa_get_image_info(image_info_size, image_info, ++ descriptor_version, descriptor_count, ++ descriptor_size, ++ package_version, package_version_name); ++ ++ if (ret) { ++ if (ret == -ENOMEM) ++ return EFI_EXIT(EFI_BUFFER_TOO_SMALL); ++ else ++ return EFI_EXIT(EFI_DEVICE_ERROR); ++ } ++ ++ return EFI_EXIT(EFI_SUCCESS); ++} ++ ++/** ++ * efi_firmware_arm_psa_set_image - update the firmware image ++ * @this: Protocol instance ++ * @image_index: Image index number ++ * @image: New image ++ * @image_size: Size of new image ++ * @vendor_code: Vendor-specific update policy ++ * @progress: Function to report the progress of update ++ * @abort_reason: Pointer to string of abort reason ++ * ++ * Update the firmware to new image, following the arm psa firmware ++ * update specification. ++ * @vendor_code, @progress and @abort_reason are not supported. ++ * ++ * Return: status code ++ */ ++static ++efi_status_t EFIAPI efi_firmware_arm_psa_set_image( ++ struct efi_firmware_management_protocol *this, ++ u8 image_index, ++ const void *image, ++ efi_uintn_t image_size, ++ const void *vendor_code, ++ efi_status_t (*progress)(efi_uintn_t completion), ++ u16 **abort_reason) ++{ ++ u32 fmp_hdr_signature; ++ const struct fmp_payload_header *header; ++ ++ EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image, ++ image_size, vendor_code, progress, abort_reason); ++ ++ if (!image) ++ return EFI_EXIT(EFI_INVALID_PARAMETER); ++ ++ /* TODO: capsule authentication */ ++ ++ fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE; ++ header = (void *)image; ++ ++ if (!memcmp(&header->signature, &fmp_hdr_signature, ++ sizeof(fmp_hdr_signature))) { ++ /* ++ * When building the capsule with the scripts in ++ * edk2, a FMP header is inserted above the capsule ++ * payload. Compensate for this header to get the ++ * actual payload that is to be updated. ++ */ ++ image = (unsigned char *)image + header->header_size; ++ image_size -= header->header_size; ++ } ++ ++ if (arm_psa_update(image, image_index, image_size)) ++ return EFI_EXIT(EFI_DEVICE_ERROR); ++ ++ return EFI_EXIT(EFI_SUCCESS); ++} ++ ++const struct efi_firmware_management_protocol efi_fmp_arm_psa = { ++ .get_image_info = efi_firmware_arm_psa_get_image_info, ++ .get_image = efi_firmware_get_image_unsupported, ++ .set_image = efi_firmware_arm_psa_set_image, ++ .check_image = efi_firmware_check_image_unsupported, ++ .get_package_info = efi_firmware_get_package_info_unsupported, ++ .set_package_info = efi_firmware_set_package_info_unsupported, ++}; ++#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA */ +diff --git a/lib/efi_loader/efi_firmware_arm_psa.c b/lib/efi_loader/efi_firmware_arm_psa.c +new file mode 100644 +index 0000000000..ab575f0124 +--- /dev/null ++++ b/lib/efi_loader/efi_firmware_arm_psa.c +@@ -0,0 +1,520 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (C) 2022 Arm Limited ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* MM return codes */ ++#define MM_SUCCESS 0 ++ ++#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 0xC4000061 ++#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 ++ ++__efi_runtime_data static u16 mm_sp_id; ++__efi_runtime_data static int fwu_initialized = 0; ++__efi_runtime_data struct fwu_image_directory cached_image_directory; ++__efi_runtime_data struct efi_mm_communicate_header *mm_hdr; ++__efi_runtime_data void *mm_comm_buf; ++ ++/** ++ * ffa_discover_mm_sp_id() - Query the MM partition ID ++ * ++ * Use the FF-A driver to get the MM partition ID. ++ * If multiple partitions are found, use the first one ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int __efi_runtime ffa_discover_mm_sp_id(void) ++{ ++ struct ffa_interface_data func_data = {0}; ++ u32 count = 0; ++ int ret; ++ struct ffa_partition_info *parts_info; ++ static union ffa_partition_uuid fwu_sp_uuid = {.bytes = FFA_FWU_SP_UUID}; ++ ++ /* ++ * get from the driver the count of the SPs matching the UUID ++ */ ++ func_data.data0_size = sizeof(fwu_sp_uuid); ++ func_data.data0 = &fwu_sp_uuid; ++ func_data.data1_size = sizeof(count); ++ func_data.data1 = &count; ++ ++ ret = ffa_helper_get_partitions_info(&func_data); ++ if (ret != FFA_ERR_STAT_SUCCESS) { ++ log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret); ++ return ret; ++ } ++ ++ if (!count) { ++ log_info("EFI: No MM partition found\n"); ++ return ret; ++ } ++ ++ /* ++ * pre-allocate a buffer to be filled by the driver ++ * with ffa_partition_info structs ++ */ ++ parts_info = calloc(count, sizeof(struct ffa_partition_info)); ++ if (!parts_info) ++ return -EINVAL; ++ ++ log_info("EFI: Pre-allocating %d partition(s) info structures\n", count); ++ ++ func_data.data1_size = count * sizeof(struct ffa_partition_info); ++ func_data.data1 = parts_info; ++ ++ /* ++ * ask the driver to fill the ++ * buffer with the SPs info ++ */ ++ ret = ffa_helper_get_partitions_info(&func_data); ++ if (ret != FFA_ERR_STAT_SUCCESS) { ++ log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret); ++ free(parts_info); ++ return ret; ++ } ++ ++ /* ++ * MM SPs found , use the first one ++ */ ++ ++ mm_sp_id = parts_info[0].id; ++ ++ log_info("EFI: MM partition ID 0x%x\n", mm_sp_id); ++ ++ free(parts_info); ++ ++ return 0; ++} ++ ++/** ++ * ffa_notify_mm_sp() - Announce there is data in the shared buffer ++ * ++ * Notifies the MM partition in the trusted world that ++ * data is available in the shared buffer. ++ * This is a blocking call during which trusted world has exclusive access ++ * to the MM shared buffer. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int __efi_runtime ffa_notify_mm_sp(void) ++{ ++ struct ffa_interface_data func_data = {0}; ++ struct ffa_send_direct_data msg = {0}; ++ int ret; ++ u32 sp_event_complete; ++ int sp_event_ret; ++ ++ func_data.data0_size = sizeof(mm_sp_id); ++ func_data.data0 = &mm_sp_id; ++ ++ msg.a3 = FFA_SHARED_MM_BUFFER_ADDR; ++ msg.a4 = FFA_SHARED_MM_BUFFER_SIZE; ++ func_data.data1_size = sizeof(msg); ++ func_data.data1 = &msg; ++ ++ ret = ffa_helper_msg_send_direct_req(&func_data); ++ if (ret != FFA_ERR_STAT_SUCCESS) { ++ log_err("EFI: Failure to notify the MM SP , FF-A error (%d)\n", ret); ++ return ret; ++ } ++ ++ sp_event_complete = msg.a3; ++ sp_event_ret = (int)msg.a4; ++ ++ if (sp_event_complete == ARM_SVC_ID_SP_EVENT_COMPLETE && sp_event_ret == MM_SUCCESS) ++ return 0; ++ ++ log_err("EFI: Failure to notify the MM SP (0x%x , %d)\n", ++ sp_event_complete, ++ sp_event_ret); ++ ++ return -EACCES; ++} ++ ++static fwu_status_t __efi_runtime fwu_discover(void) ++{ ++ int ret; ++ struct mm_fwu_discover_arg *discover_arg = get_fwu_discover_arg(mm_hdr); ++ struct mm_fwu_discover_ret *discover_ret = get_fwu_discover_ret(mm_hdr); ++ ++ discover_arg->func_id = FWU_DISCOVER; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_discover_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ if (discover_ret->version_major != 1) { ++ log_err("FWU: Unsupported Update Agent version\n"); ++ return -EINVAL; ++ } ++ /* TODO: check other parameters as well */ ++ ++ return discover_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_begin_staging(void) ++{ ++ int ret; ++ struct mm_fwu_begin_staging_arg *begin_staging_arg = get_fwu_begin_staging_arg(mm_hdr); ++ struct mm_fwu_begin_staging_ret *begin_staging_ret = get_fwu_begin_staging_ret(mm_hdr); ++ ++ begin_staging_arg->func_id = FWU_BEGIN_STAGING; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_begin_staging_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ return begin_staging_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_end_staging(void) ++{ ++ int ret; ++ struct mm_fwu_end_staging_arg *end_staging_arg = get_fwu_end_staging_arg(mm_hdr); ++ struct mm_fwu_end_staging_ret *end_staging_ret = get_fwu_end_staging_ret(mm_hdr); ++ ++ end_staging_arg->func_id = FWU_END_STAGING; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_end_staging_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ return end_staging_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_cancel_staging(void) ++{ ++ int ret; ++ struct mm_fwu_cancel_staging_arg *cancel_staging_arg = get_fwu_cancel_staging_arg(mm_hdr); ++ struct mm_fwu_cancel_staging_ret *cancel_staging_ret = get_fwu_cancel_staging_ret(mm_hdr); ++ ++ cancel_staging_arg->func_id = FWU_CANCEL_STAGING; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_cancel_staging_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ return cancel_staging_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_open(const efi_guid_t *img_uuid, uint32_t *handle) ++{ ++ int ret; ++ struct mm_fwu_open_arg *open_hdr = get_fwu_open_arg(mm_hdr); ++ struct mm_fwu_open_ret *open_ret = get_fwu_open_ret(mm_hdr); ++ ++ open_hdr->func_id = FWU_OPEN; ++ guidcpy(&open_hdr->image_guid, img_uuid); ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_open_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ *handle = open_ret->handle; ++ ++ return open_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_read_stream(uint32_t handle, uint8_t *buffer, uint32_t buffer_size) ++{ ++ int ret; ++ struct mm_fwu_read_stream_arg *read_stream_hdr = get_fwu_read_stream_arg(mm_hdr); ++ struct mm_fwu_read_stream_ret *read_stream_ret = get_fwu_read_stream_ret(mm_hdr); ++ uint32_t payload_size = FFA_SHARED_MM_BUFFER_SIZE - sizeof(struct mm_fwu_read_stream_ret) ++ - sizeof(struct efi_mm_communicate_header); ++ uint32_t read_offset = 0, read_size, total_size; ++ ++ do { ++ read_stream_hdr->func_id = FWU_READ_STREAM; ++ read_stream_hdr->handle = handle; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_read_stream_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ if (read_stream_ret->status) ++ return read_stream_ret->status; ++ ++ read_size = read_stream_ret->read_bytes; ++ total_size = read_stream_ret->total_bytes; ++ ++ log_info("FWU: read bytes / total bytes : %d/%d\n", read_size, total_size); ++ ++ if ((read_size <= payload_size) && (read_offset + read_size <= buffer_size)) ++ memcpy(buffer + read_offset, read_stream_ret->payload, read_size); ++ else ++ return -EINVAL; ++ ++ read_offset += read_size; ++ ++ if (read_offset > total_size) ++ return -EINVAL; ++ } while (total_size != read_offset); ++ ++ return read_stream_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_write_stream(uint32_t handle, const uint8_t *buffer, uint32_t remaining_size) ++{ ++ int ret; ++ struct mm_fwu_write_stream_arg *write_stream_arg = get_fwu_write_stream_arg(mm_hdr); ++ struct mm_fwu_write_stream_ret *write_stream_ret = get_fwu_write_stream_ret(mm_hdr); ++ uint32_t write_size; ++ uint32_t payload_size = FFA_SHARED_MM_BUFFER_SIZE - sizeof(struct mm_fwu_write_stream_arg) ++ - sizeof(struct efi_mm_communicate_header); ++ ++ while (remaining_size) { ++ write_size = (remaining_size < payload_size) ? remaining_size : payload_size; ++ write_stream_arg->func_id = FWU_WRITE_STREAM; ++ write_stream_arg->handle = handle; ++ write_stream_arg->data_len = write_size; ++ memcpy(write_stream_arg->payload, buffer, write_size); ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_write_stream_arg) + write_size; ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ if(write_stream_ret->status) ++ return write_stream_ret->status; ++ ++ remaining_size -= write_size; ++ buffer += write_size; ++ ++ log_info("FWU: write size = %d, remaining size = %d\n", ++ write_size, remaining_size); ++ } ++ ++ return write_stream_ret->status; ++} ++ ++static fwu_status_t __efi_runtime fwu_commit(uint32_t handle, bool client_accept) ++{ ++ int ret; ++ struct mm_fwu_commit_arg *commit_arg = get_fwu_commit_arg(mm_hdr); ++ struct mm_fwu_commit_ret *commit_ret = get_fwu_commit_ret(mm_hdr); ++ ++ do { ++ commit_arg->func_id = FWU_COMMIT; ++ commit_arg->handle = handle; ++ commit_arg->acceptance_req = client_accept; ++ commit_arg->max_atomic_len = 0; ++ ++ mm_hdr->message_len = sizeof(struct mm_fwu_commit_arg); ++ ++ ret = ffa_notify_mm_sp(); ++ if (ret) ++ return ret; ++ ++ log_info("FWU: commit progress %d/%d (work/total_work)\n", ++ commit_ret->progress, commit_ret->total_work); ++ ++ } while(commit_ret->status==FWU_RESUME); ++ ++ return commit_ret->status; ++} ++ ++int __efi_runtime arm_psa_update( ++ const void *image, ++ u8 image_index, ++ efi_uintn_t image_size ++) ++{ ++ int ret = 0; ++ uint32_t handle; ++ ++ if(image_index >= cached_image_directory.num_images) ++ return -EINVAL; ++ ++ ret = fwu_begin_staging(); ++ if (ret) { ++ log_err("FWU: begin staging failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ ret = fwu_open(&cached_image_directory.entries[image_index].image_guid, &handle); ++ if (ret) { ++ log_err("FWU: firmware image open failed, ret = %d\n", ret); ++ goto cancel_staging; ++ } ++ ++ ret = fwu_write_stream(handle, (uint8_t *)image, image_size); ++ if (ret) { ++ log_err("FWU: write stream failed, ret = %d\n", ret); ++ goto cancel_staging; ++ } ++ ++ /* TODO: implement client driven image acceptance */ ++ ret = fwu_commit(handle, 0); ++ if (ret) { ++ log_err("FWU: commit failed, ret = %d\n", ret); ++ goto cancel_staging; ++ } ++ ++ ret = fwu_end_staging(); ++ if (ret) { ++ log_err("FWU: end staging failed, ret = %d\n", ret); ++ goto cancel_staging; ++ } ++ ++ log_info("successfully updated the image at index %d\n", image_index); ++ return ret; ++ ++cancel_staging: ++ if (fwu_cancel_staging()) ++ log_err("FWU: cancel staging failed, ret = %d\n", ret); ++ ++ return ret; ++} ++ ++static int __efi_runtime read_image_directory(void) ++{ ++ int ret; ++ uint32_t handle; ++ ++ const efi_guid_t fwu_directory_uuid = PSA_FWU_DIRECTORY_UUID; ++ ++ ret = fwu_open(&fwu_directory_uuid, &handle); ++ if (ret) { ++ log_err("FWU: open image directory failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ ret = fwu_read_stream(handle, (uint8_t *)&cached_image_directory, sizeof(cached_image_directory)); ++ if (ret) { ++ log_err("FWU: read stream failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ if(cached_image_directory.num_images > MAX_IMAGES) { ++ log_err("FWU: image limit exceeded.\n"); ++ log_err("FWU: number of images present: %d, max number of images supported: %d\n", ++ cached_image_directory.num_images, MAX_IMAGES); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int update_agent_init(void) ++{ ++ int ret; ++ ++ ret = ffa_discover_mm_sp_id(); ++ if (ret) { ++ log_err("FWU: discover update agent failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ mm_comm_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0); ++ mm_hdr = (struct efi_mm_communicate_header *)mm_comm_buf; ++ ++ ret = fwu_discover(); ++ if (ret) { ++ log_err("FWU: discover failed, ret = %d\n", ret); ++ goto out; ++ } ++ ++ ret = read_image_directory(); ++ if (ret) { ++ log_err("FWU: reading image directory failed, ret = %d\n", ret); ++ goto out; ++ } ++ ++ fwu_initialized = 1; ++ return ret; ++out: ++ unmap_sysmem(mm_comm_buf); ++ return ret; ++} ++ ++int __efi_runtime arm_psa_get_image_info( ++ efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name) ++{ ++ int ret = 0; ++ int required_image_info_size; ++ ++ if (!fwu_initialized) { ++ ret = update_agent_init(); ++ if (ret) { ++ log_err("update agent init failed, ret = %d\n", ret); ++ return ret; ++ } ++ } ++ ++ required_image_info_size = cached_image_directory.num_images * ++ sizeof(struct efi_firmware_image_descriptor); ++ ++ if (*image_info_size < required_image_info_size) { ++ *image_info_size = required_image_info_size; ++ return -ENOMEM; ++ } ++ ++ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; ++ *descriptor_count = cached_image_directory.num_images; ++ *descriptor_size = required_image_info_size; ++ *package_version = 0xffffffff; /* not supported */ ++ *package_version_name = NULL; /* not supported */ ++ ++ for (int i = 0; i < cached_image_directory.num_images; i++) { ++ image_info[i].image_index = i+1; ++ guidcpy(&image_info[i].image_type_id, &cached_image_directory.entries[i].image_guid); ++ image_info[i].image_id = i; ++ image_info[i].image_id_name = NULL; /* not supported */ ++ image_info[i].version = cached_image_directory.entries[i].img_version; ++ image_info[i].version_name = NULL; /* not supported */ ++ image_info[i].size = cached_image_directory.entries[i].img_max_size; ++ ++ image_info[i].attributes_supported = ++ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ image_info[i].attributes_setting = ++ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; ++ ++ /* Check if the capsule authentication is enabled */ ++ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) ++ image_info[i].attributes_setting |= ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ ++ image_info[i].lowest_supported_image_version = ++ cached_image_directory.entries[i].lowest_acceptable_version; ++ image_info[i].last_attempt_version = 0; ++ image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; ++ image_info[i].hardware_instance = 1; ++ image_info[i].dependencies = NULL; /* not supported */ ++ } ++ ++ return ret; ++} +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0006-arm-total_compute-enable-capsule-update.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0006-arm-total_compute-enable-capsule-update.patch new file mode 100644 index 000000000000..bf2bfe8cb928 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0006-arm-total_compute-enable-capsule-update.patch @@ -0,0 +1,70 @@ +From 2ab887402b9e22842d07e5f2fe1ac54518555af5 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Mon, 6 Jun 2022 13:24:42 +0530 +Subject: [PATCH 6/7] arm: total_compute: enable capsule update + +It includes: +* Enabling runtime capsule update +* Enabling efidebug command line tool +* Enabling the FMP driver that supports ARM PSA firmware update specification +* Predefining the carved out memory to be used for MM communication +* Enabling FF-A transport driver and adding an entry in dts + +Signed-off-by: Davidson K +Change-Id: I6d6c70c6fc386d6c40def800a7417c1ce4b8acf5 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/total_compute.dts | 7 +++++++ + configs/total_compute_defconfig | 5 +++++ + include/configs/total_compute.h | 4 ++++ + 3 files changed, 16 insertions(+) + +diff --git a/arch/arm/dts/total_compute.dts b/arch/arm/dts/total_compute.dts +index 96edacda0b..9b2cbfb452 100644 +--- a/arch/arm/dts/total_compute.dts ++++ b/arch/arm/dts/total_compute.dts +@@ -45,8 +45,15 @@ + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; ++ + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; ++ ++ arm_ffa { ++ compatible = "arm,ffa"; ++ method = "smc"; ++ status = "okay"; ++ }; + }; +diff --git a/configs/total_compute_defconfig b/configs/total_compute_defconfig +index 6a375543cd..531ce41cd3 100644 +--- a/configs/total_compute_defconfig ++++ b/configs/total_compute_defconfig +@@ -52,3 +52,8 @@ CONFIG_SYS_FLASH_PROTECTION=y + CONFIG_SYS_FLASH_CFI=y + CONFIG_LIBAVB=y + CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_ARM_FFA_TRANSPORT=y ++CONFIG_CMD_EFIDEBUG=y ++CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA=y ++CONFIG_EFI_CAPSULE_ON_DISK=y ++CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y +diff --git a/include/configs/total_compute.h b/include/configs/total_compute.h +index 62bdb4f6a3..4b00f47ec6 100644 +--- a/include/configs/total_compute.h ++++ b/include/configs/total_compute.h +@@ -59,4 +59,8 @@ + #define CONFIG_SYS_FLASH_EMPTY_INFO /* flinfo indicates empty blocks */ + #define FLASH_MAX_SECTOR_SIZE 0x00040000 + ++/* Shared buffer used for communication between u-boot and the FWU SP */ ++#define FFA_SHARED_MM_BUFFER_SIZE 4 * 1024 * 1024 /* 4 MB */ ++#define FFA_SHARED_MM_BUFFER_ADDR (0xFCA00000) ++ + #endif /* __TOTAL_COMPUTE_H */ +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0007-arm_ffa-unmap-rxtx-buffer-before-exiting-u-boot.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0007-arm_ffa-unmap-rxtx-buffer-before-exiting-u-boot.patch new file mode 100644 index 000000000000..5c437232df65 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/0007-arm_ffa-unmap-rxtx-buffer-before-exiting-u-boot.patch @@ -0,0 +1,51 @@ +From 47be0456ea1760837d2de857e57842e595e9ea5e Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Mon, 27 Jun 2022 14:11:27 +0530 +Subject: [PATCH 7/7] arm_ffa: unmap rxtx buffer before exiting u-boot + +The linux kernel ffa driver will be used after the kernel boots. It +will try to map its own rxtx buffer. But there can be only one rxtx +buffer mapped from the non secure world. Since the rxtx buffer of +the u-boot is no longer used and we have to map the rxtx buffer of +the linux kernel, the rxtx buffer of the u-boot should be unmapped. + +This will not be needed after the efi runtime services are enabled + +Signed-off-by: Davidson K +Change-Id: I9deb6283d81f791185aa0a32d205b394d6d91f76 +Upstream-Status: Pending [Not submitted to upstream yet] +--- + drivers/arm-ffa/core.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c +index 98e2d2fa17..0c619439cb 100644 +--- a/drivers/arm-ffa/core.c ++++ b/drivers/arm-ffa/core.c +@@ -1470,6 +1470,16 @@ static const struct udevice_id ffa_match_id[] = { + {}, + }; + ++/** ++ * Unmap the rxtx buffer before exiting u-boot ++ * This avoids conflicts with the linux kernel ffa driver ++ */ ++ ++static int ffa_remove(struct udevice *dev) ++{ ++ return ffa_unmap_rxtx_buffers(); ++} ++ + /** + * Declaring the arm_ffa driver under UCLASS_FFA + */ +@@ -1481,4 +1491,6 @@ U_BOOT_DRIVER(arm_ffa) = { + .of_to_plat = ffa_of_to_plat, + .probe = ffa_probe, + .plat_auto = sizeof(struct ffa_pdata), ++ .remove = ffa_remove, ++ .flags = DM_FLAG_OS_PREPARE, + }; +-- +2.34.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/bootargs.cfg b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/bootargs.cfg new file mode 100644 index 000000000000..8c3160249cd2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/tc/bootargs.cfg @@ -0,0 +1,2 @@ +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyAMA0 debug user_debug=31 earlycon=pl011,0x7ff80000 loglevel=9 androidboot.hardware=total_compute androidboot.boot_devices=1c050000.mmci ip=dhcp androidboot.selinux=permissive allow_mismatched_32bit_el0" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend new file mode 100644 index 000000000000..b89ea872c7d3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend @@ -0,0 +1,95 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +# +# Corstone-500 MACHINE +# +SRC_URI:append:corstone500 = " \ + file://0001-armv7-adding-generic-timer-access-through-MMIO.patch \ + file://0002-board-arm-add-corstone500-board.patch" + +# +# Corstone1000 64-bit machines +# +DEPENDS:append:corstone1000 = " gnutls-native" +CORSTONE1000_DEVICE_TREE:corstone1000-mps3 = "corstone1000-mps3" +CORSTONE1000_DEVICE_TREE:corstone1000-fvp = "corstone1000-fvp" +EXTRA_OEMAKE:append:corstone1000 = ' DEVICE_TREE=${CORSTONE1000_DEVICE_TREE}' + +SYSROOT_DIRS:append:corstone1000 = " /boot" + +SRC_URI:append:corstone1000 = " \ + file://0001-arm64-smccc-add-support-for-SMCCCv1.2-x0-x17-registe.patch \ + file://0002-lib-uuid-introduce-uuid_str_to_le_bin-function.patch \ + file://0003-arm_ffa-introduce-Arm-FF-A-low-level-driver.patch \ + file://0004-arm_ffa-efi-unmap-RX-TX-buffers.patch \ + file://0005-arm_ffa-introduce-armffa-command.patch \ + file://0006-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch \ + file://0007-arm_ffa-introduce-Sandbox-test-cases-for-UCLASS_FFA.patch \ + file://0008-arm_ffa-introduce-armffa-command-Sandbox-test.patch \ + file://0009-arm_ffa-efi-introduce-FF-A-MM-communication.patch \ + file://0010-arm_ffa-efi-corstone1000-enable-MM-communication.patch \ + file://0011-efi-corstone1000-introduce-EFI-capsule-update.patch \ + file://0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch \ + file://0013-efi_capsule-corstone1000-pass-interface-id-and-buffe.patch \ + file://0014-efi_boottime-corstone1000-pass-interface-id-and-kern.patch \ + file://0015-efi_loader-corstone1000-remove-guid-check-from-corst.patch \ + file://0016-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch \ + file://0017-efi_firmware-add-get_image_info-for-corstone1000.patch \ + file://0018-efi_loader-send-bootcomplete-message-to-secure-encla.patch \ + file://0019-efi_loader-fix-null-pointer-exception-with-get_image.patch \ + file://0020-arm-corstone1000-add-mmc-for-fvp.patch \ + file://0021-corstone1000-add-compressed-kernel-support.patch \ + file://0022-Introduce-external-sys-driver-to-device-tree.patch \ + file://0023-Add-mhu-and-rpmsg-client-to-u-boot-device-tree.patch \ + file://0024-arm-corstone1000-esrt-support.patch \ + file://0025-efi_setup-discover-FF-A-bus-before-raising-EFI-start.patch \ + file://0026-corstone1000-enable-distro-booting-command.patch \ + " + +# +# FVP BASE +# +SRC_URI:append:fvp-base = " file://bootargs.cfg" + +# +# FVP BASE ARM32 +# +SRC_URI:append:fvp-base-arm32 = " file://0001-Add-vexpress_aemv8a_aarch32-variant.patch \ + file://0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch \ + " + +# +# FVP BASER +# +SRC_URI:append:fvp-baser-aemv8r64 = " \ + file://0001-armv8-Add-ARMv8-MPU-configuration-logic.patch \ + file://0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch \ + file://0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch \ + file://0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch \ + file://0005-armv8-Make-disabling-HVC-configurable-when-switching.patch \ + file://0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch \ + file://0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch \ + file://0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch \ + file://0009-armv8-Enable-icache-when-switching-exception-levels-.patch \ + " + + +# +# Juno Machines +# +SRC_URI:append:juno = " file://0001-configs-vexpress-modify-to-boot-compressed-initramfs.patch" + + +# +# TC0 and TC1 MACHINES +# +SRC_URI:append:tc = " \ + file://bootargs.cfg \ + file://0001-arm-total_compute-update-secure-dram-size.patch \ + file://0002-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch \ + file://0003-arm-total_compute-enable-psci.patch \ + file://0004-arm_ffa-rxtx_map-should-use-64-bit-calls.patch \ + file://0005-efi_firmware-add-new-fmp-driver-that-supports-arm-fw.patch \ + file://0006-arm-total_compute-enable-capsule-update.patch \ + file://0007-arm_ffa-unmap-rxtx-buffer-before-exiting-u-boot.patch \ + " diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.04.bb b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.04.bb new file mode 100644 index 000000000000..46f924469935 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.04.bb @@ -0,0 +1,26 @@ +HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome" +DESCRIPTION = "U-Boot, a boot loader for Embedded boards based on PowerPC, \ +ARM, MIPS and several other processors, which can be installed in a boot \ +ROM and used to initialize and test the hardware or to download and run \ +application code." +SECTION = "bootloaders" +DEPENDS += "flex-native bison-native" + +LICENSE = "GPL-2.0-or-later" +LIC_FILES_CHKSUM = "file://Licenses/README;md5=5a7450c57ffe5ae63fd732446b988025" +PE = "1" + +# We use the revision in order to avoid having to fetch it from the +# repo during parse +SRCREV = "e4b6ebd3de982ae7185dbf689a030e73fd06e0d2" + +SRC_URI = "git://git.denx.de/u-boot.git;branch=master \ + " + +S = "${WORKDIR}/git" +B = "${WORKDIR}/build" +do_configure[cleandirs] = "${B}" + +require recipes-bsp/u-boot/u-boot.inc + +DEPENDS += "bc-native dtc-native gnutls-native" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.10.bb b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.10.bb new file mode 100644 index 000000000000..905ae552a784 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2022.10.bb @@ -0,0 +1,26 @@ +HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome" +DESCRIPTION = "U-Boot, a boot loader for Embedded boards based on PowerPC, \ +ARM, MIPS and several other processors, which can be installed in a boot \ +ROM and used to initialize and test the hardware or to download and run \ +application code." +SECTION = "bootloaders" +DEPENDS += "flex-native bison-native" + +LICENSE = "GPL-2.0-or-later" +LIC_FILES_CHKSUM = "file://Licenses/README;md5=2ca5f2c35c8cc335f0a19756634782f1" +PE = "1" + +# We use the revision in order to avoid having to fetch it from the +# repo during parse +SRCREV = "4debc57a3da6c3f4d3f89a637e99206f4cea0a96" + +SRC_URI = "git://git.denx.de/u-boot.git;branch=master \ + " + +S = "${WORKDIR}/git" +B = "${WORKDIR}/build" +do_configure[cleandirs] = "${B}" + +require recipes-bsp/u-boot/u-boot.inc + +DEPENDS += "bc-native dtc-native gnutls-native" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-fvp-base.inc b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-fvp-base.inc new file mode 100644 index 000000000000..7069c4d7f3ca --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-fvp-base.inc @@ -0,0 +1,6 @@ +EDK2_BUILD_RELEASE = "0" +EDK2_PLATFORM = "ArmVExpress-FVP-AArch64" +EDK2_PLATFORM_DSC = "Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc" +EDK2_BIN_NAME = "FVP_AARCH64_EFI.fd" + +COMPATIBLE_MACHINE = "fvp-base" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-juno.inc b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-juno.inc new file mode 100644 index 000000000000..44613f134ab9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-juno.inc @@ -0,0 +1,5 @@ +EDK2_PLATFORM = "ArmJuno" +EDK2_PLATFORM_DSC = "Platform/ARM/JunoPkg/ArmJuno.dsc" +EDK2_BIN_NAME = "BL33_AP_UEFI.fd" + +COMPATIBLE_MACHINE = "juno" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-n1sdp.inc b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-n1sdp.inc new file mode 100644 index 000000000000..629ea04947f2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-n1sdp.inc @@ -0,0 +1,30 @@ +# Align with N1SDP-2022.06.22 release +SRCREV_edk2 = "b24306f15daa2ff8510b06702114724b33895d3c" +SRCREV_edk2-platforms = "fdaf4eb69a8b6839aecf6d3bdd938aa5c34a8a17" +PV .= "+git${SRCPV}" + +# N1SDP specific EDK2 configurations +EDK2_BUILD_RELEASE = "0" +EDK2_PLATFORM = "n1sdp" +EDK2_PLATFORM_DSC = "Platform/ARM/N1Sdp/N1SdpPlatform.dsc" +EDK2_BIN_NAME = "BL33_AP_UEFI.fd" + +COMPATIBLE_MACHINE = "n1sdp" + +# UEFI EDK2 on N1SDP is unable to detect FS2 during boot resulting in launching of +# EDK2 shell instead of launching grub. The startup.nsh will force launching of grub +EFIDIR = "/EFI/BOOT" +EFI_BOOT_IMAGE = "bootaa64.efi" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files/edk2-platforms:" + +SRC_URI:append = "\ + file://0001-Platform-ARM-N1sdp-Add-support-to-parse-NT_FW_CONFIG.patch;patchdir=edk2-platforms \ + file://0002-Platform-ARM-N1Sdp-Fix-RemoteDdrSize-cast.patch;patchdir=edk2-platforms \ + file://0003-Platform-ARM-N1Sdp-Modify-the-IRQ-ID-of-Debug-UART-a.patch;patchdir=edk2-platforms \ +" + +do_deploy:append() { + EFIPATH=$(echo "${EFIDIR}" | sed 's/\//\\/g') + printf 'FS2:%s\%s\n' "$EFIPATH" "${EFI_BOOT_IMAGE}" > ${DEPLOYDIR}/startup.nsh +} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-sgi575.inc b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-sgi575.inc new file mode 100644 index 000000000000..e26225f87a07 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware-sgi575.inc @@ -0,0 +1,7 @@ +# SGI575 specific EDK2 configurations +EDK2_BUILD_RELEASE = "0" +EDK2_PLATFORM = "Sgi575" +EDK2_PLATFORM_DSC = "Platform/ARM/SgiPkg/Sgi575/Sgi575.dsc" +EDK2_BIN_NAME = "BL33_AP_UEFI.fd" + +COMPATIBLE_MACHINE = "sgi575" diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware_%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware_%.bbappend new file mode 100644 index 000000000000..e5018bb00b29 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/edk2-firmware_%.bbappend @@ -0,0 +1,10 @@ +# Include machine specific configurations for UEFI EDK2 + +MACHINE_EDK2_REQUIRE ?= "" + +MACHINE_EDK2_REQUIRE:fvp-base = "edk2-firmware-fvp-base.inc" +MACHINE_EDK2_REQUIRE:juno = "edk2-firmware-juno.inc" +MACHINE_EDK2_REQUIRE:sgi575 = "edk2-firmware-sgi575.inc" +MACHINE_EDK2_REQUIRE:n1sdp = "edk2-firmware-n1sdp.inc" + +require ${MACHINE_EDK2_REQUIRE} diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0001-Platform-ARM-N1sdp-Add-support-to-parse-NT_FW_CONFIG.patch b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0001-Platform-ARM-N1sdp-Add-support-to-parse-NT_FW_CONFIG.patch new file mode 100644 index 000000000000..e5526dd66e3d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0001-Platform-ARM-N1sdp-Add-support-to-parse-NT_FW_CONFIG.patch @@ -0,0 +1,475 @@ +From fa3fd24ffbc987e952a2e5610a7b02556afd2087 Mon Sep 17 00:00:00 2001 +From: sahil +Date: Thu, 17 Mar 2022 16:28:05 +0530 +Subject: [PATCH 1/3] Platform/ARM/N1sdp: Add support to parse NT_FW_CONFIG + +NT_FW_CONFIG DTB contains platform information passed by +Tf-A boot stage. +This information is used for Virtual memory map generation +during PEI phase and passed on to DXE phase as a HOB, where +it is used in ConfigurationManagerDxe. + +Upstream-Status: Pending +Signed-off-by: Adam Johnston +Signed-off-by: Xueliang Zhong +Signed-off-by: sahil +Change-Id: Ib82571280bf1ca5febe5766e618de09e7b70bb02 + +--- + .../ConfigurationManager.c | 24 ++-- + .../ConfigurationManagerDxe.inf | 3 +- + .../ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h | 16 +-- + .../Library/PlatformLib/AArch64/Helper.S | 4 +- + .../Library/PlatformLib/PlatformLib.c | 12 +- + .../Library/PlatformLib/PlatformLib.inf | 8 +- + .../Library/PlatformLib/PlatformLibMem.c | 103 +++++++++++++++++- + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec | 7 +- + 8 files changed, 152 insertions(+), 25 deletions(-) + +diff --git a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +index f50623ae..e023d47c 100644 +--- a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c ++++ b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +@@ -1,7 +1,7 @@ + /** @file + Configuration Manager Dxe + +- Copyright (c) 2021, ARM Limited. All rights reserved.
++ Copyright (c) 2021 - 2022, ARM Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -28,6 +29,7 @@ + #include "Platform.h" + + extern struct EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE Hmat; ++static NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + + /** The platform configuration repository information. + */ +@@ -1242,13 +1244,11 @@ InitializePlatformRepository ( + IN EDKII_PLATFORM_REPOSITORY_INFO * CONST PlatRepoInfo + ) + { +- NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + UINT64 Dram2Size; + UINT64 RemoteDdrSize; + + RemoteDdrSize = 0; + +- PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE; + Dram2Size = ((PlatInfo->LocalDdrSize - 2) * SIZE_1GB); + + PlatRepoInfo->MemAffInfo[LOCAL_DDR_REGION2].Length = Dram2Size; +@@ -1512,7 +1512,6 @@ GetGicCInfo ( + ) + { + EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo; +- NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + UINT32 TotalObjCount; + UINT32 ObjIndex; + +@@ -1523,7 +1522,6 @@ GetGicCInfo ( + } + + PlatformRepo = This->PlatRepoInfo; +- PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE; + + if (PlatInfo->MultichipMode == 1) { + TotalObjCount = PLAT_CPU_COUNT * 2; +@@ -1623,7 +1621,6 @@ GetStandardNameSpaceObject ( + { + EFI_STATUS Status; + EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo; +- NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + UINT32 AcpiTableCount; + + if ((This == NULL) || (CmObject == NULL)) { +@@ -1634,7 +1631,7 @@ GetStandardNameSpaceObject ( + + Status = EFI_NOT_FOUND; + PlatformRepo = This->PlatRepoInfo; +- PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE; ++ + AcpiTableCount = ARRAY_SIZE (PlatformRepo->CmAcpiTableList); + if (PlatInfo->MultichipMode == 0) + AcpiTableCount -= 1; +@@ -1697,7 +1694,6 @@ GetArmNameSpaceObject ( + { + EFI_STATUS Status; + EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo; +- NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + UINT32 GicRedistCount; + UINT32 GicCpuCount; + UINT32 ProcHierarchyInfoCount; +@@ -1718,8 +1714,6 @@ GetArmNameSpaceObject ( + Status = EFI_NOT_FOUND; + PlatformRepo = This->PlatRepoInfo; + +- // Probe for multi chip information +- PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE; + if (PlatInfo->MultichipMode == 1) { + GicRedistCount = 2; + GicCpuCount = PLAT_CPU_COUNT * 2; +@@ -2162,8 +2156,18 @@ ConfigurationManagerDxeInitialize ( + IN EFI_SYSTEM_TABLE * SystemTable + ) + { ++ VOID *PlatInfoHob; + EFI_STATUS Status; + ++ PlatInfoHob = GetFirstGuidHob (&gArmNeoverseN1SocPlatformInfoDescriptorGuid); ++ ++ if (PlatInfoHob == NULL) { ++ DEBUG ((DEBUG_ERROR, "Platform HOB is NULL\n")); ++ return EFI_NOT_FOUND; ++ } ++ ++ PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)GET_GUID_HOB_DATA (PlatInfoHob); ++ + // Initialize the Platform Configuration Repository before installing the + // Configuration Manager Protocol + Status = InitializePlatformRepository ( +diff --git a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf +index 4f8e7f13..fb59c295 100644 +--- a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf ++++ b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf +@@ -1,7 +1,7 @@ + ## @file + # Configuration Manager Dxe + # +-# Copyright (c) 2021, ARM Limited. All rights reserved.
++# Copyright (c) 2021 - 2022, ARM Limited. All rights reserved.
+ # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -42,6 +42,7 @@ + + [LibraryClasses] + ArmPlatformLib ++ HobLib + PrintLib + UefiBootServicesTableLib + UefiDriverEntryPoint +diff --git a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h +index 097160c7..63cebaf0 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h ++++ b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h +@@ -1,6 +1,6 @@ + /** @file + * +-* Copyright (c) 2018 - 2020, ARM Limited. All rights reserved. ++* Copyright (c) 2018 - 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * +@@ -41,11 +41,6 @@ + #define NEOVERSEN1SOC_EXP_PERIPH_BASE0 0x1C000000 + #define NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ 0x1300000 + +-// Base address to a structure of type NEOVERSEN1SOC_PLAT_INFO which is +-// pre-populated by a earlier boot stage +-#define NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE (NEOVERSEN1SOC_NON_SECURE_SRAM_BASE + \ +- 0x00008000) +- + /* + * Platform information structure stored in Non-secure SRAM. Platform + * information are passed from the trusted firmware with the below structure +@@ -55,12 +50,17 @@ + typedef struct { + /*! 0 - Single Chip, 1 - Chip to Chip (C2C) */ + UINT8 MultichipMode; +- /*! Slave count in C2C mode */ +- UINT8 SlaveCount; ++ /*! Secondary chip count in C2C mode */ ++ UINT8 SecondaryChipCount; + /*! Local DDR memory size in GigaBytes */ + UINT8 LocalDdrSize; + /*! Remote DDR memory size in GigaBytes */ + UINT8 RemoteDdrSize; + } NEOVERSEN1SOC_PLAT_INFO; + ++// NT_FW_CONFIG DT structure ++typedef struct { ++ UINT64 NtFwConfigDtAddr; ++} NEOVERSEN1SOC_NT_FW_CONFIG_INFO_PPI; ++ + #endif +diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/AArch64/Helper.S b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/AArch64/Helper.S +index 8d2069de..88ed640d 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/AArch64/Helper.S ++++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/AArch64/Helper.S +@@ -1,6 +1,6 @@ + /** @file + * +-* Copyright (c) 2019 - 2020, ARM Limited. All rights reserved. ++* Copyright (c) 2019 - 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * +@@ -25,6 +25,8 @@ GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore) + // the UEFI firmware through the CPU registers. + // + ASM_PFX(ArmPlatformPeiBootAction): ++ adr x10, NtFwConfigDtBlob ++ str x0, [x10] + ret + + // +diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.c b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.c +index c0effd37..fabe902c 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.c ++++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.c +@@ -1,6 +1,6 @@ + /** @file + +- Copyright (c) 2018-2021, ARM Limited. All rights reserved.
++ Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -8,8 +8,12 @@ + + #include + #include ++#include + #include + ++UINT64 NtFwConfigDtBlob; ++STATIC NEOVERSEN1SOC_NT_FW_CONFIG_INFO_PPI mNtFwConfigDtInfoPpi; ++ + STATIC ARM_CORE_INFO mCoreInfoTable[] = { + { 0x0, 0x0 }, // Cluster 0, Core 0 + { 0x0, 0x1 }, // Cluster 0, Core 1 +@@ -46,6 +50,7 @@ ArmPlatformInitialize ( + IN UINTN MpId + ) + { ++ mNtFwConfigDtInfoPpi.NtFwConfigDtAddr = NtFwConfigDtBlob; + return RETURN_SUCCESS; + } + +@@ -80,6 +85,11 @@ EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gArmMpCoreInfoPpiGuid, + &mMpCoreInfoPpi ++ }, ++ { ++ EFI_PEI_PPI_DESCRIPTOR_PPI, ++ &gNtFwConfigDtInfoPpiGuid, ++ &mNtFwConfigDtInfoPpi + } + }; + +diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.inf b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.inf +index 96e590cd..6f9c9d5a 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.inf ++++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.inf +@@ -1,7 +1,7 @@ + ## @file + # Platform Library for N1Sdp. + # +-# Copyright (c) 2018-2021, ARM Limited. All rights reserved.
++# Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+ # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -18,10 +18,14 @@ + [Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec ++ EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec + ++[LibraryClasses] ++ FdtLib ++ + [Sources.common] + PlatformLibMem.c + PlatformLib.c +@@ -59,7 +63,9 @@ + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + + [Guids] ++ gArmNeoverseN1SocPlatformInfoDescriptorGuid + gEfiHobListGuid ## CONSUMES ## SystemTable + + [Ppis] + gArmMpCoreInfoPpiGuid ++ gNtFwConfigDtInfoPpiGuid +diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c +index 339fa07b..b58bda4b 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c ++++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c +@@ -1,6 +1,6 @@ + /** @file + +- Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.
++ Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -10,11 +10,95 @@ + #include + #include + #include ++#include ++#include + #include + + // The total number of descriptors, including the final "end-of-table" descriptor. + #define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 19 + ++/** A helper function to locate the NtFwConfig PPI and get the base address of ++ NT_FW_CONFIG DT from which values are obtained using FDT helper functions. ++ ++ @param [out] plat_info Pointer to the NeoverseN1Soc PLATFORM_INFO HOB ++ ++ @retval EFI_SUCCESS Success. ++ returns EFI_INVALID_PARAMETER A parameter is invalid. ++**/ ++EFI_STATUS ++GetNeoverseN1SocPlatInfo ( ++ OUT NEOVERSEN1SOC_PLAT_INFO *plat_info ++ ) ++{ ++ CONST UINT32 *Property; ++ INT32 Offset; ++ CONST VOID *NtFwCfgDtBlob; ++ NEOVERSEN1SOC_NT_FW_CONFIG_INFO_PPI *NtFwConfigInfoPpi; ++ EFI_STATUS Status; ++ ++ Status = PeiServicesLocatePpi ( ++ &gNtFwConfigDtInfoPpiGuid, ++ 0, ++ NULL, ++ (VOID **)&NtFwConfigInfoPpi ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "PeiServicesLocatePpi failed with error %r\n", ++ Status ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ NtFwCfgDtBlob = (VOID *)(UINTN)NtFwConfigInfoPpi->NtFwConfigDtAddr; ++ if (fdt_check_header (NtFwCfgDtBlob) != 0) { ++ DEBUG ((DEBUG_ERROR, "Invalid DTB file %p passed\n", NtFwCfgDtBlob)); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Offset = fdt_subnode_offset (NtFwCfgDtBlob, 0, "platform-info"); ++ if (Offset == -FDT_ERR_NOTFOUND) { ++ DEBUG ((DEBUG_ERROR, "Invalid DTB : platform-info node not found\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Property = fdt_getprop (NtFwCfgDtBlob, Offset, "local-ddr-size", NULL); ++ if (Property == NULL) { ++ DEBUG ((DEBUG_ERROR, "local-ddr-size property not found\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ plat_info->LocalDdrSize = fdt32_to_cpu (*Property); ++ ++ Property = fdt_getprop (NtFwCfgDtBlob, Offset, "remote-ddr-size", NULL); ++ if (Property == NULL) { ++ DEBUG ((DEBUG_ERROR, "remote-ddr-size property not found\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ plat_info->RemoteDdrSize = fdt32_to_cpu (*Property); ++ ++ Property = fdt_getprop (NtFwCfgDtBlob, Offset, "secondary-chip-count", NULL); ++ if (Property == NULL) { ++ DEBUG ((DEBUG_ERROR, "secondary-chip-count property not found\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ plat_info->SecondaryChipCount = fdt32_to_cpu (*Property); ++ ++ Property = fdt_getprop (NtFwCfgDtBlob, Offset, "multichip-mode", NULL); ++ if (Property == NULL) { ++ DEBUG ((DEBUG_ERROR, "multichip-mode property not found\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ plat_info->MultichipMode = fdt32_to_cpu (*Property); ++ ++ return EFI_SUCCESS; ++} ++ + /** + Returns the Virtual Memory Map of the platform. + +@@ -36,9 +120,24 @@ ArmPlatformGetVirtualMemoryMap ( + NEOVERSEN1SOC_PLAT_INFO *PlatInfo; + UINT64 DramBlock2Size; + UINT64 RemoteDdrSize; ++ EFI_STATUS Status; + + Index = 0; +- PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE; ++ ++ // Create platform info HOB ++ PlatInfo = (NEOVERSEN1SOC_PLAT_INFO *)BuildGuidHob ( ++ &gArmNeoverseN1SocPlatformInfoDescriptorGuid, ++ sizeof (NEOVERSEN1SOC_PLAT_INFO) ++ ); ++ ++ if (PlatInfo == NULL) { ++ DEBUG ((DEBUG_ERROR, "Platform HOB is NULL\n")); ++ ASSERT (FALSE); ++ return; ++ } ++ ++ Status = GetNeoverseN1SocPlatInfo (PlatInfo); ++ ASSERT (Status == 0); + DramBlock2Size = ((UINT64)(PlatInfo->LocalDdrSize - + NEOVERSEN1SOC_DRAM_BLOCK1_SIZE / SIZE_1GB) * + (UINT64)SIZE_1GB); +diff --git a/Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec b/Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec +index d59f25a5..4dea8fe1 100644 +--- a/Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec ++++ b/Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec +@@ -1,7 +1,7 @@ + ## @file + # Describes the entire platform configuration. + # +-# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.
++# Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+ # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -22,6 +22,8 @@ + Include # Root include for the package + + [Guids.common] ++ # ARM NeoverseN1Soc Platform Info descriptor ++ gArmNeoverseN1SocPlatformInfoDescriptorGuid = { 0x095cb024, 0x1e00, 0x4d6f, { 0xaa, 0x34, 0x4a, 0xf8, 0xaf, 0x0e, 0xad, 0x99 } } + gArmNeoverseN1SocTokenSpaceGuid = { 0xab93eb78, 0x60d7, 0x4099, { 0xac, 0xeb, 0x6d, 0xb5, 0x02, 0x58, 0x7c, 0x24 } } + + [PcdsFixedAtBuild] +@@ -83,3 +85,6 @@ + gArmNeoverseN1SocTokenSpaceGuid.PcdRemotePcieMmio32Translation|0x40000000000|UINT64|0x0000004F + gArmNeoverseN1SocTokenSpaceGuid.PcdRemotePcieMmio64Translation|0x40000000000|UINT64|0x00000050 + gArmNeoverseN1SocTokenSpaceGuid.PcdRemotePcieSegmentNumber|2|UINT32|0x00000051 ++ ++[Ppis] ++ gNtFwConfigDtInfoPpiGuid = { 0xb50dee0e, 0x577f, 0x47fb, { 0x83, 0xd0, 0x41, 0x78, 0x61, 0x8b, 0x33, 0x8a } } +-- +2.37.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0002-Platform-ARM-N1Sdp-Fix-RemoteDdrSize-cast.patch b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0002-Platform-ARM-N1Sdp-Fix-RemoteDdrSize-cast.patch new file mode 100644 index 000000000000..1c097fcc7e4d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0002-Platform-ARM-N1Sdp-Fix-RemoteDdrSize-cast.patch @@ -0,0 +1,48 @@ +From 73aab76042ae34fa4b07414c1830129e572dcd65 Mon Sep 17 00:00:00 2001 +From: sahil +Date: Wed, 20 Apr 2022 12:24:41 +0530 +Subject: [PATCH 2/3] Platform/ARM/N1Sdp: Fix RemoteDdrSize cast + +RemoteDdrSize calculation wraps around when booting N1Sdp in +multichip mode. Casting it to UINT64 to fix the issue. + +Upstream-Status: Pending +Signed-off-by: Adam Johnston +Signed-off-by: Xueliang Zhong +Signed-off-by: sahil +Change-Id: I2c2a70c2ab046337236fba92d25dec5905ccd117 + +--- + .../ConfigurationManagerDxe/ConfigurationManager.c | 2 +- + Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +index e023d47c..36b5fc9e 100644 +--- a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c ++++ b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +@@ -1254,7 +1254,7 @@ InitializePlatformRepository ( + PlatRepoInfo->MemAffInfo[LOCAL_DDR_REGION2].Length = Dram2Size; + + if (PlatInfo->MultichipMode == 1) { +- RemoteDdrSize = ((PlatInfo->RemoteDdrSize - 2) * SIZE_1GB); ++ RemoteDdrSize = ((UINT64)(PlatInfo->RemoteDdrSize - 2) * SIZE_1GB); + + // Update Remote DDR Region1 + PlatRepoInfo->MemAffInfo[REMOTE_DDR_REGION1].ProximityDomain = 1; +diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c +index b58bda4b..fbc9b05e 100644 +--- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c ++++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c +@@ -157,7 +157,7 @@ ArmPlatformGetVirtualMemoryMap ( + DramBlock2Size); + + if (PlatInfo->MultichipMode == 1) { +- RemoteDdrSize = ((PlatInfo->RemoteDdrSize - 2) * SIZE_1GB); ++ RemoteDdrSize = ((UINT64)(PlatInfo->RemoteDdrSize - 2) * SIZE_1GB); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, +-- +2.37.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0003-Platform-ARM-N1Sdp-Modify-the-IRQ-ID-of-Debug-UART-a.patch b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0003-Platform-ARM-N1Sdp-Modify-the-IRQ-ID-of-Debug-UART-a.patch new file mode 100644 index 000000000000..f0de02eb662d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0003-Platform-ARM-N1Sdp-Modify-the-IRQ-ID-of-Debug-UART-a.patch @@ -0,0 +1,67 @@ +From adc66d99663f71ec97313c40b0d00a908f292c30 Mon Sep 17 00:00:00 2001 +From: Himanshu Sharma +Date: Mon, 30 May 2022 10:53:30 +0000 +Subject: [PATCH 3/3] Platform/ARM/N1Sdp: Modify the IRQ ID of Debug UART and + routing it to IOFPGA UART1 + +In DBG2 table, IRQ ID was set as 0 for the UART. This overwrote the +IPI0 trigger method to "level", which prevented SGI0 to be enabled +again after a CPU offline/online cycle. + +This patch fixes the above issue by assigning a reserved IRQ ID +for the Debug UART, other than 0 and also routing it to use IOFPGA +UART1 by unsharing it from currently using serial terminal. + +Upstream-Status: Pending +Signed-off-by: Adam Johnston +Signed-off-by: Xueliang Zhong +Signed-off-by: Himanshu Sharma +Change-Id: I6640c3c8f77afd233304ce9cb06dcf80a8659c16 + +--- + .../ConfigurationManagerDxe/ConfigurationManager.c | 2 +- + Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +index 36b5fc9e..e8873200 100644 +--- a/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c ++++ b/Platform/ARM/N1Sdp/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c +@@ -320,7 +320,7 @@ EDKII_PLATFORM_REPOSITORY_INFO N1sdpRepositoryInfo = { + // Debug Serial Port + { + FixedPcdGet64 (PcdSerialDbgRegisterBase), // BaseAddress +- 0, // Interrupt -unused ++ 250, // Interrupt (reserved) + FixedPcdGet64 (PcdSerialDbgUartBaudRate), // BaudRate + FixedPcdGet32 (PcdSerialDbgUartClkInHz), // Clock + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART // Port subtype +diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc +index 865dd04d..878c8f2f 100644 +--- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc ++++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc +@@ -4,7 +4,7 @@ + # This provides platform specific component descriptions and libraries that + # conform to EFI/Framework standards. + # +-# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.
++# Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+ # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -136,9 +136,9 @@ + gArmPlatformTokenSpaceGuid.PL011UartInterrupt|95 + + # PL011 Serial Debug UART (DBG2) +- gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase|gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase +- gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate|gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate +- gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz|50000000 ++ gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase|0x1C0A0000 ++ gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate|115200 ++ gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz|24000000 + + # SBSA Watchdog + gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum|93 +-- +2.37.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/files/juno/interfaces b/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/files/juno/interfaces new file mode 100644 index 000000000000..8c323c2a4842 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/files/juno/interfaces @@ -0,0 +1,32 @@ +# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) + +# The loopback interface +auto lo +iface lo inet loopback + +# Wireless interfaces +iface wlan0 inet dhcp + wireless_mode managed + wireless_essid any + wpa-driver wext + wpa-conf /etc/wpa_supplicant.conf + + +# Wired or wireless interfaces +auto eth0 +# Juno has 2 ethernet (front and back) +auto eth1 +iface eth0 inet dhcp +iface eth1 inet dhcp + +# Ethernet/RNDIS gadget (g_ether) +# ... or on host side, usbnet and random hwaddr +iface usb0 inet static + address 192.168.7.2 + netmask 255.255.255.0 + network 192.168.7.0 + gateway 192.168.7.1 + +# Bluetooth networking +iface bnep0 inet dhcp + diff --git a/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend b/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend new file mode 100644 index 000000000000..65e37d8e7c61 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend @@ -0,0 +1,8 @@ +# Use custom interface file for Juno + +# +# Enable second network interface on startup +# +PACKAGE_ARCH = "${MACHINE_ARCH}" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files:" diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/README.md b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/README.md new file mode 100644 index 000000000000..ba61ca323f91 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/README.md @@ -0,0 +1,4 @@ +Arm platforms BSPs +================== + +This directory contains Arm platforms definitions and configuration for Linux. diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/arm64.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/arm64.cfg new file mode 100644 index 000000000000..62c023878633 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/arm64.cfg @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: MIT +# +# ARM64 +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_VEXPRESS=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y + +# +# Bus devices +# +CONFIG_VEXPRESS_CONFIG=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000-standard.scc new file mode 100644 index 000000000000..9278ce11a5aa --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000-standard.scc @@ -0,0 +1,5 @@ +define KMACHINE corstone1000 +define KTYPE standard +define KARCH arm64 + +kconf hardware corstone1000/base.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000/base.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000/base.cfg new file mode 100644 index 000000000000..aea1d84e5928 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/corstone1000/base.cfg @@ -0,0 +1,29 @@ +CONFIG_LOCALVERSION="-yocto-standard" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_LOG_BUF_SHIFT=12 +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARM64=y +CONFIG_THUMB2_KERNEL=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_VFP=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y +CONFIG_TMPFS=y +# CONFIG_WLAN is not set +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y +CONFIG_MAILBOX=y +# CONFIG_CRYPTO_HW is not set diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32-standard.scc new file mode 100644 index 000000000000..656902745d6a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32-standard.scc @@ -0,0 +1,8 @@ +define KMACHINE fvp-arm32 +define KTYPE standard +define KARCH arm + +include ktypes/standard/standard.scc + +include fvp-arm32.scc + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32.scc new file mode 100644 index 000000000000..ff7ce5729523 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32.scc @@ -0,0 +1,14 @@ +include features/input/input.scc +include features/net/net.scc +include cfg/timer/no_hz.scc +include cfg/virtio.scc + +kconf hardware fvp-arm32/fvp-board.cfg +kconf hardware fvp-arm32/fvp-features.cfg +kconf hardware fvp/fvp-net.cfg +kconf hardware fvp/fvp-rtc.cfg +kconf hardware fvp/fvp-serial.cfg +kconf hardware fvp/fvp-cfi.cfg +kconf hardware fvp/fvp-drm.cfg +kconf hardware fvp/fvp-timer.cfg +kconf hardware fvp/fvp-watchdog.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-board.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-board.cfg new file mode 100644 index 000000000000..e49a1e367ce9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-board.cfg @@ -0,0 +1,12 @@ +CONFIG_ARM=y + +CONFIG_ARCH_VEXPRESS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y + +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y + +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-features.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-features.cfg new file mode 100644 index 000000000000..12e7697104ec --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-arm32/fvp-features.cfg @@ -0,0 +1,9 @@ +CONFIG_BINFMT_MISC=y +CONFIG_BOUNCE=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_NEON=y +CONFIG_VFP=y +CONFIG_VFPv3=y + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc new file mode 100644 index 000000000000..e8fea0b8224a --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc @@ -0,0 +1,6 @@ +define KMACHINE fvp-baser-aemv8r64 +define KTYPE preempt-rt +define KARCH arm64 + +include ktypes/preempt-rt/preempt-rt.scc +include fvp-baser-aemv8r64.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc new file mode 100644 index 000000000000..fd1fb2824678 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc @@ -0,0 +1,7 @@ +define KMACHINE fvp-baser-aemv8r64 +define KTYPE standard +define KARCH arm64 + +include ktypes/standard/standard.scc + +include fvp-baser-aemv8r64.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc new file mode 100644 index 000000000000..a8d796702c22 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc @@ -0,0 +1,4 @@ +kconf hardware arm64.cfg +kconf hardware fvp-common-peripherals.cfg +include cfg/virtio.scc +include virtio-9p.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-common-peripherals.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-common-peripherals.cfg new file mode 100644 index 000000000000..ecb3cc9da44f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-common-peripherals.cfg @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: MIT +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + +CONFIG_ARM_SP805_WATCHDOG=y + +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-standard.scc new file mode 100644 index 000000000000..d29e0b811bee --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-standard.scc @@ -0,0 +1,11 @@ +define KMACHINE fvp +define KTYPE standard +define KARCH arm64 + +include ktypes/standard/standard.scc + +include fvp.scc + +# default policy for standard kernels +#include features/latencytop/latencytop.scc +#include features/profiling/profiling.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp.scc new file mode 100644 index 000000000000..80b858198b37 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp.scc @@ -0,0 +1,13 @@ +include features/input/input.scc +include features/net/net.scc +include cfg/timer/no_hz.scc +include cfg/virtio.scc + +kconf hardware fvp/fvp-board.cfg +kconf hardware fvp/fvp-net.cfg +kconf hardware fvp/fvp-rtc.cfg +kconf hardware fvp/fvp-serial.cfg +kconf hardware fvp/fvp-cfi.cfg +kconf hardware fvp/fvp-drm.cfg +kconf hardware fvp/fvp-timer.cfg +kconf hardware fvp/fvp-watchdog.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-board.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-board.cfg new file mode 100644 index 000000000000..a9ee80e11a69 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-board.cfg @@ -0,0 +1,10 @@ +CONFIG_ARM64=y +CONFIG_ARCH_VEXPRESS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y + +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y + +CONFIG_CPU_IDLE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-cfi.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-cfi.cfg new file mode 100644 index 000000000000..f28e0d920504 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-cfi.cfg @@ -0,0 +1,3 @@ +# CFI Flash +CONFIG_MTD=y +CONFIG_MTD_CFI=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-drm.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-drm.cfg new file mode 100644 index 000000000000..77133a9dfe3f --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-drm.cfg @@ -0,0 +1,5 @@ +# DRM CLCD +CONFIG_DRM=y +CONFIG_DRM_PL111=y +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-net.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-net.cfg new file mode 100644 index 000000000000..20cc408f3966 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-net.cfg @@ -0,0 +1,3 @@ +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMSC911X=y +CONFIG_SMC91X=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-rtc.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-rtc.cfg new file mode 100644 index 000000000000..5d377b396a87 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-rtc.cfg @@ -0,0 +1,2 @@ +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-serial.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-serial.cfg new file mode 100644 index 000000000000..445716403925 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-serial.cfg @@ -0,0 +1,2 @@ +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-timer.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-timer.cfg new file mode 100644 index 000000000000..b33c65c283da --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-timer.cfg @@ -0,0 +1,4 @@ +# Dual timer module +CONFIG_COMPILE_TEST=y +CONFIG_ARM_TIMER_SP804=y +CONFIG_CLK_SP810=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-watchdog.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-watchdog.cfg new file mode 100644 index 000000000000..977f317c86b7 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp/fvp-watchdog.cfg @@ -0,0 +1,3 @@ +# Watchdog +CONFIG_WATCHDOG=y +CONFIG_ARM_SP805_WATCHDOG=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno-standard.scc new file mode 100644 index 000000000000..c9d2405a275e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno-standard.scc @@ -0,0 +1,11 @@ +define KMACHINE juno +define KTYPE standard +define KARCH arm64 + +include ktypes/standard/standard.scc + +include juno.scc + +# default policy for standard kernels +#include features/latencytop/latencytop.scc +#include features/profiling/profiling.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno.scc new file mode 100644 index 000000000000..a167d2254d99 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno.scc @@ -0,0 +1,24 @@ +include features/input/input.scc +include features/net/net.scc +include features/usb/usb-base.scc +include features/bluetooth/bluetooth.scc +include cfg/timer/no_hz.scc +include cfg/usb-mass-storage.scc + +kconf hardware juno/juno-board.cfg +kconf hardware juno/juno-devfreq.cfg +kconf hardware juno/juno-dma.cfg +kconf hardware juno/juno-drm.cfg +kconf hardware juno/juno-fb.cfg +kconf hardware juno/juno-i2c.cfg +# kconf hardware juno/juno-mali-midgard.cfg +kconf hardware juno/juno-mmc.cfg +kconf hardware juno/juno-net.cfg +kconf hardware juno/juno-pci.cfg +kconf hardware juno/juno-rtc.cfg +kconf hardware juno/juno-sata.cfg +kconf hardware juno/juno-serial.cfg +kconf hardware juno/juno-sound.cfg +kconf hardware juno/juno-thermal.cfg +kconf hardware juno/juno-usb.cfg + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-board.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-board.cfg new file mode 100644 index 000000000000..2d7ad8c47508 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-board.cfg @@ -0,0 +1,42 @@ +CONFIG_ARM64=y +CONFIG_ARCH_VEXPRESS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y + +# Keyboard over AMBA +CONFIG_SERIO=y +CONFIG_SERIO_AMBAKMI=y + +# Hardware mailbox +CONFIG_MAILBOX=y +CONFIG_ARM_MHU=y + +# SCMI support +CONFIG_HWMON=y +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=y +CONFIG_ARM_SCMI_POWER_DOMAIN=y +CONFIG_SENSORS_ARM_SCMI=y +CONFIG_COMMON_CLK_SCMI=y + +# Power Interface and system control +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_ARM_SCPI_POWER_DOMAIN=y +CONFIG_SENSORS_ARM_SCPI=y +CONFIG_COMMON_CLK_SCPI=y + +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y + +CONFIG_CPU_IDLE=y + +CONFIG_CPU_FREQ=y +CONFIG_ARM_SCPI_CPUFREQ=y + +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y + +CONFIG_CONNECTOR=y +CONFIG_PRINTK_TIME=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-devfreq.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-devfreq.cfg new file mode 100644 index 000000000000..474e01052872 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-devfreq.cfg @@ -0,0 +1,4 @@ +CONFIG_PM_DEVFREQ=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-dma.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-dma.cfg new file mode 100644 index 000000000000..cbdffa3eecca --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-dma.cfg @@ -0,0 +1,5 @@ +CONFIG_DMADEVICES=y +CONFIG_PL330_DMA=y +CONFIG_CMA=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=96 diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-drm.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-drm.cfg new file mode 100644 index 000000000000..1216297943f0 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-drm.cfg @@ -0,0 +1,5 @@ +CONFIG_DRM=y +CONFIG_DRM_HDLCD=y +CONFIG_DRM_I2C_NXP_TDA998X=y +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-fb.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-fb.cfg new file mode 100644 index 000000000000..59499fa649ee --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-fb.cfg @@ -0,0 +1,4 @@ +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_VGA_CONSOLE is not set diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-i2c.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-i2c.cfg new file mode 100644 index 000000000000..97f80c439118 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-i2c.cfg @@ -0,0 +1,2 @@ +CONFIG_I2C=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mali-midgard.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mali-midgard.cfg new file mode 100644 index 000000000000..adf02b7fbd6d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mali-midgard.cfg @@ -0,0 +1,7 @@ +CONFIG_MALI_MIDGARD=y +CONFIG_MALI_EXPERT=y +CONFIG_MALI_PLATFORM_FAKE=y +CONFIG_MALI_PLATFORM_THIRDPARTY=y +CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="juno_soc" +CONFIG_MALI_PLATFORM_DEVICETREE=y +CONFIG_MALI_DEVFREQ=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mmc.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mmc.cfg new file mode 100644 index 000000000000..41af527c8aaa --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-mmc.cfg @@ -0,0 +1,2 @@ +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-net.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-net.cfg new file mode 100644 index 000000000000..20cc408f3966 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-net.cfg @@ -0,0 +1,3 @@ +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMSC911X=y +CONFIG_SMC91X=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-pci.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-pci.cfg new file mode 100644 index 000000000000..ec919e39a226 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-pci.cfg @@ -0,0 +1,12 @@ +CONFIG_PCI=y +CONFIG_PCI_IOV=y +CONFIG_PCI_MSI=y +CONFIG_PCI_REALLOC_ENABLE_AUTO=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIEAER=y +CONFIG_PCIE_ECRC=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-rtc.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-rtc.cfg new file mode 100644 index 000000000000..5d377b396a87 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-rtc.cfg @@ -0,0 +1,2 @@ +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sata.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sata.cfg new file mode 100644 index 000000000000..179d7b8f9534 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sata.cfg @@ -0,0 +1,2 @@ +CONFIG_ATA=y +CONFIG_SATA_SIL24=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-serial.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-serial.cfg new file mode 100644 index 000000000000..445716403925 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-serial.cfg @@ -0,0 +1,2 @@ +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sound.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sound.cfg new file mode 100644 index 000000000000..d3419efdb589 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-sound.cfg @@ -0,0 +1,14 @@ +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_DESIGNWARE_I2S=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_SPDIF=y +CONFIG_SND_SIMPLE_CARD=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-thermal.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-thermal.cfg new file mode 100644 index 000000000000..f4d220e0de5b --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-thermal.cfg @@ -0,0 +1,8 @@ +CONFIG_THERMAL=y +CONFIG_THERMAL_OF=y +CONFIG_ENERGY_MODEL=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-usb.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-usb.cfg new file mode 100644 index 000000000000..9159de157e8b --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/juno/juno-usb.cfg @@ -0,0 +1,7 @@ +CONFIG_USB_STORAGE=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_OHCI_HCD=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-preempt-rt.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-preempt-rt.scc new file mode 100644 index 000000000000..dc844458bbc6 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-preempt-rt.scc @@ -0,0 +1,6 @@ +define KMACHINE n1sdp +define KTYPE preempt-rt +define KARCH arm64 + +include ktypes/preempt-rt/preempt-rt.scc +include n1sdp/disable-kvm.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-standard.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-standard.scc new file mode 100644 index 000000000000..8536c818c90c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp-standard.scc @@ -0,0 +1,5 @@ +define KMACHINE n1sdp +define KTYPE standard +define KARCH arm64 + +include ktypes/standard/standard.scc diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp/disable-kvm.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp/disable-kvm.cfg new file mode 100644 index 000000000000..617d3e51b1ae --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/n1sdp/disable-kvm.cfg @@ -0,0 +1 @@ +# CONFIG_KVM is not set diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc-autofdo.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc-autofdo.scc new file mode 100644 index 000000000000..5b20b6c08596 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc-autofdo.scc @@ -0,0 +1 @@ +kconf non-hardware tc/autofdo.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc new file mode 100644 index 000000000000..6542e6bc5599 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc @@ -0,0 +1,13 @@ +kconf hardware tc/base.cfg +kconf non-hardware tc/dhcp.cfg +kconf non-hardware tc/devtmpfs.cfg +kconf non-hardware tc/gralloc.cfg +kconf non-hardware tc/mali.cfg +kconf non-hardware tc/ffa.cfg +kconf non-hardware tc/optee.cfg +kconf non-hardware tc/virtio.cfg +kconf non-hardware tc/autofdo.cfg +kconf non-hardware tc/ci700.cfg +kconf non-hardware tc/trusty.cfg +kconf non-hardware tc/disable_mpam.cfg +kconf non-hardware tc/disable_btf.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/autofdo.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/autofdo.cfg new file mode 100644 index 000000000000..8530c8840914 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/autofdo.cfg @@ -0,0 +1,3 @@ +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_SOURCE_ETM4X=y +CONFIG_CORESIGHT_TRBE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/base.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/base.cfg new file mode 100644 index 000000000000..90b08f128c61 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/base.cfg @@ -0,0 +1,12 @@ +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARM_MHU=y +CONFIG_ARM_MHU_V2=y +CONFIG_ARM_SMMU_V3=y +CONFIG_ARM64_VA_BITS_48=y +CONFIG_COMMON_CLK_SCMI=y +CONFIG_DRM_HDLCD=y +CONFIG_DRM_KOMEDA=y +CONFIG_DRM_VIRT_ENCODER=y +CONFIG_MMC_ARMMMCI=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SMC91X=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg new file mode 100644 index 000000000000..50c015319fbc --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg @@ -0,0 +1 @@ +CONFIG_ARM_CMN=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/devtmpfs.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/devtmpfs.cfg new file mode 100644 index 000000000000..abde41232b07 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/devtmpfs.cfg @@ -0,0 +1,3 @@ +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_VT=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/dhcp.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/dhcp.cfg new file mode 100644 index 000000000000..78c5a040dda5 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/dhcp.cfg @@ -0,0 +1,2 @@ +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_btf.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_btf.cfg new file mode 100644 index 000000000000..27433824b468 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_btf.cfg @@ -0,0 +1 @@ +CONFIG_DEBUG_INFO_BTF=n diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_mpam.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_mpam.cfg new file mode 100644 index 000000000000..2dceb6ccb9b4 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/disable_mpam.cfg @@ -0,0 +1 @@ +CONFIG_ARM64_MPAM=n diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ffa.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ffa.cfg new file mode 100644 index 000000000000..34de78e8955d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ffa.cfg @@ -0,0 +1 @@ +CONFIG_ARM_FFA_TRANSPORT=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/gralloc.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/gralloc.cfg new file mode 100644 index 000000000000..22abcb5456cc --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/gralloc.cfg @@ -0,0 +1,2 @@ +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/mali.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/mali.cfg new file mode 100644 index 000000000000..166818f97c27 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/mali.cfg @@ -0,0 +1 @@ +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/optee.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/optee.cfg new file mode 100644 index 000000000000..07554cf843d3 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/optee.cfg @@ -0,0 +1,2 @@ +CONFIG_TEE=y +CONFIG_OPTEE=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/trusty.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/trusty.cfg new file mode 100644 index 000000000000..54e8657f26b9 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/trusty.cfg @@ -0,0 +1 @@ +CONFIG_TRUSTY=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/virtio.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/virtio.cfg new file mode 100644 index 000000000000..9e6d21c4e8dd --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/virtio.cfg @@ -0,0 +1,2 @@ +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_MMIO=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.cfg new file mode 100644 index 000000000000..c9fefa14b657 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.cfg @@ -0,0 +1,4 @@ +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_9P_FS=y +CONFIG_9P_FS_POSIX_ACL=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.scc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.scc new file mode 100644 index 000000000000..33c0465c66eb --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/virtio-9p.scc @@ -0,0 +1 @@ +kconf non-hardware virtio-9p.cfg diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0002-Add-external-system-driver.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0002-Add-external-system-driver.patch new file mode 100644 index 000000000000..ae69090a361c --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0002-Add-external-system-driver.patch @@ -0,0 +1,223 @@ +Upstream-Status: Pending[Not submitted to upstream yet] +Signed-off-by: Emekcan Aras + +From 97509e82b51c57935fc8e918b33c09c4f6648ed7 Mon Sep 17 00:00:00 2001 +From: Emekcan +Date: Fri, 19 Aug 2022 14:51:08 +0100 +Subject: [PATCH] Add external system driver + +Adds external system driver to control it +from user-space. It provides run and reset +functionality at the moment. + +Signed-off-by: Emekcan Aras +--- + drivers/misc/Kconfig | 2 + + drivers/misc/Makefile | 1 + + drivers/misc/arm/Kconfig | 5 ++ + drivers/misc/arm/Makefile | 1 + + drivers/misc/arm/extsys_ctrl.c | 151 +++++++++++++++++++++++++++++++++ + 5 files changed, 160 insertions(+) + create mode 100644 drivers/misc/arm/Kconfig + create mode 100644 drivers/misc/arm/Makefile + create mode 100644 drivers/misc/arm/extsys_ctrl.c + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 0f5a49fc7c9e..5ca195110b3f 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -487,4 +487,6 @@ source "drivers/misc/cardreader/Kconfig" + source "drivers/misc/habanalabs/Kconfig" + source "drivers/misc/uacce/Kconfig" + source "drivers/misc/pvpanic/Kconfig" ++source "drivers/misc/arm/Kconfig" ++ + endmenu +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index a086197af544..f5c1bd5747f7 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -59,3 +59,4 @@ obj-$(CONFIG_UACCE) += uacce/ + obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o + obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o + obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o ++obj-y += arm/ +diff --git a/drivers/misc/arm/Kconfig b/drivers/misc/arm/Kconfig +new file mode 100644 +index 000000000000..3c4b3f08e6b4 +--- /dev/null ++++ b/drivers/misc/arm/Kconfig +@@ -0,0 +1,5 @@ ++config EXTSYS_CTRL ++ tristate "Arm External System control driver" ++ help ++ Say y here to enable support for external system control ++ driver for the Arm Corstone-700 and Corstone1000 platform +\ No newline at end of file +diff --git a/drivers/misc/arm/Makefile b/drivers/misc/arm/Makefile +new file mode 100644 +index 000000000000..1ca3084cf8a0 +--- /dev/null ++++ b/drivers/misc/arm/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_EXTSYS_CTRL) += extsys_ctrl.o +diff --git a/drivers/misc/arm/extsys_ctrl.c b/drivers/misc/arm/extsys_ctrl.c +new file mode 100644 +index 000000000000..1c6ef14a32ae +--- /dev/null ++++ b/drivers/misc/arm/extsys_ctrl.c +@@ -0,0 +1,151 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Arm Corstone700 and Corstone1000 external system reset control driver ++ * ++ * Copyright (C) 2019 Arm Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define EXTSYS_DRV_NAME "extsys_ctrl" ++#define EXTSYS_MAX_DEVS 4 ++ ++#define EXTSYS_RST_SIZE U(0x8) ++#define EXTSYS_RST_CTRL_OFF U(0x0) ++#define EXTSYS_RST_ST_OFF U(0x4) ++ ++/* External system reset control indexes */ ++#define EXTSYS_CPU_WAIT (0x0) ++#define EXTSYS_RST_REQ (0x1) ++ ++/* External system reset status masks */ ++#define EXTSYS_RST_ST_ACK_OFF U(0x1) ++ ++/* No Reset Requested */ ++#define EXTSYS_RST_ST_ACK_NRR (0x0 << EXTSYS_RST_ST_ACK_OFF) ++ ++/* Reset Request Complete */ ++#define EXTSYS_RST_ST_ACK_RRC (0x2 << EXTSYS_RST_ST_ACK_OFF) ++ ++/* Reset Request Unable to Complete */ ++#define EXTSYS_RST_ST_ACK_RRUC (0x3 << EXTSYS_RST_ST_ACK_OFF) ++ ++/* IOCTL commands */ ++#define EXTSYS_CPU_WAIT_DISABLE 0x0 ++#define EXTSYS_RESET_REQ_ENABLE 0x1 ++ ++struct extsys_ctrl { ++ struct miscdevice miscdev; ++ void __iomem *reset_reg; ++ void __iomem *set_reg; ++}; ++ ++#define CLEAR_BIT(addr, index) writel(readl(addr) & ~(1UL << index), addr) ++#define SET_BIT(addr, index) writel(readl(addr) | (1UL << index), addr) ++ ++static long extsys_ctrl_ioctl(struct file *f, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct extsys_ctrl *extsys; ++ ++ extsys = container_of(f->private_data, struct extsys_ctrl, miscdev); ++ ++ switch (cmd) { ++ case EXTSYS_CPU_WAIT_DISABLE: ++ CLEAR_BIT(extsys->reset_reg, EXTSYS_CPU_WAIT); ++ break; ++ case EXTSYS_RESET_REQ_ENABLE: ++ SET_BIT(extsys->reset_reg, EXTSYS_RST_REQ); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct file_operations extsys_ctrl_fops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = extsys_ctrl_ioctl, ++}; ++ ++static int extsys_ctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct extsys_ctrl *extsys; ++ struct resource *res; ++ void __iomem *reset_reg; ++ void __iomem *set_reg; ++ int ret; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rstreg"); ++ reset_reg = devm_ioremap_resource(dev, res); ++ if (IS_ERR(reset_reg)) ++ return PTR_ERR(reset_reg); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "streg"); ++ set_reg = devm_ioremap_resource(dev, res); ++ if (IS_ERR(set_reg)) ++ return PTR_ERR(set_reg); ++ ++ extsys = devm_kzalloc(dev, sizeof(*extsys), GFP_KERNEL); ++ if (!extsys) ++ return -ENOMEM; ++ ++ extsys->reset_reg = reset_reg; ++ extsys->set_reg = set_reg; ++ ++ extsys->miscdev.minor = MISC_DYNAMIC_MINOR; ++ extsys->miscdev.name = EXTSYS_DRV_NAME; ++ extsys->miscdev.fops = &extsys_ctrl_fops; ++ extsys->miscdev.parent = dev; ++ ++ ret = misc_register(&extsys->miscdev); ++ if (ret) ++ return ret; ++ ++ dev_info(dev, "external system controller ready\n"); ++ ++ return 0; ++} ++ ++static int extsys_ctrl_remove(struct platform_device *pdev) ++{ ++ struct extsys_ctrl *extsys = dev_get_drvdata(&pdev->dev); ++ ++ misc_deregister(&extsys->miscdev); ++ ++ return 0; ++} ++ ++static const struct of_device_id extsys_ctrl_match[] = { ++ { .compatible = "arm,extsys_ctrl" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, extsys_ctrl_match); ++ ++static struct platform_driver extsys_ctrl_driver = { ++ .driver = { ++ .name = EXTSYS_DRV_NAME, ++ .of_match_table = extsys_ctrl_match, ++ }, ++ .probe = extsys_ctrl_probe, ++ .remove = extsys_ctrl_remove, ++}; ++module_platform_driver(extsys_ctrl_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Arm External System Control Driver"); ++MODULE_AUTHOR("Morten Borup Petersen"); ++MODULE_AUTHOR("Rui Miguel Silva "); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0003-Add-rpmsg-driver-for-corstone1000.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0003-Add-rpmsg-driver-for-corstone1000.patch new file mode 100644 index 000000000000..809661487d81 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0003-Add-rpmsg-driver-for-corstone1000.patch @@ -0,0 +1,222 @@ +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Emekcan Aras + +From e683c37ee51717e625c8a598056cf4bb1bdadcbc Mon Sep 17 00:00:00 2001 +From: Emekcan +Date: Wed, 17 Aug 2022 14:21:42 +0100 +Subject: [PATCH] Add rpmsg driver for corstone1000 + +Adds rpmsg driver to communicate with external +system in corstone1000 platform. + +Signed-off-by: Emekcan Aras +--- + drivers/rpmsg/Kconfig | 10 ++ + drivers/rpmsg/Makefile | 1 + + drivers/rpmsg/rpmsg_arm_mailbox.c | 164 ++++++++++++++++++++++ + 3 files changed, 175 insertions(+) + create mode 100644 drivers/rpmsg/rpmsg_arm_mailbox.c + +diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig +index 0b4407abdf13..c276bd17bffe 100644 +--- a/drivers/rpmsg/Kconfig ++++ b/drivers/rpmsg/Kconfig +@@ -73,4 +73,14 @@ config RPMSG_VIRTIO + select RPMSG_NS + select VIRTIO + ++config RPMSG_ARM ++ tristate "ARM RPMSG driver" ++ select RPMSG ++ depends on HAS_IOMEM ++ depends on MAILBOX ++ help ++ Say y here to enable support for rpmsg lient driver which is built ++ around mailbox client using Arm MHUv2.1 as physical medium.This ++ driver enables communication which remote processor using MHU. ++ + endmenu +diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile +index 8d452656f0ee..34e9c146cd64 100644 +--- a/drivers/rpmsg/Makefile ++++ b/drivers/rpmsg/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_RPMSG) += rpmsg_core.o ++obj-$(CONFIG_RPMSG_ARM) += rpmsg_arm_mailbox.o + obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o + obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o + obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o +diff --git a/drivers/rpmsg/rpmsg_arm_mailbox.c b/drivers/rpmsg/rpmsg_arm_mailbox.c +new file mode 100644 +index 000000000000..4a80102669f6 +--- /dev/null ++++ b/drivers/rpmsg/rpmsg_arm_mailbox.c +@@ -0,0 +1,164 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * rpmsg client driver using mailbox client interface ++ * ++ * Copyright (C) 2019 ARM Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rpmsg_internal.h" ++#include ++ ++#define RPMSG_NAME "arm_rpmsg" ++#define RPMSG_ADDR_ANY 0xFFFFFFFF ++ ++struct arm_channel { ++ struct rpmsg_endpoint ept; ++ struct mbox_client cl; ++ struct mbox_chan *mbox; ++}; ++ ++#define arm_channel_from_rpmsg(_ept) container_of(_ept, struct arm_channel, ept) ++#define arm_channel_from_mbox(_ept) container_of(_ept, struct arm_channel, cl) ++ ++ ++static void arm_msg_rx_handler(struct mbox_client *cl, void *mssg) ++{ ++ struct arm_mhuv2_mbox_msg *msg = mssg; ++ struct arm_channel* channel = arm_channel_from_mbox(cl); ++ int err = channel->ept.cb(channel->ept.rpdev, msg->data, 4, channel->ept.priv, RPMSG_ADDR_ANY); ++ if(err) { ++ printk("ARM Mailbox: Endpoint callback failed with error: %d", err); ++ } ++} ++ ++ ++static void arm_destroy_ept(struct rpmsg_endpoint *ept) ++{ ++ struct arm_channel *channel = arm_channel_from_rpmsg(ept); ++ mbox_free_channel(channel->mbox); ++ kfree(channel); ++} ++ ++static int arm_send(struct rpmsg_endpoint *ept, void *data, int len) ++{ ++ struct arm_channel *channel = arm_channel_from_rpmsg(ept); ++ ++ mbox_send_message(channel->mbox, data); ++ return 0; ++} ++ ++static int arm_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dest) ++{ ++ struct arm_mhuv2_mbox_msg msg; ++ struct arm_channel *channel = arm_channel_from_rpmsg(ept); ++ msg.data = data; ++ msg.len = len; ++ mbox_send_message(channel->mbox, &msg); ++ return 0; ++} ++ ++ ++static const struct rpmsg_endpoint_ops arm_endpoint_ops = { ++ .destroy_ept = arm_destroy_ept, ++ .send = arm_send, ++ .sendto = arm_sendto, ++}; ++ ++ ++static struct rpmsg_endpoint *arm_create_ept(struct rpmsg_device *rpdev, ++ rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo) ++{ ++ struct arm_channel *channel; ++ ++ channel = kzalloc(sizeof(*channel), GFP_KERNEL); ++ ++ // Initialize rpmsg endpoint ++ kref_init(&channel->ept.refcount); ++ channel->ept.rpdev = rpdev; ++ channel->ept.cb = cb; ++ channel->ept.priv = priv; ++ channel->ept.ops = &arm_endpoint_ops; ++ ++ // Initialize mailbox client ++ channel->cl.dev = rpdev->dev.parent; ++ channel->cl.rx_callback = arm_msg_rx_handler; ++ channel->cl.tx_done = NULL; /* operate in blocking mode */ ++ channel->cl.tx_block = true; ++ channel->cl.tx_tout = 500; /* by half a second */ ++ channel->cl.knows_txdone = false; /* depending upon protocol */ ++ ++ channel->mbox = mbox_request_channel_byname(&channel->cl, chinfo.name); ++ if (IS_ERR_OR_NULL(channel->mbox)) { ++ printk("RPMsg ARM: Cannot get channel by name: '%s'\n", chinfo.name); ++ return -1; ++ } ++ ++ return &channel->ept; ++} ++ ++static const struct rpmsg_device_ops arm_device_ops = { ++ .create_ept = arm_create_ept, ++}; ++ ++ ++static void arm_release_device(struct device *dev) ++{ ++ struct rpmsg_device *rpdev = to_rpmsg_device(dev); ++ ++ kfree(rpdev); ++} ++ ++ ++static int client_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpmsg_device *rpdev; ++ ++ rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL); ++ if (!rpdev) ++ return -ENOMEM; ++ ++ /* Assign callbacks for rpmsg_device */ ++ rpdev->ops = &arm_device_ops; ++ ++ /* Assign public information to the rpmsg_device */ ++ memcpy(rpdev->id.name, RPMSG_NAME, strlen(RPMSG_NAME)); ++ ++ rpdev->dev.parent = dev; ++ rpdev->dev.release = arm_release_device; ++ ++ return rpmsg_chrdev_register_device(rpdev); ++} ++ ++static const struct of_device_id client_of_match[] = { ++ { .compatible = "arm,client", .data = NULL }, ++ { /* Sentinel */ }, ++}; ++ ++static struct platform_driver client_driver = { ++ .driver = { ++ .name = "arm-mhu-client", ++ .of_match_table = client_of_match, ++ }, ++ .probe = client_probe, ++}; ++ ++module_platform_driver(client_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("ARM RPMSG Driver"); ++MODULE_AUTHOR("Tushar Khandelwal "); +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0004-rpmsg-arm-fix-return-value.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0004-rpmsg-arm-fix-return-value.patch new file mode 100644 index 000000000000..207476886941 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0004-rpmsg-arm-fix-return-value.patch @@ -0,0 +1,35 @@ +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Rui Miguel Silva + +From 1426dd2b541cb51741bffbd95191ae5593e1749d Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Tue, 27 Sep 2022 10:05:27 +0100 +Subject: [PATCH 1/2] rpmsg: arm: fix return value + +The creation of and endpoint returns a pointer, fix the return +value to the right type. + +Signed-off-by: Rui Miguel Silva +--- + drivers/rpmsg/rpmsg_arm_mailbox.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/rpmsg/rpmsg_arm_mailbox.c b/drivers/rpmsg/rpmsg_arm_mailbox.c +index 4a80102669f6..5c0dcc8e353d 100644 +--- a/drivers/rpmsg/rpmsg_arm_mailbox.c ++++ b/drivers/rpmsg/rpmsg_arm_mailbox.c +@@ -103,8 +103,9 @@ static struct rpmsg_endpoint *arm_create_ept(struct rpmsg_device *rpdev, + + channel->mbox = mbox_request_channel_byname(&channel->cl, chinfo.name); + if (IS_ERR_OR_NULL(channel->mbox)) { +- printk("RPMsg ARM: Cannot get channel by name: '%s'\n", chinfo.name); +- return -1; ++ printk("RPMsg ARM: Cannot get channel by name: %s\n", ++ chinfo.name); ++ return ERR_PTR(-ENOENT); + } + + return &channel->ept; +-- +2.37.3 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0005-rpmsg-arm-update-chrdev-to-ctrldev-registration.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0005-rpmsg-arm-update-chrdev-to-ctrldev-registration.patch new file mode 100644 index 000000000000..504fa676c5df --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0005-rpmsg-arm-update-chrdev-to-ctrldev-registration.patch @@ -0,0 +1,33 @@ +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Rui Miguel Silva + +From 20cd41fee8e4638eb47072b91d9a9f985730583b Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Tue, 27 Sep 2022 10:07:21 +0100 +Subject: [PATCH 2/2] rpmsg: arm: update chrdev to ctrldev registration + +Since "rpmsg: Update rpmsg_chrdev_register_device function", +there was a replacement of the chrdev driver to ctrldev +driver. Fix the registration. + +Signed-off-by: Rui Miguel Silva +--- + drivers/rpmsg/rpmsg_arm_mailbox.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/rpmsg/rpmsg_arm_mailbox.c b/drivers/rpmsg/rpmsg_arm_mailbox.c +index 5c0dcc8e353d..90bc8df90885 100644 +--- a/drivers/rpmsg/rpmsg_arm_mailbox.c ++++ b/drivers/rpmsg/rpmsg_arm_mailbox.c +@@ -142,7 +142,7 @@ static int client_probe(struct platform_device *pdev) + rpdev->dev.parent = dev; + rpdev->dev.release = arm_release_device; + +- return rpmsg_chrdev_register_device(rpdev); ++ return rpmsg_ctrldev_register_device(rpdev); + } + + static const struct of_device_id client_of_match[] = { +-- +2.37.3 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0006-Adds-workaround-for-cs1k-specific-bug.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0006-Adds-workaround-for-cs1k-specific-bug.patch new file mode 100644 index 000000000000..5cd8e4b0d142 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/0006-Adds-workaround-for-cs1k-specific-bug.patch @@ -0,0 +1,41 @@ +Upstream-Status: Inappropriate[Temporary bugfix] +Signed-off-by: Emekcan Aras + +From f1a869ea986305a6fb20f3c770c11778a898b86d Mon Sep 17 00:00:00 2001 +From: Emekcan +Date: Thu, 13 Oct 2022 20:53:42 +0100 +Subject: [PATCH] Adds workaround for cs1k specific bug + +Adds a temporary workaround to solve a possible +race-conditioning issue in the tee driver +for corstone1000. + +Signed-off-by: Emekcan Aras +--- + drivers/firmware/arm_ffa/driver.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index ec731e9e942b..2a3ef649935e 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #include "common.h" + +@@ -344,7 +345,7 @@ static int ffa_msg_send_direct_req(u16 src_id, u16 dst_id, bool mode_32bit, + { + u32 req_id, resp_id, src_dst_ids = PACK_TARGET_INFO(src_id, dst_id); + ffa_value_t ret; +- ++ msleep(1); + if (mode_32bit) { + req_id = FFA_MSG_SEND_DIRECT_REQ; + resp_id = FFA_MSG_SEND_DIRECT_RESP; +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/corstone1000_kernel_debug.cfg b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/corstone1000_kernel_debug.cfg new file mode 100644 index 000000000000..aad9e93a64c1 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/corstone1000_kernel_debug.cfg @@ -0,0 +1,3 @@ +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO_DWARF4=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig new file mode 100644 index 000000000000..f6e6409cea4d --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig @@ -0,0 +1,100 @@ +CONFIG_LOCALVERSION="-yocto-standard" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_LOG_BUF_SHIFT=13 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=13 +CONFIG_RELAY=y +CONFIG_BOOT_CONFIG=y +CONFIG_ARCH_VEXPRESS=y +CONFIG_CMDLINE="console=ttyAMA0 loglevel=9" +CONFIG_EFI=y +# CONFIG_SUSPEND is not set +CONFIG_EFI_BOOTLOADER_CONTROL=y +CONFIG_EFI_CAPSULE_LOADER=y +CONFIG_EFI_TEST=y +CONFIG_RESET_ATTACK_MITIGATION=y +# CONFIG_STACKPROTECTOR is not set +CONFIG_MODULES=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_SCHED=y +CONFIG_DEVTMPFS=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +CONFIG_SMC91X=y +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_USB=y +CONFIG_USB_STORAGE=y +CONFIG_USB_UAS=y +CONFIG_USB_ISP1760=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_CONFIGFS_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y +CONFIG_LIBCRC32C=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_DEBUG_FS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_STACKTRACE=y +CONFIG_EXTSYS_CTRL=y +CONFIG_MAILBOX=y +CONFIG_ARM_MHU_V2=y +CONFIG_RPMSG=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_ARM=y +CONFIG_RPMSG_CTRL=y diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone500/0001-arm-defconfig-drop-CONFIG_SND_SOC_AC97-from-multi_v7.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone500/0001-arm-defconfig-drop-CONFIG_SND_SOC_AC97-from-multi_v7.patch new file mode 100644 index 000000000000..68c9ca00f662 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/corstone500/0001-arm-defconfig-drop-CONFIG_SND_SOC_AC97-from-multi_v7.patch @@ -0,0 +1,30 @@ +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Vishnu Banavath + +From 7ee0e1c0a6498d376b38679c908f01a1528a1450 Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Thu, 29 Sep 2022 17:16:45 +0100 +Subject: [PATCH] arm: defconfig: drop CONFIG_SND_SOC_AC97 from + multi_v7_defconfig + +The CONFIG_SND_SOC_AC97 symbol was recently enabled but does not +actually exist. This change is to remove it to fix warnings when +used some of the build tools like yocto. + +Signed-off-by: Vishnu Banavath + +diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig +index ce9826bce29b..b3662f126efa 100644 +--- a/arch/arm/configs/multi_v7_defconfig ++++ b/arch/arm/configs/multi_v7_defconfig +@@ -817,7 +817,6 @@ CONFIG_SND_SOC_TEGRA_TRIMSLICE=m + CONFIG_SND_SOC_TEGRA_ALC5632=m + CONFIG_SND_SOC_TEGRA_MAX98090=m + CONFIG_SND_SOC_DAVINCI_MCASP=m +-CONFIG_SND_SOC_AC97=m + CONFIG_SND_SOC_AK4642=m + CONFIG_SND_SOC_CPCAP=m + CONFIG_SND_SOC_CS42L51_I2C=m +-- +2.17.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base-arm32/0001-ARM-vexpress-enable-GICv3.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base-arm32/0001-ARM-vexpress-enable-GICv3.patch new file mode 100644 index 000000000000..184a763176b6 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base-arm32/0001-ARM-vexpress-enable-GICv3.patch @@ -0,0 +1,31 @@ +From 9fe529a146f4528ec80a3d04588e387f3651dc22 Mon Sep 17 00:00:00 2001 +From: Ryan Harkin +Date: Wed, 16 Nov 2016 14:43:02 +0000 +Subject: [PATCH] ARM: vexpress: enable GICv3 + +Upstream-Status: Pending + +ARMv8 targets such as ARM's FVP Cortex-A32 model can run the 32-bit +ARMv7 kernel. And these targets often contain GICv3. + +Signed-off-by: Ryan Harkin +Signed-off-by: Jon Medhurst +--- + arch/arm/mach-versatile/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig +index 2ef226194c3a..3d54877fe339 100644 +--- a/arch/arm/mach-versatile/Kconfig ++++ b/arch/arm/mach-versatile/Kconfig +@@ -251,6 +251,7 @@ menuconfig ARCH_VEXPRESS + depends on ARCH_MULTI_V7 + select ARM_AMBA + select ARM_GIC ++ select ARM_GIC_V3 + select ARM_GLOBAL_TIMER + select ARM_TIMER_SP804 + select GPIOLIB +-- +2.30.2 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base/0001-arm64-dts-fvp-Enable-virtio-rng-support.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base/0001-arm64-dts-fvp-Enable-virtio-rng-support.patch new file mode 100644 index 000000000000..1cbdc9afe1bf --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-base/0001-arm64-dts-fvp-Enable-virtio-rng-support.patch @@ -0,0 +1,29 @@ +From b443c8efd563dc372c60e7ad9f52aeddf7c13706 Mon Sep 17 00:00:00 2001 +From: Anton Antonov +Date: Mon, 7 Nov 2022 11:37:51 +0000 +Subject: [PATCH] arm64: dts: fvp: Enable virtio-rng support + +The virtio-rng is available from FVP_Base_RevC-2xAEMvA version 11.17. +Enable it since Yocto includes a recipe for a newer FVP version. + +Upstream-Status: Inappropriate [Yocto specific] +Signed-off-by: Anton Antonov +--- + arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi +index ec2d5280a30b..acafdcbf1063 100644 +--- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi ++++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi +@@ -26,7 +26,6 @@ virtio@200000 { + compatible = "virtio,mmio"; + reg = <0x200000 0x200>; + interrupts = <46>; +- status = "disabled"; + }; + }; + }; +-- +2.25.1 + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts new file mode 100644 index 000000000000..6911a598f7ce --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts @@ -0,0 +1,212 @@ +/dts-v1/; + +/ { + + #address-cells = <0x2>; + #size-cells = <0x2>; + interrupt-parent = <0x1>; + model = "Generated"; + compatible = "arm,base"; + + memory@0 { + #address-cells = <0x2>; + #size-cells = <0x2>; + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>, + <0x00000008 0x80000000 0x0 0x80000000>; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + cpu-map { + cluster0 { + core0 { thread0 { cpu = <&CPU_0>; }; }; + core1 { thread0 { cpu = <&CPU_1>; }; }; + core2 { thread0 { cpu = <&CPU_2>; }; }; + core3 { thread0 { cpu = <&CPU_3>; }; }; + }; + }; + + CPU_0: cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x7f800>; + }; + + CPU_1: cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x7f808>; + }; + + CPU_2: cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x7f810>; + }; + + CPU_3: cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x7f818>; + }; + }; + + interrupt-controller@af000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <0x3>; + #address-cells = <0x2>; + #size-cells = <0x2>; + ranges; + interrupt-controller; + #redistributor-regions = <0x1>; + reg = <0x0 0xaf000000 0x0 0x10000>, // GICD + <0x0 0xaf100000 0x0 0x100000>, // GICR + <0x0 0xac000000 0x0 0x2000>, // GICC + <0x0 0xac010000 0x0 0x2000>, // GICH + <0x0 0xac02f000 0x0 0x2000>; // GICV + interrupts = <0x1 9 0x4>; + linux,phandle = <0x1>; + phandle = <0x1>; + + its: msi-controller@2f020000 { + #msi-cells = <1>; + compatible = "arm,gic-v3-its"; + reg = <0x0 0xaf020000 0x0 0x20000>; // GITS + msi-controller; + }; + + }; + + refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + refclk24mhz: refclk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "refclk24mhz"; + }; + + refclk1hz: refclk1hz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1>; + clock-output-names = "refclk1hz"; + }; + + uart@9c090000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x9c090000 0x0 0x1000>; + interrupts = <0x0 5 0x4>; + clocks = <&refclk24mhz>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + uart@9c0a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x9c0a0000 0x0 0x1000>; + interrupts = <0x0 6 0x4>; + clocks = <&refclk24mhz>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + uart@9c0b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x9c0b0000 0x0 0x1000>; + interrupts = <0x0 7 0x4>; + clocks = <&refclk24mhz>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + uart@9c0c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x9c0c0000 0x0 0x1000>; + interrupts = <0x0 8 0x4>; + clocks = <&refclk24mhz>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@9c0f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0x9c0f0000 0x0 0x1000>; + interrupts = <0x0 0 0x4>; + clocks = <&refclk24mhz>, <&refclk100mhz>; + clock-names = "wdog_clk", "apb_pclk"; + }; + + rtc@9c170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x0 0x9c170000 0x0 0x1000>; + interrupts = <0x0 4 0x4>; + clocks = <&refclk1hz>; + clock-names = "apb_pclk"; + }; + + virtio-block@9c130000 { + compatible = "virtio,mmio"; + reg = <0 0x9c130000 0 0x200>; + interrupts = <0x0 42 0x4>; + }; + + virtio-p9@9c140000{ + compatible = "virtio,mmio"; + reg = <0x0 0x9c140000 0x0 0x1000>; + interrupts = <0x0 43 0x4>; + }; + + virtio-net@9c150000 { + compatible = "virtio,mmio"; + reg = <0 0x9c150000 0 0x200>; + interrupts = <0x0 44 0x4>; + }; + + virtio-rng@9c200000 { + compatible = "virtio,mmio"; + reg = <0 0x9c200000 0 0x200>; + interrupts = <0x0 46 0x4>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x1 13 0xff08>, + <0x1 14 0xff08>, + <0x1 11 0xff08>, + <0x1 4 0xff08>; + clock-frequency = <100000000>; + }; + + aliases { + serial0 = "/uart@9c090000"; + serial1 = "/uart@9c0a0000"; + serial2 = "/uart@9c0b0000"; + serial3 = "/uart@9c0c0000"; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + chosen { + bootargs = "earlycon console=ttyAMA0 loglevel=8 rootfstype=ext4 root=/dev/vda1 rw"; + stdout-path = "serial0"; + }; +}; diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0001-arm64-dts-Update-cache-properties-for-Arm-Ltd-platfo.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0001-arm64-dts-Update-cache-properties-for-Arm-Ltd-platfo.patch new file mode 100644 index 000000000000..329c939fb6a2 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0001-arm64-dts-Update-cache-properties-for-Arm-Ltd-platfo.patch @@ -0,0 +1,138 @@ +From dc250cab31c6611cc7fa76bc8b2027dbd56dd65d Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Mon, 7 Nov 2022 16:56:58 +0100 +Subject: [PATCH] arm64: dts: Update cache properties for Arm Ltd platforms + +The DeviceTree Specification v0.3 specifies that the cache node +"compatible" and "cache-level" properties are required. + +Cf. s3.8 Multi-level and Shared Cache Nodes +The 'cache-unified' property should be present if one of the properties +for unified cache is present ('cache-size', ...). + +Update the relevant device trees nodes accordingly. + +Signed-off-by: Pierre Gondois +Link: https://lore.kernel.org/r/20221107155825.1644604-6-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla + +Signed-off-by: Jon Mason +Upstream-Status: Backport +--- + arch/arm64/boot/dts/arm/corstone1000.dtsi | 1 + + arch/arm64/boot/dts/arm/foundation-v8.dtsi | 1 + + arch/arm64/boot/dts/arm/juno-r1.dts | 2 ++ + arch/arm64/boot/dts/arm/juno-r2.dts | 2 ++ + arch/arm64/boot/dts/arm/juno.dts | 2 ++ + arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts | 1 + + arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts | 1 + + 7 files changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/arm/corstone1000.dtsi b/arch/arm64/boot/dts/arm/corstone1000.dtsi +index 4e46826f883a..21f1f952e985 100644 +--- a/arch/arm64/boot/dts/arm/corstone1000.dtsi ++++ b/arch/arm64/boot/dts/arm/corstone1000.dtsi +@@ -53,6 +53,7 @@ gic: interrupt-controller@1c000000 { + + L2_0: l2-cache0 { + compatible = "cache"; ++ cache-unified; + cache-level = <2>; + cache-size = <0x80000>; + cache-line-size = <64>; +diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi +index 83e3e7e3984f..c8bd23b1a7ba 100644 +--- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi ++++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi +@@ -58,6 +58,7 @@ cpu3: cpu@3 { + + L2_0: l2-cache0 { + compatible = "cache"; ++ cache-level = <2>; + }; + }; + +diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts +index 6451c62146fd..1d90eeebb37d 100644 +--- a/arch/arm64/boot/dts/arm/juno-r1.dts ++++ b/arch/arm64/boot/dts/arm/juno-r1.dts +@@ -189,6 +189,7 @@ A53_3: cpu@103 { + + A57_L2: l2-cache0 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x200000>; + cache-line-size = <64>; + cache-sets = <2048>; +@@ -197,6 +198,7 @@ A57_L2: l2-cache0 { + + A53_L2: l2-cache1 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; +diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts +index 438cd1ff4bd0..d2ada69b0a43 100644 +--- a/arch/arm64/boot/dts/arm/juno-r2.dts ++++ b/arch/arm64/boot/dts/arm/juno-r2.dts +@@ -195,6 +195,7 @@ A53_3: cpu@103 { + + A72_L2: l2-cache0 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x200000>; + cache-line-size = <64>; + cache-sets = <2048>; +@@ -203,6 +204,7 @@ A72_L2: l2-cache0 { + + A53_L2: l2-cache1 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; +diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts +index cf4a58211399..5e48a01a5b9f 100644 +--- a/arch/arm64/boot/dts/arm/juno.dts ++++ b/arch/arm64/boot/dts/arm/juno.dts +@@ -194,6 +194,7 @@ A53_3: cpu@103 { + + A57_L2: l2-cache0 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x200000>; + cache-line-size = <64>; + cache-sets = <2048>; +@@ -202,6 +203,7 @@ A57_L2: l2-cache0 { + + A53_L2: l2-cache1 { + compatible = "cache"; ++ cache-unified; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; +diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +index 258991ad7cc0..ef68f5aae7dd 100644 +--- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts ++++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +@@ -71,6 +71,7 @@ cpu@3 { + + L2_0: l2-cache0 { + compatible = "cache"; ++ cache-level = <2>; + }; + }; + +diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts +index 5b6d9d8e934d..796cd7d02eb5 100644 +--- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts ++++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts +@@ -57,6 +57,7 @@ cpu@1 { + + L2_0: l2-cache0 { + compatible = "cache"; ++ cache-level = <2>; + }; + }; + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0002-arm64-dts-fvp-Add-SPE-to-Foundation-FVP.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0002-arm64-dts-fvp-Add-SPE-to-Foundation-FVP.patch new file mode 100644 index 000000000000..4495f397bd3e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0002-arm64-dts-fvp-Add-SPE-to-Foundation-FVP.patch @@ -0,0 +1,35 @@ +From bd354219987dddbf8ab6fd11450b4046547aca1b Mon Sep 17 00:00:00 2001 +From: James Clark +Date: Thu, 17 Nov 2022 10:25:36 +0000 +Subject: [PATCH] arm64: dts: fvp: Add SPE to Foundation FVP + +Add SPE DT node to FVP model. If the model doesn't support SPE (e.g., +turned off via parameter), the driver will skip the initialisation +accordingly and thus is safe. + +Signed-off-by: James Clark +Link: https://lore.kernel.org/r/20221117102536.237515-1-james.clark@arm.com +Signed-off-by: Sudeep Holla + +Signed-off-by: Jon Mason +Upstream-Status: Backport +--- + arch/arm64/boot/dts/arm/foundation-v8.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi +index c8bd23b1a7ba..029578072d8f 100644 +--- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi ++++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi +@@ -85,6 +85,11 @@ pmu { + ; + }; + ++ spe-pmu { ++ compatible = "arm,statistical-profiling-extension-v1"; ++ interrupts = ; ++ }; ++ + watchdog@2a440000 { + compatible = "arm,sbsa-gwdt"; + reg = <0x0 0x2a440000 0 0x1000>, diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0003-arm64-dts-fvp-Add-information-about-L1-and-L2-caches.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0003-arm64-dts-fvp-Add-information-about-L1-and-L2-caches.patch new file mode 100644 index 000000000000..fc02751004e6 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0003-arm64-dts-fvp-Add-information-about-L1-and-L2-caches.patch @@ -0,0 +1,146 @@ +From 22e740d069e14875a64864bf86e0826a96560b44 Mon Sep 17 00:00:00 2001 +From: Sudeep Holla +Date: Fri, 18 Nov 2022 15:10:17 +0000 +Subject: [PATCH] arm64: dts: fvp: Add information about L1 and L2 caches + +Add the information about L1 and L2 caches on FVP RevC platform. +Though the cache size is configurable through the model parameters, +having default values in the device tree helps to exercise and debug +any code utilising the cache information without the need of real +hardware. + +Link: https://lore.kernel.org/r/20221118151017.704716-1-sudeep.holla@arm.com +Signed-off-by: Sudeep Holla + +Signed-off-by: Jon Mason +Upstream-Status: Backport +--- + arch/arm64/boot/dts/arm/fvp-base-revc.dts | 73 +++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts +index 5f6f30c801a7..60472d65a355 100644 +--- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts ++++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts +@@ -47,48 +47,121 @@ cpu0: cpu@0 { + compatible = "arm,armv8"; + reg = <0x0 0x000>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C0_L2>; + }; + cpu1: cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C0_L2>; + }; + cpu2: cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C0_L2>; + }; + cpu3: cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C0_L2>; + }; + cpu4: cpu@10000 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x10000>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C1_L2>; + }; + cpu5: cpu@10100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x10100>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C1_L2>; + }; + cpu6: cpu@10200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x10200>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C1_L2>; + }; + cpu7: cpu@10300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x10300>; + enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; ++ next-level-cache = <&C1_L2>; ++ }; ++ C0_L2: l2-cache0 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <64>; ++ cache-sets = <512>; ++ cache-level = <2>; ++ cache-unified; ++ }; ++ ++ C1_L2: l2-cache1 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <64>; ++ cache-sets = <512>; ++ cache-level = <2>; ++ cache-unified; + }; + }; + diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0004-ARM-dts-vexpress-align-LED-node-names-with-dtschema.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0004-ARM-dts-vexpress-align-LED-node-names-with-dtschema.patch new file mode 100644 index 000000000000..e3828ec96a5e --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/juno/0004-ARM-dts-vexpress-align-LED-node-names-with-dtschema.patch @@ -0,0 +1,81 @@ +From 4edb625e2256d5761312110e34cbc0164915d772 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Fri, 25 Nov 2022 15:41:12 +0100 +Subject: [PATCH] ARM: dts: vexpress: align LED node names with dtschema + +The node names should be generic and DT schema expects certain pattern. + + vexpress-v2p-ca9.dtb: leds: 'user1', 'user2', 'user3', 'user4', 'user5', 'user6', 'user7', 'user8' do not match any of the regexes: '(^led-[0-9a-f]$|led)', 'pinctrl-[0-9]+' + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20221125144112.476817-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Sudeep Holla + +Signed-off-by: Jon Mason +Upstream-Status: Backport +--- + arch/arm/boot/dts/vexpress-v2m.dtsi | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi +index f434fe5cf4a1..def538ce8769 100644 +--- a/arch/arm/boot/dts/vexpress-v2m.dtsi ++++ b/arch/arm/boot/dts/vexpress-v2m.dtsi +@@ -383,49 +383,49 @@ v2m_refclk32khz: refclk32khz { + leds { + compatible = "gpio-leds"; + +- user1 { ++ led-user1 { + label = "v2m:green:user1"; + gpios = <&v2m_led_gpios 0 0>; + linux,default-trigger = "heartbeat"; + }; + +- user2 { ++ led-user2 { + label = "v2m:green:user2"; + gpios = <&v2m_led_gpios 1 0>; + linux,default-trigger = "mmc0"; + }; + +- user3 { ++ led-user3 { + label = "v2m:green:user3"; + gpios = <&v2m_led_gpios 2 0>; + linux,default-trigger = "cpu0"; + }; + +- user4 { ++ led-user4 { + label = "v2m:green:user4"; + gpios = <&v2m_led_gpios 3 0>; + linux,default-trigger = "cpu1"; + }; + +- user5 { ++ led-user5 { + label = "v2m:green:user5"; + gpios = <&v2m_led_gpios 4 0>; + linux,default-trigger = "cpu2"; + }; + +- user6 { ++ led-user6 { + label = "v2m:green:user6"; + gpios = <&v2m_led_gpios 5 0>; + linux,default-trigger = "cpu3"; + }; + +- user7 { ++ led-user7 { + label = "v2m:green:user7"; + gpios = <&v2m_led_gpios 6 0>; + linux,default-trigger = "cpu4"; + }; + +- user8 { ++ led-user8 { + label = "v2m:green:user8"; + gpios = <&v2m_led_gpios 7 0>; + linux,default-trigger = "cpu5"; diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc new file mode 100644 index 000000000000..e2a36c9b6078 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc @@ -0,0 +1,200 @@ +# Kernel configuration and dts specific information + +# +# Kernel configurations and dts (If not using Linux provided ones) are captured +# in this file. Update SRC_URI and do_patch for building images with custom dts +# + +# We can't set FILESEXTRAPATHS once because of how the kernel classes search for +# config fragments. Discussion is ongoing as to whether this is the correct +# solution, or a workaround. +# https://bugzilla.yoctoproject.org/show_bug.cgi?id=14154 +ARMBSPFILESPATHS := "${THISDIR}:${THISDIR}/files:" + +# Arm platforms kmeta +SRC_URI_KMETA = "file://arm-platforms-kmeta;type=kmeta;name=arm-platforms-kmeta;destsuffix=arm-platforms-kmeta" +SRC_URI:append:fvp-base = " ${SRC_URI_KMETA}" +SRC_URI:append:fvp-base-arm32 = " ${SRC_URI_KMETA}" +SRC_URI:append:fvp-baser-aemv8r64 = " ${SRC_URI_KMETA}" +SRC_URI:append:juno = " ${SRC_URI_KMETA}" +SRC_URI:append:n1sdp = " ${SRC_URI_KMETA}" +SRC_URI:append:tc = " ${SRC_URI_KMETA}" +SRCREV:arm-platforms-kmeta = "6147e82375aa9df8f2a162d42ea6406c79c854c5" + +# +# Corstone-500 KMACHINE +# +COMPATIBLE_MACHINE:corstone500 = "corstone500" +KBUILD_DEFCONFIG:corstone500 = "multi_v7_defconfig" +KCONFIG_MODE:corstone500 = "--alldefconfig" +FILESEXTRAPATHS:prepend:corstone500 := "${ARMBSPFILESPATHS}" +SRC_URI:append:corstone500 = " \ + file://0001-arm-defconfig-drop-CONFIG_SND_SOC_AC97-from-multi_v7.patch \ + " + +# +# Corstone1000 KMACHINE +# +FILESEXTRAPATHS:prepend:corstone1000 := "${ARMBSPFILESPATHS}" +COMPATIBLE_MACHINE:corstone1000 = "${MACHINE}" +KCONFIG_MODE:corstone1000 = "--alldefconfig" +KMACHINE:corstone1000 = "corstone1000" +LINUX_KERNEL_TYPE:corstone1000 = "standard" +#disabling the rootfs cpio file compression so it is not compressed twice when bundled with the kernel +KERNEL_EXTRA_ARGS:corstone1000 += "CONFIG_INITRAMFS_COMPRESSION_NONE=y" +SRC_URI:append:corstone1000 = " \ + file://defconfig \ + file://0002-Add-external-system-driver.patch \ + file://0003-Add-rpmsg-driver-for-corstone1000.patch \ + file://0004-rpmsg-arm-fix-return-value.patch \ + file://0005-rpmsg-arm-update-chrdev-to-ctrldev-registration.patch \ + file://0006-Adds-workaround-for-cs1k-specific-bug.patch \ + " + +SRC_URI:append:corstone1000 = " ${@bb.utils.contains('MACHINE_FEATURES', \ + 'corstone1000_kernel_debug', \ + 'file://corstone1000_kernel_debug.cfg', \ + '', \ + d)}" + +# Default kernel features not needed for corstone1000 +# otherwise the extra kernel modules will increase the rootfs size +# corstone1000 has limited flash memory constraints +KERNEL_EXTRA_FEATURES:corstone1000 = "" +KERNEL_FEATURES:corstone1000 = "" + +# +# FVP BASE KMACHINE +# +COMPATIBLE_MACHINE:fvp-base = "fvp-base" +KMACHINE:fvp-base = "fvp" +FILESEXTRAPATHS:prepend:fvp-base := "${ARMBSPFILESPATHS}" +SRC_URI:append:fvp-base = " file://0001-arm64-dts-fvp-Enable-virtio-rng-support.patch" + +# +# FVP BASE ARM32 KMACHINE +# +COMPATIBLE_MACHINE:fvp-base-arm32 = "fvp-base-arm32" +KMACHINE:fvp-base-arm32 = "fvp-arm32" +FILESEXTRAPATHS:prepend:fvp-base-arm32 := "${ARMBSPFILESPATHS}" +SRC_URI:append:fvp-base-arm32 = " file://0001-ARM-vexpress-enable-GICv3.patch" +# We want to use the DT in the arm64 tree but the kernel build doesn't like that, so symlink it +do_compile:prepend:fvp-base-arm32() { + mkdir --parents ${S}/arch/arm/boot/dts/arm + for file in fvp-base-revc.dts rtsm_ve-motherboard.dtsi rtsm_ve-motherboard-rs2.dtsi; do + ln -fsr ${S}/arch/arm64/boot/dts/arm/$file ${S}/arch/arm/boot/dts/arm + done +} + +# +# FVP BaseR AEMv8r64 Machine +# +COMPATIBLE_MACHINE:fvp-baser-aemv8r64 = "fvp-baser-aemv8r64" +FILESEXTRAPATHS:prepend:fvp-baser-aemv8r64 := "${ARMBSPFILESPATHS}" +SRC_URI:append:fvp-baser-aemv8r64 = " file://fvp-baser-aemv8r64.dts;subdir=git/arch/arm64/boot/dts/arm" + +# +# Juno KMACHINE +# +COMPATIBLE_MACHINE:juno = "juno" +#KBUILD_DEFCONFIG:juno = "defconfig" +#KCONFIG_MODE:juno = "--alldefconfig" +FILESEXTRAPATHS:prepend:juno := "${ARMBSPFILESPATHS}" +SRC_URI:append:juno = " \ + file://0001-arm64-dts-Update-cache-properties-for-Arm-Ltd-platfo.patch \ + file://0002-arm64-dts-fvp-Add-SPE-to-Foundation-FVP.patch \ + file://0003-arm64-dts-fvp-Add-information-about-L1-and-L2-caches.patch \ + file://0004-ARM-dts-vexpress-align-LED-node-names-with-dtschema.patch \ + " + +# +# Musca B1/S2 can't run Linux +# +COMPATIBLE_MACHINE:musca-b1 = "(^$)" +COMPATIBLE_MACHINE:musca-s1 = "(^$)" + +# +# N1SDP KMACHINE +# +FILESEXTRAPATHS:prepend:n1sdp := "${THISDIR}/linux-yocto-5.19/n1sdp:" +COMPATIBLE_MACHINE:n1sdp = "n1sdp" +KBUILD_DEFCONFIG:n1sdp = "defconfig" +KCONFIG_MODE:n1sdp = "--alldefconfig" +FILESEXTRAPATHS:prepend:n1sdp := "${ARMBSPFILESPATHS}" +SRC_URI:append:n1sdp = " \ + file://0001-iommu-arm-smmu-v3-workaround-for-ATC_INV_SIZE_ALL-in.patch \ + file://0002-n1sdp-pci_quirk-add-acs-override-for-PCI-devices.patch \ + file://0003-pcie-Add-quirk-for-the-Arm-Neoverse-N1SDP-platform.patch \ + file://0004-n1sdp-pcie-add-quirk-support-enabling-remote-chip-PC.patch \ + file://0005-arm64-kpti-Whitelist-early-Arm-Neoverse-N1-revisions.patch \ + file://0006-arm64-defconfig-disable-config-options-that-does-not.patch \ + file://enable-realtek-R8169.cfg \ + file://enable-usb_conn_gpio.cfg \ + file://usb_xhci_pci_renesas.cfg \ + " +# Since we use the intree defconfig and the preempt-rt turns off some configs +# do_kernel_configcheck will display warnings. So, lets disable it. +KCONF_AUDIT_LEVEL:n1sdp:pn-linux-yocto-rt = "0" + +# +# SGI575 KMACHINE +# +COMPATIBLE_MACHINE:sgi575 = "sgi575" +KBUILD_DEFCONFIG:sgi575 = "defconfig" +KCONFIG_MODE:sgi575 = "--alldefconfig" + +# +# Total Compute (TC0/TC1) KMACHINE +# +COMPATIBLE_MACHINE:tc = "(tc0|tc1)" +KCONFIG_MODE:tc = "--alldefconfig" +FILESEXTRAPATHS:prepend:tc := "${ARMBSPFILESPATHS}:${THISDIR}/linux-arm64-ack-5.15/tc:" +SRC_URI:append:tc = " \ + file://gki_defconfig \ + file://0001-drm-Add-component-aware-simple-encoder.patch \ + file://0001-drm-komeda-Fix-handling-of-atomic-commits-in-the-ato.patch \ + file://0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch \ + file://0003-firmware-arm_ffa-Fix-uuid-argument-passed-to-ffa_par.patch \ + file://0004-firmware-arm_ffa-Add-ffa_dev_get_drvdata.patch \ + file://0005-firmware-arm_ffa-extern-ffa_bus_type.patch \ + file://0006-firmware-arm_ffa-Fix-FFA_MEM_SHARE-and-FFA_MEM_FRAG_.patch \ + file://0007-Revert-optee-use-driver-internal-tee_context-for-som.patch \ + file://0008-tee-add-sec_world_id-to-struct-tee_shm.patch \ + file://0009-optee-simplify-optee_release.patch \ + file://0010-optee-refactor-driver-with-internal-callbacks.patch \ + file://0011-optee-isolate-smc-abi.patch \ + file://0012-optee-add-FF-A-support.patch \ + file://0013-optee-smc_abi.c-add-missing-include-linux-mm.h.patch \ + file://0014-optee-Fix-spelling-mistake-reclain-reclaim.patch \ + file://0015-optee-fix-kfree-NULL-pointer.patch \ + file://0016-perf-arm-cmn-Account-for-NUMA-affinity.patch \ + file://0017-perf-arm-cmn-Drop-compile-test-restriction.patch \ + file://0018-perf-arm-cmn-Refactor-node-ID-handling.patch \ + file://0019-perf-arm-cmn-Streamline-node-iteration.patch \ + file://0020-perf-arm-cmn-Refactor-DTM-handling.patch \ + file://0021-perf-arm-cmn-Optimise-DTM-counter-reads.patch \ + file://0022-perf-arm-cmn-Optimise-DTC-counter-accesses.patch \ + file://0023-perf-arm-cmn-Move-group-validation-data-off-stack.patch \ + file://0024-perf-arm-cmn-Demarcate-CMN-600-specifics.patch \ + file://0025-perf-arm-cmn-Support-new-IP-features.patch \ + file://0026-perf-arm-cmn-Add-CI-700-Support.patch \ + file://0027-ANDROID-trusty-Backport-of-trusty-driver.patch \ + file://0028-ANDROID-trusty-Remove-FFA-specific-initilization.patch \ + file://0029-ANDROID-trusty-Rename-transfer-memory-function-to-le.patch \ + file://0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch \ + file://0031-ANDROID-trusty-Modify-device-compatible-string.patch \ + file://0032-ANDROID-trusty-Add-transport-descriptor.patch \ + file://0033-ANDROID-trusty-Add-trusty-ffa-driver.patch \ + file://0034-ANDROID-trusty-ffa-Add-support-for-FFA-memory-operat.patch \ + file://0035-ANDROID-trusty-ffa-Enable-FFA-transport-for-both-mem.patch \ + file://0036-ANDROID-trusty-Make-trusty-transports-configurable.patch \ + file://0037-ANDROID-trusty-log-include-panic_notifier.h.patch \ + file://0038-ANDROID-trusty-ipc-fix-VIRTIO_ID_TRUSTY_IPC-ID.patch \ + file://0039-gki_config-add-tc-disable_mpam.patch \ + file://0040-ANDROID-KVM-arm64-disable-FFA-driver-at-EL2.patch \ + file://init_disassemble_info-signature-changes-causes-compile-failures.patch \ + file://0041-etherdevice-Adjust-ether_addr-prototypes-to-silence-.patch \ + file://0042-mm-page_alloc-fix-building-error-on-Werror-array-com.patch \ + " +KERNEL_FEATURES:append:tc = " bsp/arm-platforms/tc.scc" +KERNEL_FEATURES:append:tc1 = " bsp/arm-platforms/tc-autofdo.scc" diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0001-drm-Add-component-aware-simple-encoder.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0001-drm-Add-component-aware-simple-encoder.patch new file mode 100644 index 000000000000..d361efd59a15 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0001-drm-Add-component-aware-simple-encoder.patch @@ -0,0 +1,367 @@ +From 5c07d2e7bf1634743249178bf2ca2a06779e6e7a Mon Sep 17 00:00:00 2001 +From: Tushar Khandelwal +Date: Tue, 16 Jun 2020 12:39:06 +0000 +Subject: [PATCH 01/40] drm: Add component-aware simple encoder + +This is a simple DRM encoder that gets its connector timings information +from a OF subnode in the device tree and exposes that as a "discovered" +panel. It can be used together with component-based DRM drivers in an +emulated environment where no real encoder or connector hardware exists +and the display output is configured outside the kernel. + +Signed-off-by: Tushar Khandelwal + +Upstream-Status: Backport [https://git.linaro.org/landing-teams/working/arm/kernel-release.git/commit/?h=latest-armlt&id=15283f7be4b1e586702551e85b4caf06531ac2fc] +Signed-off-by: Arunachalam Ganapathy +Change-Id: Ic68cbba7da7d36ee23359ff53bf30eb44cb78661 +Signed-off-by: Rupinderjit Singh +--- + drivers/gpu/drm/Kconfig | 11 + + drivers/gpu/drm/Makefile | 2 + + drivers/gpu/drm/drm_virtual_encoder.c | 299 ++++++++++++++++++++++++++ + 3 files changed, 312 insertions(+) + create mode 100644 drivers/gpu/drm/drm_virtual_encoder.c + +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index cea777ae7fb9..2468ec7155ef 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -291,6 +291,17 @@ config DRM_VKMS + + If M is selected the module will be called vkms. + ++config DRM_VIRT_ENCODER ++ tristate "Virtual OF-based encoder" ++ depends on DRM && OF ++ select VIDEOMODE_HELPERS ++ help ++ Choose this option to get a virtual encoder and its associated ++ connector that will use the device tree to read the display ++ timings information. If M is selected the module will be called ++ drm_vencoder. ++ ++ + source "drivers/gpu/drm/exynos/Kconfig" + + source "drivers/gpu/drm/rockchip/Kconfig" +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index ad1112154898..361999b7d063 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -59,6 +59,8 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o + + obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o + obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ ++drm_vencoder-y := drm_virtual_encoder.o ++obj-$(CONFIG_DRM_VIRT_ENCODER) += drm_vencoder.o + + obj-$(CONFIG_DRM) += drm.o + obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o +diff --git a/drivers/gpu/drm/drm_virtual_encoder.c b/drivers/gpu/drm/drm_virtual_encoder.c +new file mode 100644 +index 000000000000..39a902ecfe32 +--- /dev/null ++++ b/drivers/gpu/drm/drm_virtual_encoder.c +@@ -0,0 +1,299 @@ ++/* ++ * Copyright (C) 2016 ARM Limited ++ * Author: Liviu Dudau ++ * ++ * Dummy encoder and connector that use the OF to "discover" the attached ++ * display timings. Can be used in situations where the encoder and connector's ++ * functionality are emulated and no setup steps are needed, or to describe ++ * attached panels for which no driver exists but can be used without ++ * additional hardware setup. ++ * ++ * The encoder also uses the component framework so that it can be a quick ++ * replacement for existing drivers when testing in an emulated environment. ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive ++ * for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include