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