Add spl_test_firmware_image() to check loadables correctly provided by
spl_load_fit_image().

We create special image with U-Boot, firmware and empty dtb. Then invoke
spl_load_fit_image(), check everything (including dtb) loaded correctly
and then check if loaded dtb contains "/fit-images/u-boot".

Signed-off-by: Nikita Shubin <[email protected]>
---
 test/image/spl_load.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 184 insertions(+)

diff --git a/test/image/spl_load.c b/test/image/spl_load.c
index c43c977f784..9d4f36c61c1 100644
--- a/test/image/spl_load.c
+++ b/test/image/spl_load.c
@@ -275,6 +275,190 @@ size_t create_image(void *dst, enum spl_test_image type,
        return 0;
 }
 
+static int append_fit_node(void *fdt, const char *node_name, const char 
*type_str,
+                          size_t data_offset, struct spl_image_info *image)
+{
+       if (fdt_begin_node(fdt, node_name))
+               return -1;
+       if (fdt_property_u32(fdt, FIT_DATA_OFFSET_PROP, data_offset))
+               return -1;
+       if (fdt_property_string(fdt, FIT_DESC_PROP, image->name))
+               return -1;
+       if (fdt_property_string(fdt, FIT_TYPE_PROP, type_str))
+               return -1;
+       if (fdt_property_string(fdt, FIT_COMP_PROP, "none"))
+               return -1;
+       if (fdt_property_u32(fdt, FIT_DATA_SIZE_PROP, image->size))
+               return -1;
+       if (fdt_property_string(fdt, FIT_OS_PROP,
+                               genimg_get_os_short_name(image->os)))
+               return -1;
+       if (fdt_property_string(fdt, FIT_ARCH_PROP,
+                               genimg_get_arch_short_name(IH_ARCH_DEFAULT)))
+               return -1;
+       if (fdt_property_addr(fdt, FIT_ENTRY_PROP, image->entry_point))
+               return -1;
+       if (fdt_property_addr(fdt, FIT_LOAD_PROP, image->load_addr))
+               return -1;
+       if (fdt_end_node(fdt))
+               return -1;
+       return 0;
+}
+
+static size_t create_firmware_fit(void *dst, struct spl_image_info 
*uboot_image,
+                                 struct spl_image_info *opensbi_image, ulong 
fdt_load_addr,
+                                 size_t *data_offset)
+{
+       size_t prop_size = 1168;
+       size_t total_size = prop_size + uboot_image->size + opensbi_image->size;
+       size_t size = prop_size;
+       size_t fdt_size;
+       char tmp[256];
+       void *fdt;
+
+       if (data_offset)
+               *data_offset = size;
+
+       if (!dst)
+               goto out;
+
+       if (fdt_create(dst, size))
+               return 0;
+       if (fdt_finish_reservemap(dst))
+               return 0;
+       if (fdt_begin_node(dst, ""))
+               return 0;
+       if (fdt_property_u32(dst, FIT_TIMESTAMP_PROP, 0))
+               return 0;
+       if (fdt_property_u32(dst, "#address-cells", ADDRESS_CELLS))
+               return 0;
+       if (fdt_property_string(dst, FIT_DESC_PROP, ""))
+               return 0;
+       if (fdt_begin_node(dst, "images"))
+               return 0;
+
+       /* u-boot image node */
+       if (append_fit_node(dst, "u-boot", "standalone", 0, uboot_image))
+               return 0;
+
+       /* opensbi image node */
+       if (append_fit_node(dst, "opensbi", "firmware", uboot_image->size, 
opensbi_image))
+               return 0;
+
+       /* generate empty dtb */
+       if (fdt_create_empty_tree(&tmp, sizeof(tmp)))
+               return 0;
+       fdt_size = fdt_totalsize(tmp);
+
+       /* empty fdt node */
+       if (fdt_begin_node(dst, "fdt-1"))
+               return 0;
+       if (fdt_property_string(dst, FIT_TYPE_PROP, "flat_dt"))
+               return 0;
+       if (fdt_property_string(dst, FIT_COMP_PROP, "none"))
+               return 0;
+
+       if (fdt_property_addr(dst, FIT_LOAD_PROP, fdt_load_addr))
+               return 0;
+
+       if (fdt_property_placeholder(dst, FIT_DATA_PROP, fdt_size, &fdt))
+               return 0;
+
+       memcpy(fdt, tmp, fdt_size);
+       if (fdt_end_node(dst)) /* fdt-1 */
+               return 0;
+
+       if (fdt_end_node(dst)) /* images */
+               return 0;
+
+       /* configurations node */
+       if (fdt_begin_node(dst, "configurations"))
+               return 0;
+       if (fdt_property_string(dst, FIT_DEFAULT_PROP, "config-1"))
+               return 0;
+       if (fdt_begin_node(dst, "config-1"))
+               return 0;
+       if (fdt_property_string(dst, FIT_DESC_PROP, opensbi_image->name))
+               return 0;
+       if (fdt_property_string(dst, FIT_FIRMWARE_PROP, "opensbi"))
+               return 0;
+       if (fdt_property_string(dst, FIT_LOADABLE_PROP, "u-boot"))
+               return 0;
+       if (fdt_property_string(dst, FIT_FDT_PROP, "fdt-1"))
+               return 0;
+       if (fdt_end_node(dst)) /* config-1 */
+               return 0;
+       if (fdt_end_node(dst)) /* configurations */
+               return 0;
+       if (fdt_end_node(dst)) /* root */
+               return 0;
+       if (fdt_finish(dst))
+               return 0;
+
+       if (fdt_totalsize(dst) > size)
+               return 0;
+
+       fdt_set_totalsize(dst, size);
+
+out:
+       return total_size;
+}
+
+static int spl_test_firmware_image(struct unit_test_state *uts)
+{
+       size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE;
+       ulong uboot_load_addr = CONFIG_TEXT_BASE;
+       ulong firmware_load_addr = ALIGN(uboot_load_addr + data_size, 4096);
+       ulong fdt_load_addr = ALIGN(firmware_load_addr + data_size, 8);
+       struct spl_image_info info_uboot = {
+               .name = "U-Boot",
+               .os = IH_OS_U_BOOT,
+               .size = data_size,
+               .load_addr = CONFIG_TEXT_BASE,
+       }, info_firmware = {
+               .name = "RISC-V OpenSBI",
+               .os = IH_OS_OPENSBI,
+               .size = data_size,
+               .load_addr = firmware_load_addr,
+               .entry_point = firmware_load_addr,
+               .flags = SPL_FIT_FOUND,
+       }, info_read = { };
+       char *data_uboot, *data_firmware;
+       ulong check_addr;
+       int noffset;
+       void *img;
+
+       img_size = create_firmware_fit(NULL, &info_uboot, &info_firmware, 
fdt_load_addr,
+                                      &img_data);
+       ut_assert(img_size);
+       img = calloc(img_size, 1);
+       ut_assertnonnull(img);
+
+       data_uboot = img + img_data;
+       generate_data(data_uboot, data_size, "uboot_image");
+       data_firmware = data_uboot + info_uboot.size;
+       generate_data(data_firmware, info_firmware.size, "firmware_image");
+       ut_asserteq(img_size, create_firmware_fit(img, &info_uboot, 
&info_firmware, fdt_load_addr,
+                   NULL));
+       ut_assertok(spl_load_fit_image(&info_read, img));
+       if (check_image_info(uts, &info_firmware, &info_read))
+               return CMD_RET_FAILURE;
+       ut_asserteq_mem(data_uboot, phys_to_virt(info_uboot.load_addr), 
info_uboot.size);
+       ut_asserteq_mem(data_firmware, phys_to_virt(info_read.load_addr), 
info_read.size);
+
+       /* check loadable and load address recorded successfully in empty dtb */
+       noffset = fdt_path_offset(phys_to_virt(fdt_load_addr), 
"/fit-images/u-boot");
+       ut_assert(noffset > 0);
+
+       ut_assertok(fit_image_get_load(phys_to_virt(fdt_load_addr), noffset, 
&check_addr));
+       ut_asserteq(uboot_load_addr, check_addr);
+
+       free(img);
+       return 0;
+}
+
+SPL_TEST(spl_test_firmware_image, 0);
+
 int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1,
                     struct spl_image_info *info2)
 {

-- 
2.54.0

Reply via email to