1 /* 2 * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <common/debug.h> 10 #include <lib/optee_utils.h> 11 12 #include <platform_def.h> 13 14 /* 15 * load_addr_hi and load_addr_lo: image load address. 16 * image_id: 0 - pager, 1 - paged 17 * size: image size in bytes. 18 */ 19 typedef struct optee_image { 20 uint32_t load_addr_hi; 21 uint32_t load_addr_lo; 22 uint32_t image_id; 23 uint32_t size; 24 } optee_image_t; 25 26 #define OPTEE_PAGER_IMAGE_ID 0 27 #define OPTEE_PAGED_IMAGE_ID 1 28 29 #define OPTEE_MAX_NUM_IMAGES 2u 30 31 #define TEE_MAGIC_NUM_OPTEE 0x4554504f 32 /* 33 * magic: header magic number. 34 * version: OPTEE header version: 35 * 1 - not supported 36 * 2 - supported 37 * arch: OPTEE os architecture type: 0 - AARCH32, 1 - AARCH64. 38 * flags: unused currently. 39 * nb_images: number of images. 40 */ 41 typedef struct optee_header { 42 uint32_t magic; 43 uint8_t version; 44 uint8_t arch; 45 uint16_t flags; 46 uint32_t nb_images; 47 optee_image_t optee_image_list[]; 48 } optee_header_t; 49 50 /******************************************************************************* 51 * Check if it is a valid tee header 52 * Return true if valid 53 * Return false if invalid 54 ******************************************************************************/ 55 static bool tee_validate_header(optee_header_t *header) 56 { 57 if ((header->magic == TEE_MAGIC_NUM_OPTEE) && 58 (header->version == 2u) && 59 (header->nb_images > 0u) && 60 (header->nb_images <= OPTEE_MAX_NUM_IMAGES)) { 61 return true; 62 } 63 64 return false; 65 } 66 67 bool optee_header_is_valid(uintptr_t header_base) 68 { 69 return tee_validate_header((optee_header_t *)header_base); 70 } 71 72 /******************************************************************************* 73 * Parse the OPTEE image 74 * Return 0 on success or a negative error code otherwise. 75 ******************************************************************************/ 76 static int parse_optee_image(image_info_t *image_info, 77 optee_image_t *image) 78 { 79 uintptr_t init_load_addr, free_end, requested_end; 80 size_t init_size; 81 82 init_load_addr = ((uint64_t)image->load_addr_hi << 32) | 83 image->load_addr_lo; 84 init_size = image->size; 85 86 /* 87 * image->load_addr_hi & image->load_addr_lo set to UINT32_MAX indicate 88 * loader decided address; take our pre-mapped area for current image 89 * since arm-tf could not allocate memory dynamically 90 */ 91 if ((image->load_addr_hi == UINT32_MAX) && 92 (image->load_addr_lo == UINT32_MAX)) { 93 init_load_addr = image_info->image_base; 94 } 95 96 /* Check that the default end address doesn't overflow */ 97 if (check_uptr_overflow(image_info->image_base, 98 image_info->image_max_size - 1)) 99 return -1; 100 free_end = image_info->image_base + (image_info->image_max_size - 1); 101 102 /* Check that the image end address doesn't overflow */ 103 if (check_uptr_overflow(init_load_addr, init_size - 1)) 104 return -1; 105 requested_end = init_load_addr + (init_size - 1); 106 /* 107 * Check that the requested RAM location is within reserved 108 * space for OPTEE. 109 */ 110 if (!((init_load_addr >= image_info->image_base) && 111 (requested_end <= free_end))) { 112 WARN("The load address in optee header %p - %p is not in reserved area: %p - %p.\n", 113 (void *)init_load_addr, 114 (void *)(init_load_addr + init_size), 115 (void *)image_info->image_base, 116 (void *)(image_info->image_base + 117 image_info->image_max_size)); 118 return -1; 119 } 120 121 /* 122 * Remove the skip attr from image_info, the image will be loaded. 123 * The default attr in image_info is "IMAGE_ATTRIB_SKIP_LOADING", which 124 * mean the image will not be loaded. Here, we parse the header image to 125 * know that the extra image need to be loaded, so remove the skip attr. 126 */ 127 image_info->h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; 128 129 /* Update image base and size of image_info */ 130 image_info->image_base = init_load_addr; 131 image_info->image_size = init_size; 132 133 return 0; 134 } 135 136 /******************************************************************************* 137 * Parse the OPTEE header 138 * Return 0 on success or a negative error code otherwise. 139 ******************************************************************************/ 140 int parse_optee_header(entry_point_info_t *header_ep, 141 image_info_t *pager_image_info, 142 image_info_t *paged_image_info) 143 144 { 145 optee_header_t *header; 146 uint32_t num; 147 int ret; 148 149 assert(header_ep); 150 header = (optee_header_t *)header_ep->pc; 151 assert(header); 152 153 /* Print the OPTEE header information */ 154 INFO("OPTEE ep=0x%x\n", (unsigned int)header_ep->pc); 155 INFO("OPTEE header info:\n"); 156 INFO(" magic=0x%x\n", header->magic); 157 INFO(" version=0x%x\n", header->version); 158 INFO(" arch=0x%x\n", header->arch); 159 INFO(" flags=0x%x\n", header->flags); 160 INFO(" nb_images=0x%x\n", header->nb_images); 161 162 /* 163 * OPTEE image has 3 types: 164 * 165 * 1. Plain OPTEE bin without header. 166 * Original bin without header, return directly, 167 * BL32_EXTRA1_IMAGE_ID and BL32_EXTRA2_IMAGE_ID will be skipped. 168 * 169 * 2. OPTEE bin with header bin, but no paging. 170 * Header available and nb_images = 1, remove skip attr for 171 * BL32_EXTRA1_IMAGE_ID. BL32_EXTRA1_IMAGE_ID will be loaded, 172 * and BL32_EXTRA2_IMAGE_ID be skipped. 173 * 174 * 3. OPTEE image with paging support. 175 * Header available and nb_images = 2, there are 3 bins: header, 176 * pager and pageable. Remove skip attr for BL32_EXTRA1_IMAGE_ID 177 * and BL32_EXTRA2_IMAGE_ID to load pager and paged bin. 178 */ 179 if (!tee_validate_header(header)) { 180 INFO("Invalid OPTEE header, set legacy mode.\n"); 181 #ifdef __aarch64__ 182 header_ep->args.arg0 = MODE_RW_64; 183 #else 184 header_ep->args.arg0 = MODE_RW_32; 185 #endif 186 return 0; 187 } 188 189 /* Parse OPTEE image */ 190 for (num = 0U; num < header->nb_images; num++) { 191 if (header->optee_image_list[num].image_id == 192 OPTEE_PAGER_IMAGE_ID) { 193 ret = parse_optee_image(pager_image_info, 194 &header->optee_image_list[num]); 195 } else if (header->optee_image_list[num].image_id == 196 OPTEE_PAGED_IMAGE_ID) { 197 if (paged_image_info == NULL) { 198 if (header->optee_image_list[num].size != 0U) { 199 ERROR("Paged image is not supported\n"); 200 return -1; 201 } 202 203 continue; 204 } else { 205 ret = parse_optee_image(paged_image_info, 206 &header->optee_image_list[num]); 207 } 208 } else { 209 ERROR("Parse optee image failed.\n"); 210 return -1; 211 } 212 213 if (ret != 0) 214 return -1; 215 } 216 217 /* 218 * Update "pc" value which should comes from pager image. After the 219 * header image is parsed, it will be unuseful, and the actual 220 * execution image after BL31 is pager image. 221 */ 222 header_ep->pc = pager_image_info->image_base; 223 224 /* 225 * The paged load address and size are populated in 226 * header image arguments so that can be read by the 227 * BL32 SPD. 228 */ 229 if (paged_image_info != NULL) { 230 header_ep->args.arg1 = paged_image_info->image_base; 231 header_ep->args.arg2 = paged_image_info->image_size; 232 } 233 234 /* Set OPTEE runtime arch - aarch32/aarch64 */ 235 if (header->arch == 0) { 236 header_ep->args.arg0 = MODE_RW_32; 237 } else { 238 #ifdef __aarch64__ 239 header_ep->args.arg0 = MODE_RW_64; 240 #else 241 ERROR("Cannot boot an AArch64 OP-TEE\n"); 242 return -1; 243 #endif 244 } 245 246 return 0; 247 } 248