1 /* 2 * (C) Copyright 2020 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <boot_rkimg.h> 9 #include <malloc.h> 10 #include <misc.h> 11 #ifdef CONFIG_SPL_BUILD 12 #include <spl.h> 13 #endif 14 #include <lzma/LzmaTools.h> 15 #include <optee_include/OpteeClientInterface.h> 16 #include <optee_include/tee_api_defines.h> 17 #include <asm/arch/rk_atags.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 #if CONFIG_IS_ENABLED(FIT) 22 23 /* 24 * Override __weak board_fit_image_post_process() for SPL & U-Boot proper. 25 */ 26 #if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS) 27 28 __weak void rk_board_fit_image_post_process(void *fit, int node, ulong *load_addr, 29 ulong **src_addr, size_t *src_len) 30 { 31 } 32 33 #define FIT_UNCOMP_HASH_NODENAME "digest" 34 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZMA) 35 static int fit_image_get_uncomp_digest(const void *fit, int parent_noffset) 36 { 37 const char *name; 38 int noffset; 39 40 fdt_for_each_subnode(noffset, fit, parent_noffset) { 41 name = fit_get_name(fit, noffset, NULL); 42 if (!strncmp(name, FIT_UNCOMP_HASH_NODENAME, 43 strlen(FIT_UNCOMP_HASH_NODENAME))) { 44 return noffset; 45 } 46 } 47 48 return -EINVAL; 49 } 50 51 static int fit_image_check_uncomp_hash(const void *fit, int parent_noffset, 52 const void *data, size_t size) 53 { 54 char *err_msgp; 55 int noffset; 56 57 noffset = fit_image_get_uncomp_digest(fit, parent_noffset); 58 if (noffset > 0) 59 return fit_image_check_hash(fit, noffset, data, size, &err_msgp); 60 61 return 0; 62 } 63 64 static int fit_decomp_image(void *fit, int node, ulong *load_addr, 65 ulong **src_addr, size_t *src_len, void *spec) 66 { 67 u64 len = *src_len; 68 int ret = -ENOSYS; 69 u8 comp; 70 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 71 u32 flags = 0; 72 #endif 73 74 if (fit_image_get_comp(fit, node, &comp)) 75 return 0; 76 77 if (comp != IH_COMP_GZIP && comp != IH_COMP_LZMA) 78 return 0; 79 80 #ifndef CONFIG_SPL_BUILD 81 /* 82 * U-Boot: 83 * handled late in bootm_decomp_image() 84 */ 85 if (fit_image_check_type(fit, node, IH_TYPE_KERNEL)) 86 return 0; 87 #elif defined(CONFIG_SPL_MTD_SUPPORT) && defined(CONFIG_SPL_MISC_DECOMPRESS) && \ 88 defined(CONFIG_SPL_KERNEL_BOOT) 89 /* 90 * SPL Thunder-boot policty on spi-nand: 91 * enable and use interrupt status as a sync signal for 92 * kernel to poll that whether ramdisk decompress is done. 93 */ 94 struct spl_load_info *info = spec; 95 struct blk_desc *desc; 96 97 if (info && info->dev) { 98 desc = info->dev; 99 if ((desc->if_type == IF_TYPE_MTD) && 100 (desc->devnum == BLK_MTD_SPI_NAND) && 101 fit_image_check_type(fit, node, IH_TYPE_RAMDISK)) { 102 flags |= DCOMP_FLG_IRQ_ONESHOT; 103 } 104 } 105 #endif 106 if (comp == IH_COMP_LZMA) { 107 #if CONFIG_IS_ENABLED(LZMA) 108 SizeT lzma_len = ALIGN(len, FIT_MAX_SPL_IMAGE_SZ); 109 ret = lzmaBuffToBuffDecompress((uchar *)(*load_addr), &lzma_len, 110 (uchar *)(*src_addr), *src_len); 111 len = lzma_len; 112 #endif 113 } else if (comp == IH_COMP_GZIP) { 114 /* 115 * For smaller spl size, we don't use misc_decompress_process() 116 * inside the gunzip(). 117 */ 118 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 119 const void *prop; 120 bool sync = true; 121 122 if (fit_image_get_uncomp_digest(fit, node) < 0) 123 sync = false; 124 125 ret = misc_decompress_process((ulong)(*load_addr), 126 (ulong)(*src_addr), (ulong)(*src_len), 127 DECOM_GZIP, sync, &len, flags); 128 /* mark for misc_decompress_cleanup() */ 129 prop = fdt_getprop(fit, node, "decomp-async", NULL); 130 if (prop) 131 misc_decompress_async(comp); 132 else 133 misc_decompress_sync(comp); 134 #else 135 #if CONFIG_IS_ENABLED(GZIP) 136 ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ), 137 (void *)(*src_addr), (void *)(&len)); 138 #endif 139 #endif 140 } 141 142 if (ret) { 143 printf("%s: decompress error, ret=%d\n", 144 fdt_get_name(fit, node, NULL), ret); 145 return ret; 146 } 147 148 /* check uncompressed data hash */ 149 ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len); 150 if (!ret) 151 puts("+ "); 152 else 153 return ret; 154 155 *src_addr = (ulong *)*load_addr; 156 *src_len = len; 157 158 return 0; 159 } 160 #endif 161 162 void board_fit_image_post_process(void *fit, int node, ulong *load_addr, 163 ulong **src_addr, size_t *src_len, void *spec) 164 { 165 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) || CONFIG_IS_ENABLED(LZMA) 166 fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec); 167 #endif 168 169 #if CONFIG_IS_ENABLED(USING_KERNEL_DTB) 170 /* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */ 171 if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) { 172 if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) { 173 *src_addr = (void *)gd->fdt_blob; 174 *src_len = (size_t)fdt_totalsize(gd->fdt_blob); 175 } else { 176 printf(" Using fdt from load-in fdt\n"); 177 } 178 } 179 #endif 180 181 #ifndef CONFIG_SPL_BUILD 182 if (fit_image_check_type(fit, node, IH_TYPE_FIRMWARE)) { 183 const char *uname; 184 char *old, *new; 185 size_t len; 186 187 uname = fdt_get_name(fit, node, NULL); 188 if (strcmp("bootargs", uname)) 189 return; 190 191 old = env_get("bootargs"); 192 if (!old) 193 return; 194 195 len = strlen(old) + (*src_len) + 2; 196 new = calloc(1, len); 197 if (new) { 198 strcpy(new, old); 199 strcat(new, " "); 200 strcat(new, (char *)(*src_addr)); 201 env_set("bootargs", new); 202 free(new); 203 } 204 205 } 206 #endif 207 rk_board_fit_image_post_process(fit, node, load_addr, src_addr, src_len); 208 } 209 #endif /* FIT_IMAGE_POST_PROCESS */ 210 /* 211 * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper. 212 */ 213 #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT) 214 int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd, 215 uint32_t *fit_index, uint32_t *otp_index) 216 { 217 int conf_noffset, ret; 218 219 conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */ 220 if (conf_noffset < 0) 221 return conf_noffset; 222 223 ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index); 224 if (ret) { 225 printf("Failed to get rollback-index from FIT, ret=%d\n", ret); 226 return ret; 227 } 228 229 ret = fit_read_otp_rollback_index(*fit_index, otp_index); 230 if (ret) { 231 printf("Failed to get rollback-index from otp, ret=%d\n", ret); 232 return ret; 233 } 234 235 /* Should update rollback index to otp ! */ 236 if (*otp_index < *fit_index) 237 gd->rollback_index = *fit_index; 238 239 return 0; 240 } 241 #endif 242 243 /* 244 * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper. 245 */ 246 int fit_board_verify_required_sigs(void) 247 { 248 uint8_t vboot = 0; 249 250 #ifdef CONFIG_SPL_BUILD 251 #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP) 252 struct udevice *dev; 253 254 dev = misc_otp_get_device(OTP_S); 255 if (!dev) 256 return 1; 257 258 if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) { 259 printf("Can't read verified-boot flag\n"); 260 return 1; 261 } 262 263 vboot = (vboot == 0xff); 264 #endif 265 #else /* !CONFIG_SPL_BUILD */ 266 #if defined(CONFIG_OPTEE_CLIENT) 267 int ret; 268 269 ret = trusty_read_vbootkey_enable_flag(&vboot); 270 if (ret) { 271 printf("Can't read verified-boot flag, ret=%d\n", ret); 272 return 1; 273 } 274 #elif defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) 275 struct tag *t; 276 277 t = atags_get_tag(ATAG_PUB_KEY); 278 if (t && t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED) 279 vboot = 1; 280 #endif 281 #endif /* CONFIG_SPL_BUILD*/ 282 283 printf("## Verified-boot: %d\n", vboot); 284 285 return vboot; 286 } 287 288 #endif /* CONFIG_IS_ENABLED(FIT) */ 289