fdtdec tests and improvements for carve-outs

pinctrl race-condition fix
 various other fixes in sandbox, sound, mkimage, etc.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAlyxBfcACgkQfxc6PpAI
 reYtsgf8DSi0h6bNmoPGA8q/aRTQii2x6TheT+AonvND4Kt5ycyw5Otjn3n7O13G
 ubDvBn3Ix5znRaj6nSip7zO1M59dNB19Qk5i+ad21w3rx2V8HTWcLYMwUmC2DPZU
 qMaOpIeEWYKuCDFRhpw/b6yF1rtq4lMxWTrSlB+ewntmrKV+Ymk0UWYSCfNMmZ8F
 cLSd/wFWoTxysZLT4t/5jbNIPU8XaO0hYH0C9Y/tsK80bCpdjkTMNQuO7/qlgUb9
 E7BCf1HXuMqWTZuqub9hu1y24PYufNSHziK1R+lNqm+yW3MxJGihP5OsCfVoHDgu
 FU+QIKeBo64R3eH1VSrAh8pLp143bg==
 =4/BU
 -----END PGP SIGNATURE-----

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.
This commit is contained in:
Tom Rini 2019-04-13 08:27:35 -04:00
commit cf5eebeb18
32 changed files with 1305 additions and 420 deletions

View File

@ -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>;
/* ... */
};
};

View File

@ -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

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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.
- 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.
For all of these the standard U-Boot build instructions apply. For example on
ARM:
U-Boot with Chromium OS verified boot
-------------------------------------
sudo apt install gcc-arm-linux-gnueabi
mkdir b
make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
To obtain:
You can obtain the vbutil_kernel utility here:
git clone https://github.com/sglass68/u-boot.git
cd u-boot
git checkout cros-master
https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U
To build for sandbox:
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
Replace sandbox with another supported target.
This produces $UB/image.bin which contains the firmware binaries in a SPI
flash image.
To run on sandbox:
$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
Snow (Samsung ARM Chromebook)
-----------------------------
Sandbox
-------
See here:
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.
https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook
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.
It is possible to run with debugging on, e.g.
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.
Nyan-big
Samus
-----
Basic support is available for samus, using the chromeos_samus target. If you
have an em100, use:
sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
to write the image and then boot samus (Power-Refresh).
Boot flow
---------
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.
More details are available here:
https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery
New uclasses
------------
Several uclasses are provided in cros/:
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
The existing UCLASS_CROS_EC is also used.
Commands
--------
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
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.
1. Build U-Boot
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().
mkdir b
make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
Config options
--------------
2. Select a .its file
The main option is CONFIG_CHROMEOS, which enables a wide array of other options
so that the required features are present.
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.
Device-tree config
------------------
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.
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
Porting to other hardware
-------------------------
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.
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
Tests
-----
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.
5. Write U-Boot to the SD card
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.
sudo dd if=u-boot.kpart of=/dev/sdc1; sync
TO DO
-----
6. Start it up
- Support for booting from coreboot (patches expected March 2019)
- Support for booting from an ARM board, e.g. bob
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.
Simon Glass
sjg@chromium.org
7 October 2018

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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;
struct udevice *dev;
struct regmap *r;
if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
return syscon_get_regmap(dev);
if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
if (syscon_probe_by_ofnode(node, &dev))
return ERR_PTR(-ENODEV);
if (!ofnode_device_is_compatible(node, "syscon"))
return ERR_PTR(-EINVAL);
r = syscon_get_regmap(dev);
if (!r) {
dev_dbg(dev, "unable to find regmap\n");
return ERR_PTR(-ENODEV);
}
/* 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)
return ERR_PTR(ret);
ret = device_probe(dev);
if (ret)
return ERR_PTR(ret);
return syscon_get_regmap(dev);
return r;
}

View File

@ -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
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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
*

View File

@ -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.
*

View File

@ -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
*/

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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)))

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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);