Browse Source

Merge tag 'pull-12apr19' of git://git.denx.de/u-boot-dm

fdtdec tests and improvements for carve-outs
pinctrl race-condition fix
various other fixes in sandbox, sound, mkimage, etc.
Tom Rini 5 years ago
parent
commit
cf5eebeb18

+ 136 - 0
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>;
+		/* ... */
+	};
+};

+ 2 - 1
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

+ 2 - 2
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;
 }

+ 6 - 6
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__ */
 

+ 1 - 1
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;
 }
 

+ 0 - 6
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);

+ 1 - 0
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

+ 1 - 0
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

+ 117 - 179
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

+ 239 - 0
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.

+ 2 - 1
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,

+ 1 - 1
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

+ 10 - 11
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)

+ 59 - 24
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;
 }

+ 8 - 32
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
 }

+ 10 - 26
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;
 

+ 2 - 13
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;
 	}

+ 4 - 4
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

+ 0 - 12
include/dm/pinctrl.h

@@ -354,18 +354,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
  *

+ 0 - 26
include/dm/util.h

@@ -39,32 +39,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.
  *

+ 169 - 0
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
 
@@ -991,6 +1020,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
  */

+ 4 - 0
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

+ 225 - 0
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)

+ 175 - 41
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;
 }

+ 31 - 0
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);

+ 1 - 1
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 */

+ 1 - 0
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)))

+ 31 - 0
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);

+ 19 - 0
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)                */
 /**********************************************************************/
@@ -313,6 +317,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

+ 1 - 0
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>

+ 7 - 0
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;

+ 15 - 8
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);