From patchwork Fri Sep 29 13:26:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Divin Raj X-Patchwork-Id: 31361 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0713E71D35 for ; Fri, 29 Sep 2023 13:27:38 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.17137.1695994052458879852 for ; Fri, 29 Sep 2023 06:27:32 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: divin.raj@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6C1021FB for ; Fri, 29 Sep 2023 06:28:10 -0700 (PDT) Received: from e127619.arm.com (unknown [10.57.69.83]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C08A53F5A1 for ; Fri, 29 Sep 2023 06:27:30 -0700 (PDT) From: Divin Raj To: meta-arm@lists.yoctoproject.org Subject: [PATCH] ci,doc,kas,arm-bsp,arm: Remove support for fvp-baser-aemv8r64 machine Date: Fri, 29 Sep 2023 14:26:50 +0100 Message-Id: <20230929132650.442243-1-divin.raj@arm.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Fri, 29 Sep 2023 13:27:38 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/5080 The fvp-baser-aemv8r64 machine will not be actively maintained. Signed-off-by: Divin Raj --- .gitlab-ci.yml | 8 - ci/fvp-baser-aemv8r64.yml | 7 - documentation/runfvp.md | 2 +- kas/fvp-baser-aemv8r64-bsp.yml | 42 - kas/fvp-baser-aemv8r64-rt-bsp.yml | 8 - .../conf/machine/fvp-baser-aemv8r64.conf | 66 - .../include/arm/armv8r/arch-armv8r64.inc | 10 - .../documentation/fvp-baser-aemv8r64.md | 264 - ...oot-wrapper-aarch64-fvp-baser-aemv8r64.inc | 36 - .../boot-wrapper-aarch64_%.bbappend | 4 - ...abels-and-prepare-for-lower-EL-booti.patch | 135 - ...0002-aarch64-Prepare-for-EL1-booting.patch | 48 - ...aarch64-Prepare-for-lower-EL-booting.patch | 55 - ...04-gic-v3-Prepare-for-gicv3-with-EL2.patch | 105 - ...aarch64-Prepare-for-booting-with-EL2.patch | 63 - ...ce-EL2-boot-code-for-Armv8-R-AArch64.patch | 182 - ...e-psci-to-choose-between-smc-and-hvc.patch | 89 - ...4-Disable-CNTPCT_EL0-trap-for-v8-R64.patch | 48 - .../0009-lds-Mark-the-mem-range.patch | 38 - .../0010-common-Introduce-the-libfdt.patch | 6044 ----------------- ...-common-Add-essential-libc-functions.patch | 101 - ...dd-the-libfdt-to-the-Makefile-system.patch | 61 - .../0013-platform-Add-print_hex-func.patch | 67 - ...4-common-Add-mem-usage-to-memreserve.patch | 96 - ...dd-the-enable-keep-el-compile-option.patch | 102 - ...efile-Change-COUNTER_FREQ-to-100-MHz.patch | 31 - ...lush-cache-after-setting-branch_data.patch | 49 - ...8-PSCI-Add-function-call-entry-point.patch | 71 - ...-lds-Rearrange-and-mark-the-sections.patch | 58 - ...n-Provide-firmware-info-using-libfdt.patch | 342 - ...-Enable-firmware-node-initialization.patch | 95 - ...v8-Add-ARMv8-MPU-configuration-logic.patch | 257 - ...add-MPU-memory-map-for-the-BASER_FVP.patch | 59 - ...bling-exception-vectors-on-non-SPL-b.patch | 104 - ...mv8-ARMV8_SWITCH_TO_EL1-improvements.patch | 140 - ...ling-HVC-configurable-when-switching.patch | 80 - ...press64-Do-not-set-COUNTER_FREQUENCY.patch | 30 - ...e-LIBFDT_OVERLAY-in-the-vexpress_aem.patch | 25 - ...RBAR-MPU-attributes-to-be-configured.patch | 103 - ...che-when-switching-exception-levels-.patch | 61 - .../recipes-bsp/u-boot/u-boot_%.bbappend | 17 - .../fvp-baser-aemv8r64-preempt-rt.scc | 6 - .../fvp-baser-aemv8r64-standard.scc | 7 - .../bsp/arm-platforms/fvp-baser-aemv8r64.scc | 4 - .../fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts | 212 - .../linux/linux-arm-platforms.inc | 8 - .../linux/linux-yocto-rt_%.bbappend | 1 - .../fvp/fvp-base-r-aem_11.22.14.bb | 10 - 48 files changed, 1 insertion(+), 9450 deletions(-) delete mode 100644 ci/fvp-baser-aemv8r64.yml delete mode 100644 kas/fvp-baser-aemv8r64-bsp.yml delete mode 100644 kas/fvp-baser-aemv8r64-rt-bsp.yml delete mode 100644 meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf delete mode 100644 meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc delete mode 100644 meta-arm-bsp/documentation/fvp-baser-aemv8r64.md delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch delete mode 100644 meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch delete mode 100644 meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc delete mode 100644 meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc delete mode 100644 meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc delete mode 100644 meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts delete mode 100644 meta-arm/recipes-devtools/fvp/fvp-base-r-aem_11.22.14.bb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c750698d..b427d788 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -125,14 +125,6 @@ fvp-base: - TESTING: testimage - FIRMWARE: edk2 -fvp-baser-aemv8r64: - extends: .build - parallel: - matrix: - - TESTING: testimage - tags: - - x86_64 - fvps: extends: .build diff --git a/ci/fvp-baser-aemv8r64.yml b/ci/fvp-baser-aemv8r64.yml deleted file mode 100644 index fd906250..00000000 --- a/ci/fvp-baser-aemv8r64.yml +++ /dev/null @@ -1,7 +0,0 @@ -header: - version: 14 - includes: - - ci/base.yml - - ci/fvp.yml - -machine: fvp-baser-aemv8r64 diff --git a/documentation/runfvp.md b/documentation/runfvp.md index b3c6467f..ed14d44a 100644 --- a/documentation/runfvp.md +++ b/documentation/runfvp.md @@ -55,7 +55,7 @@ The name of the FVP binary itself, for example `fvp-base` uses `FVP_Base_RevC-2x 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. +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. If `FVP_PROVIDER` is not set then it is assumed that `FVP_EXE` is installed on the host already. diff --git a/kas/fvp-baser-aemv8r64-bsp.yml b/kas/fvp-baser-aemv8r64-bsp.yml deleted file mode 100644 index 366ab87e..00000000 --- a/kas/fvp-baser-aemv8r64-bsp.yml +++ /dev/null @@ -1,42 +0,0 @@ -header: - version: 9 - includes: - - kas/fvp-eula.yml - -env: - DISPLAY: "" - -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: - -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" - IMAGE_CLASSES:append = " testimage" - -target: - - core-image-minimal diff --git a/kas/fvp-baser-aemv8r64-rt-bsp.yml b/kas/fvp-baser-aemv8r64-rt-bsp.yml deleted file mode 100644 index 19ee747f..00000000 --- a/kas/fvp-baser-aemv8r64-rt-bsp.yml +++ /dev/null @@ -1,8 +0,0 @@ -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-bsp/conf/machine/fvp-baser-aemv8r64.conf b/meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf deleted file mode 100644 index 3d82a2bd..00000000 --- a/meta-arm-bsp/conf/machine/fvp-baser-aemv8r64.conf +++ /dev/null @@ -1,66 +0,0 @@ -# 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 ?= "2023.01" - -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" - -IMAGE_NAME_SUFFIX = "" - -# 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 = "OEFVPTarget" -TEST_SUITES:append = " fvp_boot fvp_devices" -TEST_TARGET_IP ?= "127.0.0.1:2222" -TEST_SERVER_IP ?= "127.0.1.1" -TEST_FVP_DEVICES ?= "rtc watchdog networking virtiorng cpu_hotplug" - -FVP_EXTRA_ARGS = "-a cluster0*=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] ?= "2222=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] ?= "${IMAGE_NAME}.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-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc b/meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc deleted file mode 100644 index 5db12e2c..00000000 --- a/meta-arm-bsp/conf/machine/include/arm/armv8r/arch-armv8r64.inc +++ /dev/null @@ -1,10 +0,0 @@ -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-bsp/documentation/fvp-baser-aemv8r64.md b/meta-arm-bsp/documentation/fvp-baser-aemv8r64.md deleted file mode 100644 index 308cf2b2..00000000 --- a/meta-arm-bsp/documentation/fvp-baser-aemv8r64.md +++ /dev/null @@ -1,264 +0,0 @@ -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.22.14 - - 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: - - ARM_FVP_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 ARM_FVP_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 ARM_FVP_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 2222 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 2222 - -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-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc deleted file mode 100644 index 8ffa0aa2..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64-fvp-baser-aemv8r64.inc +++ /dev/null @@ -1,36 +0,0 @@ -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-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend deleted file mode 100644 index c2e7e6e3..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/boot-wrapper-aarch64_%.bbappend +++ /dev/null @@ -1,4 +0,0 @@ -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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch deleted file mode 100644 index 31fd5152..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0001-aarch64-Rename-labels-and-prepare-for-lower-EL-booti.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 545f6950ae4dc55b4974986aa9629adb16eaf4e1 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 d682ba5..fab694e 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -34,18 +34,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 - -@@ -145,7 +157,7 @@ ASM_FUNC(_start) - - bl gic_secure_init - -- b start_el3 -+ b start_el_max - - err_invalid_id: - b . -@@ -172,7 +184,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 -@@ -181,7 +193,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 - -@@ -199,5 +211,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch deleted file mode 100644 index 4ef4507e..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0002-aarch64-Prepare-for-EL1-booting.patch +++ /dev/null @@ -1,48 +0,0 @@ -From bad32d3fc127a421be416b17e4f7d6d514f06abb 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 fab694e..5105b41 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -177,10 +177,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 49d3f86..3767da3 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch deleted file mode 100644 index c621187b..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0003-aarch64-Prepare-for-lower-EL-booting.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 252cbd36e51414b60ab68306f9c38e358709494d 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 5105b41..243198d 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -151,7 +151,16 @@ el3_init: - mov x0, #ZCR_EL3_LEN_MAX // 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 - -@@ -199,7 +208,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 -@@ -217,3 +226,5 @@ ASM_FUNC(jump_kernel) - .align 3 - flag_keep_el: - .long 0 -+spsr_to_elx: -+ .long 0 diff --git a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch deleted file mode 100644 index 43885b93..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0004-gic-v3-Prepare-for-gicv3-with-EL2.patch +++ /dev/null @@ -1,105 +0,0 @@ -From bff110a95a5e4c9db2d61e629b4aa4b84530201e 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch deleted file mode 100644 index c6343456..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0005-aarch64-Prepare-for-booting-with-EL2.patch +++ /dev/null @@ -1,63 +0,0 @@ -From ba955efb35ce1d41b562190d7c2fbcbcf8ef97ff 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 243198d..3593ca5 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -216,10 +216,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch deleted file mode 100644 index 18dc7ed7..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 8e44fac113d935affed1550480631f3fe7f30584 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 3593ca5..a219ea7 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -37,16 +37,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] -@@ -160,6 +168,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 -@@ -169,6 +256,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 3767da3..3c0e00d 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 */ - -@@ -50,6 +51,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch deleted file mode 100644 index 131e2710..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0007-Allow-enable-psci-to-choose-between-smc-and-hvc.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0b9a966b8a28961b078215ee7169e32a976d5e7d 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 5731a19..fc66662 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch deleted file mode 100644 index d3ccb2eb..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0008-aarch64-Disable-CNTPCT_EL0-trap-for-v8-R64.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 521c121eccb386aca7c75d92528e495546adccec 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 a219ea7..27b1139 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -240,6 +240,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch deleted file mode 100644 index c34d01c3..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0009-lds-Mark-the-mem-range.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 780df234d98db81485b1f351f902a68def35c9d4 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch deleted file mode 100644 index 2d12db59..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0010-common-Introduce-the-libfdt.patch +++ /dev/null @@ -1,6044 +0,0 @@ -From b3762b6c5a56bf594bc5cb63d145e8efd86e106e 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch deleted file mode 100644 index b7726f51..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0011-common-Add-essential-libc-functions.patch +++ /dev/null @@ -1,101 +0,0 @@ -From e2eff4f80e65cb3fcbe6345b5376a6bf7de7e2cc 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch deleted file mode 100644 index b77ab3e2..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0012-Makefile-Add-the-libfdt-to-the-Makefile-system.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f4d5cf4c3424598a2b3bb391717313b70c79ea28 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 fc66662..ab2c3a9 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 -@@ -127,11 +130,12 @@ CFLAGS += -I$(top_srcdir)/include/ -I$(top_srcdir)/$(ARCH_SRC)/include/ - CFLAGS += -Wall -fomit-frame-pointer - CFLAGS += -ffreestanding -nostdlib - CFLAGS += -fno-stack-protector -+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. -@@ -152,10 +156,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch deleted file mode 100644 index 2346109c..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0013-platform-Add-print_hex-func.patch +++ /dev/null @@ -1,67 +0,0 @@ -From f0ece5e8cac761a76a86df7204bae7c6ef09215f 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch deleted file mode 100644 index f4ea89c6..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0014-common-Add-mem-usage-to-memreserve.patch +++ /dev/null @@ -1,96 +0,0 @@ -From f4704146e1af9f6e0a2220db6b39a328c813fac1 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 ab2c3a9..e905602 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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch deleted file mode 100644 index 7d59e5fc..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0015-boot-Add-the-enable-keep-el-compile-option.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 5995f83592aea874f5b423538e36675e2204582b 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 e905602..6604baa 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 27b1139..c079d22 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -254,7 +254,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 -@@ -334,5 +338,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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch deleted file mode 100644 index e93a300f..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0016-Makefile-Change-COUNTER_FREQ-to-100-MHz.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0c0695cd3160ccdb95bae29b7668918015c0b6aa 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 6604baa..cc6504e 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) diff --git a/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-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch deleted file mode 100644 index b63d8d1d..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0017-PSCI-Apply-flush-cache-after-setting-branch_data.patch +++ /dev/null @@ -1,49 +0,0 @@ -From fa73d885be85eee4369b292ec601e7b024a68807 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; - } - diff --git a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch deleted file mode 100644 index dd2b9653..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0018-PSCI-Add-function-call-entry-point.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 9da48e3433b919868650cd60e28827273a42c63b 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) diff --git a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch deleted file mode 100644 index c0d1fcbb..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0019-lds-Rearrange-and-mark-the-sections.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 7c5e40d9f8699a55ac2187c035429c643e6d0ef0 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!") diff --git a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch deleted file mode 100644 index 1573be05..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0020-common-Provide-firmware-info-using-libfdt.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 3c1140c29c39561848056fb4b9a03042b00279f3 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); -+} diff --git a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch b/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch deleted file mode 100644 index 9b367a7b..00000000 --- a/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0021-boot-Enable-firmware-node-initialization.patch +++ /dev/null @@ -1,95 +0,0 @@ -From b1105e862e8f770fc195bc20e9c64d231dd32f66 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 cc6504e..fbe6b81 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 -@@ -134,7 +134,7 @@ CFLAGS += -I$(top_srcdir)/include/ -I$(top_srcdir)/$(ARCH_SRC)/include/ - CFLAGS += -Wall -fomit-frame-pointer - CFLAGS += -ffreestanding -nostdlib - CFLAGS += -fno-stack-protector --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 c079d22..daaa674 100644 ---- a/arch/aarch64/boot.S -+++ b/arch/aarch64/boot.S -@@ -261,6 +261,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: -@@ -340,3 +344,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(); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch deleted file mode 100644 index 45db74e1..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0001-armv8-Add-ARMv8-MPU-configuration-logic.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 401a88bf6019941d4095476de76af5893686d6f6 Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Wed, 26 May 2021 17:41:10 +0100 -Subject: [PATCH] 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 2a226fd063..8611a35eb3 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 up page tables only once (it is done also by mmu_setup()) */ -@@ -523,7 +614,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 - */ diff --git a/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-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch deleted file mode 100644 index 103e4847..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0002-vexpress64-add-MPU-memory-map-for-the-BASER_FVP.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 5b42322cb57692dbea7d2c39fd8769b6f0f6b7af Mon Sep 17 00:00:00 2001 -From: Qi Feng -Date: Tue, 26 Jul 2022 18:13:23 +0800 -Subject: [PATCH] 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, diff --git a/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-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch deleted file mode 100644 index 5953abc6..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0003-armv8-Allow-disabling-exception-vectors-on-non-SPL-b.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ffb0f72a67926c3053308cf03420bc0c36675d42 Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Fri, 10 Dec 2021 11:41:19 +0000 -Subject: [PATCH] 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 f3ea858577..7fad901336 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 diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch deleted file mode 100644 index 157a15d7..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 14e204ffca5870d6bfd238627937a2028c88589d Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Wed, 14 Jul 2021 12:44:27 +0100 -Subject: [PATCH] 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 e414ef8267..9a86c17d2a 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(struct bootm_headers *images, int flag) -@@ -312,21 +310,29 @@ static void boot_jump_linux(struct bootm_headers *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 diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch deleted file mode 100644 index 82926cc3..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0005-armv8-Make-disabling-HVC-configurable-when-switching.patch +++ /dev/null @@ -1,80 +0,0 @@ -From e3d24bc1fd0b09915b5181de1282f7008bbf776f Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Fri, 10 Dec 2021 16:37:26 +0000 -Subject: [PATCH] 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 diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch deleted file mode 100644 index eb2273e5..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0006-vexpress64-Do-not-set-COUNTER_FREQUENCY.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 571f44d5292cfead6f68bf4c6c9519872337bfd0 Mon Sep 17 00:00:00 2001 -From: Qi Feng -Date: Thu, 28 Jul 2022 17:47:18 +0800 -Subject: [PATCH] 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" diff --git a/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-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch deleted file mode 100644 index 6f5bfa38..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0007-vexpress64-Enable-LIBFDT_OVERLAY-in-the-vexpress_aem.patch +++ /dev/null @@ -1,25 +0,0 @@ -From df01346bb63c821cf8e73202e2894ceda9cb692b Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Tue, 22 Feb 2022 15:32:51 +0000 -Subject: [PATCH] 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 diff --git a/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-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch deleted file mode 100644 index 61bdf928..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-Allow-PRBAR-MPU-attributes-to-be-configured.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 665ab8253a0e3e17db54a1682bbee0f5659939a2 Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Wed, 18 May 2022 15:24:19 +0100 -Subject: [PATCH] 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 8611a35eb3..f7de952187 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, diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch deleted file mode 100644 index a4bc746e..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0009-armv8-Enable-icache-when-switching-exception-levels-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From c7301588a3aec9ebf36749da601d0d6e3d807bfc Mon Sep 17 00:00:00 2001 -From: Peter Hoyes -Date: Thu, 19 May 2022 09:02:32 +0100 -Subject: [PATCH] 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); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend b/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend index d1dcd745..591f080a 100644 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend @@ -53,23 +53,6 @@ SRC_URI:append:corstone1000 = " \ SRC_URI:append:fvp-base = " file://bootargs.cfg \ file://0001-Revert-vexpress64-pick-DRAM-size-from-DT.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 # diff --git a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc deleted file mode 100644 index e8fea0b8..00000000 --- a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-preempt-rt.scc +++ /dev/null @@ -1,6 +0,0 @@ -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-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc deleted file mode 100644 index fd1fb282..00000000 --- a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64-standard.scc +++ /dev/null @@ -1,7 +0,0 @@ -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-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc deleted file mode 100644 index a8d79670..00000000 --- a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/fvp-baser-aemv8r64.scc +++ /dev/null @@ -1,4 +0,0 @@ -kconf hardware arm64.cfg -kconf hardware fvp-common-peripherals.cfg -include cfg/virtio.scc -include virtio-9p.scc diff --git a/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts b/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts deleted file mode 100644 index 6911a598..00000000 --- a/meta-arm-bsp/recipes-kernel/linux/files/fvp-baser-aemv8r64/fvp-baser-aemv8r64.dts +++ /dev/null @@ -1,212 +0,0 @@ -/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-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc index 666ed41d..4028cf31 100644 --- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc +++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc @@ -14,7 +14,6 @@ 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-baser-aemv8r64 = " ${SRC_URI_KMETA}" SRC_URI:append:juno = " ${SRC_URI_KMETA}" SRC_URI:append:n1sdp = " ${SRC_URI_KMETA}" SRCREV:arm-platforms-kmeta = "6147e82375aa9df8f2a162d42ea6406c79c854c5" @@ -58,13 +57,6 @@ 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 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 # diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-yocto-rt_%.bbappend b/meta-arm-bsp/recipes-kernel/linux/linux-yocto-rt_%.bbappend index 8994c241..b1efabf3 100644 --- a/meta-arm-bsp/recipes-kernel/linux/linux-yocto-rt_%.bbappend +++ b/meta-arm-bsp/recipes-kernel/linux/linux-yocto-rt_%.bbappend @@ -1,6 +1,5 @@ # Only enable linux-yocto-rt for n1sdp and the Armv8-R AArch64 AEM FVP LINUX_YOCTO_RT_REQUIRE ?= "" LINUX_YOCTO_RT_REQUIRE:n1sdp = "linux-arm-platforms.inc" -LINUX_YOCTO_RT_REQUIRE:fvp-baser-aemv8r64 = "linux-arm-platforms.inc" require ${LINUX_YOCTO_RT_REQUIRE} diff --git a/meta-arm/recipes-devtools/fvp/fvp-base-r-aem_11.22.14.bb b/meta-arm/recipes-devtools/fvp/fvp-base-r-aem_11.22.14.bb deleted file mode 100644 index 89c83eab..00000000 --- a/meta-arm/recipes-devtools/fvp/fvp-base-r-aem_11.22.14.bb +++ /dev/null @@ -1,10 +0,0 @@ -require fvp-envelope.inc - -SUMMARY = "Arm Fixed Virtual Platform - Armv8-R Base Architecture Envelope Model FVP" -LIC_FILES_CHKSUM = "file://license_terms/license_agreement.txt;md5=1a33828e132ba71861c11688dbb0bd16 \ - file://license_terms/third_party_licenses/third_party_licenses.txt;md5=34a1ba318d745f05e6197def68ea5411 \ - file://license_terms/third_party_licenses/arm_license_management_utilities/third_party_licenses.txt;md5=c09526c02e631abb95ad61528892552d" - -SRC_URI[fvp-x86_64.sha256sum] = "e819bfbccd91749345e3c7c6db22cbe41e02223118eb6395a4307ca81b175f7a" - -MODEL_CODE = "FVP_Base_AEMv8R"