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 defined(CONFIG_ROCKCHIP_RV1106) || defined(CONFIG_ROCKCHIP_RV1103B) 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_get_startup_part_info(struct spl_load_info *info, disk_partition_t part_info, 28 uint32_t *per_part_size, struct meta_head *meta_p) 29 { 30 struct meta_head meta_next; 31 uint32_t total_part_num = 1; 32 uint32_t i = 1; 33 ulong sector = part_info.start; 34 35 if (info->read(info, sector, 1, meta_p) != 1) { 36 printf("%s: Failed to read header\n", __func__); 37 return -EIO; 38 } 39 40 if (meta_p->tag != RK_META) { 41 printf("Invalid meta tag is %x.\n", meta_p->tag); 42 return -EINVAL; 43 } 44 45 total_part_num = meta_p->total_part_num; 46 *per_part_size = meta_p->size + meta_p->part_reserved_size; 47 if (*per_part_size * meta_p->total_part_num > part_info.size * part_info.blksz) { 48 printf("Error: Total part size (0x%08x * %d) is larger than partition size (0x%08lx).\n", 49 *per_part_size, meta_p->total_part_num, part_info.size * part_info.blksz); 50 return -EINVAL; 51 } 52 53 memset(&meta_next, 0, sizeof(struct meta_head)); 54 for (i = 1; i < total_part_num; i++) { 55 if (info->read(info, sector + i * (*per_part_size / info->bl_len), 56 1, &meta_next) != 1) { 57 printf("%s: Failed to read header\n", __func__); 58 return -EIO; 59 } 60 61 if (meta_next.tag != RK_META) { 62 debug("Not read meta tag from meta part[%d], read from part[%d] by default.\n", i, i - 1); 63 break; 64 } 65 66 debug("Check part[%d]:part_flag=%d part[%d]:part_flag=%d\n", i - 1, meta_p->part_flag, 67 i, meta_next.part_flag); 68 if (meta_next.part_flag != meta_p->part_flag) 69 break; 70 71 memcpy(meta_p, &meta_next, sizeof(struct meta_head)); 72 } 73 74 if (meta_p->crc32 != crc32(0, (const unsigned char *)meta_p, sizeof(struct meta_head) - 4 - 4)) { 75 printf("Invalid meta crc32.\n"); 76 return -EINVAL; 77 } 78 79 return i; 80 } 81 82 static int rk_meta_iq_decom(unsigned long dst, unsigned long src, 83 unsigned long src_len, u64 *len) 84 { 85 int ret; 86 #if CONFIG_IS_ENABLED(MISC_DECOMPRESS) 87 88 ret = misc_decompress_process(dst, src, src_len, DECOM_GZIP, true, len, 0); 89 misc_decompress_sync(IH_COMP_GZIP); 90 #else 91 ret = gunzip((void *)&dst, ALIGN(len, FIT_MAX_SPL_IMAGE_SZ), 92 (void *)&src, (void *)len); 93 #endif 94 95 return ret; 96 } 97 98 int spl_load_meta(struct spl_image_info *spl_image, struct spl_load_info *info) 99 { 100 const char *part_name = PART_META; 101 disk_partition_t part_info; 102 struct meta_head meta; 103 struct meta_head *meta_p; 104 struct cmdline_info *cmd; 105 ulong sector; 106 char *data; 107 u64 len; 108 int meta_iq_item_size = 0; 109 int meta_startup_part_num = 0; 110 uint32_t meta_per_part_size = 0; 111 uint32_t meta_startup_part_offset = 0; 112 113 if (part_get_info_by_name(info->dev, part_name, &part_info) <= 0) { 114 debug("%s: no partition\n", __func__); 115 return -EINVAL; 116 } 117 sector = part_info.start; 118 119 printf("\n"); 120 memset(&meta, 0, sizeof(struct meta_head)); 121 122 meta_startup_part_num = rk_meta_get_startup_part_info(info, part_info, &meta_per_part_size, &meta); 123 if (meta_startup_part_num <= 0) { 124 debug("Get startup part number failed.[%d]\n", meta_startup_part_num); 125 return -EINVAL; 126 } 127 printf("Meta: Found meta partition. Current part number: %d, total: %d\n", 128 meta_startup_part_num, meta.total_part_num); 129 130 /* The first part offset starts at 0x0 offset. */ 131 meta_startup_part_offset = (meta_startup_part_num - 1) * (meta_per_part_size / info->bl_len); 132 133 data = (char *)meta.load; 134 printf("Meta: 0x%08x - 0x%08x\n", meta.load, meta.load + meta.size); 135 if (info->read(info, sector + meta_startup_part_offset, 136 DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len), data) 137 != DIV_ROUND_UP(MAX_META_SEGMENT_SIZE, info->bl_len)) { 138 debug("%s: Failed to read header\n", __func__); 139 return -EIO; 140 } 141 142 meta_p = (struct meta_head *)meta.load; 143 144 cmd = (struct cmdline_info *)(meta_p->load + CMDLINE_OFFSET); 145 if (cmd->tag == RK_CMDLINE) { 146 if (cmd->crc32 == crc32(0, (const unsigned char *)cmd, sizeof(struct cmdline_info) - 4)) 147 cmdline = (char *)cmd->data; 148 } 149 150 /* load compress data */ 151 data = (char *)COMPRESS_LOAD_ADDR; 152 meta_iq_item_size = meta_p->iq_item_size + meta.comp_size; 153 if (meta_p->comp_type == META_COMPRESS_TYPE_GZ) { 154 if (info->read(info, 155 sector + meta_startup_part_offset + (MAX_META_SEGMENT_SIZE / info->bl_len), 156 DIV_ROUND_UP(meta_iq_item_size, info->bl_len), 157 data) 158 != DIV_ROUND_UP(meta_iq_item_size, info->bl_len)) { 159 printf("%s: Failed to read compress data.\n", __func__); 160 return -EIO; 161 } 162 163 memcpy((void *)(meta_p->load + SENSOR_IQ_BIN_OFFSET), data, meta_p->iq_item_size); 164 165 if (rk_meta_iq_decom((meta_p->load + meta_p->comp_off), 166 (unsigned long)(data + meta_p->comp_off - 167 MAX_META_SEGMENT_SIZE), 168 meta.comp_size, &len)) { 169 printf("%s: Failed to decompress.\n", __func__); 170 return -EIO; 171 } 172 173 } else { 174 if (info->read(info, 175 sector + meta_startup_part_offset + (MAX_META_SEGMENT_SIZE / info->bl_len), 176 DIV_ROUND_UP(meta_iq_item_size, info->bl_len), 177 (void *)(meta_p->load + MAX_META_SEGMENT_SIZE)) 178 != DIV_ROUND_UP(meta_iq_item_size, info->bl_len)) { 179 printf("%s: Failed to read\n", __func__); 180 return -EIO; 181 } 182 } 183 184 meta_p->meta_flags = META_READ_DONE_FLAG; 185 flush_cache(meta_p->load, meta_p->size); 186 rk_meta_process(); 187 188 printf("\nMeta: ok\n"); 189 return 0; 190 } 191 192 void rk_meta_bootargs_append(void *fdt) 193 { 194 if (!cmdline || (!fdt || fdt_check_header(fdt))) 195 return; 196 197 fdt_bootargs_append(fdt, cmdline); 198 } 199