mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
of-platdata and dtoc improvements
sandbox SPL tests binman support for compressed sections -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAl+cXssRHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIreaYuAgAjG05oxt8a4DXhdzGuXBCbehZv2T7X5Lg 2+i9uwyg3MkKWp0Spm2J+0flWs+1Bynw335hgNVgq+bh29sajOQz2BtgfDKFY+Aw D+D16YBEiEuIbIXLzSsv+ct1va83A3JmlxxoaJ7+ZvoN/5Z3ZvJIZ7F4AzmwlAFT 5pOFgDEfVM4MYFU4R2wZAaJMnYKQrqR5Tvrxecc6OkhvWIgq7j3elE4xOuh2hL/L Bz/KM+4Eq+EUALG+quyEzd+gDKoPY2rNOojxS/lg7PRsN6S8engwE+LkcAkMaNG3 uDVrTYsA8lCJJwso0in25fUy8sEYWaCSVr/82xfRJMWksPajubem7w== =9u1O -----END PGP SIGNATURE----- Merge tag 'dm-pull-30oct20' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm of-platdata and dtoc improvements sandbox SPL tests binman support for compressed sections
This commit is contained in:
commit
63d4607e03
89 changed files with 1861 additions and 502 deletions
|
@ -182,7 +182,7 @@ jobs:
|
||||||
OVERRIDE: "-O clang-10"
|
OVERRIDE: "-O clang-10"
|
||||||
sandbox_spl:
|
sandbox_spl:
|
||||||
TEST_PY_BD: "sandbox_spl"
|
TEST_PY_BD: "sandbox_spl"
|
||||||
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff"
|
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
|
||||||
sandbox_flattree:
|
sandbox_flattree:
|
||||||
TEST_PY_BD: "sandbox_flattree"
|
TEST_PY_BD: "sandbox_flattree"
|
||||||
evb_ast2500:
|
evb_ast2500:
|
||||||
|
|
|
@ -198,7 +198,7 @@ sandbox_spl test.py:
|
||||||
tags: [ 'all' ]
|
tags: [ 'all' ]
|
||||||
variables:
|
variables:
|
||||||
TEST_PY_BD: "sandbox_spl"
|
TEST_PY_BD: "sandbox_spl"
|
||||||
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff"
|
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
|
||||||
<<: *buildman_and_testpy_dfn
|
<<: *buildman_and_testpy_dfn
|
||||||
|
|
||||||
evb-ast2500 test.py:
|
evb-ast2500 test.py:
|
||||||
|
|
|
@ -512,7 +512,7 @@ matrix:
|
||||||
- name: "test/py sandbox_spl"
|
- name: "test/py sandbox_spl"
|
||||||
env:
|
env:
|
||||||
- TEST_PY_BD="sandbox_spl"
|
- TEST_PY_BD="sandbox_spl"
|
||||||
TEST_PY_TEST_SPEC="test_ofplatdata or test_handoff"
|
TEST_PY_TEST_SPEC="test_ofplatdata or test_handoff or test_spl"
|
||||||
TOOLCHAIN="i386"
|
TOOLCHAIN="i386"
|
||||||
TEST_PY_TOOLS="yes"
|
TEST_PY_TOOLS="yes"
|
||||||
- name: "test/py sandbox_flattree"
|
- name: "test/py sandbox_flattree"
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -807,7 +807,7 @@ libs-$(CONFIG_API) += api/
|
||||||
ifdef CONFIG_POST
|
ifdef CONFIG_POST
|
||||||
libs-y += post/
|
libs-y += post/
|
||||||
endif
|
endif
|
||||||
libs-$(CONFIG_UNIT_TEST) += test/ test/dm/
|
libs-$(CONFIG_UNIT_TEST) += test/
|
||||||
libs-$(CONFIG_UT_ENV) += test/env/
|
libs-$(CONFIG_UT_ENV) += test/env/
|
||||||
libs-$(CONFIG_UT_OPTEE) += test/optee/
|
libs-$(CONFIG_UT_OPTEE) += test/optee/
|
||||||
libs-$(CONFIG_UT_OVERLAY) += test/overlay/
|
libs-$(CONFIG_UT_OVERLAY) += test/overlay/
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct scu_regs {
|
||||||
u32 fpga_rev;
|
u32 fpga_rev;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_IMX_THERMAL)
|
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_IMX_THERMAL)
|
||||||
static const struct imx_thermal_plat imx6_thermal_plat = {
|
static const struct imx_thermal_plat imx6_thermal_plat = {
|
||||||
.regs = (void *)ANATOP_BASE_ADDR,
|
.regs = (void *)ANATOP_BASE_ADDR,
|
||||||
.fuse_bank = 1,
|
.fuse_bank = 1,
|
||||||
|
|
|
@ -127,7 +127,8 @@ int sandbox_sdl_init_display(int width, int height, int log2_bpp,
|
||||||
sdl.pitch = sdl.width * sdl.depth / 8;
|
sdl.pitch = sdl.width * sdl.depth / 8;
|
||||||
SDL_Window *screen = SDL_CreateWindow("U-Boot", SDL_WINDOWPOS_UNDEFINED,
|
SDL_Window *screen = SDL_CreateWindow("U-Boot", SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
sdl.vis_width, sdl.vis_height, 0);
|
sdl.vis_width, sdl.vis_height,
|
||||||
|
SDL_WINDOW_RESIZABLE);
|
||||||
if (!screen) {
|
if (!screen) {
|
||||||
printf("Unable to initialise SDL screen: %s\n",
|
printf("Unable to initialise SDL screen: %s\n",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <spl.h>
|
#include <spl.h>
|
||||||
#include <asm/spl.h>
|
#include <asm/spl.h>
|
||||||
#include <asm/state.h>
|
#include <asm/state.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
@ -53,19 +54,14 @@ SPL_LOAD_IMAGE_METHOD("sandbox", 9, BOOT_DEVICE_BOARD, spl_board_load_image);
|
||||||
void spl_board_init(void)
|
void spl_board_init(void)
|
||||||
{
|
{
|
||||||
struct sandbox_state *state = state_get_current();
|
struct sandbox_state *state = state_get_current();
|
||||||
struct udevice *dev;
|
|
||||||
|
|
||||||
preloader_console_init();
|
preloader_console_init();
|
||||||
if (state->show_of_platdata) {
|
|
||||||
/*
|
if (state->run_unittests) {
|
||||||
* Scan all the devices so that we can output their platform
|
int ret;
|
||||||
* data. See sandbox_spl_probe().
|
|
||||||
*/
|
ret = dm_test_main(state->select_unittests);
|
||||||
printf("Scanning misc devices\n");
|
/* continue execution into U-Boot */
|
||||||
for (uclass_first_device(UCLASS_MISC, &dev);
|
|
||||||
dev;
|
|
||||||
uclass_next_device(&dev))
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,14 +365,23 @@ static int sandbox_cmdline_cb_log_level(struct sandbox_state *state,
|
||||||
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
|
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
|
||||||
"Set log level (0=panic, 7=debug)");
|
"Set log level (0=panic, 7=debug)");
|
||||||
|
|
||||||
static int sandbox_cmdline_cb_show_of_platdata(struct sandbox_state *state,
|
static int sandbox_cmdline_cb_unittests(struct sandbox_state *state,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
{
|
{
|
||||||
state->show_of_platdata = true;
|
state->run_unittests = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
SANDBOX_CMDLINE_OPT(show_of_platdata, 0, "Show of-platdata in SPL");
|
SANDBOX_CMDLINE_OPT_SHORT(unittests, 'u', 0, "Run unit tests");
|
||||||
|
|
||||||
|
static int sandbox_cmdline_cb_select_unittests(struct sandbox_state *state,
|
||||||
|
const char *arg)
|
||||||
|
{
|
||||||
|
state->select_unittests = arg;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SANDBOX_CMDLINE_OPT_SHORT(select_unittests, 'k', 1, "Select unit tests to run");
|
||||||
|
|
||||||
static void setup_ram_buf(struct sandbox_state *state)
|
static void setup_ram_buf(struct sandbox_state *state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_i2c0>;
|
pinctrl-0 = <&pinctrl_i2c0>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
pcic: pci@0 {
|
pcic: pci@0 {
|
||||||
|
|
|
@ -29,6 +29,32 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clk_fixed: clk-fixed {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <1234>;
|
||||||
|
};
|
||||||
|
|
||||||
|
clk_sandbox: clk-sbox {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "sandbox,clk";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
assigned-clocks = <&clk_sandbox 3>;
|
||||||
|
assigned-clock-rates = <321>;
|
||||||
|
};
|
||||||
|
|
||||||
|
clk-test {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "sandbox,clk-test";
|
||||||
|
clocks = <&clk_fixed>,
|
||||||
|
<&clk_sandbox 1>,
|
||||||
|
<&clk_sandbox 0>,
|
||||||
|
<&clk_sandbox 3>,
|
||||||
|
<&clk_sandbox 2>;
|
||||||
|
clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
|
||||||
|
};
|
||||||
|
|
||||||
gpio_a: gpios@0 {
|
gpio_a: gpios@0 {
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -64,6 +90,7 @@
|
||||||
reg = <0x43>;
|
reg = <0x43>;
|
||||||
compatible = "sandbox-rtc";
|
compatible = "sandbox-rtc";
|
||||||
sandbox,emul = <&emul0>;
|
sandbox,emul = <&emul0>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
};
|
};
|
||||||
sandbox_pmic: sandbox_pmic {
|
sandbox_pmic: sandbox_pmic {
|
||||||
reg = <0x40>;
|
reg = <0x40>;
|
||||||
|
|
|
@ -90,8 +90,9 @@ struct sandbox_state {
|
||||||
bool skip_delays; /* Ignore any time delays (for test) */
|
bool skip_delays; /* Ignore any time delays (for test) */
|
||||||
bool show_test_output; /* Don't suppress stdout in tests */
|
bool show_test_output; /* Don't suppress stdout in tests */
|
||||||
int default_log_level; /* Default log level for sandbox */
|
int default_log_level; /* Default log level for sandbox */
|
||||||
bool show_of_platdata; /* Show of-platdata in SPL */
|
|
||||||
bool ram_buf_read; /* true if we read the RAM buffer */
|
bool ram_buf_read; /* true if we read the RAM buffer */
|
||||||
|
bool run_unittests; /* Run unit tests */
|
||||||
|
const char *select_unittests; /* Unit test to run */
|
||||||
|
|
||||||
/* Pointer to information for each SPI bus/cs */
|
/* Pointer to information for each SPI bus/cs */
|
||||||
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
|
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
|
||||||
|
|
|
@ -85,6 +85,8 @@ config APL_SPI_FLASH_BOOT
|
||||||
bool "Support booting with SPI-flash driver instead memory-mapped SPI"
|
bool "Support booting with SPI-flash driver instead memory-mapped SPI"
|
||||||
select TPL_SPI_FLASH_SUPPORT
|
select TPL_SPI_FLASH_SUPPORT
|
||||||
select TPL_SPI_SUPPORT
|
select TPL_SPI_SUPPORT
|
||||||
|
select TPL_DM_SPI
|
||||||
|
select TPL_DM_SPI_FLASH
|
||||||
help
|
help
|
||||||
This enables SPI and SPI flash in TPL. Without the this only
|
This enables SPI and SPI flash in TPL. Without the this only
|
||||||
available boot method is to use memory-mapped SPI. Since this is
|
available boot method is to use memory-mapped SPI. Since this is
|
||||||
|
|
|
@ -90,7 +90,8 @@ static int apl_flash_probe(struct udevice *dev)
|
||||||
*/
|
*/
|
||||||
static int apl_flash_bind(struct udevice *dev)
|
static int apl_flash_bind(struct udevice *dev)
|
||||||
{
|
{
|
||||||
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
if (CONFIG_IS_ENABLED(OF_PLATDATA) &&
|
||||||
|
!CONFIG_IS_ENABLED(OF_PLATDATA_PARENT)) {
|
||||||
struct dm_spi_slave_platdata *plat;
|
struct dm_spi_slave_platdata *plat;
|
||||||
struct udevice *spi;
|
struct udevice *spi;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -21,10 +21,12 @@
|
||||||
*/
|
*/
|
||||||
gd_t *gd;
|
gd_t *gd;
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
/* Add a simple GPIO device */
|
/* Add a simple GPIO device */
|
||||||
U_BOOT_DEVICE(gpio_sandbox) = {
|
U_BOOT_DEVICE(gpio_sandbox) = {
|
||||||
.name = "sandbox_gpio",
|
.name = "sandbox_gpio",
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
void flush_cache(unsigned long start, unsigned long size)
|
void flush_cache(unsigned long start, unsigned long size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -296,20 +296,21 @@ static int initr_noncached(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_OF_LIVE
|
|
||||||
static int initr_of_live(void)
|
static int initr_of_live(void)
|
||||||
{
|
{
|
||||||
int ret;
|
if (CONFIG_IS_ENABLED(OF_LIVE)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
bootstage_start(BOOTSTAGE_ID_ACCUM_OF_LIVE, "of_live");
|
bootstage_start(BOOTSTAGE_ID_ACCUM_OF_LIVE, "of_live");
|
||||||
ret = of_live_build(gd->fdt_blob, (struct device_node **)&gd->of_root);
|
ret = of_live_build(gd->fdt_blob,
|
||||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_OF_LIVE);
|
(struct device_node **)gd_of_root_ptr());
|
||||||
if (ret)
|
bootstage_accum(BOOTSTAGE_ID_ACCUM_OF_LIVE);
|
||||||
return ret;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_DM
|
#ifdef CONFIG_DM
|
||||||
static int initr_dm(void)
|
static int initr_dm(void)
|
||||||
|
@ -713,9 +714,7 @@ static init_fnc_t init_sequence_r[] = {
|
||||||
#ifdef CONFIG_SYS_NONCACHED_MEMORY
|
#ifdef CONFIG_SYS_NONCACHED_MEMORY
|
||||||
initr_noncached,
|
initr_noncached,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_OF_LIVE
|
|
||||||
initr_of_live,
|
initr_of_live,
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_DM
|
#ifdef CONFIG_DM
|
||||||
initr_dm,
|
initr_dm,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,11 +22,12 @@ CONFIG_BOOTSTAGE_STASH=y
|
||||||
CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
|
CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
|
||||||
CONFIG_CONSOLE_RECORD=y
|
CONFIG_CONSOLE_RECORD=y
|
||||||
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
||||||
CONFIG_SILENT_CONSOLE=y
|
|
||||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||||
CONFIG_HANDOFF=y
|
CONFIG_HANDOFF=y
|
||||||
CONFIG_SPL_BOARD_INIT=y
|
CONFIG_SPL_BOARD_INIT=y
|
||||||
CONFIG_SPL_ENV_SUPPORT=y
|
CONFIG_SPL_ENV_SUPPORT=y
|
||||||
|
CONFIG_SPL_I2C_SUPPORT=y
|
||||||
|
CONFIG_SPL_RTC_SUPPORT=y
|
||||||
CONFIG_CMD_CPU=y
|
CONFIG_CMD_CPU=y
|
||||||
CONFIG_CMD_LICENSE=y
|
CONFIG_CMD_LICENSE=y
|
||||||
CONFIG_CMD_BOOTZ=y
|
CONFIG_CMD_BOOTZ=y
|
||||||
|
@ -105,6 +106,7 @@ CONFIG_ADC_SANDBOX=y
|
||||||
CONFIG_AXI=y
|
CONFIG_AXI=y
|
||||||
CONFIG_AXI_SANDBOX=y
|
CONFIG_AXI_SANDBOX=y
|
||||||
CONFIG_CLK=y
|
CONFIG_CLK=y
|
||||||
|
CONFIG_SPL_CLK=y
|
||||||
CONFIG_CPU=y
|
CONFIG_CPU=y
|
||||||
CONFIG_DM_DEMO=y
|
CONFIG_DM_DEMO=y
|
||||||
CONFIG_DM_DEMO_SIMPLE=y
|
CONFIG_DM_DEMO_SIMPLE=y
|
||||||
|
@ -120,7 +122,6 @@ CONFIG_I2C_CROS_EC_LDO=y
|
||||||
CONFIG_DM_I2C_GPIO=y
|
CONFIG_DM_I2C_GPIO=y
|
||||||
CONFIG_SYS_I2C_SANDBOX=y
|
CONFIG_SYS_I2C_SANDBOX=y
|
||||||
CONFIG_I2C_MUX=y
|
CONFIG_I2C_MUX=y
|
||||||
CONFIG_SPL_I2C_MUX=y
|
|
||||||
CONFIG_I2C_ARB_GPIO_CHALLENGE=y
|
CONFIG_I2C_ARB_GPIO_CHALLENGE=y
|
||||||
CONFIG_CROS_EC_KEYB=y
|
CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_I8042_KEYB=y
|
CONFIG_I8042_KEYB=y
|
||||||
|
@ -187,6 +188,7 @@ CONFIG_REMOTEPROC_SANDBOX=y
|
||||||
CONFIG_DM_RESET=y
|
CONFIG_DM_RESET=y
|
||||||
CONFIG_SANDBOX_RESET=y
|
CONFIG_SANDBOX_RESET=y
|
||||||
CONFIG_DM_RTC=y
|
CONFIG_DM_RTC=y
|
||||||
|
CONFIG_SPL_DM_RTC=y
|
||||||
CONFIG_SANDBOX_SERIAL=y
|
CONFIG_SANDBOX_SERIAL=y
|
||||||
CONFIG_SOUND=y
|
CONFIG_SOUND=y
|
||||||
CONFIG_SOUND_SANDBOX=y
|
CONFIG_SOUND_SANDBOX=y
|
||||||
|
@ -221,5 +223,6 @@ CONFIG_TPM=y
|
||||||
CONFIG_LZ4=y
|
CONFIG_LZ4=y
|
||||||
CONFIG_ERRNO_STR=y
|
CONFIG_ERRNO_STR=y
|
||||||
CONFIG_UNIT_TEST=y
|
CONFIG_UNIT_TEST=y
|
||||||
|
CONFIG_SPL_UNIT_TEST=y
|
||||||
CONFIG_UT_TIME=y
|
CONFIG_UT_TIME=y
|
||||||
CONFIG_UT_DM=y
|
CONFIG_UT_DM=y
|
||||||
|
|
|
@ -66,12 +66,6 @@ strictly necessary. Notable problems include:
|
||||||
normally also supports device tree it must use #ifdef to separate
|
normally also supports device tree it must use #ifdef to separate
|
||||||
out this code, since the structures are only available in SPL.
|
out this code, since the structures are only available in SPL.
|
||||||
|
|
||||||
- Correct relations between nodes are not implemented. This means that
|
|
||||||
parent/child relations (like bus device iteration) do not work yet.
|
|
||||||
Some phandles (those that are recognised as such) are converted into
|
|
||||||
a pointer to struct driver_info. This pointer can be used to access
|
|
||||||
the referenced device.
|
|
||||||
|
|
||||||
|
|
||||||
How it works
|
How it works
|
||||||
------------
|
------------
|
||||||
|
@ -134,10 +128,14 @@ the following C struct declaration:
|
||||||
fdt32_t vmmc_supply;
|
fdt32_t vmmc_supply;
|
||||||
};
|
};
|
||||||
|
|
||||||
and the following device declaration:
|
and the following device declarations:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
|
/* Node /clock-controller@ff760000 index 0 */
|
||||||
|
...
|
||||||
|
|
||||||
|
/* Node /dwmmc@ff0c0000 index 2 */
|
||||||
static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
|
static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
|
||||||
.fifo_depth = 0x100,
|
.fifo_depth = 0x100,
|
||||||
.cap_sd_highspeed = true,
|
.cap_sd_highspeed = true,
|
||||||
|
@ -145,10 +143,10 @@ and the following device declaration:
|
||||||
.clock_freq_min_max = {0x61a80, 0x8f0d180},
|
.clock_freq_min_max = {0x61a80, 0x8f0d180},
|
||||||
.vmmc_supply = 0xb,
|
.vmmc_supply = 0xb,
|
||||||
.num_slots = 0x1,
|
.num_slots = 0x1,
|
||||||
.clocks = {{NULL, 456},
|
.clocks = {{0, 456},
|
||||||
{NULL, 68},
|
{0, 68},
|
||||||
{NULL, 114},
|
{0, 114},
|
||||||
{NULL, 118}},
|
{0, 118}},
|
||||||
.cap_mmc_highspeed = true,
|
.cap_mmc_highspeed = true,
|
||||||
.disable_wp = true,
|
.disable_wp = true,
|
||||||
.bus_width = 0x4,
|
.bus_width = 0x4,
|
||||||
|
@ -161,13 +159,10 @@ and the following device declaration:
|
||||||
.name = "rockchip_rk3288_dw_mshc",
|
.name = "rockchip_rk3288_dw_mshc",
|
||||||
.platdata = &dtv_dwmmc_at_ff0c0000,
|
.platdata = &dtv_dwmmc_at_ff0c0000,
|
||||||
.platdata_size = sizeof(dtv_dwmmc_at_ff0c0000),
|
.platdata_size = sizeof(dtv_dwmmc_at_ff0c0000),
|
||||||
|
.parent_idx = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
dtv_dwmmc_at_ff0c0000.clocks[0].node = DM_GET_DEVICE(clock_controller_at_ff760000);
|
|
||||||
dtv_dwmmc_at_ff0c0000.clocks[1].node = DM_GET_DEVICE(clock_controller_at_ff760000);
|
|
||||||
dtv_dwmmc_at_ff0c0000.clocks[2].node = DM_GET_DEVICE(clock_controller_at_ff760000);
|
|
||||||
dtv_dwmmc_at_ff0c0000.clocks[3].node = DM_GET_DEVICE(clock_controller_at_ff760000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
The device is then instantiated at run-time and the platform data can be
|
The device is then instantiated at run-time and the platform data can be
|
||||||
|
@ -193,6 +188,13 @@ In order to make this a bit more flexible U_BOOT_DRIVER_ALIAS macro can be
|
||||||
used to declare an alias for a driver name, typically a 'compatible' string.
|
used to declare an alias for a driver name, typically a 'compatible' string.
|
||||||
This macro produces no code, but it is by dtoc tool.
|
This macro produces no code, but it is by dtoc tool.
|
||||||
|
|
||||||
|
The parent_idx is the index of the parent driver_info structure within its
|
||||||
|
linker list (instantiated by the U_BOOT_DEVICE() macro). This is used to support
|
||||||
|
dev_get_parent(). The dm_populate_phandle_data() is included to allow for
|
||||||
|
fix-ups required by dtoc. It is not currently used. The values in 'clocks' are
|
||||||
|
the index of the driver_info for the target device followed by any phandle
|
||||||
|
arguments. This is used to support device_get_by_driver_info_idx().
|
||||||
|
|
||||||
During the build process dtoc parses both U_BOOT_DRIVER and U_BOOT_DRIVER_ALIAS
|
During the build process dtoc parses both U_BOOT_DRIVER and U_BOOT_DRIVER_ALIAS
|
||||||
to build a list of valid driver names and driver aliases. If the 'compatible'
|
to build a list of valid driver names and driver aliases. If the 'compatible'
|
||||||
string used for a device does not not match a valid driver name, it will be
|
string used for a device does not not match a valid driver name, it will be
|
||||||
|
@ -339,12 +341,7 @@ spl/dt-platdata.c. It additionally contains the definition of
|
||||||
dm_populate_phandle_data() which is responsible of filling the phandle
|
dm_populate_phandle_data() which is responsible of filling the phandle
|
||||||
information by adding references to U_BOOT_DEVICE by using DM_GET_DEVICE
|
information by adding references to U_BOOT_DEVICE by using DM_GET_DEVICE
|
||||||
|
|
||||||
The beginnings of a libfdt Python module are provided. So far this only
|
The pylibfdt Python module is used to access the devicetree.
|
||||||
implements a subset of the features.
|
|
||||||
|
|
||||||
The 'swig' tool is needed to build the libfdt Python module. If this is not
|
|
||||||
found then the Python model is not used and a fallback is used instead, which
|
|
||||||
makes use of fdtget.
|
|
||||||
|
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
|
@ -357,11 +354,10 @@ Future work
|
||||||
-----------
|
-----------
|
||||||
- Consider programmatically reading binding files instead of device tree
|
- Consider programmatically reading binding files instead of device tree
|
||||||
contents
|
contents
|
||||||
- Complete the phandle feature
|
|
||||||
- Move to using a full Python libfdt module
|
|
||||||
|
|
||||||
|
|
||||||
.. Simon Glass <sjg@chromium.org>
|
.. Simon Glass <sjg@chromium.org>
|
||||||
.. Google, Inc
|
.. Google, Inc
|
||||||
.. 6/6/16
|
.. 6/6/16
|
||||||
.. Updated Independence Day 2016
|
.. Updated Independence Day 2016
|
||||||
|
.. Updated 1st October 2020
|
||||||
|
|
|
@ -38,8 +38,7 @@ int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = device_get_by_driver_info((struct driver_info *)cells->node,
|
ret = device_get_by_driver_info_idx(cells->idx, &clk->dev);
|
||||||
&clk->dev);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
clk->id = cells->arg[0];
|
clk->id = cells->arg[0];
|
||||||
|
|
|
@ -46,8 +46,8 @@ static const struct udevice_id clk_fixed_rate_match[] = {
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(clk_fixed_rate) = {
|
U_BOOT_DRIVER(fixed_clock) = {
|
||||||
.name = "fixed_rate_clock",
|
.name = "fixed_clock",
|
||||||
.id = UCLASS_CLK,
|
.id = UCLASS_CLK,
|
||||||
.of_match = clk_fixed_rate_match,
|
.of_match = clk_fixed_rate_match,
|
||||||
.ofdata_to_platdata = clk_fixed_rate_ofdata_to_platdata,
|
.ofdata_to_platdata = clk_fixed_rate_ofdata_to_platdata,
|
||||||
|
|
|
@ -124,8 +124,8 @@ static const struct udevice_id sandbox_clk_ids[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(clk_sandbox) = {
|
U_BOOT_DRIVER(sandbox_clk) = {
|
||||||
.name = "clk_sandbox",
|
.name = "sandbox_clk",
|
||||||
.id = UCLASS_CLK,
|
.id = UCLASS_CLK,
|
||||||
.of_match = sandbox_clk_ids,
|
.of_match = sandbox_clk_ids,
|
||||||
.ops = &sandbox_clk_ops,
|
.ops = &sandbox_clk_ops,
|
||||||
|
|
|
@ -40,10 +40,24 @@ config DM_WARN
|
||||||
depends on DM
|
depends on DM
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
|
Enable this to see warnings related to driver model.
|
||||||
|
|
||||||
|
Warnings may help with debugging, such as when expected devices do
|
||||||
|
not bind correctly. If the option is disabled, dm_warn() is compiled
|
||||||
|
out - it will do nothing when called.
|
||||||
|
|
||||||
|
config SPL_DM_WARN
|
||||||
|
bool "Enable warnings in driver model wuth SPL"
|
||||||
|
depends on SPL_DM
|
||||||
|
help
|
||||||
|
Enable this to see warnings related to driver model in SPL
|
||||||
|
|
||||||
The dm_warn() function can use up quite a bit of space for its
|
The dm_warn() function can use up quite a bit of space for its
|
||||||
strings. By default this is disabled for SPL builds to save space.
|
strings. By default this is disabled for SPL builds to save space.
|
||||||
This will cause dm_warn() to be compiled out - it will do nothing
|
|
||||||
when called.
|
Warnings may help with debugging, such as when expected devices do
|
||||||
|
not bind correctly. If the option is disabled, dm_warn() is compiled
|
||||||
|
out - it will do nothing when called.
|
||||||
|
|
||||||
config DM_DEBUG
|
config DM_DEBUG
|
||||||
bool "Enable debug messages in driver model core"
|
bool "Enable debug messages in driver model core"
|
||||||
|
|
|
@ -11,7 +11,7 @@ obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
|
||||||
obj-$(CONFIG_DM) += dump.o
|
obj-$(CONFIG_DM) += dump.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)REGMAP) += regmap.o
|
obj-$(CONFIG_$(SPL_TPL_)REGMAP) += regmap.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)SYSCON) += syscon-uclass.o
|
obj-$(CONFIG_$(SPL_TPL_)SYSCON) += syscon-uclass.o
|
||||||
obj-$(CONFIG_OF_LIVE) += of_access.o of_addr.o
|
obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o
|
||||||
ifndef CONFIG_DM_DEV_READ_INLINE
|
ifndef CONFIG_DM_DEV_READ_INLINE
|
||||||
obj-$(CONFIG_OF_CONTROL) += read.o
|
obj-$(CONFIG_OF_CONTROL) += read.o
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -249,7 +249,7 @@ int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
||||||
struct driver_info *info, struct udevice **devp)
|
const struct driver_info *info, struct udevice **devp)
|
||||||
{
|
{
|
||||||
struct driver *drv;
|
struct driver *drv;
|
||||||
uint platdata_size = 0;
|
uint platdata_size = 0;
|
||||||
|
@ -269,9 +269,6 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
||||||
platdata_size, devp);
|
platdata_size, devp);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
|
||||||
info->dev = *devp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -764,9 +761,25 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
|
||||||
int device_get_by_driver_info(const struct driver_info *info,
|
int device_get_by_driver_info(const struct driver_info *info,
|
||||||
struct udevice **devp)
|
struct udevice **devp)
|
||||||
{
|
{
|
||||||
|
struct driver_info *info_base =
|
||||||
|
ll_entry_start(struct driver_info, driver_info);
|
||||||
|
int idx = info - info_base;
|
||||||
|
struct driver_rt *drt = gd_dm_driver_rt() + idx;
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
|
|
||||||
dev = info->dev;
|
dev = drt->dev;
|
||||||
|
*devp = NULL;
|
||||||
|
|
||||||
|
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int device_get_by_driver_info_idx(uint idx, struct udevice **devp)
|
||||||
|
{
|
||||||
|
struct driver_rt *drt = gd_dm_driver_rt() + idx;
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
dev = drt->dev;
|
||||||
|
*devp = NULL;
|
||||||
|
|
||||||
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
|
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,25 +51,81 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
|
static int bind_drivers_pass(struct udevice *parent, bool pre_reloc_only)
|
||||||
{
|
{
|
||||||
struct driver_info *info =
|
struct driver_info *info =
|
||||||
ll_entry_start(struct driver_info, driver_info);
|
ll_entry_start(struct driver_info, driver_info);
|
||||||
const int n_ents = ll_entry_count(struct driver_info, driver_info);
|
const int n_ents = ll_entry_count(struct driver_info, driver_info);
|
||||||
struct driver_info *entry;
|
bool missing_parent = false;
|
||||||
struct udevice *dev;
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int ret;
|
uint idx;
|
||||||
|
|
||||||
for (entry = info; entry != info + n_ents; entry++) {
|
/*
|
||||||
ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev);
|
* Do one iteration through the driver_info records. For of-platdata,
|
||||||
if (ret && ret != -EPERM) {
|
* bind only devices whose parent is already bound. If we find any
|
||||||
|
* device we can't bind, set missing_parent to true, which will cause
|
||||||
|
* this function to be called again.
|
||||||
|
*/
|
||||||
|
for (idx = 0; idx < n_ents; idx++) {
|
||||||
|
struct udevice *par = parent;
|
||||||
|
const struct driver_info *entry = info + idx;
|
||||||
|
struct driver_rt *drt = gd_dm_driver_rt() + idx;
|
||||||
|
struct udevice *dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
|
int parent_idx = driver_info_parent_id(entry);
|
||||||
|
|
||||||
|
if (drt->dev)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(OF_PLATDATA_PARENT) &&
|
||||||
|
parent_idx != -1) {
|
||||||
|
struct driver_rt *parent_drt;
|
||||||
|
|
||||||
|
parent_drt = gd_dm_driver_rt() + parent_idx;
|
||||||
|
if (!parent_drt->dev) {
|
||||||
|
missing_parent = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
par = parent_drt->dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = device_bind_by_name(par, pre_reloc_only, entry, &dev);
|
||||||
|
if (!ret) {
|
||||||
|
if (CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||||
|
drt->dev = dev;
|
||||||
|
} else if (ret != -EPERM) {
|
||||||
dm_warn("No match for driver '%s'\n", entry->name);
|
dm_warn("No match for driver '%s'\n", entry->name);
|
||||||
if (!result || ret != -ENOENT)
|
if (!result || ret != -ENOENT)
|
||||||
result = ret;
|
result = ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result ? result : missing_parent ? -EAGAIN : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 10 passes is 10 levels deep in the devicetree, which is plenty. If
|
||||||
|
* OF_PLATDATA_PARENT is not enabled, then bind_drivers_pass() will
|
||||||
|
* always succeed on the first pass.
|
||||||
|
*/
|
||||||
|
for (pass = 0; pass < 10; pass++) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = bind_drivers_pass(parent, pre_reloc_only);
|
||||||
|
if (!ret)
|
||||||
|
break;
|
||||||
|
if (ret != -EAGAIN && !result)
|
||||||
|
result = ret;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,6 @@ void dm_fixup_for_gd_move(struct global_data *new_gd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
|
||||||
void fix_drivers(void)
|
void fix_drivers(void)
|
||||||
{
|
{
|
||||||
struct driver *drv =
|
struct driver *drv =
|
||||||
|
@ -61,7 +60,7 @@ void fix_drivers(void)
|
||||||
for (entry = drv; entry != drv + n_ents; entry++) {
|
for (entry = drv; entry != drv + n_ents; entry++) {
|
||||||
if (entry->of_match)
|
if (entry->of_match)
|
||||||
entry->of_match = (const struct udevice_id *)
|
entry->of_match = (const struct udevice_id *)
|
||||||
((u32)entry->of_match + gd->reloc_off);
|
((ulong)entry->of_match + gd->reloc_off);
|
||||||
if (entry->bind)
|
if (entry->bind)
|
||||||
entry->bind += gd->reloc_off;
|
entry->bind += gd->reloc_off;
|
||||||
if (entry->probe)
|
if (entry->probe)
|
||||||
|
@ -129,8 +128,6 @@ void fix_devices(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int dm_init(bool of_live)
|
int dm_init(bool of_live)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -141,21 +138,19 @@ int dm_init(bool of_live)
|
||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
|
INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
|
||||||
|
|
||||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
|
||||||
fix_drivers();
|
fix_drivers();
|
||||||
fix_uclass();
|
fix_uclass();
|
||||||
fix_devices();
|
fix_devices();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
|
ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||||
# if CONFIG_IS_ENABLED(OF_LIVE)
|
if (CONFIG_IS_ENABLED(OF_LIVE) && of_live)
|
||||||
if (of_live)
|
DM_ROOT_NON_CONST->node = np_to_ofnode(gd_of_root());
|
||||||
DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);
|
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
|
DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
|
||||||
#endif
|
#endif
|
||||||
ret = device_probe(DM_ROOT_NON_CONST);
|
ret = device_probe(DM_ROOT_NON_CONST);
|
||||||
|
@ -187,6 +182,17 @@ int dm_scan_platdata(bool pre_reloc_only)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
|
struct driver_rt *dyn;
|
||||||
|
int n_ents;
|
||||||
|
|
||||||
|
n_ents = ll_entry_count(struct driver_info, driver_info);
|
||||||
|
dyn = calloc(n_ents, sizeof(struct driver_rt));
|
||||||
|
if (!dyn)
|
||||||
|
return -ENOMEM;
|
||||||
|
gd_set_dm_driver_rt(dyn);
|
||||||
|
}
|
||||||
|
|
||||||
ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
|
ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
dm_warn("Some drivers were not found\n");
|
dm_warn("Some drivers were not found\n");
|
||||||
|
@ -196,7 +202,7 @@ int dm_scan_platdata(bool pre_reloc_only)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
static int dm_scan_fdt_live(struct udevice *parent,
|
static int dm_scan_fdt_live(struct udevice *parent,
|
||||||
const struct device_node *node_parent,
|
const struct device_node *node_parent,
|
||||||
bool pre_reloc_only)
|
bool pre_reloc_only)
|
||||||
|
@ -223,9 +229,7 @@ static int dm_scan_fdt_live(struct udevice *parent,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IS_ENABLED(OF_LIVE) */
|
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
|
|
||||||
/**
|
/**
|
||||||
* dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
|
* dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
|
||||||
*
|
*
|
||||||
|
@ -272,24 +276,20 @@ int dm_scan_fdt_dev(struct udevice *dev)
|
||||||
if (!dev_of_valid(dev))
|
if (!dev_of_valid(dev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
|
||||||
if (of_live_active())
|
if (of_live_active())
|
||||||
return dm_scan_fdt_live(dev, dev_np(dev),
|
return dm_scan_fdt_live(dev, dev_np(dev),
|
||||||
gd->flags & GD_FLG_RELOC ? false : true);
|
gd->flags & GD_FLG_RELOC ? false : true);
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
|
return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
|
||||||
gd->flags & GD_FLG_RELOC ? false : true);
|
gd->flags & GD_FLG_RELOC ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_scan_fdt(const void *blob, bool pre_reloc_only)
|
int dm_scan_fdt(const void *blob, bool pre_reloc_only)
|
||||||
{
|
{
|
||||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
|
||||||
if (of_live_active())
|
if (of_live_active())
|
||||||
return dm_scan_fdt_live(gd->dm_root, gd->of_root,
|
return dm_scan_fdt_live(gd->dm_root, gd_of_root(),
|
||||||
pre_reloc_only);
|
pre_reloc_only);
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
|
return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,10 +302,9 @@ static int dm_scan_fdt_ofnode_path(const void *blob, const char *path,
|
||||||
if (!ofnode_valid(node))
|
if (!ofnode_valid(node))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
|
||||||
if (of_live_active())
|
if (of_live_active())
|
||||||
return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
|
return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
|
||||||
#endif
|
|
||||||
return dm_scan_fdt_node(gd->dm_root, blob, node.of_offset,
|
return dm_scan_fdt_node(gd->dm_root, blob, node.of_offset,
|
||||||
pre_reloc_only);
|
pre_reloc_only);
|
||||||
}
|
}
|
||||||
|
@ -348,11 +347,10 @@ int dm_init_and_scan(bool pre_reloc_only)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
if (CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||||
dm_populate_phandle_data();
|
dm_populate_phandle_data();
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
|
ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("dm_init() failed: %d\n", ret);
|
debug("dm_init() failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <linux/libfdt.h>
|
#include <linux/libfdt.h>
|
||||||
#include <vsprintf.h>
|
#include <vsprintf.h>
|
||||||
|
|
||||||
#ifdef CONFIG_DM_WARN
|
#if CONFIG_IS_ENABLED(DM_WARN)
|
||||||
void dm_warn(const char *fmt, ...)
|
void dm_warn(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
|
@ -6,7 +6,7 @@ obj-$(CONFIG_DM_I2C) += i2c-uclass.o
|
||||||
ifdef CONFIG_ACPIGEN
|
ifdef CONFIG_ACPIGEN
|
||||||
obj-$(CONFIG_DM_I2C) += acpi_i2c.o
|
obj-$(CONFIG_DM_I2C) += acpi_i2c.o
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_DM_I2C_GPIO) += i2c-gpio.o
|
obj-$(CONFIG_$(SPL_)DM_I2C_GPIO) += i2c-gpio.o
|
||||||
obj-$(CONFIG_$(SPL_)I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o
|
obj-$(CONFIG_$(SPL_)I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o
|
||||||
obj-$(CONFIG_$(SPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o
|
obj-$(CONFIG_$(SPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,9 @@ UCLASS_DRIVER(i2c_emul) = {
|
||||||
UCLASS_DRIVER(i2c_emul_parent) = {
|
UCLASS_DRIVER(i2c_emul_parent) = {
|
||||||
.id = UCLASS_I2C_EMUL_PARENT,
|
.id = UCLASS_I2C_EMUL_PARENT,
|
||||||
.name = "i2c_emul_parent",
|
.name = "i2c_emul_parent",
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
.post_bind = dm_scan_fdt_dev,
|
.post_bind = dm_scan_fdt_dev,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id i2c_emul_parent_ids[] = {
|
static const struct udevice_id i2c_emul_parent_ids[] = {
|
||||||
|
|
|
@ -93,8 +93,8 @@ static const struct udevice_id sandbox_i2c_ids[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(i2c_sandbox) = {
|
U_BOOT_DRIVER(sandbox_i2c) = {
|
||||||
.name = "i2c_sandbox",
|
.name = "sandbox_i2c",
|
||||||
.id = UCLASS_I2C,
|
.id = UCLASS_I2C,
|
||||||
.of_match = sandbox_i2c_ids,
|
.of_match = sandbox_i2c_ids,
|
||||||
.ops = &sandbox_i2c_ops,
|
.ops = &sandbox_i2c_ops,
|
||||||
|
|
|
@ -69,7 +69,7 @@ int irq_get_by_driver_info(struct udevice *dev,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = device_get_by_driver_info(cells->node, &irq->dev);
|
ret = device_get_by_driver_info_idx(cells->idx, &irq->dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
irq->id = cells->arg[0];
|
irq->id = cells->arg[0];
|
||||||
|
|
|
@ -174,19 +174,20 @@ int p2sb_set_port_id(struct udevice *dev, int portid)
|
||||||
if (!CONFIG_IS_ENABLED(OF_PLATDATA))
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
uclass_find_first_device(UCLASS_P2SB, &ps2b);
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA_PARENT)) {
|
||||||
if (!ps2b)
|
uclass_find_first_device(UCLASS_P2SB, &ps2b);
|
||||||
return -EDEADLK;
|
if (!ps2b)
|
||||||
dev->parent = ps2b;
|
return -EDEADLK;
|
||||||
|
dev->parent = ps2b;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must allocate this, since when the device was bound it did not
|
* We must allocate this, since when the device was bound it did
|
||||||
* have a parent.
|
* not have a parent.
|
||||||
* TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc
|
*/
|
||||||
*/
|
dev->parent_platdata = malloc(sizeof(*pplat));
|
||||||
dev->parent_platdata = malloc(sizeof(*pplat));
|
if (!dev->parent_platdata)
|
||||||
if (!dev->parent_platdata)
|
return -ENOMEM;
|
||||||
return -ENOMEM;
|
}
|
||||||
pplat = dev_get_parent_platdata(dev);
|
pplat = dev_get_parent_platdata(dev);
|
||||||
pplat->pid = portid;
|
pplat->pid = portid;
|
||||||
|
|
||||||
|
|
|
@ -8,43 +8,8 @@
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <dt-structs.h>
|
#include <dt-structs.h>
|
||||||
|
|
||||||
static int sandbox_spl_probe(struct udevice *dev)
|
|
||||||
{
|
|
||||||
struct dtd_sandbox_spl_test *plat = dev_get_platdata(dev);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
printf("of-platdata probe:\n");
|
|
||||||
printf("bool %d\n", plat->boolval);
|
|
||||||
|
|
||||||
printf("byte %02x\n", plat->byteval);
|
|
||||||
printf("bytearray");
|
|
||||||
for (i = 0; i < sizeof(plat->bytearray); i++)
|
|
||||||
printf(" %02x", plat->bytearray[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
printf("int %d\n", plat->intval);
|
|
||||||
printf("intarray");
|
|
||||||
for (i = 0; i < ARRAY_SIZE(plat->intarray); i++)
|
|
||||||
printf(" %d", plat->intarray[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
printf("longbytearray");
|
|
||||||
for (i = 0; i < sizeof(plat->longbytearray); i++)
|
|
||||||
printf(" %02x", plat->longbytearray[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
printf("string %s\n", plat->stringval);
|
|
||||||
printf("stringarray");
|
|
||||||
for (i = 0; i < ARRAY_SIZE(plat->stringarray); i++)
|
|
||||||
printf(" \"%s\"", plat->stringarray[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
U_BOOT_DRIVER(sandbox_spl_test) = {
|
U_BOOT_DRIVER(sandbox_spl_test) = {
|
||||||
.name = "sandbox_spl_test",
|
.name = "sandbox_spl_test",
|
||||||
.id = UCLASS_MISC,
|
.id = UCLASS_MISC,
|
||||||
.flags = DM_FLAG_PRE_RELOC,
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
.probe = sandbox_spl_probe,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1504,12 +1504,9 @@ static int fsl_esdhc_probe(struct udevice *dev)
|
||||||
|
|
||||||
if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) {
|
if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) {
|
||||||
struct udevice *gpiodev;
|
struct udevice *gpiodev;
|
||||||
struct driver_info *info;
|
|
||||||
|
|
||||||
info = (struct driver_info *)dtplat->cd_gpios->node;
|
|
||||||
|
|
||||||
ret = device_get_by_driver_info(info, &gpiodev);
|
|
||||||
|
|
||||||
|
ret = device_get_by_driver_info_idx(dtplat->cd_gpios->idx,
|
||||||
|
&gpiodev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -174,5 +174,7 @@ int rtc_write32(struct udevice *dev, unsigned int reg, u32 value)
|
||||||
UCLASS_DRIVER(rtc) = {
|
UCLASS_DRIVER(rtc) = {
|
||||||
.name = "rtc",
|
.name = "rtc",
|
||||||
.id = UCLASS_RTC,
|
.id = UCLASS_RTC,
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
.post_bind = dm_scan_fdt_dev,
|
.post_bind = dm_scan_fdt_dev,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,8 +92,8 @@ static const struct udevice_id sandbox_rtc_ids[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(rtc_sandbox) = {
|
U_BOOT_DRIVER(sandbox_rtc) = {
|
||||||
.name = "rtc-sandbox",
|
.name = "sandbox_rtc",
|
||||||
.id = UCLASS_RTC,
|
.id = UCLASS_RTC,
|
||||||
.of_match = sandbox_rtc_ids,
|
.of_match = sandbox_rtc_ids,
|
||||||
.ops = &sandbox_rtc_ops,
|
.ops = &sandbox_rtc_ops,
|
||||||
|
|
|
@ -267,6 +267,7 @@ U_BOOT_DRIVER(sandbox_serial) = {
|
||||||
.flags = DM_FLAG_PRE_RELOC,
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
static const struct sandbox_serial_platdata platdata_non_fdt = {
|
static const struct sandbox_serial_platdata platdata_non_fdt = {
|
||||||
.colour = -1,
|
.colour = -1,
|
||||||
};
|
};
|
||||||
|
@ -275,4 +276,6 @@ U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
|
||||||
.name = "sandbox_serial",
|
.name = "sandbox_serial",
|
||||||
.platdata = &platdata_non_fdt,
|
.platdata = &platdata_non_fdt,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
|
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
|
||||||
|
|
|
@ -615,6 +615,7 @@ static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
/**
|
/**
|
||||||
* ich_spi_get_basics() - Get basic information about the ICH device
|
* ich_spi_get_basics() - Get basic information about the ICH device
|
||||||
*
|
*
|
||||||
|
@ -657,6 +658,7 @@ static int ich_spi_get_basics(struct udevice *bus, bool can_probe,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ich_get_mmap_bus() - Handle the get_mmap() method for a bus
|
* ich_get_mmap_bus() - Handle the get_mmap() method for a bus
|
||||||
|
@ -946,10 +948,10 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
|
||||||
static int ich_spi_ofdata_to_platdata(struct udevice *dev)
|
static int ich_spi_ofdata_to_platdata(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct ich_spi_platdata *plat = dev_get_platdata(dev);
|
struct ich_spi_platdata *plat = dev_get_platdata(dev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
struct ich_spi_priv *priv = dev_get_priv(dev);
|
struct ich_spi_priv *priv = dev_get_priv(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
ret = ich_spi_get_basics(dev, true, &priv->pch, &plat->ich_version,
|
ret = ich_spi_get_basics(dev, true, &priv->pch, &plat->ich_version,
|
||||||
&plat->mmio_base);
|
&plat->mmio_base);
|
||||||
|
|
|
@ -130,7 +130,9 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = {
|
||||||
.ops = &sandbox_warm_sysreset_ops,
|
.ops = &sandbox_warm_sysreset_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
/* This is here in case we don't have a device tree */
|
/* This is here in case we don't have a device tree */
|
||||||
U_BOOT_DEVICE(sysreset_sandbox_non_fdt) = {
|
U_BOOT_DEVICE(sysreset_sandbox_non_fdt) = {
|
||||||
.name = "sysreset_sandbox",
|
.name = "sysreset_sandbox",
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
18
dts/Kconfig
18
dts/Kconfig
|
@ -355,6 +355,15 @@ config SPL_OF_PLATDATA
|
||||||
compatible string, then adding platform data and U_BOOT_DEVICE
|
compatible string, then adding platform data and U_BOOT_DEVICE
|
||||||
declarations for each node. See of-plat.txt for more information.
|
declarations for each node. See of-plat.txt for more information.
|
||||||
|
|
||||||
|
config SPL_OF_PLATDATA_PARENT
|
||||||
|
bool "Support parent information in devices"
|
||||||
|
depends on SPL_OF_PLATDATA
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Generally it is useful to be able to access the parent of a device
|
||||||
|
with of-platdata. To save space this can be disabled, but in that
|
||||||
|
case dev_get_parent() will always return NULL;
|
||||||
|
|
||||||
config TPL_OF_PLATDATA
|
config TPL_OF_PLATDATA
|
||||||
bool "Generate platform data for use in TPL"
|
bool "Generate platform data for use in TPL"
|
||||||
depends on TPL_OF_CONTROL
|
depends on TPL_OF_CONTROL
|
||||||
|
@ -376,4 +385,13 @@ config TPL_OF_PLATDATA
|
||||||
compatible string, then adding platform data and U_BOOT_DEVICE
|
compatible string, then adding platform data and U_BOOT_DEVICE
|
||||||
declarations for each node. See of-plat.txt for more information.
|
declarations for each node. See of-plat.txt for more information.
|
||||||
|
|
||||||
|
config TPL_OF_PLATDATA_PARENT
|
||||||
|
bool "Support parent information in devices"
|
||||||
|
depends on TPL_OF_PLATDATA
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Generally it is useful to be able to access the parent of a device
|
||||||
|
with of-platdata. To save space this can be disabled, but in that
|
||||||
|
case dev_get_parent() will always return NULL;
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <membuff.h>
|
#include <membuff.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
struct driver_rt;
|
||||||
|
|
||||||
typedef struct global_data gd_t;
|
typedef struct global_data gd_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -192,6 +194,10 @@ struct global_data {
|
||||||
* @uclass_root: head of core tree
|
* @uclass_root: head of core tree
|
||||||
*/
|
*/
|
||||||
struct list_head uclass_root;
|
struct list_head uclass_root;
|
||||||
|
# if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
/** Dynamic info about the driver */
|
||||||
|
struct driver_rt *dm_driver_rt;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TIMER
|
#ifdef CONFIG_TIMER
|
||||||
/**
|
/**
|
||||||
|
@ -211,7 +217,7 @@ struct global_data {
|
||||||
* @fdt_size: space reserved for relocated device space
|
* @fdt_size: space reserved for relocated device space
|
||||||
*/
|
*/
|
||||||
unsigned long fdt_size;
|
unsigned long fdt_size;
|
||||||
#ifdef CONFIG_OF_LIVE
|
#if CONFIG_IS_ENABLED(OF_LIVE)
|
||||||
/**
|
/**
|
||||||
* @of_root: root node of the live tree
|
* @of_root: root node of the live tree
|
||||||
*/
|
*/
|
||||||
|
@ -427,6 +433,25 @@ struct global_data {
|
||||||
#define gd_board_type() 0
|
#define gd_board_type() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* These macros help avoid #ifdefs in the code */
|
||||||
|
#if CONFIG_IS_ENABLED(OF_LIVE)
|
||||||
|
#define gd_of_root() gd->of_root
|
||||||
|
#define gd_of_root_ptr() &gd->of_root
|
||||||
|
#define gd_set_of_root(_root) gd->of_root = (_root)
|
||||||
|
#else
|
||||||
|
#define gd_of_root() NULL
|
||||||
|
#define gd_of_root_ptr() NULL
|
||||||
|
#define gd_set_of_root(_root)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
#define gd_set_dm_driver_rt(dyn) gd->dm_driver_rt = dyn
|
||||||
|
#define gd_dm_driver_rt() gd->dm_driver_rt
|
||||||
|
#else
|
||||||
|
#define gd_set_dm_driver_rt(dyn)
|
||||||
|
#define gd_dm_driver_rt() NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum gd_flags - global data flags
|
* enum gd_flags - global data flags
|
||||||
*
|
*
|
||||||
|
|
|
@ -42,6 +42,13 @@ int binman_entry_map(ofnode parent, const char *name, void **bufp, int *sizep);
|
||||||
*/
|
*/
|
||||||
void binman_set_rom_offset(int rom_offset);
|
void binman_set_rom_offset(int rom_offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* binman_get_rom_offset() - Get the ROM memory-map offset
|
||||||
|
*
|
||||||
|
* @returns offset from an image_pos to the memory-mapped address
|
||||||
|
*/
|
||||||
|
int binman_get_rom_offset(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* binman_entry_find() - Find a binman symbol
|
* binman_entry_find() - Find a binman symbol
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#undef CONFIG_DM_SPI
|
#undef CONFIG_DM_SPI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef CONFIG_DM_WARN
|
|
||||||
#undef CONFIG_DM_STDIO
|
#undef CONFIG_DM_STDIO
|
||||||
|
|
||||||
#endif /* CONFIG_SPL_BUILD */
|
#endif /* CONFIG_SPL_BUILD */
|
||||||
|
|
|
@ -81,7 +81,7 @@ int device_bind_with_driver_data(struct udevice *parent,
|
||||||
* @return 0 if OK, -ve on error
|
* @return 0 if OK, -ve on error
|
||||||
*/
|
*/
|
||||||
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
||||||
struct driver_info *info, struct udevice **devp);
|
const struct driver_info *info, struct udevice **devp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_reparent: reparent the device to a new parent
|
* device_reparent: reparent the device to a new parent
|
||||||
|
|
|
@ -553,6 +553,20 @@ int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
|
||||||
int device_get_by_driver_info(const struct driver_info *info,
|
int device_get_by_driver_info(const struct driver_info *info,
|
||||||
struct udevice **devp);
|
struct udevice **devp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_get_by_driver_info_idx() - Get a device based on driver_info index
|
||||||
|
*
|
||||||
|
* Locates a device by its struct driver_info, by using its index number which
|
||||||
|
* is written into the idx field of struct phandle_1_arg, etc.
|
||||||
|
*
|
||||||
|
* The device is probed to activate it ready for use.
|
||||||
|
*
|
||||||
|
* @idx: Index number of the driver_info structure (0=first)
|
||||||
|
* @devp: Returns pointer to device if found, otherwise this is set to NULL
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int device_get_by_driver_info_idx(uint idx, struct udevice **devp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_find_first_child() - Find the first child of a device
|
* device_find_first_child() - Find the first child of a device
|
||||||
*
|
*
|
||||||
|
@ -823,7 +837,7 @@ static inline bool device_is_on_pci_bus(const struct udevice *dev)
|
||||||
_ret = device_next_child_err(&dev))
|
_ret = device_next_child_err(&dev))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dm_scan_fdt_dev() - Bind child device in a the device tree
|
* dm_scan_fdt_dev() - Bind child device in the device tree
|
||||||
*
|
*
|
||||||
* This handles device which have sub-nodes in the device tree. It scans all
|
* This handles device which have sub-nodes in the device tree. It scans all
|
||||||
* sub-nodes and binds drivers for each node where a driver can be found.
|
* sub-nodes and binds drivers for each node where a driver can be found.
|
||||||
|
|
|
@ -90,17 +90,10 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
*
|
*
|
||||||
* @returns true if livetree is active, false it not
|
* @returns true if livetree is active, false it not
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_OF_LIVE
|
|
||||||
static inline bool of_live_active(void)
|
static inline bool of_live_active(void)
|
||||||
{
|
{
|
||||||
return gd->of_root != NULL;
|
return gd_of_root() != NULL;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static inline bool of_live_active(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define OF_BAD_ADDR ((u64)-1)
|
#define OF_BAD_ADDR ((u64)-1)
|
||||||
|
|
||||||
|
|
|
@ -22,30 +22,71 @@
|
||||||
* @name: Driver name
|
* @name: Driver name
|
||||||
* @platdata: Driver-specific platform data
|
* @platdata: Driver-specific platform data
|
||||||
* @platdata_size: Size of platform data structure
|
* @platdata_size: Size of platform data structure
|
||||||
* @dev: Device created from this structure data
|
* @parent_idx: Index of the parent driver_info structure
|
||||||
*/
|
*/
|
||||||
struct driver_info {
|
struct driver_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
const void *platdata;
|
const void *platdata;
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
uint platdata_size;
|
unsigned short platdata_size;
|
||||||
struct udevice *dev;
|
short parent_idx;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
#define driver_info_parent_id(driver_info) driver_info->parent_idx
|
||||||
|
#else
|
||||||
|
#define driver_info_parent_id(driver_info) (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* driver_rt - runtime information set up by U-Boot
|
||||||
|
*
|
||||||
|
* There is one of these for every driver_info in the linker list, indexed by
|
||||||
|
* the driver_info idx value.
|
||||||
|
*
|
||||||
|
* @dev: Device created from this idx
|
||||||
|
*/
|
||||||
|
struct driver_rt {
|
||||||
|
struct udevice *dev;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: Avoid using these except in extreme circumstances, where device tree
|
* NOTE: Avoid using these except in extreme circumstances, where device tree
|
||||||
* is not feasible (e.g. serial driver in SPL where <8KB of SRAM is
|
* is not feasible (e.g. serial driver in SPL where <8KB of SRAM is
|
||||||
* available). U-Boot's driver model uses device tree for configuration.
|
* available). U-Boot's driver model uses device tree for configuration.
|
||||||
|
*
|
||||||
|
* When of-platdata is in use, U_BOOT_DEVICE() cannot be used outside of the
|
||||||
|
* dt-platdata.c file created by dtoc
|
||||||
*/
|
*/
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) && !defined(DT_PLATDATA_C)
|
||||||
|
#define U_BOOT_DEVICE(__name) _Static_assert(false, \
|
||||||
|
"Cannot use U_BOOT_DEVICE with of-platdata. Please use devicetree instead")
|
||||||
|
#else
|
||||||
#define U_BOOT_DEVICE(__name) \
|
#define U_BOOT_DEVICE(__name) \
|
||||||
ll_entry_declare(struct driver_info, __name, driver_info)
|
ll_entry_declare(struct driver_info, __name, driver_info)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Declare a list of devices. The argument is a driver_info[] array */
|
/* Declare a list of devices. The argument is a driver_info[] array */
|
||||||
#define U_BOOT_DEVICES(__name) \
|
#define U_BOOT_DEVICES(__name) \
|
||||||
ll_entry_declare_list(struct driver_info, __name, driver_info)
|
ll_entry_declare_list(struct driver_info, __name, driver_info)
|
||||||
|
|
||||||
/* Get a pointer to a given driver */
|
/**
|
||||||
|
* Get a pointer to a given device info given its name
|
||||||
|
*
|
||||||
|
* With the declaration U_BOOT_DEVICE(name), DM_GET_DEVICE(name) will return a
|
||||||
|
* pointer to the struct driver_info created by that declaration.
|
||||||
|
*
|
||||||
|
* if OF_PLATDATA is enabled, from this it is possible to use the @dev member of
|
||||||
|
* struct driver_info to find the device pointer itself.
|
||||||
|
*
|
||||||
|
* TODO(sjg@chromium.org): U_BOOT_DEVICE() tells U-Boot to create a device, so
|
||||||
|
* the naming seems sensible, but DM_GET_DEVICE() is a bit of misnomer, since it
|
||||||
|
* finds the driver_info record, not the device.
|
||||||
|
*
|
||||||
|
* @__name: Driver name (C identifier, not a string. E.g. gpio7_at_ff7e0000)
|
||||||
|
* @return struct driver_info * to the driver that created the device
|
||||||
|
*/
|
||||||
#define DM_GET_DEVICE(__name) \
|
#define DM_GET_DEVICE(__name) \
|
||||||
ll_entry_get(struct driver_info, __name, driver_info)
|
ll_entry_get(struct driver_info, __name, driver_info)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#ifndef __DM_UTIL_H
|
#ifndef __DM_UTIL_H
|
||||||
#define __DM_UTIL_H
|
#define __DM_UTIL_H
|
||||||
|
|
||||||
#ifdef CONFIG_DM_WARN
|
#if CONFIG_IS_ENABLED(DM_WARN)
|
||||||
void dm_warn(const char *fmt, ...);
|
void dm_warn(const char *fmt, ...);
|
||||||
#else
|
#else
|
||||||
static inline void dm_warn(const char *fmt, ...)
|
static inline void dm_warn(const char *fmt, ...)
|
||||||
|
|
|
@ -8,18 +8,20 @@
|
||||||
|
|
||||||
/* These structures may only be used in SPL */
|
/* These structures may only be used in SPL */
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
struct driver_info;
|
||||||
|
|
||||||
struct phandle_0_arg {
|
struct phandle_0_arg {
|
||||||
const void *node;
|
uint idx;
|
||||||
int arg[0];
|
int arg[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phandle_1_arg {
|
struct phandle_1_arg {
|
||||||
const void *node;
|
uint idx;
|
||||||
int arg[1];
|
int arg[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phandle_2_arg {
|
struct phandle_2_arg {
|
||||||
const void *node;
|
uint idx;
|
||||||
int arg[2];
|
int arg[2];
|
||||||
};
|
};
|
||||||
#include <generated/dt-structs-gen.h>
|
#include <generated/dt-structs-gen.h>
|
||||||
|
|
|
@ -94,4 +94,15 @@ enum {
|
||||||
TEST_DEVRES_SIZE3 = 37,
|
TEST_DEVRES_SIZE3 = 37,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dm_test_main() - Run driver model tests
|
||||||
|
*
|
||||||
|
* Run all the available driver model tests, or a selection
|
||||||
|
*
|
||||||
|
* @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just
|
||||||
|
* "fdt_pre_reloc"), or NULL to run all
|
||||||
|
* @return 0 if all tests passed, 1 if not
|
||||||
|
*/
|
||||||
|
int dm_test_main(const char *test_name);
|
||||||
|
|
||||||
#endif /* __TEST_TEST_H */
|
#endif /* __TEST_TEST_H */
|
||||||
|
|
14
lib/binman.c
14
lib/binman.c
|
@ -43,7 +43,7 @@ static int binman_entry_find_internal(ofnode node, const char *name,
|
||||||
|
|
||||||
ret = ofnode_read_u32(node, "image-pos", &entry->image_pos);
|
ret = ofnode_read_u32(node, "image-pos", &entry->image_pos);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("import-pos", ret);
|
return log_msg_ret("image-pos", ret);
|
||||||
ret = ofnode_read_u32(node, "size", &entry->size);
|
ret = ofnode_read_u32(node, "size", &entry->size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("size", ret);
|
return log_msg_ret("size", ret);
|
||||||
|
@ -83,6 +83,11 @@ void binman_set_rom_offset(int rom_offset)
|
||||||
binman->rom_offset = rom_offset;
|
binman->rom_offset = rom_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int binman_get_rom_offset(void)
|
||||||
|
{
|
||||||
|
return binman->rom_offset;
|
||||||
|
}
|
||||||
|
|
||||||
int binman_init(void)
|
int binman_init(void)
|
||||||
{
|
{
|
||||||
binman = malloc(sizeof(struct binman_info));
|
binman = malloc(sizeof(struct binman_info));
|
||||||
|
@ -91,6 +96,13 @@ int binman_init(void)
|
||||||
binman->image = ofnode_path("/binman");
|
binman->image = ofnode_path("/binman");
|
||||||
if (!ofnode_valid(binman->image))
|
if (!ofnode_valid(binman->image))
|
||||||
return log_msg_ret("binman node", -EINVAL);
|
return log_msg_ret("binman node", -EINVAL);
|
||||||
|
if (ofnode_read_bool(binman->image, "multiple-images")) {
|
||||||
|
ofnode node = ofnode_first_subnode(binman->image);
|
||||||
|
|
||||||
|
if (!ofnode_valid(node))
|
||||||
|
return log_msg_ret("first image", -ENOENT);
|
||||||
|
binman->image = node;
|
||||||
|
}
|
||||||
binman->rom_offset = ROM_OFFSET_NONE;
|
binman->rom_offset = ROM_OFFSET_NONE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -99,6 +99,7 @@ libs-y += dts/
|
||||||
libs-y += fs/
|
libs-y += fs/
|
||||||
libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/
|
libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/
|
||||||
libs-$(CONFIG_SPL_NET_SUPPORT) += net/
|
libs-$(CONFIG_SPL_NET_SUPPORT) += net/
|
||||||
|
libs-$(CONFIG_SPL_UNIT_TEST) += test/
|
||||||
|
|
||||||
head-y := $(addprefix $(obj)/,$(head-y))
|
head-y := $(addprefix $(obj)/,$(head-y))
|
||||||
libs-y := $(addprefix $(obj)/,$(libs-y))
|
libs-y := $(addprefix $(obj)/,$(libs-y))
|
||||||
|
@ -213,7 +214,7 @@ spl/boot.bin: $(obj)/$(SPL_BIN)-align.bin FORCE
|
||||||
$(call if_changed,mkimage)
|
$(call if_changed,mkimage)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INPUTS-y += $(obj)/$(SPL_BIN).bin
|
INPUTS-y += $(obj)/$(SPL_BIN).bin $(obj)/$(SPL_BIN).sym
|
||||||
|
|
||||||
ifdef CONFIG_SAMSUNG
|
ifdef CONFIG_SAMSUNG
|
||||||
INPUTS-y += $(obj)/$(BOARD)-spl.bin
|
INPUTS-y += $(obj)/$(BOARD)-spl.bin
|
||||||
|
@ -407,6 +408,11 @@ MKIMAGEFLAGS_u-boot-spl-mtk.bin = -T mtk_image \
|
||||||
$(obj)/u-boot-spl-mtk.bin: $(obj)/u-boot-spl.bin FORCE
|
$(obj)/u-boot-spl-mtk.bin: $(obj)/u-boot-spl.bin FORCE
|
||||||
$(call if_changed,mkimage)
|
$(call if_changed,mkimage)
|
||||||
|
|
||||||
|
quiet_cmd_sym ?= SYM $@
|
||||||
|
cmd_sym ?= $(OBJDUMP) -t $< > $@
|
||||||
|
$(obj)/$(SPL_BIN).sym: $(obj)/$(SPL_BIN) FORCE
|
||||||
|
$(call if_changed,sym)
|
||||||
|
|
||||||
# Rule to link u-boot-spl
|
# Rule to link u-boot-spl
|
||||||
# May be overridden by arch/$(ARCH)/config.mk
|
# May be overridden by arch/$(ARCH)/config.mk
|
||||||
quiet_cmd_u-boot-spl ?= LD $@
|
quiet_cmd_u-boot-spl ?= LD $@
|
||||||
|
|
10
test/Kconfig
10
test/Kconfig
|
@ -6,6 +6,16 @@ menuconfig UNIT_TEST
|
||||||
This does not require sandbox to be included, but it is most
|
This does not require sandbox to be included, but it is most
|
||||||
often used there.
|
often used there.
|
||||||
|
|
||||||
|
config SPL_UNIT_TEST
|
||||||
|
bool "Unit tests in SPL"
|
||||||
|
# We need to be able to unbind devices for tests to work
|
||||||
|
select SPL_DM_DEVICE_REMOVE
|
||||||
|
help
|
||||||
|
Select this to enable unit tests in SPL. Most test are designed for
|
||||||
|
running in U-Boot proper, but some are intended for SPL, such as
|
||||||
|
of-platdata and SPL handover. To run these tests with the sandbox_spl
|
||||||
|
board, use the -u (unit test) option.
|
||||||
|
|
||||||
config UT_LIB
|
config UT_LIB
|
||||||
bool "Unit tests for library functions"
|
bool "Unit tests for library functions"
|
||||||
depends on UNIT_TEST
|
depends on UNIT_TEST
|
||||||
|
|
|
@ -2,15 +2,19 @@
|
||||||
#
|
#
|
||||||
# (C) Copyright 2012 The Chromium Authors
|
# (C) Copyright 2012 The Chromium Authors
|
||||||
|
|
||||||
obj-$(CONFIG_SANDBOX) += bloblist.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
|
||||||
obj-$(CONFIG_CMDLINE) += cmd/
|
obj-$(CONFIG_$(SPL_)CMDLINE) += cmd/
|
||||||
obj-$(CONFIG_UNIT_TEST) += cmd_ut.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_ut.o
|
||||||
obj-$(CONFIG_UNIT_TEST) += ut.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += command_ut.o
|
||||||
obj-$(CONFIG_SANDBOX) += command_ut.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += compression.o
|
||||||
obj-$(CONFIG_SANDBOX) += compression.o
|
obj-y += dm/
|
||||||
obj-$(CONFIG_SANDBOX) += print_ut.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += print_ut.o
|
||||||
obj-$(CONFIG_SANDBOX) += str_ut.o
|
obj-$(CONFIG_$(SPL_)CMDLINE) += str_ut.o
|
||||||
obj-$(CONFIG_UT_TIME) += time_ut.o
|
obj-$(CONFIG_UT_TIME) += time_ut.o
|
||||||
obj-$(CONFIG_UT_UNICODE) += unicode_ut.o
|
obj-y += ut.o
|
||||||
obj-y += log/
|
|
||||||
|
ifeq ($(CONFIG_SPL_BUILD),)
|
||||||
obj-$(CONFIG_UNIT_TEST) += lib/
|
obj-$(CONFIG_UNIT_TEST) += lib/
|
||||||
|
obj-y += log/
|
||||||
|
obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o
|
||||||
|
endif
|
||||||
|
|
|
@ -2,15 +2,18 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013 Google, Inc
|
# Copyright (c) 2013 Google, Inc
|
||||||
|
|
||||||
obj-$(CONFIG_UT_DM) += bus.o
|
|
||||||
obj-$(CONFIG_UT_DM) += nop.o
|
|
||||||
obj-$(CONFIG_UT_DM) += test-driver.o
|
|
||||||
obj-$(CONFIG_UT_DM) += test-fdt.o
|
|
||||||
obj-$(CONFIG_UT_DM) += test-main.o
|
obj-$(CONFIG_UT_DM) += test-main.o
|
||||||
obj-$(CONFIG_UT_DM) += test-uclass.o
|
|
||||||
|
|
||||||
# Tests for particular subsystems - when enabling driver model for a new
|
# Tests for particular subsystems - when enabling driver model for a new
|
||||||
# subsystem you must add sandbox tests here.
|
# subsystem you must add sandbox tests here.
|
||||||
|
ifeq ($(CONFIG_SPL_BUILD),y)
|
||||||
|
obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o
|
||||||
|
else
|
||||||
|
obj-$(CONFIG_UT_DM) += bus.o
|
||||||
|
obj-$(CONFIG_UT_DM) += test-driver.o
|
||||||
|
obj-$(CONFIG_UT_DM) += test-fdt.o
|
||||||
|
obj-$(CONFIG_UT_DM) += test-uclass.o
|
||||||
|
|
||||||
obj-$(CONFIG_UT_DM) += core.o
|
obj-$(CONFIG_UT_DM) += core.o
|
||||||
ifneq ($(CONFIG_SANDBOX),)
|
ifneq ($(CONFIG_SANDBOX),)
|
||||||
obj-$(CONFIG_ACPIGEN) += acpi.o
|
obj-$(CONFIG_ACPIGEN) += acpi.o
|
||||||
|
@ -36,6 +39,7 @@ obj-$(CONFIG_DM_MAILBOX) += mailbox.o
|
||||||
obj-$(CONFIG_DM_MMC) += mmc.o
|
obj-$(CONFIG_DM_MMC) += mmc.o
|
||||||
obj-$(CONFIG_CMD_MUX) += mux-cmd.o
|
obj-$(CONFIG_CMD_MUX) += mux-cmd.o
|
||||||
obj-y += fdtdec.o
|
obj-y += fdtdec.o
|
||||||
|
obj-$(CONFIG_UT_DM) += nop.o
|
||||||
obj-y += ofnode.o
|
obj-y += ofnode.o
|
||||||
obj-y += ofread.o
|
obj-y += ofread.o
|
||||||
obj-$(CONFIG_OSD) += osd.o
|
obj-$(CONFIG_OSD) += osd.o
|
||||||
|
@ -88,3 +92,4 @@ ifneq ($(CONFIG_PINMUX),)
|
||||||
obj-$(CONFIG_PINCONF) += pinmux.o
|
obj-$(CONFIG_PINCONF) += pinmux.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif # !SPL
|
||||||
|
|
222
test/dm/of_platdata.c
Normal file
222
test/dm/of_platdata.c
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <dt-structs.h>
|
||||||
|
#include <dm/test.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
#include <test/ut.h>
|
||||||
|
|
||||||
|
/* Test that we can find a device using of-platdata */
|
||||||
|
static int dm_test_of_platdata_base(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_SERIAL, &dev));
|
||||||
|
ut_asserteq_str("sandbox_serial", dev->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_of_platdata_base, UT_TESTF_SCAN_PDATA);
|
||||||
|
|
||||||
|
/* Test that we can read properties from a device */
|
||||||
|
static int dm_test_of_platdata_props(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct dtd_sandbox_spl_test *plat;
|
||||||
|
struct udevice *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Skip the clock */
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev));
|
||||||
|
ut_asserteq_str("sandbox_clk_test", dev->name);
|
||||||
|
|
||||||
|
ut_assertok(uclass_next_device_err(&dev));
|
||||||
|
plat = dev_get_platdata(dev);
|
||||||
|
ut_assert(plat->boolval);
|
||||||
|
ut_asserteq(1, plat->intval);
|
||||||
|
ut_asserteq(4, ARRAY_SIZE(plat->intarray));
|
||||||
|
ut_asserteq(2, plat->intarray[0]);
|
||||||
|
ut_asserteq(3, plat->intarray[1]);
|
||||||
|
ut_asserteq(4, plat->intarray[2]);
|
||||||
|
ut_asserteq(0, plat->intarray[3]);
|
||||||
|
ut_asserteq(5, plat->byteval);
|
||||||
|
ut_asserteq(3, ARRAY_SIZE(plat->bytearray));
|
||||||
|
ut_asserteq(6, plat->bytearray[0]);
|
||||||
|
ut_asserteq(0, plat->bytearray[1]);
|
||||||
|
ut_asserteq(0, plat->bytearray[2]);
|
||||||
|
ut_asserteq(9, ARRAY_SIZE(plat->longbytearray));
|
||||||
|
for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++)
|
||||||
|
ut_asserteq(9 + i, plat->longbytearray[i]);
|
||||||
|
ut_asserteq_str("message", plat->stringval);
|
||||||
|
ut_asserteq(3, ARRAY_SIZE(plat->stringarray));
|
||||||
|
ut_asserteq_str("multi-word", plat->stringarray[0]);
|
||||||
|
ut_asserteq_str("message", plat->stringarray[1]);
|
||||||
|
ut_asserteq_str("", plat->stringarray[2]);
|
||||||
|
|
||||||
|
ut_assertok(uclass_next_device_err(&dev));
|
||||||
|
plat = dev_get_platdata(dev);
|
||||||
|
ut_assert(!plat->boolval);
|
||||||
|
ut_asserteq(3, plat->intval);
|
||||||
|
ut_asserteq(5, plat->intarray[0]);
|
||||||
|
ut_asserteq(0, plat->intarray[1]);
|
||||||
|
ut_asserteq(0, plat->intarray[2]);
|
||||||
|
ut_asserteq(0, plat->intarray[3]);
|
||||||
|
ut_asserteq(8, plat->byteval);
|
||||||
|
ut_asserteq(3, ARRAY_SIZE(plat->bytearray));
|
||||||
|
ut_asserteq(1, plat->bytearray[0]);
|
||||||
|
ut_asserteq(0x23, plat->bytearray[1]);
|
||||||
|
ut_asserteq(0x34, plat->bytearray[2]);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++)
|
||||||
|
ut_asserteq(i < 4 ? 9 + i : 0, plat->longbytearray[i]);
|
||||||
|
ut_asserteq_str("message2", plat->stringval);
|
||||||
|
ut_asserteq_str("another", plat->stringarray[0]);
|
||||||
|
ut_asserteq_str("multi-word", plat->stringarray[1]);
|
||||||
|
ut_asserteq_str("message", plat->stringarray[2]);
|
||||||
|
|
||||||
|
ut_assertok(uclass_next_device_err(&dev));
|
||||||
|
plat = dev_get_platdata(dev);
|
||||||
|
ut_assert(!plat->boolval);
|
||||||
|
ut_asserteq_str("one", plat->stringarray[0]);
|
||||||
|
ut_asserteq_str("", plat->stringarray[1]);
|
||||||
|
ut_asserteq_str("", plat->stringarray[2]);
|
||||||
|
|
||||||
|
ut_assertok(uclass_next_device_err(&dev));
|
||||||
|
plat = dev_get_platdata(dev);
|
||||||
|
ut_assert(!plat->boolval);
|
||||||
|
ut_asserteq_str("spl", plat->stringarray[0]);
|
||||||
|
|
||||||
|
ut_asserteq(-ENODEV, uclass_next_device_err(&dev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_of_platdata_props, UT_TESTF_SCAN_PDATA);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_driver_info - recursively find the driver_info for a device
|
||||||
|
*
|
||||||
|
* This sets found[idx] to true when it finds the driver_info record for a
|
||||||
|
* device, where idx is the index in the driver_info linker list.
|
||||||
|
*
|
||||||
|
* @uts: Test state
|
||||||
|
* @parent: Parent to search
|
||||||
|
* @found: bool array to update
|
||||||
|
* @return 0 if OK, non-zero on error
|
||||||
|
*/
|
||||||
|
static int find_driver_info(struct unit_test_state *uts, struct udevice *parent,
|
||||||
|
bool found[])
|
||||||
|
{
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
/* If not the root device, find the entry that caused it to be bound */
|
||||||
|
if (parent->parent) {
|
||||||
|
const int n_ents =
|
||||||
|
ll_entry_count(struct driver_info, driver_info);
|
||||||
|
int idx = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_ents; i++) {
|
||||||
|
const struct driver_rt *drt = gd_dm_driver_rt() + i;
|
||||||
|
|
||||||
|
if (drt->dev == parent) {
|
||||||
|
idx = i;
|
||||||
|
found[idx] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_assert(idx != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_foreach_child(dev, parent) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = find_driver_info(uts, dev, found);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that every device is recorded in its driver_info struct */
|
||||||
|
static int dm_test_of_platdata_dev(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
const struct driver_info *info =
|
||||||
|
ll_entry_start(struct driver_info, driver_info);
|
||||||
|
const int n_ents = ll_entry_count(struct driver_info, driver_info);
|
||||||
|
bool found[n_ents];
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
/* Record the indexes that are found */
|
||||||
|
memset(found, '\0', sizeof(found));
|
||||||
|
ut_assertok(find_driver_info(uts, gd->dm_root, found));
|
||||||
|
|
||||||
|
/* Make sure that the driver entries without devices have no ->dev */
|
||||||
|
for (i = 0; i < n_ents; i++) {
|
||||||
|
const struct driver_rt *drt = gd_dm_driver_rt() + i;
|
||||||
|
const struct driver_info *entry = info + i;
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
if (found[i]) {
|
||||||
|
/* Make sure we can find it */
|
||||||
|
ut_assertnonnull(drt->dev);
|
||||||
|
ut_assertok(device_get_by_driver_info(entry, &dev));
|
||||||
|
ut_asserteq_ptr(dev, drt->dev);
|
||||||
|
} else {
|
||||||
|
ut_assertnull(drt->dev);
|
||||||
|
ut_asserteq(-ENOENT,
|
||||||
|
device_get_by_driver_info(entry, &dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_of_platdata_dev, UT_TESTF_SCAN_PDATA);
|
||||||
|
|
||||||
|
/* Test handling of phandles that point to other devices */
|
||||||
|
static int dm_test_of_platdata_phandle(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct dtd_sandbox_clk_test *plat;
|
||||||
|
struct udevice *dev, *clk;
|
||||||
|
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev));
|
||||||
|
ut_asserteq_str("sandbox_clk_test", dev->name);
|
||||||
|
plat = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
ut_assertok(device_get_by_driver_info_idx(plat->clocks[0].idx, &clk));
|
||||||
|
ut_asserteq_str("fixed_clock", clk->name);
|
||||||
|
|
||||||
|
ut_assertok(device_get_by_driver_info_idx(plat->clocks[1].idx, &clk));
|
||||||
|
ut_asserteq_str("sandbox_clk", clk->name);
|
||||||
|
ut_asserteq(1, plat->clocks[1].arg[0]);
|
||||||
|
|
||||||
|
ut_assertok(device_get_by_driver_info_idx(plat->clocks[2].idx, &clk));
|
||||||
|
ut_asserteq_str("sandbox_clk", clk->name);
|
||||||
|
ut_asserteq(0, plat->clocks[2].arg[0]);
|
||||||
|
|
||||||
|
ut_assertok(device_get_by_driver_info_idx(plat->clocks[3].idx, &clk));
|
||||||
|
ut_asserteq_str("sandbox_clk", clk->name);
|
||||||
|
ut_asserteq(3, plat->clocks[3].arg[0]);
|
||||||
|
|
||||||
|
ut_assertok(device_get_by_driver_info_idx(plat->clocks[4].idx, &clk));
|
||||||
|
ut_asserteq_str("sandbox_clk", clk->name);
|
||||||
|
ut_asserteq(2, plat->clocks[4].arg[0]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_of_platdata_phandle, UT_TESTF_SCAN_PDATA);
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA_PARENT)
|
||||||
|
/* Test that device parents are correctly set up */
|
||||||
|
static int dm_test_of_platdata_parent(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct udevice *rtc, *i2c;
|
||||||
|
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc));
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
|
||||||
|
ut_asserteq_ptr(i2c, dev_get_parent(rtc));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_of_platdata_parent, UT_TESTF_SCAN_PDATA);
|
||||||
|
#endif
|
|
@ -30,13 +30,12 @@ static int dm_test_init(struct unit_test_state *uts, bool of_live)
|
||||||
|
|
||||||
memset(dms, '\0', sizeof(*dms));
|
memset(dms, '\0', sizeof(*dms));
|
||||||
gd->dm_root = NULL;
|
gd->dm_root = NULL;
|
||||||
memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||||
|
memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
|
||||||
state_reset_for_test(state_get_current());
|
state_reset_for_test(state_get_current());
|
||||||
|
|
||||||
#ifdef CONFIG_OF_LIVE
|
|
||||||
/* Determine whether to make the live tree available */
|
/* Determine whether to make the live tree available */
|
||||||
gd->of_root = of_live ? uts->of_root : NULL;
|
gd_set_of_root(of_live ? uts->of_root : NULL);
|
||||||
#endif
|
|
||||||
ut_assertok(dm_init(of_live));
|
ut_assertok(dm_init(of_live));
|
||||||
dms->root = dm_root();
|
dms->root = dm_root();
|
||||||
|
|
||||||
|
@ -93,7 +92,8 @@ static int dm_do_test(struct unit_test_state *uts, struct unit_test *test,
|
||||||
ut_assertok(dm_scan_platdata(false));
|
ut_assertok(dm_scan_platdata(false));
|
||||||
if (test->flags & UT_TESTF_PROBE_TEST)
|
if (test->flags & UT_TESTF_PROBE_TEST)
|
||||||
ut_assertok(do_autoprobe(uts));
|
ut_assertok(do_autoprobe(uts));
|
||||||
if (test->flags & UT_TESTF_SCAN_FDT)
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
|
||||||
|
(test->flags & UT_TESTF_SCAN_FDT))
|
||||||
ut_assertok(dm_extended_scan_fdt(gd->fdt_blob, false));
|
ut_assertok(dm_extended_scan_fdt(gd->fdt_blob, false));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -127,7 +127,25 @@ static bool dm_test_run_on_flattree(struct unit_test *test)
|
||||||
return !strstr(fname, "video") || strstr(test->name, "video_base");
|
return !strstr(fname, "video") || strstr(test->name, "video_base");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_test_main(const char *test_name)
|
static bool test_matches(const char *test_name, const char *find_name)
|
||||||
|
{
|
||||||
|
if (!find_name)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!strcmp(test_name, find_name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* All tests have this prefix */
|
||||||
|
if (!strncmp(test_name, "dm_test_", 8))
|
||||||
|
test_name += 8;
|
||||||
|
|
||||||
|
if (!strcmp(test_name, find_name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_test_main(const char *test_name)
|
||||||
{
|
{
|
||||||
struct unit_test *tests = ll_entry_start(struct unit_test, dm_test);
|
struct unit_test *tests = ll_entry_start(struct unit_test, dm_test);
|
||||||
const int n_ents = ll_entry_count(struct unit_test, dm_test);
|
const int n_ents = ll_entry_count(struct unit_test, dm_test);
|
||||||
|
@ -138,36 +156,34 @@ static int dm_test_main(const char *test_name)
|
||||||
uts->priv = &_global_priv_dm_test_state;
|
uts->priv = &_global_priv_dm_test_state;
|
||||||
uts->fail_count = 0;
|
uts->fail_count = 0;
|
||||||
|
|
||||||
/*
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
* If we have no device tree, or it only has a root node, then these
|
/*
|
||||||
* tests clearly aren't going to work...
|
* If we have no device tree, or it only has a root node, then
|
||||||
*/
|
* these * tests clearly aren't going to work...
|
||||||
if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
|
*/
|
||||||
puts("Please run with test device tree:\n"
|
if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
|
||||||
" ./u-boot -d arch/sandbox/dts/test.dtb\n");
|
puts("Please run with test device tree:\n"
|
||||||
ut_assert(gd->fdt_blob);
|
" ./u-boot -d arch/sandbox/dts/test.dtb\n");
|
||||||
|
ut_assert(gd->fdt_blob);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!test_name)
|
if (!test_name)
|
||||||
printf("Running %d driver model tests\n", n_ents);
|
printf("Running %d driver model tests\n", n_ents);
|
||||||
|
else
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
#ifdef CONFIG_OF_LIVE
|
uts->of_root = gd_of_root();
|
||||||
uts->of_root = gd->of_root;
|
|
||||||
#endif
|
|
||||||
for (test = tests; test < tests + n_ents; test++) {
|
for (test = tests; test < tests + n_ents; test++) {
|
||||||
const char *name = test->name;
|
const char *name = test->name;
|
||||||
int runs;
|
int runs;
|
||||||
|
|
||||||
/* All tests have this prefix */
|
if (!test_matches(name, test_name))
|
||||||
if (!strncmp(name, "dm_test_", 8))
|
|
||||||
name += 8;
|
|
||||||
if (test_name && strcmp(test_name, name))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Run with the live tree if possible */
|
/* Run with the live tree if possible */
|
||||||
runs = 0;
|
runs = 0;
|
||||||
if (IS_ENABLED(CONFIG_OF_LIVE)) {
|
if (CONFIG_IS_ENABLED(OF_LIVE)) {
|
||||||
if (!(test->flags & UT_TESTF_FLAT_TREE)) {
|
if (!(test->flags & UT_TESTF_FLAT_TREE)) {
|
||||||
ut_assertok(dm_do_test(uts, test, true));
|
ut_assertok(dm_do_test(uts, test, true));
|
||||||
runs++;
|
runs++;
|
||||||
|
@ -192,13 +208,12 @@ static int dm_test_main(const char *test_name)
|
||||||
printf("Failures: %d\n", uts->fail_count);
|
printf("Failures: %d\n", uts->fail_count);
|
||||||
|
|
||||||
/* Put everything back to normal so that sandbox works as expected */
|
/* Put everything back to normal so that sandbox works as expected */
|
||||||
#ifdef CONFIG_OF_LIVE
|
gd_set_of_root(uts->of_root);
|
||||||
gd->of_root = uts->of_root;
|
|
||||||
#endif
|
|
||||||
gd->dm_root = NULL;
|
gd->dm_root = NULL;
|
||||||
ut_assertok(dm_init(IS_ENABLED(CONFIG_OF_LIVE)));
|
ut_assertok(dm_init(CONFIG_IS_ENABLED(OF_LIVE)));
|
||||||
dm_scan_platdata(false);
|
dm_scan_platdata(false);
|
||||||
dm_scan_fdt(gd->fdt_blob, false);
|
if (!CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||||
|
dm_scan_fdt(gd->fdt_blob, false);
|
||||||
|
|
||||||
return uts->fail_count ? CMD_RET_FAILURE : 0;
|
return uts->fail_count ? CMD_RET_FAILURE : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ def pytest_configure(config):
|
||||||
console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
|
console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
|
||||||
|
|
||||||
re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')
|
re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')
|
||||||
def generate_ut_subtest(metafunc, fixture_name):
|
def generate_ut_subtest(metafunc, fixture_name, sym_path):
|
||||||
"""Provide parametrization for a ut_subtest fixture.
|
"""Provide parametrization for a ut_subtest fixture.
|
||||||
|
|
||||||
Determines the set of unit tests built into a U-Boot binary by parsing the
|
Determines the set of unit tests built into a U-Boot binary by parsing the
|
||||||
|
@ -237,12 +237,13 @@ def generate_ut_subtest(metafunc, fixture_name):
|
||||||
Args:
|
Args:
|
||||||
metafunc: The pytest test function.
|
metafunc: The pytest test function.
|
||||||
fixture_name: The fixture name to test.
|
fixture_name: The fixture name to test.
|
||||||
|
sym_path: Relative path to the symbol file with preceding '/'
|
||||||
|
(e.g. '/u-boot.sym')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Nothing.
|
Nothing.
|
||||||
"""
|
"""
|
||||||
|
fn = console.config.build_dir + sym_path
|
||||||
fn = console.config.build_dir + '/u-boot.sym'
|
|
||||||
try:
|
try:
|
||||||
with open(fn, 'rt') as f:
|
with open(fn, 'rt') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
@ -317,10 +318,12 @@ def pytest_generate_tests(metafunc):
|
||||||
Returns:
|
Returns:
|
||||||
Nothing.
|
Nothing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for fn in metafunc.fixturenames:
|
for fn in metafunc.fixturenames:
|
||||||
if fn == 'ut_subtest':
|
if fn == 'ut_subtest':
|
||||||
generate_ut_subtest(metafunc, fn)
|
generate_ut_subtest(metafunc, fn, '/u-boot.sym')
|
||||||
|
continue
|
||||||
|
if fn == 'ut_spl_subtest':
|
||||||
|
generate_ut_subtest(metafunc, fn, '/spl/u-boot-spl.sym')
|
||||||
continue
|
continue
|
||||||
generate_config(metafunc, fn)
|
generate_config(metafunc, fn)
|
||||||
|
|
||||||
|
|
|
@ -4,53 +4,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
import u_boot_utils as util
|
import u_boot_utils as util
|
||||||
|
|
||||||
OF_PLATDATA_OUTPUT = '''
|
|
||||||
of-platdata probe:
|
|
||||||
bool 1
|
|
||||||
byte 05
|
|
||||||
bytearray 06 00 00
|
|
||||||
int 1
|
|
||||||
intarray 2 3 4 0
|
|
||||||
longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
|
|
||||||
string message
|
|
||||||
stringarray "multi-word" "message" ""
|
|
||||||
of-platdata probe:
|
|
||||||
bool 0
|
|
||||||
byte 08
|
|
||||||
bytearray 01 23 34
|
|
||||||
int 3
|
|
||||||
intarray 5 0 0 0
|
|
||||||
longbytearray 09 00 00 00 00 00 00 00 00
|
|
||||||
string message2
|
|
||||||
stringarray "another" "multi-word" "message"
|
|
||||||
of-platdata probe:
|
|
||||||
bool 0
|
|
||||||
byte 00
|
|
||||||
bytearray 00 00 00
|
|
||||||
int 0
|
|
||||||
intarray 0 0 0 0
|
|
||||||
longbytearray 00 00 00 00 00 00 00 00 00
|
|
||||||
string <NULL>
|
|
||||||
stringarray "one" "" ""
|
|
||||||
of-platdata probe:
|
|
||||||
bool 0
|
|
||||||
byte 00
|
|
||||||
bytearray 00 00 00
|
|
||||||
int 0
|
|
||||||
intarray 0 0 0 0
|
|
||||||
longbytearray 00 00 00 00 00 00 00 00 00
|
|
||||||
string <NULL>
|
|
||||||
stringarray "spl" "" ""
|
|
||||||
'''
|
|
||||||
|
|
||||||
@pytest.mark.buildconfigspec('spl_of_platdata')
|
|
||||||
def test_ofplatdata(u_boot_console):
|
|
||||||
"""Test that of-platdata can be generated and used in sandbox"""
|
|
||||||
cons = u_boot_console
|
|
||||||
cons.restart_uboot_with_flags(['--show_of_platdata'])
|
|
||||||
output = cons.get_spawn_output().replace('\r', '')
|
|
||||||
assert OF_PLATDATA_OUTPUT in output
|
|
||||||
|
|
||||||
@pytest.mark.buildconfigspec('spl_of_platdata')
|
@pytest.mark.buildconfigspec('spl_of_platdata')
|
||||||
def test_spl_devicetree(u_boot_console):
|
def test_spl_devicetree(u_boot_console):
|
||||||
"""Test content of spl device-tree"""
|
"""Test content of spl device-tree"""
|
||||||
|
|
34
test/py/tests/test_spl.py
Normal file
34
test/py/tests/test_spl.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright 2020 Google LLC
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_spl(u_boot_console, ut_spl_subtest):
|
||||||
|
"""Execute a "ut" subtest.
|
||||||
|
|
||||||
|
The subtests are collected in function generate_ut_subtest() from linker
|
||||||
|
generated lists by applying a regular expression to the lines of file
|
||||||
|
spl/u-boot-spl.sym. The list entries are created using the C macro
|
||||||
|
UNIT_TEST().
|
||||||
|
|
||||||
|
Strict naming conventions have to be followed to match the regular
|
||||||
|
expression. Use UNIT_TEST(foo_test_bar, _flags, foo_test) for a test bar in
|
||||||
|
test suite foo that can be executed via command 'ut foo bar' and is
|
||||||
|
implemented in C function foo_test_bar().
|
||||||
|
|
||||||
|
Args:
|
||||||
|
u_boot_console (ConsoleBase): U-Boot console
|
||||||
|
ut_subtest (str): SPL test to be executed (e.g. 'dm platdata_phandle')
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
cons = u_boot_console
|
||||||
|
cons.restart_uboot_with_flags(['-u', '-k', ut_spl_subtest.split()[1]])
|
||||||
|
output = cons.get_spawn_output().replace('\r', '')
|
||||||
|
assert 'Failures: 0' in output
|
||||||
|
finally:
|
||||||
|
# Restart afterward in case a non-SPL test is run next. This should not
|
||||||
|
# happen since SPL tests are run in their own invocation of test.py, but
|
||||||
|
# the cost of doing this is not too great at present.
|
||||||
|
u_boot_console.restart_uboot()
|
2
test/run
2
test/run
|
@ -28,7 +28,7 @@ fi
|
||||||
|
|
||||||
# Run tests which require sandbox_spl
|
# Run tests which require sandbox_spl
|
||||||
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
|
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
|
||||||
-k 'test_ofplatdata or test_handoff'
|
-k 'test_ofplatdata or test_handoff or test_spl'
|
||||||
|
|
||||||
if [ -z "$tools_only" ]; then
|
if [ -z "$tools_only" ]; then
|
||||||
# Run tests for the flat-device-tree version of sandbox. This is a special
|
# Run tests for the flat-device-tree version of sandbox. This is a special
|
||||||
|
|
|
@ -278,9 +278,12 @@ offset:
|
||||||
|
|
||||||
align:
|
align:
|
||||||
This sets the alignment of the entry. The entry offset is adjusted
|
This sets the alignment of the entry. The entry offset is adjusted
|
||||||
so that the entry starts on an aligned boundary within the image. For
|
so that the entry starts on an aligned boundary within the containing
|
||||||
example 'align = <16>' means that the entry will start on a 16-byte
|
section or image. For example 'align = <16>' means that the entry will
|
||||||
boundary. Alignment shold be a power of 2. If 'align' is not
|
start on a 16-byte boundary. This may mean that padding is added before
|
||||||
|
the entry. The padding is part of the containing section but is not
|
||||||
|
included in the entry, meaning that an empty space may be created before
|
||||||
|
the entry starts. Alignment should be a power of 2. If 'align' is not
|
||||||
provided, no alignment is performed.
|
provided, no alignment is performed.
|
||||||
|
|
||||||
size:
|
size:
|
||||||
|
@ -290,26 +293,40 @@ size:
|
||||||
|
|
||||||
pad-before:
|
pad-before:
|
||||||
Padding before the contents of the entry. Normally this is 0, meaning
|
Padding before the contents of the entry. Normally this is 0, meaning
|
||||||
that the contents start at the beginning of the entry. This can be
|
that the contents start at the beginning of the entry. This can be used
|
||||||
offset the entry contents a little. Defaults to 0.
|
to offset the entry contents a little. While this does not affect the
|
||||||
|
contents of the entry within binman itself (the padding is performed
|
||||||
|
only when its parent section is assembled), the end result will be that
|
||||||
|
the entry starts with the padding bytes, so may grow. Defaults to 0.
|
||||||
|
|
||||||
pad-after:
|
pad-after:
|
||||||
Padding after the contents of the entry. Normally this is 0, meaning
|
Padding after the contents of the entry. Normally this is 0, meaning
|
||||||
that the entry ends at the last byte of content (unless adjusted by
|
that the entry ends at the last byte of content (unless adjusted by
|
||||||
other properties). This allows room to be created in the image for
|
other properties). This allows room to be created in the image for
|
||||||
this entry to expand later. Defaults to 0.
|
this entry to expand later. While this does not affect the contents of
|
||||||
|
the entry within binman itself (the padding is performed only when its
|
||||||
|
parent section is assembled), the end result will be that the entry ends
|
||||||
|
with the padding bytes, so may grow. Defaults to 0.
|
||||||
|
|
||||||
align-size:
|
align-size:
|
||||||
This sets the alignment of the entry size. For example, to ensure
|
This sets the alignment of the entry size. For example, to ensure
|
||||||
that the size of an entry is a multiple of 64 bytes, set this to 64.
|
that the size of an entry is a multiple of 64 bytes, set this to 64.
|
||||||
If 'align-size' is not provided, no alignment is performed.
|
While this does not affect the contents of the entry within binman
|
||||||
|
itself (the padding is performed only when its parent section is
|
||||||
|
assembled), the end result is that the entry ends with the padding
|
||||||
|
bytes, so may grow. If 'align-size' is not provided, no alignment is
|
||||||
|
performed.
|
||||||
|
|
||||||
align-end:
|
align-end:
|
||||||
This sets the alignment of the end of an entry. Some entries require
|
This sets the alignment of the end of an entry with respect to the
|
||||||
that they end on an alignment boundary, regardless of where they
|
containing section. Some entries require that they end on an alignment
|
||||||
start. This does not move the start of the entry, so the contents of
|
boundary, regardless of where they start. This does not move the start
|
||||||
the entry will still start at the beginning. But there may be padding
|
of the entry, so the contents of the entry will still start at the
|
||||||
at the end. If 'align-end' is not provided, no alignment is performed.
|
beginning. But there may be padding at the end. While this does not
|
||||||
|
affect the contents of the entry within binman itself (the padding is
|
||||||
|
performed only when its parent section is assembled), the end result
|
||||||
|
is that the entry ends with the padding bytes, so may grow.
|
||||||
|
If 'align-end' is not provided, no alignment is performed.
|
||||||
|
|
||||||
filename:
|
filename:
|
||||||
For 'blob' types this provides the filename containing the binary to
|
For 'blob' types this provides the filename containing the binary to
|
||||||
|
@ -695,41 +712,38 @@ size of an entry. The 'current' image offset is passed in, and the function
|
||||||
returns the offset immediately after the entry being packed. The default
|
returns the offset immediately after the entry being packed. The default
|
||||||
implementation of Pack() is usually sufficient.
|
implementation of Pack() is usually sufficient.
|
||||||
|
|
||||||
6. CheckSize() - checks that the contents of all the entries fits within
|
Note: for sections, this also checks that the entries do not overlap, nor extend
|
||||||
the image size. If the image does not have a defined size, the size is set
|
outside the section. If the section does not have a defined size, the size is
|
||||||
large enough to hold all the entries.
|
set large enough to hold all the entries.
|
||||||
|
|
||||||
7. CheckEntries() - checks that the entries do not overlap, nor extend
|
6. SetImagePos() - sets the image position of every entry. This is the absolute
|
||||||
outside the image.
|
|
||||||
|
|
||||||
8. SetImagePos() - sets the image position of every entry. This is the absolute
|
|
||||||
position 'image-pos', as opposed to 'offset' which is relative to the containing
|
position 'image-pos', as opposed to 'offset' which is relative to the containing
|
||||||
section. This must be done after all offsets are known, which is why it is quite
|
section. This must be done after all offsets are known, which is why it is quite
|
||||||
late in the ordering.
|
late in the ordering.
|
||||||
|
|
||||||
9. SetCalculatedProperties() - update any calculated properties in the device
|
7. SetCalculatedProperties() - update any calculated properties in the device
|
||||||
tree. This sets the correct 'offset' and 'size' vaues, for example.
|
tree. This sets the correct 'offset' and 'size' vaues, for example.
|
||||||
|
|
||||||
10. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry.
|
8. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry.
|
||||||
The default implementatoin does nothing. This can be overriden to adjust the
|
The default implementatoin does nothing. This can be overriden to adjust the
|
||||||
contents of an entry in some way. For example, it would be possible to create
|
contents of an entry in some way. For example, it would be possible to create
|
||||||
an entry containing a hash of the contents of some other entries. At this
|
an entry containing a hash of the contents of some other entries. At this
|
||||||
stage the offset and size of entries should not be adjusted unless absolutely
|
stage the offset and size of entries should not be adjusted unless absolutely
|
||||||
necessary, since it requires a repack (going back to PackEntries()).
|
necessary, since it requires a repack (going back to PackEntries()).
|
||||||
|
|
||||||
11. ResetForPack() - if the ProcessEntryContents() step failed, in that an entry
|
9. ResetForPack() - if the ProcessEntryContents() step failed, in that an entry
|
||||||
has changed its size, then there is no alternative but to go back to step 5 and
|
has changed its size, then there is no alternative but to go back to step 5 and
|
||||||
try again, repacking the entries with the updated size. ResetForPack() removes
|
try again, repacking the entries with the updated size. ResetForPack() removes
|
||||||
the fixed offset/size values added by binman, so that the packing can start from
|
the fixed offset/size values added by binman, so that the packing can start from
|
||||||
scratch.
|
scratch.
|
||||||
|
|
||||||
12. WriteSymbols() - write the value of symbols into the U-Boot SPL binary.
|
10. WriteSymbols() - write the value of symbols into the U-Boot SPL binary.
|
||||||
See 'Access to binman entry offsets at run time' below for a description of
|
See 'Access to binman entry offsets at run time' below for a description of
|
||||||
what happens in this stage.
|
what happens in this stage.
|
||||||
|
|
||||||
13. BuildImage() - builds the image and writes it to a file
|
11. BuildImage() - builds the image and writes it to a file
|
||||||
|
|
||||||
14. WriteMap() - writes a text file containing a map of the image. This is the
|
12. WriteMap() - writes a text file containing a map of the image. This is the
|
||||||
final step.
|
final step.
|
||||||
|
|
||||||
|
|
||||||
|
@ -839,6 +853,14 @@ The entry will then contain the compressed data, using the 'lz4' compression
|
||||||
algorithm. Currently this is the only one that is supported. The uncompressed
|
algorithm. Currently this is the only one that is supported. The uncompressed
|
||||||
size is written to the node in an 'uncomp-size' property, if -u is used.
|
size is written to the node in an 'uncomp-size' property, if -u is used.
|
||||||
|
|
||||||
|
Compression is also supported for sections. In that case the entire section is
|
||||||
|
compressed in one block, including all its contents. This means that accessing
|
||||||
|
an entry from the section required decompressing the entire section. Also, the
|
||||||
|
size of a section indicates the space that it consumes in its parent section
|
||||||
|
(and typically the image). With compression, the section may contain more data,
|
||||||
|
and the uncomp-size property indicates that, as above. The contents of the
|
||||||
|
section is compressed first, before any padding is added. This ensures that the
|
||||||
|
padding itself is not compressed, which would be a waste of time.
|
||||||
|
|
||||||
|
|
||||||
Map files
|
Map files
|
||||||
|
|
|
@ -299,7 +299,7 @@ Entry: files: Entry containing a set of files
|
||||||
|
|
||||||
Properties / Entry arguments:
|
Properties / Entry arguments:
|
||||||
- pattern: Filename pattern to match the files to include
|
- pattern: Filename pattern to match the files to include
|
||||||
- compress: Compression algorithm to use:
|
- files-compress: Compression algorithm to use:
|
||||||
none: No compression
|
none: No compression
|
||||||
lz4: Use lz4 compression (via 'lz4' command-line utility)
|
lz4: Use lz4 compression (via 'lz4' command-line utility)
|
||||||
|
|
||||||
|
@ -406,6 +406,10 @@ The 'default' property, if present, will be automatically set to the name
|
||||||
if of configuration whose devicetree matches the 'default-dt' entry
|
if of configuration whose devicetree matches the 'default-dt' entry
|
||||||
argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
|
argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
|
||||||
|
|
||||||
|
Available substitutions for '@' property values are:
|
||||||
|
|
||||||
|
DEFAULT-SEQ Sequence number of the default fdt,as provided by the
|
||||||
|
'default-dt' entry argument
|
||||||
|
|
||||||
Properties (in the 'fit' node itself):
|
Properties (in the 'fit' node itself):
|
||||||
fit,external-offset: Indicates that the contents of the FIT are external
|
fit,external-offset: Indicates that the contents of the FIT are external
|
||||||
|
@ -739,6 +743,16 @@ placed at offset 'RESET_VECTOR_ADDRESS - 0xffc'.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Entry: scp: Entry containing a System Control Processor (SCP) firmware blob
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Properties / Entry arguments:
|
||||||
|
- scp-path: Filename of file to read into the entry, typically scp.bin
|
||||||
|
|
||||||
|
This entry holds firmware for an external platform-specific coprocessor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Entry: section: Entry that contains other entries
|
Entry: section: Entry that contains other entries
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
|
@ -878,6 +892,15 @@ relocated to any address for execution.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Entry: u-boot-env: An entry which contains a U-Boot environment
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
Properties / Entry arguments:
|
||||||
|
- filename: File containing the environment text, with each line in the
|
||||||
|
form var=value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Entry: u-boot-img: U-Boot legacy image
|
Entry: u-boot-img: U-Boot legacy image
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ controlled by a description in the board device tree.'''
|
||||||
'3=info, 4=detail, 5=debug')
|
'3=info, 4=detail, 5=debug')
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest='cmd')
|
subparsers = parser.add_subparsers(dest='cmd')
|
||||||
|
subparsers.required = True
|
||||||
|
|
||||||
build_parser = subparsers.add_parser('build', help='Build firmware image')
|
build_parser = subparsers.add_parser('build', help='Build firmware image')
|
||||||
build_parser.add_argument('-a', '--entry-arg', type=str, action='append',
|
build_parser.add_argument('-a', '--entry-arg', type=str, action='append',
|
||||||
|
|
|
@ -462,7 +462,7 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
|
||||||
for image in images.values():
|
for image in images.values():
|
||||||
image.ExpandEntries()
|
image.ExpandEntries()
|
||||||
if update_fdt:
|
if update_fdt:
|
||||||
image.AddMissingProperties()
|
image.AddMissingProperties(True)
|
||||||
image.ProcessFdt(dtb)
|
image.ProcessFdt(dtb)
|
||||||
|
|
||||||
for dtb_item in state.GetAllFdts():
|
for dtb_item in state.GetAllFdts():
|
||||||
|
@ -513,8 +513,6 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
|
||||||
for pack_pass in range(passes):
|
for pack_pass in range(passes):
|
||||||
try:
|
try:
|
||||||
image.PackEntries()
|
image.PackEntries()
|
||||||
image.CheckSize()
|
|
||||||
image.CheckEntries()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if write_map:
|
if write_map:
|
||||||
fname = image.WriteMap()
|
fname = image.WriteMap()
|
||||||
|
|
|
@ -48,12 +48,22 @@ class Entry(object):
|
||||||
uncomp_size: Size of uncompressed data in bytes, if the entry is
|
uncomp_size: Size of uncompressed data in bytes, if the entry is
|
||||||
compressed, else None
|
compressed, else None
|
||||||
contents_size: Size of contents in bytes, 0 by default
|
contents_size: Size of contents in bytes, 0 by default
|
||||||
align: Entry start offset alignment, or None
|
align: Entry start offset alignment relative to the start of the
|
||||||
|
containing section, or None
|
||||||
align_size: Entry size alignment, or None
|
align_size: Entry size alignment, or None
|
||||||
align_end: Entry end offset alignment, or None
|
align_end: Entry end offset alignment relative to the start of the
|
||||||
pad_before: Number of pad bytes before the contents, 0 if none
|
containing section, or None
|
||||||
pad_after: Number of pad bytes after the contents, 0 if none
|
pad_before: Number of pad bytes before the contents when it is placed
|
||||||
data: Contents of entry (string of bytes)
|
in the containing section, 0 if none. The pad bytes become part of
|
||||||
|
the entry.
|
||||||
|
pad_after: Number of pad bytes after the contents when it is placed in
|
||||||
|
the containing section, 0 if none. The pad bytes become part of
|
||||||
|
the entry.
|
||||||
|
data: Contents of entry (string of bytes). This does not include
|
||||||
|
padding created by pad_before or pad_after. If the entry is
|
||||||
|
compressed, this contains the compressed data.
|
||||||
|
uncomp_data: Original uncompressed data, if this entry is compressed,
|
||||||
|
else None
|
||||||
compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
|
compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
|
||||||
orig_offset: Original offset value read from node
|
orig_offset: Original offset value read from node
|
||||||
orig_size: Original size value read from node
|
orig_size: Original size value read from node
|
||||||
|
@ -76,6 +86,7 @@ class Entry(object):
|
||||||
self.pre_reset_size = None
|
self.pre_reset_size = None
|
||||||
self.uncomp_size = None
|
self.uncomp_size = None
|
||||||
self.data = None
|
self.data = None
|
||||||
|
self.uncomp_data = None
|
||||||
self.contents_size = 0
|
self.contents_size = 0
|
||||||
self.align = None
|
self.align = None
|
||||||
self.align_size = None
|
self.align_size = None
|
||||||
|
@ -180,6 +191,9 @@ class Entry(object):
|
||||||
self.expand_size = fdt_util.GetBool(self._node, 'expand-size')
|
self.expand_size = fdt_util.GetBool(self._node, 'expand-size')
|
||||||
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
|
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
|
||||||
|
|
||||||
|
# This is only supported by blobs and sections at present
|
||||||
|
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
||||||
|
|
||||||
def GetDefaultFilename(self):
|
def GetDefaultFilename(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -199,11 +213,20 @@ class Entry(object):
|
||||||
def ExpandEntries(self):
|
def ExpandEntries(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def AddMissingProperties(self):
|
def AddMissingProperties(self, have_image_pos):
|
||||||
"""Add new properties to the device tree as needed for this entry"""
|
"""Add new properties to the device tree as needed for this entry
|
||||||
for prop in ['offset', 'size', 'image-pos']:
|
|
||||||
|
Args:
|
||||||
|
have_image_pos: True if this entry has an image position. This can
|
||||||
|
be False if its parent section is compressed, since compression
|
||||||
|
groups all entries together into a compressed block of data,
|
||||||
|
obscuring the start of each individual child entry
|
||||||
|
"""
|
||||||
|
for prop in ['offset', 'size']:
|
||||||
if not prop in self._node.props:
|
if not prop in self._node.props:
|
||||||
state.AddZeroProp(self._node, prop)
|
state.AddZeroProp(self._node, prop)
|
||||||
|
if have_image_pos and 'image-pos' not in self._node.props:
|
||||||
|
state.AddZeroProp(self._node, 'image-pos')
|
||||||
if self.GetImage().allow_repack:
|
if self.GetImage().allow_repack:
|
||||||
if self.orig_offset is not None:
|
if self.orig_offset is not None:
|
||||||
state.AddZeroProp(self._node, 'orig-offset', True)
|
state.AddZeroProp(self._node, 'orig-offset', True)
|
||||||
|
@ -221,7 +244,8 @@ class Entry(object):
|
||||||
state.SetInt(self._node, 'offset', self.offset)
|
state.SetInt(self._node, 'offset', self.offset)
|
||||||
state.SetInt(self._node, 'size', self.size)
|
state.SetInt(self._node, 'size', self.size)
|
||||||
base = self.section.GetRootSkipAtStart() if self.section else 0
|
base = self.section.GetRootSkipAtStart() if self.section else 0
|
||||||
state.SetInt(self._node, 'image-pos', self.image_pos - base)
|
if self.image_pos is not None:
|
||||||
|
state.SetInt(self._node, 'image-pos', self.image_pos)
|
||||||
if self.GetImage().allow_repack:
|
if self.GetImage().allow_repack:
|
||||||
if self.orig_offset is not None:
|
if self.orig_offset is not None:
|
||||||
state.SetInt(self._node, 'orig-offset', self.orig_offset, True)
|
state.SetInt(self._node, 'orig-offset', self.orig_offset, True)
|
||||||
|
@ -423,6 +447,12 @@ class Entry(object):
|
||||||
return self._node.path
|
return self._node.path
|
||||||
|
|
||||||
def GetData(self):
|
def GetData(self):
|
||||||
|
"""Get the contents of an entry
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bytes content of the entry, excluding any padding. If the entry is
|
||||||
|
compressed, the compressed data is returned
|
||||||
|
"""
|
||||||
self.Detail('GetData: size %s' % ToHexSize(self.data))
|
self.Detail('GetData: size %s' % ToHexSize(self.data))
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
|
@ -490,7 +520,7 @@ class Entry(object):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def CheckOffset(self):
|
def CheckEntries(self):
|
||||||
"""Check that the entry offsets are correct
|
"""Check that the entry offsets are correct
|
||||||
|
|
||||||
This is used for entries which have extra offset requirements (other
|
This is used for entries which have extra offset requirements (other
|
||||||
|
@ -836,3 +866,18 @@ features to produce new behaviours.
|
||||||
list of possible tags, most desirable first
|
list of possible tags, most desirable first
|
||||||
"""
|
"""
|
||||||
return list(filter(None, [self.missing_msg, self.name, self.etype]))
|
return list(filter(None, [self.missing_msg, self.name, self.etype]))
|
||||||
|
|
||||||
|
def CompressData(self, indata):
|
||||||
|
"""Compress data according to the entry's compression method
|
||||||
|
|
||||||
|
Args:
|
||||||
|
indata: Data to compress
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Compressed data (first word is the compressed size)
|
||||||
|
"""
|
||||||
|
self.uncomp_data = indata
|
||||||
|
if self.compress != 'none':
|
||||||
|
self.uncomp_size = len(indata)
|
||||||
|
data = tools.Compress(indata, self.compress)
|
||||||
|
return data
|
||||||
|
|
|
@ -33,7 +33,6 @@ class Entry_blob(Entry):
|
||||||
def __init__(self, section, etype, node):
|
def __init__(self, section, etype, node):
|
||||||
super().__init__(section, etype, node)
|
super().__init__(section, etype, node)
|
||||||
self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
|
self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
|
||||||
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
|
||||||
|
|
||||||
def ObtainContents(self):
|
def ObtainContents(self):
|
||||||
self._filename = self.GetDefaultFilename()
|
self._filename = self.GetDefaultFilename()
|
||||||
|
@ -48,12 +47,6 @@ class Entry_blob(Entry):
|
||||||
self.ReadBlobContents()
|
self.ReadBlobContents()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def CompressData(self, indata):
|
|
||||||
if self.compress != 'none':
|
|
||||||
self.uncomp_size = len(indata)
|
|
||||||
data = tools.Compress(indata, self.compress)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def ReadBlobContents(self):
|
def ReadBlobContents(self):
|
||||||
"""Read blob contents into memory
|
"""Read blob contents into memory
|
||||||
|
|
||||||
|
|
|
@ -237,10 +237,10 @@ class Entry_cbfs(Entry):
|
||||||
if entry._cbfs_compress:
|
if entry._cbfs_compress:
|
||||||
entry.uncomp_size = cfile.memlen
|
entry.uncomp_size = cfile.memlen
|
||||||
|
|
||||||
def AddMissingProperties(self):
|
def AddMissingProperties(self, have_image_pos):
|
||||||
super().AddMissingProperties()
|
super().AddMissingProperties(have_image_pos)
|
||||||
for entry in self._cbfs_entries.values():
|
for entry in self._cbfs_entries.values():
|
||||||
entry.AddMissingProperties()
|
entry.AddMissingProperties(have_image_pos)
|
||||||
if entry._cbfs_compress:
|
if entry._cbfs_compress:
|
||||||
state.AddZeroProp(entry._node, 'uncomp-size')
|
state.AddZeroProp(entry._node, 'uncomp-size')
|
||||||
# Store the 'compress' property, since we don't look at
|
# Store the 'compress' property, since we don't look at
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Entry_files(Entry_section):
|
||||||
|
|
||||||
Properties / Entry arguments:
|
Properties / Entry arguments:
|
||||||
- pattern: Filename pattern to match the files to include
|
- pattern: Filename pattern to match the files to include
|
||||||
- compress: Compression algorithm to use:
|
- files-compress: Compression algorithm to use:
|
||||||
none: No compression
|
none: No compression
|
||||||
lz4: Use lz4 compression (via 'lz4' command-line utility)
|
lz4: Use lz4 compression (via 'lz4' command-line utility)
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ class Entry_files(Entry_section):
|
||||||
self._pattern = fdt_util.GetString(self._node, 'pattern')
|
self._pattern = fdt_util.GetString(self._node, 'pattern')
|
||||||
if not self._pattern:
|
if not self._pattern:
|
||||||
self.Raise("Missing 'pattern' property")
|
self.Raise("Missing 'pattern' property")
|
||||||
self._compress = fdt_util.GetString(self._node, 'compress', 'none')
|
self._files_compress = fdt_util.GetString(self._node, 'files-compress',
|
||||||
|
'none')
|
||||||
self._require_matches = fdt_util.GetBool(self._node,
|
self._require_matches = fdt_util.GetBool(self._node,
|
||||||
'require-matches')
|
'require-matches')
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ class Entry_files(Entry_section):
|
||||||
subnode = state.AddSubnode(self._node, name)
|
subnode = state.AddSubnode(self._node, name)
|
||||||
state.AddString(subnode, 'type', 'blob')
|
state.AddString(subnode, 'type', 'blob')
|
||||||
state.AddString(subnode, 'filename', fname)
|
state.AddString(subnode, 'filename', fname)
|
||||||
state.AddString(subnode, 'compress', self._compress)
|
state.AddString(subnode, 'compress', self._files_compress)
|
||||||
|
|
||||||
# Read entries again, now that we have some
|
# Read entries again, now that we have some
|
||||||
self._ReadEntries()
|
self._ReadEntries()
|
||||||
|
|
|
@ -16,6 +16,7 @@ from binman.entry import Entry
|
||||||
from dtoc import fdt_util
|
from dtoc import fdt_util
|
||||||
from patman import tools
|
from patman import tools
|
||||||
from patman import tout
|
from patman import tout
|
||||||
|
from patman.tools import ToHexSize
|
||||||
|
|
||||||
|
|
||||||
class Entry_section(Entry):
|
class Entry_section(Entry):
|
||||||
|
@ -56,7 +57,7 @@ class Entry_section(Entry):
|
||||||
self._end_4gb = False
|
self._end_4gb = False
|
||||||
|
|
||||||
def ReadNode(self):
|
def ReadNode(self):
|
||||||
"""Read properties from the image node"""
|
"""Read properties from the section node"""
|
||||||
super().ReadNode()
|
super().ReadNode()
|
||||||
self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
|
self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
|
||||||
self._sort = fdt_util.GetBool(self._node, 'sort-by-offset')
|
self._sort = fdt_util.GetBool(self._node, 'sort-by-offset')
|
||||||
|
@ -135,32 +136,113 @@ class Entry_section(Entry):
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
entry.ExpandEntries()
|
entry.ExpandEntries()
|
||||||
|
|
||||||
def AddMissingProperties(self):
|
def AddMissingProperties(self, have_image_pos):
|
||||||
"""Add new properties to the device tree as needed for this entry"""
|
"""Add new properties to the device tree as needed for this entry"""
|
||||||
super().AddMissingProperties()
|
super().AddMissingProperties(have_image_pos)
|
||||||
|
if self.compress != 'none':
|
||||||
|
have_image_pos = False
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
entry.AddMissingProperties()
|
entry.AddMissingProperties(have_image_pos)
|
||||||
|
|
||||||
def ObtainContents(self):
|
def ObtainContents(self):
|
||||||
return self.GetEntryContents()
|
return self.GetEntryContents()
|
||||||
|
|
||||||
def GetData(self):
|
def GetPaddedDataForEntry(self, entry, entry_data):
|
||||||
|
"""Get the data for an entry including any padding
|
||||||
|
|
||||||
|
Gets the entry data and uses the section pad-byte value to add padding
|
||||||
|
before and after as defined by the pad-before and pad-after properties.
|
||||||
|
This does not consider alignment.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
entry: Entry to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Contents of the entry along with any pad bytes before and
|
||||||
|
after it (bytes)
|
||||||
|
"""
|
||||||
|
pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
|
||||||
|
else self._pad_byte)
|
||||||
|
|
||||||
|
data = b''
|
||||||
|
# Handle padding before the entry
|
||||||
|
if entry.pad_before:
|
||||||
|
data += tools.GetBytes(self._pad_byte, entry.pad_before)
|
||||||
|
|
||||||
|
# Add in the actual entry data
|
||||||
|
data += entry_data
|
||||||
|
|
||||||
|
# Handle padding after the entry
|
||||||
|
if entry.pad_after:
|
||||||
|
data += tools.GetBytes(self._pad_byte, entry.pad_after)
|
||||||
|
|
||||||
|
if entry.size:
|
||||||
|
data += tools.GetBytes(pad_byte, entry.size - len(data))
|
||||||
|
|
||||||
|
self.Detail('GetPaddedDataForEntry: size %s' % ToHexSize(self.data))
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _BuildSectionData(self):
|
||||||
|
"""Build the contents of a section
|
||||||
|
|
||||||
|
This places all entries at the right place, dealing with padding before
|
||||||
|
and after entries. It does not do padding for the section itself (the
|
||||||
|
pad-before and pad-after properties in the section items) since that is
|
||||||
|
handled by the parent section.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Contents of the section (bytes)
|
||||||
|
"""
|
||||||
section_data = b''
|
section_data = b''
|
||||||
|
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
data = entry.GetData()
|
data = self.GetPaddedDataForEntry(entry, entry.GetData())
|
||||||
base = self.pad_before + (entry.offset or 0) - self._skip_at_start
|
# Handle empty space before the entry
|
||||||
pad = base - len(section_data) + (entry.pad_before or 0)
|
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
|
||||||
if pad > 0:
|
if pad > 0:
|
||||||
section_data += tools.GetBytes(self._pad_byte, pad)
|
section_data += tools.GetBytes(self._pad_byte, pad)
|
||||||
|
|
||||||
|
# Add in the actual entry data
|
||||||
section_data += data
|
section_data += data
|
||||||
if self.size:
|
|
||||||
pad = self.size - len(section_data)
|
|
||||||
if pad > 0:
|
|
||||||
section_data += tools.GetBytes(self._pad_byte, pad)
|
|
||||||
self.Detail('GetData: %d entries, total size %#x' %
|
self.Detail('GetData: %d entries, total size %#x' %
|
||||||
(len(self._entries), len(section_data)))
|
(len(self._entries), len(section_data)))
|
||||||
return section_data
|
return self.CompressData(section_data)
|
||||||
|
|
||||||
|
def GetPaddedData(self, data=None):
|
||||||
|
"""Get the data for a section including any padding
|
||||||
|
|
||||||
|
Gets the section data and uses the parent section's pad-byte value to
|
||||||
|
add padding before and after as defined by the pad-before and pad-after
|
||||||
|
properties. If this is a top-level section (i.e. an image), this is the
|
||||||
|
same as GetData(), since padding is not supported.
|
||||||
|
|
||||||
|
This does not consider alignment.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Contents of the section along with any pad bytes before and
|
||||||
|
after it (bytes)
|
||||||
|
"""
|
||||||
|
section = self.section or self
|
||||||
|
if data is None:
|
||||||
|
data = self.GetData()
|
||||||
|
return section.GetPaddedDataForEntry(self, data)
|
||||||
|
|
||||||
|
def GetData(self):
|
||||||
|
"""Get the contents of an entry
|
||||||
|
|
||||||
|
This builds the contents of the section, stores this as the contents of
|
||||||
|
the section and returns it
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bytes content of the section, made up for all all of its subentries.
|
||||||
|
This excludes any padding. If the section is compressed, the
|
||||||
|
compressed data is returned
|
||||||
|
"""
|
||||||
|
data = self._BuildSectionData()
|
||||||
|
self.SetContents(data)
|
||||||
|
return data
|
||||||
|
|
||||||
def GetOffsets(self):
|
def GetOffsets(self):
|
||||||
"""Handle entries that want to set the offset/size of other entries
|
"""Handle entries that want to set the offset/size of other entries
|
||||||
|
@ -180,14 +262,25 @@ class Entry_section(Entry):
|
||||||
def Pack(self, offset):
|
def Pack(self, offset):
|
||||||
"""Pack all entries into the section"""
|
"""Pack all entries into the section"""
|
||||||
self._PackEntries()
|
self._PackEntries()
|
||||||
return super().Pack(offset)
|
if self._sort:
|
||||||
|
self._SortEntries()
|
||||||
|
self._ExpandEntries()
|
||||||
|
|
||||||
|
data = self._BuildSectionData()
|
||||||
|
self.SetContents(data)
|
||||||
|
|
||||||
|
self.CheckSize()
|
||||||
|
|
||||||
|
offset = super().Pack(offset)
|
||||||
|
self.CheckEntries()
|
||||||
|
return offset
|
||||||
|
|
||||||
def _PackEntries(self):
|
def _PackEntries(self):
|
||||||
"""Pack all entries into the image"""
|
"""Pack all entries into the section"""
|
||||||
offset = self._skip_at_start
|
offset = self._skip_at_start
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
offset = entry.Pack(offset)
|
offset = entry.Pack(offset)
|
||||||
self.size = self.CheckSize()
|
return offset
|
||||||
|
|
||||||
def _ExpandEntries(self):
|
def _ExpandEntries(self):
|
||||||
"""Expand any entries that are permitted to"""
|
"""Expand any entries that are permitted to"""
|
||||||
|
@ -209,21 +302,22 @@ class Entry_section(Entry):
|
||||||
self._entries[entry._node.name] = entry
|
self._entries[entry._node.name] = entry
|
||||||
|
|
||||||
def CheckEntries(self):
|
def CheckEntries(self):
|
||||||
"""Check that entries do not overlap or extend outside the image"""
|
"""Check that entries do not overlap or extend outside the section"""
|
||||||
if self._sort:
|
max_size = self.size if self.uncomp_size is None else self.uncomp_size
|
||||||
self._SortEntries()
|
|
||||||
self._ExpandEntries()
|
|
||||||
offset = 0
|
offset = 0
|
||||||
prev_name = 'None'
|
prev_name = 'None'
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
entry.CheckOffset()
|
entry.CheckEntries()
|
||||||
if (entry.offset < self._skip_at_start or
|
if (entry.offset < self._skip_at_start or
|
||||||
entry.offset + entry.size > self._skip_at_start +
|
entry.offset + entry.size > self._skip_at_start +
|
||||||
self.size):
|
max_size):
|
||||||
entry.Raise("Offset %#x (%d) is outside the section starting "
|
entry.Raise('Offset %#x (%d) size %#x (%d) is outside the '
|
||||||
"at %#x (%d)" %
|
"section '%s' starting at %#x (%d) "
|
||||||
(entry.offset, entry.offset, self._skip_at_start,
|
'of size %#x (%d)' %
|
||||||
self._skip_at_start))
|
(entry.offset, entry.offset, entry.size, entry.size,
|
||||||
|
self._node.path, self._skip_at_start,
|
||||||
|
self._skip_at_start, max_size, max_size))
|
||||||
if entry.offset < offset and entry.size:
|
if entry.offset < offset and entry.size:
|
||||||
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
|
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
|
||||||
"ending at %#x (%d)" %
|
"ending at %#x (%d)" %
|
||||||
|
@ -243,8 +337,9 @@ class Entry_section(Entry):
|
||||||
|
|
||||||
def SetImagePos(self, image_pos):
|
def SetImagePos(self, image_pos):
|
||||||
super().SetImagePos(image_pos)
|
super().SetImagePos(image_pos)
|
||||||
for entry in self._entries.values():
|
if self.compress == 'none':
|
||||||
entry.SetImagePos(image_pos + self.offset)
|
for entry in self._entries.values():
|
||||||
|
entry.SetImagePos(image_pos + self.offset)
|
||||||
|
|
||||||
def ProcessContents(self):
|
def ProcessContents(self):
|
||||||
sizes_ok_base = super(Entry_section, self).ProcessContents()
|
sizes_ok_base = super(Entry_section, self).ProcessContents()
|
||||||
|
@ -254,9 +349,6 @@ class Entry_section(Entry):
|
||||||
sizes_ok = False
|
sizes_ok = False
|
||||||
return sizes_ok and sizes_ok_base
|
return sizes_ok and sizes_ok_base
|
||||||
|
|
||||||
def CheckOffset(self):
|
|
||||||
self.CheckEntries()
|
|
||||||
|
|
||||||
def WriteMap(self, fd, indent):
|
def WriteMap(self, fd, indent):
|
||||||
"""Write a map of the section to a .map file
|
"""Write a map of the section to a .map file
|
||||||
|
|
||||||
|
@ -412,7 +504,7 @@ class Entry_section(Entry):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def GetEntryContents(self):
|
def GetEntryContents(self):
|
||||||
"""Call ObtainContents() for the section
|
"""Call ObtainContents() for each entry in the section
|
||||||
"""
|
"""
|
||||||
todo = self._entries.values()
|
todo = self._entries.values()
|
||||||
for passnum in range(3):
|
for passnum in range(3):
|
||||||
|
@ -454,18 +546,13 @@ class Entry_section(Entry):
|
||||||
for name, info in offset_dict.items():
|
for name, info in offset_dict.items():
|
||||||
self._SetEntryOffsetSize(name, *info)
|
self._SetEntryOffsetSize(name, *info)
|
||||||
|
|
||||||
|
|
||||||
def CheckSize(self):
|
def CheckSize(self):
|
||||||
"""Check that the image contents does not exceed its size, etc."""
|
contents_size = len(self.data)
|
||||||
contents_size = 0
|
|
||||||
for entry in self._entries.values():
|
|
||||||
contents_size = max(contents_size, entry.offset + entry.size)
|
|
||||||
|
|
||||||
contents_size -= self._skip_at_start
|
|
||||||
|
|
||||||
size = self.size
|
size = self.size
|
||||||
if not size:
|
if not size:
|
||||||
size = self.pad_before + contents_size + self.pad_after
|
data = self.GetPaddedData(self.data)
|
||||||
|
size = len(data)
|
||||||
size = tools.Align(size, self.align_size)
|
size = tools.Align(size, self.align_size)
|
||||||
|
|
||||||
if self.size and contents_size > self.size:
|
if self.size and contents_size > self.size:
|
||||||
|
|
|
@ -81,6 +81,7 @@ class Entry_u_boot_ucode(Entry_blob):
|
||||||
if fdt_entry:
|
if fdt_entry:
|
||||||
break
|
break
|
||||||
if not fdt_entry:
|
if not fdt_entry:
|
||||||
|
self.data = b''
|
||||||
return True
|
return True
|
||||||
if not fdt_entry.ready:
|
if not fdt_entry.ready:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -70,6 +70,7 @@ VBLOCK_DATA = b'vblk'
|
||||||
FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
|
FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
|
||||||
b"sorry you're alive\n")
|
b"sorry you're alive\n")
|
||||||
COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
|
COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
|
||||||
|
COMPRESS_DATA_BIG = COMPRESS_DATA * 2
|
||||||
REFCODE_DATA = b'refcode'
|
REFCODE_DATA = b'refcode'
|
||||||
FSP_M_DATA = b'fsp_m'
|
FSP_M_DATA = b'fsp_m'
|
||||||
FSP_S_DATA = b'fsp_s'
|
FSP_S_DATA = b'fsp_s'
|
||||||
|
@ -175,6 +176,7 @@ class TestFunctional(unittest.TestCase):
|
||||||
os.path.join(cls._indir, 'files'))
|
os.path.join(cls._indir, 'files'))
|
||||||
|
|
||||||
TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
|
TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
|
||||||
|
TestFunctional._MakeInputFile('compress_big', COMPRESS_DATA_BIG)
|
||||||
TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
|
TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
|
||||||
TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
|
TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
|
||||||
|
|
||||||
|
@ -785,9 +787,9 @@ class TestFunctional(unittest.TestCase):
|
||||||
|
|
||||||
def testPackExtra(self):
|
def testPackExtra(self):
|
||||||
"""Test that extra packing feature works as expected"""
|
"""Test that extra packing feature works as expected"""
|
||||||
retcode = self._DoTestFile('009_pack_extra.dts')
|
data, _, _, out_dtb_fname = self._DoReadFileDtb('009_pack_extra.dts',
|
||||||
|
update_dtb=True)
|
||||||
|
|
||||||
self.assertEqual(0, retcode)
|
|
||||||
self.assertIn('image', control.images)
|
self.assertIn('image', control.images)
|
||||||
image = control.images['image']
|
image = control.images['image']
|
||||||
entries = image.GetEntries()
|
entries = image.GetEntries()
|
||||||
|
@ -799,34 +801,82 @@ class TestFunctional(unittest.TestCase):
|
||||||
self.assertEqual(0, entry.offset)
|
self.assertEqual(0, entry.offset)
|
||||||
self.assertEqual(3, entry.pad_before)
|
self.assertEqual(3, entry.pad_before)
|
||||||
self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
|
self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
self.assertEqual(tools.GetBytes(0, 3) + U_BOOT_DATA +
|
||||||
|
tools.GetBytes(0, 5), data[:entry.size])
|
||||||
|
pos = entry.size
|
||||||
|
|
||||||
# Second u-boot has an aligned size, but it has no effect
|
# Second u-boot has an aligned size, but it has no effect
|
||||||
self.assertIn('u-boot-align-size-nop', entries)
|
self.assertIn('u-boot-align-size-nop', entries)
|
||||||
entry = entries['u-boot-align-size-nop']
|
entry = entries['u-boot-align-size-nop']
|
||||||
self.assertEqual(12, entry.offset)
|
self.assertEqual(pos, entry.offset)
|
||||||
self.assertEqual(4, entry.size)
|
self.assertEqual(len(U_BOOT_DATA), entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
self.assertEqual(U_BOOT_DATA, data[pos:pos + entry.size])
|
||||||
|
pos += entry.size
|
||||||
|
|
||||||
# Third u-boot has an aligned size too
|
# Third u-boot has an aligned size too
|
||||||
self.assertIn('u-boot-align-size', entries)
|
self.assertIn('u-boot-align-size', entries)
|
||||||
entry = entries['u-boot-align-size']
|
entry = entries['u-boot-align-size']
|
||||||
self.assertEqual(16, entry.offset)
|
self.assertEqual(pos, entry.offset)
|
||||||
self.assertEqual(32, entry.size)
|
self.assertEqual(32, entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 32 - len(U_BOOT_DATA)),
|
||||||
|
data[pos:pos + entry.size])
|
||||||
|
pos += entry.size
|
||||||
|
|
||||||
# Fourth u-boot has an aligned end
|
# Fourth u-boot has an aligned end
|
||||||
self.assertIn('u-boot-align-end', entries)
|
self.assertIn('u-boot-align-end', entries)
|
||||||
entry = entries['u-boot-align-end']
|
entry = entries['u-boot-align-end']
|
||||||
self.assertEqual(48, entry.offset)
|
self.assertEqual(48, entry.offset)
|
||||||
self.assertEqual(16, entry.size)
|
self.assertEqual(16, entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
|
||||||
|
self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 16 - len(U_BOOT_DATA)),
|
||||||
|
data[pos:pos + entry.size])
|
||||||
|
pos += entry.size
|
||||||
|
|
||||||
# Fifth u-boot immediately afterwards
|
# Fifth u-boot immediately afterwards
|
||||||
self.assertIn('u-boot-align-both', entries)
|
self.assertIn('u-boot-align-both', entries)
|
||||||
entry = entries['u-boot-align-both']
|
entry = entries['u-boot-align-both']
|
||||||
self.assertEqual(64, entry.offset)
|
self.assertEqual(64, entry.offset)
|
||||||
self.assertEqual(64, entry.size)
|
self.assertEqual(64, entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
|
||||||
|
self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 64 - len(U_BOOT_DATA)),
|
||||||
|
data[pos:pos + entry.size])
|
||||||
|
|
||||||
self.CheckNoGaps(entries)
|
self.CheckNoGaps(entries)
|
||||||
self.assertEqual(128, image.size)
|
self.assertEqual(128, image.size)
|
||||||
|
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['size', 'offset', 'image-pos'])
|
||||||
|
expected = {
|
||||||
|
'image-pos': 0,
|
||||||
|
'offset': 0,
|
||||||
|
'size': 128,
|
||||||
|
|
||||||
|
'u-boot:image-pos': 0,
|
||||||
|
'u-boot:offset': 0,
|
||||||
|
'u-boot:size': 3 + 5 + len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'u-boot-align-size-nop:image-pos': 12,
|
||||||
|
'u-boot-align-size-nop:offset': 12,
|
||||||
|
'u-boot-align-size-nop:size': 4,
|
||||||
|
|
||||||
|
'u-boot-align-size:image-pos': 16,
|
||||||
|
'u-boot-align-size:offset': 16,
|
||||||
|
'u-boot-align-size:size': 32,
|
||||||
|
|
||||||
|
'u-boot-align-end:image-pos': 48,
|
||||||
|
'u-boot-align-end:offset': 48,
|
||||||
|
'u-boot-align-end:size': 16,
|
||||||
|
|
||||||
|
'u-boot-align-both:image-pos': 64,
|
||||||
|
'u-boot-align-both:offset': 64,
|
||||||
|
'u-boot-align-both:size': 64,
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
def testPackAlignPowerOf2(self):
|
def testPackAlignPowerOf2(self):
|
||||||
"""Test that invalid entry alignment is detected"""
|
"""Test that invalid entry alignment is detected"""
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
|
@ -970,8 +1020,9 @@ class TestFunctional(unittest.TestCase):
|
||||||
"""Test that the end-at-4gb property checks for offset boundaries"""
|
"""Test that the end-at-4gb property checks for offset boundaries"""
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
self._DoTestFile('028_pack_4gb_outside.dts')
|
self._DoTestFile('028_pack_4gb_outside.dts')
|
||||||
self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
|
self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) size 0x4 (4) "
|
||||||
"the section starting at 0xffffffe0 (4294967264)",
|
"is outside the section '/binman' starting at "
|
||||||
|
'0xffffffe0 (4294967264) of size 0x20 (32)',
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
|
||||||
def testPackX86Rom(self):
|
def testPackX86Rom(self):
|
||||||
|
@ -1761,6 +1812,20 @@ class TestFunctional(unittest.TestCase):
|
||||||
props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
|
props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
|
||||||
orig = self._decompress(data)
|
orig = self._decompress(data)
|
||||||
self.assertEquals(COMPRESS_DATA, orig)
|
self.assertEquals(COMPRESS_DATA, orig)
|
||||||
|
|
||||||
|
# Do a sanity check on various fields
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
self.assertEqual(1, len(entries))
|
||||||
|
|
||||||
|
entry = entries['blob']
|
||||||
|
self.assertEqual(COMPRESS_DATA, entry.uncomp_data)
|
||||||
|
self.assertEqual(len(COMPRESS_DATA), entry.uncomp_size)
|
||||||
|
orig = self._decompress(entry.data)
|
||||||
|
self.assertEqual(orig, entry.uncomp_data)
|
||||||
|
|
||||||
|
self.assertEqual(image.data, entry.data)
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
'blob:uncomp-size': len(COMPRESS_DATA),
|
'blob:uncomp-size': len(COMPRESS_DATA),
|
||||||
'blob:size': len(data),
|
'blob:size': len(data),
|
||||||
|
@ -1961,7 +2026,7 @@ class TestFunctional(unittest.TestCase):
|
||||||
self.assertTrue(os.path.exists(map_fname))
|
self.assertTrue(os.path.exists(map_fname))
|
||||||
map_data = tools.ReadFile(map_fname, binary=False)
|
map_data = tools.ReadFile(map_fname, binary=False)
|
||||||
self.assertEqual('''ImagePos Offset Size Name
|
self.assertEqual('''ImagePos Offset Size Name
|
||||||
<none> 00000000 00000007 main-section
|
<none> 00000000 00000008 main-section
|
||||||
<none> 00000000 00000004 u-boot
|
<none> 00000000 00000004 u-boot
|
||||||
<none> 00000003 00000004 u-boot-align
|
<none> 00000003 00000004 u-boot-align
|
||||||
''', map_data)
|
''', map_data)
|
||||||
|
@ -3530,12 +3595,39 @@ class TestFunctional(unittest.TestCase):
|
||||||
|
|
||||||
def testPadInSections(self):
|
def testPadInSections(self):
|
||||||
"""Test pad-before, pad-after for entries in sections"""
|
"""Test pad-before, pad-after for entries in sections"""
|
||||||
data = self._DoReadFile('166_pad_in_sections.dts')
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'166_pad_in_sections.dts', update_dtb=True)
|
||||||
expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
|
expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
|
||||||
U_BOOT_DATA + tools.GetBytes(ord('!'), 6) +
|
U_BOOT_DATA + tools.GetBytes(ord('!'), 6) +
|
||||||
U_BOOT_DATA)
|
U_BOOT_DATA)
|
||||||
self.assertEqual(expected, data)
|
self.assertEqual(expected, data)
|
||||||
|
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['size', 'image-pos', 'offset'])
|
||||||
|
expected = {
|
||||||
|
'image-pos': 0,
|
||||||
|
'offset': 0,
|
||||||
|
'size': 12 + 6 + 3 * len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'section:image-pos': 0,
|
||||||
|
'section:offset': 0,
|
||||||
|
'section:size': 12 + 6 + 3 * len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'section/before:image-pos': 0,
|
||||||
|
'section/before:offset': 0,
|
||||||
|
'section/before:size': len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'section/u-boot:image-pos': 4,
|
||||||
|
'section/u-boot:offset': 4,
|
||||||
|
'section/u-boot:size': 12 + len(U_BOOT_DATA) + 6,
|
||||||
|
|
||||||
|
'section/after:image-pos': 26,
|
||||||
|
'section/after:offset': 26,
|
||||||
|
'section/after:size': len(U_BOOT_DATA),
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
def testFitImageSubentryAlignment(self):
|
def testFitImageSubentryAlignment(self):
|
||||||
"""Test relative alignability of FIT image subentries"""
|
"""Test relative alignability of FIT image subentries"""
|
||||||
entry_args = {
|
entry_args = {
|
||||||
|
@ -3737,14 +3829,14 @@ class TestFunctional(unittest.TestCase):
|
||||||
def testEnvironmentNoSize(self):
|
def testEnvironmentNoSize(self):
|
||||||
"""Test that a missing 'size' property is detected"""
|
"""Test that a missing 'size' property is detected"""
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
data = self._DoTestFile('175_env_no_size.dts')
|
self._DoTestFile('175_env_no_size.dts')
|
||||||
self.assertIn("'u-boot-env' entry must have a size property",
|
self.assertIn("'u-boot-env' entry must have a size property",
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
|
||||||
def testEnvironmentTooSmall(self):
|
def testEnvironmentTooSmall(self):
|
||||||
"""Test handling of an environment that does not fit"""
|
"""Test handling of an environment that does not fit"""
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
data = self._DoTestFile('176_env_too_small.dts')
|
self._DoTestFile('176_env_too_small.dts')
|
||||||
|
|
||||||
# checksum, start byte, environment with \0 terminator, final \0
|
# checksum, start byte, environment with \0 terminator, final \0
|
||||||
need = 4 + 1 + len(ENV_DATA) + 1 + 1
|
need = 4 + 1 + len(ENV_DATA) + 1 + 1
|
||||||
|
@ -3752,6 +3844,301 @@ class TestFunctional(unittest.TestCase):
|
||||||
self.assertIn("too small to hold data (need %#x more bytes)" % short,
|
self.assertIn("too small to hold data (need %#x more bytes)" % short,
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
|
||||||
|
def testSkipAtStart(self):
|
||||||
|
"""Test handling of skip-at-start section"""
|
||||||
|
data = self._DoReadFile('177_skip_at_start.dts')
|
||||||
|
self.assertEqual(U_BOOT_DATA, data)
|
||||||
|
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
section = entries['section']
|
||||||
|
self.assertEqual(0, section.offset)
|
||||||
|
self.assertEqual(len(U_BOOT_DATA), section.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, section.GetData())
|
||||||
|
|
||||||
|
entry = section.GetEntries()['u-boot']
|
||||||
|
self.assertEqual(16, entry.offset)
|
||||||
|
self.assertEqual(len(U_BOOT_DATA), entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
|
||||||
|
def testSkipAtStartPad(self):
|
||||||
|
"""Test handling of skip-at-start section with padded entry"""
|
||||||
|
data = self._DoReadFile('178_skip_at_start_pad.dts')
|
||||||
|
before = tools.GetBytes(0, 8)
|
||||||
|
after = tools.GetBytes(0, 4)
|
||||||
|
all = before + U_BOOT_DATA + after
|
||||||
|
self.assertEqual(all, data)
|
||||||
|
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
section = entries['section']
|
||||||
|
self.assertEqual(0, section.offset)
|
||||||
|
self.assertEqual(len(all), section.size)
|
||||||
|
self.assertEqual(all, section.GetData())
|
||||||
|
|
||||||
|
entry = section.GetEntries()['u-boot']
|
||||||
|
self.assertEqual(16, entry.offset)
|
||||||
|
self.assertEqual(len(all), entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
|
||||||
|
def testSkipAtStartSectionPad(self):
|
||||||
|
"""Test handling of skip-at-start section with padding"""
|
||||||
|
data = self._DoReadFile('179_skip_at_start_section_pad.dts')
|
||||||
|
before = tools.GetBytes(0, 8)
|
||||||
|
after = tools.GetBytes(0, 4)
|
||||||
|
all = before + U_BOOT_DATA + after
|
||||||
|
self.assertEqual(all, data)
|
||||||
|
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
section = entries['section']
|
||||||
|
self.assertEqual(0, section.offset)
|
||||||
|
self.assertEqual(len(all), section.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, section.data)
|
||||||
|
self.assertEqual(all, section.GetPaddedData())
|
||||||
|
|
||||||
|
entry = section.GetEntries()['u-boot']
|
||||||
|
self.assertEqual(16, entry.offset)
|
||||||
|
self.assertEqual(len(U_BOOT_DATA), entry.size)
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
|
||||||
|
def testSectionPad(self):
|
||||||
|
"""Testing padding with sections"""
|
||||||
|
data = self._DoReadFile('180_section_pad.dts')
|
||||||
|
expected = (tools.GetBytes(ord('&'), 3) +
|
||||||
|
tools.GetBytes(ord('!'), 5) +
|
||||||
|
U_BOOT_DATA +
|
||||||
|
tools.GetBytes(ord('!'), 1) +
|
||||||
|
tools.GetBytes(ord('&'), 2))
|
||||||
|
self.assertEqual(expected, data)
|
||||||
|
|
||||||
|
def testSectionAlign(self):
|
||||||
|
"""Testing alignment with sections"""
|
||||||
|
data = self._DoReadFileDtb('181_section_align.dts', map=True)[0]
|
||||||
|
expected = (b'\0' + # fill section
|
||||||
|
tools.GetBytes(ord('&'), 1) + # padding to section align
|
||||||
|
b'\0' + # fill section
|
||||||
|
tools.GetBytes(ord('!'), 3) + # padding to u-boot align
|
||||||
|
U_BOOT_DATA +
|
||||||
|
tools.GetBytes(ord('!'), 4) + # padding to u-boot size
|
||||||
|
tools.GetBytes(ord('!'), 4)) # padding to section size
|
||||||
|
self.assertEqual(expected, data)
|
||||||
|
|
||||||
|
def testCompressImage(self):
|
||||||
|
"""Test compression of the entire image"""
|
||||||
|
self._CheckLz4()
|
||||||
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'182_compress_image.dts', use_real_dtb=True, update_dtb=True)
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size',
|
||||||
|
'uncomp-size'])
|
||||||
|
orig = self._decompress(data)
|
||||||
|
self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig)
|
||||||
|
|
||||||
|
# Do a sanity check on various fields
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
self.assertEqual(2, len(entries))
|
||||||
|
|
||||||
|
entry = entries['blob']
|
||||||
|
self.assertEqual(COMPRESS_DATA, entry.data)
|
||||||
|
self.assertEqual(len(COMPRESS_DATA), entry.size)
|
||||||
|
|
||||||
|
entry = entries['u-boot']
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
self.assertEqual(len(U_BOOT_DATA), entry.size)
|
||||||
|
|
||||||
|
self.assertEqual(len(data), image.size)
|
||||||
|
self.assertEqual(COMPRESS_DATA + U_BOOT_DATA, image.uncomp_data)
|
||||||
|
self.assertEqual(len(COMPRESS_DATA + U_BOOT_DATA), image.uncomp_size)
|
||||||
|
orig = self._decompress(image.data)
|
||||||
|
self.assertEqual(orig, image.uncomp_data)
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
'blob:offset': 0,
|
||||||
|
'blob:size': len(COMPRESS_DATA),
|
||||||
|
'u-boot:offset': len(COMPRESS_DATA),
|
||||||
|
'u-boot:size': len(U_BOOT_DATA),
|
||||||
|
'uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA),
|
||||||
|
'offset': 0,
|
||||||
|
'image-pos': 0,
|
||||||
|
'size': len(data),
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
|
def testCompressImageLess(self):
|
||||||
|
"""Test compression where compression reduces the image size"""
|
||||||
|
self._CheckLz4()
|
||||||
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'183_compress_image_less.dts', use_real_dtb=True, update_dtb=True)
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size',
|
||||||
|
'uncomp-size'])
|
||||||
|
orig = self._decompress(data)
|
||||||
|
|
||||||
|
self.assertEquals(COMPRESS_DATA + COMPRESS_DATA + U_BOOT_DATA, orig)
|
||||||
|
|
||||||
|
# Do a sanity check on various fields
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
self.assertEqual(2, len(entries))
|
||||||
|
|
||||||
|
entry = entries['blob']
|
||||||
|
self.assertEqual(COMPRESS_DATA_BIG, entry.data)
|
||||||
|
self.assertEqual(len(COMPRESS_DATA_BIG), entry.size)
|
||||||
|
|
||||||
|
entry = entries['u-boot']
|
||||||
|
self.assertEqual(U_BOOT_DATA, entry.data)
|
||||||
|
self.assertEqual(len(U_BOOT_DATA), entry.size)
|
||||||
|
|
||||||
|
self.assertEqual(len(data), image.size)
|
||||||
|
self.assertEqual(COMPRESS_DATA_BIG + U_BOOT_DATA, image.uncomp_data)
|
||||||
|
self.assertEqual(len(COMPRESS_DATA_BIG + U_BOOT_DATA),
|
||||||
|
image.uncomp_size)
|
||||||
|
orig = self._decompress(image.data)
|
||||||
|
self.assertEqual(orig, image.uncomp_data)
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
'blob:offset': 0,
|
||||||
|
'blob:size': len(COMPRESS_DATA_BIG),
|
||||||
|
'u-boot:offset': len(COMPRESS_DATA_BIG),
|
||||||
|
'u-boot:size': len(U_BOOT_DATA),
|
||||||
|
'uncomp-size': len(COMPRESS_DATA_BIG + U_BOOT_DATA),
|
||||||
|
'offset': 0,
|
||||||
|
'image-pos': 0,
|
||||||
|
'size': len(data),
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
|
def testCompressSectionSize(self):
|
||||||
|
"""Test compression of a section with a fixed size"""
|
||||||
|
self._CheckLz4()
|
||||||
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'184_compress_section_size.dts', use_real_dtb=True, update_dtb=True)
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size',
|
||||||
|
'uncomp-size'])
|
||||||
|
orig = self._decompress(data)
|
||||||
|
self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig)
|
||||||
|
expected = {
|
||||||
|
'section/blob:offset': 0,
|
||||||
|
'section/blob:size': len(COMPRESS_DATA),
|
||||||
|
'section/u-boot:offset': len(COMPRESS_DATA),
|
||||||
|
'section/u-boot:size': len(U_BOOT_DATA),
|
||||||
|
'section:offset': 0,
|
||||||
|
'section:image-pos': 0,
|
||||||
|
'section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA),
|
||||||
|
'section:size': 0x30,
|
||||||
|
'offset': 0,
|
||||||
|
'image-pos': 0,
|
||||||
|
'size': 0x30,
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
|
def testCompressSection(self):
|
||||||
|
"""Test compression of a section with no fixed size"""
|
||||||
|
self._CheckLz4()
|
||||||
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'185_compress_section.dts', use_real_dtb=True, update_dtb=True)
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size',
|
||||||
|
'uncomp-size'])
|
||||||
|
orig = self._decompress(data)
|
||||||
|
self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig)
|
||||||
|
expected = {
|
||||||
|
'section/blob:offset': 0,
|
||||||
|
'section/blob:size': len(COMPRESS_DATA),
|
||||||
|
'section/u-boot:offset': len(COMPRESS_DATA),
|
||||||
|
'section/u-boot:size': len(U_BOOT_DATA),
|
||||||
|
'section:offset': 0,
|
||||||
|
'section:image-pos': 0,
|
||||||
|
'section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA),
|
||||||
|
'section:size': len(data),
|
||||||
|
'offset': 0,
|
||||||
|
'image-pos': 0,
|
||||||
|
'size': len(data),
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
|
def testCompressExtra(self):
|
||||||
|
"""Test compression of a section with no fixed size"""
|
||||||
|
self._CheckLz4()
|
||||||
|
data, _, _, out_dtb_fname = self._DoReadFileDtb(
|
||||||
|
'186_compress_extra.dts', use_real_dtb=True, update_dtb=True)
|
||||||
|
dtb = fdt.Fdt(out_dtb_fname)
|
||||||
|
dtb.Scan()
|
||||||
|
props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size',
|
||||||
|
'uncomp-size'])
|
||||||
|
|
||||||
|
base = data[len(U_BOOT_DATA):]
|
||||||
|
self.assertEquals(U_BOOT_DATA, base[:len(U_BOOT_DATA)])
|
||||||
|
rest = base[len(U_BOOT_DATA):]
|
||||||
|
|
||||||
|
# Check compressed data
|
||||||
|
section1 = self._decompress(rest)
|
||||||
|
expect1 = tools.Compress(COMPRESS_DATA + U_BOOT_DATA, 'lz4')
|
||||||
|
self.assertEquals(expect1, rest[:len(expect1)])
|
||||||
|
self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, section1)
|
||||||
|
rest1 = rest[len(expect1):]
|
||||||
|
|
||||||
|
section2 = self._decompress(rest1)
|
||||||
|
expect2 = tools.Compress(COMPRESS_DATA + COMPRESS_DATA, 'lz4')
|
||||||
|
self.assertEquals(expect2, rest1[:len(expect2)])
|
||||||
|
self.assertEquals(COMPRESS_DATA + COMPRESS_DATA, section2)
|
||||||
|
rest2 = rest1[len(expect2):]
|
||||||
|
|
||||||
|
expect_size = (len(U_BOOT_DATA) + len(U_BOOT_DATA) + len(expect1) +
|
||||||
|
len(expect2) + len(U_BOOT_DATA))
|
||||||
|
#self.assertEquals(expect_size, len(data))
|
||||||
|
|
||||||
|
#self.assertEquals(U_BOOT_DATA, rest2)
|
||||||
|
|
||||||
|
self.maxDiff = None
|
||||||
|
expected = {
|
||||||
|
'u-boot:offset': 0,
|
||||||
|
'u-boot:image-pos': 0,
|
||||||
|
'u-boot:size': len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'base:offset': len(U_BOOT_DATA),
|
||||||
|
'base:image-pos': len(U_BOOT_DATA),
|
||||||
|
'base:size': len(data) - len(U_BOOT_DATA),
|
||||||
|
'base/u-boot:offset': 0,
|
||||||
|
'base/u-boot:image-pos': len(U_BOOT_DATA),
|
||||||
|
'base/u-boot:size': len(U_BOOT_DATA),
|
||||||
|
'base/u-boot2:offset': len(U_BOOT_DATA) + len(expect1) +
|
||||||
|
len(expect2),
|
||||||
|
'base/u-boot2:image-pos': len(U_BOOT_DATA) * 2 + len(expect1) +
|
||||||
|
len(expect2),
|
||||||
|
'base/u-boot2:size': len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'base/section:offset': len(U_BOOT_DATA),
|
||||||
|
'base/section:image-pos': len(U_BOOT_DATA) * 2,
|
||||||
|
'base/section:size': len(expect1),
|
||||||
|
'base/section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA),
|
||||||
|
'base/section/blob:offset': 0,
|
||||||
|
'base/section/blob:size': len(COMPRESS_DATA),
|
||||||
|
'base/section/u-boot:offset': len(COMPRESS_DATA),
|
||||||
|
'base/section/u-boot:size': len(U_BOOT_DATA),
|
||||||
|
|
||||||
|
'base/section2:offset': len(U_BOOT_DATA) + len(expect1),
|
||||||
|
'base/section2:image-pos': len(U_BOOT_DATA) * 2 + len(expect1),
|
||||||
|
'base/section2:size': len(expect2),
|
||||||
|
'base/section2:uncomp-size': len(COMPRESS_DATA + COMPRESS_DATA),
|
||||||
|
'base/section2/blob:offset': 0,
|
||||||
|
'base/section2/blob:size': len(COMPRESS_DATA),
|
||||||
|
'base/section2/blob2:offset': len(COMPRESS_DATA),
|
||||||
|
'base/section2/blob2:size': len(COMPRESS_DATA),
|
||||||
|
|
||||||
|
'offset': 0,
|
||||||
|
'image-pos': 0,
|
||||||
|
'size': len(data),
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, props)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -146,7 +146,7 @@ class Image(section.Entry_section):
|
||||||
fname = tools.GetOutputFilename(self._filename)
|
fname = tools.GetOutputFilename(self._filename)
|
||||||
tout.Info("Writing image to '%s'" % fname)
|
tout.Info("Writing image to '%s'" % fname)
|
||||||
with open(fname, 'wb') as fd:
|
with open(fname, 'wb') as fd:
|
||||||
data = self.GetData()
|
data = self.GetPaddedData()
|
||||||
fd.write(data)
|
fd.write(data)
|
||||||
tout.Info("Wrote %#x bytes" % len(data))
|
tout.Info("Wrote %#x bytes" % len(data))
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
u-boot-align-both {
|
u-boot-align-both {
|
||||||
type = "u-boot";
|
type = "u-boot";
|
||||||
align= <64>;
|
align = <64>;
|
||||||
align-end = <128>;
|
align-end = <128>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
binman {
|
binman {
|
||||||
files {
|
files {
|
||||||
pattern = "files/*.dat";
|
pattern = "files/*.dat";
|
||||||
compress = "lz4";
|
files-compress = "lz4";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
19
tools/binman/test/177_skip_at_start.dts
Normal file
19
tools/binman/test/177_skip_at_start.dts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2018 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
section {
|
||||||
|
skip-at-start = <16>;
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
21
tools/binman/test/178_skip_at_start_pad.dts
Normal file
21
tools/binman/test/178_skip_at_start_pad.dts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2018 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
section {
|
||||||
|
skip-at-start = <16>;
|
||||||
|
u-boot {
|
||||||
|
pad-before = <8>;
|
||||||
|
pad-after = <4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
22
tools/binman/test/179_skip_at_start_section_pad.dts
Normal file
22
tools/binman/test/179_skip_at_start_section_pad.dts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2018 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
section {
|
||||||
|
skip-at-start = <16>;
|
||||||
|
pad-before = <8>;
|
||||||
|
pad-after = <4>;
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
27
tools/binman/test/180_section_pad.dts
Normal file
27
tools/binman/test/180_section_pad.dts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
pad-byte = <0x26>;
|
||||||
|
section@0 {
|
||||||
|
read-only;
|
||||||
|
|
||||||
|
/* Padding for the section uses the 0x26 pad byte */
|
||||||
|
pad-before = <3>;
|
||||||
|
pad-after = <2>;
|
||||||
|
|
||||||
|
/* Set the padding byte for entries, i.e. u-boot */
|
||||||
|
pad-byte = <0x21>;
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
pad-before = <5>;
|
||||||
|
pad-after = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
34
tools/binman/test/181_section_align.dts
Normal file
34
tools/binman/test/181_section_align.dts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
pad-byte = <0x26>;
|
||||||
|
fill {
|
||||||
|
size = <1>;
|
||||||
|
};
|
||||||
|
section@1 {
|
||||||
|
read-only;
|
||||||
|
|
||||||
|
/* Padding for the section uses the 0x26 pad byte */
|
||||||
|
align = <2>;
|
||||||
|
align-size = <0x10>;
|
||||||
|
|
||||||
|
/* Set the padding byte for entries, i.e. u-boot */
|
||||||
|
pad-byte = <0x21>;
|
||||||
|
|
||||||
|
fill {
|
||||||
|
size = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
align = <4>;
|
||||||
|
align-size = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
14
tools/binman/test/182_compress_image.dts
Normal file
14
tools/binman/test/182_compress_image.dts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
14
tools/binman/test/183_compress_image_less.dts
Normal file
14
tools/binman/test/183_compress_image_less.dts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress_big";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
17
tools/binman/test/184_compress_section_size.dts
Normal file
17
tools/binman/test/184_compress_section_size.dts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
section {
|
||||||
|
size = <0x30>;
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
16
tools/binman/test/185_compress_section.dts
Normal file
16
tools/binman/test/185_compress_section.dts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
section {
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
37
tools/binman/test/186_compress_extra.dts
Normal file
37
tools/binman/test/186_compress_extra.dts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
base {
|
||||||
|
type = "section";
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
section {
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
section2 {
|
||||||
|
type = "section";
|
||||||
|
compress = "lz4";
|
||||||
|
blob {
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
blob2 {
|
||||||
|
type = "blob";
|
||||||
|
filename = "compress";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
u-boot2 {
|
||||||
|
type = "u-boot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -54,6 +54,13 @@ VAL_PREFIX = 'dtv_'
|
||||||
# phandles is len(args). This is a list of integers.
|
# phandles is len(args). This is a list of integers.
|
||||||
PhandleInfo = collections.namedtuple('PhandleInfo', ['max_args', 'args'])
|
PhandleInfo = collections.namedtuple('PhandleInfo', ['max_args', 'args'])
|
||||||
|
|
||||||
|
# Holds a single phandle link, allowing a C struct value to be assigned to point
|
||||||
|
# to a device
|
||||||
|
#
|
||||||
|
# var_node: C variable to assign (e.g. 'dtv_mmc.clocks[0].node')
|
||||||
|
# dev_name: Name of device to assign to (e.g. 'clock')
|
||||||
|
PhandleLink = collections.namedtuple('PhandleLink', ['var_node', 'dev_name'])
|
||||||
|
|
||||||
|
|
||||||
def conv_name_to_c(name):
|
def conv_name_to_c(name):
|
||||||
"""Convert a device-tree name to a C identifier
|
"""Convert a device-tree name to a C identifier
|
||||||
|
@ -136,7 +143,8 @@ class DtbPlatdata(object):
|
||||||
Properties:
|
Properties:
|
||||||
_fdt: Fdt object, referencing the device tree
|
_fdt: Fdt object, referencing the device tree
|
||||||
_dtb_fname: Filename of the input device tree binary file
|
_dtb_fname: Filename of the input device tree binary file
|
||||||
_valid_nodes: A list of Node object with compatible strings
|
_valid_nodes: A list of Node object with compatible strings. The list
|
||||||
|
is ordered by conv_name_to_c(node.name)
|
||||||
_include_disabled: true to include nodes marked status = "disabled"
|
_include_disabled: true to include nodes marked status = "disabled"
|
||||||
_outfile: The current output file (sys.stdout or a real file)
|
_outfile: The current output file (sys.stdout or a real file)
|
||||||
_warning_disabled: true to disable warnings about driver names not found
|
_warning_disabled: true to disable warnings about driver names not found
|
||||||
|
@ -146,7 +154,6 @@ class DtbPlatdata(object):
|
||||||
key: Driver alias declared with
|
key: Driver alias declared with
|
||||||
U_BOOT_DRIVER_ALIAS(driver_alias, driver_name)
|
U_BOOT_DRIVER_ALIAS(driver_alias, driver_name)
|
||||||
value: Driver name declared with U_BOOT_DRIVER(driver_name)
|
value: Driver name declared with U_BOOT_DRIVER(driver_name)
|
||||||
_links: List of links to be included in dm_populate_phandle_data()
|
|
||||||
_drivers_additional: List of additional drivers to use during scanning
|
_drivers_additional: List of additional drivers to use during scanning
|
||||||
"""
|
"""
|
||||||
def __init__(self, dtb_fname, include_disabled, warning_disabled,
|
def __init__(self, dtb_fname, include_disabled, warning_disabled,
|
||||||
|
@ -160,7 +167,6 @@ class DtbPlatdata(object):
|
||||||
self._lines = []
|
self._lines = []
|
||||||
self._drivers = []
|
self._drivers = []
|
||||||
self._driver_aliases = {}
|
self._driver_aliases = {}
|
||||||
self._links = []
|
|
||||||
self._drivers_additional = drivers_additional
|
self._drivers_additional = drivers_additional
|
||||||
|
|
||||||
def get_normalized_compat_name(self, node):
|
def get_normalized_compat_name(self, node):
|
||||||
|
@ -359,23 +365,24 @@ class DtbPlatdata(object):
|
||||||
"""
|
"""
|
||||||
self._fdt = fdt.FdtScan(self._dtb_fname)
|
self._fdt = fdt.FdtScan(self._dtb_fname)
|
||||||
|
|
||||||
def scan_node(self, root):
|
def scan_node(self, root, valid_nodes):
|
||||||
"""Scan a node and subnodes to build a tree of node and phandle info
|
"""Scan a node and subnodes to build a tree of node and phandle info
|
||||||
|
|
||||||
This adds each node to self._valid_nodes.
|
This adds each node to self._valid_nodes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
root: Root node for scan
|
root: Root node for scan
|
||||||
|
valid_nodes: List of Node objects to add to
|
||||||
"""
|
"""
|
||||||
for node in root.subnodes:
|
for node in root.subnodes:
|
||||||
if 'compatible' in node.props:
|
if 'compatible' in node.props:
|
||||||
status = node.props.get('status')
|
status = node.props.get('status')
|
||||||
if (not self._include_disabled and not status or
|
if (not self._include_disabled and not status or
|
||||||
status.value != 'disabled'):
|
status.value != 'disabled'):
|
||||||
self._valid_nodes.append(node)
|
valid_nodes.append(node)
|
||||||
|
|
||||||
# recurse to handle any subnodes
|
# recurse to handle any subnodes
|
||||||
self.scan_node(node)
|
self.scan_node(node, valid_nodes)
|
||||||
|
|
||||||
def scan_tree(self):
|
def scan_tree(self):
|
||||||
"""Scan the device tree for useful information
|
"""Scan the device tree for useful information
|
||||||
|
@ -384,8 +391,12 @@ class DtbPlatdata(object):
|
||||||
_valid_nodes: A list of nodes we wish to consider include in the
|
_valid_nodes: A list of nodes we wish to consider include in the
|
||||||
platform data
|
platform data
|
||||||
"""
|
"""
|
||||||
self._valid_nodes = []
|
valid_nodes = []
|
||||||
return self.scan_node(self._fdt.GetRoot())
|
self.scan_node(self._fdt.GetRoot(), valid_nodes)
|
||||||
|
self._valid_nodes = sorted(valid_nodes,
|
||||||
|
key=lambda x: conv_name_to_c(x.name))
|
||||||
|
for idx, node in enumerate(self._valid_nodes):
|
||||||
|
node.idx = idx
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_num_cells(node):
|
def get_num_cells(node):
|
||||||
|
@ -458,8 +469,15 @@ class DtbPlatdata(object):
|
||||||
|
|
||||||
Once the widest property is determined, all other properties are
|
Once the widest property is determined, all other properties are
|
||||||
updated to match that width.
|
updated to match that width.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict containing structures:
|
||||||
|
key (str): Node name, as a C identifier
|
||||||
|
value: dict containing structure fields:
|
||||||
|
key (str): Field name
|
||||||
|
value: Prop object with field information
|
||||||
"""
|
"""
|
||||||
structs = {}
|
structs = collections.OrderedDict()
|
||||||
for node in self._valid_nodes:
|
for node in self._valid_nodes:
|
||||||
node_name, _ = self.get_normalized_compat_name(node)
|
node_name, _ = self.get_normalized_compat_name(node)
|
||||||
fields = {}
|
fields = {}
|
||||||
|
@ -528,6 +546,14 @@ class DtbPlatdata(object):
|
||||||
This writes out the body of a header file consisting of structure
|
This writes out the body of a header file consisting of structure
|
||||||
definitions for node in self._valid_nodes. See the documentation in
|
definitions for node in self._valid_nodes. See the documentation in
|
||||||
doc/driver-model/of-plat.rst for more information.
|
doc/driver-model/of-plat.rst for more information.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
structs: dict containing structures:
|
||||||
|
key (str): Node name, as a C identifier
|
||||||
|
value: dict containing structure fields:
|
||||||
|
key (str): Field name
|
||||||
|
value: Prop object with field information
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.out_header()
|
self.out_header()
|
||||||
self.out('#include <stdbool.h>\n')
|
self.out('#include <stdbool.h>\n')
|
||||||
|
@ -560,8 +586,51 @@ class DtbPlatdata(object):
|
||||||
Args:
|
Args:
|
||||||
node: node to output
|
node: node to output
|
||||||
"""
|
"""
|
||||||
|
def _output_list(node, prop):
|
||||||
|
"""Output the C code for a devicetree property that holds a list
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node (fdt.Node): Node to output
|
||||||
|
prop (fdt.Prop): Prop to output
|
||||||
|
"""
|
||||||
|
self.buf('{')
|
||||||
|
vals = []
|
||||||
|
# For phandles, output a reference to the platform data
|
||||||
|
# of the target node.
|
||||||
|
info = self.get_phandle_argc(prop, node.name)
|
||||||
|
if info:
|
||||||
|
# Process the list as pairs of (phandle, id)
|
||||||
|
pos = 0
|
||||||
|
item = 0
|
||||||
|
for args in info.args:
|
||||||
|
phandle_cell = prop.value[pos]
|
||||||
|
phandle = fdt_util.fdt32_to_cpu(phandle_cell)
|
||||||
|
target_node = self._fdt.phandle_to_node[phandle]
|
||||||
|
name = conv_name_to_c(target_node.name)
|
||||||
|
arg_values = []
|
||||||
|
for i in range(args):
|
||||||
|
arg_values.append(
|
||||||
|
str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
|
||||||
|
pos += 1 + args
|
||||||
|
vals.append('\t{%d, {%s}}' % (target_node.idx,
|
||||||
|
', '.join(arg_values)))
|
||||||
|
item += 1
|
||||||
|
for val in vals:
|
||||||
|
self.buf('\n\t\t%s,' % val)
|
||||||
|
else:
|
||||||
|
for val in prop.value:
|
||||||
|
vals.append(get_value(prop.type, val))
|
||||||
|
|
||||||
|
# Put 8 values per line to avoid very long lines.
|
||||||
|
for i in range(0, len(vals), 8):
|
||||||
|
if i:
|
||||||
|
self.buf(',\n\t\t')
|
||||||
|
self.buf(', '.join(vals[i:i + 8]))
|
||||||
|
self.buf('}')
|
||||||
|
|
||||||
struct_name, _ = self.get_normalized_compat_name(node)
|
struct_name, _ = self.get_normalized_compat_name(node)
|
||||||
var_name = conv_name_to_c(node.name)
|
var_name = conv_name_to_c(node.name)
|
||||||
|
self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
|
||||||
self.buf('static struct %s%s %s%s = {\n' %
|
self.buf('static struct %s%s %s%s = {\n' %
|
||||||
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
|
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
|
||||||
for pname in sorted(node.props):
|
for pname in sorted(node.props):
|
||||||
|
@ -573,46 +642,7 @@ class DtbPlatdata(object):
|
||||||
|
|
||||||
# Special handling for lists
|
# Special handling for lists
|
||||||
if isinstance(prop.value, list):
|
if isinstance(prop.value, list):
|
||||||
self.buf('{')
|
_output_list(node, prop)
|
||||||
vals = []
|
|
||||||
# For phandles, output a reference to the platform data
|
|
||||||
# of the target node.
|
|
||||||
info = self.get_phandle_argc(prop, node.name)
|
|
||||||
if info:
|
|
||||||
# Process the list as pairs of (phandle, id)
|
|
||||||
pos = 0
|
|
||||||
item = 0
|
|
||||||
for args in info.args:
|
|
||||||
phandle_cell = prop.value[pos]
|
|
||||||
phandle = fdt_util.fdt32_to_cpu(phandle_cell)
|
|
||||||
target_node = self._fdt.phandle_to_node[phandle]
|
|
||||||
name = conv_name_to_c(target_node.name)
|
|
||||||
arg_values = []
|
|
||||||
for i in range(args):
|
|
||||||
arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
|
|
||||||
pos += 1 + args
|
|
||||||
# node member is filled with NULL as the real value
|
|
||||||
# will be update at run-time during dm_init_and_scan()
|
|
||||||
# by dm_populate_phandle_data()
|
|
||||||
vals.append('\t{NULL, {%s}}' % (', '.join(arg_values)))
|
|
||||||
var_node = '%s%s.%s[%d].node' % \
|
|
||||||
(VAL_PREFIX, var_name, member_name, item)
|
|
||||||
# Save the the link information to be use to define
|
|
||||||
# dm_populate_phandle_data()
|
|
||||||
self._links.append({'var_node': var_node, 'dev_name': name})
|
|
||||||
item += 1
|
|
||||||
for val in vals:
|
|
||||||
self.buf('\n\t\t%s,' % val)
|
|
||||||
else:
|
|
||||||
for val in prop.value:
|
|
||||||
vals.append(get_value(prop.type, val))
|
|
||||||
|
|
||||||
# Put 8 values per line to avoid very long lines.
|
|
||||||
for i in range(0, len(vals), 8):
|
|
||||||
if i:
|
|
||||||
self.buf(',\n\t\t')
|
|
||||||
self.buf(', '.join(vals[i:i + 8]))
|
|
||||||
self.buf('}')
|
|
||||||
else:
|
else:
|
||||||
self.buf(get_value(prop.type, prop.value))
|
self.buf(get_value(prop.type, prop.value))
|
||||||
self.buf(',\n')
|
self.buf(',\n')
|
||||||
|
@ -623,6 +653,10 @@ class DtbPlatdata(object):
|
||||||
self.buf('\t.name\t\t= "%s",\n' % struct_name)
|
self.buf('\t.name\t\t= "%s",\n' % struct_name)
|
||||||
self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
|
self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
|
||||||
self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
|
self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
|
||||||
|
idx = -1
|
||||||
|
if node.parent and node.parent in self._valid_nodes:
|
||||||
|
idx = node.parent.idx
|
||||||
|
self.buf('\t.parent_idx\t= %d,\n' % idx)
|
||||||
self.buf('};\n')
|
self.buf('};\n')
|
||||||
self.buf('\n')
|
self.buf('\n')
|
||||||
|
|
||||||
|
@ -639,6 +673,9 @@ class DtbPlatdata(object):
|
||||||
information.
|
information.
|
||||||
"""
|
"""
|
||||||
self.out_header()
|
self.out_header()
|
||||||
|
self.out('/* Allow use of U_BOOT_DEVICE() in this file */\n')
|
||||||
|
self.out('#define DT_PLATDATA_C\n')
|
||||||
|
self.out('\n')
|
||||||
self.out('#include <common.h>\n')
|
self.out('#include <common.h>\n')
|
||||||
self.out('#include <dm.h>\n')
|
self.out('#include <dm.h>\n')
|
||||||
self.out('#include <dt-structs.h>\n')
|
self.out('#include <dt-structs.h>\n')
|
||||||
|
@ -660,9 +697,6 @@ class DtbPlatdata(object):
|
||||||
# nodes using DM_GET_DEVICE
|
# nodes using DM_GET_DEVICE
|
||||||
# dtv_dmc_at_xxx.clocks[0].node = DM_GET_DEVICE(clock_controller_at_xxx)
|
# dtv_dmc_at_xxx.clocks[0].node = DM_GET_DEVICE(clock_controller_at_xxx)
|
||||||
self.buf('void dm_populate_phandle_data(void) {\n')
|
self.buf('void dm_populate_phandle_data(void) {\n')
|
||||||
for l in self._links:
|
|
||||||
self.buf('\t%s = DM_GET_DEVICE(%s);\n' %
|
|
||||||
(l['var_node'], l['dev_name']))
|
|
||||||
self.buf('}\n')
|
self.buf('}\n')
|
||||||
|
|
||||||
self.out(''.join(self.get_buf()))
|
self.out(''.join(self.get_buf()))
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
compatible = "sandbox,spl-test";
|
compatible = "sandbox,spl-test";
|
||||||
stringarray = "one";
|
stringarray = "one";
|
||||||
|
longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
|
||||||
};
|
};
|
||||||
|
|
||||||
spl-test4 {
|
spl-test4 {
|
||||||
|
|
|
@ -129,6 +129,15 @@ class Prop:
|
||||||
specific.
|
specific.
|
||||||
"""
|
"""
|
||||||
if newprop.type < self.type:
|
if newprop.type < self.type:
|
||||||
|
# Special handling to convert an int into bytes
|
||||||
|
if self.type == TYPE_INT and newprop.type == TYPE_BYTE:
|
||||||
|
if type(self.value) == list:
|
||||||
|
new_value = []
|
||||||
|
for val in self.value:
|
||||||
|
new_value += [tools.ToChar(by) for by in val]
|
||||||
|
else:
|
||||||
|
new_value = [tools.ToChar(by) for by in self.value]
|
||||||
|
self.value = new_value
|
||||||
self.type = newprop.type
|
self.type = newprop.type
|
||||||
|
|
||||||
if type(newprop.value) == list and type(self.value) != list:
|
if type(newprop.value) == list and type(self.value) != list:
|
||||||
|
|
|
@ -44,6 +44,9 @@ C_HEADER = '''/*
|
||||||
* This file was generated by dtoc from a .dtb (device tree binary) file.
|
* This file was generated by dtoc from a .dtb (device tree binary) file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Allow use of U_BOOT_DEVICE() in this file */
|
||||||
|
#define DT_PLATDATA_C
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <dt-structs.h>
|
#include <dt-structs.h>
|
||||||
|
@ -209,6 +212,29 @@ struct dtd_sandbox_spl_test_2 {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /i2c@0 index 0 */
|
||||||
|
static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
|
||||||
|
};
|
||||||
|
U_BOOT_DEVICE(i2c_at_0) = {
|
||||||
|
\t.name\t\t= "sandbox_i2c_test",
|
||||||
|
\t.platdata\t= &dtv_i2c_at_0,
|
||||||
|
\t.platdata_size\t= sizeof(dtv_i2c_at_0),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Node /i2c@0/pmic@9 index 1 */
|
||||||
|
static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
|
||||||
|
\t.low_power\t\t= true,
|
||||||
|
\t.reg\t\t\t= {0x9, 0x0},
|
||||||
|
};
|
||||||
|
U_BOOT_DEVICE(pmic_at_9) = {
|
||||||
|
\t.name\t\t= "sandbox_pmic_test",
|
||||||
|
\t.platdata\t= &dtv_pmic_at_9,
|
||||||
|
\t.platdata_size\t= sizeof(dtv_pmic_at_9),
|
||||||
|
\t.parent_idx\t= 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Node /spl-test index 2 */
|
||||||
static struct dtd_sandbox_spl_test dtv_spl_test = {
|
static struct dtd_sandbox_spl_test dtv_spl_test = {
|
||||||
\t.boolval\t\t= true,
|
\t.boolval\t\t= true,
|
||||||
\t.bytearray\t\t= {0x6, 0x0, 0x0},
|
\t.bytearray\t\t= {0x6, 0x0, 0x0},
|
||||||
|
@ -225,15 +251,17 @@ U_BOOT_DEVICE(spl_test) = {
|
||||||
\t.name\t\t= "sandbox_spl_test",
|
\t.name\t\t= "sandbox_spl_test",
|
||||||
\t.platdata\t= &dtv_spl_test,
|
\t.platdata\t= &dtv_spl_test,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /spl-test2 index 3 */
|
||||||
static struct dtd_sandbox_spl_test dtv_spl_test2 = {
|
static struct dtd_sandbox_spl_test dtv_spl_test2 = {
|
||||||
\t.acpi_name\t\t= "\\\\_SB.GPO0",
|
\t.acpi_name\t\t= "\\\\_SB.GPO0",
|
||||||
\t.bytearray\t\t= {0x1, 0x23, 0x34},
|
\t.bytearray\t\t= {0x1, 0x23, 0x34},
|
||||||
\t.byteval\t\t= 0x8,
|
\t.byteval\t\t= 0x8,
|
||||||
\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
|
\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
|
||||||
\t.intval\t\t\t= 0x3,
|
\t.intval\t\t\t= 0x3,
|
||||||
\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0x0, 0x0, 0x0, 0x0,
|
||||||
\t\t0x0},
|
\t\t0x0},
|
||||||
\t.stringarray\t\t= {"another", "multi-word", "message"},
|
\t.stringarray\t\t= {"another", "multi-word", "message"},
|
||||||
\t.stringval\t\t= "message2",
|
\t.stringval\t\t= "message2",
|
||||||
|
@ -242,41 +270,30 @@ U_BOOT_DEVICE(spl_test2) = {
|
||||||
\t.name\t\t= "sandbox_spl_test",
|
\t.name\t\t= "sandbox_spl_test",
|
||||||
\t.platdata\t= &dtv_spl_test2,
|
\t.platdata\t= &dtv_spl_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /spl-test3 index 4 */
|
||||||
static struct dtd_sandbox_spl_test dtv_spl_test3 = {
|
static struct dtd_sandbox_spl_test dtv_spl_test3 = {
|
||||||
|
\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
|
||||||
|
\t\t0x0},
|
||||||
\t.stringarray\t\t= {"one", "", ""},
|
\t.stringarray\t\t= {"one", "", ""},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(spl_test3) = {
|
U_BOOT_DEVICE(spl_test3) = {
|
||||||
\t.name\t\t= "sandbox_spl_test",
|
\t.name\t\t= "sandbox_spl_test",
|
||||||
\t.platdata\t= &dtv_spl_test3,
|
\t.platdata\t= &dtv_spl_test3,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test3),
|
\t.platdata_size\t= sizeof(dtv_spl_test3),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /spl-test4 index 5 */
|
||||||
static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
|
static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(spl_test4) = {
|
U_BOOT_DEVICE(spl_test4) = {
|
||||||
\t.name\t\t= "sandbox_spl_test_2",
|
\t.name\t\t= "sandbox_spl_test_2",
|
||||||
\t.platdata\t= &dtv_spl_test4,
|
\t.platdata\t= &dtv_spl_test4,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test4),
|
\t.platdata_size\t= sizeof(dtv_spl_test4),
|
||||||
};
|
\t.parent_idx\t= -1,
|
||||||
|
|
||||||
static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
|
|
||||||
};
|
|
||||||
U_BOOT_DEVICE(i2c_at_0) = {
|
|
||||||
\t.name\t\t= "sandbox_i2c_test",
|
|
||||||
\t.platdata\t= &dtv_i2c_at_0,
|
|
||||||
\t.platdata_size\t= sizeof(dtv_i2c_at_0),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
|
|
||||||
\t.low_power\t\t= true,
|
|
||||||
\t.reg\t\t\t= {0x9, 0x0},
|
|
||||||
};
|
|
||||||
U_BOOT_DEVICE(pmic_at_9) = {
|
|
||||||
\t.name\t\t= "sandbox_pmic_test",
|
|
||||||
\t.platdata\t= &dtv_pmic_at_9,
|
|
||||||
\t.platdata_size\t= sizeof(dtv_pmic_at_9),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
@ -300,6 +317,7 @@ struct dtd_sandbox_gpio {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /gpios@0 index 0 */
|
||||||
static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
|
static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
|
||||||
\t.gpio_bank_name\t\t= "a",
|
\t.gpio_bank_name\t\t= "a",
|
||||||
\t.gpio_controller\t= true,
|
\t.gpio_controller\t= true,
|
||||||
|
@ -309,6 +327,7 @@ U_BOOT_DEVICE(gpios_at_0) = {
|
||||||
\t.name\t\t= "sandbox_gpio",
|
\t.name\t\t= "sandbox_gpio",
|
||||||
\t.platdata\t= &dtv_gpios_at_0,
|
\t.platdata\t= &dtv_gpios_at_0,
|
||||||
\t.platdata_size\t= sizeof(dtv_gpios_at_0),
|
\t.platdata_size\t= sizeof(dtv_gpios_at_0),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
|
@ -333,12 +352,14 @@ struct dtd_invalid {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /spl-test index 0 */
|
||||||
static struct dtd_invalid dtv_spl_test = {
|
static struct dtd_invalid dtv_spl_test = {
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(spl_test) = {
|
U_BOOT_DEVICE(spl_test) = {
|
||||||
\t.name\t\t= "invalid",
|
\t.name\t\t= "invalid",
|
||||||
\t.platdata\t= &dtv_spl_test,
|
\t.platdata\t= &dtv_spl_test,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
|
@ -365,15 +386,7 @@ struct dtd_target {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
static struct dtd_target dtv_phandle_target = {
|
/* Node /phandle2-target index 0 */
|
||||||
\t.intval\t\t\t= 0x0,
|
|
||||||
};
|
|
||||||
U_BOOT_DEVICE(phandle_target) = {
|
|
||||||
\t.name\t\t= "target",
|
|
||||||
\t.platdata\t= &dtv_phandle_target,
|
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct dtd_target dtv_phandle2_target = {
|
static struct dtd_target dtv_phandle2_target = {
|
||||||
\t.intval\t\t\t= 0x1,
|
\t.intval\t\t\t= 0x1,
|
||||||
};
|
};
|
||||||
|
@ -381,8 +394,10 @@ U_BOOT_DEVICE(phandle2_target) = {
|
||||||
\t.name\t\t= "target",
|
\t.name\t\t= "target",
|
||||||
\t.platdata\t= &dtv_phandle2_target,
|
\t.platdata\t= &dtv_phandle2_target,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle3-target index 1 */
|
||||||
static struct dtd_target dtv_phandle3_target = {
|
static struct dtd_target dtv_phandle3_target = {
|
||||||
\t.intval\t\t\t= 0x2,
|
\t.intval\t\t\t= 0x2,
|
||||||
};
|
};
|
||||||
|
@ -390,37 +405,48 @@ U_BOOT_DEVICE(phandle3_target) = {
|
||||||
\t.name\t\t= "target",
|
\t.name\t\t= "target",
|
||||||
\t.platdata\t= &dtv_phandle3_target,
|
\t.platdata\t= &dtv_phandle3_target,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-target index 4 */
|
||||||
|
static struct dtd_target dtv_phandle_target = {
|
||||||
|
\t.intval\t\t\t= 0x0,
|
||||||
|
};
|
||||||
|
U_BOOT_DEVICE(phandle_target) = {
|
||||||
|
\t.name\t\t= "target",
|
||||||
|
\t.platdata\t= &dtv_phandle_target,
|
||||||
|
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-source index 2 */
|
||||||
static struct dtd_source dtv_phandle_source = {
|
static struct dtd_source dtv_phandle_source = {
|
||||||
\t.clocks\t\t\t= {
|
\t.clocks\t\t\t= {
|
||||||
\t\t\t{NULL, {}},
|
\t\t\t{4, {}},
|
||||||
\t\t\t{NULL, {11}},
|
\t\t\t{0, {11}},
|
||||||
\t\t\t{NULL, {12, 13}},
|
\t\t\t{1, {12, 13}},
|
||||||
\t\t\t{NULL, {}},},
|
\t\t\t{4, {}},},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_source) = {
|
U_BOOT_DEVICE(phandle_source) = {
|
||||||
\t.name\t\t= "source",
|
\t.name\t\t= "source",
|
||||||
\t.platdata\t= &dtv_phandle_source,
|
\t.platdata\t= &dtv_phandle_source,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-source2 index 3 */
|
||||||
static struct dtd_source dtv_phandle_source2 = {
|
static struct dtd_source dtv_phandle_source2 = {
|
||||||
\t.clocks\t\t\t= {
|
\t.clocks\t\t\t= {
|
||||||
\t\t\t{NULL, {}},},
|
\t\t\t{4, {}},},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_source2) = {
|
U_BOOT_DEVICE(phandle_source2) = {
|
||||||
\t.name\t\t= "source",
|
\t.name\t\t= "source",
|
||||||
\t.platdata\t= &dtv_phandle_source2,
|
\t.platdata\t= &dtv_phandle_source2,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
\tdtv_phandle_source.clocks[0].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
\tdtv_phandle_source.clocks[1].node = DM_GET_DEVICE(phandle2_target);
|
|
||||||
\tdtv_phandle_source.clocks[2].node = DM_GET_DEVICE(phandle3_target);
|
|
||||||
\tdtv_phandle_source.clocks[3].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
}
|
}
|
||||||
''', data)
|
''', data)
|
||||||
|
|
||||||
|
@ -448,26 +474,29 @@ struct dtd_target {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /phandle-target index 1 */
|
||||||
static struct dtd_target dtv_phandle_target = {
|
static struct dtd_target dtv_phandle_target = {
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_target) = {
|
U_BOOT_DEVICE(phandle_target) = {
|
||||||
\t.name\t\t= "target",
|
\t.name\t\t= "target",
|
||||||
\t.platdata\t= &dtv_phandle_target,
|
\t.platdata\t= &dtv_phandle_target,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-source2 index 0 */
|
||||||
static struct dtd_source dtv_phandle_source2 = {
|
static struct dtd_source dtv_phandle_source2 = {
|
||||||
\t.clocks\t\t\t= {
|
\t.clocks\t\t\t= {
|
||||||
\t\t\t{NULL, {}},},
|
\t\t\t{1, {}},},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_source2) = {
|
U_BOOT_DEVICE(phandle_source2) = {
|
||||||
\t.name\t\t= "source",
|
\t.name\t\t= "source",
|
||||||
\t.platdata\t= &dtv_phandle_source2,
|
\t.platdata\t= &dtv_phandle_source2,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
}
|
}
|
||||||
''', data)
|
''', data)
|
||||||
|
|
||||||
|
@ -479,15 +508,7 @@ void dm_populate_phandle_data(void) {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
static struct dtd_target dtv_phandle_target = {
|
/* Node /phandle2-target index 0 */
|
||||||
\t.intval\t\t\t= 0x0,
|
|
||||||
};
|
|
||||||
U_BOOT_DEVICE(phandle_target) = {
|
|
||||||
\t.name\t\t= "target",
|
|
||||||
\t.platdata\t= &dtv_phandle_target,
|
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct dtd_target dtv_phandle2_target = {
|
static struct dtd_target dtv_phandle2_target = {
|
||||||
\t.intval\t\t\t= 0x1,
|
\t.intval\t\t\t= 0x1,
|
||||||
};
|
};
|
||||||
|
@ -495,8 +516,10 @@ U_BOOT_DEVICE(phandle2_target) = {
|
||||||
\t.name\t\t= "target",
|
\t.name\t\t= "target",
|
||||||
\t.platdata\t= &dtv_phandle2_target,
|
\t.platdata\t= &dtv_phandle2_target,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
\t.platdata_size\t= sizeof(dtv_phandle2_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle3-target index 1 */
|
||||||
static struct dtd_target dtv_phandle3_target = {
|
static struct dtd_target dtv_phandle3_target = {
|
||||||
\t.intval\t\t\t= 0x2,
|
\t.intval\t\t\t= 0x2,
|
||||||
};
|
};
|
||||||
|
@ -504,37 +527,48 @@ U_BOOT_DEVICE(phandle3_target) = {
|
||||||
\t.name\t\t= "target",
|
\t.name\t\t= "target",
|
||||||
\t.platdata\t= &dtv_phandle3_target,
|
\t.platdata\t= &dtv_phandle3_target,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
\t.platdata_size\t= sizeof(dtv_phandle3_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-target index 4 */
|
||||||
|
static struct dtd_target dtv_phandle_target = {
|
||||||
|
\t.intval\t\t\t= 0x0,
|
||||||
|
};
|
||||||
|
U_BOOT_DEVICE(phandle_target) = {
|
||||||
|
\t.name\t\t= "target",
|
||||||
|
\t.platdata\t= &dtv_phandle_target,
|
||||||
|
\t.platdata_size\t= sizeof(dtv_phandle_target),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-source index 2 */
|
||||||
static struct dtd_source dtv_phandle_source = {
|
static struct dtd_source dtv_phandle_source = {
|
||||||
\t.cd_gpios\t\t= {
|
\t.cd_gpios\t\t= {
|
||||||
\t\t\t{NULL, {}},
|
\t\t\t{4, {}},
|
||||||
\t\t\t{NULL, {11}},
|
\t\t\t{0, {11}},
|
||||||
\t\t\t{NULL, {12, 13}},
|
\t\t\t{1, {12, 13}},
|
||||||
\t\t\t{NULL, {}},},
|
\t\t\t{4, {}},},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_source) = {
|
U_BOOT_DEVICE(phandle_source) = {
|
||||||
\t.name\t\t= "source",
|
\t.name\t\t= "source",
|
||||||
\t.platdata\t= &dtv_phandle_source,
|
\t.platdata\t= &dtv_phandle_source,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
\t.platdata_size\t= sizeof(dtv_phandle_source),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /phandle-source2 index 3 */
|
||||||
static struct dtd_source dtv_phandle_source2 = {
|
static struct dtd_source dtv_phandle_source2 = {
|
||||||
\t.cd_gpios\t\t= {
|
\t.cd_gpios\t\t= {
|
||||||
\t\t\t{NULL, {}},},
|
\t\t\t{4, {}},},
|
||||||
};
|
};
|
||||||
U_BOOT_DEVICE(phandle_source2) = {
|
U_BOOT_DEVICE(phandle_source2) = {
|
||||||
\t.name\t\t= "source",
|
\t.name\t\t= "source",
|
||||||
\t.platdata\t= &dtv_phandle_source2,
|
\t.platdata\t= &dtv_phandle_source2,
|
||||||
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
\t.platdata_size\t= sizeof(dtv_phandle_source2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_populate_phandle_data(void) {
|
void dm_populate_phandle_data(void) {
|
||||||
\tdtv_phandle_source.cd_gpios[0].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
\tdtv_phandle_source.cd_gpios[1].node = DM_GET_DEVICE(phandle2_target);
|
|
||||||
\tdtv_phandle_source.cd_gpios[2].node = DM_GET_DEVICE(phandle3_target);
|
|
||||||
\tdtv_phandle_source.cd_gpios[3].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
\tdtv_phandle_source2.cd_gpios[0].node = DM_GET_DEVICE(phandle_target);
|
|
||||||
}
|
}
|
||||||
''', data)
|
''', data)
|
||||||
|
|
||||||
|
@ -581,6 +615,7 @@ struct dtd_test3 {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /test1 index 0 */
|
||||||
static struct dtd_test1 dtv_test1 = {
|
static struct dtd_test1 dtv_test1 = {
|
||||||
\t.reg\t\t\t= {0x1234, 0x5678},
|
\t.reg\t\t\t= {0x1234, 0x5678},
|
||||||
};
|
};
|
||||||
|
@ -588,8 +623,10 @@ U_BOOT_DEVICE(test1) = {
|
||||||
\t.name\t\t= "test1",
|
\t.name\t\t= "test1",
|
||||||
\t.platdata\t= &dtv_test1,
|
\t.platdata\t= &dtv_test1,
|
||||||
\t.platdata_size\t= sizeof(dtv_test1),
|
\t.platdata_size\t= sizeof(dtv_test1),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test2 index 1 */
|
||||||
static struct dtd_test2 dtv_test2 = {
|
static struct dtd_test2 dtv_test2 = {
|
||||||
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
|
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
|
||||||
};
|
};
|
||||||
|
@ -597,8 +634,10 @@ U_BOOT_DEVICE(test2) = {
|
||||||
\t.name\t\t= "test2",
|
\t.name\t\t= "test2",
|
||||||
\t.platdata\t= &dtv_test2,
|
\t.platdata\t= &dtv_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_test2),
|
\t.platdata_size\t= sizeof(dtv_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test3 index 2 */
|
||||||
static struct dtd_test3 dtv_test3 = {
|
static struct dtd_test3 dtv_test3 = {
|
||||||
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
|
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
|
||||||
};
|
};
|
||||||
|
@ -606,6 +645,7 @@ U_BOOT_DEVICE(test3) = {
|
||||||
\t.name\t\t= "test3",
|
\t.name\t\t= "test3",
|
||||||
\t.platdata\t= &dtv_test3,
|
\t.platdata\t= &dtv_test3,
|
||||||
\t.platdata_size\t= sizeof(dtv_test3),
|
\t.platdata_size\t= sizeof(dtv_test3),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
@ -630,6 +670,7 @@ struct dtd_test2 {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /test1 index 0 */
|
||||||
static struct dtd_test1 dtv_test1 = {
|
static struct dtd_test1 dtv_test1 = {
|
||||||
\t.reg\t\t\t= {0x1234, 0x5678},
|
\t.reg\t\t\t= {0x1234, 0x5678},
|
||||||
};
|
};
|
||||||
|
@ -637,8 +678,10 @@ U_BOOT_DEVICE(test1) = {
|
||||||
\t.name\t\t= "test1",
|
\t.name\t\t= "test1",
|
||||||
\t.platdata\t= &dtv_test1,
|
\t.platdata\t= &dtv_test1,
|
||||||
\t.platdata_size\t= sizeof(dtv_test1),
|
\t.platdata_size\t= sizeof(dtv_test1),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test2 index 1 */
|
||||||
static struct dtd_test2 dtv_test2 = {
|
static struct dtd_test2 dtv_test2 = {
|
||||||
\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
|
\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
|
||||||
};
|
};
|
||||||
|
@ -646,6 +689,7 @@ U_BOOT_DEVICE(test2) = {
|
||||||
\t.name\t\t= "test2",
|
\t.name\t\t= "test2",
|
||||||
\t.platdata\t= &dtv_test2,
|
\t.platdata\t= &dtv_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_test2),
|
\t.platdata_size\t= sizeof(dtv_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
@ -673,6 +717,7 @@ struct dtd_test3 {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /test1 index 0 */
|
||||||
static struct dtd_test1 dtv_test1 = {
|
static struct dtd_test1 dtv_test1 = {
|
||||||
\t.reg\t\t\t= {0x123400000000, 0x5678},
|
\t.reg\t\t\t= {0x123400000000, 0x5678},
|
||||||
};
|
};
|
||||||
|
@ -680,8 +725,10 @@ U_BOOT_DEVICE(test1) = {
|
||||||
\t.name\t\t= "test1",
|
\t.name\t\t= "test1",
|
||||||
\t.platdata\t= &dtv_test1,
|
\t.platdata\t= &dtv_test1,
|
||||||
\t.platdata_size\t= sizeof(dtv_test1),
|
\t.platdata_size\t= sizeof(dtv_test1),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test2 index 1 */
|
||||||
static struct dtd_test2 dtv_test2 = {
|
static struct dtd_test2 dtv_test2 = {
|
||||||
\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
|
\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
|
||||||
};
|
};
|
||||||
|
@ -689,8 +736,10 @@ U_BOOT_DEVICE(test2) = {
|
||||||
\t.name\t\t= "test2",
|
\t.name\t\t= "test2",
|
||||||
\t.platdata\t= &dtv_test2,
|
\t.platdata\t= &dtv_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_test2),
|
\t.platdata_size\t= sizeof(dtv_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test3 index 2 */
|
||||||
static struct dtd_test3 dtv_test3 = {
|
static struct dtd_test3 dtv_test3 = {
|
||||||
\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
|
\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
|
||||||
};
|
};
|
||||||
|
@ -698,6 +747,7 @@ U_BOOT_DEVICE(test3) = {
|
||||||
\t.name\t\t= "test3",
|
\t.name\t\t= "test3",
|
||||||
\t.platdata\t= &dtv_test3,
|
\t.platdata\t= &dtv_test3,
|
||||||
\t.platdata_size\t= sizeof(dtv_test3),
|
\t.platdata_size\t= sizeof(dtv_test3),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
@ -725,6 +775,7 @@ struct dtd_test3 {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /test1 index 0 */
|
||||||
static struct dtd_test1 dtv_test1 = {
|
static struct dtd_test1 dtv_test1 = {
|
||||||
\t.reg\t\t\t= {0x1234, 0x567800000000},
|
\t.reg\t\t\t= {0x1234, 0x567800000000},
|
||||||
};
|
};
|
||||||
|
@ -732,8 +783,10 @@ U_BOOT_DEVICE(test1) = {
|
||||||
\t.name\t\t= "test1",
|
\t.name\t\t= "test1",
|
||||||
\t.platdata\t= &dtv_test1,
|
\t.platdata\t= &dtv_test1,
|
||||||
\t.platdata_size\t= sizeof(dtv_test1),
|
\t.platdata_size\t= sizeof(dtv_test1),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test2 index 1 */
|
||||||
static struct dtd_test2 dtv_test2 = {
|
static struct dtd_test2 dtv_test2 = {
|
||||||
\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
|
\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
|
||||||
};
|
};
|
||||||
|
@ -741,8 +794,10 @@ U_BOOT_DEVICE(test2) = {
|
||||||
\t.name\t\t= "test2",
|
\t.name\t\t= "test2",
|
||||||
\t.platdata\t= &dtv_test2,
|
\t.platdata\t= &dtv_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_test2),
|
\t.platdata_size\t= sizeof(dtv_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /test3 index 2 */
|
||||||
static struct dtd_test3 dtv_test3 = {
|
static struct dtd_test3 dtv_test3 = {
|
||||||
\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
|
\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
|
||||||
};
|
};
|
||||||
|
@ -750,6 +805,7 @@ U_BOOT_DEVICE(test3) = {
|
||||||
\t.name\t\t= "test3",
|
\t.name\t\t= "test3",
|
||||||
\t.platdata\t= &dtv_test3,
|
\t.platdata\t= &dtv_test3,
|
||||||
\t.platdata_size\t= sizeof(dtv_test3),
|
\t.platdata_size\t= sizeof(dtv_test3),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
@ -792,6 +848,7 @@ struct dtd_sandbox_spl_test {
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._CheckStrings(C_HEADER + '''
|
self._CheckStrings(C_HEADER + '''
|
||||||
|
/* Node /spl-test index 0 */
|
||||||
static struct dtd_sandbox_spl_test dtv_spl_test = {
|
static struct dtd_sandbox_spl_test dtv_spl_test = {
|
||||||
\t.intval\t\t\t= 0x1,
|
\t.intval\t\t\t= 0x1,
|
||||||
};
|
};
|
||||||
|
@ -799,8 +856,10 @@ U_BOOT_DEVICE(spl_test) = {
|
||||||
\t.name\t\t= "sandbox_spl_test",
|
\t.name\t\t= "sandbox_spl_test",
|
||||||
\t.platdata\t= &dtv_spl_test,
|
\t.platdata\t= &dtv_spl_test,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test),
|
\t.platdata_size\t= sizeof(dtv_spl_test),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Node /spl-test2 index 1 */
|
||||||
static struct dtd_sandbox_spl_test dtv_spl_test2 = {
|
static struct dtd_sandbox_spl_test dtv_spl_test2 = {
|
||||||
\t.intarray\t\t= 0x5,
|
\t.intarray\t\t= 0x5,
|
||||||
};
|
};
|
||||||
|
@ -808,6 +867,7 @@ U_BOOT_DEVICE(spl_test2) = {
|
||||||
\t.name\t\t= "sandbox_spl_test",
|
\t.name\t\t= "sandbox_spl_test",
|
||||||
\t.platdata\t= &dtv_spl_test2,
|
\t.platdata\t= &dtv_spl_test2,
|
||||||
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
\t.platdata_size\t= sizeof(dtv_spl_test2),
|
||||||
|
\t.parent_idx\t= -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
|
||||||
|
|
|
@ -298,6 +298,7 @@ class TestProp(unittest.TestCase):
|
||||||
def testWiden(self):
|
def testWiden(self):
|
||||||
"""Test widening of values"""
|
"""Test widening of values"""
|
||||||
node2 = self.dtb.GetNode('/spl-test2')
|
node2 = self.dtb.GetNode('/spl-test2')
|
||||||
|
node3 = self.dtb.GetNode('/spl-test3')
|
||||||
prop = self.node.props['intval']
|
prop = self.node.props['intval']
|
||||||
|
|
||||||
# No action
|
# No action
|
||||||
|
@ -316,11 +317,20 @@ class TestProp(unittest.TestCase):
|
||||||
# byte array, it should turn into an array.
|
# byte array, it should turn into an array.
|
||||||
prop = self.node.props['longbytearray']
|
prop = self.node.props['longbytearray']
|
||||||
prop2 = node2.props['longbytearray']
|
prop2 = node2.props['longbytearray']
|
||||||
|
prop3 = node3.props['longbytearray']
|
||||||
self.assertFalse(isinstance(prop2.value, list))
|
self.assertFalse(isinstance(prop2.value, list))
|
||||||
self.assertEqual(4, len(prop2.value))
|
self.assertEqual(4, len(prop2.value))
|
||||||
|
self.assertEqual(b'\x09\x0a\x0b\x0c', prop2.value)
|
||||||
prop2.Widen(prop)
|
prop2.Widen(prop)
|
||||||
self.assertTrue(isinstance(prop2.value, list))
|
self.assertTrue(isinstance(prop2.value, list))
|
||||||
self.assertEqual(9, len(prop2.value))
|
self.assertEqual(9, len(prop2.value))
|
||||||
|
self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\0',
|
||||||
|
'\0', '\0', '\0', '\0'], prop2.value)
|
||||||
|
prop3.Widen(prop)
|
||||||
|
self.assertTrue(isinstance(prop3.value, list))
|
||||||
|
self.assertEqual(9, len(prop3.value))
|
||||||
|
self.assertEqual(['\x09', '\x0a', '\x0b', '\x0c', '\x0d',
|
||||||
|
'\x0e', '\x0f', '\x10', '\0'], prop3.value)
|
||||||
|
|
||||||
# Similarly for a string array
|
# Similarly for a string array
|
||||||
prop = self.node.props['stringval']
|
prop = self.node.props['stringval']
|
||||||
|
|
Loading…
Reference in a new issue