1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH 4 */ 5 6#include <common.h> 7#include <command.h> 8#include <errno.h> 9#include <fdt_support.h> 10#include <log.h> 11#include <malloc.h> 12#include <tee/optee.h> 13 14#include <linux/sizes.h> 15 16#include <test/ut.h> 17#include <test/optee.h> 18#include <test/suites.h> 19 20/* 4k ought to be enough for anybody */ 21#define FDT_COPY_SIZE (4 * SZ_1K) 22 23extern u32 __dtb_test_optee_base_begin; 24extern u32 __dtb_test_optee_optee_begin; 25extern u32 __dtb_test_optee_no_optee_begin; 26 27static void *fdt; 28static bool expect_success; 29 30static int optee_fdt_firmware(struct unit_test_state *uts) 31{ 32 const void *prop; 33 int offs, len; 34 35 offs = fdt_path_offset(fdt, "/firmware/optee"); 36 ut_assert(expect_success ? offs >= 0 : offs < 0); 37 38 /* only continue if we have an optee node */ 39 if (offs < 0) 40 return CMD_RET_SUCCESS; 41 42 prop = fdt_getprop(fdt, offs, "compatible", &len); 43 ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len)); 44 45 prop = fdt_getprop(fdt, offs, "method", &len); 46 ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0); 47 48 return CMD_RET_SUCCESS; 49} 50OPTEE_TEST(optee_fdt_firmware, 0); 51 52static int optee_fdt_protected_memory(struct unit_test_state *uts) 53{ 54 int offs, subnode; 55 bool found; 56 57 offs = fdt_path_offset(fdt, "/firmware/optee"); 58 ut_assert(expect_success ? offs >= 0 : offs < 0); 59 60 /* only continue if we have an optee node */ 61 if (offs < 0) 62 return CMD_RET_SUCCESS; 63 64 /* optee inserts its memory regions as reserved-memory nodes */ 65 offs = fdt_subnode_offset(fdt, 0, "reserved-memory"); 66 ut_assert(offs >= 0); 67 68 subnode = fdt_first_subnode(fdt, offs); 69 ut_assert(subnode); 70 71 found = 0; 72 while (subnode >= 0) { 73 const char *name = fdt_get_name(fdt, subnode, NULL); 74 struct fdt_resource res; 75 76 ut_assert(name); 77 78 /* only handle optee reservations */ 79 if (strncmp(name, "optee", 5)) 80 continue; 81 82 found = true; 83 84 /* check if this subnode has a reg property */ 85 ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res)); 86 subnode = fdt_next_subnode(fdt, subnode); 87 } 88 89 ut_assert(found); 90 91 return CMD_RET_SUCCESS; 92} 93OPTEE_TEST(optee_fdt_protected_memory, 0); 94 95int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 96{ 97 struct unit_test *tests = UNIT_TEST_SUITE_START(optee_test); 98 const int n_ents = UNIT_TEST_SUITE_COUNT(optee_test); 99 struct unit_test_state *uts; 100 void *fdt_optee = &__dtb_test_optee_optee_begin; 101 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin; 102 void *fdt_base = &__dtb_test_optee_base_begin; 103 int ret = -ENOMEM; 104 105 uts = calloc(1, sizeof(*uts)); 106 if (!uts) 107 return -ENOMEM; 108 109 ut_assertok(fdt_check_header(fdt_base)); 110 ut_assertok(fdt_check_header(fdt_optee)); 111 ut_assertok(fdt_check_header(fdt_no_optee)); 112 113 fdt = malloc(FDT_COPY_SIZE); 114 if (!fdt) 115 return ret; 116 117 /* 118 * Resize the FDT to 4k so that we have room to operate on 119 * 120 * (and relocate it since the memory might be mapped 121 * read-only) 122 */ 123 ut_assertok(fdt_open_into(fdt_base, fdt, FDT_COPY_SIZE)); 124 125 /* 126 * (1) Try to copy optee nodes from empty dt. 127 * This should still run successfully. 128 */ 129 ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt)); 130 131 expect_success = false; 132 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); 133 134 /* (2) Try to copy optee nodes from prefilled dt */ 135 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); 136 137 expect_success = true; 138 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); 139 140 /* (3) Try to copy OP-TEE nodes into a already filled DT */ 141 ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE)); 142 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); 143 144 expect_success = true; 145 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); 146 147 free(fdt); 148 return ret; 149} 150