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