summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-01-31 16:49:53 +0300
committerTom Rini <trini@konsulko.com>2021-01-31 16:49:53 +0300
commit242ef48ea76ae13ac6357cc50aae01eb7a46bfef (patch)
tree18105866b6063eddcc7ddb0530c002fadc377b3b
parent76404f86a24aa28efc26a296bf6ab9d697c60b9f (diff)
parentf84eda89e5970ef513fe64ba8e8d977788c44dca (diff)
downloadu-boot-242ef48ea76ae13ac6357cc50aae01eb7a46bfef.tar.xz
Merge tag 'dm-pull-30jan21' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm
tpm fixes for coral binman fixes support for symbols in sub-sections support for additional cros_ec commands various minor fixes / tweaks
-rw-r--r--Kconfig13
-rw-r--r--arch/sandbox/cpu/os.c25
-rw-r--r--arch/sandbox/cpu/start.c2
-rw-r--r--arch/sandbox/dts/sandbox.dtsi10
-rw-r--r--arch/sandbox/dts/test.dts10
-rw-r--r--arch/sandbox/include/asm/test.h15
-rw-r--r--arch/x86/cpu/i386/cpu.c2
-rw-r--r--arch/x86/cpu/start.S2
-rw-r--r--arch/x86/dts/chromebook_coral.dts21
-rw-r--r--arch/x86/include/asm/arch-apollolake/iomap.h3
-rw-r--r--cmd/cros_ec.c195
-rw-r--r--configs/chromebook_coral_defconfig1
-rw-r--r--configs/sandbox_spl_defconfig1
-rw-r--r--disk/part.c1
-rw-r--r--doc/arch/sandbox.rst35
-rw-r--r--drivers/block/sandbox.c11
-rw-r--r--drivers/clk/clk-uclass.c16
-rw-r--r--drivers/clk/intel/clk_intel.c4
-rw-r--r--drivers/core/device.c9
-rw-r--r--drivers/core/of_extra.c21
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/designware_i2c_pci.c2
-rw-r--r--drivers/misc/cros_ec.c200
-rw-r--r--drivers/misc/cros_ec_lpc.c7
-rw-r--r--drivers/misc/cros_ec_sandbox.c100
-rw-r--r--drivers/rtc/i2c_rtc_emul.c4
-rw-r--r--drivers/tpm/cr50_i2c.c42
-rw-r--r--include/cros_ec.h142
l---------include/ctype.h1
-rw-r--r--include/dm/device.h2
-rw-r--r--include/dm/read.h5
-rw-r--r--include/ec_commands.h45
-rw-r--r--include/os.h18
-rw-r--r--lib/binman.c2
-rw-r--r--test/dm/Makefile2
-rw-r--r--test/dm/cros_ec.c178
-rw-r--r--test/dm/of_extra.c38
-rw-r--r--test/dm/of_platdata.c8
-rw-r--r--tools/binman/README3
-rw-r--r--tools/binman/control.py3
-rw-r--r--tools/binman/elf.py3
-rw-r--r--tools/binman/elf_test.py4
-rw-r--r--tools/binman/entry.py3
-rw-r--r--tools/binman/etype/blob.py4
-rw-r--r--tools/binman/etype/files.py4
-rw-r--r--tools/binman/etype/section.py66
-rw-r--r--tools/binman/etype/u_boot_spl_bss_pad.py1
-rw-r--r--tools/binman/etype/u_boot_spl_nodtb.py2
-rw-r--r--tools/binman/etype/vblock.py15
-rw-r--r--tools/binman/fmap_util.py4
-rw-r--r--tools/binman/ftest.py110
-rw-r--r--tools/binman/image.py62
-rw-r--r--tools/binman/state.py10
-rw-r--r--tools/binman/test/084_files.dts2
-rw-r--r--tools/binman/test/187_symbols_sub.dts22
-rw-r--r--tools/binman/test/188_image_entryarg.dts21
-rw-r--r--tools/binman/test/189_vblock_content.dts31
-rw-r--r--tools/binman/test/190_files_align.dts12
-rw-r--r--tools/binman/test/191_read_image_skip.dts23
-rw-r--r--tools/dtoc/fdt.py15
-rwxr-xr-xtools/dtoc/test_fdt.py6
-rw-r--r--tools/patman/tools.py3
62 files changed, 1487 insertions, 137 deletions
diff --git a/Kconfig b/Kconfig
index 6dc20ed25b..86f0a39bb0 100644
--- a/Kconfig
+++ b/Kconfig
@@ -217,22 +217,25 @@ config SYS_MALLOC_LEN
TODO: Use for other architectures
config SPL_SYS_MALLOC_F_LEN
- hex "Size of malloc() pool in SPL before relocation"
+ hex "Size of malloc() pool in SPL"
depends on SYS_MALLOC_F && SPL
default 0x2800 if RCAR_GEN3
default SYS_MALLOC_F_LEN
help
- Before relocation, memory is very limited on many platforms. Still,
+ In SPL memory is very limited on many platforms. Still,
we can provide a small malloc() pool if needed. Driver model in
particular needs this to operate, so that it can allocate the
initial serial device and any others that are needed.
+ It is possible to enable CONFIG_SYS_SPL_MALLOC_START to start a new
+ malloc() region in SDRAM once it is inited.
+
config TPL_SYS_MALLOC_F_LEN
- hex "Size of malloc() pool in TPL before relocation"
+ hex "Size of malloc() pool in TPL"
depends on SYS_MALLOC_F && TPL
- default SYS_MALLOC_F_LEN
+ default SPL_SYS_MALLOC_F_LEN
help
- Before relocation, memory is very limited on many platforms. Still,
+ In TPL memory is very limited on many platforms. Still,
we can provide a small malloc() pool if needed. Driver model in
particular needs this to operate, so that it can allocate the
initial serial device and any others that are needed.
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 80996a91ce..3d8af0a52b 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -32,6 +32,9 @@
#include <os.h>
#include <rtc_def.h>
+/* Environment variable for time offset */
+#define ENV_TIME_OFFSET "UBOOT_SB_TIME_OFFSET"
+
/* Operating System Interface */
struct os_mem_hdr {
@@ -798,6 +801,28 @@ int os_spl_to_uboot(const char *fname)
return os_jump_to_file(fname);
}
+long os_get_time_offset(void)
+{
+ const char *offset;
+
+ offset = getenv(ENV_TIME_OFFSET);
+ if (offset)
+ return strtol(offset, NULL, 0);
+ return 0;
+}
+
+void os_set_time_offset(long offset)
+{
+ char buf[21];
+ int ret;
+
+ snprintf(buf, sizeof(buf), "%ld", offset);
+ ret = setenv(ENV_TIME_OFFSET, buf, true);
+ if (ret)
+ printf("Could not set environment variable %s\n",
+ ENV_TIME_OFFSET);
+}
+
void os_localtime(struct rtc_time *rt)
{
time_t t = time(NULL);
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2d18d9debc..2542580974 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -215,7 +215,7 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state,
if (!p)
p = fname + strlen(fname);
len -= p - fname;
- snprintf(p, len, fmt, p);
+ snprintf(p, len, fmt);
state->fdt_fname = fname;
return 0;
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index d842f02176..dc933f3bfc 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -260,10 +260,14 @@
stringarray = "pre-proper";
};
- spl-test7 {
+ test-bus {
+ compatible = "simple-bus";
u-boot,dm-spl;
- compatible = "sandbox,spl-test";
- stringarray = "spl";
+ spl-test7 {
+ u-boot,dm-spl;
+ compatible = "sandbox,spl-test";
+ stringarray = "spl";
+ };
};
square {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f86cd0d3b2..e95f4631bf 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -90,6 +90,16 @@
wp-ro {
image-pos = <0xf000>;
size = <0x1000>;
+ used = <0x884>;
+ compress = "lz4";
+ uncomp-size = <0xcf8>;
+ hash {
+ algo = "sha256";
+ value = [00 01 02 03 04 05 06 07
+ 08 09 0a 0b 0c 0d 0e 0f
+ 10 11 12 13 14 15 16 17
+ 18 19 1a 1b 1c 1d 1e 1f];
+ };
};
rw {
image-pos = <0x10000>;
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 05f66f700c..1cb960ac24 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -58,6 +58,13 @@ enum {
};
/**
+ */
+enum cros_ec_test_t {
+ CROSECT_BREAK_HELLO = BIT(1),
+ CROSECT_LID_OPEN = BIT(2),
+};
+
+/**
* sandbox_i2c_set_test_mode() - set test mode for running unit tests
*
* See sandbox_i2c_xfer() for the behaviour changes.
@@ -260,4 +267,12 @@ uint sandbox_pci_read_bar(u32 barval, int type, uint size);
*/
void sandbox_set_enable_memio(bool enable);
+/**
+ * sandbox_cros_ec_set_test_flags() - Set behaviour for testing purposes
+ *
+ * @dev: Device to check
+ * @flags: Flags to control behaviour (CROSECT_...)
+ */
+void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags);
+
#endif
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 7517b756f4..6fa0f4d32b 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -175,7 +175,7 @@ void arch_setup_gd(gd_t *new_gd)
* Per Intel FSP external architecture specification, before calling any FSP
* APIs, we need make sure the system is in flat 32-bit mode and both the code
* and data selectors should have full 4GB access range. Here we reuse the one
- * we used in arch/x86/cpu/start16.S, and reload the segement registers.
+ * we used in arch/x86/cpu/start16.S, and reload the segment registers.
*/
void setup_fsp_gdt(void)
{
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 3b6ed37bc0..3d0d95295f 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -77,7 +77,7 @@ _start:
lgdt gdt_ptr2
#endif
- /* Load the segement registers to match the GDT loaded in start16.S */
+ /* Load the segment registers to match the GDT loaded in start16.S */
movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
movw %ax, %fs
movw %ax, %ds
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
index a846022095..9319123c0c 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/x86-gpio.h>
/include/ "skeleton.dtsi"
@@ -99,6 +100,7 @@
clk: clock {
compatible = "intel,apl-clk";
#clock-cells = <1>;
+ u-boot,dm-pre-reloc;
};
cpus {
@@ -139,6 +141,7 @@
};
acpi_gpe: general-purpose-events {
+ u-boot,dm-pre-reloc;
reg = <IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>;
compatible = "intel,acpi-gpe";
interrupt-controller;
@@ -417,8 +420,10 @@
};
i2c_2: i2c2@16,2 {
- compatible = "intel,apl-i2c";
+ compatible = "intel,apl-i2c", "snps,designware-i2c-pci";
reg = <0x0200b210 0 0 0 0>;
+ early-regs = <IOMAP_I2C2_BASE 0x1000>;
+ u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <400000>;
@@ -429,6 +434,7 @@
tpm: tpm@50 {
reg = <0x50>;
compatible = "google,cr50";
+ u-boot,dm-pre-reloc;
u-boot,i2c-offset-len = <0>;
ready-gpios = <&gpio_n 28 GPIO_ACTIVE_LOW>;
interrupts-extended = <&acpi_gpe GPIO_28_IRQ
@@ -583,6 +589,7 @@
u-boot,dm-pre-reloc;
cros_ec: cros-ec {
u-boot,dm-pre-proper;
+ u-boot,dm-vpl;
compatible = "google,cros-ec-lpc";
reg = <0x204 1 0x200 1 0x880 0x80>;
@@ -637,6 +644,7 @@
PAD_CFG0_TX_DISABLE | PAD_CFG0_ROUTE_IOAPIC |
PAD_CFG0_TRIG_LEVEL | PAD_CFG0_RX_POL_INVERT)
(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TXD_RXE)
+ PAD_CFG_GPI(GPIO_25, UP_20K, DEEP) /* unused */
/*
* WLAN_PE_RST - default to deasserted just in case FSP
@@ -657,6 +665,11 @@
PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1) /* LPC_AD3 */
PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */
PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */
+
+ PAD_CFG_GPI(GPIO_101, NONE, DEEP) /* FST_IO2 -- MEM_CONFIG0 */
+ PAD_CFG_GPI(GPIO_102, NONE, DEEP) /* FST_IO3 -- MEM_CONFIG1 */
+ PAD_CFG_GPI(GPIO_38, NONE, DEEP) /* LPSS_UART0_RXD - MEM_CONFIG2*/
+ PAD_CFG_GPI(GPIO_45, NONE, DEEP) /* LPSS_UART1_CTS - MEM_CONFIG3 */
>;
};
@@ -1210,3 +1223,9 @@
PAD_CFG_GPI(GPIO_73, UP_20K, DEEP) /* GP_CAMERASB11 */
>;
};
+
+&rtc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/x86/include/asm/arch-apollolake/iomap.h b/arch/x86/include/asm/arch-apollolake/iomap.h
index 21c5f33021..a4ea150707 100644
--- a/arch/x86/include/asm/arch-apollolake/iomap.h
+++ b/arch/x86/include/asm/arch-apollolake/iomap.h
@@ -33,6 +33,9 @@
#define SRAM_SIZE_2 (4 * KiB)
#endif
+/* Early address for I2C port 2 */
+#define IOMAP_I2C2_BASE (0xfe020000 + 2 * 0x1000)
+
/*
* Use UART2. To use UART1 you need to set '2' to '1', change device tree serial
* node name and 'reg' property, and update CONFIG_DEBUG_UART_BASE.
diff --git a/cmd/cros_ec.c b/cmd/cros_ec.c
index ce1f59a740..eb5053d642 100644
--- a/cmd/cros_ec.c
+++ b/cmd/cros_ec.c
@@ -94,6 +94,169 @@ static int do_read_write(struct udevice *dev, int is_write, int argc,
return 0;
}
+static const char *const feat_name[64] = {
+ "limited",
+ "flash",
+ "pwm_fan",
+ "pwm_keyb",
+ "lightbar",
+ "led",
+ "motion_sense",
+ "keyb",
+ "pstore",
+ "port80",
+ "thermal",
+ "bklight_switch",
+ "wifi_switch",
+ "host_events",
+ "gpio",
+ "i2c",
+ "charger",
+ "battery",
+ "smart_battery",
+ "hang_detect",
+ "pmu",
+ "sub_mcu",
+ "usb_pd",
+ "usb_mux",
+ "motion_sense_fifo",
+ "vstore",
+ "usbc_ss_mux_virtual",
+ "rtc",
+ "fingerprint",
+ "touchpad",
+ "rwsig",
+ "device_event",
+ "unified_wake_masks",
+ "host_event64",
+ "exec_in_ram",
+ "cec",
+ "motion_sense_tight_timestamps",
+ "refined_tablet_mode_hysteresis",
+ "efs2",
+ "scp",
+ "ish",
+ "typec_cmd",
+ "typec_require_ap_mode_entry",
+ "typec_mux_require_ap_ack",
+};
+
+static int do_show_features(struct udevice *dev)
+{
+ u64 feat;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_features(dev, &feat);
+ if (ret)
+ return ret;
+ for (i = 0; i < ARRAY_SIZE(feat_name); i++) {
+ if (feat & (1ULL << i)) {
+ if (feat_name[i])
+ printf("%s\n", feat_name[i]);
+ else
+ printf("unknown %d\n", i);
+ }
+ }
+
+ return 0;
+}
+
+static const char *const switch_name[8] = {
+ "lid open",
+ "power button pressed",
+ "write-protect disabled",
+ NULL,
+ "dedicated recovery",
+ NULL,
+ NULL,
+ NULL,
+};
+
+static int do_show_switches(struct udevice *dev)
+{
+ uint switches;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_switches(dev);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ switches = ret;
+ for (i = 0; i < ARRAY_SIZE(switch_name); i++) {
+ uint mask = 1 << i;
+
+ if (switches & mask) {
+ if (switch_name[i])
+ printf("%s\n", switch_name[i]);
+ else
+ printf("unknown %02x\n", mask);
+ }
+ }
+
+ return 0;
+}
+
+static const char *const event_name[] = {
+ "lid_closed",
+ "lid_open",
+ "power_button",
+ "ac_connected",
+ "ac_disconnected",
+ "battery_low",
+ "battery_critical",
+ "battery",
+ "thermal_threshold",
+ "device",
+ "thermal",
+ "usb_charger",
+ "key_pressed",
+ "interface_ready",
+ "keyboard_recovery",
+ "thermal_shutdown",
+ "battery_shutdown",
+ "throttle_start",
+ "throttle_stop",
+ "hang_detect",
+ "hang_reboot",
+ "pd_mcu",
+ "battery_status",
+ "panic",
+ "keyboard_fastboot",
+ "rtc",
+ "mkbp",
+ "usb_mux",
+ "mode_change",
+ "keyboard_recovery_hw_reinit",
+ "extended",
+ "invalid",
+};
+
+static int do_show_events(struct udevice *dev)
+{
+ u32 events;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_host_events(dev, &events);
+ if (ret)
+ return ret;
+ printf("%08x\n", events);
+ for (i = 0; i < ARRAY_SIZE(event_name); i++) {
+ enum host_event_code code = i + 1;
+ u64 mask = EC_HOST_EVENT_MASK(code);
+
+ if (events & mask) {
+ if (event_name[i])
+ printf("%s\n", event_name[i]);
+ else
+ printf("unknown code %#x\n", code);
+ }
+ }
+
+ return 0;
+}
+
static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -140,6 +303,16 @@ static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
}
printf("rows = %u\n", info.rows);
printf("cols = %u\n", info.cols);
+ } else if (!strcmp("features", cmd)) {
+ ret = do_show_features(dev);
+
+ if (ret)
+ printf("Error: %d\n", ret);
+ } else if (!strcmp("switches", cmd)) {
+ ret = do_show_switches(dev);
+
+ if (ret)
+ printf("Error: %d\n", ret);
} else if (0 == strcmp("curimage", cmd)) {
enum ec_current_image image;
@@ -190,13 +363,10 @@ static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
return 1;
}
} else if (0 == strcmp("events", cmd)) {
- uint32_t events;
+ ret = do_show_events(dev);
- if (cros_ec_get_host_events(dev, &events)) {
- debug("%s: Could not read host events\n", __func__);
- return 1;
- }
- printf("0x%08x\n", events);
+ if (ret)
+ printf("Error: %d\n", ret);
} else if (0 == strcmp("clrevents", cmd)) {
uint32_t events = 0x7fffffff;
@@ -352,6 +522,15 @@ static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
debug("%s: Could not access LDO%d\n", __func__, index);
return ret;
}
+ } else if (!strcmp("sku", cmd)) {
+ ret = cros_ec_get_sku_id(dev);
+
+ if (ret >= 0) {
+ printf("%d\n", ret);
+ ret = 0;
+ } else {
+ printf("Error: %d\n", ret);
+ }
} else {
return CMD_RET_USAGE;
}
@@ -370,10 +549,13 @@ U_BOOT_CMD(
"init Re-init CROS-EC (done on startup automatically)\n"
"crosec id Read CROS-EC ID\n"
"crosec info Read CROS-EC info\n"
+ "crosec features Read CROS-EC features\n"
+ "crosec switches Read CROS-EC switches\n"
"crosec curimage Read CROS-EC current image\n"
"crosec hash Read CROS-EC hash\n"
"crosec reboot [rw | ro | cold] Reboot CROS-EC\n"
"crosec events Read CROS-EC host events\n"
+ "crosec eventsb Read CROS-EC host events_b\n"
"crosec clrevents [mask] Clear CROS-EC host events\n"
"crosec regioninfo <ro|rw> Read image info\n"
"crosec flashinfo Read flash info\n"
@@ -382,6 +564,7 @@ U_BOOT_CMD(
"crosec write <ro|rw> <addr> [<size>] Write EC image\n"
"crosec vbnvcontext [hexstring] Read [write] VbNvContext from EC\n"
"crosec ldo <idx> [<state>] Switch/Read LDO state\n"
+ "crosec sku Read board SKU ID\n"
"crosec test run tests on cros_ec\n"
"crosec version Read CROS-EC version"
);
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index 05e6ce6493..ab73a0a88c 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -29,6 +29,7 @@ CONFIG_BOOTSTAGE_REPORT=y
CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10
CONFIG_BOOTSTAGE_STASH=y
CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS_SUBST=y
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_LOGF_FUNC=y
CONFIG_SPL_LOG=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index d193b18f47..61dae34a6a 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -101,7 +101,6 @@ CONFIG_SYSCON=y
CONFIG_SPL_SYSCON=y
CONFIG_DEVRES=y
CONFIG_DEBUG_DEVRES=y
-# CONFIG_SPL_SIMPLE_BUS is not set
CONFIG_ADC=y
CONFIG_ADC_SANDBOX=y
CONFIG_AXI=y
diff --git a/disk/part.c b/disk/part.c
index b69fd345f3..85b1af55e2 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -150,6 +150,7 @@ void dev_print (struct blk_desc *dev_desc)
case IF_TYPE_USB:
case IF_TYPE_NVME:
case IF_TYPE_PVBLOCK:
+ case IF_TYPE_HOST:
printf ("Vendor: %s Rev: %s Prod: %s\n",
dev_desc->vendor,
dev_desc->revision,
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 4674c420ac..60ee1e0741 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -99,37 +99,44 @@ Command-line Options
Various options are available, mostly for test purposes. Use -h to see
available options. Some of these are described below:
-* -t, --terminal <arg>
- - The terminal is normally in what is called 'raw-with-sigs' mode. This means
+-t, --terminal <arg>
+ The terminal is normally in what is called 'raw-with-sigs' mode. This means
that you can use arrow keys for command editing and history, but if you
press Ctrl-C, U-Boot will exit instead of handling this as a keypress.
Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked'
(where the terminal is in cooked mode and cursor keys will not work, Ctrl-C
will exit).
-* -l
- - Show the LCD emulation window.
+-l
+ Show the LCD emulation window.
-* -d <device_tree>
- - A device tree binary file can be provided with -d. If you edit the source
+-d <device_tree>
+ A device tree binary file can be provided with -d. If you edit the source
(it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to
recreate the binary file.
-* -D
- - To use the default device tree, use -D.
+-D
+ To use the default device tree, use -D.
-* -T
- - To use the test device tree, use -T.
+-T
+ To use the test device tree, use -T.
-* -c [<cmd>;]<cmd>
- - To execute commands directly, use the -c option. You can specify a single
+-c [<cmd>;]<cmd>
+ To execute commands directly, use the -c option. You can specify a single
command, or multiple commands separated by a semicolon, as is normal in
U-Boot. Be careful with quoting as the shell will normally process and
swallow quotes. When -c is used, U-Boot exits after the command is complete,
but you can force it to go to interactive mode instead with -i.
-* -i
- - Go to interactive mode after executing the commands specified by -c.
+-i
+ Go to interactive mode after executing the commands specified by -c.
+
+Environment Variables
+---------------------
+
+UBOOT_SB_TIME_OFFSET
+ This environment variable stores the offset of the emulated real time clock
+ to the host's real time clock in seconds. The offset defaults to zero.
Memory Emulation
----------------
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index 34c26cda47..f57f690d3c 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -92,6 +92,7 @@ int host_dev_bind(int devnum, char *filename)
{
struct host_block_dev *host_dev;
struct udevice *dev;
+ struct blk_desc *desc;
char dev_name[20], *str, *fname;
int ret, fd;
@@ -143,6 +144,12 @@ int host_dev_bind(int devnum, char *filename)
goto err_file;
}
+ desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum);
+ desc->removable = 1;
+ snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
+ snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
+ snprintf(desc->revision, BLK_REV_SIZE, "1.0");
+
return 0;
err_file:
os_close(fd);
@@ -187,6 +194,10 @@ int host_dev_bind(int dev, char *filename)
blk_dev->block_write = host_block_write;
blk_dev->devnum = dev;
blk_dev->part_type = PART_TYPE_UNKNOWN;
+ blk_dev->removable = 1;
+ snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot");
+ snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile");
+ snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0");
part_init(blk_dev);
return 0;
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b75056718b..d5c4e3cbe5 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -83,7 +83,7 @@ static int clk_get_by_index_tail(int ret, ofnode node,
if (ret) {
debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
__func__, ret);
- return ret;
+ return log_msg_ret("get", ret);
}
clk->dev = dev_clk;
@@ -96,14 +96,15 @@ static int clk_get_by_index_tail(int ret, ofnode node,
ret = clk_of_xlate_default(clk, args);
if (ret) {
debug("of_xlate() failed: %d\n", ret);
- return ret;
+ return log_msg_ret("xlate", ret);
}
return clk_request(dev_clk, clk);
err:
debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
__func__, ofnode_get_name(node), list_name, index, ret);
- return ret;
+
+ return log_msg_ret("prop", ret);
}
static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
@@ -122,7 +123,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
if (ret) {
debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
__func__, ret);
- return ret;
+ return log_ret(ret);
}
@@ -470,6 +471,7 @@ int clk_free(struct clk *clk)
ulong clk_get_rate(struct clk *clk)
{
const struct clk_ops *ops;
+ int ret;
debug("%s(clk=%p)\n", __func__, clk);
if (!clk_valid(clk))
@@ -479,7 +481,11 @@ ulong clk_get_rate(struct clk *clk)
if (!ops->get_rate)
return -ENOSYS;
- return ops->get_rate(clk);
+ ret = ops->get_rate(clk);
+ if (ret)
+ return log_ret(ret);
+
+ return 0;
}
struct clk *clk_get_parent(struct clk *clk)
diff --git a/drivers/clk/intel/clk_intel.c b/drivers/clk/intel/clk_intel.c
index b633934d90..46ccbb1d83 100644
--- a/drivers/clk/intel/clk_intel.c
+++ b/drivers/clk/intel/clk_intel.c
@@ -29,8 +29,8 @@ static const struct udevice_id intel_clk_ids[] = {
{ }
};
-U_BOOT_DRIVER(clk_intel) = {
- .name = "clk_intel",
+U_BOOT_DRIVER(intel_apl_clk) = {
+ .name = "intel_apl_clk",
.id = UCLASS_CLK,
.of_match = intel_clk_ids,
.ops = &intel_clk_ops,
diff --git a/drivers/core/device.c b/drivers/core/device.c
index aeab3836ed..8629df8def 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -462,6 +462,15 @@ int device_probe(struct udevice *dev)
* continue regardless of the result of pinctrl. Don't process pinctrl
* settings for pinctrl devices since the device may not yet be
* probed.
+ *
+ * This call can produce some non-intuitive results. For example, on an
+ * x86 device where dev is the main PCI bus, the pinctrl device may be
+ * child or grandchild of that bus, meaning that the child will be
+ * probed here. If the child happens to be the P2SB and the pinctrl
+ * device is a child of that, then both the pinctrl and P2SB will be
+ * probed by this call. This works because the DM_FLAG_ACTIVATED flag
+ * is set just above. However, the PCI bus' probe() method and
+ * associated uclass methods have not yet been called.
*/
if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
pinctrl_select_state(dev, "default");
diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c
index 6420e6ec44..653344529e 100644
--- a/drivers/core/of_extra.c
+++ b/drivers/core/of_extra.c
@@ -14,16 +14,17 @@
int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
{
const char *prop;
+ ofnode subnode;
if (ofnode_read_u32(node, "image-pos", &entry->offset)) {
debug("Node '%s' has bad/missing 'image-pos' property\n",
ofnode_get_name(node));
- return log_ret(-ENOENT);
+ return log_msg_ret("image-pos", -ENOENT);
}
if (ofnode_read_u32(node, "size", &entry->length)) {
debug("Node '%s' has bad/missing 'size' property\n",
ofnode_get_name(node));
- return log_ret(-ENOENT);
+ return log_msg_ret("size", -ENOENT);
}
entry->used = ofnode_read_s32_default(node, "used", entry->length);
prop = ofnode_read_string(node, "compress");
@@ -31,18 +32,20 @@ int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
if (!strcmp(prop, "lz4"))
entry->compress_algo = FMAP_COMPRESS_LZ4;
else
- return log_msg_ret("Unknown compression algo",
- -EINVAL);
+ return log_msg_ret("compression algo", -EINVAL);
} else {
entry->compress_algo = FMAP_COMPRESS_NONE;
}
entry->unc_length = ofnode_read_s32_default(node, "uncomp-size",
entry->length);
- prop = ofnode_read_string(node, "hash");
- if (prop)
- entry->hash_size = strlen(prop);
- entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
- entry->hash = (uint8_t *)prop;
+ subnode = ofnode_find_subnode(node, "hash");
+ if (ofnode_valid(subnode)) {
+ prop = ofnode_read_prop(subnode, "value", &entry->hash_size);
+
+ /* Assume it is sha256 */
+ entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
+ entry->hash = (uint8_t *)prop;
+ }
return 0;
}
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 1aac5c481e..29aab0f9e3 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -39,7 +39,9 @@ obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
+ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
+endif
obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index ec0cdf6220..9e387737b6 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -192,6 +192,8 @@ static const struct udevice_id designware_i2c_pci_ids[] = {
{ }
};
+DM_DRIVER_ALIAS(i2c_designware_pci, intel_apl_i2c)
+
U_BOOT_DRIVER(i2c_designware_pci) = {
.name = "i2c_designware_pci",
.id = UCLASS_I2C,
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index f03b7d55d6..ebfa7c41c2 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -44,6 +44,10 @@ enum {
CROS_EC_CMD_TIMEOUT_MS = 5000,
/* Timeout waiting for a synchronous hash to be recomputed */
CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
+
+ /* Wait 10 ms between attempts to check if EC's hash is ready */
+ CROS_EC_HASH_CHECK_DELAY_MS = 10,
+
};
#define INVALID_HCMD 0xFF
@@ -400,6 +404,8 @@ static int ec_command(struct udevice *dev, uint cmd, int cmd_version,
*/
if (din && in_buffer) {
assert(len <= din_len);
+ if (len > din_len)
+ return -ENOSPC;
memmove(din, in_buffer, len);
}
}
@@ -502,9 +508,10 @@ static int cros_ec_wait_on_hash_done(struct udevice *dev,
start = get_timer(0);
while (hash->status == EC_VBOOT_HASH_STATUS_BUSY) {
- mdelay(50); /* Insert some reasonable delay */
+ mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
p->cmd = EC_VBOOT_HASH_GET;
+
if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, p, sizeof(*p), hash,
sizeof(*hash)) < 0)
return -1;
@@ -591,6 +598,25 @@ static int cros_ec_invalidate_hash(struct udevice *dev)
return 0;
}
+int cros_ec_hello(struct udevice *dev, uint *handshakep)
+{
+ struct ec_params_hello req;
+ struct ec_response_hello *resp;
+
+ req.in_data = 0x12345678;
+ if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+ (uint8_t **)&resp, sizeof(*resp)) < 0)
+ return -EIO;
+ if (resp->out_data != req.in_data + 0x01020304) {
+ printf("Received invalid handshake %x\n", resp->out_data);
+ if (handshakep)
+ *handshakep = req.in_data;
+ return -ENOTSYNC;
+ }
+
+ return 0;
+}
+
int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags)
{
struct ec_params_reboot_ec p;
@@ -603,18 +629,23 @@ int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags)
return -1;
if (!(flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) {
+ ulong start;
+
/*
* EC reboot will take place immediately so delay to allow it
* to complete. Note that some reboot types (EC_REBOOT_COLD)
* will reboot the AP as well, in which case we won't actually
* get to this point.
*/
- /*
- * TODO(rspangler@chromium.org): Would be nice if we had a
- * better way to determine when the reboot is complete. Could
- * we poll a memory-mapped LPC value?
- */
- udelay(50000);
+ mdelay(50);
+ start = get_timer(0);
+ while (cros_ec_hello(dev, NULL)) {
+ if (get_timer(start) > 3000) {
+ log_err("EC did not return from reboot\n");
+ return -ETIMEDOUT;
+ }
+ mdelay(5);
+ }
}
return 0;
@@ -738,7 +769,6 @@ static int cros_ec_check_version(struct udevice *dev)
{
struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
struct ec_params_hello req;
- struct ec_response_hello *resp;
struct dm_cros_ec_ops *ops;
int ret;
@@ -767,14 +797,14 @@ static int cros_ec_check_version(struct udevice *dev)
/* Try sending a version 3 packet */
cdev->protocol_version = 3;
req.in_data = 0;
- if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
- (uint8_t **)&resp, sizeof(*resp)) > 0)
+ ret = cros_ec_hello(dev, NULL);
+ if (!ret || ret == -ENOTSYNC)
return 0;
/* Try sending a version 2 packet */
cdev->protocol_version = 2;
- if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
- (uint8_t **)&resp, sizeof(*resp)) > 0)
+ ret = cros_ec_hello(dev, NULL);
+ if (!ret || ret == -ENOTSYNC)
return 0;
/*
@@ -790,18 +820,16 @@ static int cros_ec_check_version(struct udevice *dev)
int cros_ec_test(struct udevice *dev)
{
- struct ec_params_hello req;
- struct ec_response_hello *resp;
+ uint out_data;
+ int ret;
- req.in_data = 0x12345678;
- if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
- (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp)) {
+ ret = cros_ec_hello(dev, &out_data);
+ if (ret == -ENOTSYNC) {
+ printf("Received invalid handshake %x\n", out_data);
+ return ret;
+ } else if (ret) {
printf("ec_command_inptr() returned error\n");
- return -1;
- }
- if (resp->out_data != req.in_data + 0x01020304) {
- printf("Received invalid handshake %x\n", resp->out_data);
- return -1;
+ return ret;
}
return 0;
@@ -1077,6 +1105,19 @@ int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image,
return 0;
}
+int cros_ec_get_sku_id(struct udevice *dev)
+{
+ struct ec_sku_id_info *r;
+ int ret;
+
+ ret = ec_command_inptr(dev, EC_CMD_GET_SKU_ID, 0, NULL, 0,
+ (uint8_t **)&r, sizeof(*r));
+ if (ret != sizeof(*r))
+ return -ret;
+
+ return r->sku_id;
+}
+
int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size)
{
struct ec_params_vbnvcontext p;
@@ -1303,19 +1344,33 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
return 0;
}
-int cros_ec_check_feature(struct udevice *dev, int feature)
+int cros_ec_get_features(struct udevice *dev, u64 *featuresp)
{
struct ec_response_get_features r;
int rv;
- rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0);
- if (rv)
- return rv;
+ rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r));
+ if (rv != sizeof(r))
+ return -EIO;
+ *featuresp = r.flags[0] | (u64)r.flags[1] << 32;
+
+ return 0;
+}
+
+int cros_ec_check_feature(struct udevice *dev, uint feature)
+{
+ struct ec_response_get_features r;
+ int rv;
+
+ rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r));
+ if (rv != sizeof(r))
+ return -EIO;
if (feature >= 8 * sizeof(r.flags))
- return -1;
+ return -EINVAL;
- return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature);
+ return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature) ? true :
+ false;
}
/*
@@ -1502,10 +1557,99 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
return 0;
}
+int cros_ec_vstore_supported(struct udevice *dev)
+{
+ return cros_ec_check_feature(dev, EC_FEATURE_VSTORE);
+}
+
+int cros_ec_vstore_info(struct udevice *dev, u32 *lockedp)
+{
+ struct ec_response_vstore_info *resp;
+
+ if (ec_command_inptr(dev, EC_CMD_VSTORE_INFO, 0, NULL, 0,
+ (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
+ return -EIO;
+
+ if (lockedp)
+ *lockedp = resp->slot_locked;
+
+ return resp->slot_count;
+}
+
+/*
+ * cros_ec_vstore_read - Read data from EC vstore slot
+ *
+ * @slot: vstore slot to read from
+ * @data: buffer to store read data, must be EC_VSTORE_SLOT_SIZE bytes
+ */
+int cros_ec_vstore_read(struct udevice *dev, int slot, uint8_t *data)
+{
+ struct ec_params_vstore_read req;
+ struct ec_response_vstore_read *resp;
+
+ req.slot = slot;
+ if (ec_command_inptr(dev, EC_CMD_VSTORE_READ, 0, &req, sizeof(req),
+ (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
+ return -EIO;
+
+ if (!data || req.slot >= EC_VSTORE_SLOT_MAX)
+ return -EINVAL;
+
+ memcpy(data, resp->data, sizeof(resp->data));
+
+ return 0;
+}
+
+/*
+ * cros_ec_vstore_write - Save data into EC vstore slot
+ *
+ * @slot: vstore slot to write into
+ * @data: data to write
+ * @size: size of data in bytes
+ *
+ * Maximum size of data is EC_VSTORE_SLOT_SIZE. It is the callers
+ * responsibility to check the number of implemented slots by
+ * querying the vstore info.
+ */
+int cros_ec_vstore_write(struct udevice *dev, int slot, const uint8_t *data,
+ size_t size)
+{
+ struct ec_params_vstore_write req;
+
+ if (slot >= EC_VSTORE_SLOT_MAX || size > EC_VSTORE_SLOT_SIZE)
+ return -EINVAL;
+
+ req.slot = slot;
+ memcpy(req.data, data, size);
+
+ if (ec_command(dev, EC_CMD_VSTORE_WRITE, 0, &req, sizeof(req), NULL, 0))
+ return -EIO;
+
+ return 0;
+}
+
+int cros_ec_get_switches(struct udevice *dev)
+{
+ struct dm_cros_ec_ops *ops;
+ int ret;
+
+ ops = dm_cros_ec_get_ops(dev);
+ if (!ops->get_switches)
+ return -ENOSYS;
+
+ ret = ops->get_switches(dev);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+
+ return ret;
+}
+
UCLASS_DRIVER(cros_ec) = {
.id = UCLASS_CROS_EC,
.name = "cros-ec",
.per_device_auto = sizeof(struct cros_ec_dev),
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.post_bind = dm_scan_fdt_dev,
+#endif
.flags = DM_UC_FLAG_ALLOC_PRIV_DMA,
};
diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c
index e0002b9753..f40375978d 100644
--- a/drivers/misc/cros_ec_lpc.c
+++ b/drivers/misc/cros_ec_lpc.c
@@ -207,6 +207,12 @@ int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
return 0;
}
+/* Return the byte of EC switch states */
+static int cros_ec_lpc_get_switches(struct udevice *dev)
+{
+ return inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
+}
+
/*
* Test if LPC command args are supported.
*
@@ -239,6 +245,7 @@ static struct dm_cros_ec_ops cros_ec_ops = {
.packet = cros_ec_lpc_packet,
.command = cros_ec_lpc_command,
.check_version = cros_ec_lpc_check_version,
+ .get_switches = cros_ec_lpc_get_switches,
};
static const struct udevice_id cros_ec_ids[] = {
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 9fd6cc2086..cb8adc4495 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -18,6 +18,7 @@
#include <asm/malloc.h>
#include <asm/state.h>
#include <asm/sdl.h>
+#include <asm/test.h>
#include <linux/input.h>
/*
@@ -61,6 +62,15 @@ struct ec_keymatrix_entry {
int keycode; /* corresponding linux key code */
};
+enum {
+ VSTORE_SLOT_COUNT = 4,
+};
+
+struct vstore_slot {
+ bool locked;
+ u8 data[EC_VSTORE_SLOT_SIZE];
+};
+
/**
* struct ec_state - Information about the EC state
*
@@ -73,6 +83,8 @@ struct ec_keymatrix_entry {
* @matrix: Information about keyboard matrix
* @keyscan: Current keyscan information (bit set for each row/column pressed)
* @recovery_req: Keyboard recovery requested
+ * @test_flags: Flags that control behaviour for tests
+ * @slot_locked: Locked vstore slots (mask)
*/
struct ec_state {
u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
@@ -84,6 +96,8 @@ struct ec_state {
struct ec_keymatrix_entry *matrix; /* the key matrix info */
uint8_t keyscan[KEYBOARD_COLS];
bool recovery_req;
+ uint test_flags;
+ struct vstore_slot slot[VSTORE_SLOT_COUNT];
} s_state, *g_state;
/**
@@ -295,6 +309,8 @@ static int process_cmd(struct ec_state *ec,
struct ec_response_hello *resp = resp_data;
resp->out_data = req->in_data + 0x01020304;
+ if (ec->test_flags & CROSECT_BREAK_HELLO)
+ resp->out_data++;
len = sizeof(*resp);
break;
}
@@ -358,10 +374,20 @@ static int process_cmd(struct ec_state *ec,
resp->mask |= EC_HOST_EVENT_MASK(
EC_HOST_EVENT_KEYBOARD_RECOVERY);
}
-
+ if (ec->test_flags & CROSECT_LID_OPEN)
+ resp->mask |=
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN);
len = sizeof(*resp);
break;
}
+ case EC_CMD_HOST_EVENT_CLEAR_B: {
+ const struct ec_params_host_event_mask *req = req_data;
+
+ if (req->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN))
+ ec->test_flags &= ~CROSECT_LID_OPEN;
+ len = 0;
+ break;
+ }
case EC_CMD_VBOOT_HASH: {
const struct ec_params_vboot_hash *req = req_data;
struct ec_response_vboot_hash *resp = resp_data;
@@ -468,6 +494,62 @@ static int process_cmd(struct ec_state *ec,
len = sizeof(*resp);
break;
}
+ case EC_CMD_GET_SKU_ID: {
+ struct ec_sku_id_info *resp = resp_data;
+
+ resp->sku_id = 1234;
+ len = sizeof(*resp);
+ break;
+ }
+ case EC_CMD_GET_FEATURES: {
+ struct ec_response_get_features *resp = resp_data;
+
+ resp->flags[0] = EC_FEATURE_MASK_0(EC_FEATURE_FLASH) |
+ EC_FEATURE_MASK_0(EC_FEATURE_I2C) |
+ EC_FEATURE_MASK_0(EC_FEATURE_VSTORE);
+ resp->flags[1] =
+ EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) |
+ EC_FEATURE_MASK_1(EC_FEATURE_ISH);
+ len = sizeof(*resp);
+ break;
+ }
+ case EC_CMD_VSTORE_INFO: {
+ struct ec_response_vstore_info *resp = resp_data;
+ int i;
+
+ resp->slot_count = VSTORE_SLOT_COUNT;
+ resp->slot_locked = 0;
+ for (i = 0; i < VSTORE_SLOT_COUNT; i++) {
+ if (ec->slot[i].locked)
+ resp->slot_locked |= 1 << i;
+ }
+ len = sizeof(*resp);
+ break;
+ };
+ case EC_CMD_VSTORE_WRITE: {
+ const struct ec_params_vstore_write *req = req_data;
+ struct vstore_slot *slot;
+
+ if (req->slot >= EC_VSTORE_SLOT_MAX)
+ return -EINVAL;
+ slot = &ec->slot[req->slot];
+ slot->locked = true;
+ memcpy(slot->data, req->data, EC_VSTORE_SLOT_SIZE);
+ len = 0;
+ break;
+ }
+ case EC_CMD_VSTORE_READ: {
+ const struct ec_params_vstore_read *req = req_data;
+ struct ec_response_vstore_read *resp = resp_data;
+ struct vstore_slot *slot;
+
+ if (req->slot >= EC_VSTORE_SLOT_MAX)
+ return -EINVAL;
+ slot = &ec->slot[req->slot];
+ memcpy(resp->data, slot->data, EC_VSTORE_SLOT_SIZE);
+ len = sizeof(*resp);
+ break;
+ }
default:
printf(" ** Unknown EC command %#02x\n", req_hdr->command);
return -1;
@@ -518,6 +600,21 @@ void cros_ec_check_keyboard(struct udevice *dev)
}
}
+/* Return the byte of EC switch states */
+static int cros_ec_sandbox_get_switches(struct udevice *dev)
+{
+ struct ec_state *ec = dev_get_priv(dev);
+
+ return ec->test_flags & CROSECT_LID_OPEN ? EC_SWITCH_LID_OPEN : 0;
+}
+
+void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags)
+{
+ struct ec_state *ec = dev_get_priv(dev);
+
+ ec->test_flags = flags;
+}
+
int cros_ec_probe(struct udevice *dev)
{
struct ec_state *ec = dev_get_priv(dev);
@@ -573,6 +670,7 @@ int cros_ec_probe(struct udevice *dev)
struct dm_cros_ec_ops cros_ec_ops = {
.packet = cros_ec_sandbox_packet,
+ .get_switches = cros_ec_sandbox_get_switches,
};
static const struct udevice_id cros_ec_ids[] = {
diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
index 5a2a154e65..f25b976e54 100644
--- a/drivers/rtc/i2c_rtc_emul.c
+++ b/drivers/rtc/i2c_rtc_emul.c
@@ -57,6 +57,7 @@ long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time,
plat->use_system_time = use_system_time;
if (offset != -1)
plat->offset = offset;
+ os_set_time_offset(plat->offset);
return old_offset;
}
@@ -80,7 +81,7 @@ static void reset_time(struct udevice *dev)
os_localtime(&now);
plat->base_time = rtc_mktime(&now);
- plat->offset = 0;
+ plat->offset = os_get_time_offset();
plat->use_system_time = true;
}
@@ -115,6 +116,7 @@ static int sandbox_i2c_rtc_set(struct udevice *dev, const struct rtc_time *time)
now = plat->base_time;
}
plat->offset = rtc_mktime(time) - now;
+ os_set_time_offset(plat->offset);
return 0;
}
diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
index ce61b72d22..b103a6fdc3 100644
--- a/drivers/tpm/cr50_i2c.c
+++ b/drivers/tpm/cr50_i2c.c
@@ -183,23 +183,31 @@ static int cr50_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer,
return cr50_i2c_wait_tpm_ready(dev);
}
-static inline u8 tpm_access(u8 locality)
+static inline u8 tpm_access(int locality)
{
+ if (locality == -1)
+ locality = 0;
return 0x0 | (locality << 4);
}
-static inline u8 tpm_sts(u8 locality)
+static inline u8 tpm_sts(int locality)
{
+ if (locality == -1)
+ locality = 0;
return 0x1 | (locality << 4);
}
-static inline u8 tpm_data_fifo(u8 locality)
+static inline u8 tpm_data_fifo(int locality)
{
+ if (locality == -1)
+ locality = 0;
return 0x5 | (locality << 4);
}
-static inline u8 tpm_did_vid(u8 locality)
+static inline u8 tpm_did_vid(int locality)
{
+ if (locality == -1)
+ locality = 0;
return 0x6 | (locality << 4);
}
@@ -372,7 +380,6 @@ out_err:
static int cr50_i2c_send(struct udevice *dev, const u8 *buf, size_t len)
{
struct cr50_priv *priv = dev_get_priv(dev);
-
int status;
size_t burstcnt, limit, sent = 0;
u8 tpm_go[4] = { TPM_STS_GO };
@@ -549,9 +556,23 @@ static int cr50_i2c_get_desc(struct udevice *dev, char *buf, int size)
{
struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
struct cr50_priv *priv = dev_get_priv(dev);
+ int len;
+
+ len = snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x), ",
+ chip->chip_addr, priv->vendor >> 16);
+ if (priv->use_irq) {
+ len += snprintf(buf + len, size - len, "irq=%s/%ld",
+ priv->irq.dev->name, priv->irq.id);
+ } else if (dm_gpio_is_valid(&priv->ready_gpio)) {
+ len += snprintf(buf + len, size - len, "gpio=%s/%u",
+ priv->ready_gpio.dev->name,
+ priv->ready_gpio.offset);
+ } else {
+ len += snprintf(buf + len, size - len, "delay=%d",
+ TIMEOUT_NO_IRQ_US);
+ }
- return snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x) irq=%d",
- chip->chip_addr, priv->vendor >> 16, priv->use_irq);
+ return len;
}
static int cr50_i2c_open(struct udevice *dev)
@@ -694,11 +715,12 @@ static int cr50_i2c_probe(struct udevice *dev)
mdelay(10);
}
if (vendor != CR50_DID_VID) {
- log_debug("DID_VID %08x not recognised\n", vendor);
+ log_warning("DID_VID %08x not recognised\n", vendor);
return log_msg_ret("vendor-id", -EXDEV);
}
priv->vendor = vendor;
priv->locality = -1;
+ log_debug("Cr50 ready\n");
return 0;
}
@@ -720,8 +742,8 @@ static const struct udevice_id cr50_i2c_ids[] = {
{ }
};
-U_BOOT_DRIVER(cr50_i2c) = {
- .name = "cr50_i2c",
+U_BOOT_DRIVER(google_cr50) = {
+ .name = "google_cr50",
.id = UCLASS_TPM,
.of_match = cr50_i2c_ids,
.ops = &cr50_i2c_ops,
diff --git a/include/cros_ec.h b/include/cros_ec.h
index f187bd0d4b..eddc23d48f 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -234,11 +234,61 @@ int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image,
struct udevice *board_get_cros_ec_dev(void);
struct dm_cros_ec_ops {
+ /**
+ * check_version() - Check the protocol version being used (optional)
+ *
+ * If provided, this function should check that the EC can be supported
+ * by the driver. If not provided, HELLO messages will be sent to try
+ * to determine the protocol version.
+ *
+ * @dev: Device to check
+ * @return 0 if the protocol is valid, -ve if not supported
+ */
int (*check_version)(struct udevice *dev);
+
+ /**
+ * command() - Old-style command interface
+ *
+ * This sends a command and receives a response (deprecated, use
+ * packet())
+ *
+ * @dev: Device to use
+ * @cmd: Command to send (only supports 0-0xff)
+ * @cmd_version: Version of command to send (often 0)
+ * @dout: Output data (may be NULL If dout_len=0)
+ * @dout_len: Length of output data excluding 4-byte header
+ * @dinp: On input, set to point to input data, often struct
+ * cros_ec_dev->din - typically this is left alone but may be
+ * updated by the driver
+ * @din_len: Maximum length of response
+ * @return number of bytes in response, or -ve on error
+ */
int (*command)(struct udevice *dev, uint8_t cmd, int cmd_version,
const uint8_t *dout, int dout_len,
uint8_t **dinp, int din_len);
+
+ /**
+ * packet() - New-style command interface
+ *
+ * This interface is preferred over command(), since it is typically
+ * easier to implement.
+ *
+ * @dev: Device to use
+ * @out_bytes: Number of bytes to send (from struct cros_ec_dev->dout)
+ * @in_bytes: Maximum number of bytes to expect in response
+ * @return number of bytes in response, or -ve on error
+ */
int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+
+ /**
+ * get_switches() - Get value of EC switches
+ *
+ * This is currently supported on the LPC EC.
+ *
+ * @dev: Device to use
+ * @return current switches value, or -ENOSYS if not supported
+ */
+ int (*get_switches)(struct udevice *dev);
};
#define dm_cros_ec_get_ops(dev) \
@@ -330,6 +380,14 @@ int cros_ec_flash_offset(struct udevice *dev, enum ec_flash_region region,
uint32_t *offset, uint32_t *size);
/**
+ * cros_ec_get_sku_id() - Read the SKU ID
+ *
+ * @dev: CROS-EC device
+ * return SKU ID, or -ve on error
+ */
+int cros_ec_get_sku_id(struct udevice *dev);
+
+/**
* Read/write non-volatile data from/to a CROS-EC device.
*
* @param dev CROS-EC device
@@ -497,4 +555,88 @@ int cros_ec_get_lid_shutdown_mask(struct udevice *dev);
*/
int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable);
+/**
+ * cros_ec_hello() - Send a hello message
+ *
+ * Sends a message with a fixed input value and checks that the expected output
+ * value is received
+ *
+ * @dev: CROS-EC device
+ * @handshakep: If non-NULL, returns received handshake value on error
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_hello(struct udevice *dev, uint *handshakep);
+
+/**
+ * cros_ec_get_features() - Get the set of features provided by the EC
+ *
+ * See enum ec_feature_code for the list of available features
+ *
+ * @dev: CROS-EC device
+ * @featuresp: Returns a bitmask of supported features
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_get_features(struct udevice *dev, u64 *featuresp);
+
+/**
+ * cros_ec_check_feature() - Check if a feature is supported
+ *
+ * @dev: CROS-EC device
+ * @feature: Feature number to check (enum ec_feature_code)
+ * @return true if supported, false if not, -ve on error
+ */
+int cros_ec_check_feature(struct udevice *dev, uint feature);
+
+/**
+ * cros_ec_get_switches() - Get switches value
+ *
+ * @dev: CROS-EC device
+ * @return switches value, or -ENOSYS if not supported, or other -ve value on
+ * other error
+ */
+int cros_ec_get_switches(struct udevice *dev);
+
+/**
+ * cros_ec_vstore_supported() - Check if vstore is supported
+ *
+ * @dev: CROS-EC device
+ * @return false if not supported, true if supported, -ve on error
+ */
+int cros_ec_vstore_supported(struct udevice *dev);
+
+/**
+ * cros_ec_vstore_info() - Get vstore information
+ *
+ * @dev: CROS-EC device
+ * @lockedp: mask of locked slots
+ * @return number of vstore slots supported by the EC,, -ve on error
+ */
+int cros_ec_vstore_info(struct udevice *dev, u32 *lockedp);
+
+/**
+ * cros_ec_vstore_read() - Read data from EC vstore slot
+ *
+ * @dev: CROS-EC device
+ * @slot: vstore slot to read from
+ * @data: buffer to store read data, must be EC_VSTORE_SLOT_SIZE bytes
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_vstore_read(struct udevice *dev, int slot, uint8_t *data);
+
+/**
+ * cros_ec_vstore_write() - Save data into EC vstore slot
+ *
+ * The maximum size of data is EC_VSTORE_SLOT_SIZE. It is the caller's
+ * responsibility to check the number of implemented slots by querying the
+ * vstore info.
+ *
+ * @dev: CROS-EC device
+ * @slot: vstore slot to write into
+ * @data: data to write
+ * @size: size of data in bytes
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_vstore_write(struct udevice *dev, int slot, const uint8_t *data,
+ size_t size);
+
#endif
diff --git a/include/ctype.h b/include/ctype.h
new file mode 120000
index 0000000000..9e43f9c6c6
--- /dev/null
+++ b/include/ctype.h
@@ -0,0 +1 @@
+linux/ctype.h \ No newline at end of file
diff --git a/include/dm/device.h b/include/dm/device.h
index f5b4cd6876..e665558444 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -111,7 +111,7 @@ enum {
* probe method if the device has a device tree node.
*
* All three of plat, priv and uclass_priv can be allocated by the
- * driver, or you can use the auto_alloc_size members of struct driver and
+ * driver, or you can use the auto members of struct driver and
* struct uclass_driver to have driver model do this automatically.
*
* @driver: The driver used by this device
diff --git a/include/dm/read.h b/include/dm/read.h
index c875e11a13..03ba98232a 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -30,8 +30,7 @@ static inline const struct device_node *dev_np(const struct udevice *dev)
}
#endif
-#ifndef CONFIG_DM_DEV_READ_INLINE
-
+#if !defined(CONFIG_DM_DEV_READ_INLINE) || CONFIG_IS_ENABLED(OF_PLATDATA)
/**
* dev_read_u32() - read a 32-bit integer from a device's DT property
*
@@ -1007,7 +1006,7 @@ static inline u64 dev_translate_dma_address(const struct udevice *dev,
static inline int dev_read_alias_highest_id(const char *stem)
{
- if (!CONFIG_IS_ENABLED(OF_LIBFDT))
+ if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !gd->fdt_blob)
return -1;
return fdtdec_get_alias_highest_id(gd->fdt_blob, stem);
}
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 444ba61e59..36f4a02f93 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1101,13 +1101,50 @@ enum ec_feature_code {
EC_FEATURE_DEVICE_EVENT = 31,
/* EC supports the unified wake masks for LPC/eSPI systems */
EC_FEATURE_UNIFIED_WAKE_MASKS = 32,
+ /* EC supports 64-bit host events */
+ EC_FEATURE_HOST_EVENT64 = 33,
+ /* EC runs code in RAM (not in place, a.k.a. XIP) */
+ EC_FEATURE_EXEC_IN_RAM = 34,
+ /* EC supports CEC commands */
+ EC_FEATURE_CEC = 35,
+ /* EC supports tight sensor timestamping. */
+ EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36,
+ /*
+ * EC supports tablet mode detection aligned to Chrome and allows
+ * setting of threshold by host command using
+ * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
+ */
+ EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
+ /*
+ * Early Firmware Selection ver.2. Enabled by CONFIG_VBOOT_EFS2.
+ * Note this is a RO feature. So, a query (EC_CMD_GET_FEATURES) should
+ * be sent to RO to be precise.
+ */
+ EC_FEATURE_EFS2 = 38,
+ /* The MCU is a System Companion Processor (SCP). */
+ EC_FEATURE_SCP = 39,
+ /* The MCU is an Integrated Sensor Hub */
+ EC_FEATURE_ISH = 40,
+ /* New TCPMv2 TYPEC_ prefaced commands supported */
+ EC_FEATURE_TYPEC_CMD = 41,
+ /*
+ * The EC will wait for direction from the AP to enter Type-C alternate
+ * modes or USB4.
+ */
+ EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY = 42,
+ /*
+ * The EC will wait for an acknowledge from the AP after setting the
+ * mux.
+ */
+ EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK = 43,
};
-#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
-#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
-struct __ec_align4 ec_response_get_features {
+#define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32)
+#define EC_FEATURE_MASK_1(event_code) BIT(event_code - 32)
+
+struct ec_response_get_features {
uint32_t flags[2];
-};
+} __ec_align4;
/*****************************************************************************/
/* Get the board's SKU ID from EC */
diff --git a/include/os.h b/include/os.h
index 0913b47b3a..e192e32d59 100644
--- a/include/os.h
+++ b/include/os.h
@@ -424,4 +424,22 @@ int os_setup_signal_handlers(void);
*/
void os_signal_action(int sig, unsigned long pc);
+/**
+ * os_get_time_offset() - get time offset
+ *
+ * Get the time offset from environment variable UBOOT_SB_TIME_OFFSET.
+ *
+ * Return: offset in seconds
+ */
+long os_get_time_offset(void);
+
+/**
+ * os_set_time_offset() - set time offset
+ *
+ * Save the time offset in environment variable UBOOT_SB_TIME_OFFSET.
+ *
+ * @offset: offset in seconds
+ */
+void os_set_time_offset(long offset);
+
#endif
diff --git a/lib/binman.c b/lib/binman.c
index f415df3054..6040ec8924 100644
--- a/lib/binman.c
+++ b/lib/binman.c
@@ -145,6 +145,8 @@ int binman_init(void)
if (ret)
return log_msg_ret("node", -ENOENT);
binman_set_rom_offset(ROM_OFFSET_NONE);
+ log_debug("binman: Selected image node '%s'\n",
+ ofnode_get_name(binman->image));
return 0;
}
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076ed09..e70e50f402 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_BLK) += blk.o
obj-$(CONFIG_BUTTON) += button.o
obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
obj-$(CONFIG_CLK) += clk.o clk_ccf.o
+obj-$(CONFIG_CROS_EC) += cros_ec.o
obj-$(CONFIG_DEVRES) += devres.o
obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
obj-$(CONFIG_DM_ETH) += eth.o
@@ -41,6 +42,7 @@ obj-y += fdtdec.o
obj-$(CONFIG_UT_DM) += nop.o
obj-y += ofnode.o
obj-y += ofread.o
+obj-y += of_extra.o
obj-$(CONFIG_OSD) += osd.o
obj-$(CONFIG_DM_VIDEO) += panel.o
obj-$(CONFIG_DM_PCI) += pci.o
diff --git a/test/dm/cros_ec.c b/test/dm/cros_ec.c
new file mode 100644
index 0000000000..30cb70e088
--- /dev/null
+++ b/test/dm/cros_ec.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <dm.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+static int dm_test_cros_ec_hello(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ uint val;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+
+ ut_assertok(cros_ec_hello(dev, NULL));
+
+ val = 0xdead1357;
+ ut_assertok(cros_ec_hello(dev, &val));
+ ut_asserteq(0xdead1357, val);
+
+ sandbox_cros_ec_set_test_flags(dev, CROSECT_BREAK_HELLO);
+ ut_asserteq(-ENOTSYNC, cros_ec_hello(dev, &val));
+ ut_asserteq(0x12345678, val);
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_hello, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_sku_id(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+ ut_asserteq(1234, cros_ec_get_sku_id(dev));
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec sku", 0));
+ ut_assert_nextline("1234");
+ ut_assert_console_end();
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_sku_id, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_features(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u64 feat;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+ ut_assertok(cros_ec_get_features(dev, &feat));
+ ut_asserteq_64(1U << EC_FEATURE_FLASH | 1U << EC_FEATURE_I2C |
+ 1u << EC_FEATURE_VSTORE |
+ 1ULL << EC_FEATURE_UNIFIED_WAKE_MASKS | 1ULL << EC_FEATURE_ISH,
+ feat);
+
+ ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_I2C));
+ ut_asserteq(false, cros_ec_check_feature(dev, EC_FEATURE_MOTION_SENSE));
+ ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_ISH));
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec features", 0));
+ ut_assert_nextline("flash");
+ ut_assert_nextline("i2c");
+ ut_assert_nextline("vstore");
+ ut_assert_nextline("unified_wake_masks");
+ ut_assert_nextline("ish");
+ ut_assert_console_end();
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_switches(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+ ut_asserteq(0, cros_ec_get_switches(dev));
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec switches", 0));
+ ut_assert_console_end();
+
+ /* Open the lid and check the switch changes */
+ sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
+ ut_asserteq(EC_SWITCH_LID_OPEN, cros_ec_get_switches(dev));
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec switches", 0));
+ ut_assert_nextline("lid open");
+ ut_assert_console_end();
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_switches, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_events(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u32 events;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+ ut_assertok(cros_ec_get_host_events(dev, &events));
+ ut_asserteq(0, events);
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec events", 0));
+ ut_assert_nextline("00000000");
+ ut_assert_console_end();
+
+ /* Open the lid and check the event appears */
+ sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
+ ut_assertok(cros_ec_get_host_events(dev, &events));
+ ut_asserteq(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN), events);
+
+ /* try the command */
+ console_record_reset();
+ ut_assertok(run_command("crosec events", 0));
+ ut_assert_nextline("00000002");
+ ut_assert_nextline("lid_open");
+ ut_assert_console_end();
+
+ /* Clear the event */
+ ut_assertok(cros_ec_clear_host_events(dev,
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)));
+ ut_assertok(cros_ec_get_host_events(dev, &events));
+ ut_asserteq(0, events);
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_events, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_vstore(struct unit_test_state *uts)
+{
+ const int size = EC_VSTORE_SLOT_SIZE;
+ u8 test_data[size], data[size];
+ struct udevice *dev;
+ u32 locked;
+ int i;
+
+ ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+ ut_asserteq(true, cros_ec_vstore_supported(dev));
+
+ ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
+ ut_asserteq(0, locked);
+
+ /* Write some data */
+ for (i = 0; i < size; i++)
+ test_data[i] = ' ' + i;
+ ut_assertok(cros_ec_vstore_write(dev, 2, test_data, size));
+
+ /* Check it is locked */
+ ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
+ ut_asserteq(1 << 2, locked);
+
+ /* Read it back and compare */
+ ut_assertok(cros_ec_vstore_read(dev, 2, data));
+ ut_asserteq_mem(test_data, data, size);
+
+ /* Try another slot to make sure it is empty */
+ ut_assertok(cros_ec_vstore_read(dev, 0, data));
+ for (i = 0; i < size; i++)
+ ut_asserteq(0, data[i]);
+
+ return 0;
+}
+DM_TEST(dm_test_cros_ec_vstore, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/of_extra.c b/test/dm/of_extra.c
new file mode 100644
index 0000000000..b19cd3787d
--- /dev/null
+++ b/test/dm/of_extra.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_extra.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <u-boot/sha256.h>
+
+static int dm_test_ofnode_read_fmap_entry(struct unit_test_state *uts)
+{
+ const char hash_expect[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ };
+ struct fmap_entry entry;
+ ofnode node;
+
+ node = ofnode_path("/cros-ec/flash/wp-ro");
+ ut_assertok(ofnode_read_fmap_entry(node, &entry));
+ ut_asserteq(0xf000, entry.offset);
+ ut_asserteq(0x1000, entry.length);
+ ut_asserteq(0x884, entry.used);
+ ut_asserteq(FMAP_COMPRESS_LZ4, entry.compress_algo);
+ ut_asserteq(0xcf8, entry.unc_length);
+ ut_asserteq(FMAP_HASH_SHA256, entry.hash_algo);
+ ut_asserteq(SHA256_SUM_LEN, entry.hash_size);
+ ut_asserteq_mem(hash_expect, entry.hash, SHA256_SUM_LEN);
+
+ return 0;
+}
+DM_TEST(dm_test_ofnode_read_fmap_entry, 0);
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c
index cfc43a5b03..26c50922c5 100644
--- a/test/dm/of_platdata.c
+++ b/test/dm/of_platdata.c
@@ -210,11 +210,11 @@ DM_TEST(dm_test_of_plat_phandle, UT_TESTF_SCAN_PDATA);
/* Test that device parents are correctly set up */
static int dm_test_of_plat_parent(struct unit_test_state *uts)
{
- struct udevice *rtc, *i2c;
+ struct udevice *dev, *bus;
- 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));
+ ut_assertok(uclass_first_device_err(UCLASS_SIMPLE_BUS, &bus));
+ ut_assertok(device_first_child_err(bus, &dev));
+ ut_asserteq_ptr(bus, dev_get_parent(dev));
return 0;
}
diff --git a/tools/binman/README b/tools/binman/README
index de1eedfc3f..a00c902616 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -1050,10 +1050,9 @@ Some ideas:
- Allow easy building of images by specifying just the board name
- Support building an image for a board (-b) more completely, with a
configurable build directory
-- Support adding FITs to an image
-- Support for ARM Trusted Firmware (ATF)
- Detect invalid properties in nodes
- Sort the fdtmap by offset
+- Output temporary files to a different directory
--
Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 072417f364..1952b2abf4 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -244,7 +244,8 @@ def ExtractEntries(image_fname, output_fname, outdir, entry_paths,
if not os.path.exists(fname):
os.makedirs(fname)
fname = os.path.join(fname, 'root')
- tout.Notice("Write entry '%s' to '%s'" % (entry.GetPath(), fname))
+ tout.Notice("Write entry '%s' size %x to '%s'" %
+ (entry.GetPath(), len(data), fname))
tools.WriteFile(fname, data)
return einfos
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 249074a334..03b49d7163 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -132,7 +132,8 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
(msg, sym.size))
# Look up the symbol in our entry tables.
- value = section.LookupSymbol(name, sym.weak, msg, base.address)
+ value = section.GetImage().LookupImageSymbol(name, sym.weak, msg,
+ base.address)
if value is None:
value = -1
pack_string = pack_string.lower()
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index e3d218a89e..7a128018d9 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -45,10 +45,12 @@ class FakeSection:
def GetPath(self):
return 'section_path'
- def LookupSymbol(self, name, weak, msg, base_addr):
+ def LookupImageSymbol(self, name, weak, msg, base_addr):
"""Fake implementation which returns the same value for all symbols"""
return self.sym_value
+ def GetImage(self):
+ return self
def BuildElfTestFiles(target_dir):
"""Build ELF files used for testing in binman
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 2be0d8e053..d58a730f3d 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -434,8 +434,7 @@ class Entry(object):
missing.append(prop.name)
values.append(value)
if missing:
- self.Raise('Missing required properties/entry args: %s' %
- (', '.join(missing)))
+ self.GetImage().MissingArgs(self, missing)
return values
def GetPath(self):
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index 301ac55e3b..81756c326d 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -66,3 +66,7 @@ class Entry_blob(Entry):
def GetDefaultFilename(self):
return self._filename
+
+ def ProcessContents(self):
+ # The blob may have changed due to WriteSymbols()
+ return self.ProcessContentsUpdate(self.data)
diff --git a/tools/binman/etype/files.py b/tools/binman/etype/files.py
index ce3832e3cd..1feebd0510 100644
--- a/tools/binman/etype/files.py
+++ b/tools/binman/etype/files.py
@@ -22,6 +22,7 @@ class Entry_files(Entry_section):
- files-compress: Compression algorithm to use:
none: No compression
lz4: Use lz4 compression (via 'lz4' command-line utility)
+ - files-align: Align each file to the given alignment
This entry reads a number of files and places each in a separate sub-entry
within this entry. To access these you need to enable device-tree updates
@@ -38,6 +39,7 @@ class Entry_files(Entry_section):
self.Raise("Missing 'pattern' property")
self._files_compress = fdt_util.GetString(self._node, 'files-compress',
'none')
+ self._files_align = fdt_util.GetInt(self._node, 'files-align');
self._require_matches = fdt_util.GetBool(self._node,
'require-matches')
@@ -55,6 +57,8 @@ class Entry_files(Entry_section):
state.AddString(subnode, 'type', 'blob')
state.AddString(subnode, 'filename', fname)
state.AddString(subnode, 'compress', self._files_compress)
+ if self._files_align:
+ state.AddInt(subnode, 'align', self._files_align)
# Read entries again, now that we have some
self._ReadEntries()
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 3dd5f58c4c..1ceadef13f 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -385,7 +385,7 @@ class Entry_section(Entry):
return entry.GetData()
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
- def LookupSymbol(self, sym_name, optional, msg, base_addr):
+ def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
"""Look up a symbol in an ELF file
Looks up a symbol in an ELF file. Only entry types which come from an
@@ -428,18 +428,20 @@ class Entry_section(Entry):
(msg, sym_name))
entry_name, prop_name = m.groups()
entry_name = entry_name.replace('_', '-')
- entry = self._entries.get(entry_name)
+ if not entries:
+ entries = self._entries
+ entry = entries.get(entry_name)
if not entry:
if entry_name.endswith('-any'):
root = entry_name[:-4]
- for name in self._entries:
+ for name in entries:
if name.startswith(root):
rest = name[len(root):]
if rest in ['', '-img', '-nodtb']:
- entry = self._entries[name]
+ entry = entries[name]
if not entry:
err = ("%s: Entry '%s' not found in list (%s)" %
- (msg, entry_name, ','.join(self._entries.keys())))
+ (msg, entry_name, ','.join(entries.keys())))
if optional:
print('Warning: %s' % err, file=sys.stderr)
return None
@@ -603,10 +605,12 @@ class Entry_section(Entry):
def ReadData(self, decomp=True):
tout.Info("ReadData path='%s'" % self.GetPath())
parent_data = self.section.ReadData(True)
- tout.Info('%s: Reading data from offset %#x-%#x, size %#x' %
- (self.GetPath(), self.offset, self.offset + self.size,
- self.size))
- data = parent_data[self.offset:self.offset + self.size]
+ offset = self.offset - self.section._skip_at_start
+ data = parent_data[offset:offset + self.size]
+ tout.Info(
+ '%s: Reading data from offset %#x-%#x (real %#x), size %#x, got %#x' %
+ (self.GetPath(), self.offset, self.offset + self.size, offset,
+ self.size, len(data)))
return data
def ReadChildData(self, child, decomp=True):
@@ -648,3 +652,47 @@ class Entry_section(Entry):
"""
for entry in self._entries.values():
entry.CheckMissing(missing_list)
+
+ def _CollectEntries(self, entries, entries_by_name, add_entry):
+ """Collect all the entries in an section
+
+ This builds up a dict of entries in this section and all subsections.
+ Entries are indexed by path and by name.
+
+ Since all paths are unique, entries will not have any conflicts. However
+ entries_by_name make have conflicts if two entries have the same name
+ (e.g. with different parent sections). In this case, an entry at a
+ higher level in the hierarchy will win over a lower-level entry.
+
+ Args:
+ entries: dict to put entries:
+ key: entry path
+ value: Entry object
+ entries_by_name: dict to put entries
+ key: entry name
+ value: Entry object
+ add_entry: Entry to add
+ """
+ entries[add_entry.GetPath()] = add_entry
+ to_add = add_entry.GetEntries()
+ if to_add:
+ for entry in to_add.values():
+ entries[entry.GetPath()] = entry
+ for entry in to_add.values():
+ self._CollectEntries(entries, entries_by_name, entry)
+ entries_by_name[add_entry.name] = add_entry
+
+ def MissingArgs(self, entry, missing):
+ """Report a missing argument, if enabled
+
+ For entries which require arguments, this reports an error if some are
+ missing. If missing entries are being ignored (e.g. because we read the
+ entry from an image rather than creating it), this function does
+ nothing.
+
+ Args:
+ missing: List of missing properties / entry args, each a string
+ """
+ if not self._ignore_missing:
+ entry.Raise('Missing required properties/entry args: %s' %
+ (', '.join(missing)))
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index 596b2bed97..df15cd24ce 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -9,7 +9,6 @@
from binman import elf
from binman.entry import Entry
-from patman import command
from binman.etype.blob import Entry_blob
from patman import tools
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 6f4529396d..c154cfde57 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -2,7 +2,7 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
-# Entry-type module for 'u-boot-nodtb.bin'
+# Entry-type module for 'u-boot-spl-nodtb.bin'
#
from binman.entry import Entry
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index f734fbaec4..eba5351dd5 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -49,7 +49,7 @@ class Entry_vblock(Entry):
EntryArg('kernelkey', str),
EntryArg('preamble-flags', int)])
- def ObtainContents(self):
+ def GetVblock(self):
# Join up the data files to be signed
input_data = b''
for entry_phandle in self.content:
@@ -76,5 +76,16 @@ class Entry_vblock(Entry):
]
#out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
stdout = tools.Run('futility', *args)
- self.SetContents(tools.ReadFile(output_fname))
+ return tools.ReadFile(output_fname)
+
+ def ObtainContents(self):
+ data = self.GetVblock()
+ if data is False:
+ return False
+ self.SetContents(data)
return True
+
+ def ProcessContents(self):
+ # The blob may have changed due to WriteSymbols()
+ data = self.GetVblock()
+ return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
index b03fc28fbb..8277619768 100644
--- a/tools/binman/fmap_util.py
+++ b/tools/binman/fmap_util.py
@@ -53,8 +53,8 @@ FmapArea = collections.namedtuple('FmapArea', FMAP_AREA_NAMES)
def NameToFmap(name):
- if type(name) == bytes and sys.version_info[0] >= 3:
- name = name.decode('utf-8') # pragma: no cover (for Python 2)
+ if type(name) == bytes:
+ name = name.decode('utf-8')
return name.replace('\0', '').replace('-', '_').upper()
def ConvertName(field_names, fields):
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index e753a342c8..814e91d42e 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1638,15 +1638,37 @@ class TestFunctional(unittest.TestCase):
str(e.exception))
def _HandleVblockCommand(self, pipe_list):
- """Fake calls to the futility utility"""
+ """Fake calls to the futility utility
+
+ The expected pipe is:
+
+ [('futility', 'vbutil_firmware', '--vblock',
+ 'vblock.vblock', '--keyblock', 'devkeys/firmware.keyblock',
+ '--signprivate', 'devkeys/firmware_data_key.vbprivk',
+ '--version', '1', '--fv', 'input.vblock', '--kernelkey',
+ 'devkeys/kernel_subkey.vbpubk', '--flags', '1')]
+
+ This writes to the output file (here, 'vblock.vblock'). If
+ self._hash_data is False, it writes VBLOCK_DATA, else it writes a hash
+ of the input data (here, 'input.vblock').
+ """
if pipe_list[0][0] == 'futility':
fname = pipe_list[0][3]
with open(fname, 'wb') as fd:
- fd.write(VBLOCK_DATA)
+ if self._hash_data:
+ infile = pipe_list[0][11]
+ m = hashlib.sha256()
+ data = tools.ReadFile(infile)
+ m.update(data)
+ fd.write(m.digest())
+ else:
+ fd.write(VBLOCK_DATA)
+
return command.CommandResult()
def testVblock(self):
"""Test for the Chromium OS Verified Boot Block"""
+ self._hash_data = False
command.test_result = self._HandleVblockCommand
entry_args = {
'keydir': 'devkeys',
@@ -1677,6 +1699,29 @@ class TestFunctional(unittest.TestCase):
self.assertIn("Node '/binman/vblock': Cannot find entry for node "
"'other'", str(e.exception))
+ def testVblockContent(self):
+ """Test that the vblock signs the right data"""
+ self._hash_data = True
+ command.test_result = self._HandleVblockCommand
+ entry_args = {
+ 'keydir': 'devkeys',
+ }
+ data = self._DoReadFileDtb(
+ '189_vblock_content.dts', use_real_dtb=True, update_dtb=True,
+ entry_args=entry_args)[0]
+ hashlen = 32 # SHA256 hash is 32 bytes
+ self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+ hashval = data[-hashlen:]
+ dtb = data[len(U_BOOT_DATA):-hashlen]
+
+ expected_data = U_BOOT_DATA + dtb
+
+ # The hashval should be a hash of the dtb
+ m = hashlib.sha256()
+ m.update(expected_data)
+ expected_hashval = m.digest()
+ self.assertEqual(expected_hashval, hashval)
+
def testTpl(self):
"""Test that an image with TPL and its device tree can be created"""
# ELF file with a '__bss_size' symbol
@@ -4139,6 +4184,67 @@ class TestFunctional(unittest.TestCase):
}
self.assertEqual(expected, props)
+ def testSymbolsSubsection(self):
+ """Test binman can assign symbols from a subsection"""
+ elf_fname = self.ElfTestFile('u_boot_binman_syms')
+ syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+ addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
+ self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
+
+ self._SetupSplElf('u_boot_binman_syms')
+ data = self._DoReadFile('187_symbols_sub.dts')
+ sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
+ expected = (sym_values + U_BOOT_SPL_DATA[20:] +
+ tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
+ U_BOOT_SPL_DATA[20:])
+ self.assertEqual(expected, data)
+
+ def testReadImageEntryArg(self):
+ """Test reading an image that would need an entry arg to generate"""
+ entry_args = {
+ 'cros-ec-rw-path': 'ecrw.bin',
+ }
+ data = self.data = self._DoReadFileDtb(
+ '188_image_entryarg.dts',use_real_dtb=True, update_dtb=True,
+ entry_args=entry_args)
+
+ image_fname = tools.GetOutputFilename('image.bin')
+ orig_image = control.images['image']
+
+ # This should not generate an error about the missing 'cros-ec-rw-path'
+ # since we are reading the image from a file. Compare with
+ # testEntryArgsRequired()
+ image = Image.FromFile(image_fname)
+ self.assertEqual(orig_image.GetEntries().keys(),
+ image.GetEntries().keys())
+
+ def testFilesAlign(self):
+ """Test alignment with files"""
+ data = self._DoReadFile('190_files_align.dts')
+
+ # The first string is 15 bytes so will align to 16
+ expect = FILES_DATA[:15] + b'\0' + FILES_DATA[15:]
+ self.assertEqual(expect, data)
+
+ def testReadImageSkip(self):
+ """Test reading an image and accessing its FDT map"""
+ data = self.data = self._DoReadFileRealDtb('191_read_image_skip.dts')
+ image_fname = tools.GetOutputFilename('image.bin')
+ orig_image = control.images['image']
+ image = Image.FromFile(image_fname)
+ self.assertEqual(orig_image.GetEntries().keys(),
+ image.GetEntries().keys())
+
+ orig_entry = orig_image.GetEntries()['fdtmap']
+ entry = image.GetEntries()['fdtmap']
+ self.assertEqual(orig_entry.offset, entry.offset)
+ self.assertEqual(orig_entry.size, entry.size)
+ self.assertEqual(16, entry.image_pos)
+
+ u_boot = image.GetEntries()['section'].GetEntries()['u-boot']
+
+ self.assertEquals(U_BOOT_DATA, u_boot.ReadData())
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index d65ab887b8..e949435241 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -43,8 +43,13 @@ class Image(section.Entry_section):
test: True if this is being called from a test of Images. This this case
there is no device tree defining the structure of the section, so
we create a section manually.
+ ignore_missing: Ignore any missing entry arguments (i.e. don't raise an
+ exception). This should be used if the Image is being loaded from
+ a file rather than generated. In that case we obviously don't need
+ the entry arguments since the contents already exists.
"""
- def __init__(self, name, node, copy_to_orig=True, test=False):
+ def __init__(self, name, node, copy_to_orig=True, test=False,
+ ignore_missing=False):
super().__init__(None, 'section', node, test=test)
self.copy_to_orig = copy_to_orig
self.name = 'main-section'
@@ -53,6 +58,7 @@ class Image(section.Entry_section):
self.fdtmap_dtb = None
self.fdtmap_data = None
self.allow_repack = False
+ self._ignore_missing = ignore_missing
if not test:
self.ReadNode()
@@ -100,7 +106,7 @@ class Image(section.Entry_section):
# Return an Image with the associated nodes
root = dtb.GetRoot()
- image = Image('image', root, copy_to_orig=False)
+ image = Image('image', root, copy_to_orig=False, ignore_missing=True)
image.image_node = fdt_util.GetString(root, 'image-node', 'image')
image.fdtmap_dtb = dtb
@@ -130,12 +136,7 @@ class Image(section.Entry_section):
Returns:
True if the new data size is OK, False if expansion is needed
"""
- sizes_ok = True
- for entry in self._entries.values():
- if not entry.ProcessContents():
- sizes_ok = False
- tout.Debug("Entry '%s' size change" % self._node.path)
- return sizes_ok
+ return super().ProcessContents()
def WriteSymbols(self):
"""Write symbol values into binary files for access at run time"""
@@ -324,3 +325,48 @@ class Image(section.Entry_section):
_DoLine(lines, _EntryToStrings(entry))
selected_entries.append(entry)
return selected_entries, lines, widths
+
+ def LookupImageSymbol(self, sym_name, optional, msg, base_addr):
+ """Look up a symbol in an ELF file
+
+ Looks up a symbol in an ELF file. Only entry types which come from an
+ ELF image can be used by this function.
+
+ This searches through this image including all of its subsections.
+
+ At present the only entry properties supported are:
+ offset
+ image_pos - 'base_addr' is added if this is not an end-at-4gb image
+ size
+
+ Args:
+ sym_name: Symbol name in the ELF file to look up in the format
+ _binman_<entry>_prop_<property> where <entry> is the name of
+ the entry and <property> is the property to find (e.g.
+ _binman_u_boot_prop_offset). As a special case, you can append
+ _any to <entry> to have it search for any matching entry. E.g.
+ _binman_u_boot_any_prop_offset will match entries called u-boot,
+ u-boot-img and u-boot-nodtb)
+ optional: True if the symbol is optional. If False this function
+ will raise if the symbol is not found
+ msg: Message to display if an error occurs
+ base_addr: Base address of image. This is added to the returned
+ image_pos in most cases so that the returned position indicates
+ where the targeted entry/binary has actually been loaded. But
+ if end-at-4gb is used, this is not done, since the binary is
+ already assumed to be linked to the ROM position and using
+ execute-in-place (XIP).
+
+ Returns:
+ Value that should be assigned to that symbol, or None if it was
+ optional and not found
+
+ Raises:
+ ValueError if the symbol is invalid or not found, or references a
+ property which is not supported
+ """
+ entries = OrderedDict()
+ entries_by_name = {}
+ self._CollectEntries(entries, entries_by_name, self)
+ return self.LookupSymbol(sym_name, optional, msg, base_addr,
+ entries_by_name)
diff --git a/tools/binman/state.py b/tools/binman/state.py
index 36bc513535..bb3e36ea7a 100644
--- a/tools/binman/state.py
+++ b/tools/binman/state.py
@@ -314,6 +314,16 @@ def AddString(node, prop, value):
for n in GetUpdateNodes(node):
n.AddString(prop, value)
+def AddInt(node, prop, value):
+ """Add a new string property to affected device trees
+
+ Args:
+ prop_name: Name of property
+ val: Integer value of property
+ """
+ for n in GetUpdateNodes(node):
+ n.AddInt(prop, value)
+
def SetInt(node, prop, value, for_repack=False):
"""Update an integer property in affected device trees with an integer value
diff --git a/tools/binman/test/084_files.dts b/tools/binman/test/084_files.dts
index 83ddb78f8e..8f09afd24e 100644
--- a/tools/binman/test/084_files.dts
+++ b/tools/binman/test/084_files.dts
@@ -5,7 +5,7 @@
binman {
files {
pattern = "files/*.dat";
- compress = "none";
+ files-compress = "none";
};
};
};
diff --git a/tools/binman/test/187_symbols_sub.dts b/tools/binman/test/187_symbols_sub.dts
new file mode 100644
index 0000000000..54511a7371
--- /dev/null
+++ b/tools/binman/test/187_symbols_sub.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ };
+
+ u-boot {
+ offset = <24>;
+ };
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl";
+ };
+ };
+};
diff --git a/tools/binman/test/188_image_entryarg.dts b/tools/binman/test/188_image_entryarg.dts
new file mode 100644
index 0000000000..29d8149162
--- /dev/null
+++ b/tools/binman/test/188_image_entryarg.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <0xc00>;
+ u-boot {
+ };
+ cros-ec-rw {
+ };
+ fdtmap {
+ };
+ image-header {
+ location = "end";
+ };
+ };
+};
diff --git a/tools/binman/test/189_vblock_content.dts b/tools/binman/test/189_vblock_content.dts
new file mode 100644
index 0000000000..dcc74449c1
--- /dev/null
+++ b/tools/binman/test/189_vblock_content.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u_boot: u-boot {
+ };
+
+ dtb: u-boot-dtb {
+ };
+
+ /*
+ * Put the vblock after the dtb so that the dtb is updated
+ * before the vblock reads its data. At present binman does not
+ * understand dependencies between entries, but simply
+ * iterates again when it thinks something needs to be
+ * recalculated.
+ */
+ vblock {
+ content = <&u_boot &dtb>;
+ keyblock = "firmware.keyblock";
+ signprivate = "firmware_data_key.vbprivk";
+ version = <1>;
+ kernelkey = "kernel_subkey.vbpubk";
+ preamble-flags = <1>;
+ };
+ };
+};
diff --git a/tools/binman/test/190_files_align.dts b/tools/binman/test/190_files_align.dts
new file mode 100644
index 0000000000..213ba966d3
--- /dev/null
+++ b/tools/binman/test/190_files_align.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ files {
+ pattern = "files/*.dat";
+ files-compress = "none";
+ files-align = <4>;
+ };
+ };
+};
diff --git a/tools/binman/test/191_read_image_skip.dts b/tools/binman/test/191_read_image_skip.dts
new file mode 100644
index 0000000000..31df518fae
--- /dev/null
+++ b/tools/binman/test/191_read_image_skip.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ end-at-4gb;
+ size = <0x400>;
+ section {
+ size = <0x10>;
+ u-boot {
+ };
+ };
+ fdtmap {
+ };
+ image-header {
+ location = "end";
+ };
+ };
+};
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 4a78c73725..25ce5136eb 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -460,10 +460,21 @@ class Node:
prop_name: Name of property to add
val: String value of property
"""
- if sys.version_info[0] >= 3: # pragma: no cover
- val = bytes(val, 'utf-8')
+ val = bytes(val, 'utf-8')
self.AddData(prop_name, val + b'\0')
+ def AddInt(self, prop_name, val):
+ """Add a new integer property to a node
+
+ The device tree is marked dirty so that the value will be written to
+ the blob on the next sync.
+
+ Args:
+ prop_name: Name of property to add
+ val: Integer value of property
+ """
+ self.AddData(prop_name, struct.pack('>I', val))
+
def AddSubnode(self, name):
"""Add a new subnode to the node
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index dc6943f733..e8fbbd5d10 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -397,6 +397,12 @@ class TestProp(unittest.TestCase):
data = self.fdt.getprop(self.node.Offset(), 'one')
self.assertEqual(1, fdt32_to_cpu(data))
+ val = 1234
+ self.node.AddInt('integer', val)
+ self.dtb.Sync(auto_resize=True)
+ data = self.fdt.getprop(self.node.Offset(), 'integer')
+ self.assertEqual(val, fdt32_to_cpu(data))
+
val = '123' + chr(0) + '456'
self.node.AddString('string', val)
self.dtb.Sync(auto_resize=True)
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index d8e01a3e60..10997e4386 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -476,7 +476,8 @@ def Compress(indata, algo, with_header=True):
fname = GetOutputFilename('%s.comp.tmp' % algo)
WriteFile(fname, indata)
if algo == 'lz4':
- data = Run('lz4', '--no-frame-crc', '-c', fname, binary=True)
+ data = Run('lz4', '--no-frame-crc', '-B4', '-5', '-c', fname,
+ binary=True)
# cbfstool uses a very old version of lzma
elif algo == 'lzma':
outfname = GetOutputFilename('%s.comp.otmp' % algo)