From cafe8712e8143ae8e5e5d733d74bc46bffe0be92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:04 -0600 Subject: video: Renname vbe.h to vesa.h We want to use VBE to mean Verfiied Boot for Embedded in U-Boot. Rename the existing VBE (Vesa BIOS extensions) to allow this. Verified Boot for Embedded is documented doc/develop/vbe.rst Signed-off-by: Simon Glass --- 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 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') 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 #include #include -#include +#include #include #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 #include #include -#include +#include #include #include #include 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 #include #include -#include +#include #include #include #include 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 #include #include -#include +#include #include #include 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 #include #include -#include +#include #include 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 #include #include -#include +#include #include #include #include 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 #include #include -#include +#include #include #include -- cgit v1.3.1 From da62e1e861b922866311bcb3e07c69c12e79730d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:05 -0600 Subject: video: Rename structs and functions to avoid VBE 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 --- 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(-) (limited to 'drivers') 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 -- cgit v1.3.1 From 331048471dee5c1d9cede54382256e6cfaee2370 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:08 -0600 Subject: dm: core: Introduce support for multiple trees 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 --- 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(-) (limited to 'drivers') 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 #include #include +#include #include #include #include @@ -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); -- cgit v1.3.1 From be0789a8ee024e685f070dbd8c58736ea3891654 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:10 -0600 Subject: dm: core: Swap parameters of ofnode_write_prop() It is normal for the length to come after the value in libfdt. Follow this same convention with ofnode. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 6 +++--- include/dm/ofnode.h | 6 +++--- test/dm/ofnode.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') 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 */ -- cgit v1.3.1 From 39e42be12b9456e604ac3e228973b1cb1136864c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:13 -0600 Subject: dm: core: Allow writing to a flat tree with ofnode 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 --- 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(-) (limited to 'drivers') 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); -- cgit v1.3.1 From 55f7990bfeb92c172065d5b53c59d5306cc554ca Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:14 -0600 Subject: dm: core: Add support for writing u32 with ofnode Add a new function to write an integer to an ofnode (live tree or flat tree). Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 15 +++++++++++++++ include/dm/ofnode.h | 10 ++++++++++ test/dm/ofnode.c | 16 ++++++++++++++++ 3 files changed, 41 insertions(+) (limited to 'drivers') 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); -- cgit v1.3.1