123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <common/debug.h>
- #include <lib/optee_utils.h>
- #include <platform_def.h>
- /*******************************************************************************
- * Check if it is a valid tee header
- * Return true if valid
- * Return false if invalid
- ******************************************************************************/
- static bool tee_validate_header(optee_header_t *header)
- {
- if ((header->magic == TEE_MAGIC_NUM_OPTEE) &&
- (header->version == 2u) &&
- (header->nb_images > 0u) &&
- (header->nb_images <= OPTEE_MAX_NUM_IMAGES)) {
- return true;
- }
- return false;
- }
- bool optee_header_is_valid(uintptr_t header_base)
- {
- return tee_validate_header((optee_header_t *)header_base);
- }
- /*******************************************************************************
- * Parse the OPTEE image
- * Return 0 on success or a negative error code otherwise.
- ******************************************************************************/
- static int parse_optee_image(image_info_t *image_info,
- optee_image_t *image)
- {
- uintptr_t init_load_addr, free_end, requested_end;
- size_t init_size;
- init_load_addr = ((uint64_t)image->load_addr_hi << 32) |
- image->load_addr_lo;
- init_size = image->size;
- /*
- * image->load_addr_hi & image->load_addr_lo set to UINT32_MAX indicate
- * loader decided address; take our pre-mapped area for current image
- * since arm-tf could not allocate memory dynamically
- */
- if ((image->load_addr_hi == UINT32_MAX) &&
- (image->load_addr_lo == UINT32_MAX)) {
- init_load_addr = image_info->image_base;
- }
- /* Check that the default end address doesn't overflow */
- if (check_uptr_overflow(image_info->image_base,
- image_info->image_max_size - 1))
- return -1;
- free_end = image_info->image_base + (image_info->image_max_size - 1);
- /* Check that the image end address doesn't overflow */
- if (check_uptr_overflow(init_load_addr, init_size - 1))
- return -1;
- requested_end = init_load_addr + (init_size - 1);
- /*
- * Check that the requested RAM location is within reserved
- * space for OPTEE.
- */
- if (!((init_load_addr >= image_info->image_base) &&
- (requested_end <= free_end))) {
- WARN("The load address in optee header %p - %p is not in reserved area: %p - %p.\n",
- (void *)init_load_addr,
- (void *)(init_load_addr + init_size),
- (void *)image_info->image_base,
- (void *)(image_info->image_base +
- image_info->image_max_size));
- return -1;
- }
- /*
- * Remove the skip attr from image_info, the image will be loaded.
- * The default attr in image_info is "IMAGE_ATTRIB_SKIP_LOADING", which
- * mean the image will not be loaded. Here, we parse the header image to
- * know that the extra image need to be loaded, so remove the skip attr.
- */
- image_info->h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
- /* Update image base and size of image_info */
- image_info->image_base = init_load_addr;
- image_info->image_size = init_size;
- return 0;
- }
- /*******************************************************************************
- * Parse the OPTEE header
- * Return 0 on success or a negative error code otherwise.
- ******************************************************************************/
- int parse_optee_header(entry_point_info_t *header_ep,
- image_info_t *pager_image_info,
- image_info_t *paged_image_info)
- {
- optee_header_t *header;
- uint32_t num;
- int ret;
- assert(header_ep);
- header = (optee_header_t *)header_ep->pc;
- assert(header);
- /* Print the OPTEE header information */
- INFO("OPTEE ep=0x%x\n", (unsigned int)header_ep->pc);
- INFO("OPTEE header info:\n");
- INFO(" magic=0x%x\n", header->magic);
- INFO(" version=0x%x\n", header->version);
- INFO(" arch=0x%x\n", header->arch);
- INFO(" flags=0x%x\n", header->flags);
- INFO(" nb_images=0x%x\n", header->nb_images);
- /*
- * OPTEE image has 3 types:
- *
- * 1. Plain OPTEE bin without header.
- * Original bin without header, return directly,
- * BL32_EXTRA1_IMAGE_ID and BL32_EXTRA2_IMAGE_ID will be skipped.
- *
- * 2. OPTEE bin with header bin, but no paging.
- * Header available and nb_images = 1, remove skip attr for
- * BL32_EXTRA1_IMAGE_ID. BL32_EXTRA1_IMAGE_ID will be loaded,
- * and BL32_EXTRA2_IMAGE_ID be skipped.
- *
- * 3. OPTEE image with paging support.
- * Header available and nb_images = 2, there are 3 bins: header,
- * pager and pageable. Remove skip attr for BL32_EXTRA1_IMAGE_ID
- * and BL32_EXTRA2_IMAGE_ID to load pager and paged bin.
- */
- if (!tee_validate_header(header)) {
- INFO("Invalid OPTEE header, set legacy mode.\n");
- #ifdef __aarch64__
- header_ep->args.arg0 = MODE_RW_64;
- #else
- header_ep->args.arg0 = MODE_RW_32;
- #endif
- return 0;
- }
- /* Parse OPTEE image */
- for (num = 0U; num < header->nb_images; num++) {
- if (header->optee_image_list[num].image_id ==
- OPTEE_PAGER_IMAGE_ID) {
- ret = parse_optee_image(pager_image_info,
- &header->optee_image_list[num]);
- } else if (header->optee_image_list[num].image_id ==
- OPTEE_PAGED_IMAGE_ID) {
- if (paged_image_info == NULL) {
- if (header->optee_image_list[num].size != 0U) {
- ERROR("Paged image is not supported\n");
- return -1;
- }
- continue;
- } else {
- ret = parse_optee_image(paged_image_info,
- &header->optee_image_list[num]);
- }
- } else {
- ERROR("Parse optee image failed.\n");
- return -1;
- }
- if (ret != 0)
- return -1;
- }
- /*
- * Update "pc" value which should comes from pager image. After the
- * header image is parsed, it will be useless, and the actual
- * execution image after BL31 is pager image.
- */
- header_ep->pc = pager_image_info->image_base;
- /*
- * The paged load address and size are populated in
- * header image arguments so that can be read by the
- * BL32 SPD.
- */
- if (paged_image_info != NULL) {
- header_ep->args.arg1 = paged_image_info->image_base;
- header_ep->args.arg2 = paged_image_info->image_size;
- }
- /* Set OPTEE runtime arch - aarch32/aarch64 */
- if (header->arch == 0) {
- header_ep->args.arg0 = MODE_RW_32;
- } else {
- #ifdef __aarch64__
- header_ep->args.arg0 = MODE_RW_64;
- #else
- ERROR("Cannot boot an AArch64 OP-TEE\n");
- return -1;
- #endif
- }
- return 0;
- }
|