summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt136
-rw-r--r--arch/sandbox/dts/test.dts3
-rw-r--r--arch/sandbox/include/asm/sdl.h4
-rw-r--r--arch/sandbox/include/asm/types.h12
-rw-r--r--arch/sandbox/lib/pci_io.c2
-rw-r--r--common/fdt_support.c6
-rw-r--r--configs/sandbox64_defconfig1
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/README.chromium296
-rw-r--r--doc/README.chromium-chainload239
-rw-r--r--drivers/clk/altera/clk-arria10.c3
-rw-r--r--drivers/clk/at91/pmc.c2
-rw-r--r--drivers/core/ofnode.c21
-rw-r--r--drivers/core/syscon-uclass.c83
-rw-r--r--drivers/core/util.c40
-rw-r--r--drivers/pinctrl/pinctrl-uclass.c36
-rw-r--r--drivers/sysreset/sysreset_syscon.c15
-rw-r--r--dts/Kconfig8
-rw-r--r--include/dm/pinctrl.h12
-rw-r--r--include/dm/util.h26
-rw-r--r--include/fdtdec.h169
-rw-r--r--lib/Kconfig4
-rw-r--r--lib/fdtdec.c225
-rw-r--r--lib/fdtdec_test.c216
-rw-r--r--lib/libfdt/fdt_ro.c31
-rw-r--r--lib/vsprintf.c2
-rw-r--r--scripts/Makefile.lib1
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c31
-rw-r--r--scripts/dtc/libfdt/libfdt.h19
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h1
-rw-r--r--test/dm/syscon.c7
-rw-r--r--tools/mkimage.c23
32 files changed, 1280 insertions, 395 deletions
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
new file mode 100644
index 0000000000..bac4afa3b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -0,0 +1,136 @@
+*** Reserved memory regions ***
+
+Reserved memory is specified as a node under the /reserved-memory node.
+The operating system shall exclude reserved memory from normal usage
+one can create child nodes describing particular reserved (excluded from
+normal use) memory regions. Such memory regions are usually designed for
+the special usage by various device drivers.
+
+Parameters for each memory region can be encoded into the device tree
+with the following nodes:
+
+/reserved-memory node
+---------------------
+#address-cells, #size-cells (required) - standard definition
+ - Should use the same values as the root node
+ranges (required) - standard definition
+ - Should be empty
+
+/reserved-memory/ child nodes
+-----------------------------
+Each child of the reserved-memory node specifies one or more regions of
+reserved memory. Each child node may either use a 'reg' property to
+specify a specific range of reserved memory, or a 'size' property with
+optional constraints to request a dynamically allocated block of memory.
+
+Following the generic-names recommended practice, node names should
+reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit
+address (@<address>) should be appended to the name if the node is a
+static allocation.
+
+Properties:
+Requires either a) or b) below.
+a) static allocation
+ reg (required) - standard definition
+b) dynamic allocation
+ size (required) - length based on parent's #size-cells
+ - Size in bytes of memory to reserve.
+ alignment (optional) - length based on parent's #size-cells
+ - Address boundary for alignment of allocation.
+ alloc-ranges (optional) - prop-encoded-array (address, length pairs).
+ - Specifies regions of memory that are
+ acceptable to allocate from.
+
+If both reg and size are present, then the reg property takes precedence
+and size is ignored.
+
+Additional properties:
+compatible (optional) - standard definition
+ - may contain the following strings:
+ - shared-dma-pool: This indicates a region of memory meant to be
+ used as a shared pool of DMA buffers for a set of devices. It can
+ be used by an operating system to instantiate the necessary pool
+ management subsystem if necessary.
+ - vendor specific string in the form <vendor>,[<device>-]<usage>
+no-map (optional) - empty property
+ - Indicates the operating system must not create a virtual mapping
+ of the region as part of its standard mapping of system memory,
+ nor permit speculative access to it under any circumstances other
+ than under the control of the device driver using the region.
+reusable (optional) - empty property
+ - The operating system can use the memory in this region with the
+ limitation that the device driver(s) owning the region need to be
+ able to reclaim it back. Typically that means that the operating
+ system can use that region to store volatile or cached data that
+ can be otherwise regenerated or migrated elsewhere.
+
+Linux implementation note:
+- If a "linux,cma-default" property is present, then Linux will use the
+ region for the default pool of the contiguous memory allocator.
+
+- If a "linux,dma-default" property is present, then Linux will use the
+ region for the default pool of the consistent DMA allocator.
+
+Device node references to reserved memory
+-----------------------------------------
+Regions in the /reserved-memory node may be referenced by other device
+nodes by adding a memory-region property to the device node.
+
+memory-region (optional) - phandle, specifier pairs to children of /reserved-memory
+
+Example
+-------
+This example defines 3 contiguous regions are defined for Linux kernel:
+one default of all device drivers (named linux,cma@72000000 and 64MiB in size),
+one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and
+one for multimedia processing (named multimedia-memory@77000000, 64MiB).
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory {
+ reg = <0x40000000 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x4000000>;
+ alignment = <0x2000>;
+ linux,cma-default;
+ };
+
+ display_reserved: framebuffer@78000000 {
+ reg = <0x78000000 0x800000>;
+ };
+
+ multimedia_reserved: multimedia@77000000 {
+ compatible = "acme,multimedia-memory";
+ reg = <0x77000000 0x4000000>;
+ };
+ };
+
+ /* ... */
+
+ fb0: video@12300000 {
+ memory-region = <&display_reserved>;
+ /* ... */
+ };
+
+ scaler: scaler@12500000 {
+ memory-region = <&multimedia_reserved>;
+ /* ... */
+ };
+
+ codec: codec@12600000 {
+ memory-region = <&multimedia_reserved>;
+ /* ... */
+ };
+};
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 87d8e5bcc9..6d4134c053 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -493,6 +493,7 @@
compatible = "denx,u-boot-probe-test";
first-syscon = <&syscon0>;
second-sys-ctrl = <&another_system_controller>;
+ third-syscon = <&syscon2>;
};
};
@@ -597,7 +598,7 @@
0x38 8>;
};
- syscon@2 {
+ syscon2: syscon@2 {
compatible = "simple-mfd", "syscon";
reg = <0x40 5
0x48 6
diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h
index 1027b59e73..c45dbddd70 100644
--- a/arch/sandbox/include/asm/sdl.h
+++ b/arch/sandbox/include/asm/sdl.h
@@ -104,7 +104,7 @@ static inline int sandbox_sdl_sound_start(uint frequency)
return -ENODEV;
}
-int sandbox_sdl_sound_play(const void *data, uint count)
+static inline int sandbox_sdl_sound_play(const void *data, uint count)
{
return -ENODEV;
}
@@ -114,7 +114,7 @@ static inline int sandbox_sdl_sound_stop(void)
return -ENODEV;
}
-int sandbox_sdl_sound_init(int rate, int channels)
+static inline int sandbox_sdl_sound_init(int rate, int channels)
{
return -ENODEV;
}
diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index 7cd56b4147..c1a5d2af82 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -18,21 +18,21 @@ typedef unsigned short umode_t;
/*
* Number of bits in a C 'long' on this architecture.
*/
-#ifdef CONFIG_PHYS64
+#ifdef CONFIG_PHYS_64BIT
#define BITS_PER_LONG 64
-#else /* CONFIG_PHYS64 */
+#else /* CONFIG_PHYS_64BIT */
#define BITS_PER_LONG 32
-#endif /* CONFIG_PHYS64 */
+#endif /* CONFIG_PHYS_64BIT */
-#ifdef CONFIG_PHYS64
+#ifdef CONFIG_PHYS_64BIT
typedef unsigned long long dma_addr_t;
typedef u64 phys_addr_t;
typedef u64 phys_size_t;
-#else /* CONFIG_PHYS64 */
+#else /* CONFIG_PHYS_64BIT */
typedef unsigned long dma_addr_t;
typedef u32 phys_addr_t;
typedef u32 phys_size_t;
-#endif /* CONFIG_PHYS64 */
+#endif /* CONFIG_PHYS_64BIT */
#endif /* __KERNEL__ */
diff --git a/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c
index 5039973cd7..01822c6069 100644
--- a/arch/sandbox/lib/pci_io.c
+++ b/arch/sandbox/lib/pci_io.c
@@ -34,7 +34,7 @@ int pci_map_physmem(phys_addr_t paddr, unsigned long *lenp,
return 0;
}
- debug("%s: failed: addr=%x\n", __func__, paddr);
+ debug("%s: failed: addr=%pap\n", __func__, &paddr);
return -ENOSYS;
}
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 42583e3ed8..ab08a0114f 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -456,12 +456,6 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
if (!banks)
return 0;
- for (i = 0; i < banks; i++)
- if (start[i] == 0 && size[i] == 0)
- break;
-
- banks = i;
-
len = fdt_pack_reg(blob, tmp, start, size, banks);
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index da4bdced31..c04ecd915a 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -194,6 +194,7 @@ CONFIG_CMD_DHRYSTONE=y
CONFIG_TPM=y
CONFIG_LZ4=y
CONFIG_ERRNO_STR=y
+CONFIG_TEST_FDTDEC=y
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 193e41896c..bb508a8d02 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -215,6 +215,7 @@ CONFIG_CMD_DHRYSTONE=y
CONFIG_TPM=y
CONFIG_LZ4=y
CONFIG_ERRNO_STR=y
+CONFIG_TEST_FDTDEC=y
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
diff --git a/doc/README.chromium b/doc/README.chromium
index 45eaeced2d..096bc4f1f7 100644
--- a/doc/README.chromium
+++ b/doc/README.chromium
@@ -1,239 +1,177 @@
-Running U-Boot from coreboot on Chromebooks
-===========================================
+Chromium OS Support in U-Boot
+=============================
-U-Boot can be used as a secondary boot loader in a few situations such as from
-UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on
-ARM platforms to start up the machine.
+Introduction
+------------
-This document aims to provide a guide to booting U-Boot on a Chromebook. It
-is only a starting point, and there are many guides on the interwebs. But
-placing this information in the U-Boot tree should make it easier to find for
-those who use U-Boot habitually.
+This describes how to use U-Boot with Chromium OS. Several options are
+available:
-Most of these platforms are supported by U-Boot natively, but it is risky to
-replace the ROM unless you have a servo board and cable to restore it with.
+ - Running U-Boot from the 'altfw' feature, which is available on selected
+ Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
+ developer-mode screen to get into U-Boot. See here for details:
+ https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1
+ - Running U-Boot from the disk partition. This involves signing U-Boot and
+ placing it on the disk, for booting as a 'kernel'. See
+ README.chromium-chainload for information on this. This is the only
+ option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
+ more involved.
-For all of these the standard U-Boot build instructions apply. For example on
-ARM:
+ - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
+ used instead of either or both of depthcharge (a bootloader which forked
+ from U-Boot in 2013) and coreboot. See below for more information on
+ this.
- sudo apt install gcc-arm-linux-gnueabi
- mkdir b
- make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
-You can obtain the vbutil_kernel utility here:
+U-Boot with Chromium OS verified boot
+-------------------------------------
- https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U
+To obtain:
+ git clone https://github.com/sglass68/u-boot.git
+ cd u-boot
+ git checkout cros-master
-Snow (Samsung ARM Chromebook)
------------------------------
+To build for sandbox:
-See here:
+ UB=/tmp/b/chromeos_sandbox # U-Boot build directory
+ CROS=/home/sglass/cosarm # Chromium OS directory
+ make O=$UB/chromeos_sandbox_defconfig
+ make O=$UB -j20 -s VBOOT_SOURCE=$CROS/src/platform/vboot_reference \
+ MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
-https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook
+Replace sandbox with another supported target.
+This produces $UB/image.bin which contains the firmware binaries in a SPI
+flash image.
-Nyan-big
---------
-
-Compiled based on information here:
-https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
-https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
-https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
-https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
-
-1. Build U-Boot
-
- mkdir b
- make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
-
-
-2. Select a .its file
-
-Select something from doc/chromium which matches your board, or create your
-own.
-
-Note that the device tree node is required, even though it is not actually
-used by U-Boot. This is because the Chromebook expects to pass it to the
-kernel, and crashes if it is not present.
-
-
-3. Build and sign an image
-
- ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
- echo test >dummy.txt
- vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
- --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
- --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
- --bootloader dummy.txt --pack u-boot.kpart
-
-
-4. Prepare an SD card
-
- DISK=/dev/sdc # Replace with your actual SD card device
- sudo cgpt create $DISK
- sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
- sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK
- sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk
-
-
-5. Write U-Boot to the SD card
+To run on sandbox:
- sudo dd if=u-boot.kpart of=/dev/sdc1; sync
+ $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \
+ -L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \
+ -l -w -s state.dtb -r
+To run on other boards:
+ Install image.bin in the SPI flash of your device
+ Boot your system
-6. Start it up
-Reboot the device in dev mode. Make sure that you have USB booting enabled. To
-do this, login as root (via Ctrl-Alt-forward_arrow) and type
-'enable_dev_usb_boot'. You only need to do this once.
+Sandbox
+-------
-Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+Most Chromium OS development with U-Boot is undertaken using sandbox. There is
+a sandbox target available (chromeos_sandbox) which allows running U-Boot on
+a Linux machine completion with emulations of the display, TPM, disk, etc.
- U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
+Running sandbox starts TPL, which contains the first phase of vboot, providing
+a device tree and binding a Chromium OS disk image for use to find kernels
+(any Chromium OS image will do). It also saves driver state between U-Boot
+phases into state.dtb and will automatically ensure that memory is shared
+between all phases. TPL will jump to SPL and then on to U-Boot proper.
- Model: Acer Chromebook 13 CB5-311
- Board: Google/NVIDIA Nyan-big, ID: 1
+It is possible to run with debugging on, e.g.
- Net: No ethernet found.
- Hit any key to stop autoboot: 0
- Tegra124 (Nyan-big) #
+ gdb --args $UB/tpl/u-boot-tpl -d ....
+Breakpoints can be set in any U-Boot phase. Overall this is a good debugging
+environment for new verified-boot features.
-7. Known problems
-On the serial console the word MMC is chopped at the start of the line:
+Samus
+-----
-C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+Basic support is available for samus, using the chromeos_samus target. If you
+have an em100, use:
-This is likely due to some problem with change-over of the serial driver
-during relocation (or perhaps updating the clock setup in board_init()).
+ sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
+to write the image and then boot samus (Power-Refresh).
-9. Notes
-To check that you copied the u-boot.its file correctly, use these commands.
-You should see that the data at 0x100 in u-boot-chromium.fit is the first few
-bytes of U-Boot:
+Boot flow
+---------
- hd u-boot-chromium.fit |head -20
- ...
- 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................|
+Verified boot starts in TPL, which selects the A or B SPL, which in turn selects
+the A or B U-Boot. Then this jumps to the selected kernel. If anything goes
+wrong, the device reboots and the recovery SPL and U-Boot are used instead.
- hd b/nyan-big/u-boot.bin |head
- 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................|
+More details are available here:
+ https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery
-The 'data' property of the FIT is set up to start at offset 0x100 bytes into
-the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes
-from the load address. If this changes, you either need to modify U-Boot to be
-fully relocatable, or expect it to hang.
+New uclasses
+------------
-chromebook_jerry
-----------------
+Several uclasses are provided in cros/:
-The instruction are similar to those for Nyan with changes as noted below:
+ UCLASS_CROS_AUX_FW Chrome OS auxiliary firmware
+ UCLASS_CROS_FWSTORE Chrome OS firmware storage
+ UCLASS_CROS_NVDATA Chrome OS non-volatile data device
+ UCLASS_CROS_VBOOT_EC Chrome OS vboot EC operations
+ UCLASS_CROS_VBOOT_FLAG Chrome OS verified boot flag
-1. Patch U-Boot
+The existing UCLASS_CROS_EC is also used.
-Open include/configs/rk3288_common.h
-Change:
-
-#define CONFIG_SYS_TEXT_BASE 0x00100000
-
-to:
-
-#define CONFIG_SYS_TEXT_BASE 0x02000100
-
-
-
-2. Build U-Boot
-
- mkdir b
- make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
- chromebook_jerry_defconfig all
-
-
-3. See above
-
-4. Build and sign an image
-
- ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
- u-boot-chromium.fit
- echo test >dummy.txt
- vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
- --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
- --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
- --bootloader dummy.txt --pack u-boot.kpart
-
-
-5. See above
+Commands
+--------
-6. See above
+A new 'vboot' command is provided to run particular vboot stages. The most
+useful command is 'vboot go auto', which continues where the last stage left
+off.
-7. Start it up
+Note that TPL and SPL do not supports commands as yet, so the vboot code is
+called directly from the SPL boot devices (BOOT_DEVICE_CROS_VBOOT). See
+cros_load_image_tpl() and cros_load_image_spl() which both call
+vboot_run_auto().
-Reboot the device in dev mode. Make sure that you have USB booting enabled. To
-do this, login as root (via Ctrl-Alt-forward_arrow) and type
-'enable_dev_usb_boot'. You only need to do this once.
-Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+Config options
+--------------
- U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
+The main option is CONFIG_CHROMEOS, which enables a wide array of other options
+so that the required features are present.
- Model: Google Jerry
- Net: Net Initialization Skipped
- No ethernet found.
- Hit any key to stop autoboot: 0
+Device-tree config
+------------------
-8. Known problems
+Various options are available which control the operation of verified boot.
+See cros/dts/bindings/config.txt for details. Most config is handled at run-
+time, although build-time config (with Kconfig) could also be added fairly
+easily.
-None as yet.
+Porting to other hardware
+-------------------------
-9. Notes
+A basic port to samus (Chromebook Pixel 2015) is in a basic working state,
+using the chromeos_samus target. Patches will likely be forthcoming in early
+2019. Ports to an ARM board and coreboot (for x86 Chromebooks) are in the
+dreaming state.
-None as yet.
+Tests
+-----
-Other notes
-===========
+Chromium OS firmware has a very limited set of tests. The tests that originally
+existed in U-Boot were not brought over to coreboot or depthcharge.
-flashrom
---------
+The U-Boot tests ('make check') do operate, but at present there are no
+Chromium OS tests available. These will hopefully come together over time. Of
+course the above sandbox feature provides a sort of functional test and can
+detecte problems that affect the flow or particular vboot features.
- Used to make a backup of your firmware, or to replace it.
- See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+TO DO
+-----
+- Support for booting from coreboot (patches expected March 2019)
+- Support for booting from an ARM board, e.g. bob
-coreboot
---------
-Coreboot itself is not designed to actually boot an OS. Instead, a program
-called Depthcharge is used. This originally came out of U-Boot and was then
-heavily hacked and modified such that is is almost unrecognisable. It does
-include a very small part of the U-Boot command-line interface but is not
-usable as a general-purpose boot loader.
-
-In addition, it has a very unusual design in that it does not do device init
-itself, but instead relies on coreboot. This is similar to (in U-Boot) having
-a SPI driver with an empty probe() method, relying on whatever was set up
-beforehand. It can be quite hard to figure out between these two code bases
-what settings are actually used. When chain-loading into U-Boot we must be
-careful to reinit anything that U-Boot expects. If not, some peripherals (or
-the whole machine) may not work. This makes the process of chainloading more
-complicated than it could be on some platforms.
-
-Finally, it supports only a subset of the U-Boot's FIT format. In particular
-it uses a fixed address to load the FIT and does not support load/exec
-addresses. This means that U-Boot must be able to boot from whatever
-address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting
-in Depthcharge). In practice this means that the data in the kernel@1 FIT node
-(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE.
+Simon Glass
+sjg@chromium.org
+7 October 2018
diff --git a/doc/README.chromium-chainload b/doc/README.chromium-chainload
new file mode 100644
index 0000000000..45eaeced2d
--- /dev/null
+++ b/doc/README.chromium-chainload
@@ -0,0 +1,239 @@
+Running U-Boot from coreboot on Chromebooks
+===========================================
+
+U-Boot can be used as a secondary boot loader in a few situations such as from
+UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on
+ARM platforms to start up the machine.
+
+This document aims to provide a guide to booting U-Boot on a Chromebook. It
+is only a starting point, and there are many guides on the interwebs. But
+placing this information in the U-Boot tree should make it easier to find for
+those who use U-Boot habitually.
+
+Most of these platforms are supported by U-Boot natively, but it is risky to
+replace the ROM unless you have a servo board and cable to restore it with.
+
+
+For all of these the standard U-Boot build instructions apply. For example on
+ARM:
+
+ sudo apt install gcc-arm-linux-gnueabi
+ mkdir b
+ make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
+
+You can obtain the vbutil_kernel utility here:
+
+ https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U
+
+
+Snow (Samsung ARM Chromebook)
+-----------------------------
+
+See here:
+
+https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook
+
+
+Nyan-big
+--------
+
+Compiled based on information here:
+https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
+https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
+https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
+https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
+
+1. Build U-Boot
+
+ mkdir b
+ make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
+
+
+2. Select a .its file
+
+Select something from doc/chromium which matches your board, or create your
+own.
+
+Note that the device tree node is required, even though it is not actually
+used by U-Boot. This is because the Chromebook expects to pass it to the
+kernel, and crashes if it is not present.
+
+
+3. Build and sign an image
+
+ ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
+ echo test >dummy.txt
+ vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
+ --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
+ --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+ --bootloader dummy.txt --pack u-boot.kpart
+
+
+4. Prepare an SD card
+
+ DISK=/dev/sdc # Replace with your actual SD card device
+ sudo cgpt create $DISK
+ sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
+ sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK
+ sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk
+
+
+5. Write U-Boot to the SD card
+
+ sudo dd if=u-boot.kpart of=/dev/sdc1; sync
+
+
+6. Start it up
+
+Reboot the device in dev mode. Make sure that you have USB booting enabled. To
+do this, login as root (via Ctrl-Alt-forward_arrow) and type
+'enable_dev_usb_boot'. You only need to do this once.
+
+Reboot the device with the SD card inserted. Press Clrl-U at the developer
+mode screen. It should show something like the following on the display:
+
+ U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
+
+ Model: Acer Chromebook 13 CB5-311
+ Board: Google/NVIDIA Nyan-big, ID: 1
+
+ Net: No ethernet found.
+ Hit any key to stop autoboot: 0
+ Tegra124 (Nyan-big) #
+
+
+7. Known problems
+
+On the serial console the word MMC is chopped at the start of the line:
+
+C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+
+This is likely due to some problem with change-over of the serial driver
+during relocation (or perhaps updating the clock setup in board_init()).
+
+
+9. Notes
+
+To check that you copied the u-boot.its file correctly, use these commands.
+You should see that the data at 0x100 in u-boot-chromium.fit is the first few
+bytes of U-Boot:
+
+ hd u-boot-chromium.fit |head -20
+ ...
+ 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................|
+
+ hd b/nyan-big/u-boot.bin |head
+ 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................|
+
+
+The 'data' property of the FIT is set up to start at offset 0x100 bytes into
+the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes
+from the load address. If this changes, you either need to modify U-Boot to be
+fully relocatable, or expect it to hang.
+
+
+chromebook_jerry
+----------------
+
+The instruction are similar to those for Nyan with changes as noted below:
+
+1. Patch U-Boot
+
+Open include/configs/rk3288_common.h
+
+Change:
+
+#define CONFIG_SYS_TEXT_BASE 0x00100000
+
+to:
+
+#define CONFIG_SYS_TEXT_BASE 0x02000100
+
+
+
+2. Build U-Boot
+
+ mkdir b
+ make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
+ chromebook_jerry_defconfig all
+
+
+3. See above
+
+4. Build and sign an image
+
+ ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
+ u-boot-chromium.fit
+ echo test >dummy.txt
+ vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
+ --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
+ --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+ --bootloader dummy.txt --pack u-boot.kpart
+
+
+5. See above
+
+6. See above
+
+7. Start it up
+
+Reboot the device in dev mode. Make sure that you have USB booting enabled. To
+do this, login as root (via Ctrl-Alt-forward_arrow) and type
+'enable_dev_usb_boot'. You only need to do this once.
+
+Reboot the device with the SD card inserted. Press Clrl-U at the developer
+mode screen. It should show something like the following on the display:
+
+ U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
+
+ Model: Google Jerry
+ Net: Net Initialization Skipped
+ No ethernet found.
+ Hit any key to stop autoboot: 0
+
+
+8. Known problems
+
+None as yet.
+
+
+9. Notes
+
+None as yet.
+
+
+Other notes
+===========
+
+flashrom
+--------
+
+ Used to make a backup of your firmware, or to replace it.
+
+ See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+
+
+coreboot
+--------
+
+Coreboot itself is not designed to actually boot an OS. Instead, a program
+called Depthcharge is used. This originally came out of U-Boot and was then
+heavily hacked and modified such that is is almost unrecognisable. It does
+include a very small part of the U-Boot command-line interface but is not
+usable as a general-purpose boot loader.
+
+In addition, it has a very unusual design in that it does not do device init
+itself, but instead relies on coreboot. This is similar to (in U-Boot) having
+a SPI driver with an empty probe() method, relying on whatever was set up
+beforehand. It can be quite hard to figure out between these two code bases
+what settings are actually used. When chain-loading into U-Boot we must be
+careful to reinit anything that U-Boot expects. If not, some peripherals (or
+the whole machine) may not work. This makes the process of chainloading more
+complicated than it could be on some platforms.
+
+Finally, it supports only a subset of the U-Boot's FIT format. In particular
+it uses a fixed address to load the FIT and does not support load/exec
+addresses. This means that U-Boot must be able to boot from whatever
+address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting
+in Depthcharge). In practice this means that the data in the kernel@1 FIT node
+(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE.
diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c
index 612a1718dc..179869df45 100644
--- a/drivers/clk/altera/clk-arria10.c
+++ b/drivers/clk/altera/clk-arria10.c
@@ -254,7 +254,8 @@ static int socfpga_a10_clk_bind(struct udevice *dev)
fdt_node_check_compatible(fdt, offset, "fixed-clock"))
continue;
- if (pre_reloc_only && !dm_fdt_pre_reloc(fdt, offset))
+ if (pre_reloc_only &&
+ !dm_ofnode_pre_reloc(offset_to_ofnode(offset)))
continue;
ret = device_bind_driver_to_node(dev, "clk-a10", name,
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 7cfbabc96d..6b55ec59d6 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -61,7 +61,7 @@ int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
offset > 0;
offset = fdt_next_subnode(fdt, offset)) {
if (pre_reloc_only &&
- !dm_fdt_pre_reloc(fdt, offset))
+ !dm_ofnode_pre_reloc(offset_to_ofnode(offset)))
continue;
/*
* If this node has "compatible" property, this is not
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 0e584c12dc..785f5c3acf 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -254,14 +254,13 @@ int ofnode_read_size(ofnode node, const char *propname)
fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
{
int na, ns;
- fdt_size_t size;
if (ofnode_is_np(node)) {
const __be32 *prop_val;
uint flags;
prop_val = of_get_address(ofnode_to_np(node), index,
- (u64 *)&size, &flags);
+ NULL, &flags);
if (!prop_val)
return FDT_ADDR_T_NONE;
@@ -278,7 +277,7 @@ fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
return fdtdec_get_addr_size_fixed(gd->fdt_blob,
ofnode_to_offset(node), "reg",
- index, na, ns, &size, true);
+ index, na, ns, NULL, true);
}
return FDT_ADDR_T_NONE;
@@ -700,18 +699,18 @@ int ofnode_read_simple_size_cells(ofnode node)
bool ofnode_pre_reloc(ofnode node)
{
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
+ /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
+ * had property dm-pre-reloc or u-boot,dm-spl/tpl.
+ * They are removed in final dtb (fdtgrep 2nd pass)
+ */
+ return true;
+#else
if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
return true;
if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
return true;
-#ifdef CONFIG_TPL_BUILD
- if (ofnode_read_bool(node, "u-boot,dm-tpl"))
- return true;
-#elif defined(CONFIG_SPL_BUILD)
- if (ofnode_read_bool(node, "u-boot,dm-spl"))
- return true;
-#else
/*
* In regular builds individual spl and tpl handling both
* count as handled pre-relocation for later second init.
@@ -719,9 +718,9 @@ bool ofnode_pre_reloc(ofnode node)
if (ofnode_read_bool(node, "u-boot,dm-spl") ||
ofnode_read_bool(node, "u-boot,dm-tpl"))
return true;
-#endif
return false;
+#endif
}
int ofnode_read_resource(ofnode node, uint index, struct resource *res)
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index afac6d6e37..5bb38e329c 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -57,18 +57,64 @@ static int syscon_pre_probe(struct udevice *dev)
#endif
}
+static int syscon_probe_by_ofnode(ofnode node, struct udevice **devp)
+{
+ struct udevice *dev, *parent;
+ int ret;
+
+ /* found node with "syscon" compatible, not bounded to SYSCON UCLASS */
+ if (!ofnode_device_is_compatible(node, "syscon")) {
+ dev_dbg(dev, "invalid compatible for syscon device\n");
+ return -EINVAL;
+ }
+
+ /* bound to driver with same ofnode or to root if not found */
+ if (device_find_global_by_ofnode(node, &parent))
+ parent = dm_root();
+
+ /* force bound to syscon class */
+ ret = device_bind_driver_to_node(parent, "syscon",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret) {
+ dev_dbg(dev, "unable to bound syscon device\n");
+ return ret;
+ }
+ ret = device_probe(dev);
+ if (ret) {
+ dev_dbg(dev, "unable to probe syscon device\n");
+ return ret;
+ }
+
+ *devp = dev;
+ return 0;
+}
+
struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
const char *name)
{
struct udevice *syscon;
struct regmap *r;
+ u32 phandle;
+ ofnode node;
int err;
err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
name, &syscon);
if (err) {
- dev_dbg(dev, "unable to find syscon device\n");
- return ERR_PTR(err);
+ /* found node with "syscon" compatible, not bounded to SYSCON */
+ err = ofnode_read_u32(dev_ofnode(dev), name, &phandle);
+ if (err)
+ return ERR_PTR(err);
+
+ node = ofnode_get_by_phandle(phandle);
+ if (!ofnode_valid(node)) {
+ dev_dbg(dev, "unable to find syscon device\n");
+ return ERR_PTR(-EINVAL);
+ }
+ err = syscon_probe_by_ofnode(node, &syscon);
+ if (err)
+ return ERR_PTR(-ENODEV);
}
r = syscon_get_regmap(syscon);
@@ -152,29 +198,18 @@ U_BOOT_DRIVER(generic_syscon) = {
*/
struct regmap *syscon_node_to_regmap(ofnode node)
{
- struct udevice *dev, *parent;
- int ret;
-
- if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
- return syscon_get_regmap(dev);
-
- if (!ofnode_device_is_compatible(node, "syscon"))
- return ERR_PTR(-EINVAL);
+ struct udevice *dev;
+ struct regmap *r;
- /* bound to driver with same ofnode or to root if not found */
- if (device_find_global_by_ofnode(node, &parent))
- parent = dm_root();
+ if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
+ if (syscon_probe_by_ofnode(node, &dev))
+ return ERR_PTR(-ENODEV);
- /* force bound to syscon class */
- ret = device_bind_driver_to_node(parent, "syscon",
- ofnode_get_name(node),
- node, &dev);
- if (ret)
- return ERR_PTR(ret);
-
- ret = device_probe(dev);
- if (ret)
- return ERR_PTR(ret);
+ r = syscon_get_regmap(dev);
+ if (!r) {
+ dev_dbg(dev, "unable to find regmap\n");
+ return ERR_PTR(-ENODEV);
+ }
- return syscon_get_regmap(dev);
+ return r;
}
diff --git a/drivers/core/util.c b/drivers/core/util.c
index 27a6848703..96e47dc707 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -31,42 +31,18 @@ int list_count_items(struct list_head *head)
return count;
}
-bool dm_fdt_pre_reloc(const void *blob, int offset)
-{
- if (fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
- return true;
-
-#ifdef CONFIG_TPL_BUILD
- if (fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL))
- return true;
-#elif defined(CONFIG_SPL_BUILD)
- if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL))
- return true;
-#else
- /*
- * In regular builds individual spl and tpl handling both
- * count as handled pre-relocation for later second init.
- */
- if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL) ||
- fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL))
- return true;
-#endif
-
- return false;
-}
-
bool dm_ofnode_pre_reloc(ofnode node)
{
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
+ /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
+ * had property dm-pre-reloc or u-boot,dm-spl/tpl.
+ * They are removed in final dtb (fdtgrep 2nd pass)
+ */
+ return true;
+#else
if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
return true;
-#ifdef CONFIG_TPL_BUILD
- if (ofnode_read_bool(node, "u-boot,dm-tpl"))
- return true;
-#elif defined(CONFIG_SPL_BUILD)
- if (ofnode_read_bool(node, "u-boot,dm-spl"))
- return true;
-#else
/*
* In regular builds individual spl and tpl handling both
* count as handled pre-relocation for later second init.
@@ -74,7 +50,7 @@ bool dm_ofnode_pre_reloc(ofnode node)
if (ofnode_read_bool(node, "u-boot,dm-spl") ||
ofnode_read_bool(node, "u-boot,dm-tpl"))
return true;
-#endif
return false;
+#endif
}
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 0e3260afd1..0e6c559d5e 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -27,28 +27,6 @@ int pinctrl_decode_pin_config(const void *blob, int node)
return flags;
}
-/*
- * TODO: this function is temporary for v2019.01.
- * It should be renamed to pinctrl_decode_pin_config(),
- * the original pinctrl_decode_pin_config() function should
- * be removed and all callers of the original function should
- * be migrated to use the new one.
- */
-int pinctrl_decode_pin_config_dm(struct udevice *dev)
-{
- int pinconfig = 0;
-
- if (dev->uclass->uc_drv->id != UCLASS_PINCONFIG)
- return -EINVAL;
-
- if (dev_read_bool(dev, "bias-pull-up"))
- pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_UP;
- else if (dev_read_bool(dev, "bias-pull-down"))
- pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_DOWN;
-
- return pinconfig;
-}
-
#if CONFIG_IS_ENABLED(PINCTRL_FULL)
/**
* pinctrl_config_one() - apply pinctrl settings for a single node
@@ -149,6 +127,9 @@ static int pinconfig_post_bind(struct udevice *dev)
ofnode_get_property(node, "compatible", &ret);
if (ret >= 0)
continue;
+ /* If this node has "gpio-controller" property, skip */
+ if (ofnode_read_bool(node, "gpio-controller"))
+ continue;
if (ret != -FDT_ERR_NOTFOUND)
return ret;
@@ -201,11 +182,14 @@ static int pinctrl_select_state_simple(struct udevice *dev)
int ret;
/*
- * For simplicity, assume the first device of PINCTRL uclass
- * is the correct one. This is most likely OK as there is
- * usually only one pinctrl device on the system.
+ * For most system, there is only one pincontroller device. But in
+ * case of multiple pincontroller devices, probe the one with sequence
+ * number 0 (defined by alias) to avoid race condition.
*/
- ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
+ ret = uclass_get_device_by_seq(UCLASS_PINCTRL, 0, &pctldev);
+ if (ret)
+ /* if not found, get the first one */
+ ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
if (ret)
return ret;
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c
index 34506402ac..3fb39b9952 100644
--- a/drivers/sysreset/sysreset_syscon.c
+++ b/drivers/sysreset/sysreset_syscon.c
@@ -36,20 +36,9 @@ static struct sysreset_ops syscon_reboot_ops = {
int syscon_reboot_probe(struct udevice *dev)
{
struct syscon_reboot_priv *priv = dev_get_priv(dev);
- int err;
- u32 phandle;
- ofnode node;
- err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle);
- if (err)
- return err;
-
- node = ofnode_get_by_phandle(phandle);
- if (!ofnode_valid(node))
- return -EINVAL;
-
- priv->regmap = syscon_node_to_regmap(node);
- if (!priv->regmap) {
+ priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap");
+ if (IS_ERR(priv->regmap)) {
pr_err("unable to find regmap\n");
return -ENODEV;
}
diff --git a/dts/Kconfig b/dts/Kconfig
index a5f30c8fd0..c9ab66cccc 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -291,10 +291,10 @@ config SPL_MULTI_DTB_FIT_USER_DEF_ADDR
config OF_SPL_REMOVE_PROPS
string "List of device tree properties to drop for SPL"
depends on SPL_OF_CONTROL
- default "interrupt-parent" if SPL_PINCTRL && SPL_CLK
- default "clocks clock-names interrupt-parent" if SPL_PINCTRL
- default "pinctrl-0 pinctrl-names interrupt-parent" if SPL_CLK
- default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent"
+ default "interrupt-parent interrupts" if SPL_PINCTRL && SPL_CLK
+ default "clocks clock-names interrupt-parent interrupts" if SPL_PINCTRL
+ default "pinctrl-0 pinctrl-names interrupt-parent interrupts" if SPL_CLK
+ default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts"
help
Since SPL normally runs in a reduced memory space, the device tree
is cut down to only what is needed to load and start U-Boot. Only
diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h
index ff2b82e7c2..63a7d55b88 100644
--- a/include/dm/pinctrl.h
+++ b/include/dm/pinctrl.h
@@ -355,18 +355,6 @@ int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph);
int pinctrl_decode_pin_config(const void *blob, int node);
/**
- * pinctrl_decode_pin_config_dm() - decode pin configuration flags
- *
- * This decodes some of the PIN_CONFIG values into flags, with each value
- * being (1 << pin_cfg). This does not support things with values like the
- * slew rate.
- *
- * @pinconfig: Pinconfig udevice
- * @return decoded flag value, or -ve on error
- */
-int pinctrl_decode_pin_config_dm(struct udevice *dev);
-
-/**
* pinctrl_get_gpio_mux() - get the mux value for a particular GPIO
*
* This allows the raw mux value for a GPIO to be obtained. It is
diff --git a/include/dm/util.h b/include/dm/util.h
index 9ff6531d1b..60d3b93dec 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -40,32 +40,6 @@ static inline void dm_dump_devres(void)
#endif
/**
- * Check if a dt node should be or was bound before relocation.
- *
- * Devicetree nodes can be marked as needed to be bound
- * in the loader stages via special devicetree properties.
- *
- * Before relocation this function can be used to check if nodes
- * are required in either SPL or TPL stages.
- *
- * After relocation and jumping into the real U-Boot binary
- * it is possible to determine if a node was bound in one of
- * SPL/TPL stages.
- *
- * There are 3 settings currently in use
- * -
- * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL
- * Existing platforms only use it to indicate nodes needed in
- * SPL. Should probably be replaced by u-boot,dm-spl for
- * existing platforms.
- * @blob: devicetree
- * @offset: node offset
- *
- * Returns true if node is needed in SPL/TL, false otherwise.
- */
-bool dm_fdt_pre_reloc(const void *blob, int offset);
-
-/**
* Check if an of node should be or was bound before relocation.
*
* Devicetree nodes can be marked as needed to be bound
diff --git a/include/fdtdec.h b/include/fdtdec.h
index ad00f79f20..266c58271f 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -23,15 +23,44 @@
*/
typedef phys_addr_t fdt_addr_t;
typedef phys_size_t fdt_size_t;
+
+static inline fdt32_t fdt_addr_unpack(fdt_addr_t addr, fdt32_t *upper)
+{
+ if (upper)
+#ifdef CONFIG_PHYS_64BIT
+ *upper = addr >> 32;
+#else
+ *upper = 0;
+#endif
+
+ return addr;
+}
+
+static inline fdt32_t fdt_size_unpack(fdt_size_t size, fdt32_t *upper)
+{
+ if (upper)
+#ifdef CONFIG_PHYS_64BIT
+ *upper = size >> 32;
+#else
+ *upper = 0;
+#endif
+
+ return size;
+}
+
#ifdef CONFIG_PHYS_64BIT
#define FDT_ADDR_T_NONE (-1U)
#define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
#define fdt_size_to_cpu(reg) be64_to_cpu(reg)
+#define cpu_to_fdt_addr(reg) cpu_to_be64(reg)
+#define cpu_to_fdt_size(reg) cpu_to_be64(reg)
typedef fdt64_t fdt_val_t;
#else
#define FDT_ADDR_T_NONE (-1U)
#define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
#define fdt_size_to_cpu(reg) be32_to_cpu(reg)
+#define cpu_to_fdt_addr(reg) cpu_to_be32(reg)
+#define cpu_to_fdt_size(reg) cpu_to_be32(reg)
typedef fdt32_t fdt_val_t;
#endif
@@ -992,6 +1021,146 @@ int fdtdec_setup_memory_banksize_fdt(const void *blob);
int fdtdec_setup_memory_banksize(void);
/**
+ * fdtdec_set_phandle() - sets the phandle of a given node
+ *
+ * @param blob FDT blob
+ * @param node offset in the FDT blob of the node whose phandle is to
+ * be set
+ * @param phandle phandle to set for the given node
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_phandle(void *blob, int node, uint32_t phandle);
+
+/**
+ * fdtdec_add_reserved_memory() - add or find a reserved-memory node
+ *
+ * If a reserved-memory node already exists for the given carveout, a phandle
+ * for that node will be returned. Otherwise a new node will be created and a
+ * phandle corresponding to it will be returned.
+ *
+ * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+ * for details on how to use reserved memory regions.
+ *
+ * As an example, consider the following code snippet:
+ *
+ * struct fdt_memory fb = {
+ * .start = 0x92cb3000,
+ * .end = 0x934b2fff,
+ * };
+ * uint32_t phandle;
+ *
+ * fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle);
+ *
+ * This results in the following subnode being added to the top-level
+ * /reserved-memory node:
+ *
+ * reserved-memory {
+ * #address-cells = <0x00000002>;
+ * #size-cells = <0x00000002>;
+ * ranges;
+ *
+ * framebuffer@92cb3000 {
+ * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
+ * phandle = <0x0000004d>;
+ * };
+ * };
+ *
+ * If the top-level /reserved-memory node does not exist, it will be created.
+ * The phandle returned from the function call can be used to reference this
+ * reserved memory region from other nodes.
+ *
+ * See fdtdec_set_carveout() for a more elaborate example.
+ *
+ * @param blob FDT blob
+ * @param basename base name of the node to create
+ * @param carveout information about the carveout region
+ * @param phandlep return location for the phandle of the carveout region
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_add_reserved_memory(void *blob, const char *basename,
+ const struct fdt_memory *carveout,
+ uint32_t *phandlep);
+
+/**
+ * fdtdec_get_carveout() - reads a carveout from an FDT
+ *
+ * Reads information about a carveout region from an FDT. The carveout is a
+ * referenced by its phandle that is read from a given property in a given
+ * node.
+ *
+ * @param blob FDT blob
+ * @param node name of a node
+ * @param name name of the property in the given node that contains
+ * the phandle for the carveout
+ * @param index index of the phandle for which to read the carveout
+ * @param carveout return location for the carveout information
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+ unsigned int index, struct fdt_memory *carveout);
+
+/**
+ * fdtdec_set_carveout() - sets a carveout region for a given node
+ *
+ * Sets a carveout region for a given node. If a reserved-memory node already
+ * exists for the carveout, the phandle for that node will be reused. If no
+ * such node exists, a new one will be created and a phandle to it stored in
+ * a specified property of the given node.
+ *
+ * As an example, consider the following code snippet:
+ *
+ * const char *node = "/host1x@50000000/dc@54240000";
+ * struct fdt_memory fb = {
+ * .start = 0x92cb3000,
+ * .end = 0x934b2fff,
+ * };
+ *
+ * fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb);
+ *
+ * dc@54200000 is a display controller and was set up by the bootloader to
+ * scan out the framebuffer specified by "fb". This would cause the following
+ * reserved memory region to be added:
+ *
+ * reserved-memory {
+ * #address-cells = <0x00000002>;
+ * #size-cells = <0x00000002>;
+ * ranges;
+ *
+ * framebuffer@92cb3000 {
+ * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
+ * phandle = <0x0000004d>;
+ * };
+ * };
+ *
+ * A "memory-region" property will also be added to the node referenced by the
+ * offset parameter.
+ *
+ * host1x@50000000 {
+ * ...
+ *
+ * dc@54240000 {
+ * ...
+ * memory-region = <0x0000004d>;
+ * ...
+ * };
+ *
+ * ...
+ * };
+ *
+ * @param blob FDT blob
+ * @param node name of the node to add the carveout to
+ * @param prop_name name of the property in which to store the phandle of
+ * the carveout
+ * @param index index of the phandle to store
+ * @param name base name of the reserved-memory node to create
+ * @param carveout information about the carveout to add
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+ unsigned int index, const char *name,
+ const struct fdt_memory *carveout);
+
+/**
* Set up the device tree ready for use
*/
int fdtdec_setup(void);
diff --git a/lib/Kconfig b/lib/Kconfig
index 8fe5d85a05..2120216593 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -436,4 +436,8 @@ source lib/efi/Kconfig
source lib/efi_loader/Kconfig
source lib/optee/Kconfig
+config TEST_FDTDEC
+ bool "enable fdtdec test"
+ depends on OF_LIBFDT
+
endmenu
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index a51dc5e986..efec3c2717 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1261,6 +1261,231 @@ __weak void *board_fdt_blob_setup(void)
}
#endif
+int fdtdec_set_phandle(void *blob, int node, uint32_t phandle)
+{
+ fdt32_t value = cpu_to_fdt32(phandle);
+
+ return fdt_setprop(blob, node, "phandle", &value, sizeof(value));
+}
+
+static int fdtdec_init_reserved_memory(void *blob)
+{
+ int na, ns, node, err;
+ fdt32_t value;
+
+ /* inherit #address-cells and #size-cells from the root node */
+ na = fdt_address_cells(blob, 0);
+ ns = fdt_size_cells(blob, 0);
+
+ node = fdt_add_subnode(blob, 0, "reserved-memory");
+ if (node < 0)
+ return node;
+
+ err = fdt_setprop(blob, node, "ranges", NULL, 0);
+ if (err < 0)
+ return err;
+
+ value = cpu_to_fdt32(ns);
+
+ err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value));
+ if (err < 0)
+ return err;
+
+ value = cpu_to_fdt32(na);
+
+ err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value));
+ if (err < 0)
+ return err;
+
+ return node;
+}
+
+int fdtdec_add_reserved_memory(void *blob, const char *basename,
+ const struct fdt_memory *carveout,
+ uint32_t *phandlep)
+{
+ fdt32_t cells[4] = {}, *ptr = cells;
+ uint32_t upper, lower, phandle;
+ int parent, node, na, ns, err;
+ char name[64];
+
+ /* create an empty /reserved-memory node if one doesn't exist */
+ parent = fdt_path_offset(blob, "/reserved-memory");
+ if (parent < 0) {
+ parent = fdtdec_init_reserved_memory(blob);
+ if (parent < 0)
+ return parent;
+ }
+
+ /* only 1 or 2 #address-cells and #size-cells are supported */
+ na = fdt_address_cells(blob, parent);
+ if (na < 1 || na > 2)
+ return -FDT_ERR_BADNCELLS;
+
+ ns = fdt_size_cells(blob, parent);
+ if (ns < 1 || ns > 2)
+ return -FDT_ERR_BADNCELLS;
+
+ /* find a matching node and return the phandle to that */
+ fdt_for_each_subnode(node, blob, parent) {
+ const char *name = fdt_get_name(blob, node, NULL);
+ phys_addr_t addr, size;
+
+ addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+ if (addr == FDT_ADDR_T_NONE) {
+ debug("failed to read address/size for %s\n", name);
+ continue;
+ }
+
+ if (addr == carveout->start && (addr + size) == carveout->end) {
+ *phandlep = fdt_get_phandle(blob, node);
+ return 0;
+ }
+ }
+
+ /*
+ * Unpack the start address and generate the name of the new node
+ * base on the basename and the unit-address.
+ */
+ lower = fdt_addr_unpack(carveout->start, &upper);
+
+ if (na > 1 && upper > 0)
+ snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+ lower);
+ else {
+ if (upper > 0) {
+ debug("address %08x:%08x exceeds addressable space\n",
+ upper, lower);
+ return -FDT_ERR_BADVALUE;
+ }
+
+ snprintf(name, sizeof(name), "%s@%x", basename, lower);
+ }
+
+ node = fdt_add_subnode(blob, parent, name);
+ if (node < 0)
+ return node;
+
+ err = fdt_generate_phandle(blob, &phandle);
+ if (err < 0)
+ return err;
+
+ err = fdtdec_set_phandle(blob, node, phandle);
+ if (err < 0)
+ return err;
+
+ /* store one or two address cells */
+ if (na > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ /* store one or two size cells */
+ lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper);
+
+ if (ns > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells));
+ if (err < 0)
+ return err;
+
+ /* return the phandle for the new node for the caller to use */
+ if (phandlep)
+ *phandlep = phandle;
+
+ return 0;
+}
+
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+ unsigned int index, struct fdt_memory *carveout)
+{
+ const fdt32_t *prop;
+ uint32_t phandle;
+ int offset, len;
+ fdt_size_t size;
+
+ offset = fdt_path_offset(blob, node);
+ if (offset < 0)
+ return offset;
+
+ prop = fdt_getprop(blob, offset, name, &len);
+ if (!prop) {
+ debug("failed to get %s for %s\n", name, node);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((len % sizeof(phandle)) != 0) {
+ debug("invalid phandle property\n");
+ return -FDT_ERR_BADPHANDLE;
+ }
+
+ if (len < (sizeof(phandle) * (index + 1))) {
+ debug("invalid phandle index\n");
+ return -FDT_ERR_BADPHANDLE;
+ }
+
+ phandle = fdt32_to_cpu(prop[index]);
+
+ offset = fdt_node_offset_by_phandle(blob, phandle);
+ if (offset < 0) {
+ debug("failed to find node for phandle %u\n", phandle);
+ return offset;
+ }
+
+ carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset,
+ "reg", 0, &size,
+ true);
+ if (carveout->start == FDT_ADDR_T_NONE) {
+ debug("failed to read address/size from \"reg\" property\n");
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ carveout->end = carveout->start + size - 1;
+
+ return 0;
+}
+
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+ unsigned int index, const char *name,
+ const struct fdt_memory *carveout)
+{
+ uint32_t phandle;
+ int err, offset;
+ fdt32_t value;
+
+ /* XXX implement support for multiple phandles */
+ if (index > 0) {
+ debug("invalid index %u\n", index);
+ return -FDT_ERR_BADOFFSET;
+ }
+
+ err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
+ if (err < 0) {
+ debug("failed to add reserved memory: %d\n", err);
+ return err;
+ }
+
+ offset = fdt_path_offset(blob, node);
+ if (offset < 0) {
+ debug("failed to find offset for node %s: %d\n", node, offset);
+ return offset;
+ }
+
+ value = cpu_to_fdt32(phandle);
+
+ err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+ if (err < 0) {
+ debug("failed to set %s property for node %s: %d\n", prop_name,
+ node, err);
+ return err;
+ }
+
+ return 0;
+}
+
int fdtdec_setup(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c
index a82e27de94..f6defe16c5 100644
--- a/lib/fdtdec_test.c
+++ b/lib/fdtdec_test.c
@@ -15,48 +15,28 @@
/* The size of our test fdt blob */
#define FDT_SIZE (16 * 1024)
-/**
- * Check if an operation failed, and if so, print an error
- *
- * @param oper_name Name of operation
- * @param err Error code to check
- *
- * @return 0 if ok, -1 if there was an error
- */
-static int fdt_checkerr(const char *oper_name, int err)
-{
- if (err) {
- printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err));
- return -1;
- }
+#define CHECK(op) ({ \
+ int err = op; \
+ if (err < 0) { \
+ printf("%s: %s: %s\n", __func__, #op, \
+ fdt_strerror(err)); \
+ return err; \
+ } \
+ \
+ err; \
+ })
- return 0;
-}
+#define CHECKVAL(op, expected) ({ \
+ int err = op; \
+ if (err != expected) { \
+ printf("%s: %s: expected %d, but returned %d\n",\
+ __func__, #op, expected, err); \
+ return err; \
+ } \
+ \
+ err; \
+ })
-/**
- * Check the result of an operation and if incorrect, print an error
- *
- * @param oper_name Name of operation
- * @param expected Expected value
- * @param value Actual value
- *
- * @return 0 if ok, -1 if there was an error
- */
-static int checkval(const char *oper_name, int expected, int value)
-{
- if (expected != value) {
- printf("%s: %s: expected %d, but returned %d\n", __func__,
- oper_name, expected, value);
- return -1;
- }
-
- return 0;
-}
-
-#define CHECK(op) if (fdt_checkerr(#op, op)) return -1
-#define CHECKVAL(op, expected) \
- if (checkval(#op, expected, op)) \
- return -1
#define CHECKOK(op) CHECKVAL(op, 0)
/* maximum number of nodes / aliases to generate */
@@ -79,7 +59,9 @@ static int make_fdt(void *fdt, int size, const char *aliases,
{
char name[20], value[20];
const char *s;
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
int fd;
+#endif
CHECK(fdt_create(fdt, size));
CHECK(fdt_finish_reservemap(fdt));
@@ -136,7 +118,7 @@ static int run_test(const char *aliases, const char *nodes, const char *expect)
CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0);
CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c",
COMPAT_UNKNOWN,
- list, ARRAY_SIZE(list)), strlen(expect));
+ list, ARRAY_SIZE(list)), (int)strlen(expect));
/* Check we got the right ones */
for (i = 0, s = expect; *s; s++, i++) {
@@ -159,6 +141,156 @@ static int run_test(const char *aliases, const char *nodes, const char *expect)
return 0;
}
+static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns)
+{
+ const char *basename = "/display";
+ struct fdt_memory carveout = {
+#ifdef CONFIG_PHYS_64BIT
+ .start = 0x180000000,
+ .end = 0x18fffffff,
+#else
+ .start = 0x80000000,
+ .end = 0x8fffffff,
+#endif
+ };
+ fdt32_t cells[4], *ptr = cells;
+ uint32_t upper, lower;
+ char name[32];
+ int offset;
+
+ /* store one or two address cells */
+ lower = fdt_addr_unpack(carveout.start, &upper);
+
+ if (na > 1 && upper > 0)
+ snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+ lower);
+ else
+ snprintf(name, sizeof(name), "%s@%x", basename, lower);
+
+ if (na > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ /* store one or two size cells */
+ lower = fdt_size_unpack(carveout.end - carveout.start + 1, &upper);
+
+ if (ns > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ offset = CHECK(fdt_add_subnode(fdt, 0, name + 1));
+ CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells)));
+
+ return fdtdec_set_carveout(fdt, name, "memory-region", 0,
+ "framebuffer", &carveout);
+}
+
+static int check_fdt_carveout(void *fdt, uint32_t address_cells,
+ uint32_t size_cells)
+{
+#ifdef CONFIG_PHYS_64BIT
+ const char *name = "/display@1,80000000";
+ const struct fdt_memory expected = {
+ .start = 0x180000000,
+ .end = 0x18fffffff,
+ };
+#else
+ const char *name = "/display@80000000";
+ const struct fdt_memory expected = {
+ .start = 0x80000000,
+ .end = 0x8fffffff,
+ };
+#endif
+ struct fdt_memory carveout;
+
+ printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start,
+ &expected.end, address_cells, size_cells);
+
+ CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout));
+
+ if ((carveout.start != expected.start) ||
+ (carveout.end != expected.end)) {
+ printf("carveout: %pap-%pap, expected %pap-%pap\n",
+ &carveout.start, &carveout.end,
+ &expected.start, &expected.end);
+ return 1;
+ }
+
+ printf("pass\n");
+ return 0;
+}
+
+static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells,
+ uint32_t size_cells)
+{
+ fdt32_t na = cpu_to_fdt32(address_cells);
+ fdt32_t ns = cpu_to_fdt32(size_cells);
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ char filename[512];
+ int fd;
+#endif
+ int err;
+
+ CHECK(fdt_create(fdt, size));
+ CHECK(fdt_finish_reservemap(fdt));
+ CHECK(fdt_begin_node(fdt, ""));
+ CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na)));
+ CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns)));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_finish(fdt));
+ CHECK(fdt_pack(fdt));
+
+ CHECK(fdt_open_into(fdt, fdt, FDT_SIZE));
+
+ err = make_fdt_carveout_device(fdt, address_cells, size_cells);
+
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb",
+ address_cells, size_cells);
+
+ fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY);
+ if (fd < 0) {
+ printf("could not open .dtb file to write\n");
+ goto out;
+ }
+
+ os_write(fd, fdt, size);
+ os_close(fd);
+
+out:
+#endif
+ return err;
+}
+
+static int check_carveout(void)
+{
+ void *fdt;
+
+ fdt = malloc(FDT_SIZE);
+ if (!fdt) {
+ printf("%s: out of memory\n", __func__);
+ return 1;
+ }
+
+#ifndef CONFIG_PHYS_64BIT
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0);
+ CHECKOK(check_fdt_carveout(fdt, 1, 1));
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0);
+ CHECKOK(check_fdt_carveout(fdt, 1, 2));
+#else
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE);
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE);
+#endif
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0);
+ CHECKOK(check_fdt_carveout(fdt, 2, 1));
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0);
+ CHECKOK(check_fdt_carveout(fdt, 2, 2));
+
+ return 0;
+}
+
static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
@@ -200,6 +332,8 @@ static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc,
CHECKOK(run_test("2a 1a 0a", "a", " a"));
CHECKOK(run_test("0a 1a 2a", "a", "a"));
+ CHECKOK(check_carveout());
+
printf("Test passed\n");
return 0;
}
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index b6ca4e0b0c..693de9aa5a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -73,6 +73,37 @@ uint32_t fdt_get_max_phandle(const void *fdt)
return 0;
}
+int fdt_generate_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 (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ return 0;
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 1b6c154d8d..2403825dc9 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -457,7 +457,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return device_path_string(buf, end, ptr, field_width,
precision, flags);
#endif
-#ifdef CONFIG_CMD_NET
case 'a':
flags |= SPECIAL | ZEROPAD;
@@ -469,6 +468,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
break;
}
break;
+#ifdef CONFIG_CMD_NET
case 'm':
flags |= SPECIAL;
/* Fallthrough */
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 70de9bb13a..de67677f61 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -525,4 +525,5 @@ quiet_cmd_fdtgrep = FDTGREP $@
cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
-n /chosen -n /config -O dtb | \
$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
+ -P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \
$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index dfb3236da3..dc499884e4 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -115,6 +115,37 @@ uint32_t fdt_get_max_phandle(const void *fdt)
return 0;
}
+int fdt_generate_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 (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ return 0;
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index fd73688f9e..cf86ddba88 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -139,6 +139,10 @@
#define FDT_ERR_MAX 17
+/* 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) */
/**********************************************************************/
@@ -314,6 +318,21 @@ const char *fdt_string(const void *fdt, int stroffset);
uint32_t fdt_get_max_phandle(const void *fdt);
/**
+ * 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.
+ *
+ * Returns:
+ * 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
*
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index bd24746287..3ff9e28630 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -52,6 +52,7 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/test/dm/syscon.c b/test/dm/syscon.c
index a294dda02e..0ff9da7ec6 100644
--- a/test/dm/syscon.c
+++ b/test/dm/syscon.c
@@ -67,6 +67,13 @@ static int dm_test_syscon_by_phandle(struct unit_test_state *uts)
ut_assert(!IS_ERR(map));
ut_asserteq(4, map->range_count);
+ ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev,
+ "third-syscon"));
+ map = syscon_regmap_lookup_by_phandle(dev, "third-syscon");
+ ut_assert(map);
+ ut_assert(!IS_ERR(map));
+ ut_asserteq(4, map->range_count);
+
ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present")));
return 0;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 2899adff81..d1e1a6743d 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -403,14 +403,21 @@ int main(int argc, char **argv)
exit (EXIT_FAILURE);
}
- /*
- * scan through mkimage registry for all supported image types
- * and verify the input image file header for match
- * Print the image information for matched image type
- * Returns the error code if not matched
- */
- retval = imagetool_verify_print_header_by_type(ptr, &sbuf,
- tparams, &params);
+ if (params.fflag) {
+ /*
+ * Verifies the header format based on the expected header for image
+ * type in tparams
+ */
+ retval = imagetool_verify_print_header_by_type(ptr, &sbuf,
+ tparams, &params);
+ } else {
+ /**
+ * When listing the image, we are not given the image type. Simply check all
+ * image types to find one that matches our header
+ */
+ retval = imagetool_verify_print_header(ptr, &sbuf,
+ tparams, &params);
+ }
(void) munmap((void *)ptr, sbuf.st_size);
(void) close (ifd);