From c20ee0ed070953600b54b16c8b48725348abead5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:50 -0600 Subject: dtoc: Add support for 32 or 64-bit addresses When using 32-bit addresses dtoc works correctly. For 64-bit addresses it does not since it ignores the #address-cells and #size-cells properties. Update the tool to use fdt64_t as the element type for reg properties when either the address or size is larger than one cell. Use the correct value so that C code can obtain the information from the device tree easily. Alos create a new type, fdt_val_t, which is defined to either fdt32_t or fdt64_t depending on the word size of the machine. This type corresponds to fdt_addr_t and fdt_size_t. Unfortunately we cannot just use those types since they are defined to phys_addr_t and phys_size_t which use 'unsigned long' in the 32-bit case, rather than 'unsigned int'. Add tests for the four combinations of address and size values (32/32, 64/64, 32/64, 64/32). Also update existing uses for rk3399 and rk3368 which now need to use the new fdt_val_t type. Signed-off-by: Simon Glass Suggested-by: Heiko Stuebner Reported-by: Kever Yang Reviewed-by: Philipp Tomsich Tested-by: Kever Yang --- include/fdtdec.h | 2 ++ include/regmap.h | 2 +- include/syscon.h | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/fdtdec.h b/include/fdtdec.h index 4a0947c6266..1ba02be8e1b 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -27,10 +27,12 @@ typedef phys_size_t fdt_size_t; #define FDT_ADDR_T_NONE (-1ULL) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) +typedef fdt64_t fdt_val_t; #else #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) +typedef fdt32_t fdt_val_t; #endif /* Information obtained about memory from the FDT */ diff --git a/include/regmap.h b/include/regmap.h index 1eed94e47a3..493a5d8eff8 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -69,7 +69,7 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp); * @count: Number of pairs (e.g. 1 if the regmap has a single entry) * @mapp: Returns allocated map */ -int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count, +int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, struct regmap **mapp); /** diff --git a/include/syscon.h b/include/syscon.h index 34842aa4705..5d52b1cc3c3 100644 --- a/include/syscon.h +++ b/include/syscon.h @@ -8,6 +8,8 @@ #ifndef __SYSCON_H #define __SYSCON_H +#include + /** * struct syscon_uc_info - Information stored by the syscon UCLASS_UCLASS * @@ -28,9 +30,11 @@ struct syscon_ops { * We don't support 64-bit machines. If they are so resource-contrained that * they need to use OF_PLATDATA, something is horribly wrong with the * education of our hardware engineers. + * + * Update: 64-bit is now supported and we have an education crisis. */ struct syscon_base_platdata { - u32 reg[2]; + fdt_val_t reg[2]; }; #endif -- cgit v1.3.1 From 0d15463c0537806f70ea2359e32e4deb8c4766c2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:56 -0600 Subject: dtoc: Rename the phandle struct Rather than naming the phandle struct according to the number of cells it uses (e.g. struct phandle_2_cell) name it according to the number of arguments it has (e.g. struct phandle_1_arg). This is a more intuitive naming. Signed-off-by: Simon Glass Tested-by: Kever Yang --- doc/driver-model/of-plat.txt | 2 +- drivers/clk/clk-uclass.c | 2 +- include/clk.h | 4 ++-- include/dt-structs.h | 7 ++++++- tools/dtoc/dtb_platdata.py | 3 ++- tools/dtoc/test_dtoc.py | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/doc/driver-model/of-plat.txt b/doc/driver-model/of-plat.txt index 3ed8c759d69..732bc34f067 100644 --- a/doc/driver-model/of-plat.txt +++ b/doc/driver-model/of-plat.txt @@ -111,7 +111,7 @@ struct dtd_rockchip_rk3288_dw_mshc { bool cap_sd_highspeed; fdt32_t card_detect_delay; fdt32_t clock_freq_min_max[2]; - struct phandle_2_cell clocks[4]; + struct phandle_1_arg clocks[4]; bool disable_wp; fdt32_t fifo_depth; fdt32_t interrupts[3]; diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index e68d9279b96..8b40326efa2 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -23,7 +23,7 @@ static inline struct clk_ops *clk_dev_ops(struct udevice *dev) #if CONFIG_IS_ENABLED(OF_CONTROL) # if CONFIG_IS_ENABLED(OF_PLATDATA) int clk_get_by_index_platdata(struct udevice *dev, int index, - struct phandle_2_cell *cells, struct clk *clk) + struct phandle_1_arg *cells, struct clk *clk) { int ret; diff --git a/include/clk.h b/include/clk.h index c5988f78a8f..e7ce3e85768 100644 --- a/include/clk.h +++ b/include/clk.h @@ -61,9 +61,9 @@ struct clk { }; #if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK) -struct phandle_2_cell; +struct phandle_1_arg; int clk_get_by_index_platdata(struct udevice *dev, int index, - struct phandle_2_cell *cells, struct clk *clk); + struct phandle_1_arg *cells, struct clk *clk); /** * clock_get_by_index - Get/request a clock by integer index. diff --git a/include/dt-structs.h b/include/dt-structs.h index 0732c442ff8..2ed997115ae 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -9,7 +9,12 @@ /* These structures may only be used in SPL */ #if CONFIG_IS_ENABLED(OF_PLATDATA) -struct phandle_2_cell { +struct phandle_0_arg { + const void *node; + int id[0]; +}; + +struct phandle_1_arg { const void *node; int id; }; diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 001bc4ea668..0234f71b767 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -419,7 +419,8 @@ class DtbPlatdata(object): info = self.get_phandle_argc(prop, structs[name]) if info: # For phandles, include a reference to the target - self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), + struct_name = 'struct phandle_%d_arg' % info.max_args + self.out('\t%s%s[%d]' % (tab_to(2, struct_name), conv_name_to_c(prop.name), len(prop.value) / 2)) else: diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 62460acb7c5..23c4439ed91 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -228,7 +228,7 @@ U_BOOT_DEVICE(pmic_at_9) = { self.assertEqual('''#include #include struct dtd_source { -\tstruct phandle_2_cell clocks[1]; +\tstruct phandle_1_arg clocks[1]; }; struct dtd_target { \tfdt32_t\t\tintval; -- cgit v1.3.1 From bc79617fdfeb4afabb94774885447dd64d7bea6c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:58 -0600 Subject: dtoc: Put phandle args in an array We want to support more than one phandle argument. It makes sense to use an array for this rather than discrete struct members. Adjust the code to support this. Rename the member to 'arg' instead of 'id'. Signed-off-by: Simon Glass Tested-by: Kever Yang --- drivers/clk/clk-uclass.c | 2 +- include/dt-structs.h | 4 ++-- tools/dtoc/dtb_platdata.py | 2 +- tools/dtoc/test_dtoc.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 8b40326efa2..83ba13374c7 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -32,7 +32,7 @@ int clk_get_by_index_platdata(struct udevice *dev, int index, ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev); if (ret) return ret; - clk->id = cells[0].id; + clk->id = cells[0].arg[0]; return 0; } diff --git a/include/dt-structs.h b/include/dt-structs.h index 2ed997115ae..9ab4e2524d1 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -11,12 +11,12 @@ #if CONFIG_IS_ENABLED(OF_PLATDATA) struct phandle_0_arg { const void *node; - int id[0]; + int arg[0]; }; struct phandle_1_arg { const void *node; - int id; + int arg[1]; }; #include #endif diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index c0a3ae692bc..1920a59f821 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -467,7 +467,7 @@ class DtbPlatdata(object): id_num = fdt_util.fdt32_to_cpu(id_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) - vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) + vals.append('{&%s%s, {%d}}' % (VAL_PREFIX, name, id_num)) for val in vals: self.buf('\n\t\t%s,' % val) else: diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index aa617a649c8..fbae927cf8f 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -253,7 +253,7 @@ U_BOOT_DEVICE(phandle_target) = { static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t{&dtv_phandle_target, 1},}, +\t\t{&dtv_phandle_target, {1}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", -- cgit v1.3.1 From 634eba4be060af3bcba51cba2d57d217df897f31 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:59 -0600 Subject: dtoc: Support properties containing multiple phandle values At present dtoc has a very simplistic view of phandles. It assumes that a property has only a single phandle with a single argument (i.e. two cells per property). This is not true in many cases. Enhance the implementation to scan all phandles in a property and to use the correct number of arguments (which can be 0, 1, 2 or more) when generating the C code. For the struct definitions, use a struct which can hold the maximum number of arguments used by the property. Signed-off-by: Simon Glass Tested-by: Kever Yang --- include/dt-structs.h | 5 +++++ tools/dtoc/dtb_platdata.py | 21 ++++++++++++++------- tools/dtoc/dtoc_test_phandle.dts | 17 +++++++++++++++-- tools/dtoc/test_dtoc.py | 27 ++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/dt-structs.h b/include/dt-structs.h index 9ab4e2524d1..76979e73e17 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -18,6 +18,11 @@ struct phandle_1_arg { const void *node; int arg[1]; }; + +struct phandle_2_arg { + const void *node; + int arg[2]; +}; #include #endif diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 1920a59f821..cfca45b0ac9 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -394,11 +394,13 @@ class DtbPlatdata(object): if not isinstance(prop.value, list): prop.value = [prop.value] # Process the list as pairs of (phandle, id) - value_it = iter(prop.value) - for phandle_cell, _ in zip(value_it, value_it): + pos = 0 + for args in info.args: + phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) target_node = self._fdt.phandle_to_node[phandle] node.phandles.add(target_node) + pos += 1 + args def generate_structs(self, structs): @@ -422,7 +424,7 @@ class DtbPlatdata(object): struct_name = 'struct phandle_%d_arg' % info.max_args self.out('\t%s%s[%d]' % (tab_to(2, struct_name), conv_name_to_c(prop.name), - len(prop.value) / 2)) + len(info.args))) else: ptype = TYPE_NAMES[prop.type] self.out('\t%s%s' % (tab_to(2, ptype), @@ -461,13 +463,18 @@ class DtbPlatdata(object): info = self.get_phandle_argc(prop, node.name) if info: # Process the list as pairs of (phandle, id) - value_it = iter(prop.value) - for phandle_cell, id_cell in zip(value_it, value_it): + pos = 0 + for args in info.args: + phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) - id_num = fdt_util.fdt32_to_cpu(id_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) - vals.append('{&%s%s, {%d}}' % (VAL_PREFIX, name, id_num)) + arg_values = [] + for i in range(args): + arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i]))) + pos += 1 + args + vals.append('\t{&%s%s, {%s}}' % (VAL_PREFIX, name, + ', '.join(arg_values))) for val in vals: self.buf('\n\t\t%s,' % val) else: diff --git a/tools/dtoc/dtoc_test_phandle.dts b/tools/dtoc/dtoc_test_phandle.dts index c0a602f2967..ba12b0fe65e 100644 --- a/tools/dtoc/dtoc_test_phandle.dts +++ b/tools/dtoc/dtoc_test_phandle.dts @@ -10,15 +10,28 @@ / { phandle: phandle-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <0>; + #clock-cells = <0>; + }; + + phandle_1: phandle2-target { u-boot,dm-pre-reloc; compatible = "target"; intval = <1>; - #clock-cells = <1>; + #clock-cells = <1>; + }; + phandle_2: phandle3-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <2>; + #clock-cells = <2>; }; phandle-source { u-boot,dm-pre-reloc; compatible = "source"; - clocks = <&phandle 1>; + clocks = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>; }; }; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index fbae927cf8f..cc009b2a256 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -228,7 +228,7 @@ U_BOOT_DEVICE(pmic_at_9) = { self.assertEqual('''#include #include struct dtd_source { -\tstruct phandle_1_arg clocks[1]; +\tstruct phandle_2_arg clocks[4]; }; struct dtd_target { \tfdt32_t\t\tintval; @@ -243,7 +243,7 @@ struct dtd_target { #include static struct dtd_target dtv_phandle_target = { -\t.intval\t\t\t= 0x1, +\t.intval\t\t\t= 0x0, }; U_BOOT_DEVICE(phandle_target) = { \t.name\t\t= "target", @@ -251,9 +251,30 @@ U_BOOT_DEVICE(phandle_target) = { \t.platdata_size\t= sizeof(dtv_phandle_target), }; +static struct dtd_target dtv_phandle2_target = { +\t.intval\t\t\t= 0x1, +}; +U_BOOT_DEVICE(phandle2_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle2_target, +\t.platdata_size\t= sizeof(dtv_phandle2_target), +}; + +static struct dtd_target dtv_phandle3_target = { +\t.intval\t\t\t= 0x2, +}; +U_BOOT_DEVICE(phandle3_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle3_target, +\t.platdata_size\t= sizeof(dtv_phandle3_target), +}; + static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t{&dtv_phandle_target, {1}},}, +\t\t\t{&dtv_phandle_target, {}}, +\t\t\t{&dtv_phandle2_target, {11}}, +\t\t\t{&dtv_phandle3_target, {12, 13}}, +\t\t\t{&dtv_phandle_target, {}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", -- cgit v1.3.1 From b145b45b0ce26028d9ad6ea8277c052c3c87ea56 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:16:00 -0600 Subject: dtoc: Rename the auto-generated dt-structs.h file The filename of the auto-generated file is the same as the file that includes it. Even though the form is in the generated/ subdirectory, this could be confused. Rename the generated file to something that makes it clear it is auto-generated. Signed-off-by: Simon Glass Tested-by: Kever Yang --- include/dt-structs.h | 2 +- scripts/Makefile.spl | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/dt-structs.h b/include/dt-structs.h index 76979e73e17..c0f56951b53 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -23,7 +23,7 @@ struct phandle_2_arg { const void *node; int arg[2]; }; -#include +#include #endif #endif diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index dd8065d87d0..b86ea76bab2 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -257,14 +257,15 @@ cmd_dtoch = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o quiet_cmd_plat = PLAT $@ cmd_plat = $(CC) $(c_flags) -c $< -o $@ -$(obj)/dts/dt-platdata.o: $(obj)/dts/dt-platdata.c include/generated/dt-structs.h +$(obj)/dts/dt-platdata.o: $(obj)/dts/dt-platdata.c \ + include/generated/dt-structs-gen.h $(call if_changed,plat) PHONY += dts_dir dts_dir: $(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts) -include/generated/dt-structs.h: $(obj)/$(SPL_BIN).dtb dts_dir checkdtoc +include/generated/dt-structs-gen.h: $(obj)/$(SPL_BIN).dtb dts_dir checkdtoc $(call if_changed,dtoch) $(obj)/dts/dt-platdata.c: $(obj)/$(SPL_BIN).dtb dts_dir checkdtoc -- cgit v1.3.1 From fc7c31891c40dd1aac2e71e9d1546727ca2b3556 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Mon, 4 Sep 2017 23:12:11 +0300 Subject: fdt: Introduce helper method fdt_overlay_apply_verbose() Introduce fdt_overlay_apply_verbose, a method that applies an overlay but in the case of an error produces a helpful message. In addition if a base tree is found to be missing the __symbols__ node the message will point out that the probable reason is that the base tree was miscompiled without the -@ option. Signed-off-by: Pantelis Antoniou Acked-by: Simon Glass --- common/fdt_support.c | 31 +++++++++++++++++++++++++++++++ include/fdt_support.h | 2 ++ 2 files changed, 33 insertions(+) (limited to 'include') diff --git a/common/fdt_support.c b/common/fdt_support.c index 916a448c11d..f4f9543d547 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1655,3 +1655,34 @@ int fdt_fixup_display(void *blob, const char *path, const char *display) } return toff; } + +#ifdef CONFIG_OF_LIBFDT_OVERLAY +/** + * fdt_overlay_apply_verbose - Apply an overlay with verbose error reporting + * + * @fdt: ptr to device tree + * @fdto: ptr to device tree overlay + * + * Convenience function to apply an overlay and display helpful messages + * in the case of an error + */ +int fdt_overlay_apply_verbose(void *fdt, void *fdto) +{ + int err; + bool has_symbols; + + err = fdt_path_offset(fdt, "/__symbols__"); + has_symbols = err >= 0; + + err = fdt_overlay_apply(fdt, fdto); + if (err < 0) { + printf("failed on fdt_overlay_apply(): %s\n", + fdt_strerror(err)); + if (!has_symbols) { + printf("base fdt does did not have a /__symbols__ node\n"); + printf("make sure you've compiled with -@\n"); + } + } + return err; +} +#endif diff --git a/include/fdt_support.h b/include/fdt_support.h index 5ef78cce6e0..2bca4d78891 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -264,6 +264,8 @@ int arch_fixup_memory_node(void *blob); int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, u32 height, u32 stride, const char *format); +int fdt_overlay_apply_verbose(void *fdt, void *fdto); + #endif /* ifdef CONFIG_OF_LIBFDT */ #ifdef USE_HOSTCC -- cgit v1.3.1 From 169043d826e6b0db3c67a60acbedfc72c43aae5d Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Mon, 4 Sep 2017 23:12:16 +0300 Subject: fit: Introduce methods for applying overlays on fit-load Introduce an overlay based method for constructing a base DT blob to pass to the kernel. It is based on a specific method now to get the FDT from a FIT image named boot_get_fdt_fit(). Signed-off-by: Pantelis Antoniou Acked-by: Simon Glass --- common/image-fdt.c | 7 +-- common/image-fit.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++-- include/image.h | 25 ++++++++ 3 files changed, 205 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/common/image-fdt.c b/common/image-fdt.c index da4d0070815..a2ef4098365 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -356,17 +356,16 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, if (fit_check_format(buf)) { ulong load, len; - fdt_noffset = fit_image_load(images, + fdt_noffset = boot_get_fdt_fit(images, fdt_addr, &fit_uname_fdt, &fit_uname_config, - arch, IH_TYPE_FLATDT, - BOOTSTAGE_ID_FIT_FDT_START, - FIT_LOAD_OPTIONAL, &load, &len); + arch, &load, &len); images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; fdt_addr = load; + break; } else #endif diff --git a/common/image-fit.c b/common/image-fit.c index e75cb649a49..7f17fd1410e 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -19,6 +19,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ @@ -434,6 +435,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } + /* optional load address for FDT */ + if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load)) + printf("%s Load Address: 0x%08lx\n", p, load); + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_entry(fit, image_noffset, &entry); @@ -1454,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) { int noffset, confs_noffset; int len; + const char *s; + char *conf_uname_copy = NULL; confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { @@ -1475,12 +1482,29 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) debug("Found default configuration: '%s'\n", conf_uname); } + s = strchr(conf_uname, '#'); + if (s) { + len = s - conf_uname; + conf_uname_copy = malloc(len + 1); + if (!conf_uname_copy) { + debug("Can't allocate uname copy: '%s'\n", + conf_uname); + return -ENOMEM; + } + memcpy(conf_uname_copy, conf_uname, len); + conf_uname_copy[len] = '\0'; + conf_uname = conf_uname_copy; + } + noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); if (noffset < 0) { debug("Can't get node offset for configuration unit name: '%s' (%s)\n", conf_uname, fdt_strerror(noffset)); } + if (conf_uname_copy) + free(conf_uname_copy); + return noffset; } @@ -1527,7 +1551,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) char *desc; const char *uname; int ret; - int loadables_index; + int fdt_index, loadables_index; /* Mandatory properties */ ret = fit_get_desc(fit, noffset, &desc); @@ -1549,9 +1573,17 @@ void fit_conf_print(const void *fit, int noffset, const char *p) if (uname) printf("%s Init Ramdisk: %s\n", p, uname); - uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); - if (uname) - printf("%s FDT: %s\n", p, uname); + for (fdt_index = 0; + uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP, + fdt_index, NULL), uname; + fdt_index++) { + + if (fdt_index == 0) + printf("%s FDT: ", p); + else + printf("%s ", p); + printf("%s\n", uname); + } uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL); if (uname) @@ -1888,3 +1920,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, return ret; } + +#ifndef USE_HOSTCC +int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp) +{ + int fdt_noffset, cfg_noffset, count; + const void *fit; + const char *fit_uname = NULL; + const char *fit_uname_config = NULL; + char *fit_uname_config_copy = NULL; + char *next_config = NULL; + ulong load, len; +#ifdef CONFIG_OF_LIBFDT_OVERLAY + ulong image_start, image_end; + ulong ovload, ovlen; + const char *uconfig; + const char *uname; + void *base, *ov; + int i, err, noffset, ov_noffset; +#endif + + fit_uname = fit_unamep ? *fit_unamep : NULL; + + if (fit_uname_configp && *fit_uname_configp) { + fit_uname_config_copy = strdup(*fit_uname_configp); + if (!fit_uname_config_copy) + return -ENOMEM; + + next_config = strchr(fit_uname_config_copy, '#'); + if (next_config) + *next_config++ = '\0'; + if (next_config - 1 > fit_uname_config_copy) + fit_uname_config = fit_uname_config_copy; + } + + fdt_noffset = fit_image_load(images, + addr, &fit_uname, &fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); + + if (fdt_noffset < 0) + goto out; + + debug("fit_uname=%s, fit_uname_config=%s\n", + fit_uname ? fit_uname : "", + fit_uname_config ? fit_uname_config : ""); + + fit = map_sysmem(addr, 0); + + cfg_noffset = fit_conf_get_node(fit, fit_uname_config); + + /* single blob, or error just return as well */ + count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP); + if (count <= 1 && !next_config) + goto out; + + /* we need to apply overlays */ + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + image_start = addr; + image_end = addr + fit_get_size(fit); + /* verify that relocation took place by load address not being in fit */ + if (load >= image_start && load < image_end) { + /* check is simplified; fit load checks for overlaps */ + printf("Overlayed FDT requires relocation\n"); + fdt_noffset = -EBADF; + goto out; + } + + base = map_sysmem(load, len); + + /* apply extra configs in FIT first, followed by args */ + for (i = 1; ; i++) { + if (i < count) { + noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, + FIT_FDT_PROP, i); + uname = fit_get_name(fit, noffset, NULL); + uconfig = NULL; + } else { + if (!next_config) + break; + uconfig = next_config; + next_config = strchr(next_config, '#'); + if (next_config) + *next_config++ = '\0'; + uname = NULL; + } + + debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig); + + ov_noffset = fit_image_load(images, + addr, &uname, &uconfig, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_REQUIRED, &ovload, &ovlen); + if (ov_noffset < 0) { + printf("load of %s failed\n", uname); + continue; + } + debug("%s loaded at 0x%08lx len=0x%08lx\n", + uname, ovload, ovlen); + ov = map_sysmem(ovload, ovlen); + + base = map_sysmem(load, len + ovlen); + err = fdt_open_into(base, base, len + ovlen); + if (err < 0) { + printf("failed on fdt_open_into\n"); + fdt_noffset = err; + goto out; + } + /* the verbose method prints out messages on error */ + err = fdt_overlay_apply_verbose(base, ov); + if (err < 0) { + fdt_noffset = err; + goto out; + } + fdt_pack(base); + len = fdt_totalsize(base); + } +#else + printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n"); + fdt_noffset = -EBADF; +#endif + +out: + if (datap) + *datap = load; + if (lenp) + *lenp = len; + if (fit_unamep) + *fit_unamep = fit_uname; + if (fit_uname_configp) + *fit_uname_configp = fit_uname_config; + + if (fit_uname_config_copy) + free(fit_uname_config_copy); + return fdt_noffset; +} +#endif diff --git a/include/image.h b/include/image.h index 339f79c6dc0..af98ed9f25c 100644 --- a/include/image.h +++ b/include/image.h @@ -593,6 +593,31 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, ulong *setup_start, ulong *setup_len); +/** + * boot_get_fdt_fit() - load a DTB from a FIT file (applying overlays) + * + * This deals with all aspects of loading an DTB from a FIT. + * The correct base image based on configuration will be selected, and + * then any overlays specified will be applied (as present in fit_uname_configp). + * + * @param images Boot images structure + * @param addr Address of FIT in memory + * @param fit_unamep On entry this is the requested image name + * (e.g. "kernel@1") or NULL to use the default. On exit + * points to the selected image name + * @param fit_uname_configp On entry this is the requested configuration + * name (e.g. "conf@1") or NULL to use the default. On + * exit points to the selected configuration name. + * @param arch Expected architecture (IH_ARCH_...) + * @param datap Returns address of loaded image + * @param lenp Returns length of loaded image + * + * @return node offset of base image, or -ve error code on error + */ +int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp); + /** * fit_image_load() - load an image from a FIT * -- cgit v1.3.1