aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS10
-rw-r--r--arch/Kconfig3
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/mach-imx/imx8/cpu.c4
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c4
-rw-r--r--arch/arm/mach-imx/imx8ulp/soc.c4
-rw-r--r--arch/arm/mach-omap2/am33xx/board.c4
-rw-r--r--arch/arm/mach-omap2/hwinit-common.c5
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/mach-pic32/cpu.c4
-rw-r--r--arch/nios2/cpu/cpu.c4
-rw-r--r--arch/riscv/cpu/cpu.c5
-rw-r--r--arch/riscv/include/asm/system.h5
-rw-r--r--arch/riscv/lib/spl.c3
-rw-r--r--arch/sandbox/cpu/start.c8
-rw-r--r--arch/x86/cpu/baytrail/cpu.c4
-rw-r--r--arch/x86/cpu/broadwell/cpu.c4
-rw-r--r--arch/x86/cpu/ivybridge/cpu.c4
-rw-r--r--arch/x86/cpu/quark/quark.c4
-rw-r--r--arch/x86/include/asm/fsp2/fsp_api.h8
-rw-r--r--arch/x86/lib/fsp2/fsp_init.c4
-rw-r--r--arch/x86/lib/spl.c5
-rw-r--r--arch/x86/lib/tpl.c10
-rw-r--r--board/google/chromebook_coral/coral.c7
-rw-r--r--board/keymile/kmcent2/kmcent2.c4
-rw-r--r--board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c5
-rw-r--r--cmd/Kconfig8
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/event.c27
-rw-r--r--common/Kconfig37
-rw-r--r--common/Makefile2
-rw-r--r--common/board_f.c13
-rw-r--r--common/board_r.c1
-rw-r--r--common/event.c196
-rw-r--r--common/log.c1
-rw-r--r--configs/chromebook_coral_defconfig1
-rw-r--r--configs/kmcent2_defconfig2
-rw-r--r--configs/pg_wcom_expu1_defconfig1
-rw-r--r--configs/pg_wcom_expu1_update_defconfig1
-rw-r--r--configs/pg_wcom_seli8_defconfig1
-rw-r--r--configs/pg_wcom_seli8_update_defconfig1
-rw-r--r--configs/sandbox64_defconfig1
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--configs/sandbox_flattree_defconfig1
-rw-r--r--configs/sandbox_spl_defconfig1
-rw-r--r--configs/tools-only_defconfig1
-rw-r--r--doc/develop/event.rst66
-rw-r--r--doc/develop/index.rst1
-rw-r--r--doc/usage/event.rst49
-rw-r--r--doc/usage/index.rst1
-rw-r--r--drivers/core/Kconfig10
-rw-r--r--drivers/core/device-remove.c8
-rw-r--r--drivers/core/device.c9
-rw-r--r--drivers/core/root.c5
-rw-r--r--include/asm-generic/global_data.h13
-rw-r--r--include/configs/km/pg-wcom-ls102xa.h2
-rw-r--r--include/dm/device-internal.h10
-rw-r--r--include/event.h210
-rw-r--r--include/event_internal.h35
-rw-r--r--include/init.h12
-rw-r--r--include/log.h2
-rwxr-xr-xscripts/event_dump.py115
-rw-r--r--test/common/Makefile1
-rw-r--r--test/common/event.c85
-rw-r--r--test/py/tests/test_event_dump.py20
-rw-r--r--test/test-main.c4
-rw-r--r--tools/binman/elf.py58
67 files changed, 1068 insertions, 73 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index fb171e0..7012cc2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -809,6 +809,16 @@ S: Maintained
F: doc/usage/environment.rst
F: scripts/env2string.awk
+EVENTS
+M: Simon Glass <sjg@chromium.org>
+S: Maintained
+F: cmd/event.c
+F: common/event.c
+F: include/event.h
+F: scripts/event_dump.py
+F: test/common/event.c
+F: test/py/tests/test_event_dump.py
+
FASTBOOT
S: Orphaned
F: cmd/fastboot.c
diff --git a/arch/Kconfig b/arch/Kconfig
index e619144..1b35fda 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -94,6 +94,7 @@ config NIOS2
bool "Nios II architecture"
select CPU
select DM
+ imply DM_EVENT
select OF_CONTROL
select SUPPORT_OF_CONTROL
imply CMD_DM
@@ -113,6 +114,7 @@ config RISCV
select DM
imply DM_SERIAL
imply DM_ETH
+ imply DM_EVENT
imply DM_MMC
imply DM_SPI
imply DM_SPI_FLASH
@@ -238,6 +240,7 @@ config X86
imply CMD_SF_TEST
imply CMD_ZBOOT
imply DM_ETH
+ imply DM_EVENT
imply DM_GPIO
imply DM_KEYBOARD
imply DM_MMC
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8c7f317..a6f2e7a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -774,6 +774,7 @@ config ARCH_OMAP2PLUS
select SUPPORT_SPL
imply TI_SYSC if DM && OF_CONTROL
imply FIT
+ imply DM_EVENT
config ARCH_MESON
bool "Amlogic Meson"
@@ -818,6 +819,7 @@ config ARCH_IMX8
select MACH_IMX
select OF_CONTROL
select ENABLE_ARM_SOC_BOOT0_HOOK
+ imply DM_EVENT
config ARCH_IMX8M
bool "NXP i.MX8M platform"
@@ -831,6 +833,7 @@ config ARCH_IMX8M
select DM
select SUPPORT_SPL
imply CMD_DM
+ imply DM_EVENT
config ARCH_IMX8ULP
bool "NXP i.MX8ULP platform"
@@ -841,6 +844,7 @@ config ARCH_IMX8ULP
select SUPPORT_SPL
select GPIO_EXTRA_HEADER
imply CMD_DM
+ imply DM_EVENT
config ARCH_IMXRT
bool "NXP i.MXRT platform"
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index ee5cc47..359f8c7 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -8,6 +8,7 @@
#include <cpu.h>
#include <cpu_func.h>
#include <dm.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <asm/cache.h>
@@ -66,7 +67,7 @@ int arch_cpu_init(void)
return 0;
}
-int arch_cpu_init_dm(void)
+static int imx8_init_mu(void *ctx, struct event *event)
{
struct udevice *devp;
int node, ret;
@@ -88,6 +89,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, imx8_init_mu);
int print_bootinfo(void)
{
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 1a5a391..838f0a3 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <asm/arch/imx-regs.h>
@@ -494,7 +495,7 @@ static void imx_set_wdog_powerdown(bool enable)
writew(enable, &wdog3->wmcr);
}
-int arch_cpu_init_dm(void)
+static int imx8m_check_clock(void *ctx, struct event *event)
{
struct udevice *dev;
int ret;
@@ -511,6 +512,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock);
int arch_cpu_init(void)
{
diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c
index 934b0ef..e6d417e 100644
--- a/arch/arm/mach-imx/imx8ulp/soc.c
+++ b/arch/arm/mach-imx/imx8ulp/soc.c
@@ -11,6 +11,7 @@
#include <asm/mach-imx/boot_mode.h>
#include <asm/global_data.h>
#include <efi_loader.h>
+#include <event.h>
#include <spl.h>
#include <asm/arch/rdc.h>
#include <asm/arch/s400_api.h>
@@ -569,7 +570,7 @@ int arch_cpu_init(void)
return 0;
}
-int arch_cpu_init_dm(void)
+static int imx8ulp_check_mu(void *ctx, struct event *event)
{
struct udevice *devp;
int node, ret;
@@ -584,6 +585,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, imx8ulp_check_mu);
#if defined(CONFIG_SPL_BUILD)
__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
index c446676..bcc907c 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -11,6 +11,7 @@
#include <dm.h>
#include <debug_uart.h>
#include <errno.h>
+#include <event.h>
#include <init.h>
#include <net.h>
#include <ns16550.h>
@@ -596,7 +597,7 @@ void board_init_f(ulong dummy)
#endif
-int arch_cpu_init_dm(void)
+static int am33xx_dm_post_init(void *ctx, struct event *event)
{
hw_data_init();
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
@@ -604,3 +605,4 @@ int arch_cpu_init_dm(void)
#endif
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, am33xx_dm_post_init);
diff --git a/arch/arm/mach-omap2/hwinit-common.c b/arch/arm/mach-omap2/hwinit-common.c
index 3da50f9..c4a8eab 100644
--- a/arch/arm/mach-omap2/hwinit-common.c
+++ b/arch/arm/mach-omap2/hwinit-common.c
@@ -12,6 +12,7 @@
*/
#include <common.h>
#include <debug_uart.h>
+#include <event.h>
#include <fdtdec.h>
#include <init.h>
#include <spl.h>
@@ -239,11 +240,13 @@ void board_init_f(ulong dummy)
}
#endif
-int arch_cpu_init_dm(void)
+static int omap2_system_init(void *ctx, struct event *event)
{
early_system_init();
+
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, omap2_system_init);
/*
* Routine: wait_for_command_complete
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 28234aa..06cae68 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -130,6 +130,7 @@ config MACH_PIC32
config TARGET_BOSTON
bool "Support Boston"
select DM
+ imply DM_EVENT
select DM_SERIAL
select MIPS_CM
select SYS_CACHE_SHIFT_6
diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
index eac2fe5..de449e3 100644
--- a/arch/mips/mach-pic32/cpu.c
+++ b/arch/mips/mach-pic32/cpu.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <event.h>
#include <init.h>
#include <malloc.h>
#include <asm/global_data.h>
@@ -95,12 +96,13 @@ static void prefetch_init(void)
}
/* arch specific CPU init after DM */
-int arch_cpu_init_dm(void)
+static int pic32_flash_prefetch(void *ctx, struct event *event)
{
/* flash prefetch */
prefetch_init();
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, pic32_flash_prefetch);
/* Un-gate DDR2 modules (gated by default) */
static void ddr2_pmd_ungate(void)
diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c
index b55c8fb..4dd9c10 100644
--- a/arch/nios2/cpu/cpu.c
+++ b/arch/nios2/cpu/cpu.c
@@ -10,6 +10,7 @@
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
+#include <event.h>
#include <init.h>
#include <irq_func.h>
#include <asm/cache.h>
@@ -63,7 +64,7 @@ static void copy_exception_trampoline(void)
}
#endif
-int arch_cpu_init_dm(void)
+static int nios_cpu_setup(void *ctx, struct event *event)
{
struct udevice *dev;
int ret;
@@ -79,6 +80,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, nios_cpu_setup);
static int altera_nios2_get_desc(const struct udevice *dev, char *buf,
int size)
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index 8d90c5e..3ffcbbd 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -7,9 +7,11 @@
#include <cpu.h>
#include <dm.h>
#include <dm/lists.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <asm/encoding.h>
+#include <asm/system.h>
#include <dm/uclass-internal.h>
#include <linux/bitops.h>
@@ -81,7 +83,7 @@ static void dummy_pending_ipi_clear(ulong hart, ulong arg0, ulong arg1)
}
#endif
-int arch_cpu_init_dm(void)
+int riscv_cpu_setup(void *ctx, struct event *event)
{
int ret;
@@ -133,6 +135,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, riscv_cpu_setup);
int arch_early_init_r(void)
{
diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h
index a340475..9d8e43e 100644
--- a/arch/riscv/include/asm/system.h
+++ b/arch/riscv/include/asm/system.h
@@ -7,6 +7,8 @@
#ifndef __ASM_RISCV_SYSTEM_H
#define __ASM_RISCV_SYSTEM_H
+struct event;
+
/*
* Interrupt configuring macros.
*
@@ -14,4 +16,7 @@
*
*/
+/* Hook to set up the CPU (called from SPL too) */
+int riscv_cpu_setup(void *ctx, struct event *event);
+
#endif /* __ASM_RISCV_SYSTEM_H */
diff --git a/arch/riscv/lib/spl.c b/arch/riscv/lib/spl.c
index 8baee07..f4d3b67 100644
--- a/arch/riscv/lib/spl.c
+++ b/arch/riscv/lib/spl.c
@@ -11,6 +11,7 @@
#include <spl.h>
#include <asm/global_data.h>
#include <asm/smp.h>
+#include <asm/system.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -27,7 +28,7 @@ __weak void board_init_f(ulong dummy)
if (ret)
panic("spl_early_init() failed: %d\n", ret);
- arch_cpu_init_dm();
+ riscv_cpu_setup(NULL, NULL);
preloader_console_init();
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 13b0731..0f5a873 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -4,14 +4,14 @@
*/
#include <common.h>
+#include <cli.h>
#include <command.h>
-#include <dm/root.h>
#include <efi_loader.h>
#include <errno.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <os.h>
-#include <cli.h>
#include <sort.h>
#include <asm/getopt.h>
#include <asm/global_data.h>
@@ -19,6 +19,7 @@
#include <asm/malloc.h>
#include <asm/sections.h>
#include <asm/state.h>
+#include <dm/root.h>
#include <linux/ctype.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -119,10 +120,11 @@ int sandbox_early_getopt_check(void)
os_exit(0);
}
-int misc_init_f(void)
+static int sandbox_misc_init_f(void *ctx, struct event *event)
{
return sandbox_early_getopt_check();
}
+EVENT_SPY(EVT_MISC_INIT_F, sandbox_misc_init_f);
static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg)
{
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 309a50a..68bf40b 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <cpu.h>
#include <dm.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <pci.h>
@@ -44,7 +45,7 @@ static void hsuart_clock_set(void *base)
* Configure the internal clock of both SIO HS-UARTs, if they are enabled
* via FSP
*/
-int arch_cpu_init_dm(void)
+static int baytrail_uart_init(void *ctx, struct event *event)
{
struct udevice *dev;
void *base;
@@ -63,6 +64,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, baytrail_uart_init);
static void set_max_freq(void)
{
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 3832a97..2adcf4b 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
#include <cpu.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <asm/cpu.h>
@@ -24,7 +25,7 @@
#include <asm/arch/pch.h>
#include <asm/arch/rcb.h>
-int arch_cpu_init_dm(void)
+static int broadwell_init_cpu(void *ctx, struct event *event)
{
struct udevice *dev;
int ret;
@@ -41,6 +42,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, broadwell_init_cpu);
void set_max_freq(void)
{
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index a02f4f9..cffc5d5 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -14,6 +14,7 @@
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
+#include <event.h>
#include <fdtdec.h>
#include <init.h>
#include <log.h>
@@ -53,7 +54,7 @@ int arch_cpu_init(void)
return x86_cpu_init_f();
}
-int arch_cpu_init_dm(void)
+static int ivybridge_cpu_init(void *ctx, struct event *ev)
{
struct pci_controller *hose;
struct udevice *bus, *dev;
@@ -85,6 +86,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, ivybridge_cpu_init);
#define PCH_EHCI0_TEMP_BAR0 0xe8000000
#define PCH_EHCI1_TEMP_BAR0 0xe8000400
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
index 30b4711..e016fae 100644
--- a/arch/x86/cpu/quark/quark.c
+++ b/arch/x86/cpu/quark/quark.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <event.h>
#include <init.h>
#include <mmc.h>
#include <asm/cache.h>
@@ -247,7 +248,7 @@ int arch_cpu_init(void)
return 0;
}
-int arch_cpu_init_dm(void)
+static int quark_init_pcie(void *ctx, struct event *event)
{
/*
* Initialize PCIe controller
@@ -262,6 +263,7 @@ int arch_cpu_init_dm(void)
return 0;
}
+EVENT_SPY(EVT_DM_POST_INIT, quark_init_pcie);
int checkcpu(void)
{
diff --git a/arch/x86/include/asm/fsp2/fsp_api.h b/arch/x86/include/asm/fsp2/fsp_api.h
index dccbfa4..ca3f684 100644
--- a/arch/x86/include/asm/fsp2/fsp_api.h
+++ b/arch/x86/include/asm/fsp2/fsp_api.h
@@ -60,4 +60,12 @@ int fsp_silicon_init(bool s3wake, bool use_spi_flash);
typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
+/**
+ * fsp_setup_pinctrl() - Set up the pinctrl for FSP
+ *
+ * @ctx: Event context (not used)
+ * @event: Event information (not used)
+ */
+int fsp_setup_pinctrl(void *ctx, struct event *event);
+
#endif
diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
index 5afdce1..b15926e 100644
--- a/arch/x86/lib/fsp2/fsp_init.c
+++ b/arch/x86/lib/fsp2/fsp_init.c
@@ -9,6 +9,7 @@
#include <bootstage.h>
#include <cbfs.h>
#include <dm.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <spi.h>
@@ -18,7 +19,7 @@
#include <dm/uclass-internal.h>
#include <asm/fsp2/fsp_internal.h>
-int arch_cpu_init_dm(void)
+int fsp_setup_pinctrl(void *ctx, struct event *event)
{
struct udevice *dev;
ofnode node;
@@ -41,6 +42,7 @@ int arch_cpu_init_dm(void)
return ret;
}
+EVENT_SPY(EVT_DM_POST_INIT, fsp_setup_pinctrl);
#if !defined(CONFIG_TPL_BUILD)
binman_sym_declare(ulong, intel_fsp_m, image_pos);
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index b18c1cd..2d50c62 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -17,6 +17,7 @@
#include <syscon.h>
#include <asm/cpu.h>
#include <asm/cpu_common.h>
+#include <asm/fsp2/fsp_api.h>
#include <asm/global_data.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
@@ -27,7 +28,7 @@
DECLARE_GLOBAL_DATA_PTR;
-__weak int arch_cpu_init_dm(void)
+__weak int fsp_setup_pinctrl(void *ctx, struct event *event)
{
return 0;
}
@@ -89,7 +90,7 @@ static int x86_spl_init(void)
return ret;
}
#ifndef CONFIG_TPL
- ret = arch_cpu_init_dm();
+ ret = fsp_setup_pinctrl(NULL, NULL);
if (ret) {
debug("%s: arch_cpu_init_dm() failed\n", __func__);
return ret;
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index 5b57e53..18b05b2 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -19,11 +19,6 @@
DECLARE_GLOBAL_DATA_PTR;
-__weak int arch_cpu_init_dm(void)
-{
- return 0;
-}
-
static int x86_tpl_init(void)
{
int ret;
@@ -44,11 +39,6 @@ static int x86_tpl_init(void)
debug("%s: arch_cpu_init() failed\n", __func__);
return ret;
}
- ret = arch_cpu_init_dm();
- if (ret) {
- debug("%s: arch_cpu_init_dm() failed\n", __func__);
- return ret;
- }
preloader_console_init();
return 0;
diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c
index 182cf75..9e23f5c 100644
--- a/board/google/chromebook_coral/coral.c
+++ b/board/google/chromebook_coral/coral.c
@@ -10,6 +10,7 @@
#include <command.h>
#include <cros_ec.h>
#include <dm.h>
+#include <event.h>
#include <init.h>
#include <log.h>
#include <sysinfo.h>
@@ -32,11 +33,12 @@ struct cros_gpio_info {
int flags;
};
-int misc_init_f(void)
+static int coral_check_ll_boot(void *ctx, struct event *event)
{
if (!ll_boot_init()) {
printf("Running as secondary loader");
- if (gd->arch.coreboot_table) {
+ if (CONFIG_IS_ENABLED(COREBOOT_SYSINFO) &&
+ gd->arch.coreboot_table) {
int ret;
printf(" (found coreboot table at %lx)",
@@ -55,6 +57,7 @@ int misc_init_f(void)
return 0;
}
+EVENT_SPY(EVT_MISC_INIT_F, coral_check_ll_boot);
int arch_misc_init(void)
{
diff --git a/board/keymile/kmcent2/kmcent2.c b/board/keymile/kmcent2/kmcent2.c
index ca24b96..4486538 100644
--- a/board/keymile/kmcent2/kmcent2.c
+++ b/board/keymile/kmcent2/kmcent2.c
@@ -6,6 +6,7 @@
* Copyright 2013 Freescale Semiconductor, Inc.
*/
+#include <event.h>
#include <asm/cache.h>
#include <asm/fsl_fdt.h>
#include <asm/fsl_law.h>
@@ -181,7 +182,7 @@ unsigned long get_serial_clock(unsigned long dummy)
return (gd->bus_clk / 2);
}
-int misc_init_f(void)
+static int kmcent2_misc_init_f(void *ctx, struct event *event)
{
/* configure QRIO pis for i2c deblocking */
i2c_deblock_gpio_cfg();
@@ -209,6 +210,7 @@ int misc_init_f(void)
return 0;
}
+EVENT_SPY(EVT_MISC_INIT_F, kmcent2_misc_init_f);
#define USED_SRDS_BANK 0
#define EXPECTED_SRDS_RFCK SRDS_PLLCR0_RFCK_SEL_100
diff --git a/board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c b/board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c
index 467f110..ed8142d 100644
--- a/board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c
+++ b/board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <event.h>
#include <i2c.h>
#include <asm/io.h>
#include <asm/arch/immap_ls102xa.h>
@@ -109,12 +110,14 @@ int board_early_init_f(void)
return 0;
}
-int misc_init_f(void)
+static int pg_wcom_misc_init_f(void *ctx, struct event *event)
{
if (IS_ENABLED(CONFIG_PG_WCOM_UBOOT_UPDATE_SUPPORTED))
check_for_uboot_update();
+
return 0;
}
+EVENT_SPY(EVT_MISC_INIT_F, pg_wcom_misc_init_f);
int board_init(void)
{
diff --git a/cmd/Kconfig b/cmd/Kconfig
index d10deed..1ed63fa 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2367,6 +2367,14 @@ config CMD_DIAG
available tests and running either all the tests, or specific tests
identified by name.
+config CMD_EVENT
+ bool "event - Show information about events"
+ default y if EVENT_DEBUG
+ help
+ This enables the 'event' command which provides information about
+ events and event-handler routines. This can help to device event
+ hadling.
+
config CMD_IRQ
bool "irq - Show information about interrupts"
depends on !ARM && !MIPS && !RISCV && !SH
diff --git a/cmd/Makefile b/cmd/Makefile
index 166c652..0d2b2ee 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_CMD_DIAG) += diag.o
endif
obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
+obj-$(CONFIG_CMD_EVENT) += event.o
obj-$(CONFIG_CMD_EXTENSION) += extension_board.o
obj-$(CONFIG_CMD_ECHO) += echo.o
obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
diff --git a/cmd/event.c b/cmd/event.c
new file mode 100644
index 0000000..9cac202
--- /dev/null
+++ b/cmd/event.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Command-line access to events
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <event.h>
+
+static int do_event_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ event_show_spy_list();
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char event_help_text[] =
+ "event list - list event spies";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(event, "Events", event_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_event_list));
diff --git a/common/Kconfig b/common/Kconfig
index add4cda..24c83f0 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -492,6 +492,37 @@ config DISPLAY_BOARDINFO_LATE
menu "Start-up hooks"
+config EVENT
+ bool "General-purpose event-handling mechanism"
+ default y if SANDBOX
+ help
+ This enables sending and processing of events, to allow interested
+ parties to be alerted when something happens. This is an attempt to
+ step the flow of weak functions, hooks, functions in board_f.c
+ and board_r.c and the Kconfig options below.
+
+ See doc/develop/event.rst for more information.
+
+if EVENT
+
+config EVENT_DYNAMIC
+ bool "Support event registration at runtime"
+ default y if SANDBOX
+ help
+ Enable this to support adding an event spy at runtime, without adding
+ it to the EVENT_SPy() linker list. This increases code size slightly
+ but provides more flexibility for boards and subsystems that need it.
+
+config EVENT_DEBUG
+ bool "Enable event debugging assistance"
+ default y if SANDBOX
+ help
+ Enable this get usefui features for seeing what is happening with
+ events, such as event-type names. This adds to the code size of
+ U-Boot so can be turned off for production builds.
+
+endif # EVENT
+
config ARCH_EARLY_INIT_R
bool "Call arch-specific init soon after relocation"
help
@@ -558,12 +589,6 @@ config LAST_STAGE_INIT
U-Boot calls last_stage_init() before the command-line interpreter is
started.
-config MISC_INIT_F
- bool "Execute pre-relocation misc init"
- help
- Enabling this option calls the 'misc_init_f' function in the init
- sequence just before DRAM is inited.
-
config MISC_INIT_R
bool "Execute Misc Init"
default y if ARCH_KEYSTONE || ARCH_SUNXI || MPC85xx
diff --git a/common/Makefile b/common/Makefile
index 3eff719..cc2ba30 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -89,6 +89,8 @@ obj-y += malloc_simple.o
endif
endif
+obj-$(CONFIG_$(SPL_TPL_)EVENT) += event.o
+
obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o
obj-$(CONFIG_IO_TRACE) += iotrace.o
obj-y += memsize.o
diff --git a/common/board_f.c b/common/board_f.c
index a687600..5b655ad 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -19,6 +19,7 @@
#include <dm.h>
#include <env.h>
#include <env_internal.h>
+#include <event.h>
#include <fdtdec.h>
#include <fs.h>
#include <hang.h>
@@ -802,19 +803,19 @@ __weak int reserve_arch(void)
return 0;
}
-__weak int arch_cpu_init_dm(void)
+__weak int checkcpu(void)
{
return 0;
}
-__weak int checkcpu(void)
+__weak int clear_bss(void)
{
return 0;
}
-__weak int clear_bss(void)
+static int misc_init_f(void)
{
- return 0;
+ return event_notify_null(EVT_MISC_INIT_F);
}
static const init_fnc_t init_sequence_f[] = {
@@ -828,6 +829,7 @@ static const init_fnc_t init_sequence_f[] = {
initf_malloc,
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
+ event_init,
#ifdef CONFIG_BLOBLIST
bloblist_init,
#endif
@@ -841,7 +843,6 @@ static const init_fnc_t init_sequence_f[] = {
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm,
- arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
@@ -875,9 +876,7 @@ static const init_fnc_t init_sequence_f[] = {
show_board_info,
#endif
INIT_FUNC_WATCHDOG_INIT
-#if defined(CONFIG_MISC_INIT_F)
misc_init_f,
-#endif
INIT_FUNC_WATCHDOG_RESET
#if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
init_func_i2c,
diff --git a/common/board_r.c b/common/board_r.c
index c24d9b4..b92c1bb 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -594,6 +594,7 @@ static int run_main_loop(void)
static init_fnc_t init_sequence_r[] = {
initr_trace,
initr_reloc,
+ event_init,
/* TODO: could x86/PPC have this also perhaps? */
#if defined(CONFIG_ARM) || defined(CONFIG_RISCV)
initr_caches,
diff --git a/common/event.c b/common/event.c
new file mode 100644
index 0000000..9d67a06
--- /dev/null
+++ b/common/event.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Events provide a general-purpose way to react to / subscribe to changes
+ * within U-Boot
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_EVENT
+
+#include <common.h>
+#include <event.h>
+#include <event_internal.h>
+#include <log.h>
+#include <linker_lists.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <linux/list.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if CONFIG_IS_ENABLED(EVENT_DEBUG)
+const char *const type_name[] = {
+ "none",
+ "test",
+
+ /* Events related to driver model */
+ "dm_post_init",
+ "dm_pre_probe",
+ "dm_post_probe",
+ "dm_pre_remove",
+ "dm_post_remove",
+
+ /* init hooks */
+ "misc_init_f",
+};
+
+_Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
+#endif
+
+static const char *event_type_name(enum event_t type)
+{
+#if CONFIG_IS_ENABLED(EVENT_DEBUG)
+ return type_name[type];
+#else
+ return "(unknown)";
+#endif
+}
+
+static int notify_static(struct event *ev)
+{
+ struct evspy_info *start =
+ ll_entry_start(struct evspy_info, evspy_info);
+ const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
+ struct evspy_info *spy;
+
+ for (spy = start; spy != start + n_ents; spy++) {
+ if (spy->type == ev->type) {
+ int ret;
+
+ log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
+ event_type_name(ev->type), event_spy_id(spy));
+ ret = spy->func(NULL, ev);
+
+ /*
+ * TODO: Handle various return codes to
+ *
+ * - claim an event (no others will see it)
+ * - return an error from the event
+ */
+ if (ret)
+ return log_msg_ret("spy", ret);
+ }
+ }
+
+ return 0;
+}
+
+static int notify_dynamic(struct event *ev)
+{
+ struct event_state *state = gd_event_state();
+ struct event_spy *spy, *next;
+
+ list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
+ if (spy->type == ev->type) {
+ int ret;
+
+ log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
+ event_type_name(ev->type), spy->id);
+ ret = spy->func(spy->ctx, ev);
+
+ /*
+ * TODO: Handle various return codes to
+ *
+ * - claim an event (no others will see it)
+ * - return an error from the event
+ */
+ if (ret)
+ return log_msg_ret("spy", ret);
+ }
+ }
+
+ return 0;
+}
+
+int event_notify(enum event_t type, void *data, int size)
+{
+ struct event event;
+ int ret;
+
+ event.type = type;
+ if (size > sizeof(event.data))
+ return log_msg_ret("size", -E2BIG);
+ memcpy(&event.data, data, size);
+
+ ret = notify_static(&event);
+ if (ret)
+ return log_msg_ret("dyn", ret);
+
+ if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
+ ret = notify_dynamic(&event);
+ if (ret)
+ return log_msg_ret("dyn", ret);
+ }
+
+ return 0;
+}
+
+int event_notify_null(enum event_t type)
+{
+ return event_notify(type, NULL, 0);
+}
+
+void event_show_spy_list(void)
+{
+ struct evspy_info *start =
+ ll_entry_start(struct evspy_info, evspy_info);
+ const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
+ struct evspy_info *spy;
+ const int size = sizeof(ulong) * 2;
+
+ printf("Seq %-24s %*s %s\n", "Type", size, "Function", "ID");
+ for (spy = start; spy != start + n_ents; spy++) {
+ printf("%3x %-3x %-20s %*p %s\n", (uint)(spy - start),
+ spy->type, event_type_name(spy->type), size, spy->func,
+ event_spy_id(spy));
+ }
+}
+
+#if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
+static void spy_free(struct event_spy *spy)
+{
+ list_del(&spy->sibling_node);
+}
+
+int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
+{
+ struct event_state *state = gd_event_state();
+ struct event_spy *spy;
+
+ if (!CONFIG_IS_ENABLED(EVENT_DYNAMIC))
+ return -ENOSYS;
+ spy = malloc(sizeof(*spy));
+ if (!spy)
+ return log_msg_ret("alloc", -ENOMEM);
+
+ spy->id = id;
+ spy->type = type;
+ spy->func = func;
+ spy->ctx = ctx;
+ list_add_tail(&spy->sibling_node, &state->spy_head);
+
+ return 0;
+}
+
+int event_uninit(void)
+{
+ struct event_state *state = gd_event_state();
+ struct event_spy *spy, *next;
+
+ list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
+ spy_free(spy);
+
+ return 0;
+}
+
+int event_init(void)
+{
+ struct event_state *state = gd_event_state();
+
+ INIT_LIST_HEAD(&state->spy_head);
+
+ return 0;
+}
+#endif /* EVENT_DYNAMIC */
diff --git a/common/log.c b/common/log.c
index f7e0c0f..7254aa7 100644
--- a/common/log.c
+++ b/common/log.c
@@ -28,6 +28,7 @@ static const char *const log_cat_name[] = {
"devres",
"acpi",
"boot",
+ "event",
};
_Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE,
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index 70d62c0..29bf9b9 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -35,6 +35,7 @@ CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; read mmc 0:2 100000 0 80; setexpr loader *001004f0; setexpr size *00100518; setexpr blocks $size / 200; read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; setexpr cmdline_ptr $loader - 2000; setexpr.s cmdline *$cmdline_ptr; setexpr cmdline gsub %U \\\\${uuid}; if part uuid mmc 0:2 uuid; then zboot start 100000 0 0 0 $setup cmdline; zboot load; zboot setup; zboot dump; zboot go;fi"
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_EVENT=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_BLOBLIST=y
# CONFIG_TPL_BLOBLIST is not set
diff --git a/configs/kmcent2_defconfig b/configs/kmcent2_defconfig
index 40f471e..982cef6 100644
--- a/configs/kmcent2_defconfig
+++ b/configs/kmcent2_defconfig
@@ -16,10 +16,10 @@ CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_EVENT=y
CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_BOARD_EARLY_INIT_R=y
CONFIG_LAST_STAGE_INIT=y
-CONFIG_MISC_INIT_F=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_DM=y
CONFIG_CMD_I2C=y
diff --git a/configs/pg_wcom_expu1_defconfig b/configs/pg_wcom_expu1_defconfig
index 706aacf..648cb2c 100644
--- a/configs/pg_wcom_expu1_defconfig
+++ b/configs/pg_wcom_expu1_defconfig
@@ -35,6 +35,7 @@ CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/ram0"
CONFIG_SILENT_CONSOLE=y
+CONFIG_EVENT=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_MISC_INIT_R=y
CONFIG_CMD_IMLS=y
diff --git a/configs/pg_wcom_expu1_update_defconfig b/configs/pg_wcom_expu1_update_defconfig
index 9cd4798..f489555 100644
--- a/configs/pg_wcom_expu1_update_defconfig
+++ b/configs/pg_wcom_expu1_update_defconfig
@@ -33,6 +33,7 @@ CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/ram0"
CONFIG_SILENT_CONSOLE=y
+CONFIG_EVENT=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_MISC_INIT_R=y
CONFIG_CMD_IMLS=y
diff --git a/configs/pg_wcom_seli8_defconfig b/configs/pg_wcom_seli8_defconfig
index 8ca1a60..bca0163 100644
--- a/configs/pg_wcom_seli8_defconfig
+++ b/configs/pg_wcom_seli8_defconfig
@@ -35,6 +35,7 @@ CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/ram0"
CONFIG_SILENT_CONSOLE=y
+CONFIG_EVENT=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_MISC_INIT_R=y
CONFIG_CMD_IMLS=y
diff --git a/configs/pg_wcom_seli8_update_defconfig b/configs/pg_wcom_seli8_update_defconfig
index 5575ee8..af1812b 100644
--- a/configs/pg_wcom_seli8_update_defconfig
+++ b/configs/pg_wcom_seli8_update_defconfig
@@ -33,6 +33,7 @@ CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/ram0"
CONFIG_SILENT_CONSOLE=y
+CONFIG_EVENT=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_MISC_INIT_R=y
CONFIG_CMD_IMLS=y
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 7c157a2..40d1422 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -23,7 +23,6 @@ CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_PRE_CONSOLE_BUFFER=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_MISC_INIT_F=y
CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
CONFIG_CMD_BOOTZ=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 7ebeb89..eaaac6d 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -32,7 +32,6 @@ CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_PRE_CONSOLE_BUFFER=y
CONFIG_LOG=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_MISC_INIT_F=y
CONFIG_STACKPROTECTOR=y
CONFIG_ANDROID_AB=y
CONFIG_CMD_CPU=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 217b064..7ccee70 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -20,7 +20,6 @@ CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_MISC_INIT_F=y
CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
CONFIG_CMD_BOOTZ=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 1687ccf..31f5aa8 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -30,7 +30,6 @@ CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_MISC_INIT_F=y
CONFIG_HANDOFF=y
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_ENV_SUPPORT=y
diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
index 64eb766..211acc7 100644
--- a/configs/tools-only_defconfig
+++ b/configs/tools-only_defconfig
@@ -9,7 +9,6 @@ CONFIG_TIMESTAMP=y
CONFIG_FIT_SIGNATURE=y
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="run distro_bootcmd"
-CONFIG_MISC_INIT_F=y
# CONFIG_CMD_BOOTD is not set
# CONFIG_CMD_BOOTM is not set
# CONFIG_CMD_ELF is not set
diff --git a/doc/develop/event.rst b/doc/develop/event.rst
new file mode 100644
index 0000000..6e144cf
--- /dev/null
+++ b/doc/develop/event.rst
@@ -0,0 +1,66 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Events
+======
+
+U-Boot supports a way for various events to be handled by interested
+subsystems. This provide a generic way to handle 'hooks' like setting up the
+CPUs after driver model is active, or reading a partition table after a new
+block device is probed.
+
+Rather than using weak functions and direct calls across subsystemss, it is
+often easier to use an event.
+
+An event consists of a type (e.g. EVT_DM_POST_INIT) and some optional data,
+in `union event_data`. An event spy can be creasted to watch for events of a
+particular type. When the event is created, it is sent to each spy in turn.
+
+
+Declaring a spy
+---------------
+
+To declare a spy, use something like this::
+
+ static int snow_setup_cpus(void *ctx, struct event *event)
+ {
+ /* do something */
+ return 0;
+ }
+ EVENT_SPY(EVT_DM_POST_INIT, snow_setup_cpus);
+
+Your function is called when EVT_DM_POST_INIT is emitted, i.e. after driver
+model is inited (in SPL, or in U-Boot proper before and after relocation).
+
+
+Debugging
+---------
+
+To assist with debugging events, enable `CONFIG_EVENT_DEBUG` and
+`CONFIG_CMD_EVENT`. The :doc:`../usage/event` command can then be used to
+provide a spy list.
+
+It is also possible to list spy information from the U-Boot executable,, using
+the `event_dump.py` script::
+
+ $ scripts/event_dump.py /tmp/b/sandbox/u-boot
+ Event type Id Source location
+ -------------------- ------------------------------ ------------------------------
+ EVT_MISC_INIT_F f:sandbox_misc_init_f arch/sandbox/cpu/start.c:125
+
+This shows each event spy in U-Boot, along with the event type, function name
+(or ID) and source location.
+
+Note that if `CONFIG_EVENT_DEBUG` is not enabled, the event ID is missing, so
+the function is shown instead (with an `f:` prefix as above). Since the ID is
+generally the same as the function name, this does not matter much.
+
+The event type is decoded by the symbol used by U-Boot for the event linker
+list. Symbols have the form::
+
+ _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F
+
+so the event type can be read from the end. To manually list spy information
+in an image, use $(CROSS_COMPILE)nm::
+
+ nm u-boot |grep evspy |grep list
+ 00000000002d6300 D _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index 93ebfa4..2e6d6c3 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -17,6 +17,7 @@ Implementation
distro
driver-model/index
environment
+ event
global_data
logging
makefiles
diff --git a/doc/usage/event.rst b/doc/usage/event.rst
new file mode 100644
index 0000000..c0f8acd
--- /dev/null
+++ b/doc/usage/event.rst
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+event command
+=============
+
+Synopsis
+--------
+
+::
+
+ event list
+
+Description
+-----------
+
+The event command provides spy list.
+
+This shows the following information:
+
+Seq
+ Sequence number of the spy, numbered from 0
+
+Type
+ Type of the spy, both as a number and a label. If `CONFIG_EVENT_DEBUG` is
+ not enabled, the label just shows `(unknown)`.
+
+Function
+ Address of the function to call
+
+ID
+ ID string for this event, if `CONFIG_EVENT_DEBUG` is enabled. Otherwise this
+ just shows `?`.
+
+
+See :doc:`../develop/event` for more information on events.
+
+Example
+-------
+
+::
+
+ => event list
+ Seq Type Function ID
+ 0 7 misc_init_f 55a070517c68 ?
+
+Configuration
+-------------
+
+The event command is only available if CONFIG_CMD_EVENT=y.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 0aacf53..7501028 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -29,6 +29,7 @@ Shell commands
x86/cbsysinfo
conitrace
echo
+ event
exception
extension
exit
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 8f7703c..5c34004 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -77,6 +77,16 @@ config DM_DEVICE_REMOVE
it causes unplugged devices to linger around in the dm-tree, and it
causes USB host controllers to not be stopped when booting the OS.
+config DM_EVENT
+ bool "Support events with driver model"
+ depends on DM
+ imply EVENT
+ default y if SANDBOX
+ help
+ This enables support for generating events related to driver model
+ operations, such as prbing or removing a device. Subsystems can
+ register a 'spy' function that is called when the event occurs.
+
config SPL_DM_DEVICE_REMOVE
bool "Support device removal in SPL"
depends on SPL_DM
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index e6ec6ff..73d2e9e 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -207,6 +207,10 @@ int device_remove(struct udevice *dev, uint flags)
if (!(dev_get_flags(dev) & DM_FLAG_ACTIVATED))
return 0;
+ ret = device_notify(dev, EVT_DM_PRE_REMOVE);
+ if (ret)
+ return ret;
+
/*
* If the child returns EKEYREJECTED, continue. It just means that it
* didn't match the flags.
@@ -256,6 +260,10 @@ int device_remove(struct udevice *dev, uint flags)
dev_bic_flags(dev, DM_FLAG_ACTIVATED);
+ ret = device_notify(dev, EVT_DM_POST_REMOVE);
+ if (ret)
+ goto err_remove;
+
return 0;
err_remove:
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 901c1e2..1b356f1 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <event.h>
#include <log.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -493,6 +494,10 @@ int device_probe(struct udevice *dev)
if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
return 0;
+ ret = device_notify(dev, EVT_DM_PRE_PROBE);
+ if (ret)
+ return ret;
+
drv = dev->driver;
assert(drv);
@@ -597,6 +602,10 @@ int device_probe(struct udevice *dev)
dev->name, ret, errno_str(ret));
}
+ ret = device_notify(dev, EVT_DM_POST_PROBE);
+ if (ret)
+ return ret;
+
return 0;
fail_uclass:
if (device_remove(dev, DM_REMOVE_NORMAL)) {
diff --git a/drivers/core/root.c b/drivers/core/root.c
index e3f8795..8efb425 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -404,6 +404,11 @@ int dm_init_and_scan(bool pre_reloc_only)
return ret;
}
}
+ if (CONFIG_IS_ENABLED(DM_EVENT)) {
+ ret = event_notify_null(EVT_DM_POST_INIT);
+ if (ret)
+ return log_msg_ret("ev", ret);
+ }
return 0;
}
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index c2f8fad..e49f5bf 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -20,6 +20,7 @@
*/
#ifndef __ASSEMBLY__
+#include <event_internal.h>
#include <fdtdec.h>
#include <membuff.h>
#include <linux/list.h>
@@ -467,6 +468,12 @@ struct global_data {
*/
char *smbios_version;
#endif
+#if CONFIG_IS_ENABLED(EVENT)
+ /**
+ * @event_state: Points to the current state of events
+ */
+ struct event_state event_state;
+#endif
};
#ifndef DO_DEPS_ONLY
static_assert(sizeof(struct global_data) == GD_SIZE);
@@ -532,6 +539,12 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
#define gd_set_multi_dtb_fit(_dtb)
#endif
+#if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
+#define gd_event_state() ((struct event_state *)&gd->event_state)
+#else
+#define gd_event_state() NULL
+#endif
+
/**
* enum gd_flags - global data flags
*
diff --git a/include/configs/km/pg-wcom-ls102xa.h b/include/configs/km/pg-wcom-ls102xa.h
index 97f6453..57d11d6 100644
--- a/include/configs/km/pg-wcom-ls102xa.h
+++ b/include/configs/km/pg-wcom-ls102xa.h
@@ -272,6 +272,4 @@
#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* Increase max gunzip size */
#define CONFIG_SYS_BOOTMAPSZ (256 << 20) /* Increase map for Linux */
-#define CONFIG_MISC_INIT_F
-
#endif
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 02002ac..c420726 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -10,6 +10,7 @@
#ifndef _DM_DEVICE_INTERNAL_H
#define _DM_DEVICE_INTERNAL_H
+#include <event.h>
#include <linker_lists.h>
#include <dm/ofnode.h>
@@ -426,4 +427,13 @@ static inline void devres_release_all(struct udevice *dev)
}
#endif /* ! CONFIG_DEVRES */
+
+static inline int device_notify(const struct udevice *dev, enum event_t type)
+{
+#if CONFIG_IS_ENABLED(DM_EVENT)
+ return event_notify(type, &dev, sizeof(dev));
+#else
+ return 0;
+#endif
+}
#endif
diff --git a/include/event.h b/include/event.h
new file mode 100644
index 0000000..62e72a7
--- /dev/null
+++ b/include/event.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Events provide a general-purpose way to react to / subscribe to changes
+ * within U-Boot
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __event_h
+#define __event_h
+
+/**
+ * enum event_t - Types of events supported by U-Boot
+ *
+ * @EVT_DM_PRE_PROBE: Device is about to be probed
+ */
+enum event_t {
+ EVT_NONE,
+ EVT_TEST,
+
+ /* Events related to driver model */
+ EVT_DM_POST_INIT,
+ EVT_DM_PRE_PROBE,
+ EVT_DM_POST_PROBE,
+ EVT_DM_PRE_REMOVE,
+ EVT_DM_POST_REMOVE,
+
+ /* Init hooks */
+ EVT_MISC_INIT_F,
+
+ EVT_COUNT
+};
+
+union event_data {
+ /**
+ * struct event_data_test - test data
+ *
+ * @signal: A value to update the state with
+ */
+ struct event_data_test {
+ int signal;
+ } test;
+
+ /**
+ * struct event_dm - driver model event
+ *
+ * @dev: Device this event relates to
+ */
+ struct event_dm {
+ struct udevice *dev;
+ } dm;
+};
+
+/**
+ * struct event - an event that can be sent and received
+ *
+ * @type: Event type
+ * @data: Data for this particular event
+ */
+struct event {
+ enum event_t type;
+ union event_data data;
+};
+
+/** Function type for event handlers */
+typedef int (*event_handler_t)(void *ctx, struct event *event);
+
+/**
+ * struct evspy_info - information about an event spy
+ *
+ * @func: Function to call when the event is activated (must be first)
+ * @type: Event type
+ * @id: Event id string
+ */
+struct evspy_info {
+ event_handler_t func;
+ enum event_t type;
+#if CONFIG_IS_ENABLED(EVENT_DEBUG)
+ const char *id;
+#endif
+};
+
+/* Declare a new event spy */
+#if CONFIG_IS_ENABLED(EVENT_DEBUG)
+#define _ESPY_REC(_type, _func) { _func, _type, #_func, }
+#else
+#define _ESPY_REC(_type, _func) { _func, _type, }
+#endif
+
+static inline const char *event_spy_id(struct evspy_info *spy)
+{
+#if CONFIG_IS_ENABLED(EVENT_DEBUG)
+ return spy->id;
+#else
+ return "?";
+#endif
+}
+
+/*
+ * It seems that LTO will drop list entries if it decides they are not used,
+ * although the conditions that cause this are unclear.
+ *
+ * The example found is the following:
+ *
+ * static int sandbox_misc_init_f(void *ctx, struct event *event)
+ * {
+ * return sandbox_early_getopt_check();
+ * }
+ * EVENT_SPY(EVT_MISC_INIT_F, sandbox_misc_init_f);
+ *
+ * where EVENT_SPY uses ll_entry_declare()
+ *
+ * In this case, LTO decides to drop the sandbox_misc_init_f() function
+ * (which is fine) but then drops the linker-list entry too. This means
+ * that the code no longer works, in this case sandbox no-longer checks its
+ * command-line arguments properly.
+ *
+ * Without LTO, the KEEP() command in the .lds file is enough to keep the
+ * entry around. But with LTO it seems that the entry has already been
+ * dropped before the link script is considered.
+ *
+ * The only solution I can think of is to mark linker-list entries as 'used'
+ * using an attribute. This should be safe, since we don't actually want to drop
+ * any of these. However this does slightly limit LTO's optimisation choices.
+ */
+#define EVENT_SPY(_type, _func) \
+ static __attribute__((used)) ll_entry_declare(struct evspy_info, \
+ _type, evspy_info) = \
+ _ESPY_REC(_type, _func)
+
+/**
+ * event_register - register a new spy
+ *
+ * @id: Spy ID
+ * @type: Event type to subscribe to
+ * @func: Function to call when the event is sent
+ * @ctx: Context to pass to the function
+ * @return 0 if OK, -ve on error
+ */
+int event_register(const char *id, enum event_t type, event_handler_t func,
+ void *ctx);
+
+/** event_show_spy_list( - Show a list of event spies */
+void event_show_spy_list(void);
+
+#if CONFIG_IS_ENABLED(EVENT)
+/**
+ * event_notify() - notify spies about an event
+ *
+ * It is possible to pass in union event_data here but that may not be
+ * convenient if the data is elsewhere, or is one of the members of the union.
+ * So this uses a void * for @data, with a separate @size.
+ *
+ * @type: Event type
+ * @data: Event data to be sent (e.g. union_event_data)
+ * @size: Size of data in bytes
+ * @return 0 if OK, -ve on error
+ */
+int event_notify(enum event_t type, void *data, int size);
+
+/**
+ * event_notify_null() - notify spies about an event
+ *
+ * Data is NULL and the size is 0
+ *
+ * @type: Event type
+ * @return 0 if OK, -ve on error
+ */
+int event_notify_null(enum event_t type);
+#else
+static inline int event_notify(enum event_t type, void *data, int size)
+{
+ return 0;
+}
+
+static inline int event_notify_null(enum event_t type)
+{
+ return 0;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
+/**
+ * event_uninit() - Clean up dynamic events
+ *
+ * This removes all dynamic event handlers
+ */
+int event_uninit(void);
+
+/**
+ * event_uninit() - Set up dynamic events
+ *
+ * Init a list of dynamic event handlers, so that these can be added as
+ * needed
+ */
+int event_init(void);
+#else
+static inline int event_uninit(void)
+{
+ return 0;
+}
+
+static inline int event_init(void)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/include/event_internal.h b/include/event_internal.h
new file mode 100644
index 0000000..8432c6f
--- /dev/null
+++ b/include/event_internal.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Internal definitions for events
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __event_internal_h
+#define __event_internal_h
+
+#include <event.h>
+#include <linux/list.h>
+
+/**
+ * struct event_spy - a spy that watches for an event of a particular type
+ *
+ * @id: Spy ID
+ * @type: Event type to subscribe to
+ * @func: Function to call when the event is sent
+ * @ctx: Context to pass to the function
+ */
+struct event_spy {
+ struct list_head sibling_node;
+ const char *id;
+ enum event_t type;
+ event_handler_t func;
+ void *ctx;
+};
+
+struct event_state {
+ struct list_head spy_head;
+};
+
+#endif
diff --git a/include/init.h b/include/init.h
index 20c3976..7449650 100644
--- a/include/init.h
+++ b/include/init.h
@@ -46,17 +46,6 @@ void board_init_f(ulong dummy);
int arch_cpu_init(void);
/**
- * arch_cpu_init_dm() - init CPU after driver model is available
- *
- * This is called immediately after driver model is available before
- * relocation. This is similar to arch_cpu_init() but is able to reference
- * devices
- *
- * Return: 0 if OK, -ve on error
- */
-int arch_cpu_init_dm(void);
-
-/**
* mach_cpu_init() - SoC/machine dependent CPU setup
*
* This is called after arch_cpu_init(). It should handle any
@@ -217,7 +206,6 @@ int init_cache_f_r(void);
int print_cpuinfo(void);
#endif
int timer_init(void);
-int misc_init_f(void);
#if defined(CONFIG_DTB_RESELECT)
int embedded_dtb_select(void);
diff --git a/include/log.h b/include/log.h
index ce48d51..8f35c10 100644
--- a/include/log.h
+++ b/include/log.h
@@ -98,6 +98,8 @@ enum log_category_t {
LOGC_ACPI,
/** @LOGC_BOOT: Related to boot process / boot image processing */
LOGC_BOOT,
+ /** @LOGC_EVENT: Related to event and event handling */
+ LOGC_EVENT,
/** @LOGC_COUNT: Number of log categories */
LOGC_COUNT,
/** @LOGC_END: Sentinel value for lists of log categories */
diff --git a/scripts/event_dump.py b/scripts/event_dump.py
new file mode 100755
index 0000000..751f41b
--- /dev/null
+++ b/scripts/event_dump.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0+
+
+"""Decode the evspy_info linker list in a U-Boot ELF image"""
+
+from argparse import ArgumentParser
+import os
+import re
+import struct
+import sys
+
+our_path = os.path.dirname(os.path.realpath(__file__))
+src_path = os.path.dirname(our_path)
+
+sys.path.insert(1, os.path.join(our_path, '../tools'))
+
+from binman import elf
+from patman import tools
+
+PREFIX = '_u_boot_list_2_evspy_info_2_'
+RE_EVTYPE = re.compile('%s(.*)' % PREFIX)
+
+def show_sym(fname, data, endian, evtype, sym):
+ """Show information about an evspy entry
+
+ Args:
+ fname (str): Filename of ELF file
+ data (bytes): Data for this symbol
+ endian (str): Endianness to use ('little', 'big', 'auto')
+ evtype (str): Event type, e.g. 'MISC_INIT_F'
+ sym (elf.Symbol): Symbol to show
+ """
+ def _unpack_val(sym_data, offset):
+ start = offset * func_size
+ val_data = sym_data[start:start + func_size]
+ fmt = '%s%s' % ('>' if endian == 'big' else '<',
+ 'L' if func_size == 4 else 'Q')
+ val = struct.unpack(fmt, val_data)[0]
+ return val
+
+ # Get the data, which is a struct evspy_info
+ sym_data = data[sym.offset:sym.offset + sym.size]
+
+ # Figure out the word size of the struct
+ func_size = 4 if sym.size < 16 else 8
+
+ # Read the function name for evspy_info->func
+ while True:
+ # Switch to big-endian if we see a failure
+ func_addr = _unpack_val(sym_data, 0)
+ func_name = elf.GetSymbolFromAddress(fname, func_addr)
+ if not func_name and endian == 'auto':
+ endian = 'big'
+ else:
+ break
+ has_id = sym.size in [12, 24]
+ if has_id:
+ # Find the address of evspy_info->id in the ELF
+ id_addr = _unpack_val(sym_data, 2)
+
+ # Get the file offset for that address
+ id_ofs = elf.GetFileOffset(fname, id_addr)
+
+ # Read out a nul-terminated string
+ id_data = data[id_ofs:id_ofs + 80]
+ pos = id_data.find(0)
+ if pos:
+ id_data = id_data[:pos]
+ id_str = id_data.decode('utf-8')
+ else:
+ id_str = None
+
+ # Find the file/line for the function
+ cmd = ['addr2line', '-e', fname, '%x' % func_addr]
+ out = tools.run(*cmd).strip()
+
+ # Drop the full path if it is the current directory
+ if out.startswith(src_path):
+ out = out[len(src_path) + 1:]
+ print('%-20s %-30s %s' % (evtype, id_str or f'f:{func_name}', out))
+
+def show_event_spy_list(fname, endian):
+ """Show a the event-spy- list from a U-Boot image
+
+ Args:
+ fname (str): Filename of ELF file
+ endian (str): Endianness to use ('little', 'big', 'auto')
+ """
+ syms = elf.GetSymbolFileOffset(fname, [PREFIX])
+ data = tools.read_file(fname)
+ print('%-20s %-30s %s' % ('Event type', 'Id', 'Source location'))
+ print('%-20s %-30s %s' % ('-' * 20, '-' * 30, '-' * 30))
+ for name, sym in syms.items():
+ m_evtype = RE_EVTYPE.search(name)
+ evtype = m_evtype .group(1)
+ show_sym(fname, data, endian, evtype, sym)
+
+def main(argv):
+ """Main program
+
+ Args:
+ argv (list of str): List of program arguments, excluding arvg[0]
+ """
+ epilog = 'Show a list of even spies in a U-Boot EFL file'
+ parser = ArgumentParser(epilog=epilog)
+ parser.add_argument('elf', type=str, help='ELF file to decode')
+ parser.add_argument('-e', '--endian', type=str, default='auto',
+ help='Big-endian image')
+ parser.add_argument('-t', '--test', action='store_true',
+ help='Big-endian image')
+ args = parser.parse_args(argv)
+ show_event_spy_list(args.elf, args.endian)
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/test/common/Makefile b/test/common/Makefile
index 24c9145..9087788 100644
--- a/test/common/Makefile
+++ b/test/common/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0+
obj-y += cmd_ut_common.o
obj-$(CONFIG_AUTOBOOT) += test_autoboot.o
+obj-$(CONFIG_EVENT) += event.o
diff --git a/test/common/event.c b/test/common/event.c
new file mode 100644
index 0000000..6037ae2
--- /dev/null
+++ b/test/common/event.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Unit tests for event handling
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <event.h>
+#include <test/common.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+struct test_state {
+ struct udevice *dev;
+ int val;
+};
+
+static int h_adder(void *ctx, struct event *event)
+{
+ struct event_data_test *data = &event->data.test;
+ struct test_state *test_state = ctx;
+
+ test_state->val += data->signal;
+
+ return 0;
+}
+
+static int test_event_base(struct unit_test_state *uts)
+{
+ struct test_state state;
+ int signal;
+
+ state.val = 12;
+ ut_assertok(event_register("wibble", EVT_TEST, h_adder, &state));
+
+ signal = 17;
+
+ /* Check that the handler is called */
+ ut_assertok(event_notify(EVT_TEST, &signal, sizeof(signal)));
+ ut_asserteq(12 + 17, state.val);
+
+ return 0;
+}
+COMMON_TEST(test_event_base, 0);
+
+static int h_probe(void *ctx, struct event *event)
+{
+ struct test_state *test_state = ctx;
+
+ test_state->dev = event->data.dm.dev;
+ switch (event->type) {
+ case EVT_DM_PRE_PROBE:
+ test_state->val |= 1;
+ break;
+ case EVT_DM_POST_PROBE:
+ test_state->val |= 2;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int test_event_probe(struct unit_test_state *uts)
+{
+ struct test_state state;
+ struct udevice *dev;
+
+ state.val = 0;
+ ut_assertok(event_register("pre", EVT_DM_PRE_PROBE, h_probe, &state));
+ ut_assertok(event_register("post", EVT_DM_POST_PROBE, h_probe, &state));
+
+ /* Probe a device */
+ ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
+
+ /* Check that the handler is called */
+ ut_asserteq(3, state.val);
+
+ return 0;
+}
+COMMON_TEST(test_event_probe, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
new file mode 100644
index 0000000..b753e80
--- /dev/null
+++ b/test/py/tests/test_event_dump.py
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+
+import pytest
+import re
+import u_boot_utils as util
+
+# This is only a partial test - coverting 64-bit sandbox. It does not test
+# big-endian images, nor 32-bit images
+@pytest.mark.boardspec('sandbox')
+def test_event_dump(u_boot_console):
+ """Test that the "help" command can be executed."""
+ cons = u_boot_console
+ sandbox = cons.config.build_dir + '/u-boot'
+ out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
+ expect = '''.*Event type Id Source location
+-------------------- ------------------------------ ------------------------------
+EVT_MISC_INIT_F sandbox_misc_init_f .*arch/sandbox/cpu/start.c:'''
+ assert re.match(expect, out, re.MULTILINE) is not None
diff --git a/test/test-main.c b/test/test-main.c
index 8fcb02e..ee38d1f 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <console.h>
#include <dm.h>
+#include <event.h>
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
@@ -218,6 +219,8 @@ static int dm_test_restore(struct device_node *of_root)
*/
static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
{
+ ut_assertok(event_init());
+
if (test->flags & UT_TESTF_DM)
ut_assertok(dm_test_pre_run(uts));
@@ -260,6 +263,7 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
ut_unsilence_console(uts);
if (test->flags & UT_TESTF_DM)
ut_assertok(dm_test_post_run(uts));
+ ut_assertok(event_uninit());
return 0;
}
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 5e7d6ae..3597173 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -85,6 +85,57 @@ def GetSymbols(fname, patterns):
# Sort dict by address
return OrderedDict(sorted(syms.items(), key=lambda x: x[1].address))
+def _GetFileOffset(elf, addr):
+ """Get the file offset for an address
+
+ Args:
+ elf (ELFFile): ELF file to check
+ addr (int): Address to search for
+
+ Returns
+ int: Offset of that address in the ELF file, or None if not valid
+ """
+ for seg in elf.iter_segments():
+ seg_end = seg['p_vaddr'] + seg['p_filesz']
+ if seg.header['p_type'] == 'PT_LOAD':
+ if addr >= seg['p_vaddr'] and addr < seg_end:
+ return addr - seg['p_vaddr'] + seg['p_offset']
+
+def GetFileOffset(fname, addr):
+ """Get the file offset for an address
+
+ Args:
+ fname (str): Filename of ELF file to check
+ addr (int): Address to search for
+
+ Returns
+ int: Offset of that address in the ELF file, or None if not valid
+ """
+ if not ELF_TOOLS:
+ raise ValueError('Python elftools package is not available')
+ with open(fname, 'rb') as fd:
+ elf = ELFFile(fd)
+ return _GetFileOffset(elf, addr)
+
+def GetSymbolFromAddress(fname, addr):
+ """Get the symbol at a particular address
+
+ Args:
+ fname (str): Filename of ELF file to check
+ addr (int): Address to search for
+
+ Returns:
+ str: Symbol name, or None if no symbol at that address
+ """
+ if not ELF_TOOLS:
+ raise ValueError('Python elftools package is not available')
+ with open(fname, 'rb') as fd:
+ elf = ELFFile(fd)
+ syms = GetSymbols(fname, None)
+ for name, sym in syms.items():
+ if sym.address == addr:
+ return name
+
def GetSymbolFileOffset(fname, patterns):
"""Get the symbols from an ELF file
@@ -97,13 +148,6 @@ def GetSymbolFileOffset(fname, patterns):
key: Name of symbol
value: Hex value of symbol
"""
- def _GetFileOffset(elf, addr):
- for seg in elf.iter_segments():
- seg_end = seg['p_vaddr'] + seg['p_filesz']
- if seg.header['p_type'] == 'PT_LOAD':
- if addr >= seg['p_vaddr'] and addr < seg_end:
- return addr - seg['p_vaddr'] + seg['p_offset']
-
if not ELF_TOOLS:
raise ValueError('Python elftools package is not available')