// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #include #include #include #include #include #include #include #include #include #include #include /* 4k ought to be enough for anybody */ #define FDT_COPY_SIZE (4 * SZ_1K) extern u32 __dtb_test_optee_base_begin; extern u32 __dtb_test_optee_optee_begin; extern u32 __dtb_test_optee_no_optee_begin; static void *fdt; static bool expect_success; static int optee_fdt_firmware(struct unit_test_state *uts) { const void *prop; int offs, len; offs = fdt_path_offset(fdt, "/firmware/optee"); ut_assert(expect_success ? offs >= 0 : offs < 0); /* only continue if we have an optee node */ if (offs < 0) return CMD_RET_SUCCESS; prop = fdt_getprop(fdt, offs, "compatible", &len); ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len)); prop = fdt_getprop(fdt, offs, "method", &len); ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0); return CMD_RET_SUCCESS; } OPTEE_TEST(optee_fdt_firmware, 0); static int optee_fdt_protected_memory(struct unit_test_state *uts) { int offs, subnode; bool found; offs = fdt_path_offset(fdt, "/firmware/optee"); ut_assert(expect_success ? offs >= 0 : offs < 0); /* only continue if we have an optee node */ if (offs < 0) return CMD_RET_SUCCESS; /* optee inserts its memory regions as reserved-memory nodes */ offs = fdt_subnode_offset(fdt, 0, "reserved-memory"); ut_assert(offs >= 0); subnode = fdt_first_subnode(fdt, offs); ut_assert(subnode); found = 0; while (subnode >= 0) { const char *name = fdt_get_name(fdt, subnode, NULL); struct fdt_resource res; ut_assert(name); /* only handle optee reservations */ if (strncmp(name, "optee", 5)) continue; found = true; /* check if this subnode has a reg property */ ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res)); subnode = fdt_next_subnode(fdt, subnode); } ut_assert(found); return CMD_RET_SUCCESS; } OPTEE_TEST(optee_fdt_protected_memory, 0); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(optee_test); const int n_ents = UNIT_TEST_SUITE_COUNT(optee_test); struct unit_test_state *uts; void *fdt_optee = &__dtb_test_optee_optee_begin; void *fdt_no_optee = &__dtb_test_optee_no_optee_begin; void *fdt_base = &__dtb_test_optee_base_begin; int ret = -ENOMEM; uts = calloc(1, sizeof(*uts)); if (!uts) return -ENOMEM; ut_assertok(fdt_check_header(fdt_base)); ut_assertok(fdt_check_header(fdt_optee)); ut_assertok(fdt_check_header(fdt_no_optee)); fdt = malloc(FDT_COPY_SIZE); if (!fdt) return ret; /* * Resize the FDT to 4k so that we have room to operate on * * (and relocate it since the memory might be mapped * read-only) */ ut_assertok(fdt_open_into(fdt_base, fdt, FDT_COPY_SIZE)); /* * (1) Try to copy optee nodes from empty dt. * This should still run successfully. */ ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt)); expect_success = false; ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); /* (2) Try to copy optee nodes from prefilled dt */ ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); expect_success = true; ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); /* (3) Try to copy OP-TEE nodes into a already filled DT */ ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE)); ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); expect_success = true; ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); free(fdt); return ret; }