Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2018-2021 NXP */ #define LOG_CATEGORY LOGC_ARCH #include <stdlib.h> #include <errno.h> #include <imx_container.h> #include <log.h> #include <mapmem.h> #include <spl.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> #endif __weak bool arch_check_dst_in_secure(void *start, ulong size) { return false; } __weak void *arch_get_container_trampoline(void) { return NULL; } static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, struct spl_load_info *info, struct container_hdr *container, int image_index, ulong container_offset) { struct boot_img_t *images; ulong offset, size; void *buf, *trampoline; if (image_index > container->num_images) { debug("Invalid image number\n"); return NULL; } images = (struct boot_img_t *)((u8 *)container + sizeof(struct container_hdr)); if (!IS_ALIGNED(images[image_index].offset, spl_get_bl_len(info))) { printf("%s: image%d offset not aligned to %u\n", __func__, image_index, spl_get_bl_len(info)); return NULL; } size = ALIGN(images[image_index].size, spl_get_bl_len(info)); offset = images[image_index].offset + container_offset; debug("%s: container: %p offset: %lu size: %lu\n", __func__, container, offset, size); buf = map_sysmem(images[image_index].dst, images[image_index].size); if (IS_ENABLED(CONFIG_SPL_IMX_CONTAINER_USE_TRAMPOLINE) && arch_check_dst_in_secure(buf, size)) { trampoline = arch_get_container_trampoline(); if (!trampoline) { printf("%s: trampoline size is zero\n", __func__); return NULL; } if (info->read(info, offset, size, trampoline) < images[image_index].size) { printf("%s: failed to load image to a trampoline buffer\n", __func__); return NULL; } memcpy(buf, trampoline, images[image_index].size); } else { if (info->read(info, offset, size, buf) < images[image_index].size) { printf("%s: failed to load image to a non-secure region\n", __func__); return NULL; } } #ifdef CONFIG_AHAB_BOOT if (ahab_verify_cntr_image(&images[image_index], image_index)) return NULL; #endif return &images[image_index]; } static int read_auth_container(struct spl_image_info *spl_image, struct spl_load_info *info, ulong offset) { struct container_hdr *container = NULL; u16 length; int i, size, ret = 0; size = ALIGN(CONTAINER_HDR_ALIGNMENT, spl_get_bl_len(info)); /* * It will not override the ATF code, so safe to use it here, * no need malloc */ container = malloc(size); if (!container) return -ENOMEM; debug("%s: container: %p offset: %lu size: %u\n", __func__, container, offset, size); if (info->read(info, offset, size, container) < CONTAINER_HDR_ALIGNMENT) { ret = -EIO; goto end; } if (!valid_container_hdr(container)) { log_err("Wrong container header\n"); ret = -ENOENT; goto end; } if (!container->num_images) { log_err("Wrong container, no image found\n"); ret = -ENOENT; goto end; } length = container->length_lsb + (container->length_msb << 8); debug("Container length %u\n", length); if (length > CONTAINER_HDR_ALIGNMENT) { size = ALIGN(length, spl_get_bl_len(info)); free(container); container = malloc(size); if (!container) return -ENOMEM; debug("%s: container: %p offset: %lu size: %u\n", __func__, container, offset, size); if (info->read(info, offset, size, container) < length) { ret = -EIO; goto end; } } #ifdef CONFIG_AHAB_BOOT ret = ahab_auth_cntr_hdr(container, length); if (ret) goto end_auth; #endif for (i = 0; i < container->num_images; i++) { struct boot_img_t *image = read_auth_image(spl_image, info, container, i, offset); if (!image) { ret = -EINVAL; goto end_auth; } if (i == 0) { spl_image->load_addr = image->dst; spl_image->entry_point = image->entry; } } end_auth: #ifdef CONFIG_AHAB_BOOT ahab_auth_release(); #endif end: free(container); return ret; } int spl_load_imx_container(struct spl_image_info *spl_image, struct spl_load_info *info, ulong offset) { return read_auth_container(spl_image, info, offset); } |