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