diff options
Diffstat (limited to 'test')
30 files changed, 1357 insertions, 361 deletions
diff --git a/test/boot/Makefile b/test/boot/Makefile index 22ed61c8fa..52947580ae 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o obj-$(CONFIG_EXPO) += expo.o +obj-$(CONFIG_CEDIT) += cedit.o ifdef CONFIG_OF_LIVE obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 8a4e090e9b..1ff2320c03 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; +extern U_BOOT_DRIVER(bootmeth_cros); extern U_BOOT_DRIVER(bootmeth_script); static int inject_response(struct unit_test_state *uts) @@ -167,21 +168,22 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts) ut_assert_nextline("Seq Method State Uclass Part Name Filename"); ut_assert_nextlinen("---"); ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); - ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); - ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); - ut_assert_nextline(" 2 extlinux media mmc 0 mmc1.bootdev.whole <NULL>"); + ut_assert_nextline(" 2 extlinux media mmc 0 mmc1.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); - ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole <NULL>"); + ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); ut_assert_nextline(" 4 extlinux 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_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( + " 3f efi media mmc 0 mmc0.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); ut_assert_nextline("No more bootdevs"); ut_assert_nextlinen("---"); @@ -192,10 +194,11 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts) ut_assert_nextline("Showing all bootflows"); ut_assert_nextline("Seq Method State Uclass Part Name Filename"); ut_assert_nextlinen("---"); - ut_assert_nextline(" 0 extlinux 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 extlinux 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_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole "); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); + ut_assert_skip_to_line( + " 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole "); ut_assert_nextlinen("---"); ut_assert_nextline("(64 bootflows, 1 valid)"); ut_assert_console_end(); @@ -384,7 +387,7 @@ static int bootflow_system(struct unit_test_state *uts) console_record_reset_enable(); ut_assertok(run_command("bootflow scan -lH", 0)); ut_assert_skip_to_line( - " 0 efi_mgr ready (none) 0 <NULL> <NULL>"); + " 0 efi_mgr ready (none) 0 <NULL> "); ut_assert_skip_to_line("No more bootdevs"); ut_assert_skip_to_line("(2 bootflows, 2 valid)"); ut_assert_console_end(); @@ -506,21 +509,25 @@ static int bootflow_cmd_boot(struct unit_test_state *uts) BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); /** - * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian + * prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros * * @uts: Unit test state + * @mmc_dev: MMC device to use, e.g. "mmc4" * Returns 0 on success, -ve on failure */ -static int prep_mmc4_bootdev(struct unit_test_state *uts) +static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, + bool bind_cros) { - static const char *order[] = {"mmc2", "mmc1", "mmc4", NULL}; + const char *order[] = {"mmc2", "mmc1", mmc_dev, NULL}; struct udevice *dev, *bootstd; struct bootstd_priv *std; const char **old_order; - ofnode node; + ofnode root, node; /* Enable the mmc4 node since we need a second bootflow */ - node = ofnode_path("/mmc4"); + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, mmc_dev); + ut_assert(ofnode_valid(node)); ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false)); /* Enable the script bootmeth too */ @@ -528,7 +535,14 @@ static int prep_mmc4_bootdev(struct unit_test_state *uts) ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_script), "bootmeth_script", 0, ofnode_null(), &dev)); - /* Change the order to include mmc4 */ + /* Enable the cros bootmeth if needed */ + if (bind_cros) { + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros), + "cros", 0, ofnode_null(), &dev)); + } + + /* Change the order to include the device */ std = dev_get_priv(bootstd); old_order = std->bootdev_order; std->bootdev_order = order; @@ -543,6 +557,19 @@ static int prep_mmc4_bootdev(struct unit_test_state *uts) return 0; } +/** + * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian + * + * @uts: Unit test state + * Returns 0 on success, -ve on failure + */ +static int prep_mmc4_bootdev(struct unit_test_state *uts) +{ + ut_assertok(prep_mmc_bootdev(uts, "mmc4", false)); + + return 0; +} + /* Check 'bootflow menu' to select a bootflow */ static int bootflow_cmd_menu(struct unit_test_state *uts) { @@ -945,3 +972,24 @@ static int bootflow_cmdline(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_cmdline, 0); + +/* Test ChromiumOS bootmeth */ +static int bootflow_cros(struct unit_test_state *uts) +{ + ut_assertok(prep_mmc_bootdev(uts, "mmc5", true)); + ut_assertok(run_command("bootflow list", 0)); + + ut_assert_nextlinen("Showing all"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextlinen(" 0 extlinux"); + ut_assert_nextlinen(" 1 cros ready mmc 2 mmc5.bootdev.part_2 "); + ut_assert_nextlinen(" 2 cros ready mmc 4 mmc5.bootdev.part_4 "); + ut_assert_nextlinen("---"); + ut_assert_skip_to_line("(3 bootflows, 3 valid)"); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cros, 0); diff --git a/test/boot/cedit.c b/test/boot/cedit.c new file mode 100644 index 0000000000..ab2b8a1f9f --- /dev/null +++ b/test/boot/cedit.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <cedit.h> +#include <env.h> +#include <expo.h> +#include <mapmem.h> +#include <dm/ofnode.h> +#include <test/ut.h> +#include "bootstd_common.h" +#include <test/cedit-test.h> +#include "../../boot/scene_internal.h" + +/* Check the cedit command */ +static int cedit_base(struct unit_test_state *uts) +{ + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + struct scene_obj_txt *txt; + struct expo *exp; + struct scene *scn; + + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + console_record_reset_enable(); + + /* + * ^N Move down to second menu + * ^M Open menu + * ^N Move down to second item + * ^M Select item + * \e Quit + */ + console_in_puts("\x0e\x0d\x0e\x0d\e"); + ut_assertok(run_command("cedit run", 0)); + + exp = cur_exp; + scn = expo_lookup_scene_id(exp, exp->scene_id); + ut_assertnonnull(scn); + + menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id)); + + ut_asserteq(ID_AC_ON, menu->cur_item_id); + + return 0; +} +BOOTSTD_TEST(cedit_base, 0); + +/* Check the cedit write_fdt and read_fdt commands */ +static int cedit_fdt(struct unit_test_state *uts) +{ + struct video_priv *vid_priv; + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + ulong addr = 0x1000; + struct ofprop prop; + struct scene *scn; + oftree tree; + ofnode node; + void *fdt; + int i; + + console_record_reset_enable(); + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn)); + + /* get a menu to fiddle with */ + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU); + ut_assertnonnull(menu); + menu->cur_item_id = ID_CPU_SPEED_2; + + ut_assertok(run_command("cedit write_fdt hostfs - settings.dtb", 0)); + ut_assertok(run_commandf("load hostfs - %lx settings.dtb", addr)); + ut_assert_nextlinen("1024 bytes read"); + + fdt = map_sysmem(addr, 1024); + tree = oftree_from_fdt(fdt); + node = ofnode_find_subnode(oftree_root(tree), CEDIT_NODE_NAME); + + ut_asserteq(ID_CPU_SPEED_2, + ofnode_read_u32_default(node, "cpu-speed", 0)); + ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str")); + ut_assert(ofnode_valid(node)); + + /* There should only be 4 properties */ + for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop); + i++, ofnode_next_property(&prop)) + ; + ut_asserteq(4, i); + + ut_assert_console_end(); + + /* reset the expo */ + menu->cur_item_id = ID_CPU_SPEED_1; + + /* load in the settings and make sure they update */ + ut_assertok(run_command("cedit read_fdt hostfs - settings.dtb", 0)); + ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id); + + ut_assertnonnull(menu); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(cedit_fdt, 0); + +/* Check the cedit write_env and read_env commands */ +static int cedit_env(struct unit_test_state *uts) +{ + struct video_priv *vid_priv; + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + struct scene *scn; + + console_record_reset_enable(); + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn)); + + /* get a menu to fiddle with */ + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU); + ut_assertnonnull(menu); + menu->cur_item_id = ID_CPU_SPEED_2; + + ut_assertok(run_command("cedit write_env -v", 0)); + ut_assert_nextlinen("c.cpu-speed=7"); + ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz"); + ut_assert_nextlinen("c.power-loss=10"); + ut_assert_nextlinen("c.power-loss-str=Always Off"); + ut_assert_console_end(); + + ut_asserteq(7, env_get_ulong("c.cpu-speed", 10, 0)); + ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str")); + + /* reset the expo */ + menu->cur_item_id = ID_CPU_SPEED_1; + + ut_assertok(run_command("cedit read_env -v", 0)); + ut_assert_nextlinen("c.cpu-speed=7"); + ut_assert_nextlinen("c.power-loss=10"); + ut_assert_console_end(); + + ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id); + + return 0; +} +BOOTSTD_TEST(cedit_env, 0); + +/* Check the cedit write_cmos and read_cmos commands */ +static int cedit_cmos(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu, *menu2; + struct video_priv *vid_priv; + extern struct expo *cur_exp; + struct scene *scn; + + console_record_reset_enable(); + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn)); + + /* get the menus to fiddle with */ + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU); + ut_assertnonnull(menu); + menu->cur_item_id = ID_CPU_SPEED_2; + + menu2 = scene_obj_find(scn, ID_POWER_LOSS, SCENEOBJT_MENU); + ut_assertnonnull(menu2); + menu2->cur_item_id = ID_AC_MEMORY; + + ut_assertok(run_command("cedit write_cmos -v", 0)); + ut_assert_nextlinen("Write 2 bytes from offset 80 to 84"); + ut_assert_console_end(); + + /* reset the expo */ + menu->cur_item_id = ID_CPU_SPEED_1; + menu2->cur_item_id = ID_AC_OFF; + + ut_assertok(run_command("cedit read_cmos -v", 0)); + ut_assert_nextlinen("Read 2 bytes from offset 80 to 84"); + ut_assert_console_end(); + + ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id); + ut_asserteq(ID_AC_MEMORY, menu2->cur_item_id); + + return 0; +} +BOOTSTD_TEST(cedit_cmos, 0); diff --git a/test/boot/expo.c b/test/boot/expo.c index 3898f853a7..90027409c8 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -289,6 +289,33 @@ static int expo_object_attr(struct unit_test_state *uts) } BOOTSTD_TEST(expo_object_attr, UT_TESTF_DM | UT_TESTF_SCAN_FDT); +/** + * struct test_iter_priv - private data for expo-iterator test + * + * @count: number of scene objects + * @menu_count: number of menus + * @fail_at: item ID at which to return an error + */ +struct test_iter_priv { + int count; + int menu_count; + int fail_at; +}; + +int h_test_iter(struct scene_obj *obj, void *vpriv) +{ + struct test_iter_priv *priv = vpriv; + + if (priv->fail_at == obj->id) + return -EINVAL; + + priv->count++; + if (obj->type == SCENEOBJT_MENU) + priv->menu_count++; + + return 0; +} + /* Check creating a scene with a menu */ static int expo_object_menu(struct unit_test_state *uts) { @@ -296,6 +323,7 @@ static int expo_object_menu(struct unit_test_state *uts) struct scene_menitem *item; int id, label_id, desc_id, key_id, pointer_id, preview_id; struct scene_obj_txt *ptr, *name1, *desc1, *key1, *tit, *prev1; + struct test_iter_priv priv; struct scene *scn; struct expo *exp; ulong start_mem; @@ -382,6 +410,23 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y); ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE); + /* check iterating through scene items */ + memset(&priv, '\0', sizeof(priv)); + ut_assertok(expo_iter_scene_objs(exp, h_test_iter, &priv)); + ut_asserteq(7, priv.count); + ut_asserteq(1, priv.menu_count); + + /* check the iterator failing part way through iteration */ + memset(&priv, '\0', sizeof(priv)); + priv.fail_at = key_id; + ut_asserteq(-EINVAL, expo_iter_scene_objs(exp, h_test_iter, &priv)); + + /* 2 items (preview_id and the menuitem) are after key_id, 7 - 2 = 5 */ + ut_asserteq(5, priv.count); + + /* menu is first, so is still processed */ + ut_asserteq(1, priv.menu_count); + expo_destroy(exp); ut_assertok(ut_check_delta(start_mem)); @@ -669,46 +714,3 @@ static int expo_test_build(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(expo_test_build, UT_TESTF_DM); - -/* Check the cedit command */ -static int expo_cedit(struct unit_test_state *uts) -{ - extern struct expo *cur_exp; - struct scene_obj_menu *menu; - struct scene_obj_txt *txt; - struct expo *exp; - struct scene *scn; - - if (!IS_ENABLED(CONFIG_CMD_CEDIT)) - return -EAGAIN; - - ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); - - console_record_reset_enable(); - - /* - * ^N Move down to second menu - * ^M Open menu - * ^N Move down to second item - * ^M Select item - * \e Quit - */ - console_in_puts("\x0e\x0d\x0e\x0d\e"); - ut_assertok(run_command("cedit run", 0)); - - exp = cur_exp; - scn = expo_lookup_scene_id(exp, exp->scene_id); - ut_assertnonnull(scn); - - menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); - ut_assertnonnull(menu); - - txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); - ut_assertnonnull(txt); - ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id)); - - ut_asserteq(ID_AC_ON, menu->cur_item_id); - - return 0; -} -BOOTSTD_TEST(expo_cedit, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/files/expo_ids.h b/test/boot/files/expo_ids.h new file mode 100644 index 0000000000..027d44bf38 --- /dev/null +++ b/test/boot/files/expo_ids.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Sample expo screen layout (ID numbers) + */ + +enum { + ZERO, + ID_PROMPT, + + ID_SCENE1, + ID_SCENE1_TITLE, + + ID_CPU_SPEED, + ID_CPU_SPEED_TITLE, + ID_CPU_SPEED_1, + ID_CPU_SPEED_2, + ID_CPU_SPEED_3, + + ID_POWER_LOSS, + ID_AC_OFF, + ID_AC_ON, + ID_AC_MEMORY, + + ID_DYNAMIC_START, +}; diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts index 55d5c910dd..cb2a674d9d 100644 --- a/test/boot/files/expo_layout.dts +++ b/test/boot/files/expo_layout.dts @@ -5,28 +5,7 @@ /dts-v1/; -/* -enum { - ZERO, - ID_PROMPT, - - ID_SCENE1, - ID_SCENE1_TITLE, - - ID_CPU_SPEED, - ID_CPU_SPEED_TITLE, - ID_CPU_SPEED_1, - ID_CPU_SPEED_2, - ID_CPU_SPEED_3, - - ID_POWER_LOSS, - ID_AC_OFF, - ID_AC_ON, - ID_AC_MEMORY, - - ID_DYNAMIC_START, -}; -*/ +/* see expo_ids.h for the IDs */ / { dynamic-start = <ID_DYNAMIC_START>; @@ -59,6 +38,9 @@ enum { /* IDs for the menu items */ item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 ID_CPU_SPEED_3>; + + start-bit = <0x400>; + bit-length = <2>; }; power-loss { @@ -70,6 +52,8 @@ enum { "Memory"; item-id = <ID_AC_OFF ID_AC_ON ID_AC_MEMORY>; + start-bit = <0x422>; + bit-length = <2>; }; }; }; diff --git a/test/cmd/Makefile b/test/cmd/Makefile index a3cf983739..6e3d7e919e 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ # # Copyright (c) 2013 Google, Inc +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> ifdef CONFIG_HUSH_PARSER obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o @@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o ifdef CONFIG_SANDBOX obj-$(CONFIG_CMD_READ) += rw.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o +obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o endif obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o obj-$(CONFIG_CMD_WGET) += wget.o diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c new file mode 100644 index 0000000000..9a44a397e8 --- /dev/null +++ b/test/cmd/armffa.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for armffa command + * + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> + * + * Authors: + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> + */ + +#include <common.h> +#include <string.h> +#include <asm/sandbox_arm_ffa.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of 'armffa' command */ +static int dm_test_armffa_cmd(struct unit_test_state *uts) +{ + /* armffa getpart <UUID> */ + ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0)); + + /* armffa ping <ID> */ + ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID)); + + /* armffa devlist */ + ut_assertok(run_command("armffa devlist", 0)); + + return 0; +} + +DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 0cb514490b..0f56409e80 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -201,7 +201,7 @@ static char ut_help_text[] = "\nfdt - fdt command" #endif #ifdef CONFIG_CONSOLE_TRUETYPE - "\nut font - font command" + "\nfont - font command" #endif #ifdef CONFIG_CMD_LOADM "\nloadm - loadm command parameters and loading memory blob" diff --git a/test/dm/Makefile b/test/dm/Makefile index 3799b1ae8f..7ed00733c1 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ # # Copyright (c) 2013 Google, Inc -# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com> +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> obj-$(CONFIG_UT_DM) += test-dm.o @@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o obj-$(CONFIG_ACPI_PMC) += pmc.o obj-$(CONFIG_DM_PMIC) += pmic.o obj-$(CONFIG_DM_PWM) += pwm.o +obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_RAM) += ram.o obj-y += regmap.o diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 77eb524b59..5997bda649 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -221,7 +221,8 @@ static int dm_test_acpi_create_dmar(struct unit_test_state *uts) ut_assertnonnull(cpu); ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP)); ut_asserteq(DMAR_INTR_REMAP, dmar.flags); - ut_asserteq(32 - 1, dmar.host_address_width); + ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, + dmar.host_address_width); return 0; } @@ -277,13 +278,16 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts) */ ut_asserteq_ptr(dmar + 3, ctx.current); ut_asserteq(DMAR_INTR_REMAP, dmar->flags); - ut_asserteq(32 - 1, dmar->host_address_width); + ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, + dmar->host_address_width); ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags); - ut_asserteq(32 - 1, dmar[1].host_address_width); + ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, + dmar[1].host_address_width); ut_asserteq(DMAR_INTR_REMAP, dmar[2].flags); - ut_asserteq(32 - 1, dmar[2].host_address_width); + ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, + dmar[2].host_address_width); /* Check that the pointers were added correctly */ for (i = 0; i < 3; i++) { diff --git a/test/dm/cpu.c b/test/dm/cpu.c index d7e596ee39..5734cd0a92 100644 --- a/test/dm/cpu.c +++ b/test/dm/cpu.c @@ -37,7 +37,7 @@ static int dm_test_cpu(struct unit_test_state *uts) ut_assertok(cpu_get_info(dev, &info)); ut_asserteq(info.cpu_freq, 42 * 42 * 42 * 42 * 42); ut_asserteq(info.features, 0x42424242); - ut_asserteq(info.address_width, 32); + ut_asserteq(info.address_width, IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32); ut_asserteq(cpu_get_count(dev), 42); diff --git a/test/dm/ffa.c b/test/dm/ffa.c new file mode 100644 index 0000000000..6912666bb4 --- /dev/null +++ b/test/dm/ffa.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Functional tests for UCLASS_FFA class + * + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> + * + * Authors: + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <asm/sandbox_arm_ffa.h> +#include <asm/sandbox_arm_ffa_priv.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Functional tests for the UCLASS_FFA */ + +static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts) +{ + struct ffa_sandbox_data func_data; + u32 fwk_version = 0; + + func_data.data0 = &fwk_version; + func_data.data0_size = sizeof(fwk_version); + ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data)); + ut_asserteq(uc_priv->fwk_version, fwk_version); + + return 0; +} + +static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts) +{ + ut_asserteq(0, uc_priv->id); + + return 0; +} + +static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts) +{ + ut_assertnonnull(uc_priv->pair.rxbuf); + ut_assertnonnull(uc_priv->pair.txbuf); + + return 0; +} + +static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts) +{ + ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K || + uc_priv->pair.rxtx_min_pages == RXTX_16K || + uc_priv->pair.rxtx_min_pages == RXTX_64K); + + return 0; +} + +static int check_rxbuf_mapped_flag(u32 queried_func_id, + u8 rxbuf_mapped, + struct unit_test_state *uts) +{ + switch (queried_func_id) { + case FFA_RXTX_MAP: + ut_asserteq(1, rxbuf_mapped); + break; + case FFA_RXTX_UNMAP: + ut_asserteq(0, rxbuf_mapped); + break; + default: + ut_assert(false); + } + + return 0; +} + +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts) +{ + ut_asserteq(0, rxbuf_owned); + + return 0; +} + +static int test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts) +{ + struct ffa_send_direct_data msg; + u8 cnt; + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); + + ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1)); + + for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++) + ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]); + + return 0; +} + +static int test_partitions_and_comms(const char *service_uuid, + struct unit_test_state *uts) +{ + struct ffa_partition_desc *descs; + u32 count, i, j, valid_sps = 0; + struct udevice *dev; + struct ffa_sandbox_data func_data; + struct ffa_partitions *partitions; + + ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); + + /* Get from the driver the count and information of the SPs matching the UUID */ + ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs)); + + /* Make sure the count is correct */ + ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count); + + /* SPs found , verify the partitions information */ + + func_data.data0 = &partitions; + func_data.data0_size = sizeof(struct ffa_partitions *); + ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data)); + + for (i = 0; i < count ; i++) { + for (j = 0; + j < partitions->count; + j++) { + if (descs[i].info.id == + partitions->descs[j].info.id) { + valid_sps++; + ut_asserteq_mem(&descs[i], + &partitions->descs[j], + sizeof(struct ffa_partition_desc)); + /* Send and receive data from the current partition */ + test_ffa_msg_send_direct_req(descs[i].info.id, uts); + } + } + } + + /* Verify expected partitions found in the emulated secure world */ + ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps); + + return 0; +} + +static int dm_test_ffa_ack(struct unit_test_state *uts) +{ + struct ffa_priv *uc_priv; + struct ffa_sandbox_data func_data; + u8 rxbuf_flag = 0; + const char *svc1_uuid = SANDBOX_SERVICE1_UUID; + const char *svc2_uuid = SANDBOX_SERVICE2_UUID; + struct udevice *dev; + + /* Test probing the sandbox FF-A bus */ + ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); + + /* Get a pointer to the sandbox FF-A bus private data */ + uc_priv = dev_get_uclass_priv(dev); + + /* Make sure the private data pointer is retrieved */ + ut_assertnonnull(uc_priv); + + /* Test FFA_VERSION */ + check_fwk_version(uc_priv, uts); + + /* Test FFA_ID_GET */ + check_endpoint_id(uc_priv, uts); + + /* Test FFA_FEATURES */ + check_features(uc_priv, uts); + + /* Test RX/TX buffers */ + check_rxtxbuf(uc_priv, uts); + + /* Test FFA_RXTX_MAP */ + func_data.data0 = &rxbuf_flag; + func_data.data0_size = sizeof(rxbuf_flag); + + rxbuf_flag = 0; + sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data); + check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts); + + /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ + test_partitions_and_comms(svc1_uuid, uts); + + /* Test FFA_RX_RELEASE */ + rxbuf_flag = 1; + sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data); + check_rxbuf_release_flag(rxbuf_flag, uts); + + /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ + test_partitions_and_comms(svc2_uuid, uts); + + /* Test FFA_RX_RELEASE */ + rxbuf_flag = 1; + ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data)); + check_rxbuf_release_flag(rxbuf_flag, uts); + + return 0; +} + +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); + +static int dm_test_ffa_nack(struct unit_test_state *uts) +{ + struct ffa_priv *uc_priv; + const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID; + const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID; + const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID; + struct ffa_send_direct_data msg; + int ret; + u32 count; + u16 part_id = 0; + struct udevice *dev; + struct ffa_partition_desc *descs = NULL; + + /* Test probing the sandbox FF-A bus */ + ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); + + /* Get a pointer to the sandbox FF-A bus private data */ + uc_priv = dev_get_uclass_priv(dev); + + /* Make sure the private data pointer is retrieved */ + ut_assertnonnull(uc_priv); + + /* Query partitions count using invalid arguments */ + ret = ffa_partition_info_get(dev, NULL, NULL, NULL); + ut_asserteq(-EINVAL, ret); + ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL); + ut_asserteq(-EINVAL, ret); + ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL); + ut_asserteq(-EINVAL, ret); + + /* Query partitions count using an invalid UUID string */ + ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs); + ut_asserteq(-EINVAL, ret); + + /* Query partitions count using an invalid UUID (no matching SP) */ + count = 0; + ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs); + ut_asserteq(0, count); + + /* Query partitions data using a valid UUID */ + count = 0; + ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs)); + /* Make sure partitions are detected */ + ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count); + ut_assertnonnull(descs); + + /* Send data to an invalid partition */ + ret = ffa_sync_send_receive(dev, part_id, &msg, 1); + ut_asserteq(-EINVAL, ret); + + /* Send data to a valid partition */ + part_id = uc_priv->partitions.descs[0].info.id; + ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1)); + + return 0; +} + +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); diff --git a/test/dm/host.c b/test/dm/host.c index 355ba7770a..85f21f9839 100644 --- a/test/dm/host.c +++ b/test/dm/host.c @@ -8,6 +8,7 @@ #include <blk.h> #include <dm.h> #include <fs.h> +#include <os.h> #include <sandbox_host.h> #include <asm/test.h> #include <dm/device-internal.h> @@ -15,9 +16,6 @@ #include <test/test.h> #include <test/ut.h> -static const char filename[] = "2MB.ext2.img"; -static const char filename2[] = "1MB.fat32.img"; - /* Basic test of host interface */ static int dm_test_host(struct unit_test_state *uts) { @@ -25,6 +23,7 @@ static int dm_test_host(struct unit_test_state *uts) struct udevice *dev, *part, *chk, *blk; struct host_sb_plat *plat; struct blk_desc *desc; + char fname[256]; ulong mem_start; loff_t actwrite; @@ -40,13 +39,15 @@ static int dm_test_host(struct unit_test_state *uts) ut_assert(label != plat->label); ut_asserteq(0, plat->fd); - /* Attach a file created in test_host.py */ - ut_assertok(host_attach_file(dev, filename)); + /* Attach a file created in test_ut_dm_init */ + ut_assertok(os_persistent_file(fname, sizeof(fname), "2MB.ext2.img")); + + ut_assertok(host_attach_file(dev, fname)); ut_assertok(uclass_first_device_err(UCLASS_HOST, &chk)); ut_asserteq_ptr(chk, dev); - ut_asserteq_str(filename, plat->filename); - ut_assert(filename != plat->filename); + ut_asserteq_str(fname, plat->filename); + ut_assert(fname != plat->filename); ut_assert(plat->fd != 0); /* Get the block device */ @@ -79,12 +80,14 @@ static int dm_test_host_dup(struct unit_test_state *uts) { static char label[] = "test"; struct udevice *dev, *chk; + char fname[256]; ut_asserteq(0, uclass_id_count(UCLASS_HOST)); ut_assertok(host_create_device(label, true, &dev)); - /* Attach a file created in test_host.py */ - ut_assertok(host_attach_file(dev, filename)); + /* Attach a file created in test_ut_dm_init */ + ut_assertok(os_persistent_file(fname, sizeof(fname), "2MB.ext2.img")); + ut_assertok(host_attach_file(dev, fname)); ut_assertok(uclass_first_device_err(UCLASS_HOST, &chk)); ut_asserteq_ptr(chk, dev); ut_asserteq(1, uclass_id_count(UCLASS_HOST)); @@ -92,8 +95,10 @@ static int dm_test_host_dup(struct unit_test_state *uts) /* Create another device with the same label (should remove old one) */ ut_assertok(host_create_device(label, true, &dev)); - /* Attach a different file created in test_host.py */ - ut_assertok(host_attach_file(dev, filename2)); + /* Attach a different file created in test_ut_dm_init */ + ut_assertok(os_persistent_file(fname, sizeof(fname), "1MB.fat32.img")); + ut_assertok(host_attach_file(dev, fname)); + ut_assertok(uclass_first_device_err(UCLASS_HOST, &chk)); ut_asserteq_ptr(chk, dev); @@ -109,6 +114,7 @@ static int dm_test_cmd_host(struct unit_test_state *uts) { struct udevice *dev, *blk; struct blk_desc *desc; + char fname[256]; console_record_reset(); @@ -117,7 +123,8 @@ static int dm_test_cmd_host(struct unit_test_state *uts) ut_assert_nextline("dev blocks label path"); ut_assert_console_end(); - ut_assertok(run_commandf("host bind -r test2 %s", filename)); + ut_assertok(os_persistent_file(fname, sizeof(fname), "2MB.ext2.img")); + ut_assertok(run_commandf("host bind -r test2 %s", fname)); /* Check the -r flag worked */ ut_assertok(uclass_first_device_err(UCLASS_HOST, &dev)); @@ -127,10 +134,11 @@ static int dm_test_cmd_host(struct unit_test_state *uts) ut_assertok(run_command("host info", 0)); ut_assert_nextline("dev blocks label path"); - ut_assert_nextline(" 0 4096 test2 2MB.ext2.img"); + ut_assert_nextlinen(" 0 4096 test2"); ut_assert_console_end(); - ut_assertok(run_commandf("host bind fat %s", filename2)); + ut_assertok(os_persistent_file(fname, sizeof(fname), "1MB.fat32.img")); + ut_assertok(run_commandf("host bind fat %s", fname)); /* Check it is not removable (no '-r') */ ut_assertok(uclass_next_device_err(&dev)); @@ -140,8 +148,8 @@ static int dm_test_cmd_host(struct unit_test_state *uts) ut_assertok(run_command("host info", 0)); ut_assert_nextline("dev blocks label path"); - ut_assert_nextline(" 0 4096 test2 2MB.ext2.img"); - ut_assert_nextline(" 1 2048 fat 1MB.fat32.img"); + ut_assert_nextlinen(" 0 4096 test2"); + ut_assert_nextlinen(" 1 2048 fat"); ut_assert_console_end(); ut_asserteq(1, run_command("host info test", 0)); @@ -150,7 +158,7 @@ static int dm_test_cmd_host(struct unit_test_state *uts) ut_assertok(run_command("host info fat", 0)); ut_assert_nextline("dev blocks label path"); - ut_assert_nextline(" 1 2048 fat 1MB.fat32.img"); + ut_assert_nextlinen(" 1 2048 fat"); ut_assert_console_end(); /* check 'host dev' */ @@ -187,7 +195,7 @@ static int dm_test_cmd_host(struct unit_test_state *uts) ut_assertok(run_command("host info", 0)); ut_assert_nextline("dev blocks label path"); - ut_assert_nextline(" 1 2048 fat 1MB.fat32.img"); + ut_assert_nextlinen(" 1 2048 fat"); ut_assert_console_end(); return 0; diff --git a/test/dm/pinmux.c b/test/dm/pinmux.c index 265df4ccb9..6880b2d2cd 100644 --- a/test/dm/pinmux.c +++ b/test/dm/pinmux.c @@ -15,6 +15,16 @@ static char buf[64]; ut_asserteq_str(expected, (char *)&buf); \ } while (0) +#define test_muxing_regaddr(selector, regaddr, expected) do { \ + char estr[64] = { 0 }; \ + if (IS_ENABLED(CONFIG_PHYS_64BIT)) \ + snprintf(estr, sizeof(estr), "0x%016llx %s", (u64)regaddr, expected); \ + else \ + snprintf(estr, sizeof(estr), "0x%08x %s", (u32)regaddr, expected); \ + ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(estr, (char *)&buf); \ +} while (0) + #define test_name(selector, expected) do { \ ut_assertok(pinctrl_get_pin_name(dev, selector, buf, sizeof(buf))); \ ut_asserteq_str(expected, (char *)&buf); \ @@ -79,14 +89,14 @@ static int dm_test_pinctrl_single(struct unit_test_state *uts) test_name(0, "PIN0"); test_name(141, "PIN141"); test_name(142, "Error"); - test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); - test_muxing(18, "0x00000048 0x00000006 pinmux_pwm_pins"); - test_muxing(28, "0x00000070 0x00000030 pinmux_uart0_pins"); - test_muxing(29, "0x00000074 0x00000000 pinmux_uart0_pins"); - test_muxing(100, "0x00000190 0x0000000c pinmux_spi0_pins"); - test_muxing(101, "0x00000194 0x0000000c pinmux_spi0_pins"); - test_muxing(102, "0x00000198 0x00000023 pinmux_spi0_pins"); - test_muxing(103, "0x0000019c 0x0000000c pinmux_spi0_pins"); + test_muxing_regaddr(0, 0x0, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(18, 0x48, "0x00000006 pinmux_pwm_pins"); + test_muxing_regaddr(28, 0x70, "0x00000030 pinmux_uart0_pins"); + test_muxing_regaddr(29, 0x74, "0x00000000 pinmux_uart0_pins"); + test_muxing_regaddr(100, 0x190, "0x0000000c pinmux_spi0_pins"); + test_muxing_regaddr(101, 0x194, "0x0000000c pinmux_spi0_pins"); + test_muxing_regaddr(102, 0x198, "0x00000023 pinmux_spi0_pins"); + test_muxing_regaddr(103, 0x19c, "0x0000000c pinmux_spi0_pins"); ret = pinctrl_get_pin_muxing(dev, 142, buf, sizeof(buf)); ut_asserteq(-EINVAL, ret); ut_assertok(uclass_get_device_by_name(UCLASS_I2C, "i2c@0", &dev)); @@ -97,39 +107,39 @@ static int dm_test_pinctrl_single(struct unit_test_state *uts) test_name(0, "PIN0"); test_name(159, "PIN159"); test_name(160, "Error"); - test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); - test_muxing(34, "0x00000010 0x00000200 pinmux_i2c0_pins"); - test_muxing(35, "0x00000010 0x00002000 pinmux_i2c0_pins"); - test_muxing(130, "0x00000040 0x00000200 pinmux_lcd_pins"); - test_muxing(131, "0x00000040 0x00002000 pinmux_lcd_pins"); - test_muxing(132, "0x00000040 0x00020000 pinmux_lcd_pins"); - test_muxing(133, "0x00000040 0x00200000 pinmux_lcd_pins"); - test_muxing(134, "0x00000040 0x02000000 pinmux_lcd_pins"); - test_muxing(135, "0x00000040 0x20000000 pinmux_lcd_pins"); - test_muxing(136, "0x00000044 0x00000002 pinmux_lcd_pins"); - test_muxing(137, "0x00000044 0x00000020 pinmux_lcd_pins"); - test_muxing(138, "0x00000044 0x00000200 pinmux_lcd_pins"); - test_muxing(139, "0x00000044 0x00002000 pinmux_lcd_pins"); - test_muxing(140, "0x00000044 0x00020000 pinmux_lcd_pins"); - test_muxing(141, "0x00000044 0x00200000 pinmux_lcd_pins"); - test_muxing(142, "0x00000044 0x02000000 pinmux_lcd_pins"); - test_muxing(143, "0x00000044 0x20000000 pinmux_lcd_pins"); - test_muxing(144, "0x00000048 0x00000002 pinmux_lcd_pins"); - test_muxing(145, "0x00000048 0x00000020 pinmux_lcd_pins"); - test_muxing(146, "0x00000048 0x00000000 UNCLAIMED"); - test_muxing(147, "0x00000048 0x00000000 UNCLAIMED"); - test_muxing(148, "0x00000048 0x00000000 UNCLAIMED"); - test_muxing(149, "0x00000048 0x00000000 UNCLAIMED"); - test_muxing(150, "0x00000048 0x02000000 pinmux_lcd_pins"); - test_muxing(151, "0x00000048 0x00000000 UNCLAIMED"); - test_muxing(152, "0x0000004c 0x00000002 pinmux_lcd_pins"); - test_muxing(153, "0x0000004c 0x00000020 pinmux_lcd_pins"); - test_muxing(154, "0x0000004c 0x00000000 UNCLAIMED"); - test_muxing(155, "0x0000004c 0x00000000 UNCLAIMED"); - test_muxing(156, "0x0000004c 0x00000000 UNCLAIMED"); - test_muxing(157, "0x0000004c 0x00000000 UNCLAIMED"); - test_muxing(158, "0x0000004c 0x02000000 pinmux_lcd_pins"); - test_muxing(159, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing_regaddr(0, 0x0, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(34, 0x10, "0x00000200 pinmux_i2c0_pins"); + test_muxing_regaddr(35, 0x10, "0x00002000 pinmux_i2c0_pins"); + test_muxing_regaddr(130, 0x40, "0x00000200 pinmux_lcd_pins"); + test_muxing_regaddr(131, 0x40, "0x00002000 pinmux_lcd_pins"); + test_muxing_regaddr(132, 0x40, "0x00020000 pinmux_lcd_pins"); + test_muxing_regaddr(133, 0x40, "0x00200000 pinmux_lcd_pins"); + test_muxing_regaddr(134, 0x40, "0x02000000 pinmux_lcd_pins"); + test_muxing_regaddr(135, 0x40, "0x20000000 pinmux_lcd_pins"); + test_muxing_regaddr(136, 0x44, "0x00000002 pinmux_lcd_pins"); + test_muxing_regaddr(137, 0x44, "0x00000020 pinmux_lcd_pins"); + test_muxing_regaddr(138, 0x44, "0x00000200 pinmux_lcd_pins"); + test_muxing_regaddr(139, 0x44, "0x00002000 pinmux_lcd_pins"); + test_muxing_regaddr(140, 0x44, "0x00020000 pinmux_lcd_pins"); + test_muxing_regaddr(141, 0x44, "0x00200000 pinmux_lcd_pins"); + test_muxing_regaddr(142, 0x44, "0x02000000 pinmux_lcd_pins"); + test_muxing_regaddr(143, 0x44, "0x20000000 pinmux_lcd_pins"); + test_muxing_regaddr(144, 0x48, "0x00000002 pinmux_lcd_pins"); + test_muxing_regaddr(145, 0x48, "0x00000020 pinmux_lcd_pins"); + test_muxing_regaddr(146, 0x48, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(147, 0x48, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(148, 0x48, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(149, 0x48, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(150, 0x48, "0x02000000 pinmux_lcd_pins"); + test_muxing_regaddr(151, 0x48, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(152, 0x4c, "0x00000002 pinmux_lcd_pins"); + test_muxing_regaddr(153, 0x4c, "0x00000020 pinmux_lcd_pins"); + test_muxing_regaddr(154, 0x4c, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(155, 0x4c, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(156, 0x4c, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(157, 0x4c, "0x00000000 UNCLAIMED"); + test_muxing_regaddr(158, 0x4c, "0x02000000 pinmux_lcd_pins"); + test_muxing_regaddr(159, 0x4c, "0x00000000 UNCLAIMED"); ret = pinctrl_get_pin_muxing(dev, 160, buf, sizeof(buf)); ut_asserteq(-EINVAL, ret); return 0; diff --git a/test/lib/Makefile b/test/lib/Makefile index e0bd9e04e8..e75a263e6a 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o obj-$(CONFIG_GETOPT) += getopt.o obj-$(CONFIG_CRC8) += test_crc8.o obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o +obj-$(CONFIG_LIB_UUID) += uuid.o else obj-$(CONFIG_SANDBOX) += kconfig_spl.o endif diff --git a/test/lib/abuf.c b/test/lib/abuf.c index 42ee4c1755..42803b20e2 100644 --- a/test/lib/abuf.c +++ b/test/lib/abuf.c @@ -155,6 +155,31 @@ static int lib_test_abuf_realloc_size(struct unit_test_state *uts) } LIB_TEST(lib_test_abuf_realloc_size, 0); +/* Test abuf_realloc_inc() */ +static int lib_test_abuf_realloc_inc(struct unit_test_state *uts) +{ + struct abuf buf; + ulong start; + + start = ut_check_free(); + + abuf_init(&buf); + ut_asserteq(0, buf.size); + ut_asserteq(false, buf.alloced); + + abuf_realloc_inc(&buf, 20); + ut_asserteq(20, buf.size); + ut_asserteq(true, buf.alloced); + + abuf_uninit(&buf); + + /* Check for memory leaks */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_abuf_realloc_inc, 0); + /* Test handling of buffers that are too large */ static int lib_test_abuf_large(struct unit_test_state *uts) { diff --git a/test/lib/asn1.c b/test/lib/asn1.c index 8661fdd306..a66cdd77df 100644 --- a/test/lib/asn1.c +++ b/test/lib/asn1.c @@ -120,7 +120,7 @@ static int lib_asn1_x509(struct unit_test_state *uts) cert = x509_cert_parse(cert_data, cert_data_len); - ut_assertf(cert != NULL, "decoding failed\n"); + ut_assertf(!IS_ERR(cert), "decoding failed\n"); ut_assertf(!strcmp(cert->subject, "Linaro: Tester"), "subject doesn't match\n"); ut_assertf(!strcmp(cert->issuer, "Linaro: Tester"), @@ -313,7 +313,7 @@ static int lib_asn1_pkcs7(struct unit_test_state *uts) pkcs7 = pkcs7_parse_message(image_pk7, image_pk7_len); - ut_assertf(pkcs7 != NULL, "decoding failed\n"); + ut_assertf(!IS_ERR(pkcs7), "decoding failed\n"); ut_assertf(pkcs7->data_len == 104, "signature size doesn't match\n"); ut_assertf(pkcs7->signed_infos != NULL, "sign-info doesn't exist\n"); ut_assertf(pkcs7->signed_infos->msgdigest_len == 32, diff --git a/test/lib/strlcat.c b/test/lib/strlcat.c index a0ec037388..d8453fe78e 100644 --- a/test/lib/strlcat.c +++ b/test/lib/strlcat.c @@ -43,11 +43,11 @@ static int do_test_strlcat(struct unit_test_state *uts, int line, size_t align1, s2[i] = 32 + 23 * i % (127 - 32); s2[len2 - 1] = '\0'; - expected = len2 < n ? min(len1 + len2 - 1, n) : n; + expected = min(strlen(s2), n) + strlen(s1); actual = strlcat(s2, s1, n); if (expected != actual) { ut_failf(uts, __FILE__, line, __func__, - "strlcat(s2, s1, 2) == len2 < n ? min(len1 + len2, n) : n", + "strlcat(s2, s1, n) == min(len2, n) + len1", "Expected %#zx (%zd), got %#zx (%zd)", expected, expected, actual, actual); return CMD_RET_FAILURE; diff --git a/test/lib/uuid.c b/test/lib/uuid.c new file mode 100644 index 0000000000..e24331a136 --- /dev/null +++ b/test/lib/uuid.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Functional tests for UCLASS_FFA class + * + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> + * + * Authors: + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> + */ + +#include <common.h> +#include <uuid.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.h> + +/* test UUID */ +#define TEST_SVC_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" + +#define UUID_SIZE 16 + +/* The UUID binary data (little-endian format) */ +static const u8 ref_uuid_bin[UUID_SIZE] = { + 0x33, 0xd5, 0x32, 0xed, + 0x09, 0x42, 0xe6, 0x99, + 0x72, 0x2d, 0xc0, 0x9c, + 0xa7, 0x98, 0xd9, 0xcd +}; + +static int lib_test_uuid_to_le(struct unit_test_state *uts) +{ + const char *uuid_str = TEST_SVC_UUID; + u8 ret_uuid_bin[UUID_SIZE] = {0}; + + ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin)); + ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE); + + return 0; +} + +LIB_TEST(lib_test_uuid_to_le, 0); diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py index 17151bcd08..9882ddb1da 100644 --- a/test/py/tests/fs_helper.py +++ b/test/py/tests/fs_helper.py @@ -9,7 +9,7 @@ import re import os from subprocess import call, check_call, check_output, CalledProcessError -def mk_fs(config, fs_type, size, prefix, use_src_dir=False): +def mk_fs(config, fs_type, size, prefix): """Create a file system volume Args: @@ -17,14 +17,12 @@ def mk_fs(config, fs_type, size, prefix, use_src_dir=False): fs_type (str): File system type, e.g. 'ext4' size (int): Size of file system in bytes prefix (str): Prefix string of volume's file name - use_src_dir (bool): true to put the file in the source directory Raises: CalledProcessError: if any error occurs when creating the filesystem """ fs_img = f'{prefix}.{fs_type}.img' - fs_img = os.path.join(config.source_dir if use_src_dir - else config.persistent_data_dir, fs_img) + fs_img = os.path.join(config.persistent_data_dir, fs_img) if fs_type == 'fat16': mkfs_opt = '-F 16' diff --git a/test/py/tests/test_efi_capsule/capsule_gen_binman.dts b/test/py/tests/test_efi_capsule/capsule_gen_binman.dts new file mode 100644 index 0000000000..e8a1858509 --- /dev/null +++ b/test/py/tests/test_efi_capsule/capsule_gen_binman.dts @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Devicetree for capsule generation through binman + */ + +/dts-v1/; + +#include <sandbox_efi_capsule.h> + +/ { + binman: binman { + multiple-images; + }; +}; + +&binman { + itb { + filename = UBOOT_FIT_IMAGE; + + fit { + description = "Automatic U-Boot environment update"; + #address-cells = <2>; + + images { + u-boot-bin { + description = "U-Boot binary on SPI Flash"; + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + text { + text = "u-boot:New"; + }; + + hash-1 { + algo = "sha1"; + }; + }; + u-boot-env { + description = "U-Boot environment on SPI Flash"; + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + text { + text = "u-boot-env:New"; + }; + + hash-1 { + algo = "sha1"; + }; + }; + }; + }; + }; + + capsule1 { + filename = "Test01"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule2 { + filename = "Test02"; + efi-capsule { + image-index = <0x2>; + image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID; + + text { + text = "u-boot-env:New"; + }; + }; + }; + + capsule3 { + filename = "Test03"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_INCORRECT_GUID; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule4 { + filename = "Test04"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule5 { + filename = "Test05"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_INCORRECT_GUID; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule6 { + filename = "Test101"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x5>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule7 { + filename = "Test102"; + efi-capsule { + image-index = <0x2>; + fw-version = <0xa>; + image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID; + + text { + text = "u-boot-env:New"; + }; + }; + }; + + capsule8 { + filename = "Test103"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule9 { + filename = "Test104"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x5>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule10 { + filename = "Test105"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule11 { + filename = "Test11"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule12 { + filename = "Test12"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + private-key = CAPSULE_INVAL_KEY; + public-key-cert = CAPSULE_INVAL_PUB_KEY; + monotonic-count = <0x1>; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule13 { + filename = "Test13"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule14 { + filename = "Test14"; + efi-capsule { + image-index = <0x1>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + private-key = CAPSULE_INVAL_KEY; + public-key-cert = CAPSULE_INVAL_PUB_KEY; + monotonic-count = <0x1>; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule15 { + filename = "Test111"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x5>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule16 { + filename = "Test112"; + efi-capsule { + image-index = <0x2>; + fw-version = <0xa>; + image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + text { + text = "u-boot-env:New"; + }; + }; + }; + + capsule17 { + filename = "Test113"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + text { + text = "u-boot:New"; + }; + }; + }; + + capsule18 { + filename = "Test114"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x5>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; + + capsule19 { + filename = "Test115"; + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + image-guid = SANDBOX_FIT_IMAGE_GUID; + private-key = CAPSULE_PRIV_KEY; + public-key-cert = CAPSULE_PUB_KEY; + monotonic-count = <0x1>; + + blob { + filename = UBOOT_FIT_IMAGE; + }; + }; + }; +}; diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index 054be1ee97..dd41da9284 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -4,6 +4,8 @@ """Fixture for UEFI capsule test.""" +import os + from subprocess import call, check_call, CalledProcessError import pytest from capsule_defs import CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR, EFITOOLS_PATH @@ -34,40 +36,31 @@ def efi_capsule_data(request, u_boot_config): capsule_auth_enabled = u_boot_config.buildconfig.get( 'config_efi_capsule_authenticate') + key_dir = u_boot_config.source_dir + '/board/sandbox' if capsule_auth_enabled: - # Create private key (SIGNER.key) and certificate (SIGNER.crt) - check_call('cd %s; ' - 'openssl req -x509 -sha256 -newkey rsa:2048 ' - '-subj /CN=TEST_SIGNER/ -keyout SIGNER.key ' - '-out SIGNER.crt -nodes -days 365' - % data_dir, shell=True) - check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl' - % (data_dir, EFITOOLS_PATH), shell=True) - - # Update dtb adding capsule certificate - check_call('cd %s; ' - 'cp %s/test/py/tests/test_efi_capsule/signature.dts .' - % (data_dir, u_boot_config.source_dir), shell=True) - check_call('cd %s; ' - 'dtc -@ -I dts -O dtb -o signature.dtbo signature.dts; ' - 'fdtoverlay -i %s/arch/sandbox/dts/test.dtb ' - '-o test_sig.dtb signature.dtbo' - % (data_dir, u_boot_config.build_dir), shell=True) + # Get the keys from the board directory + check_call('cp %s/capsule_priv_key_good.key %s/SIGNER.key' + % (key_dir, data_dir), shell=True) + check_call('cp %s/capsule_pub_key_good.crt %s/SIGNER.crt' + % (key_dir, data_dir), shell=True) + check_call('cp %s/capsule_pub_esl_good.esl %s/SIGNER.esl' + % (key_dir, data_dir), shell=True) - # Create *malicious* private key (SIGNER2.key) and certificate - # (SIGNER2.crt) - check_call('cd %s; ' - 'openssl req -x509 -sha256 -newkey rsa:2048 ' - '-subj /CN=TEST_SIGNER/ -keyout SIGNER2.key ' - '-out SIGNER2.crt -nodes -days 365' - % data_dir, shell=True) + check_call('cp %s/capsule_priv_key_bad.key %s/SIGNER2.key' + % (key_dir, data_dir), shell=True) + check_call('cp %s/capsule_pub_key_bad.crt %s/SIGNER2.crt' + % (key_dir, data_dir), shell=True) # Update dtb to add the version information check_call('cd %s; ' 'cp %s/test/py/tests/test_efi_capsule/version.dts .' % (data_dir, u_boot_config.source_dir), shell=True) + if capsule_auth_enabled: check_call('cd %s; ' + 'cp %s/arch/sandbox/dts/test.dtb test_sig.dtb' + % (data_dir, u_boot_config.build_dir), shell=True) + check_call('cd %s; ' 'dtc -@ -I dts -O dtb -o version.dtbo version.dts; ' 'fdtoverlay -i test_sig.dtb ' '-o test_ver.dtb version.dtbo' @@ -79,132 +72,20 @@ def efi_capsule_data(request, u_boot_config): '-o test_ver.dtb version.dtbo' % (data_dir, u_boot_config.build_dir), shell=True) - # Create capsule files # two regions: one for u-boot.bin and the other for u-boot.env check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old > u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir, shell=True) - check_call('sed -e \"s?BINFILE1?u-boot.bin.new?\" -e \"s?BINFILE2?u-boot.env.new?\" %s/test/py/tests/test_efi_capsule/uboot_bin_env.its > %s/uboot_bin_env.its' % - (u_boot_config.source_dir, data_dir), - shell=True) - check_call('cd %s; %s/tools/mkimage -f uboot_bin_env.its uboot_bin_env.itb' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test01' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 2 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test02' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 u-boot.bin.new Test03' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 5 ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test101' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 2 --fw-version 10 ' - '--guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test102' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 2 ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test103' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 5 ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test104' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 2 ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test105' % - (data_dir, u_boot_config.build_dir), - shell=True) - if capsule_auth_enabled: - # raw firmware signed with proper key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test11' - % (data_dir, u_boot_config.build_dir), - shell=True) - # raw firmware signed with *mal* key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER2.key ' - '--certificate SIGNER2.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test12' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with proper key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test13' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with *mal* key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER2.key ' - '--certificate SIGNER2.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test14' - % (data_dir, u_boot_config.build_dir), - shell=True) - # raw firmware signed with proper key with version information - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--fw-version 5 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test111' - % (data_dir, u_boot_config.build_dir), - shell=True) - # raw firmware signed with proper key with version information - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 2 --monotonic-count 1 ' - '--fw-version 10 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 ' - 'u-boot.env.new Test112' - % (data_dir, u_boot_config.build_dir), - shell=True) - # raw firmware signed with proper key with lower version information - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--fw-version 2 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test113' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with proper key with version information - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--fw-version 5 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test114' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with proper key with lower version information - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--fw-version 2 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test115' - % (data_dir, u_boot_config.build_dir), - shell=True) + pythonpath = os.environ.get('PYTHONPATH', '') + os.environ['PYTHONPATH'] = pythonpath + ':' + '%s/scripts/dtc/pylibfdt' % u_boot_config.build_dir + check_call('cd %s; ' + 'cc -E -I %s/include -x assembler-with-cpp -o capsule_gen_tmp.dts %s/test/py/tests/test_efi_capsule/capsule_gen_binman.dts; ' + 'dtc -I dts -O dtb capsule_gen_tmp.dts -o capsule_binman.dtb;' + % (data_dir, u_boot_config.source_dir, u_boot_config.source_dir), shell=True) + check_call('cd %s; ' + './tools/binman/binman --toolpath %s/tools build -u -d %s/capsule_binman.dtb -O %s -m --allow-missing -I %s -I ./board/sandbox -I ./arch/sandbox/dts' + % (u_boot_config.source_dir, u_boot_config.build_dir, data_dir, data_dir, data_dir), shell=True) + os.environ['PYTHONPATH'] = pythonpath # Create a disk image with EFI system partition check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' % diff --git a/test/py/tests/test_efi_capsule/signature.dts b/test/py/tests/test_efi_capsule/signature.dts deleted file mode 100644 index 078cfc76c9..0000000000 --- a/test/py/tests/test_efi_capsule/signature.dts +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/dts-v1/; -/plugin/; - -&{/} { - signature { - capsule-key = /incbin/("SIGNER.esl"); - }; -}; diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its deleted file mode 100644 index fc65907481..0000000000 --- a/test/py/tests/test_efi_capsule/uboot_bin_env.its +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Automatic software update for U-Boot - * Make sure the flashing addresses ('load' prop) is correct for your board! - */ - -/dts-v1/; - -/ { - description = "Automatic U-Boot environment update"; - #address-cells = <2>; - - images { - u-boot-bin { - description = "U-Boot binary on SPI Flash"; - data = /incbin/("BINFILE1"); - compression = "none"; - type = "firmware"; - arch = "sandbox"; - load = <0>; - hash-1 { - algo = "sha1"; - }; - }; - u-boot-env { - description = "U-Boot environment on SPI Flash"; - data = /incbin/("BINFILE2"); - compression = "none"; - type = "firmware"; - arch = "sandbox"; - load = <0>; - hash-1 { - algo = "sha1"; - }; - }; - }; -}; diff --git a/test/py/tests/test_semihosting/conftest.py b/test/py/tests/test_semihosting/conftest.py new file mode 100644 index 0000000000..b00d8f4ea9 --- /dev/null +++ b/test/py/tests/test_semihosting/conftest.py @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +"""Fixture for semihosting command test +""" + +import os +import pytest + +@pytest.fixture(scope='session') +def semihosting_data(u_boot_config): + """Set up a file system to be used in semihosting tests + + Args: + u_boot_config -- U-Boot configuration. + """ + image_path = u_boot_config.persistent_data_dir + '/semihosting.txt' + + with open(image_path, 'w', encoding = 'utf-8') as file: + file.write('Das U-Boot\n') + + yield image_path + + os.remove(image_path) diff --git a/test/py/tests/test_semihosting/test_hostfs.py b/test/py/tests/test_semihosting/test_hostfs.py new file mode 100644 index 0000000000..51f6fa7702 --- /dev/null +++ b/test/py/tests/test_semihosting/test_hostfs.py @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0+ + +""" Unit test for semihosting +""" + +import pytest + +@pytest.mark.buildconfigspec('semihosting') +def test_semihosting_hostfs(u_boot_console, semihosting_data): + """ Unit test for semihosting + + Args: + u_boot_console -- U-Boot console + semihosting_data -- Path to the disk image used for testing. + """ + response = u_boot_console.run_command( + f'load hostfs - $loadaddr {semihosting_data}') + assert '11 bytes read' in response + + response = u_boot_console.run_command( + 'crc32 $loadaddr $filesize') + assert '==> 60cfccfc' in response + + u_boot_console.run_command( + f'save hostfs - $loadaddr {semihosting_data} 11 11') + + response = u_boot_console.run_command( + f'load hostfs - $loadaddr {semihosting_data} 4 13') + assert '4 bytes read' in response + + response = u_boot_console.run_command( + 'crc32 $loadaddr $filesize') + assert '==> e29063ea' in response diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py index ac3e95925e..ad2250920d 100644 --- a/test/py/tests/test_trace.py +++ b/test/py/tests/test_trace.py @@ -61,7 +61,7 @@ def collect_trace(cons): # Read out the trace data addr = 0x02000000 - size = 0x01000000 + size = 0x02000000 out = cons.run_command(f'trace calls {addr:x} {size:x}') print(out) fname = os.path.join(TMPDIR, 'trace') diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index aa1d477cd5..82932a662b 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +import collections import getpass import gzip import os @@ -282,13 +283,155 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) copy_prepared_image(cons, mmc_dev, fname) +def setup_cros_image(cons): + """Create a 20MB disk image with ChromiumOS partitions""" + Partition = collections.namedtuple('part', 'start,size,name') + parts = {} + disk_data = None + + def pack_kernel(cons, arch, kern, dummy): + """Pack a kernel containing some fake data + + Args: + cons (ConsoleBase): Console to use + arch (str): Architecture to use ('x86' or 'arm') + kern (str): Filename containing kernel + dummy (str): Dummy filename to use for config and bootloader + + Return: + bytes: Packed-kernel data + """ + kern_part = os.path.join(cons.config.result_dir, 'kern-part-{arch}.bin') + u_boot_utils.run_and_log( + cons, + f'futility vbutil_kernel --pack {kern_part} ' + '--keyblock doc/chromium/files/devkeys/kernel.keyblock ' + '--signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk ' + f'--version 1 --config {dummy} --bootloader {dummy} ' + f'--vmlinuz {kern}') + + with open(kern_part, 'rb') as inf: + kern_part_data = inf.read() + return kern_part_data + + def set_part_data(partnum, data): + """Set the contents of a disk partition + + This updates disk_data by putting data in the right place + + Args: + partnum (int): Partition number to set + data (bytes): Data for that partition + """ + nonlocal disk_data + + start = parts[partnum].start * sect_size + disk_data = disk_data[:start] + data + disk_data[start + len(data):] + + mmc_dev = 5 + fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + #mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') + #mkdir_cond(mnt) + u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + + uuid_state = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7' + uuid_kern = 'fe3a2a5d-4f32-41a7-b725-accc3285a309' + uuid_root = '3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec' + uuid_rwfw = 'cab6e88e-abf3-4102-a07a-d4bb9be3c1d3' + uuid_reserved = '2e0a753d-9e48-43b0-8337-b15192cb1b5e' + uuid_efi = 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b' + + ptr = 40 + + # Number of sectors in 1MB + sect_size = 512 + sect_1mb = (1 << 20) // sect_size + + required_parts = [ + {'num': 0xb, 'label':'RWFW', 'type': uuid_rwfw, 'size': '1'}, + {'num': 6, 'label':'KERN_C', 'type': uuid_kern, 'size': '1'}, + {'num': 7, 'label':'ROOT_C', 'type': uuid_root, 'size': '1'}, + {'num': 9, 'label':'reserved', 'type': uuid_reserved, 'size': '1'}, + {'num': 0xa, 'label':'reserved', 'type': uuid_reserved, 'size': '1'}, + + {'num': 2, 'label':'KERN_A', 'type': uuid_kern, 'size': '1M'}, + {'num': 4, 'label':'KERN_B', 'type': uuid_kern, 'size': '1M'}, + + {'num': 8, 'label':'OEM', 'type': uuid_state, 'size': '1M'}, + {'num': 0xc, 'label':'EFI-SYSTEM', 'type': uuid_efi, 'size': '1M'}, + + {'num': 5, 'label':'ROOT_B', 'type': uuid_root, 'size': '1'}, + {'num': 3, 'label':'ROOT_A', 'type': uuid_root, 'size': '1'}, + {'num': 1, 'label':'STATE', 'type': uuid_state, 'size': '1M'}, + ] + + for part in required_parts: + size_str = part['size'] + if 'M' in size_str: + size = int(size_str[:-1]) * sect_1mb + else: + size = int(size_str) + u_boot_utils.run_and_log( + cons, + f"cgpt add -i {part['num']} -b {ptr} -s {size} -t {part['type']} {fname}") + ptr += size + + u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + '''We expect something like this: + 8239 2048 1 Basic data + 45 2048 2 ChromeOS kernel + 8238 1 3 ChromeOS rootfs + 2093 2048 4 ChromeOS kernel + 8237 1 5 ChromeOS rootfs + 41 1 6 ChromeOS kernel + 42 1 7 ChromeOS rootfs + 4141 2048 8 Basic data + 43 1 9 ChromeOS reserved + 44 1 10 ChromeOS reserved + 40 1 11 ChromeOS firmware + 6189 2048 12 EFI System Partition + ''' + + # Create a dict (indexed by partition number) containing the above info + for line in out.splitlines(): + start, size, num, name = line.split(maxsplit=3) + parts[int(num)] = Partition(int(start), int(size), name) + + dummy = os.path.join(cons.config.result_dir, 'dummy.txt') + with open(dummy, 'wb') as outf: + outf.write(b'dummy\n') + + # For now we just use dummy kernels. This limits testing to just detecting + # a signed kernel. We could add support for the x86 data structures so that + # testing could cover getting the cmdline, setup.bin and other pieces. + kern = os.path.join(cons.config.result_dir, 'kern.bin') + with open(kern, 'wb') as outf: + outf.write(b'kernel\n') + + with open(fname, 'rb') as inf: + disk_data = inf.read() + + # put x86 kernel in partition 2 and arm one in partition 4 + set_part_data(2, pack_kernel(cons, 'x86', kern, dummy)) + set_part_data(4, pack_kernel(cons, 'arm', kern, dummy)) + + with open(fname, 'wb') as outf: + outf.write(disk_data) + + return fname + + def setup_cedit_file(cons): infname = os.path.join(cons.config.source_dir, 'test/boot/files/expo_layout.dts') + inhname = os.path.join(cons.config.source_dir, + 'test/boot/files/expo_ids.h') expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py') outfname = 'cedit.dtb' u_boot_utils.run_and_log( - cons, f'{expo_tool} -e {infname} -l {infname} -o {outfname}') + cons, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}') @pytest.mark.buildconfigspec('ut_dm') @@ -317,10 +460,8 @@ def test_ut_dm_init(u_boot_console): u_boot_utils.run_and_log( u_boot_console, f'sfdisk {fn}', stdin=b'type=83') - fs_helper.mk_fs(u_boot_console.config, 'ext2', 0x200000, '2MB', - use_src_dir=True) - fs_helper.mk_fs(u_boot_console.config, 'fat32', 0x100000, '1MB', - use_src_dir=True) + fs_helper.mk_fs(u_boot_console.config, 'ext2', 0x200000, '2MB') + fs_helper.mk_fs(u_boot_console.config, 'fat32', 0x100000, '1MB') @pytest.mark.buildconfigspec('cmd_bootflow') def test_ut_dm_init_bootstd(u_boot_console): @@ -329,6 +470,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootflow_image(u_boot_console) setup_bootmenu_image(u_boot_console) setup_cedit_file(u_boot_console) + setup_cros_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() diff --git a/test/unicode_ut.c b/test/unicode_ut.c index b27d7116b9..1d0d90c2d7 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -807,28 +807,28 @@ static int unicode_test_u16_strlcat(struct unit_test_state *uts) /* dest and src are empty string */ memset(buf, 0, sizeof(buf)); - ret = u16_strlcat(buf, &null_src, sizeof(buf)); - ut_asserteq(1, ret); + ret = u16_strlcat(buf, &null_src, ARRAY_SIZE(buf)); + ut_asserteq(0, ret); /* dest is empty string */ memset(buf, 0, sizeof(buf)); - ret = u16_strlcat(buf, src, sizeof(buf)); - ut_asserteq(5, ret); + ret = u16_strlcat(buf, src, ARRAY_SIZE(buf)); + ut_asserteq(4, ret); ut_assert(!unicode_test_u16_strcmp(buf, src, 40)); /* src is empty string */ memset(buf, 0xCD, (sizeof(buf) - sizeof(u16))); buf[39] = 0; memcpy(buf, dest, sizeof(dest)); - ret = u16_strlcat(buf, &null_src, sizeof(buf)); - ut_asserteq(6, ret); + ret = u16_strlcat(buf, &null_src, ARRAY_SIZE(buf)); + ut_asserteq(5, ret); ut_assert(!unicode_test_u16_strcmp(buf, dest, 40)); for (i = 0; i <= 40; i++) { memset(buf, 0xCD, (sizeof(buf) - sizeof(u16))); buf[39] = 0; memcpy(buf, dest, sizeof(dest)); - expected = 10; + expected = min(5, i) + 4; ret = u16_strlcat(buf, src, i); ut_asserteq(expected, ret); if (i <= 6) { |