1aa8e825bSJoseph Chen /* 2aa8e825bSJoseph Chen * (C) Copyright 2020 Rockchip Electronics Co., Ltd 3aa8e825bSJoseph Chen * 4aa8e825bSJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 5aa8e825bSJoseph Chen */ 6aa8e825bSJoseph Chen 7aa8e825bSJoseph Chen #include <common.h> 8aa8e825bSJoseph Chen #include <boot_rkimg.h> 9aa8e825bSJoseph Chen #include <misc.h> 10aa8e825bSJoseph Chen #ifdef CONFIG_SPL_BUILD 11aa8e825bSJoseph Chen #include <spl.h> 12aa8e825bSJoseph Chen #endif 13ade0ccd7SJoseph Chen #include <lzma/LzmaTools.h> 14aa8e825bSJoseph Chen #include <optee_include/OpteeClientInterface.h> 15aa8e825bSJoseph Chen #include <optee_include/tee_api_defines.h> 16aa8e825bSJoseph Chen 17aa8e825bSJoseph Chen DECLARE_GLOBAL_DATA_PTR; 18aa8e825bSJoseph Chen 19aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT) 20aa8e825bSJoseph Chen 21aa8e825bSJoseph Chen /* 22aa8e825bSJoseph Chen * Override __weak board_fit_image_post_process() for SPL & U-Boot proper. 23aa8e825bSJoseph Chen */ 24aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS) 25aa8e825bSJoseph Chen 26aa8e825bSJoseph Chen #define FIT_UNCOMP_HASH_NODENAME "digest" 275beee4e8SYifeng Zhao #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) 28aa8e825bSJoseph Chen static int fit_image_check_uncomp_hash(const void *fit, int parent_noffset, 29aa8e825bSJoseph Chen const void *data, size_t size) 30aa8e825bSJoseph Chen { 31aa8e825bSJoseph Chen const char *name; 32aa8e825bSJoseph Chen char *err_msgp; 33aa8e825bSJoseph Chen int noffset; 34aa8e825bSJoseph Chen 35aa8e825bSJoseph Chen fdt_for_each_subnode(noffset, fit, parent_noffset) { 36aa8e825bSJoseph Chen name = fit_get_name(fit, noffset, NULL); 37aa8e825bSJoseph Chen if (!strncmp(name, FIT_UNCOMP_HASH_NODENAME, 38aa8e825bSJoseph Chen strlen(FIT_UNCOMP_HASH_NODENAME))) { 39aa8e825bSJoseph Chen return fit_image_check_hash(fit, noffset, data, 40aa8e825bSJoseph Chen size, &err_msgp); 41aa8e825bSJoseph Chen } 42aa8e825bSJoseph Chen } 43aa8e825bSJoseph Chen 44aa8e825bSJoseph Chen return 0; 45aa8e825bSJoseph Chen } 46aa8e825bSJoseph Chen 47ade0ccd7SJoseph Chen static int fit_decomp_image(void *fit, int node, ulong *load_addr, 489bb8411cSJoseph Chen ulong **src_addr, size_t *src_len, void *spec) 49aa8e825bSJoseph Chen { 50aa8e825bSJoseph Chen u64 len = *src_len; 51ade0ccd7SJoseph Chen int ret = -ENOSYS; 52aa8e825bSJoseph Chen u8 comp; 53*86b1f5c1SJason Zhu #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 54*86b1f5c1SJason Zhu u32 flags = 0; 55*86b1f5c1SJason Zhu #endif 56aa8e825bSJoseph Chen 57aa8e825bSJoseph Chen if (fit_image_get_comp(fit, node, &comp)) 58aa8e825bSJoseph Chen return 0; 59aa8e825bSJoseph Chen 60ade0ccd7SJoseph Chen if (comp != IH_COMP_GZIP && comp != IH_COMP_LZMA) 61aa8e825bSJoseph Chen return 0; 62aa8e825bSJoseph Chen 63aa8e825bSJoseph Chen #ifndef CONFIG_SPL_BUILD 649bb8411cSJoseph Chen /* 659bb8411cSJoseph Chen * U-Boot: 669bb8411cSJoseph Chen * handled late in bootm_decomp_image() 679bb8411cSJoseph Chen */ 68aa8e825bSJoseph Chen if (fit_image_check_type(fit, node, IH_TYPE_KERNEL)) 69aa8e825bSJoseph Chen return 0; 709bb8411cSJoseph Chen #elif defined(CONFIG_SPL_MTD_SUPPORT) && defined(CONFIG_SPL_MISC_DECOMPRESS) && \ 719bb8411cSJoseph Chen defined(CONFIG_SPL_KERNEL_BOOT) 729bb8411cSJoseph Chen /* 739bb8411cSJoseph Chen * SPL Thunder-boot policty on spi-nand: 749bb8411cSJoseph Chen * enable and use interrupt status as a sync signal for 759bb8411cSJoseph Chen * kernel to poll that whether ramdisk decompress is done. 769bb8411cSJoseph Chen */ 779bb8411cSJoseph Chen struct spl_load_info *info = spec; 789bb8411cSJoseph Chen struct blk_desc *desc; 799bb8411cSJoseph Chen 809bb8411cSJoseph Chen if (info && info->dev) { 819bb8411cSJoseph Chen desc = info->dev; 829bb8411cSJoseph Chen if ((desc->if_type == IF_TYPE_MTD) && 839bb8411cSJoseph Chen (desc->devnum == BLK_MTD_SPI_NAND) && 849bb8411cSJoseph Chen fit_image_check_type(fit, node, IH_TYPE_RAMDISK)) { 859bb8411cSJoseph Chen flags |= DCOMP_FLG_IRQ_ONESHOT; 869bb8411cSJoseph Chen } 879bb8411cSJoseph Chen } 88aa8e825bSJoseph Chen #endif 89ade0ccd7SJoseph Chen if (comp == IH_COMP_LZMA) { 90ade0ccd7SJoseph Chen #if CONFIG_IS_ENABLED(LZMA) 91ade0ccd7SJoseph Chen SizeT lzma_len = ALIGN(len, FIT_MAX_SPL_IMAGE_SZ); 92ade0ccd7SJoseph Chen SizeT src_lenp; 93ade0ccd7SJoseph Chen const fdt32_t *val; 94ade0ccd7SJoseph Chen 95ade0ccd7SJoseph Chen val = fdt_getprop(fit, node, "raw-size", NULL); 96ade0ccd7SJoseph Chen if (!val) 97ade0ccd7SJoseph Chen return -ENOENT; 98ade0ccd7SJoseph Chen src_lenp = fdt32_to_cpu(*val); 99ade0ccd7SJoseph Chen ret = lzmaBuffToBuffDecompress((uchar *)(*load_addr), &lzma_len, 100ade0ccd7SJoseph Chen (uchar *)(*src_addr), src_lenp); 101ade0ccd7SJoseph Chen len = lzma_len; 102ade0ccd7SJoseph Chen #endif 103ade0ccd7SJoseph Chen } else if (comp == IH_COMP_GZIP) { 104aa8e825bSJoseph Chen /* 105aa8e825bSJoseph Chen * For smaller spl size, we don't use misc_decompress_process() 106aa8e825bSJoseph Chen * inside the gunzip(). 107aa8e825bSJoseph Chen */ 108aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 109ade0ccd7SJoseph Chen const void *prop; 110ade0ccd7SJoseph Chen 111aa8e825bSJoseph Chen ret = misc_decompress_process((ulong)(*load_addr), 112aa8e825bSJoseph Chen (ulong)(*src_addr), (ulong)(*src_len), 113dd5acf09SJason Zhu DECOM_GZIP, true, &len, flags); 114ade0ccd7SJoseph Chen /* mark for misc_decompress_cleanup() */ 115ade0ccd7SJoseph Chen prop = fdt_getprop(fit, node, "decomp-async", NULL); 116ade0ccd7SJoseph Chen if (prop) 117ade0ccd7SJoseph Chen misc_decompress_async(comp); 118ade0ccd7SJoseph Chen else 119ade0ccd7SJoseph Chen misc_decompress_sync(comp); 120aa8e825bSJoseph Chen #else 1212708ed29SJoseph Chen ret = gunzip((void *)(*load_addr), ALIGN(len, FIT_MAX_SPL_IMAGE_SZ), 122aa8e825bSJoseph Chen (void *)(*src_addr), (void *)(&len)); 123aa8e825bSJoseph Chen #endif 124ade0ccd7SJoseph Chen } 125ade0ccd7SJoseph Chen 126aa8e825bSJoseph Chen if (ret) { 127aa8e825bSJoseph Chen printf("%s: decompress error, ret=%d\n", 128aa8e825bSJoseph Chen fdt_get_name(fit, node, NULL), ret); 129aa8e825bSJoseph Chen return ret; 130aa8e825bSJoseph Chen } 131aa8e825bSJoseph Chen 132aa8e825bSJoseph Chen /* check uncompressed data hash */ 133aa8e825bSJoseph Chen ret = fit_image_check_uncomp_hash(fit, node, (void *)(*load_addr), len); 134aa8e825bSJoseph Chen if (!ret) 135aa8e825bSJoseph Chen puts("+ "); 136aa8e825bSJoseph Chen else 137aa8e825bSJoseph Chen return ret; 138aa8e825bSJoseph Chen 139aa8e825bSJoseph Chen *src_addr = (ulong *)*load_addr; 140aa8e825bSJoseph Chen *src_len = len; 141aa8e825bSJoseph Chen 142aa8e825bSJoseph Chen return 0; 143aa8e825bSJoseph Chen } 144aa8e825bSJoseph Chen #endif 145aa8e825bSJoseph Chen 146aa8e825bSJoseph Chen void board_fit_image_post_process(void *fit, int node, ulong *load_addr, 1479bb8411cSJoseph Chen ulong **src_addr, size_t *src_len, void *spec) 148aa8e825bSJoseph Chen { 149aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) || CONFIG_IS_ENABLED(GZIP) 150ade0ccd7SJoseph Chen fit_decomp_image(fit, node, load_addr, src_addr, src_len, spec); 151aa8e825bSJoseph Chen #endif 152aa8e825bSJoseph Chen 153aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(USING_KERNEL_DTB) 154aa8e825bSJoseph Chen /* Avoid overriding processed(overlay, hw-dtb, ...) kernel dtb */ 155d94316bfSJoseph Chen if (fit_image_check_type(fit, node, IH_TYPE_FLATDT)) { 156d94316bfSJoseph Chen if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) { 157aa8e825bSJoseph Chen *src_addr = (void *)gd->fdt_blob; 158aa8e825bSJoseph Chen *src_len = (size_t)fdt_totalsize(gd->fdt_blob); 159d94316bfSJoseph Chen } else { 160d94316bfSJoseph Chen printf(" Using fdt from load-in fdt\n"); 161d94316bfSJoseph Chen } 162aa8e825bSJoseph Chen } 163aa8e825bSJoseph Chen #endif 164aa8e825bSJoseph Chen } 165aa8e825bSJoseph Chen #endif /* FIT_IMAGE_POST_PROCESS */ 166aa8e825bSJoseph Chen /* 167aa8e825bSJoseph Chen * Override __weak fit_rollback_index_verify() for SPL & U-Boot proper. 168aa8e825bSJoseph Chen */ 169aa8e825bSJoseph Chen #if CONFIG_IS_ENABLED(FIT_ROLLBACK_PROTECT) 170aa8e825bSJoseph Chen int fit_rollback_index_verify(const void *fit, uint32_t rollback_fd, 171aa8e825bSJoseph Chen uint32_t *fit_index, uint32_t *otp_index) 172aa8e825bSJoseph Chen { 173aa8e825bSJoseph Chen int conf_noffset, ret; 174aa8e825bSJoseph Chen 175aa8e825bSJoseph Chen conf_noffset = fit_conf_get_node(fit, NULL); /* NULL for default conf */ 176aa8e825bSJoseph Chen if (conf_noffset < 0) 177aa8e825bSJoseph Chen return conf_noffset; 178aa8e825bSJoseph Chen 179aa8e825bSJoseph Chen ret = fit_image_get_rollback_index(fit, conf_noffset, fit_index); 180aa8e825bSJoseph Chen if (ret) { 181aa8e825bSJoseph Chen printf("Failed to get rollback-index from FIT, ret=%d\n", ret); 182aa8e825bSJoseph Chen return ret; 183aa8e825bSJoseph Chen } 184aa8e825bSJoseph Chen 185aa8e825bSJoseph Chen ret = fit_read_otp_rollback_index(*fit_index, otp_index); 186aa8e825bSJoseph Chen if (ret) { 187aa8e825bSJoseph Chen printf("Failed to get rollback-index from otp, ret=%d\n", ret); 188aa8e825bSJoseph Chen return ret; 189aa8e825bSJoseph Chen } 190aa8e825bSJoseph Chen 191aa8e825bSJoseph Chen /* Should update rollback index to otp ! */ 192aa8e825bSJoseph Chen if (*otp_index < *fit_index) 193aa8e825bSJoseph Chen gd->rollback_index = *fit_index; 194aa8e825bSJoseph Chen 195aa8e825bSJoseph Chen return 0; 196aa8e825bSJoseph Chen } 197aa8e825bSJoseph Chen #endif 198aa8e825bSJoseph Chen 199aa8e825bSJoseph Chen /* 200aa8e825bSJoseph Chen * Override __weak fit_board_verify_required_sigs() for SPL & U-Boot proper. 201aa8e825bSJoseph Chen */ 202aa8e825bSJoseph Chen int fit_board_verify_required_sigs(void) 203aa8e825bSJoseph Chen { 204aa8e825bSJoseph Chen uint8_t vboot = 0; 205aa8e825bSJoseph Chen 206aa8e825bSJoseph Chen #ifdef CONFIG_SPL_BUILD 207299f09a0SJason Zhu #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP) 208aa8e825bSJoseph Chen struct udevice *dev; 209aa8e825bSJoseph Chen 210aa8e825bSJoseph Chen dev = misc_otp_get_device(OTP_S); 211aa8e825bSJoseph Chen if (!dev) 212aa8e825bSJoseph Chen return 1; 213aa8e825bSJoseph Chen 214a31e24f3SJason Zhu if (misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, &vboot, 1)) { 215aa8e825bSJoseph Chen printf("Can't read verified-boot flag\n"); 216aa8e825bSJoseph Chen return 1; 217aa8e825bSJoseph Chen } 218aa8e825bSJoseph Chen 219aa8e825bSJoseph Chen vboot = (vboot == 0xff); 220aa8e825bSJoseph Chen #endif 221aa8e825bSJoseph Chen #else /* !CONFIG_SPL_BUILD */ 222aa8e825bSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 223aa8e825bSJoseph Chen int ret; 224aa8e825bSJoseph Chen 225aa8e825bSJoseph Chen ret = trusty_read_vbootkey_enable_flag(&vboot); 226aa8e825bSJoseph Chen if (ret) { 227aa8e825bSJoseph Chen printf("Can't read verified-boot flag, ret=%d\n", ret); 228aa8e825bSJoseph Chen return 1; 229aa8e825bSJoseph Chen } 230aa8e825bSJoseph Chen #endif 231aa8e825bSJoseph Chen #endif /* CONFIG_SPL_BUILD*/ 232aa8e825bSJoseph Chen 233aa8e825bSJoseph Chen printf("## Verified-boot: %d\n", vboot); 234aa8e825bSJoseph Chen 235aa8e825bSJoseph Chen return vboot; 236aa8e825bSJoseph Chen } 237aa8e825bSJoseph Chen 238aa8e825bSJoseph Chen #endif /* CONFIG_IS_ENABLED(FIT) */ 239