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 54 if (part_get_info_by_name(info->dev, part_name, &part_info) <= 0) { 55 debug("%s: no partition\n", __func__); 56 return -EINVAL; 57 } 58 sector = part_info.start; 59 60 memset(&meta, 0, sizeof(struct meta_head)); 61 if (info->read(info, sector, 1, &meta) != 1) { 62 debug("%s: Failed to read header\n", __func__); 63 return -EIO; 64 } 65 66 if (meta.tag != RK_META) { 67 debug("Invalid meta tag is %x.\n", meta.tag); 68 return -EINVAL; 69 } 70 71 if (meta.crc32 != crc32(0, (const unsigned char *)&meta, sizeof(struct meta_head) - 4 - 4)) { 72 debug("Invalid meta crc32.\n"); 73 return -EINVAL; 74 } 75 76 data = (char *)meta.load; 77 printf("Meta: 0x%08x - 0x%08x\n", meta.load, meta.load + meta.size); 78 if (info->read(info, sector, DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len), data) 79 != DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len)) { 80 debug("%s: Failed to read header\n", __func__); 81 return -EIO; 82 } 83 84 meta_p = (struct meta_head *)meta.load; 85 86 cmd = (struct cmdline_info *)(meta_p->load + CMDLINE_OFFSET); 87 if (cmd->tag == RK_CMDLINE) { 88 if (cmd->crc32 == crc32(0, (const unsigned char *)cmd, sizeof(struct cmdline_info) - 4)) 89 cmdline = (char *)cmd->data; 90 } 91 92 /* load compress data */ 93 data = (char *)COMPRESS_LOAD_ADDR; 94 if (meta_p->comp_type == META_COMPRESS_TYPE_GZ) { 95 if (info->read(info, sector + (MAX_META_SEGMENT_SIZE / info->bl_len), 96 DIV_ROUND_UP(meta.comp_size, info->bl_len), data) 97 != DIV_ROUND_UP(meta.comp_size, info->bl_len)) { 98 debug("%s: Failed to read compress data.\n", __func__); 99 return -EIO; 100 } 101 102 memcpy((void *)(meta_p->load + SENSOR_IQ_BIN_OFFSET), data, ITEM_SIZE); 103 104 if (rk_meta_iq_decom((meta_p->load + meta_p->comp_off), 105 (unsigned long)(data + meta_p->comp_off - 106 MAX_META_SEGMENT_SIZE), 107 meta.comp_size, &len)) { 108 debug("%s: Failed to decompress.\n", __func__); 109 return -EIO; 110 } 111 112 } else { 113 if (info->read(info, sector + (MAX_META_SEGMENT_SIZE / info->bl_len), 114 DIV_ROUND_UP(meta.comp_size, info->bl_len), 115 (void *)(meta_p->load + MAX_META_SEGMENT_SIZE)) 116 != DIV_ROUND_UP(meta.comp_size, info->bl_len)) { 117 debug("%s: Failed to read\n", __func__); 118 return -EIO; 119 } 120 } 121 122 meta_p->meta_flags = META_READ_DONE_FLAG; 123 flush_cache(meta_p->load, meta_p->size); 124 rk_meta_process(); 125 126 return 0; 127 } 128 129 void rk_meta_bootargs_append(void *fdt) 130 { 131 if (!cmdline || (!fdt || fdt_check_header(fdt))) 132 return; 133 134 fdt_bootargs_append(fdt, cmdline); 135 } 136