1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 4 * 5 */ 6 7 #include <common.h> 8 #include <boot_rkimg.h> 9 #include <crc.h> 10 #include <errno.h> 11 #include <fdt_support.h> 12 #include <image.h> 13 #include <misc.h> 14 #include <spl.h> 15 #include <asm/arch/rk_meta.h> 16 17 static char *cmdline; 18 19 #if (IS_ENABLED(CONFIG_ROCKCHIP_RV1106)) 20 #define COMPRESS_LOAD_ADDR 0xa0000 21 #else 22 #error "Please Define COMPRESS_LOAD_ADDR !!!" 23 #endif 24 25 __weak void rk_meta_process(void) { } 26 27 static int rk_meta_iq_decom(unsigned long dst, unsigned long src, 28 unsigned long src_len, u64 *len) 29 { 30 int ret; 31 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 32 33 ret = misc_decompress_process(dst, src, src_len, DECOM_GZIP, true, len, 0); 34 misc_decompress_sync(IH_COMP_GZIP); 35 #else 36 ret = gunzip((void *)&dst, ALIGN(len, FIT_MAX_SPL_IMAGE_SZ), 37 (void *)&src, (void *)len); 38 #endif 39 40 return ret; 41 } 42 43 int spl_load_meta(struct spl_image_info *spl_image, struct spl_load_info *info) 44 { 45 const char *part_name = PART_META; 46 disk_partition_t part_info; 47 struct meta_head meta; 48 struct meta_head *meta_p; 49 struct cmdline_info *cmd; 50 ulong sector; 51 char *data; 52 u64 len; 53 int meta_iq_item_size = 0; 54 55 if (part_get_info_by_name(info->dev, part_name, &part_info) <= 0) { 56 debug("%s: no partition\n", __func__); 57 return -EINVAL; 58 } 59 sector = part_info.start; 60 61 memset(&meta, 0, sizeof(struct meta_head)); 62 if (info->read(info, sector, 1, &meta) != 1) { 63 debug("%s: Failed to read header\n", __func__); 64 return -EIO; 65 } 66 67 if (meta.tag != RK_META) { 68 debug("Invalid meta tag is %x.\n", meta.tag); 69 return -EINVAL; 70 } 71 72 if (meta.crc32 != crc32(0, (const unsigned char *)&meta, sizeof(struct meta_head) - 4 - 4)) { 73 debug("Invalid meta crc32.\n"); 74 return -EINVAL; 75 } 76 77 data = (char *)meta.load; 78 printf("Meta: 0x%08x - 0x%08x\n", meta.load, meta.load + meta.size); 79 if (info->read(info, sector, DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len), data) 80 != DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len)) { 81 debug("%s: Failed to read header\n", __func__); 82 return -EIO; 83 } 84 85 meta_p = (struct meta_head *)meta.load; 86 87 cmd = (struct cmdline_info *)(meta_p->load + CMDLINE_OFFSET); 88 if (cmd->tag == RK_CMDLINE) { 89 if (cmd->crc32 == crc32(0, (const unsigned char *)cmd, sizeof(struct cmdline_info) - 4)) 90 cmdline = (char *)cmd->data; 91 } 92 93 /* load compress data */ 94 data = (char *)COMPRESS_LOAD_ADDR; 95 meta_iq_item_size = meta_p->iq_item_size + meta.comp_size; 96 if (meta_p->comp_type == META_COMPRESS_TYPE_GZ) { 97 if (info->read(info, sector + (MAX_META_SEGMENT_SIZE / info->bl_len), 98 DIV_ROUND_UP(meta_iq_item_size, info->bl_len), data) 99 != DIV_ROUND_UP(meta_iq_item_size, info->bl_len)) { 100 printf("%s: Failed to read compress data.\n", __func__); 101 return -EIO; 102 } 103 104 memcpy((void *)(meta_p->load + SENSOR_IQ_BIN_OFFSET), data, meta_p->iq_item_size); 105 106 if (rk_meta_iq_decom((meta_p->load + meta_p->comp_off), 107 (unsigned long)(data + meta_p->comp_off - 108 MAX_META_SEGMENT_SIZE), 109 meta.comp_size, &len)) { 110 printf("%s: Failed to decompress.\n", __func__); 111 return -EIO; 112 } 113 114 } else { 115 if (info->read(info, sector + (MAX_META_SEGMENT_SIZE / info->bl_len), 116 DIV_ROUND_UP(meta_iq_item_size, info->bl_len), 117 (void *)(meta_p->load + MAX_META_SEGMENT_SIZE)) 118 != DIV_ROUND_UP(meta_iq_item_size, info->bl_len)) { 119 printf("%s: Failed to read\n", __func__); 120 return -EIO; 121 } 122 } 123 124 meta_p->meta_flags = META_READ_DONE_FLAG; 125 flush_cache(meta_p->load, meta_p->size); 126 rk_meta_process(); 127 128 printf("\nMeta: ok\n"); 129 return 0; 130 } 131 132 void rk_meta_bootargs_append(void *fdt) 133 { 134 if (!cmdline || (!fdt || fdt_check_header(fdt))) 135 return; 136 137 fdt_bootargs_append(fdt, cmdline); 138 } 139