All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] vbe: Verified Boot for Embedded initial support
@ 2022-07-20 16:59 Simon Glass
  2022-07-20 16:59 ` [PATCH 01/19] video: Renname vbe.h to vesa.h Simon Glass
                   ` (18 more replies)
  0 siblings, 19 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Alexandru Gagniuc, Anatolij Gustschin,
	Andrew Scull, Artem Lapkin, Ashok Reddy Soma, Bin Meng,
	Chris Morgan, Daniel Golle, Etienne Carriere,
	Heinrich Schuchardt, Huang Jianan, Marek Behún, Marek Vasut,
	Masahisa Kojima, Michal Simek, Nandor Han, Ovidiu Panait,
	Patrick Delaunay, Pavel Herrmann, Philippe Reynes, Ramon Fried,
	Roland Gaudig, Sean Anderson, Steffen Jaeckel, Thomas Huth

This adds the concept of a VBE method to U-Boot, along with an
implementation of the 'VBE simple' method, basically a simple way of
updating firmware in MMC from userspace and monitoring it from U-Boot.

VBE simple is implemented in fwupd. U-Boot's role is to set up the
device tree with the required firmware-update properties and provide the
developer with information about the current VBE state. To that end this
series includes a new 'vbe' command that allows VBE methods to be listed
and examined.

As part of this work, support for doing FDT fixups via the event interface
is provided, along with the ability to write to the device tree via the
ofnode interface.

Further work is needed to pull everything together, but this is a step
along the way.


Simon Glass (19):
  video: Renname vbe.h to vesa.h
  video: Rename structs and functions to avoid VBE
  dm: core: Split out the declaration of ofnode
  ofnode: Add a note about how livetree updates work
  ofnode: Introduce support for multiple trees
  dm: core: Move ofnode-writing test to ofnode
  dm: core: Swap parameters of ofnode_write_prop()
  dm: core: Tidy up ofnode-writing test
  dm: core: Prepare for updating the device tree with ofnode
  ofnode: Allow writing to a flat tree
  dm: core: Add support for writing u32 with ofnode
  event: Add an event for device tree fixups
  read: Support sandbox
  bootstd: Fix comment in bootmeth test
  bootstd: Detect empty bootmeth ordering
  bootstd: Provide a bootmeth method to obtain state info
  vbe: Add initial support for VBE
  vbe: Support VBE simple
  vbe: Add a new vbe command

 arch/sandbox/dts/sandbox.dtsi         |  13 ++
 arch/sandbox/dts/test.dts             |  15 ++
 arch/x86/lib/bios.c                   |  12 +-
 arch/x86/lib/coreboot_table.c         |   2 +-
 arch/x86/lib/fsp/fsp_graphics.c       |   4 +-
 boot/Kconfig                          |  21 ++
 boot/Makefile                         |   3 +
 boot/bootmeth-uclass.c                |  12 +
 boot/bootmeth_distro.c                |  14 ++
 boot/image-fdt.c                      |  11 +
 boot/vbe.c                            | 119 ++++++++++
 boot/vbe_simple.c                     | 304 ++++++++++++++++++++++++++
 cmd/Kconfig                           |  10 +
 cmd/Makefile                          |   1 +
 cmd/elf.c                             |   2 +-
 cmd/read.c                            |   3 +-
 cmd/vbe.c                             |  87 ++++++++
 common/event.c                        |   3 +
 doc/develop/driver-model/livetree.rst |  60 ++++-
 drivers/bios_emulator/atibios.c       |  18 +-
 drivers/core/of_access.c              |  57 ++++-
 drivers/core/ofnode.c                 |  81 +++----
 drivers/pci/pci_rom.c                 |  14 +-
 drivers/video/broadwell_igd.c         |   4 +-
 drivers/video/coreboot.c              |   4 +-
 drivers/video/efi.c                   |   4 +-
 drivers/video/ivybridge_igd.c         |   4 +-
 drivers/video/vesa.c                  |   4 +-
 include/bios_emul.h                   |   6 +-
 include/bootmeth.h                    |  38 +++-
 include/bootstd.h                     |   2 +
 include/dm/of_access.h                |  22 +-
 include/dm/ofnode.h                   | 122 +++++------
 include/dm/ofnode_decl.h              |  85 +++++++
 include/event.h                       |  14 ++
 include/of_live.h                     |  16 ++
 include/test/test.h                   |   2 +
 include/vbe.h                         | 146 ++++---------
 include/vesa.h                        | 116 ++++++++++
 lib/elf.c                             |   2 +-
 lib/of_live.c                         |  14 +-
 test/boot/Makefile                    |   4 +
 test/boot/bootflow.c                  |  53 +++--
 test/boot/bootmeth.c                  |  31 ++-
 test/boot/vbe_simple.c                | 115 ++++++++++
 test/dm/ofnode.c                      | 132 +++++++++++
 test/dm/test-fdt.c                    |  53 -----
 test/py/tests/test_event_dump.py      |   1 +
 test/test-main.c                      |   3 +-
 49 files changed, 1503 insertions(+), 360 deletions(-)
 create mode 100644 boot/vbe.c
 create mode 100644 boot/vbe_simple.c
 create mode 100644 cmd/vbe.c
 create mode 100644 include/dm/ofnode_decl.h
 create mode 100644 include/vesa.h
 create mode 100644 test/boot/vbe_simple.c

-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 01/19] video: Renname vbe.h to vesa.h
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-21  1:25   ` Bin Meng
  2022-07-20 16:59 ` [PATCH 02/19] video: Rename structs and functions to avoid VBE Simon Glass
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Anatolij Gustschin, Andrew Scull,
	Bin Meng, Heinrich Schuchardt

We want to use VBE to mean Verfiied Boot for Embedded in U-Boot. Rename
the existing VBE (Vesa BIOS extensions) to allow this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/x86/lib/bios.c             | 2 +-
 arch/x86/lib/coreboot_table.c   | 2 +-
 arch/x86/lib/fsp/fsp_graphics.c | 2 +-
 cmd/elf.c                       | 2 +-
 drivers/bios_emulator/atibios.c | 2 +-
 drivers/pci/pci_rom.c           | 2 +-
 drivers/video/broadwell_igd.c   | 2 +-
 drivers/video/coreboot.c        | 2 +-
 drivers/video/efi.c             | 2 +-
 drivers/video/ivybridge_igd.c   | 2 +-
 drivers/video/vesa.c            | 2 +-
 include/{vbe.h => vesa.h}       | 4 ++--
 lib/elf.c                       | 2 +-
 13 files changed, 14 insertions(+), 14 deletions(-)
 rename include/{vbe.h => vesa.h} (98%)

diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index 98cc05de2eb..087539ba7db 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -10,7 +10,7 @@
 #include <bios_emul.h>
 #include <irq_func.h>
 #include <log.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <linux/linkage.h>
 #include <asm/cache.h>
 #include <asm/processor.h>
diff --git a/arch/x86/lib/coreboot_table.c b/arch/x86/lib/coreboot_table.c
index 6eab0452fda..05519d851a9 100644
--- a/arch/x86/lib/coreboot_table.c
+++ b/arch/x86/lib/coreboot_table.c
@@ -6,7 +6,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <net.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <acpi/acpi_s3.h>
 #include <asm/coreboot_tables.h>
 #include <asm/e820.h>
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index 02fd05c9faf..6a7552e6956 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -9,7 +9,7 @@
 #include <dm.h>
 #include <init.h>
 #include <log.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <acpi/acpi_table.h>
 #include <asm/fsp/fsp_support.h>
diff --git a/cmd/elf.c b/cmd/elf.c
index 2b33c50bd02..ce40d3f72a7 100644
--- a/cmd/elf.c
+++ b/cmd/elf.c
@@ -14,7 +14,7 @@
 #include <net.h>
 #include <vxworks.h>
 #ifdef CONFIG_X86
-#include <vbe.h>
+#include <vesa.h>
 #include <asm/cache.h>
 #include <asm/e820.h>
 #include <linux/linkage.h>
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
index cdc5ba6ad90..09da76bc5d9 100644
--- a/drivers/bios_emulator/atibios.c
+++ b/drivers/bios_emulator/atibios.c
@@ -51,7 +51,7 @@
 #include <errno.h>
 #include <log.h>
 #include <malloc.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <linux/delay.h>
 #include "biosemui.h"
 
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 73d15e797fc..ceeb59d1fe4 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -34,7 +34,7 @@
 #include <malloc.h>
 #include <pci.h>
 #include <pci_rom.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <acpi/acpi_s3.h>
 #include <asm/global_data.h>
diff --git a/drivers/video/broadwell_igd.c b/drivers/video/broadwell_igd.c
index 2551f162e8f..81f0fd8c019 100644
--- a/drivers/video/broadwell_igd.c
+++ b/drivers/video/broadwell_igd.c
@@ -11,7 +11,7 @@
 #include <dm.h>
 #include <init.h>
 #include <log.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <asm/cpu.h>
 #include <asm/global_data.h>
diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c
index 7237542c076..3efc65daa2b 100644
--- a/drivers/video/coreboot.c
+++ b/drivers/video/coreboot.c
@@ -6,7 +6,7 @@
 #include <common.h>
 #include <dm.h>
 #include <init.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <asm/cb_sysinfo.h>
 
diff --git a/drivers/video/efi.c b/drivers/video/efi.c
index 5f9031f2ec5..d60b6e27569 100644
--- a/drivers/video/efi.c
+++ b/drivers/video/efi.c
@@ -9,7 +9,7 @@
 #include <dm.h>
 #include <efi_api.h>
 #include <log.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 
 struct pixel {
diff --git a/drivers/video/ivybridge_igd.c b/drivers/video/ivybridge_igd.c
index 1aa5317dd5f..18672a18973 100644
--- a/drivers/video/ivybridge_igd.c
+++ b/drivers/video/ivybridge_igd.c
@@ -10,7 +10,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <pci_rom.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <asm/global_data.h>
 #include <asm/intel_regs.h>
diff --git a/drivers/video/vesa.c b/drivers/video/vesa.c
index 869e5469732..91da939e59b 100644
--- a/drivers/video/vesa.c
+++ b/drivers/video/vesa.c
@@ -7,7 +7,7 @@
 #include <dm.h>
 #include <log.h>
 #include <pci.h>
-#include <vbe.h>
+#include <vesa.h>
 #include <video.h>
 #include <asm/mtrr.h>
 
diff --git a/include/vbe.h b/include/vesa.h
similarity index 98%
rename from include/vbe.h
rename to include/vesa.h
index 1631260eb73..30df58a9f1b 100644
--- a/include/vbe.h
+++ b/include/vesa.h
@@ -7,8 +7,8 @@
  * Contributors:
  *     IBM Corporation - initial implementation
  *****************************************************************************/
-#ifndef _VBE_H
-#define _VBE_H
+#ifndef _VESA_H
+#define _VESA_H
 
 /* these structs are for input from and output to OF */
 struct __packed vbe_screen_info {
diff --git a/lib/elf.c b/lib/elf.c
index d074e4e0a7d..0476b2614c3 100644
--- a/lib/elf.c
+++ b/lib/elf.c
@@ -11,7 +11,7 @@
 #include <net.h>
 #include <vxworks.h>
 #ifdef CONFIG_X86
-#include <vbe.h>
+#include <vesa.h>
 #include <asm/e820.h>
 #include <linux/linkage.h>
 #endif
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 02/19] video: Rename structs and functions to avoid VBE
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
  2022-07-20 16:59 ` [PATCH 01/19] video: Renname vbe.h to vesa.h Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 03/19] dm: core: Split out the declaration of ofnode Simon Glass
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Anatolij Gustschin, Andrew Scull,
	Bin Meng, Heinrich Schuchardt

Rename these to VESA, itself an abbreviation, to avoid a conflict with
Verified Boot for Embedded.

Rename this to avoid referencing VBE.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/x86/lib/bios.c             | 10 +++++-----
 arch/x86/lib/fsp/fsp_graphics.c |  2 +-
 drivers/bios_emulator/atibios.c | 16 ++++++++--------
 drivers/pci/pci_rom.c           | 12 ++++++------
 drivers/video/broadwell_igd.c   |  2 +-
 drivers/video/coreboot.c        |  2 +-
 drivers/video/efi.c             |  2 +-
 drivers/video/ivybridge_igd.c   |  2 +-
 drivers/video/vesa.c            |  2 +-
 include/bios_emul.h             |  6 +++---
 include/vesa.h                  | 25 ++++++++++++++-----------
 11 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index 087539ba7db..94349ba8073 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -190,7 +190,7 @@ static void setup_realmode_idt(void)
 }
 
 #ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
-static u8 vbe_get_mode_info(struct vbe_mode_info *mi)
+static u8 vbe_get_mode_info(struct vesa_state *mi)
 {
 	u16 buffer_seg;
 	u16 buffer_adr;
@@ -204,13 +204,13 @@ static u8 vbe_get_mode_info(struct vbe_mode_info *mi)
 
 	realmode_interrupt(0x10, VESA_GET_MODE_INFO, 0x0000, mi->video_mode,
 			   0x0000, buffer_seg, buffer_adr);
-	memcpy(mi->mode_info_block, buffer, sizeof(struct vbe_mode_info));
+	memcpy(mi->mode_info_block, buffer, sizeof(struct vesa_state));
 	mi->valid = true;
 
 	return 0;
 }
 
-static u8 vbe_set_mode(struct vbe_mode_info *mi)
+static u8 vbe_set_mode(struct vesa_state *mi)
 {
 	int video_mode = mi->video_mode;
 
@@ -225,7 +225,7 @@ static u8 vbe_set_mode(struct vbe_mode_info *mi)
 	return 0;
 }
 
-static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info)
+static void vbe_set_graphics(int vesa_mode, struct vesa_state *mode_info)
 {
 	unsigned char *framebuffer;
 
@@ -249,7 +249,7 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info)
 #endif /* CONFIG_FRAMEBUFFER_SET_VESA_MODE */
 
 void bios_run_on_x86(struct udevice *dev, unsigned long addr, int vesa_mode,
-		     struct vbe_mode_info *mode_info)
+		     struct vesa_state *mode_info)
 {
 	pci_dev_t pcidev = dm_pci_get_bdf(dev);
 	u32 num_dev;
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index 6a7552e6956..b07c666caf7 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -106,7 +106,7 @@ static int fsp_video_probe(struct udevice *dev)
 	vesa->phys_base_ptr = dm_pci_read_bar32(dev, 2);
 	gd->fb_base = vesa->phys_base_ptr;
 
-	ret = vbe_setup_video_priv(vesa, uc_priv, plat);
+	ret = vesa_setup_video_priv(vesa, uc_priv, plat);
 	if (ret)
 		goto err;
 
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
index 09da76bc5d9..7ebead6bfad 100644
--- a/drivers/bios_emulator/atibios.c
+++ b/drivers/bios_emulator/atibios.c
@@ -83,13 +83,13 @@ static const void *bios_ptr(const void *buf, BE_VGAInfo *vga_info,
 }
 
 static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
-			      int vesa_mode, struct vbe_mode_info *mode_info)
+			      int vesa_mode, struct vesa_state *mode_info)
 {
 	void *buffer = (void *)(M.mem_base + vbe_offset);
 	u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
 	u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
 	struct vesa_mode_info *vm;
-	struct vbe_info *info;
+	struct vesa_bios_ext_info *info;
 	const u16 *modes_bios, *ptr;
 	u16 *modes;
 	int size;
@@ -140,7 +140,7 @@ static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
 		int attr;
 
 		debug("Mode %x: ", mode);
-		memset(buffer, '\0', sizeof(struct vbe_mode_info));
+		memset(buffer, '\0', sizeof(struct vesa_state));
 		regs->e.eax = VESA_GET_MODE_INFO;
 		regs->e.ebx = 0;
 		regs->e.ecx = mode;
@@ -174,7 +174,7 @@ static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
 }
 
 static int atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
-				 struct vbe_mode_info *mode_info)
+				 struct vesa_state *mode_info)
 {
 	void *buffer = (void *)(M.mem_base + vbe_offset);
 	u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
@@ -192,7 +192,7 @@ static int atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
 		return -ENOSYS;
 	}
 
-	memset(buffer, '\0', sizeof(struct vbe_mode_info));
+	memset(buffer, '\0', sizeof(struct vesa_state));
 	debug("VBE: Geting info for VESA mode %#04x\n", vesa_mode);
 	regs->e.eax = VESA_GET_MODE_INFO;
 	regs->e.ecx = vesa_mode;
@@ -231,7 +231,7 @@ at this stage the controller has its I/O and memory space enabled and
 that all other controllers are in a disabled state.
 ****************************************************************************/
 static void PCI_doBIOSPOST(struct udevice *pcidev, BE_VGAInfo *vga_info,
-			   int vesa_mode, struct vbe_mode_info *mode_info)
+			   int vesa_mode, struct vesa_state *mode_info)
 {
 	RMREGS regs;
 	RMSREGS sregs;
@@ -416,7 +416,7 @@ image we can extract over the PCI bus.
 ****************************************************************************/
 static int PCI_postController(struct udevice *pcidev, uchar *bios_rom,
 			      int bios_len, BE_VGAInfo *vga_info,
-			      int vesa_mode, struct vbe_mode_info *mode_info)
+			      int vesa_mode, struct vesa_state *mode_info)
 {
 	u32 bios_image_len;
 	uchar *mapped_bios;
@@ -496,7 +496,7 @@ void biosemu_set_interrupt_handler(int intnum, int (*int_func)(void))
 
 int biosemu_run(struct udevice *pcidev, uchar *bios_rom, int bios_len,
 		BE_VGAInfo *vga_info, int clean_up, int vesa_mode,
-		struct vbe_mode_info *mode_info)
+		struct vesa_state *mode_info)
 {
 	/*Post all the display controller BIOS'es*/
 	if (!PCI_postController(pcidev, bios_rom, bios_len, vga_info,
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index ceeb59d1fe4..27a24daa12a 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -202,7 +202,7 @@ static int pci_rom_load(struct pci_rom_header *rom_header,
 	return 0;
 }
 
-struct vbe_mode_info mode_info;
+struct vesa_state mode_info;
 
 void setup_video(struct screen_info *screen_info)
 {
@@ -326,9 +326,9 @@ err:
 }
 
 #ifdef CONFIG_DM_VIDEO
-int vbe_setup_video_priv(struct vesa_mode_info *vesa,
-			 struct video_priv *uc_priv,
-			 struct video_uc_plat *plat)
+int vesa_setup_video_priv(struct vesa_mode_info *vesa,
+			  struct video_priv *uc_priv,
+			  struct video_uc_plat *plat)
 {
 	if (!vesa->x_resolution)
 		return log_msg_ret("No x resolution", -ENXIO);
@@ -358,7 +358,7 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa,
 	return 0;
 }
 
-int vbe_setup_video(struct udevice *dev, int (*int15_handler)(void))
+int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void))
 {
 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
@@ -378,7 +378,7 @@ int vbe_setup_video(struct udevice *dev, int (*int15_handler)(void))
 		return ret;
 	}
 
-	ret = vbe_setup_video_priv(&mode_info.vesa, uc_priv, plat);
+	ret = vesa_setup_video_priv(&mode_info.vesa, uc_priv, plat);
 	if (ret) {
 		if (ret == -ENFILE) {
 			/*
diff --git a/drivers/video/broadwell_igd.c b/drivers/video/broadwell_igd.c
index 81f0fd8c019..6aa4e27071d 100644
--- a/drivers/video/broadwell_igd.c
+++ b/drivers/video/broadwell_igd.c
@@ -681,7 +681,7 @@ static int broadwell_igd_probe(struct udevice *dev)
 	debug("%s: is_broadwell=%d\n", __func__, is_broadwell);
 	ret = igd_pre_init(dev, is_broadwell);
 	if (!ret) {
-		ret = vbe_setup_video(dev, broadwell_igd_int15_handler);
+		ret = vesa_setup_video(dev, broadwell_igd_int15_handler);
 		if (ret)
 			debug("failed to run video BIOS: %d\n", ret);
 	}
diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c
index 3efc65daa2b..d2d87c75c89 100644
--- a/drivers/video/coreboot.c
+++ b/drivers/video/coreboot.c
@@ -57,7 +57,7 @@ static int coreboot_video_probe(struct udevice *dev)
 		goto err;
 	}
 
-	ret = vbe_setup_video_priv(vesa, uc_priv, plat);
+	ret = vesa_setup_video_priv(vesa, uc_priv, plat);
 	if (ret) {
 		ret = log_msg_ret("setup", ret);
 		goto err;
diff --git a/drivers/video/efi.c b/drivers/video/efi.c
index d60b6e27569..b11e42c0ebf 100644
--- a/drivers/video/efi.c
+++ b/drivers/video/efi.c
@@ -149,7 +149,7 @@ static int efi_video_probe(struct udevice *dev)
 	if (ret)
 		goto err;
 
-	ret = vbe_setup_video_priv(vesa, uc_priv, plat);
+	ret = vesa_setup_video_priv(vesa, uc_priv, plat);
 	if (ret)
 		goto err;
 
diff --git a/drivers/video/ivybridge_igd.c b/drivers/video/ivybridge_igd.c
index 18672a18973..9264dd6770d 100644
--- a/drivers/video/ivybridge_igd.c
+++ b/drivers/video/ivybridge_igd.c
@@ -762,7 +762,7 @@ static int bd82x6x_video_probe(struct udevice *dev)
 	rev = gma_func0_init(dev);
 	if (rev < 0)
 		return rev;
-	ret = vbe_setup_video(dev, int15_handler);
+	ret = vesa_setup_video(dev, int15_handler);
 	if (ret)
 		return ret;
 
diff --git a/drivers/video/vesa.c b/drivers/video/vesa.c
index 91da939e59b..cac3bb0c331 100644
--- a/drivers/video/vesa.c
+++ b/drivers/video/vesa.c
@@ -17,7 +17,7 @@ static int vesa_video_probe(struct udevice *dev)
 	ulong fbbase;
 	int ret;
 
-	ret = vbe_setup_video(dev, NULL);
+	ret = vesa_setup_video(dev, NULL);
 	if (ret)
 		return log_ret(ret);
 
diff --git a/include/bios_emul.h b/include/bios_emul.h
index 72410dc7948..a7e6d73972c 100644
--- a/include/bios_emul.h
+++ b/include/bios_emul.h
@@ -36,14 +36,14 @@ typedef struct {
 	u8 LowMem[1536];
 } BE_VGAInfo;
 
-struct vbe_mode_info;
+struct vesa_state;
 
 int BootVideoCardBIOS(struct udevice *pcidev, BE_VGAInfo **pVGAInfo,
 		      int clean_up);
 
 /* Run a BIOS ROM natively (only supported on x86 machines) */
 void bios_run_on_x86(struct udevice *dev, unsigned long addr, int vesa_mode,
-		     struct vbe_mode_info *mode_info);
+		     struct vesa_state *mode_info);
 
 /**
  * bios_set_interrupt_handler() - Install an interrupt handler for the BIOS
@@ -61,6 +61,6 @@ int biosemu_setup(struct udevice *pcidev, BE_VGAInfo **pVGAInfo);
 
 int biosemu_run(struct udevice *dev, uchar *bios_rom, int bios_len,
 		BE_VGAInfo *vga_info, int clean_up, int vesa_mode,
-		struct vbe_mode_info *mode_info);
+		struct vesa_state *mode_info);
 
 #endif
diff --git a/include/vesa.h b/include/vesa.h
index 30df58a9f1b..a42c1796863 100644
--- a/include/vesa.h
+++ b/include/vesa.h
@@ -11,7 +11,7 @@
 #define _VESA_H
 
 /* these structs are for input from and output to OF */
-struct __packed vbe_screen_info {
+struct __packed vesa_screen_info {
 	u8 display_type;	/* 0=NONE, 1= analog, 2=digital */
 	u16 screen_width;
 	u16 screen_height;
@@ -22,7 +22,7 @@ struct __packed vbe_screen_info {
 	u8 edid_block_zero[128];
 };
 
-struct __packed vbe_screen_info_input {
+struct __packed vesa_screen_info_input {
 	u8 signature[4];
 	u16 size_reserved;
 	u8 monitor_number;
@@ -30,8 +30,11 @@ struct __packed vbe_screen_info_input {
 	u8 color_depth;
 };
 
-/* these structs only store the required a subset of the VBE-defined fields */
-struct __packed vbe_info {
+/*
+ * These structs only store the required subset of fields  in Vesa BIOS
+ * Extensions
+ */
+struct __packed vesa_bios_ext_info {
 	char signature[4];
 	u16 version;
 	u32 oem_string_ptr;
@@ -80,7 +83,7 @@ struct __packed vesa_mode_info {
 	u8 reserved[206];
 };
 
-struct vbe_mode_info {
+struct vesa_state {
 	u16 video_mode;
 	bool valid;
 	union {
@@ -89,7 +92,7 @@ struct vbe_mode_info {
 	};
 };
 
-struct vbe_ddc_info {
+struct vesa_ddc_info {
 	u8 port_number;	/* i.e. monitor number */
 	u8 edid_transfer_time;
 	u8 ddc_level;
@@ -101,13 +104,13 @@ struct vbe_ddc_info {
 #define VESA_SET_MODE		0x4f02
 #define VESA_GET_CUR_MODE	0x4f03
 
-extern struct vbe_mode_info mode_info;
+extern struct vesa_state mode_info;
 
 struct video_priv;
 struct video_uc_plat;
-int vbe_setup_video_priv(struct vesa_mode_info *vesa,
-			 struct video_priv *uc_priv,
-			 struct video_uc_plat *plat);
-int vbe_setup_video(struct udevice *dev, int (*int15_handler)(void));
+int vesa_setup_video_priv(struct vesa_mode_info *vesa,
+			  struct video_priv *uc_priv,
+			  struct video_uc_plat *plat);
+int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void));
 
 #endif
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 03/19] dm: core: Split out the declaration of ofnode
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
  2022-07-20 16:59 ` [PATCH 01/19] video: Renname vbe.h to vesa.h Simon Glass
  2022-07-20 16:59 ` [PATCH 02/19] video: Rename structs and functions to avoid VBE Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 04/19] ofnode: Add a note about how livetree updates work Simon Glass
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Marek Vasut, Pavel Herrmann

This is used by a lot of files, but ofnode.h needs to include a lot of
header files. This can create dependency cycles, particularly with
global_data.h which must include various declarations.

Split the core delcarations into a separate file to fix this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/dm/ofnode.h      | 61 +---------------------------------
 include/dm/ofnode_decl.h | 72 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 60 deletions(-)
 create mode 100644 include/dm/ofnode_decl.h

diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index bb60433124b..346b09c7d96 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -19,41 +19,7 @@
 
 struct resource;
 
-/**
- * typedef union ofnode_union ofnode - reference to a device tree node
- *
- * This union can hold either a straightforward pointer to a struct device_node
- * in the live device tree, or an offset within the flat device tree. In the
- * latter case, the pointer value is just the integer offset within the flat DT.
- *
- * Thus we can reference nodes in both the live tree (once available) and the
- * flat tree (until then). Functions are available to translate between an
- * ofnode and either an offset or a `struct device_node *`.
- *
- * The reference can also hold a null offset, in which case the pointer value
- * here is NULL. This corresponds to a struct device_node * value of
- * NULL, or an offset of -1.
- *
- * There is no ambiguity as to whether ofnode holds an offset or a node
- * pointer: when the live tree is active it holds a node pointer, otherwise it
- * holds an offset. The value itself does not need to be unique and in theory
- * the same value could point to a valid device node or a valid offset. We
- * could arrange for a unique value to be used (e.g. by making the pointer
- * point to an offset within the flat device tree in the case of an offset) but
- * this increases code size slightly due to the subtraction. Since it offers no
- * real benefit, the approach described here seems best.
- *
- * For now these points use constant types, since we don't allow writing
- * the DT.
- *
- * @np: Pointer to device node, used for live tree
- * @of_offset: Pointer into flat device tree, used for flat tree. Note that this
- *	is not a really a pointer to a node: it is an offset value. See above.
- */
-typedef union ofnode_union {
-	const struct device_node *np;
-	long of_offset;
-} ofnode;
+#include <dm/ofnode_decl.h>
 
 struct ofnode_phandle_args {
 	ofnode node;
@@ -61,31 +27,6 @@ struct ofnode_phandle_args {
 	uint32_t args[OF_MAX_PHANDLE_ARGS];
 };
 
-/**
- * struct ofprop - reference to a property of a device tree node
- *
- * This struct hold the reference on one property of one node,
- * using struct ofnode and an offset within the flat device tree or either
- * a pointer to a struct property in the live device tree.
- *
- * Thus we can reference arguments in both the live tree and the flat tree.
- *
- * The property reference can also hold a null reference. This corresponds to
- * a struct property NULL pointer or an offset of -1.
- *
- * @node: Pointer to device node
- * @offset: Pointer into flat device tree, used for flat tree.
- * @prop: Pointer to property, used for live treee.
- */
-
-struct ofprop {
-	ofnode node;
-	union {
-		int offset;
-		const struct property *prop;
-	};
-};
-
 /**
  * ofnode_to_np() - convert an ofnode to a live DT node pointer
  *
diff --git a/include/dm/ofnode_decl.h b/include/dm/ofnode_decl.h
new file mode 100644
index 00000000000..7c9e43e4ad8
--- /dev/null
+++ b/include/dm/ofnode_decl.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef _DM_OFNODE_DECL_H
+#define _DM_OFNODE_DECL_H
+
+/**
+ * typedef union ofnode_union ofnode - reference to a device tree node
+ *
+ * This union can hold either a straightforward pointer to a struct device_node
+ * in the live device tree, or an offset within the flat device tree. In the
+ * latter case, the pointer value is just the integer offset within the flat DT.
+ *
+ * Thus we can reference nodes in both the live tree (once available) and the
+ * flat tree (until then). Functions are available to translate between an
+ * ofnode and either an offset or a `struct device_node *`.
+ *
+ * The reference can also hold a null offset, in which case the pointer value
+ * here is NULL. This corresponds to a struct device_node * value of
+ * NULL, or an offset of -1.
+ *
+ * There is no ambiguity as to whether ofnode holds an offset or a node
+ * pointer: when the live tree is active it holds a node pointer, otherwise it
+ * holds an offset. The value itself does not need to be unique and in theory
+ * the same value could point to a valid device node or a valid offset. We
+ * could arrange for a unique value to be used (e.g. by making the pointer
+ * point to an offset within the flat device tree in the case of an offset) but
+ * this increases code size slightly due to the subtraction. Since it offers no
+ * real benefit, the approach described here seems best.
+ *
+ * For now these points use constant types, since we don't allow writing
+ * the DT.
+ *
+ * @np: Pointer to device node, used for live tree
+ * @of_offset: Pointer into flat device tree, used for flat tree. Note that this
+ *	is not a really a pointer to a node: it is an offset value. See above.
+ */
+typedef union ofnode_union {
+	const struct device_node *np;
+	long of_offset;
+} ofnode;
+
+/**
+ * struct ofprop - reference to a property of a device tree node
+ *
+ * This struct hold the reference on one property of one node,
+ * using struct ofnode and an offset within the flat device tree or either
+ * a pointer to a struct property in the live device tree.
+ *
+ * Thus we can reference arguments in both the live tree and the flat tree.
+ *
+ * The property reference can also hold a null reference. This corresponds to
+ * a struct property NULL pointer or an offset of -1.
+ *
+ * @node: Pointer to device node
+ * @offset: Pointer into flat device tree, used for flat tree.
+ * @prop: Pointer to property, used for live treee.
+ */
+
+struct ofprop {
+	ofnode node;
+	union {
+		int offset;
+		const struct property *prop;
+	};
+};
+
+#endif
+
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 04/19] ofnode: Add a note about how livetree updates work
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (2 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 03/19] dm: core: Split out the declaration of ofnode Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 05/19] ofnode: Introduce support for multiple trees Simon Glass
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

The unflattening algorithm results in a single block of memory being
allocated for the whole tree. When writing new properties, these are
allocated new memory outside that block. When the block is freed, the
allocated properties remain.

Document how this works and the potential memory leak, as well as
mentioning that updating the livetree is actually supported now.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/develop/driver-model/livetree.rst | 17 +++++++++++++----
 include/dm/ofnode.h                   |  3 ++-
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/doc/develop/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst
index 9f654f3b894..fb2969259d0 100644
--- a/doc/develop/driver-model/livetree.rst
+++ b/doc/develop/driver-model/livetree.rst
@@ -211,9 +211,18 @@ using it in new code.
 Modifying the livetree
 ----------------------
 
-This is not currently supported. Once implemented it should provide a much
-more efficient implementation for modification of the device tree than using
-the flat tree.
+This is supported in a limited way, with ofnode_write_prop() and related
+functions.
+
+The unflattening algorithm results in a single block of memory being
+allocated for the whole tree. When writing new properties, these are
+allocated new memory outside that block. When the block is freed, the
+allocated properties remain. This can result in a memory leak.
+
+The solution to this leak would be to add a flag for properties (and nodes when
+support is provided for adding those) that indicates that they should be
+freed. Then the tree can be scanned for these 'separately allocated' nodes and
+properties before freeing the memory block.
 
 
 Internal implementation
@@ -281,6 +290,6 @@ Live tree support was introduced in U-Boot 2017.07. There is still quite a bit
 of work to do to flesh this out:
 
 - tests for all access functions
-- support for livetree modification
+- more support for livetree modification
 - addition of more access functions as needed
 - support for livetree in SPL and before relocation (if desired)
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 346b09c7d96..5a5309d79a7 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1081,7 +1081,8 @@ int ofnode_device_is_compatible(ofnode node, const char *compat);
  * ofnode_write_prop() - Set a property of a ofnode
  *
  * Note that the value passed to the function is *not* allocated by the
- * function itself, but must be allocated by the caller if necessary.
+ * function itself, but must be allocated by the caller if necessary. However
+ * it does allocate memory for the property struct and name.
  *
  * @node:	The node for whose property should be set
  * @propname:	The name of the property to set
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 05/19] ofnode: Introduce support for multiple trees
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (3 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 04/19] ofnode: Add a note about how livetree updates work Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 06/19] dm: core: Move ofnode-writing test to ofnode Simon Glass
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Heinrich Schuchardt

At present ofnode only works with a single device tree, for the most part.
This is the control FDT used by U-Boot.

When booting an OS we may obtain a different device tree and want to
modify it. Add some initial support for this into the ofnode API.

Note that we don't permit aliases in this other device tree, since the
of_access implementation maintains a list of aliases collected at
start-up. Also, we don't need aliases to do fixups in the other FDT. So
make sure that flat tree and live tree processing are consistent in this
area.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/develop/driver-model/livetree.rst | 17 +++++++
 drivers/core/of_access.c              | 14 ++++--
 drivers/core/ofnode.c                 | 11 +++++
 include/dm/of_access.h                | 10 +++-
 include/dm/ofnode.h                   | 28 +++++++++++
 include/dm/ofnode_decl.h              | 13 ++++++
 include/of_live.h                     | 16 +++++++
 lib/of_live.c                         | 14 +-----
 test/dm/ofnode.c                      | 67 +++++++++++++++++++++++++++
 9 files changed, 171 insertions(+), 19 deletions(-)

diff --git a/doc/develop/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst
index fb2969259d0..c29f29b205b 100644
--- a/doc/develop/driver-model/livetree.rst
+++ b/doc/develop/driver-model/livetree.rst
@@ -225,6 +225,23 @@ freed. Then the tree can be scanned for these 'separately allocated' nodes and
 properties before freeing the memory block.
 
 
+Multiple livetrees
+------------------
+
+The livetree implementation was originally designed for use with the control
+FDT. This means that the FDT fix-ups (ft_board_setup() and the like, must use
+a flat tree.
+
+It would be helpful to use livetree for fixups, since adding a lot of nodes and
+properties would involve less memory copying and be more efficient. As a step
+towards this, an `oftree` type has been introduced. It is normally set to
+oftree_default() but can be set to other values. Eventually this should allow
+the use of FDT fixups using the ofnode interface, instead of the low-level
+libfdt one.
+
+See dm_test_ofnode_root() for some examples.
+
+
 Internal implementation
 -----------------------
 
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index c20b19cb50f..0e5915a43e6 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -343,24 +343,30 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent,
 #define for_each_property_of_node(dn, pp) \
 	for (pp = dn->properties; pp != NULL; pp = pp->next)
 
-struct device_node *of_find_node_opts_by_path(const char *path,
+struct device_node *of_find_node_opts_by_path(struct device_node *root,
+					      const char *path,
 					      const char **opts)
 {
 	struct device_node *np = NULL;
 	struct property *pp;
 	const char *separator = strchr(path, ':');
 
+	if (!root)
+		root = gd->of_root;
 	if (opts)
 		*opts = separator ? separator + 1 : NULL;
 
 	if (strcmp(path, "/") == 0)
-		return of_node_get(gd->of_root);
+		return of_node_get(root);
 
 	/* The path could begin with an alias */
 	if (*path != '/') {
 		int len;
 		const char *p = separator;
 
+		/* Only allow alias processing on the control FDT */
+		if (root != gd->of_root)
+			return NULL;
 		if (!p)
 			p = strchrnul(path, '/');
 		len = p - path;
@@ -383,7 +389,7 @@ struct device_node *of_find_node_opts_by_path(const char *path,
 
 	/* Step down the tree matching path components */
 	if (!np)
-		np = of_node_get(gd->of_root);
+		np = of_node_get(root);
 	while (np && *path == '/') {
 		struct device_node *tmp = np;
 
@@ -791,7 +797,7 @@ int of_alias_scan(void)
 
 		name = of_get_property(of_chosen, "stdout-path", NULL);
 		if (name)
-			of_stdout = of_find_node_opts_by_path(name,
+			of_stdout = of_find_node_opts_by_path(NULL, name,
 							&of_stdout_options);
 	}
 
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index a59832ebbfb..bd41ef503c2 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -552,6 +552,17 @@ ofnode ofnode_path(const char *path)
 		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
 }
 
+ofnode ofnode_path_root(oftree tree, const char *path)
+{
+	if (of_live_active())
+		return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
+							      NULL));
+	else if (*path != '/' && tree.fdt != gd->fdt_blob)
+		return ofnode_null();  /* Aliases only on control FDT */
+	else
+		return offset_to_ofnode(fdt_path_offset(tree.fdt, path));
+}
+
 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
 {
 	ofnode chosen_node;
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
index ec6e6e2c7c0..078f2ea06cd 100644
--- a/include/dm/of_access.h
+++ b/include/dm/of_access.h
@@ -197,6 +197,11 @@ struct device_node *of_get_parent(const struct device_node *np);
 /**
  * of_find_node_opts_by_path() - Find a node matching a full OF path
  *
+ * Note that alias processing is only available on the control FDT (gd->of_root).
+ * For other trees it is skipped, so any attempt to obtain an alias will result
+ * in returning NULL.
+ *
+ * @root: Root node of the tree to use. If this is NULL, then gd->of_root is used
  * @path: Either the full path to match, or if the path does not start with
  *	'/', the name of a property of the /aliases node (an alias). In the
  *	case of an alias, the node matching the alias' value will be returned.
@@ -210,12 +215,13 @@ struct device_node *of_get_parent(const struct device_node *np);
  *
  * Return: a node pointer or NULL if not found
  */
-struct device_node *of_find_node_opts_by_path(const char *path,
+struct device_node *of_find_node_opts_by_path(struct device_node *root,
+					      const char *path,
 					      const char **opts);
 
 static inline struct device_node *of_find_node_by_path(const char *path)
 {
-	return of_find_node_opts_by_path(path, NULL);
+	return of_find_node_opts_by_path(NULL, path, NULL);
 }
 
 /**
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 5a5309d79a7..d7ad5dccc14 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -176,6 +176,23 @@ static inline ofnode ofnode_root(void)
 	return node;
 }
 
+/**
+ * oftree_default() - Returns the default device tree (U-Boot's control FDT)
+ *
+ * Returns: reference to the control FDT
+ */
+static inline oftree oftree_default(void)
+{
+	oftree tree;
+
+	if (of_live_active())
+		tree.np = gd_of_root();
+	else
+		tree.fdt = (void *)gd->fdt_blob;
+
+	return tree;
+}
+
 /**
  * ofnode_name_eq() - Check if the node name is equivalent to a given name
  *                    ignoring the unit address
@@ -640,11 +657,22 @@ int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
 /**
  * ofnode_path() - find a node by full path
  *
+ * This uses the control FDT.
+ *
  * @path: Full path to node, e.g. "/bus/spi@1"
  * Return: reference to the node found. Use ofnode_valid() to check if it exists
  */
 ofnode ofnode_path(const char *path);
 
+/**
+ * ofnode_path_root() - find a node by full path from a root node
+ *
+ * @tree: Device tree to use
+ * @path: Full path to node, e.g. "/bus/spi@1"
+ * Return: reference to the node found. Use ofnode_valid() to check if it exists
+ */
+ofnode ofnode_path_root(oftree tree, const char *path);
+
 /**
  * ofnode_read_chosen_prop() - get the value of a chosen property
  *
diff --git a/include/dm/ofnode_decl.h b/include/dm/ofnode_decl.h
index 7c9e43e4ad8..266253d5e33 100644
--- a/include/dm/ofnode_decl.h
+++ b/include/dm/ofnode_decl.h
@@ -68,5 +68,18 @@ struct ofprop {
 	};
 };
 
+/**
+ * union oftree_union - reference to a tree of device tree nodes
+ *
+ * One or other of the members is used, depending on of_live_active()
+ *
+ * @np: Pointer to roott device node, used for live tree
+ * @fdt: Pointer to the flat device tree, used for flat tree
+ */
+typedef union oftree_union {
+	struct device_node *np;
+	void *fdt;
+} oftree;
+
 #endif
 
diff --git a/include/of_live.h b/include/of_live.h
index b2b9679ae84..f59d6af3350 100644
--- a/include/of_live.h
+++ b/include/of_live.h
@@ -20,4 +20,20 @@ struct device_node;
  */
 int of_live_build(const void *fdt_blob, struct device_node **rootp);
 
+/**
+ * unflatten_device_tree() - create tree of device_nodes from flat blob
+ *
+ * Note that this allocates a single block of memory, pointed to by *mynodes.
+ * To free the tree, use free(*mynodes)
+ *
+ * unflattens a device-tree, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used.
+ * @blob: The blob to expand
+ * @mynodes: The device_node tree created by the call
+ * Return: 0 if OK, -ve on error
+ */
+int unflatten_device_tree(const void *blob, struct device_node **mynodes);
+
 #endif
diff --git a/lib/of_live.c b/lib/of_live.c
index 2cb0dd9c073..30cae9ab881 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -248,19 +248,7 @@ static void *unflatten_dt_node(const void *blob, void *mem, int *poffset,
 	return mem;
 }
 
-/**
- * unflatten_device_tree() - create tree of device_nodes from flat blob
- *
- * unflattens a device-tree, creating the
- * tree of struct device_node. It also fills the "name" and "type"
- * pointers of the nodes so the normal device-tree walking functions
- * can be used.
- * @blob: The blob to expand
- * @mynodes: The device_node tree created by the call
- * Return: 0 if OK, -ve on error
- */
-static int unflatten_device_tree(const void *blob,
-				 struct device_node **mynodes)
+int unflatten_device_tree(const void *blob, struct device_node **mynodes)
 {
 	unsigned long size;
 	int start;
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 61ae1db62d7..6a252f3f504 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -3,6 +3,7 @@
 #include <common.h>
 #include <dm.h>
 #include <log.h>
+#include <of_live.h>
 #include <dm/of_extra.h>
 #include <dm/test.h>
 #include <test/test.h>
@@ -469,3 +470,69 @@ static int dm_test_ofnode_get_phy(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_ofnode_get_phy, 0);
+
+/**
+ * make_ofnode_fdt() - Create an FDT for testing with ofnode
+ *
+ * The size is set to the minimum needed
+ *
+ * @uts: Test state
+ * @fdt: Place to write FDT
+ * @size: Maximum size of space for fdt
+ */
+static int make_ofnode_fdt(struct unit_test_state *uts, void *fdt, int size)
+{
+	ut_assertok(fdt_create(fdt, size));
+	ut_assertok(fdt_finish_reservemap(fdt));
+	ut_assert(fdt_begin_node(fdt, "") >= 0);
+
+	ut_assert(fdt_begin_node(fdt, "aliases") >= 0);
+	ut_assertok(fdt_property_string(fdt, "mmc0", "/new-mmc"));
+	ut_assertok(fdt_end_node(fdt));
+
+	ut_assert(fdt_begin_node(fdt, "new-mmc") >= 0);
+	ut_assertok(fdt_end_node(fdt));
+
+	ut_assertok(fdt_end_node(fdt));
+	ut_assertok(fdt_finish(fdt));
+
+	return 0;
+}
+
+static int dm_test_ofnode_root(struct unit_test_state *uts)
+{
+	struct device_node *root = NULL;
+	char fdt[256];
+	oftree tree;
+	ofnode node;
+
+	/* Check that aliases work on the control FDT */
+	node = ofnode_get_aliases_node("ethernet3");
+	ut_assert(ofnode_valid(node));
+	ut_asserteq_str("sbe5", ofnode_get_name(node));
+
+	ut_assertok(make_ofnode_fdt(uts, fdt, sizeof(fdt)));
+	if (of_live_active()) {
+		ut_assertok(unflatten_device_tree(fdt, &root));
+		tree.np = root;
+	} else {
+		tree.fdt = fdt;
+	}
+
+	/* Make sure they don't work on this new tree */
+	node = ofnode_path_root(tree, "mmc0");
+	ut_assert(!ofnode_valid(node));
+
+	/* It should appear in the new tree */
+	node = ofnode_path_root(tree, "/new-mmc");
+	ut_assert(ofnode_valid(node));
+
+	/* ...and not in the control FDT */
+	node = ofnode_path_root(oftree_default(), "/new-mmc");
+	ut_assert(!ofnode_valid(node));
+
+	free(root);
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_root, UT_TESTF_SCAN_FDT);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 06/19] dm: core: Move ofnode-writing test to ofnode
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (4 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 05/19] ofnode: Introduce support for multiple trees Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 07/19] dm: core: Swap parameters of ofnode_write_prop() Simon Glass
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Marek Vasut, Pavel Herrmann

This fits better in the ofnode tests, so move it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 test/dm/ofnode.c   | 56 ++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/test-fdt.c | 53 -------------------------------------------
 2 files changed, 56 insertions(+), 53 deletions(-)

diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 6a252f3f504..b8d8e440dbc 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -4,8 +4,12 @@
 #include <dm.h>
 #include <log.h>
 #include <of_live.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
 #include <dm/of_extra.h>
+#include <dm/root.h>
 #include <dm/test.h>
+#include <dm/uclass-internal.h>
 #include <test/test.h>
 #include <test/ut.h>
 
@@ -536,3 +540,55 @@ static int dm_test_ofnode_root(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_ofnode_root, UT_TESTF_SCAN_FDT);
+
+static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	ofnode node;
+
+	if (!of_live_active()) {
+		printf("Live tree not active; ignore test\n");
+		return 0;
+	}
+
+	/* Test enabling devices */
+
+	node = ofnode_path("/usb@2");
+
+	ut_assert(!of_device_is_available(ofnode_to_np(node)));
+	ofnode_set_enabled(node, true);
+	ut_assert(of_device_is_available(ofnode_to_np(node)));
+
+	device_bind_driver_to_node(dm_root(), "usb_sandbox", "usb@2", node,
+				   &dev);
+	ut_assertok(uclass_find_device_by_seq(UCLASS_USB, 2, &dev));
+
+	/* Test string property setting */
+
+	ut_assert(device_is_compatible(dev, "sandbox,usb"));
+	ofnode_write_string(node, "compatible", "gdsys,super-usb");
+	ut_assert(device_is_compatible(dev, "gdsys,super-usb"));
+	ofnode_write_string(node, "compatible", "sandbox,usb");
+	ut_assert(device_is_compatible(dev, "sandbox,usb"));
+
+	/* Test setting generic properties */
+
+	/* Non-existent in DTB */
+	ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev));
+	/* reg = 0x42, size = 0x100 */
+	ut_assertok(ofnode_write_prop(node, "reg", 8,
+				      "\x00\x00\x00\x42\x00\x00\x01\x00"));
+	ut_asserteq(0x42, dev_read_addr(dev));
+
+	/* Test disabling devices */
+
+	device_remove(dev, DM_REMOVE_NORMAL);
+	device_unbind(dev);
+
+	ut_assert(of_device_is_available(ofnode_to_np(node)));
+	ofnode_set_enabled(node, false);
+	ut_assert(!of_device_is_available(ofnode_to_np(node)));
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_livetree_writing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index f9e81747595..6118ad42ca8 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -17,7 +17,6 @@
 #include <dm/devres.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
-#include <dm/lists.h>
 #include <dm/of_access.h>
 #include <linux/ioport.h>
 #include <test/test.h>
@@ -735,58 +734,6 @@ static int dm_test_fdt_remap_addr_name_live(struct unit_test_state *uts)
 DM_TEST(dm_test_fdt_remap_addr_name_live,
 	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
-static int dm_test_fdt_livetree_writing(struct unit_test_state *uts)
-{
-	struct udevice *dev;
-	ofnode node;
-
-	if (!of_live_active()) {
-		printf("Live tree not active; ignore test\n");
-		return 0;
-	}
-
-	/* Test enabling devices */
-
-	node = ofnode_path("/usb@2");
-
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, true);
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
-
-	device_bind_driver_to_node(dm_root(), "usb_sandbox", "usb@2", node,
-				   &dev);
-	ut_assertok(uclass_find_device_by_seq(UCLASS_USB, 2, &dev));
-
-	/* Test string property setting */
-
-	ut_assert(device_is_compatible(dev, "sandbox,usb"));
-	ofnode_write_string(node, "compatible", "gdsys,super-usb");
-	ut_assert(device_is_compatible(dev, "gdsys,super-usb"));
-	ofnode_write_string(node, "compatible", "sandbox,usb");
-	ut_assert(device_is_compatible(dev, "sandbox,usb"));
-
-	/* Test setting generic properties */
-
-	/* Non-existent in DTB */
-	ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev));
-	/* reg = 0x42, size = 0x100 */
-	ut_assertok(ofnode_write_prop(node, "reg", 8,
-				      "\x00\x00\x00\x42\x00\x00\x01\x00"));
-	ut_asserteq(0x42, dev_read_addr(dev));
-
-	/* Test disabling devices */
-
-	device_remove(dev, DM_REMOVE_NORMAL);
-	device_unbind(dev);
-
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, false);
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
-
-	return 0;
-}
-DM_TEST(dm_test_fdt_livetree_writing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-
 static int dm_test_fdt_disable_enable_by_path(struct unit_test_state *uts)
 {
 	ofnode node;
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 07/19] dm: core: Swap parameters of ofnode_write_prop()
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (5 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 06/19] dm: core: Move ofnode-writing test to ofnode Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 08/19] dm: core: Tidy up ofnode-writing test Simon Glass
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Marek Vasut, Pavel Herrmann

It is normal for the length to come after the value in libfdt. Follow this
same convention with ofnode.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/ofnode.c | 6 +++---
 include/dm/ofnode.h   | 6 +++---
 test/dm/ofnode.c      | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index bd41ef503c2..1c9542a3567 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1105,8 +1105,8 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
 	}
 }
 
-int ofnode_write_prop(ofnode node, const char *propname, int len,
-		      const void *value)
+int ofnode_write_prop(ofnode node, const char *propname, const void *value,
+		      int len)
 {
 	const struct device_node *np = ofnode_to_np(node);
 	struct property *pp;
@@ -1161,7 +1161,7 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value)
 
 	debug("%s: %s = %s", __func__, propname, value);
 
-	return ofnode_write_prop(node, propname, strlen(value) + 1, value);
+	return ofnode_write_prop(node, propname, value, strlen(value) + 1);
 }
 
 int ofnode_set_enabled(ofnode node, bool value)
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index d7ad5dccc14..071a9d63f67 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1114,13 +1114,13 @@ int ofnode_device_is_compatible(ofnode node, const char *compat);
  *
  * @node:	The node for whose property should be set
  * @propname:	The name of the property to set
- * @len:	The length of the new value of the property
  * @value:	The new value of the property (must be valid prior to calling
  *		the function)
+ * @len:	The length of the new value of the property
  * Return: 0 if successful, -ve on error
  */
-int ofnode_write_prop(ofnode node, const char *propname, int len,
-		      const void *value);
+int ofnode_write_prop(ofnode node, const char *propname, const void *value,
+		      int len);
 
 /**
  * ofnode_write_string() - Set a string property of a ofnode
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index b8d8e440dbc..0aeaaeb7f8c 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -576,8 +576,8 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	/* Non-existent in DTB */
 	ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev));
 	/* reg = 0x42, size = 0x100 */
-	ut_assertok(ofnode_write_prop(node, "reg", 8,
-				      "\x00\x00\x00\x42\x00\x00\x01\x00"));
+	ut_assertok(ofnode_write_prop(node, "reg",
+				      "\x00\x00\x00\x42\x00\x00\x01\x00", 8));
 	ut_asserteq(0x42, dev_read_addr(dev));
 
 	/* Test disabling devices */
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 08/19] dm: core: Tidy up ofnode-writing test
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (6 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 07/19] dm: core: Swap parameters of ofnode_write_prop() Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 09/19] dm: core: Prepare for updating the device tree with ofnode Simon Glass
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Marek Vasut, Pavel Herrmann

Update this test to use the livetree flag so that special check can be
avoided. Also drop a few blank lines.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 test/dm/ofnode.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 0aeaaeb7f8c..ce96f9d1ee2 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -546,13 +546,7 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	struct udevice *dev;
 	ofnode node;
 
-	if (!of_live_active()) {
-		printf("Live tree not active; ignore test\n");
-		return 0;
-	}
-
 	/* Test enabling devices */
-
 	node = ofnode_path("/usb@2");
 
 	ut_assert(!of_device_is_available(ofnode_to_np(node)));
@@ -564,7 +558,6 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	ut_assertok(uclass_find_device_by_seq(UCLASS_USB, 2, &dev));
 
 	/* Test string property setting */
-
 	ut_assert(device_is_compatible(dev, "sandbox,usb"));
 	ofnode_write_string(node, "compatible", "gdsys,super-usb");
 	ut_assert(device_is_compatible(dev, "gdsys,super-usb"));
@@ -581,7 +574,6 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	ut_asserteq(0x42, dev_read_addr(dev));
 
 	/* Test disabling devices */
-
 	device_remove(dev, DM_REMOVE_NORMAL);
 	device_unbind(dev);
 
@@ -591,4 +583,5 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 
 	return 0;
 }
-DM_TEST(dm_test_ofnode_livetree_writing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+DM_TEST(dm_test_ofnode_livetree_writing,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_TREE);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 09/19] dm: core: Prepare for updating the device tree with ofnode
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (7 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 08/19] dm: core: Tidy up ofnode-writing test Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 10/19] ofnode: Allow writing to a flat tree Simon Glass
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Heinrich Schuchardt, Marek Vasut, Pavel Herrmann

Add some documentation and a new flag so that we can safely enabled using
the ofnode interface to write to the device tree.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/develop/driver-model/livetree.rst | 26 ++++++++++++++++++++++++++
 include/test/test.h                   |  2 ++
 test/test-main.c                      |  3 ++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/doc/develop/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst
index c29f29b205b..faf3eb5b5f0 100644
--- a/doc/develop/driver-model/livetree.rst
+++ b/doc/develop/driver-model/livetree.rst
@@ -224,6 +224,32 @@ support is provided for adding those) that indicates that they should be
 freed. Then the tree can be scanned for these 'separately allocated' nodes and
 properties before freeing the memory block.
 
+The ofnode_write\_...() functions also support writing to the flat tree. Care
+should be taken however, since this can change the position of node names and
+properties in the flat tree, thus affecting the live tree. Generally this does
+not matter, since when we fire up the live tree we don't ever use the flat tree
+again. But in the case of tests, this can cause a problem.
+
+The sandbox tests typically run with OF_LIVE enabled but with the actual live
+tree either present or absent. This is to make sure that the flat tree functions
+work correctly even with OF_LIVE is enabled. But if a test modifies the flat
+device tree, then the live tree can become invalid. Any live tree tests that run
+after that point will use a corrupted tree, e.g. with an incorrect property name
+or worse. To deal with this we use a flag UT_TESTF_LIVE_OR_FLAT then ensures
+that tests which write to the flat tree are not run if OF_LIVE is enabled. Only
+the live tree version of the test is run, when OF_LIVE is enabled, with
+sandbox_flattree running the flat tree version.
+
+This is of course a work-around, even if a reasonable one. One solution to this
+problem would be to make a copy of the flat tree before the test and restore it
+afterwards, in the same memory location, so that the live tree pointers work
+again. Another would be to regenerate the live tree if a test modified the flat
+tree.
+
+Neither of these solutions is currently implemented, since the situation that
+causes the problem can only occur in sandbox tests, is somewhat esoteric and
+the UT_TESTF_LIVE_OR_FLAT flag deals with it in a reasonable way.
+
 
 Multiple livetrees
 ------------------
diff --git a/include/test/test.h b/include/test/test.h
index 0104e189f63..c888d68b1ed 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -46,6 +46,8 @@ enum {
 	UT_TESTF_CONSOLE_REC	= BIT(5),	/* needs console recording */
 	/* do extra driver model init and uninit */
 	UT_TESTF_DM		= BIT(6),
+	/* live or flat device tree, but not both in the same executable */
+	UT_TESTF_LIVE_OR_FLAT	= BIT(4),
 };
 
 /**
diff --git a/test/test-main.c b/test/test-main.c
index ee38d1faea8..c0d0378c5d8 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -338,7 +338,8 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
 	/* Run with the live tree if possible */
 	runs = 0;
 	if (CONFIG_IS_ENABLED(OF_LIVE)) {
-		if (!(test->flags & UT_TESTF_FLAT_TREE)) {
+		if (!(test->flags &
+		    (UT_TESTF_FLAT_TREE | UT_TESTF_LIVE_OR_FLAT))) {
 			uts->of_live = true;
 			ut_assertok(ut_run_test(uts, test, test->name));
 			runs++;
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 10/19] ofnode: Allow writing to a flat tree
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (8 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 09/19] dm: core: Prepare for updating the device tree with ofnode Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 11/19] dm: core: Add support for writing u32 with ofnode Simon Glass
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

In generally it is not permitted to implement an ofnode function only for
flat tree or live tree. Both must be supported. Also the code for
live tree access should be in of_access.c rather than ofnode.c which is
really just for holding the API-conversion code.

Update ofnode_write_prop() accordingly and fix the test so it can work
with flat tree too.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/of_access.c | 43 +++++++++++++++++++++++++++++++++
 drivers/core/ofnode.c    | 51 ++++------------------------------------
 include/dm/of_access.h   | 12 ++++++++++
 include/dm/ofnode.h      | 18 ++++++++++++++
 test/dm/ofnode.c         | 14 +++++------
 5 files changed, 85 insertions(+), 53 deletions(-)

diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 0e5915a43e6..a52f5a6b18b 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -887,3 +887,46 @@ struct device_node *of_get_stdout(void)
 {
 	return of_stdout;
 }
+
+int of_write_prop(struct device_node *np, const char *propname, int len,
+		  const void *value)
+{
+	struct property *pp;
+	struct property *pp_last = NULL;
+	struct property *new;
+
+	if (!np)
+		return -EINVAL;
+
+	for (pp = np->properties; pp; pp = pp->next) {
+		if (strcmp(pp->name, propname) == 0) {
+			/* Property exists -> change value */
+			pp->value = (void *)value;
+			pp->length = len;
+			return 0;
+		}
+		pp_last = pp;
+	}
+
+	if (!pp_last)
+		return -ENOENT;
+
+	/* Property does not exist -> append new property */
+	new = malloc(sizeof(struct property));
+	if (!new)
+		return -ENOMEM;
+
+	new->name = strdup(propname);
+	if (!new->name) {
+		free(new);
+		return -ENOMEM;
+	}
+
+	new->value = (void *)value;
+	new->length = len;
+	new->next = NULL;
+
+	pp_last->next = new;
+
+	return 0;
+}
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 1c9542a3567..b7a55589a1c 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1108,55 +1108,17 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
 		      int len)
 {
-	const struct device_node *np = ofnode_to_np(node);
-	struct property *pp;
-	struct property *pp_last = NULL;
-	struct property *new;
-
-	if (!of_live_active())
-		return -ENOSYS;
-
-	if (!np)
-		return -EINVAL;
-
-	for (pp = np->properties; pp; pp = pp->next) {
-		if (strcmp(pp->name, propname) == 0) {
-			/* Property exists -> change value */
-			pp->value = (void *)value;
-			pp->length = len;
-			return 0;
-		}
-		pp_last = pp;
-	}
-
-	if (!pp_last)
-		return -ENOENT;
-
-	/* Property does not exist -> append new property */
-	new = malloc(sizeof(struct property));
-	if (!new)
-		return -ENOMEM;
-
-	new->name = strdup(propname);
-	if (!new->name) {
-		free(new);
-		return -ENOMEM;
-	}
-
-	new->value = (void *)value;
-	new->length = len;
-	new->next = NULL;
-
-	pp_last->next = new;
+	if (of_live_active())
+		return of_write_prop(ofnode_to_npw(node), propname, len, value);
+	else
+		return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node),
+				   propname, value, len);
 
 	return 0;
 }
 
 int ofnode_write_string(ofnode node, const char *propname, const char *value)
 {
-	if (!of_live_active())
-		return -ENOSYS;
-
 	assert(ofnode_valid(node));
 
 	debug("%s: %s = %s", __func__, propname, value);
@@ -1166,9 +1128,6 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value)
 
 int ofnode_set_enabled(ofnode node, bool value)
 {
-	if (!of_live_active())
-		return -ENOSYS;
-
 	assert(ofnode_valid(node));
 
 	if (value)
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
index 078f2ea06cd..5b7821d0a1b 100644
--- a/include/dm/of_access.h
+++ b/include/dm/of_access.h
@@ -519,4 +519,16 @@ int of_alias_get_highest_id(const char *stem);
  */
 struct device_node *of_get_stdout(void);
 
+/**
+ * of_write_prop() - Write a property to the device tree
+ *
+ * @np:		device node to which the property value is to be written
+ * @propname:	name of the property to write
+ * @value:	value of the property
+ * @len:	length of the property in bytes
+ * Returns: 0 if OK, -ve on error
+ */
+int of_write_prop(struct device_node *np, const char *propname, int len,
+		  const void *value);
+
 #endif
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 071a9d63f67..16c8890b097 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -44,6 +44,24 @@ static inline const struct device_node *ofnode_to_np(ofnode node)
 	return node.np;
 }
 
+/**
+ * ofnode_to_npw() - convert an ofnode to a writeable live DT node pointer
+ *
+ * This cannot be called if the reference contains an offset.
+ *
+ * @node: Reference containing struct device_node * (possibly invalid)
+ * Return: pointer to device node (can be NULL)
+ */
+static inline struct device_node *ofnode_to_npw(ofnode node)
+{
+#ifdef OF_CHECKS
+	if (!of_live_active())
+		return NULL;
+#endif
+	/* Drop constant */
+	return (struct device_node *)node.np;
+}
+
 /**
  * ofnode_to_offset() - convert an ofnode to a flat DT offset
  *
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index ce96f9d1ee2..bd598d23e44 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -549,9 +549,9 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	/* Test enabling devices */
 	node = ofnode_path("/usb@2");
 
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, true);
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
+	ut_assert(!ofnode_is_enabled(node));
+	ut_assertok(ofnode_set_enabled(node, true));
+	ut_asserteq(true, ofnode_is_enabled(node));
 
 	device_bind_driver_to_node(dm_root(), "usb_sandbox", "usb@2", node,
 				   &dev);
@@ -577,11 +577,11 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	device_remove(dev, DM_REMOVE_NORMAL);
 	device_unbind(dev);
 
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, false);
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
+	ut_assert(ofnode_is_enabled(node));
+	ut_assertok(ofnode_set_enabled(node, false));
+	ut_assert(!ofnode_is_enabled(node));
 
 	return 0;
 }
 DM_TEST(dm_test_ofnode_livetree_writing,
-	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_TREE);
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 11/19] dm: core: Add support for writing u32 with ofnode
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (9 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 10/19] ofnode: Allow writing to a flat tree Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 12/19] event: Add an event for device tree fixups Simon Glass
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass, Marek Vasut, Pavel Herrmann

Add a new function to write an integer to an ofnode (live tree or
flat tree).

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/ofnode.c | 15 +++++++++++++++
 include/dm/ofnode.h   | 10 ++++++++++
 test/dm/ofnode.c      | 16 ++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index b7a55589a1c..45ea84e9fb8 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1126,6 +1126,21 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value)
 	return ofnode_write_prop(node, propname, value, strlen(value) + 1);
 }
 
+int ofnode_write_u32(ofnode node, const char *propname, u32 value)
+{
+	fdt32_t *val;
+
+	assert(ofnode_valid(node));
+
+	log_debug("%s = %x", propname, value);
+	val = malloc(sizeof(*val));
+	if (!val)
+		return -ENOMEM;
+	*val = cpu_to_fdt32(value);
+
+	return ofnode_write_prop(node, propname, val, sizeof(value));
+}
+
 int ofnode_set_enabled(ofnode node, bool value)
 {
 	assert(ofnode_valid(node));
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 16c8890b097..7ce1e4c6d91 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1154,6 +1154,16 @@ int ofnode_write_prop(ofnode node, const char *propname, const void *value,
  */
 int ofnode_write_string(ofnode node, const char *propname, const char *value);
 
+/**
+ * ofnode_write_u32() - Set an integer property of an ofnode
+ *
+ * @node:	The node for whose string property should be set
+ * @propname:	The name of the string property to set
+ * @value:	The new value of the 32-bit integer property
+ * Return: 0 if successful, -ve on error
+ */
+int ofnode_write_u32(ofnode node, const char *propname, u32 value);
+
 /**
  * ofnode_set_enabled() - Enable or disable a device tree node given by its
  *			  ofnode
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index bd598d23e44..f80993f8927 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -585,3 +585,19 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_ofnode_livetree_writing,
 	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT);
+
+static int dm_test_ofnode_u32(struct unit_test_state *uts)
+{
+	ofnode node;
+
+	node = ofnode_path("/lcd");
+	ut_assert(ofnode_valid(node));
+	ut_asserteq(1366, ofnode_read_u32_default(node, "xres", 123));
+	ut_assertok(ofnode_write_u32(node, "xres", 1367));
+	ut_asserteq(1367, ofnode_read_u32_default(node, "xres", 123));
+	ut_assertok(ofnode_write_u32(node, "xres", 1366));
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_u32,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 12/19] event: Add an event for device tree fixups
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (10 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 11/19] dm: core: Add support for writing u32 with ofnode Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 13/19] read: Support sandbox Simon Glass
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Alexandru Gagniuc, Artem Lapkin,
	Daniel Golle, Heinrich Schuchardt, Marek Vasut

At present there is a confusing array of functions that handle the
device tree fix-ups needed for booting an OS. We should be able to switch
to using events to clean this up.

As a first step, create a new event type and call it from the standard
place.

Note that this event uses the ofnode interface only, since this can
support live tree which is more efficient when making lots of updates.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/image-fdt.c                 | 11 +++++++++++
 common/event.c                   |  3 +++
 include/event.h                  | 14 ++++++++++++++
 test/py/tests/test_event_dump.py |  1 +
 4 files changed, 29 insertions(+)

diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 9db2cee9942..5e5b24674d3 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -21,6 +21,7 @@
 #include <linux/libfdt.h>
 #include <mapmem.h>
 #include <asm/io.h>
+#include <dm/ofnode.h>
 #include <tee/optee.h>
 
 #ifndef CONFIG_SYS_FDT_PAD
@@ -668,6 +669,16 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
 			goto err;
 		}
 	}
+	if (CONFIG_IS_ENABLED(EVENT)) {
+		struct event_ft_fixup fixup;
+
+		fixup.tree = oftree_default();
+		ret = event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup));
+		if (ret) {
+			printf("ERROR: fdt fixup event failed: %d\n", ret);
+			goto err;
+		}
+	}
 
 	/* Delete the old LMB reservation */
 	if (lmb)
diff --git a/common/event.c b/common/event.c
index af1ed4121d8..3e345509783 100644
--- a/common/event.c
+++ b/common/event.c
@@ -35,6 +35,9 @@ const char *const type_name[] = {
 
 	/* init hooks */
 	"misc_init_f",
+
+	/* fdt hooks */
+	"ft_fixup",
 };
 
 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
diff --git a/include/event.h b/include/event.h
index c00c4fb68dc..05802019820 100644
--- a/include/event.h
+++ b/include/event.h
@@ -10,6 +10,8 @@
 #ifndef __event_h
 #define __event_h
 
+#include <dm/ofnode_decl.h>
+
 /**
  * enum event_t - Types of events supported by U-Boot
  *
@@ -29,6 +31,9 @@ enum event_t {
 	/* Init hooks */
 	EVT_MISC_INIT_F,
 
+	/* Device tree fixups before booting */
+	EVT_FT_FIXUP,
+
 	EVT_COUNT
 };
 
@@ -50,6 +55,15 @@ union event_data {
 	struct event_dm {
 		struct udevice *dev;
 	} dm;
+
+	/**
+	 * struct event_ft_fixup - FDT fixup before booting
+	 *
+	 * @tree: tree to update
+	 */
+	struct event_ft_fixup {
+		oftree tree;
+	} ft_fixup;
 };
 
 /**
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index b753e804ac3..17001777247 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -16,5 +16,6 @@ def test_event_dump(u_boot_console):
     out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
     expect = '''.*Event type            Id                              Source location
 --------------------  ------------------------------  ------------------------------
+EVT_FT_FIXUP          bootmeth_vbe_simple_ft_fixup    boot/vbe_simple.c:.*
 EVT_MISC_INIT_F       sandbox_misc_init_f             .*arch/sandbox/cpu/start.c:'''
     assert re.match(expect, out, re.MULTILINE) is not None
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 13/19] read: Support sandbox
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (11 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 12/19] event: Add an event for device tree fixups Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 14/19] bootstd: Fix comment in bootmeth test Simon Glass
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

Update the 'read' command to work correctly with sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/read.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cmd/read.c b/cmd/read.c
index 99c7e3854e1..fecfadaa1fa 100644
--- a/cmd/read.c
+++ b/cmd/read.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <part.h>
 
 int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
@@ -45,7 +46,7 @@ int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		return 1;
 	}
 
-	addr = (void *)hextoul(argv[3], NULL);
+	addr = map_sysmem(hextoul(argv[3], NULL), 0);
 	blk = hextoul(argv[4], NULL);
 	cnt = hextoul(argv[5], NULL);
 
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 14/19] bootstd: Fix comment in bootmeth test
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (12 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 13/19] read: Support sandbox Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 15/19] bootstd: Detect empty bootmeth ordering Simon Glass
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

Correct the comment at the top of this file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 test/boot/bootmeth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c
index 07776c5368d..81421f550b5 100644
--- a/test/boot/bootmeth.c
+++ b/test/boot/bootmeth.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Test for bootdev functions. All start with 'bootdev'
+ * Test for bootdev functions. All start with 'bootmeth'
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 15/19] bootstd: Detect empty bootmeth ordering
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (13 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 14/19] bootstd: Fix comment in bootmeth test Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 16/19] bootstd: Provide a bootmeth method to obtain state info Simon Glass
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

If the ordering produces no entries, this is an error. Report it, so that
the caller doesn't try to continue with a NULL bootmeth.

This fixes a crash in the bootflow_iter test when running with the sandbox
'default' device tree, instead of the required 'test' one.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/bootmeth-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index c040d5f92b2..b8ba4eca7ab 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -114,6 +114,8 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter)
 		}
 		count = upto;
 	}
+	if (!count)
+		return log_msg_ret("count2", -ENOENT);
 
 	iter->method_order = order;
 	iter->num_methods = count;
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 16/19] bootstd: Provide a bootmeth method to obtain state info
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (14 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 15/19] bootstd: Detect empty bootmeth ordering Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 17/19] vbe: Add initial support for VBE Simon Glass
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Tom Rini, Simon Glass

Some bootmeths can provide information about what is available to boot.
For example, VBE simple provides access to the firmware state.

Add a new method for this, along with a sandbox test.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/bootmeth-uclass.c | 10 ++++++++++
 boot/bootmeth_distro.c | 14 ++++++++++++++
 include/bootmeth.h     | 38 +++++++++++++++++++++++++++++++++++++-
 test/boot/bootmeth.c   | 18 ++++++++++++++++++
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index b8ba4eca7ab..1e276c0f26b 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -20,6 +20,16 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int bootmeth_get_state_desc(struct udevice *dev, char *buf, int maxsize)
+{
+	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+	if (!ops->get_state_desc)
+		return -ENOSYS;
+
+	return ops->get_state_desc(dev, buf, maxsize);
+}
+
 int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter)
 {
 	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
diff --git a/boot/bootmeth_distro.c b/boot/bootmeth_distro.c
index 2b41e654ade..fea09b2c2fb 100644
--- a/boot/bootmeth_distro.c
+++ b/boot/bootmeth_distro.c
@@ -22,6 +22,19 @@
 #include <mmc.h>
 #include <pxe_utils.h>
 
+static int distro_get_state_desc(struct udevice *dev, char *buf, int maxsize)
+{
+	if (IS_ENABLED(CONFIG_SANDBOX)) {
+		int len;
+
+		len = snprintf(buf, maxsize, "OK");
+
+		return len + 1 < maxsize ? 0 : -ENOSPC;
+	}
+
+	return 0;
+}
+
 static int disto_getfile(struct pxe_context *ctx, const char *file_path,
 			 char *file_addr, ulong *sizep)
 {
@@ -123,6 +136,7 @@ static int distro_bootmeth_bind(struct udevice *dev)
 }
 
 static struct bootmeth_ops distro_bootmeth_ops = {
+	.get_state_desc	= distro_get_state_desc,
 	.check		= distro_check,
 	.read_bootflow	= distro_read_bootflow,
 	.read_file	= bootmeth_common_read_file,
diff --git a/include/bootmeth.h b/include/bootmeth.h
index 484e503e338..4967031a0a8 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -24,7 +24,25 @@ struct bootmeth_uc_plat {
 /** struct bootmeth_ops - Operations for boot methods */
 struct bootmeth_ops {
 	/**
-	 * check_supported() - check if a bootmeth supports this bootflow
+	 * get_state_desc() - get detailed state information
+	 *
+	 * Prodecues a textual description of the state of the bootmeth. This
+	 * can include newline characters if it extends to multiple lines. It
+	 * must be a nul-terminated string.
+	 *
+	 * This may involve reading state from the system, e.g. some data in
+	 * the firmware area.
+	 *
+	 * @dev:	Bootmethod device to check
+	 * @buf:	Buffer to place the info in (terminator must fit)
+	 * @maxsize:	Size of buffer
+	 * Returns: 0 if OK, -ENOSPC is buffer is too small, other -ve error if
+	 * something else went wrong
+	 */
+	int (*get_state_desc)(struct udevice *dev, char *buf, int maxsize);
+
+	/**
+	 * check_supported() - check if a bootmeth supports this bootdev
 	 *
 	 * This is optional. If not provided, the bootdev is assumed to be
 	 * supported
@@ -91,6 +109,24 @@ struct bootmeth_ops {
 
 #define bootmeth_get_ops(dev)  ((struct bootmeth_ops *)(dev)->driver->ops)
 
+/**
+ * bootmeth_get_state_desc() - get detailed state information
+ *
+ * Prodecues a textual description of the state of the bootmeth. This
+ * can include newline characters if it extends to multiple lines. It
+ * must be a nul-terminated string.
+ *
+ * This may involve reading state from the system, e.g. some data in
+ * the firmware area.
+ *
+ * @dev:	Bootmethod device to check
+ * @buf:	Buffer to place the info in (terminator must fit)
+ * @maxsize:	Size of buffer
+ * Returns: 0 if OK, -ENOSPC is buffer is too small, other -ve error if
+ * something else went wrong
+ */
+int bootmeth_get_state_desc(struct udevice *dev, char *buf, int maxsize);
+
 /**
  * bootmeth_check() - check if a bootmeth supports this bootflow
  *
diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c
index 81421f550b5..5d2e87b1c95 100644
--- a/test/boot/bootmeth.c
+++ b/test/boot/bootmeth.c
@@ -7,7 +7,9 @@
  */
 
 #include <common.h>
+#include <bootmeth.h>
 #include <bootstd.h>
+#include <dm.h>
 #include <test/suites.h>
 #include <test/ut.h>
 #include "bootstd_common.h"
@@ -120,3 +122,19 @@ static int bootmeth_env(struct unit_test_state *uts)
 	return 0;
 }
 BOOTSTD_TEST(bootmeth_env, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check the get_state_desc() method */
+static int bootmeth_state(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	char buf[50];
+
+	ut_assertok(uclass_first_device(UCLASS_BOOTMETH, &dev));
+	ut_assertnonnull(dev);
+
+	ut_assertok(bootmeth_get_state_desc(dev, buf, sizeof(buf)));
+	ut_asserteq_str("OK", buf);
+
+	return 0;
+}
+BOOTSTD_TEST(bootmeth_state, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 17/19] vbe: Add initial support for VBE
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (15 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 16/19] bootstd: Provide a bootmeth method to obtain state info Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 18/19] vbe: Support VBE simple Simon Glass
  2022-07-20 16:59 ` [PATCH 19/19] vbe: Add a new vbe command Simon Glass
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Alexandru Gagniuc, Artem Lapkin,
	Philippe Reynes, Ramon Fried, Steffen Jaeckel

Create a new bootmeth for VBE along with a library to handle finding the
VBE methods.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/Kconfig      |   9 ++++
 boot/Makefile     |   2 +
 boot/vbe.c        | 119 ++++++++++++++++++++++++++++++++++++++++++++++
 include/bootstd.h |   2 +
 include/vbe.h     |  47 ++++++++++++++++++
 5 files changed, 179 insertions(+)
 create mode 100644 boot/vbe.c
 create mode 100644 include/vbe.h

diff --git a/boot/Kconfig b/boot/Kconfig
index 37880af5519..2bda221a68e 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -385,6 +385,15 @@ config BOOTMETH_EFILOADER
 
 	  This provides a way to try out standard boot on an existing boot flow.
 
+config BOOTMETH_VBE
+	bool "Bootdev support for Verified Boot for Embedded"
+	depends on FIT
+	default y
+	help
+	  Enables support for VBE boot. This is a standard boot method which
+	  supports selection of various firmware components, seleciton of an OS to
+	  boot as well as updating these using fwupd.
+
 config BOOTMETH_SANDBOX
 	def_bool y
 	depends on SANDBOX
diff --git a/boot/Makefile b/boot/Makefile
index a70674259c1..dd74bf5bc93 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -47,3 +47,5 @@ obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
 endif
+
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o
diff --git a/boot/vbe.c b/boot/vbe.c
new file mode 100644
index 00000000000..e6ee087dc24
--- /dev/null
+++ b/boot/vbe.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Verified Boot for Embedded (VBE) access functions
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <image.h>
+#include <vbe.h>
+#include <dm/uclass-internal.h>
+
+/**
+ * is_vbe() - Check if a device is a VBE method
+ *
+ * @dev: Device to check
+ * @return true if this is a VBE bootmth device, else false
+ */
+static bool is_vbe(struct udevice *dev)
+{
+	return !strncmp("vbe", dev->driver->name, 3);
+}
+
+int vbe_find_next_device(struct udevice **devp)
+{
+	for (uclass_find_next_device(devp);
+	     *devp;
+	     uclass_find_next_device(devp)) {
+		if (is_vbe(*devp))
+			return 0;
+	}
+
+	return 0;
+}
+
+int vbe_find_first_device(struct udevice **devp)
+{
+	uclass_find_first_device(UCLASS_BOOTMETH, devp);
+	if (*devp && is_vbe(*devp))
+		return 0;
+
+	return vbe_find_next_device(devp);
+}
+
+int vbe_list(void)
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	printf("%3s  %-3s  %-15s  %-15s %s\n", "#", "Sel", "Device", "Driver",
+	       "Description");
+	printf("%3s  %-3s  %-15s  %-15s %s\n", "---", "---", "--------------",
+	       "--------------", "-----------");
+	for (ret = vbe_find_first_device(&dev); dev;
+	     ret = vbe_find_next_device(&dev)) {
+		const struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+		printf("%3d  %-3s  %-15s  %-15s %s\n", dev_seq(dev),
+		       std->vbe_bootmeth == dev ? "*" : "", dev->name,
+		       dev->driver->name, plat->desc);
+	}
+	printf("%3s  %-3s  %-15s  %-15s %s\n", "---", "---", "--------------",
+	       "--------------", "-----------");
+
+	return 0;
+}
+
+int vbe_select(struct udevice *dev)
+{
+	struct bootstd_priv *std;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+	std->vbe_bootmeth = dev;
+
+	return 0;
+}
+
+int vbe_find_by_any(const char *name, struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret, seq;
+	char *endp;
+
+	seq = simple_strtol(name, &endp, 16);
+
+	/* Select by name */
+	if (*endp) {
+		ret = uclass_get_device_by_name(UCLASS_BOOTMETH, name, &dev);
+		if (ret) {
+			printf("Cannot probe VBE bootmeth '%s' (err=%d)\n", name,
+			       ret);
+			return ret;
+		}
+
+	/* select by number */
+	} else {
+		ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, seq, &dev);
+		if (ret) {
+			printf("Cannot find '%s' (err=%d)\n", name, ret);
+			return ret;
+		}
+	}
+
+	*devp = dev;
+
+	return 0;
+}
diff --git a/include/bootstd.h b/include/bootstd.h
index b002365f4f0..01be249d16e 100644
--- a/include/bootstd.h
+++ b/include/bootstd.h
@@ -26,6 +26,7 @@ struct udevice;
  * @glob_head: Head for the global list of all bootflows across all bootdevs
  * @bootmeth_count: Number of bootmeth devices in @bootmeth_order
  * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
+ * @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
  */
 struct bootstd_priv {
 	const char **prefixes;
@@ -35,6 +36,7 @@ struct bootstd_priv {
 	struct list_head glob_head;
 	int bootmeth_count;
 	struct udevice **bootmeth_order;
+	struct udevice *vbe_bootmeth;
 };
 
 /**
diff --git a/include/vbe.h b/include/vbe.h
new file mode 100644
index 00000000000..fa76268af46
--- /dev/null
+++ b/include/vbe.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Verified Boot for Embedded (VBE) support
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __VBE_H
+#define __VBE_H
+
+/**
+ * vbe_list() - List the VBE bootmeths
+ *
+ * This shows a list of the VBE bootmeth devices
+ *
+ * @return 0 (always)
+ */
+int vbe_list(void);
+
+/**
+ * vbe_find_by_any() - Find a VBE bootmeth by name or sequence
+ *
+ * @name: name (e.g. "vbe-simple"), or sequence ("2") to find
+ * @devp: returns the device found, on success
+ * Return: 0 if OK, -ve on error
+ */
+int vbe_find_by_any(const char *name, struct udevice **devp);
+
+/**
+ * vbe_find_first_device() - Find the first VBE bootmeth
+ *
+ * @devp: Returns first available VBE bootmeth, or NULL if none
+ * Returns: 0 (always)
+ */
+int vbe_find_first_device(struct udevice **devp);
+
+/**
+ * vbe_find_next_device() - Find the next available VBE bootmeth
+ *
+ * @devp: Previous device to start from. Returns next available VBE bootmeth,
+ * or NULL if none
+ * Returns: 0 (always)
+ */
+int vbe_find_next_device(struct udevice **devp);
+
+#endif
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 18/19] vbe: Support VBE simple
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (16 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 17/19] vbe: Add initial support for VBE Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  2022-07-20 16:59 ` [PATCH 19/19] vbe: Add a new vbe command Simon Glass
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Alexandru Gagniuc, Artem Lapkin,
	Philippe Reynes, Ramon Fried, Steffen Jaeckel

Add support for VBE simple, which permits firmware update of a single
image stored in MMC or another block device.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/Kconfig                     |  12 ++
 boot/Makefile                    |   1 +
 boot/vbe_simple.c                | 304 +++++++++++++++++++++++++++++++
 test/py/tests/test_event_dump.py |   2 +-
 4 files changed, 318 insertions(+), 1 deletion(-)
 create mode 100644 boot/vbe_simple.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 2bda221a68e..4a42b1b410a 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -394,6 +394,18 @@ config BOOTMETH_VBE
 	  supports selection of various firmware components, seleciton of an OS to
 	  boot as well as updating these using fwupd.
 
+if BOOTMETH_VBE
+
+config BOOTMETH_VBE_SIMPLE
+	bool "Bootdev support for VBE 'simple' method"
+	default y
+	help
+	  Enables support for VBE 'simple' boot. This allows updating a single
+	  firmware image in boot media such as MMC. It does not support any sort
+	  of rollback, recovery or A/B boot.
+
+endif # BOOTMETH_VBE
+
 config BOOTMETH_SANDBOX
 	def_bool y
 	depends on SANDBOX
diff --git a/boot/Makefile b/boot/Makefile
index dd74bf5bc93..eef3ae223c0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
 endif
 
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o
diff --git a/boot/vbe_simple.c b/boot/vbe_simple.c
new file mode 100644
index 00000000000..7ba8778f2b2
--- /dev/null
+++ b/boot/vbe_simple.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Verified Boot for Embedded (VBE) 'simple' method
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <memalign.h>
+#include <part.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <mmc.h>
+#include <vbe.h>
+#include <version_string.h>
+#include <dm/device-internal.h>
+#include <dm/ofnode.h>
+#include <u-boot/crc.h>
+
+enum {
+	MAX_VERSION_LEN		= 256,
+
+	NVD_HDR_VER_SHIFT	= 0,
+	NVD_HDR_VER_MASK	= 0xf,
+	NVD_HDR_SIZE_SHIFT	= 4,
+	NVD_HDR_SIZE_MASK	= 0xf << NVD_HDR_SIZE_SHIFT,
+
+	/* Firmware key-version is in the top 16 bits of fw_ver */
+	FWVER_KEY_SHIFT		= 16,
+	FWVER_FW_MASK		= 0xffff,
+
+	NVD_HDR_VER_CUR		= 1,	/* current version */
+};
+
+/** struct simple_priv - information read from the device tree */
+struct simple_priv {
+	u32 area_start;
+	u32 area_size;
+	u32 skip_offset;
+	u32 state_offset;
+	u32 state_size;
+	u32 version_offset;
+	u32 version_size;
+	const char *storage;
+};
+
+/** struct simple_state - state information read from media
+ *
+ * @fw_version: Firmware version string
+ * @fw_vernum: Firmware version number
+ */
+struct simple_state {
+	char fw_version[MAX_VERSION_LEN];
+	u32 fw_vernum;
+};
+
+/** struct simple_nvdata - storage format for non-volatile data */
+struct simple_nvdata {
+	u8 crc8;
+	u8 hdr;
+	u16 spare1;
+	u32 fw_vernum;
+	u8 spare2[0x38];
+};
+
+static int simple_read_version(struct udevice *dev, struct blk_desc *desc,
+			       u8 *buf, struct simple_state *state)
+{
+	struct simple_priv *priv = dev_get_priv(dev);
+	int start;
+
+	if (priv->version_size > MMC_MAX_BLOCK_LEN)
+		return log_msg_ret("ver", -E2BIG);
+
+	start = priv->area_start + priv->version_offset;
+	if (start & (MMC_MAX_BLOCK_LEN - 1))
+		return log_msg_ret("get", -EBADF);
+	start /= MMC_MAX_BLOCK_LEN;
+
+	if (blk_dread(desc, start, 1, buf) != 1)
+		return log_msg_ret("read", -EIO);
+	strlcpy(state->fw_version, buf, MAX_VERSION_LEN);
+	log_debug("version=%s\n", state->fw_version);
+
+	return 0;
+}
+
+static int simple_read_nvdata(struct udevice *dev, struct blk_desc *desc,
+			      u8 *buf, struct simple_state *state)
+{
+	struct simple_priv *priv = dev_get_priv(dev);
+	uint hdr_ver, hdr_size, size, crc;
+	const struct simple_nvdata *nvd;
+	int start;
+
+	if (priv->state_size > MMC_MAX_BLOCK_LEN)
+		return log_msg_ret("state", -E2BIG);
+
+	start = priv->area_start + priv->state_offset;
+	if (start & (MMC_MAX_BLOCK_LEN - 1))
+		return log_msg_ret("get", -EBADF);
+	start /= MMC_MAX_BLOCK_LEN;
+
+	if (blk_dread(desc, start, 1, buf) != 1)
+		return log_msg_ret("read", -EIO);
+	nvd = (struct simple_nvdata *)buf;
+	hdr_ver = (nvd->hdr & NVD_HDR_VER_MASK) >> NVD_HDR_VER_SHIFT;
+	hdr_size = (nvd->hdr & NVD_HDR_SIZE_MASK) >> NVD_HDR_SIZE_SHIFT;
+	if (hdr_ver != NVD_HDR_VER_CUR)
+		return log_msg_ret("hdr", -EPERM);
+	size = 1 << hdr_size;
+	if (size > sizeof(*nvd))
+		return log_msg_ret("sz", -ENOEXEC);
+
+	crc = crc8(0, buf + 1, size - 1);
+	if (crc != nvd->crc8)
+		return log_msg_ret("crc", -EPERM);
+	state->fw_vernum = nvd->fw_vernum;
+
+	log_debug("version=%s\n", state->fw_version);
+
+	return 0;
+}
+
+static int simple_read_state(struct udevice *dev, struct simple_state *state)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
+	struct simple_priv *priv = dev_get_priv(dev);
+	struct blk_desc *desc;
+	char devname[16];
+	const char *end;
+	int devnum;
+	int ret;
+
+	/* First figure out the block device */
+	log_debug("storage=%s\n", priv->storage);
+	devnum = trailing_strtoln_end(priv->storage, NULL, &end);
+	if (devnum == -1)
+		return log_msg_ret("num", -ENODEV);
+	if (end - priv->storage >= sizeof(devname))
+		return log_msg_ret("end", -E2BIG);
+	strlcpy(devname, priv->storage, end - priv->storage + 1);
+	log_debug("dev=%s, %x\n", devname, devnum);
+
+	desc = blk_get_dev(devname, devnum);
+	if (!desc)
+		return log_msg_ret("get", -ENXIO);
+
+	ret = simple_read_version(dev, desc, buf, state);
+	if (ret)
+		return log_msg_ret("ver", ret);
+
+	ret = simple_read_nvdata(dev, desc, buf, state);
+	if (ret)
+		return log_msg_ret("nvd", ret);
+
+	return 0;
+}
+
+static int simple_get_state_desc(struct udevice *dev, char *buf, int maxsize)
+{
+	struct simple_state state;
+	int ret;
+
+	ret = simple_read_state(dev, &state);
+	if (ret)
+		return log_msg_ret("read", ret);
+
+	if (maxsize < 30)
+		return -ENOSPC;
+	snprintf(buf, maxsize, "Version: %s\nVernum: %x/%x", state.fw_version,
+		 state.fw_vernum >> FWVER_KEY_SHIFT,
+		 state.fw_vernum & FWVER_FW_MASK);
+
+	return 0;
+}
+
+static struct bootmeth_ops bootmeth_vbe_simple_ops = {
+	.get_state_desc	= simple_get_state_desc,
+	.read_file	= bootmeth_common_read_file,
+};
+
+int vbe_simple_fixup_node(ofnode node, struct simple_state *state)
+{
+	char *version;
+	int ret;
+
+	version = strdup(state->fw_version);
+	if (!version)
+		return log_msg_ret("ver", -ENOMEM);
+
+	ret = ofnode_write_string(node, "cur-version", version);
+	if (ret)
+		return log_msg_ret("ver", ret);
+	ret = ofnode_write_u32(node, "cur-vernum", state->fw_vernum);
+	if (ret)
+		return log_msg_ret("ver", ret);
+	ret = ofnode_write_string(node, "bootloader-version", version_string);
+	if (ret)
+		return log_msg_ret("fix", ret);
+
+	return 0;
+}
+
+/**
+ * bootmeth_vbe_simple_ft_fixup() - Write out all VBE simple data to the DT
+ *
+ * @ctx: Context for event
+ * @event: Event to process
+ * @return 0 if OK, -ve on error
+ */
+static int bootmeth_vbe_simple_ft_fixup(void *ctx, struct event *event)
+{
+	oftree tree = event->data.ft_fixup.tree;
+	struct udevice *dev;
+	ofnode node;
+	int ret;
+
+	/*
+	 * Ideally we would have driver model support for fixups, but that does
+	 * not exist yet. It is a step too far to try to do this before VBE is
+	 * in place.
+	 */
+	for (ret = vbe_find_first_device(&dev); dev;
+	     ret = vbe_find_next_device(&dev)) {
+		struct simple_state state;
+
+		if (strcmp("vbe_simple", dev->driver->name))
+			continue;
+
+		/* Check if there is a node to fix up */
+		node = ofnode_path_root(tree, "/chosen/fwupd");
+		if (!ofnode_valid(node))
+			continue;
+		node = ofnode_find_subnode(node, dev->name);
+		if (!ofnode_valid(node))
+			continue;
+
+		log_debug("Fixing up: %s\n", dev->name);
+		ret = device_probe(dev);
+		if (ret)
+			return log_msg_ret("probe", ret);
+		ret = simple_read_state(dev, &state);
+		if (ret)
+			return log_msg_ret("read", ret);
+
+		ret = vbe_simple_fixup_node(node, &state);
+		if (ret)
+			return log_msg_ret("fix", ret);
+	}
+
+	return 0;
+}
+EVENT_SPY(EVT_FT_FIXUP, bootmeth_vbe_simple_ft_fixup);
+
+static int bootmeth_vbe_simple_probe(struct udevice *dev)
+{
+	struct simple_priv *priv = dev_get_priv(dev);
+
+	memset(priv, '\0', sizeof(*priv));
+	if (dev_read_u32(dev, "area-start", &priv->area_start) ||
+	    dev_read_u32(dev, "area-size", &priv->area_size) ||
+	    dev_read_u32(dev, "version-offset", &priv->version_offset) ||
+	    dev_read_u32(dev, "version-size", &priv->version_size) ||
+	    dev_read_u32(dev, "state-offset", &priv->state_offset) ||
+	    dev_read_u32(dev, "state-size", &priv->state_size))
+		return log_msg_ret("read", -EINVAL);
+	dev_read_u32(dev, "skip-offset", &priv->skip_offset);
+	priv->storage = strdup(dev_read_string(dev, "storage"));
+	if (!priv->storage)
+		return log_msg_ret("str", -EINVAL);
+
+	return 0;
+}
+
+static int bootmeth_vbe_simple_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
+		"VBE simple" : "vbe-simple";
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(OF_REAL)
+static const struct udevice_id generic_simple_vbe_simple_ids[] = {
+	{ .compatible = "fwupd,vbe-simple" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(vbe_simple) = {
+	.name	= "vbe_simple",
+	.id	= UCLASS_BOOTMETH,
+	.of_match = of_match_ptr(generic_simple_vbe_simple_ids),
+	.ops	= &bootmeth_vbe_simple_ops,
+	.bind	= bootmeth_vbe_simple_bind,
+	.probe	= bootmeth_vbe_simple_probe,
+	.flags	= DM_FLAG_PRE_RELOC,
+	.priv_auto	= sizeof(struct simple_priv),
+};
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index 17001777247..bc54149e8f2 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -16,6 +16,6 @@ def test_event_dump(u_boot_console):
     out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
     expect = '''.*Event type            Id                              Source location
 --------------------  ------------------------------  ------------------------------
-EVT_FT_FIXUP          bootmeth_vbe_simple_ft_fixup    boot/vbe_simple.c:.*
+EVT_FT_FIXUP          bootmeth_vbe_simple_ft_fixup    .*boot/vbe_simple.c:.*
 EVT_MISC_INIT_F       sandbox_misc_init_f             .*arch/sandbox/cpu/start.c:'''
     assert re.match(expect, out, re.MULTILINE) is not None
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 19/19] vbe: Add a new vbe command
  2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
                   ` (17 preceding siblings ...)
  2022-07-20 16:59 ` [PATCH 18/19] vbe: Support VBE simple Simon Glass
@ 2022-07-20 16:59 ` Simon Glass
  18 siblings, 0 replies; 23+ messages in thread
From: Simon Glass @ 2022-07-20 16:59 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Tom Rini, Simon Glass, Andrew Scull, Artem Lapkin,
	Ashok Reddy Soma, Chris Morgan, Etienne Carriere,
	Heinrich Schuchardt, Huang Jianan, Marek Behún,
	Masahisa Kojima, Michal Simek, Nandor Han, Ovidiu Panait,
	Patrick Delaunay, Philippe Reynes, Ramon Fried, Roland Gaudig,
	Sean Anderson, Thomas Huth

Add a command to look at VBE methods and their status. Provide a test for
all of this as well.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/dts/sandbox.dtsi |  13 ++++
 arch/sandbox/dts/test.dts     |  15 +++++
 cmd/Kconfig                   |  10 +++
 cmd/Makefile                  |   1 +
 cmd/vbe.c                     |  87 +++++++++++++++++++++++++
 test/boot/Makefile            |   4 ++
 test/boot/bootflow.c          |  53 ++++++++++------
 test/boot/bootmeth.c          |  11 ++--
 test/boot/vbe_simple.c        | 115 ++++++++++++++++++++++++++++++++++
 9 files changed, 285 insertions(+), 24 deletions(-)
 create mode 100644 cmd/vbe.c
 create mode 100644 test/boot/vbe_simple.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index aa22b8765c8..56e6b38bfa7 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -12,6 +12,19 @@
 
 	chosen {
 		stdout-path = "/serial";
+
+		fwupd {
+			compatible = "simple-bus";
+			firmware {
+				compatible = "fwupd,vbe-simple";
+				cur-version = "1.2.3";
+				bootloader-version = "2022.01";
+				storage = "mmc1";
+				area-start = <0x0>;
+				area-size = <0x1000000>;
+				skip-offset = <0x8000>;
+			};
+		};
 	};
 
 	audio: audio-codec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 0194b9b30ef..2cd5abbcfe2 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1378,6 +1378,21 @@
 			compatible = "denx,u-boot-fdt-test";
 			reg = <9 1>;
 		};
+
+		fwupd {
+			compatible = "simple-bus";
+			firmware0 {
+				compatible = "fwupd,vbe-simple";
+				storage = "mmc1";
+				area-start = <0x400>;
+				area-size = <0x1000>;
+				skip-offset = <0x200>;
+				state-offset = <0x400>;
+				state-size = <0x40>;
+				version-offset = <0x800>;
+				version-size = <0x100>;
+			};
+		};
 	};
 
 	translation-test@8000 {
diff --git a/cmd/Kconfig b/cmd/Kconfig
index d5f842136cf..321a612c54c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -328,6 +328,16 @@ config BOOTM_RTEMS
 	help
 	  Support booting RTEMS images via the bootm command.
 
+config CMD_VBE
+	bool "vbe - Verified Boot for Embedded"
+	depends on BOOTMETH_VBE
+	default y
+	help
+	  Provides various subcommands related to VBE, such as listing the
+	  available methods, looking at the state and changing which method
+	  is used to boot. Updating the parameters is not currently
+	  supported.
+
 config BOOTM_VXWORKS
 	bool "Support booting VxWorks OS images"
 	depends on CMD_BOOTM
diff --git a/cmd/Makefile b/cmd/Makefile
index 5e43a1e022e..6e87522b62e 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -179,6 +179,7 @@ obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
 obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o
 obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o
+obj-$(CONFIG_CMD_VBE) += vbe.o
 obj-$(CONFIG_CMD_XIMG) += ximg.o
 obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o
 obj-$(CONFIG_CMD_SPL) += spl.o
diff --git a/cmd/vbe.c b/cmd/vbe.c
new file mode 100644
index 00000000000..a5737edc047
--- /dev/null
+++ b/cmd/vbe.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Verified Boot for Embedded (VBE) command
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <command.h>
+#include <vbe.h>
+
+static int do_vbe_list(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	vbe_list();
+
+	return 0;
+}
+
+static int do_vbe_select(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+	if (argc < 2) {
+		std->vbe_bootmeth = NULL;
+		return 0;
+	}
+	if (vbe_find_by_any(argv[1], &dev))
+		return CMD_RET_FAILURE;
+
+	std->vbe_bootmeth = dev;
+
+	return 0;
+}
+
+static int do_vbe_info(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	struct bootstd_priv *std;
+	char buf[256];
+	int ret, len;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+	if (!std->vbe_bootmeth) {
+		printf("No VBE bootmeth selected\n");
+		return CMD_RET_FAILURE;
+	}
+	ret = bootmeth_get_state_desc(std->vbe_bootmeth, buf, sizeof(buf));
+	if (ret) {
+		printf("Failed (err=%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+	len = strnlen(buf, sizeof(buf));
+	if (len >= sizeof(buf)) {
+		printf("Buffer overflow\n");
+		return CMD_RET_FAILURE;
+	}
+
+	puts(buf);
+	if (buf[len] != '\n')
+		putc('\n');
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char vbe_help_text[] =
+	"list   - list VBE bootmeths\n"
+	"vbe select - select a VBE bootmeth by sequence or name\n"
+	"vbe info   - show information about a VBE bootmeth";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(vbe, "Verified Boot for Embedded", vbe_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_vbe_list),
+	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_vbe_select),
+	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_vbe_info));
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 1730792b5fa..9e9d5ae21f3 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -3,3 +3,7 @@
 # Copyright 2021 Google LLC
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
+
+ifdef CONFIG_OF_LIVE
+obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o
+endif
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 1ebb789e97b..ed4cf653d96 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -114,21 +114,23 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts)
 	ut_assert_nextline("     ** No partition found, err=-93");
 	ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
 	ut_assert_nextline("     ** No partition found, err=-93");
+	ut_assert_nextline("  2  firmware0    media   mmc          0  mmc2.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
 
 	ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
-	ut_assert_nextline("  2  syslinux     media   mmc          0  mmc1.bootdev.whole        <NULL>");
+	ut_assert_nextline("  3  syslinux     media   mmc          0  mmc1.bootdev.whole        <NULL>");
 	ut_assert_nextline("     ** No partition found, err=-2");
-	ut_assert_nextline("  3  efi          media   mmc          0  mmc1.bootdev.whole        <NULL>");
+	ut_assert_nextline("  4  efi          media   mmc          0  mmc1.bootdev.whole        <NULL>");
 	ut_assert_nextline("     ** No partition found, err=-2");
-	ut_assert_nextline("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
-	ut_assert_nextline("  5  efi          fs      mmc          1  mmc1.bootdev.part_1       efi/boot/bootsbox.efi");
+	ut_assert_nextline("  5  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextline("  6  efi          fs      mmc          1  mmc1.bootdev.part_1       efi/boot/bootsbox.efi");
 
 	ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
-	ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
+	ut_assert_skip_to_line(" 5d  firmware0    media   mmc          0  mmc0.bootdev.whole        <NULL>");
 	ut_assert_nextline("     ** No partition found, err=-93");
 	ut_assert_nextline("No more bootdevs");
 	ut_assert_nextlinen("---");
-	ut_assert_nextline("(64 bootflows, 1 valid)");
+	ut_assert_nextline("(94 bootflows, 1 valid)");
 	ut_assert_console_end();
 
 	ut_assertok(run_command("bootflow list", 0));
@@ -137,10 +139,10 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts)
 	ut_assert_nextlinen("---");
 	ut_assert_nextline("  0  syslinux     media   mmc          0  mmc2.bootdev.whole        <NULL>");
 	ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
-	ut_assert_skip_to_line("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
-	ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
+	ut_assert_skip_to_line("  5  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_skip_to_line(" 5d  firmware0    media   mmc          0  mmc0.bootdev.whole        <NULL>");
 	ut_assert_nextlinen("---");
-	ut_assert_nextline("(64 bootflows, 1 valid)");
+	ut_assert_nextline("(94 bootflows, 1 valid)");
 	ut_assert_console_end();
 
 	return 0;
@@ -216,7 +218,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 	/* The first device is mmc2.bootdev which has no media */
 	ut_asserteq(-EPROTONOSUPPORT,
 		    bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(0, iter.cur_method);
 	ut_asserteq(0, iter.part);
 	ut_asserteq(0, iter.max_part);
@@ -224,7 +226,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 	ut_asserteq(0, bflow.err);
 
 	/*
-	 * This shows MEDIA even though there is none, since int
+	 * This shows MEDIA even though there is none, since in
 	 * bootdev_find_in_blk() we call part_get_info() which returns
 	 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
 	 * know.
@@ -232,7 +234,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
 
 	ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(1, iter.cur_method);
 	ut_asserteq(0, iter.part);
 	ut_asserteq(0, iter.max_part);
@@ -241,9 +243,20 @@ static int bootflow_iter(struct unit_test_state *uts)
 	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
 	bootflow_free(&bflow);
 
+	/* Now we have the VBE bootmeth */
+	ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(3, iter.num_methods);
+	ut_asserteq(2, iter.cur_method);
+	ut_asserteq(0, iter.part);
+	ut_asserteq(0, iter.max_part);
+	ut_asserteq_str("firmware0", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+	bootflow_free(&bflow);
+
 	/* The next device is mmc1.bootdev - at first we use the whole device */
 	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(0, iter.cur_method);
 	ut_asserteq(0, iter.part);
 	ut_asserteq(0x1e, iter.max_part);
@@ -253,7 +266,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 	bootflow_free(&bflow);
 
 	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(1, iter.cur_method);
 	ut_asserteq(0, iter.part);
 	ut_asserteq(0x1e, iter.max_part);
@@ -262,9 +275,9 @@ static int bootflow_iter(struct unit_test_state *uts)
 	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
 	bootflow_free(&bflow);
 
-	/* Then more to partition 1 where we find something */
+	/* Then move to partition 1 where we find something */
 	ut_assertok(bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(0, iter.cur_method);
 	ut_asserteq(1, iter.part);
 	ut_asserteq(0x1e, iter.max_part);
@@ -274,7 +287,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 	bootflow_free(&bflow);
 
 	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(1, iter.cur_method);
 	ut_asserteq(1, iter.part);
 	ut_asserteq(0x1e, iter.max_part);
@@ -285,7 +298,7 @@ static int bootflow_iter(struct unit_test_state *uts)
 
 	/* Then more to partition 2 which doesn't exist */
 	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	ut_asserteq(0, iter.cur_method);
 	ut_asserteq(2, iter.part);
 	ut_asserteq(0x1e, iter.max_part);
@@ -356,7 +369,7 @@ static int bootflow_iter_disable(struct unit_test_state *uts)
 	/* Try to boot the bootmgr flow, which will fail */
 	console_record_reset_enable();
 	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
-	ut_asserteq(3, iter.num_methods);
+	ut_asserteq(4, iter.num_methods);
 	ut_asserteq_str("sandbox", iter.method->name);
 	ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
 
@@ -364,7 +377,7 @@ static int bootflow_iter_disable(struct unit_test_state *uts)
 	ut_assert_console_end();
 
 	/* Check that the sandbox bootmeth has been removed */
-	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(3, iter.num_methods);
 	for (i = 0; i < iter.num_methods; i++)
 		ut_assert(strcmp("sandbox", iter.method_order[i]->name));
 
diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c
index 5d2e87b1c95..dd87ae0b2a0 100644
--- a/test/boot/bootmeth.c
+++ b/test/boot/bootmeth.c
@@ -23,8 +23,9 @@ static int bootmeth_cmd_list(struct unit_test_state *uts)
 	ut_assert_nextlinen("---");
 	ut_assert_nextline("    0    0  syslinux            Syslinux boot from a block device");
 	ut_assert_nextline("    1    1  efi                 EFI boot from an .efi file");
+	ut_assert_nextline("    2    2  firmware0           VBE simple");
 	ut_assert_nextlinen("---");
-	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_nextline("(3 bootmeths)");
 	ut_assert_console_end();
 
 	return 0;
@@ -56,8 +57,9 @@ static int bootmeth_cmd_order(struct unit_test_state *uts)
 	ut_assert_nextlinen("---");
 	ut_assert_nextline("    0    0  syslinux            Syslinux boot from a block device");
 	ut_assert_nextline("    -    1  efi                 EFI boot from an .efi file");
+	ut_assert_nextline("    -    2  firmware0           VBE simple");
 	ut_assert_nextlinen("---");
-	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_nextline("(3 bootmeths)");
 	ut_assert_console_end();
 
 	/* Check the -a flag with the reverse order */
@@ -68,8 +70,9 @@ static int bootmeth_cmd_order(struct unit_test_state *uts)
 	ut_assert_nextlinen("---");
 	ut_assert_nextline("    1    0  syslinux            Syslinux boot from a block device");
 	ut_assert_nextline("    0    1  efi                 EFI boot from an .efi file");
+	ut_assert_nextline("    -    2  firmware0           VBE simple");
 	ut_assert_nextlinen("---");
-	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_nextline("(3 bootmeths)");
 	ut_assert_console_end();
 
 	/* Now reset the order to empty, which should show all of them again */
@@ -77,7 +80,7 @@ static int bootmeth_cmd_order(struct unit_test_state *uts)
 	ut_assert_console_end();
 	ut_assertnull(env_get("bootmeths"));
 	ut_assertok(run_command("bootmeth list", 0));
-	ut_assert_skip_to_line("(2 bootmeths)");
+	ut_assert_skip_to_line("(3 bootmeths)");
 
 	/* Try reverse order */
 	ut_assertok(run_command("bootmeth order \"efi syslinux\"", 0));
diff --git a/test/boot/vbe_simple.c b/test/boot/vbe_simple.c
new file mode 100644
index 00000000000..2f6979cafcf
--- /dev/null
+++ b/test/boot/vbe_simple.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for vbe-simple bootmeth. All start with 'vbe_simple'
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <image.h>
+#include <memalign.h>
+#include <mmc.h>
+#include <of_live.h>
+#include <vbe.h>
+#include <version_string.h>
+#include <linux/log2.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include <u-boot/crc.h>
+#include "bootstd_common.h"
+
+#define NVDATA_START_BLK	((0x400 + 0x400) / MMC_MAX_BLOCK_LEN)
+#define VERSION_START_BLK	((0x400 + 0x800) / MMC_MAX_BLOCK_LEN)
+#define TEST_VERSION		"U-Boot v2022.04-local2"
+#define TEST_VERNUM		0x00010002
+
+/* Basic test of reading nvdata and updating a fwupd node in the device tree */
+static int vbe_simple_test_base(struct unit_test_state *uts)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
+	const char *version, *bl_version;
+	struct event_ft_fixup fixup;
+	struct udevice *dev, *mmc;
+	struct device_node *np;
+	struct blk_desc *desc;
+	char fdt_buf[0x400];
+	char info[100];
+	int node_ofs;
+	ofnode node;
+	u32 vernum;
+
+	/* Set up the version string */
+	ut_assertok(uclass_get_device(UCLASS_MMC, 1, &mmc));
+	desc = blk_get_by_device(mmc);
+	ut_assertnonnull(desc);
+
+	memset(buf, '\0', MMC_MAX_BLOCK_LEN);
+	strcpy(buf, TEST_VERSION);
+	if (blk_dwrite(desc, VERSION_START_BLK, 1, buf) != 1)
+		return log_msg_ret("write", -EIO);
+
+	/* Set up the nvdata */
+	memset(buf, '\0', MMC_MAX_BLOCK_LEN);
+	buf[1] = ilog2(0x40) << 4 | 1;
+	*(u32 *)(buf + 4) = TEST_VERNUM;
+	buf[0] = crc8(0, buf + 1, 0x3f);
+	if (blk_dwrite(desc, NVDATA_START_BLK, 1, buf) != 1)
+		return log_msg_ret("write", -EIO);
+
+	/* Read the version back */
+	ut_assertok(vbe_find_by_any("firmware0", &dev));
+	ut_assertok(bootmeth_get_state_desc(dev, info, sizeof(info)));
+	ut_asserteq_str("Version: " TEST_VERSION "\nVernum: 1/2", info);
+
+	ut_assertok(fdt_create_empty_tree(fdt_buf, sizeof(fdt_buf)));
+	node_ofs = fdt_add_subnode(fdt_buf, 0, "chosen");
+	ut_assert(node_ofs > 0);
+
+	node_ofs = fdt_add_subnode(fdt_buf, node_ofs, "fwupd");
+	ut_assert(node_ofs > 0);
+
+	node_ofs = fdt_add_subnode(fdt_buf, node_ofs, "firmware0");
+	ut_assert(node_ofs > 0);
+
+	/*
+	 * This can only work on the live tree, since the ofnode interface for
+	 * flat tree assumes that ofnode points to the control FDT
+	 */
+	ut_assertok(unflatten_device_tree(fdt_buf, &np));
+
+	/*
+	 * It would be better to call image_setup_libfdt() here, but that
+	 * function does not allow passing an ofnode. We can pass fdt_buf but
+	 * when it comes to send the evenr, it creates an ofnode that uses the
+	 * control FDT, since it has no way of accessing the live tree created
+	 * here.
+	 *
+	 * Two fix this we need:
+	 * - image_setup_libfdt() is updated to use ofnode
+	 * - ofnode updated to support access to an FDT other than the control
+	 *   FDT. This is partially implemented with live tree, but not with
+	 *   flat tree
+	 */
+	fixup.tree.np = np;
+	ut_assertok(event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup)));
+
+	node = ofnode_path_root(fixup.tree, "/chosen/fwupd/firmware0");
+
+	version = ofnode_read_string(node, "cur-version");
+	ut_assertnonnull(version);
+	ut_asserteq_str(TEST_VERSION, version);
+
+	ut_assertok(ofnode_read_u32(node, "cur-vernum", &vernum));
+	ut_asserteq(TEST_VERNUM, vernum);
+
+	bl_version = ofnode_read_string(node, "bootloader-version");
+	ut_assertnonnull(bl_version);
+	ut_asserteq_str(version_string, bl_version);
+
+	return 0;
+}
+BOOTSTD_TEST(vbe_simple_test_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+	     UT_TESTF_LIVE_TREE);
-- 
2.37.0.170.g444d1eabd0-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 01/19] video: Renname vbe.h to vesa.h
  2022-07-20 16:59 ` [PATCH 01/19] video: Renname vbe.h to vesa.h Simon Glass
@ 2022-07-21  1:25   ` Bin Meng
  2022-07-22  8:59     ` Simon Glass
  0 siblings, 1 reply; 23+ messages in thread
From: Bin Meng @ 2022-07-21  1:25 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Tom Rini, Anatolij Gustschin, Andrew Scull,
	Heinrich Schuchardt

Hi Simon,

On Thu, Jul 21, 2022 at 1:00 AM Simon Glass <sjg@chromium.org> wrote:
>
> We want to use VBE to mean Verfiied Boot for Embedded in U-Boot. Rename

typo: Verified

Is there a doc link to describe the Verified Boot for Embedded ? Just
want to make sure if this acronym is the correct one to replace
another existing and old VBE.

> the existing VBE (Vesa BIOS extensions) to allow this.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>  arch/x86/lib/bios.c             | 2 +-
>  arch/x86/lib/coreboot_table.c   | 2 +-
>  arch/x86/lib/fsp/fsp_graphics.c | 2 +-
>  cmd/elf.c                       | 2 +-
>  drivers/bios_emulator/atibios.c | 2 +-
>  drivers/pci/pci_rom.c           | 2 +-
>  drivers/video/broadwell_igd.c   | 2 +-
>  drivers/video/coreboot.c        | 2 +-
>  drivers/video/efi.c             | 2 +-
>  drivers/video/ivybridge_igd.c   | 2 +-
>  drivers/video/vesa.c            | 2 +-
>  include/{vbe.h => vesa.h}       | 4 ++--
>  lib/elf.c                       | 2 +-
>  13 files changed, 14 insertions(+), 14 deletions(-)
>  rename include/{vbe.h => vesa.h} (98%)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 01/19] video: Renname vbe.h to vesa.h
  2022-07-21  1:25   ` Bin Meng
@ 2022-07-22  8:59     ` Simon Glass
  2022-07-22 12:49       ` Bin Meng
  0 siblings, 1 reply; 23+ messages in thread
From: Simon Glass @ 2022-07-22  8:59 UTC (permalink / raw)
  To: Bin Meng
  Cc: U-Boot Mailing List, Tom Rini, Anatolij Gustschin, Andrew Scull,
	Heinrich Schuchardt

Hi Bin,

On Wed, 20 Jul 2022 at 19:25, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Thu, Jul 21, 2022 at 1:00 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > We want to use VBE to mean Verfiied Boot for Embedded in U-Boot. Rename
>
> typo: Verified
>
> Is there a doc link to describe the Verified Boot for Embedded ? Just
> want to make sure if this acronym is the correct one to replace
> another existing and old VBE.

Yes: https://docs.google.com/document/d/e/2PACX-1vQjXLPWMIyVktaTMf8edHZYDrEvMYD_iNzIj1FgPmKF37fpglAC47Tt5cvPBC5fvTdoK-GA5Zv1wifo/pub

Also this has more links:
https://github.com/fwupd/fwupd/tree/main/plugins/vbe#documentation

>
> > the existing VBE (Vesa BIOS extensions) to allow this.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >

Regards,
Simon

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 01/19] video: Renname vbe.h to vesa.h
  2022-07-22  8:59     ` Simon Glass
@ 2022-07-22 12:49       ` Bin Meng
  0 siblings, 0 replies; 23+ messages in thread
From: Bin Meng @ 2022-07-22 12:49 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Tom Rini, Anatolij Gustschin, Andrew Scull,
	Heinrich Schuchardt

Hi Simon,

On Fri, Jul 22, 2022 at 5:00 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Wed, 20 Jul 2022 at 19:25, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Thu, Jul 21, 2022 at 1:00 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > We want to use VBE to mean Verfiied Boot for Embedded in U-Boot. Rename
> >
> > typo: Verified
> >
> > Is there a doc link to describe the Verified Boot for Embedded ? Just
> > want to make sure if this acronym is the correct one to replace
> > another existing and old VBE.
>
> Yes: https://docs.google.com/document/d/e/2PACX-1vQjXLPWMIyVktaTMf8edHZYDrEvMYD_iNzIj1FgPmKF37fpglAC47Tt5cvPBC5fvTdoK-GA5Zv1wifo/pub
>
> Also this has more links:
> https://github.com/fwupd/fwupd/tree/main/plugins/vbe#documentation
>

Thanks for the links. I suggest we put these links in the commit
message and/or code for reference.

Regards,
Bin

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2022-07-22 12:49 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-20 16:59 [PATCH 00/19] vbe: Verified Boot for Embedded initial support Simon Glass
2022-07-20 16:59 ` [PATCH 01/19] video: Renname vbe.h to vesa.h Simon Glass
2022-07-21  1:25   ` Bin Meng
2022-07-22  8:59     ` Simon Glass
2022-07-22 12:49       ` Bin Meng
2022-07-20 16:59 ` [PATCH 02/19] video: Rename structs and functions to avoid VBE Simon Glass
2022-07-20 16:59 ` [PATCH 03/19] dm: core: Split out the declaration of ofnode Simon Glass
2022-07-20 16:59 ` [PATCH 04/19] ofnode: Add a note about how livetree updates work Simon Glass
2022-07-20 16:59 ` [PATCH 05/19] ofnode: Introduce support for multiple trees Simon Glass
2022-07-20 16:59 ` [PATCH 06/19] dm: core: Move ofnode-writing test to ofnode Simon Glass
2022-07-20 16:59 ` [PATCH 07/19] dm: core: Swap parameters of ofnode_write_prop() Simon Glass
2022-07-20 16:59 ` [PATCH 08/19] dm: core: Tidy up ofnode-writing test Simon Glass
2022-07-20 16:59 ` [PATCH 09/19] dm: core: Prepare for updating the device tree with ofnode Simon Glass
2022-07-20 16:59 ` [PATCH 10/19] ofnode: Allow writing to a flat tree Simon Glass
2022-07-20 16:59 ` [PATCH 11/19] dm: core: Add support for writing u32 with ofnode Simon Glass
2022-07-20 16:59 ` [PATCH 12/19] event: Add an event for device tree fixups Simon Glass
2022-07-20 16:59 ` [PATCH 13/19] read: Support sandbox Simon Glass
2022-07-20 16:59 ` [PATCH 14/19] bootstd: Fix comment in bootmeth test Simon Glass
2022-07-20 16:59 ` [PATCH 15/19] bootstd: Detect empty bootmeth ordering Simon Glass
2022-07-20 16:59 ` [PATCH 16/19] bootstd: Provide a bootmeth method to obtain state info Simon Glass
2022-07-20 16:59 ` [PATCH 17/19] vbe: Add initial support for VBE Simon Glass
2022-07-20 16:59 ` [PATCH 18/19] vbe: Support VBE simple Simon Glass
2022-07-20 16:59 ` [PATCH 19/19] vbe: Add a new vbe command Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.