1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <boot_rkimg.h>
9*4882a593Smuzhiyun #include <image.h>
10*4882a593Smuzhiyun #include <malloc.h>
11*4882a593Smuzhiyun #include <sysmem.h>
12*4882a593Smuzhiyun #include <asm/arch/resource_img.h>
13*4882a593Smuzhiyun #include <asm/arch/uimage.h>
14*4882a593Smuzhiyun
uimage_load_one(struct blk_desc * dev_desc,disk_partition_t * part,int pos_off,int size,void * dst)15*4882a593Smuzhiyun int uimage_load_one(struct blk_desc *dev_desc, disk_partition_t *part,
16*4882a593Smuzhiyun int pos_off, int size, void *dst)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun u32 blknum, blkoff;
19*4882a593Smuzhiyun u32 unused;
20*4882a593Smuzhiyun ulong blksz;
21*4882a593Smuzhiyun void *buf;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun blksz = dev_desc->blksz;
24*4882a593Smuzhiyun blkoff = pos_off / blksz;
25*4882a593Smuzhiyun unused = pos_off - blkoff * blksz;
26*4882a593Smuzhiyun blknum = DIV_ROUND_UP(size, blksz) + !!unused;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun if (!size)
29*4882a593Smuzhiyun return -EINVAL;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (!IS_ALIGNED(unused, ARCH_DMA_MINALIGN)) {
32*4882a593Smuzhiyun buf = memalign(ARCH_DMA_MINALIGN, blknum * blksz);
33*4882a593Smuzhiyun if (!buf)
34*4882a593Smuzhiyun return -ENOMEM;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (blk_dread(dev_desc, part->start + blkoff,
37*4882a593Smuzhiyun blknum, buf) != blknum) {
38*4882a593Smuzhiyun free(buf);
39*4882a593Smuzhiyun return -EIO;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun memcpy(dst, buf + unused, size);
43*4882a593Smuzhiyun free(buf);
44*4882a593Smuzhiyun } else {
45*4882a593Smuzhiyun if (blk_dread(dev_desc, part->start + blkoff,
46*4882a593Smuzhiyun blknum, (void *)((ulong)dst - unused)) != blknum)
47*4882a593Smuzhiyun return -EIO;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun return 0;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
uimage_get_hdr(struct blk_desc * dev_desc,disk_partition_t * part)53*4882a593Smuzhiyun static image_header_t *uimage_get_hdr(struct blk_desc *dev_desc,
54*4882a593Smuzhiyun disk_partition_t *part)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun image_header_t *hdr;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE);
59*4882a593Smuzhiyun if (!hdr)
60*4882a593Smuzhiyun return NULL;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (blk_dread(dev_desc, part->start, 1, hdr) != 1)
63*4882a593Smuzhiyun goto err;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun if (!image_check_magic(hdr) || (image_get_type(hdr) != IH_TYPE_MULTI))
66*4882a593Smuzhiyun goto err;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun return hdr;
69*4882a593Smuzhiyun err:
70*4882a593Smuzhiyun free(hdr);
71*4882a593Smuzhiyun return NULL;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
uimage_load_bootables(void)74*4882a593Smuzhiyun void *uimage_load_bootables(void)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun struct blk_desc *dev_desc;
77*4882a593Smuzhiyun disk_partition_t part;
78*4882a593Smuzhiyun image_header_t *hdr;
79*4882a593Smuzhiyun char *part_name;
80*4882a593Smuzhiyun ulong raddr;
81*4882a593Smuzhiyun ulong kaddr;
82*4882a593Smuzhiyun ulong faddr;
83*4882a593Smuzhiyun int blknum;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun raddr = env_get_ulong("ramdisk_addr_r", 16, 0);
86*4882a593Smuzhiyun kaddr = env_get_ulong("kernel_addr_r", 16, 0);
87*4882a593Smuzhiyun faddr = env_get_ulong("fdt_addr_r", 16, 0);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (!faddr || !kaddr || !raddr)
90*4882a593Smuzhiyun return NULL;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun dev_desc = rockchip_get_bootdev();
93*4882a593Smuzhiyun if (!dev_desc) {
94*4882a593Smuzhiyun UIMG_I("No dev_desc\n");
95*4882a593Smuzhiyun return NULL;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
99*4882a593Smuzhiyun part_name = PART_RECOVERY;
100*4882a593Smuzhiyun else
101*4882a593Smuzhiyun part_name = PART_BOOT;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (part_get_info_by_name(dev_desc, part_name, &part) < 0) {
104*4882a593Smuzhiyun UIMG_I("No %s partition\n", part_name);
105*4882a593Smuzhiyun return NULL;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun hdr = uimage_get_hdr(dev_desc, &part);
109*4882a593Smuzhiyun if (!hdr)
110*4882a593Smuzhiyun return NULL;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* load */
113*4882a593Smuzhiyun blknum = DIV_ROUND_UP(image_get_image_size(hdr), dev_desc->blksz);
114*4882a593Smuzhiyun hdr = sysmem_alloc(MEM_UIMAGE, blknum * dev_desc->blksz);
115*4882a593Smuzhiyun if (!hdr)
116*4882a593Smuzhiyun return NULL;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (blk_dread(dev_desc, part.start, blknum, (void *)hdr) != blknum) {
119*4882a593Smuzhiyun UIMG_I("Failed to read %s data\n", part.name);
120*4882a593Smuzhiyun return NULL;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return hdr;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
uimage_sysmem_reserve_each(image_header_t * hdr,u32 * ramdisk_sz)126*4882a593Smuzhiyun int uimage_sysmem_reserve_each(image_header_t *hdr, u32 *ramdisk_sz)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun ulong raddr, kaddr, faddr;
129*4882a593Smuzhiyun ulong data, size;
130*4882a593Smuzhiyun int blknum;
131*4882a593Smuzhiyun int blksz = RK_BLK_SIZE;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun raddr = env_get_ulong("ramdisk_addr_r", 16, 0);
134*4882a593Smuzhiyun kaddr = env_get_ulong("kernel_addr_r", 16, 0);
135*4882a593Smuzhiyun faddr = env_get_ulong("fdt_addr_r", 16, 0);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if (!faddr || !kaddr || !raddr)
138*4882a593Smuzhiyun return -EINVAL;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* kernel */
141*4882a593Smuzhiyun image_multi_getimg(hdr, 0, &data, &size);
142*4882a593Smuzhiyun blknum = DIV_ROUND_UP(size, blksz);
143*4882a593Smuzhiyun if (!sysmem_alloc_base(MEM_KERNEL, (phys_addr_t)kaddr,
144*4882a593Smuzhiyun blknum * blksz))
145*4882a593Smuzhiyun return -ENOMEM;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* ramdisk */
148*4882a593Smuzhiyun image_multi_getimg(hdr, 1, &data, &size);
149*4882a593Smuzhiyun *ramdisk_sz = size;
150*4882a593Smuzhiyun blknum = DIV_ROUND_UP(size, blksz);
151*4882a593Smuzhiyun if (size && !sysmem_alloc_base(MEM_RAMDISK, (phys_addr_t)raddr,
152*4882a593Smuzhiyun blknum * blksz))
153*4882a593Smuzhiyun return -ENOMEM;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* fdt */
156*4882a593Smuzhiyun image_multi_getimg(hdr, 2, &data, &size);
157*4882a593Smuzhiyun blknum = DIV_ROUND_UP(size, blksz);
158*4882a593Smuzhiyun if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)faddr,
159*4882a593Smuzhiyun blknum * blksz))
160*4882a593Smuzhiyun return -ENOMEM;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun env_set_hex("fdt_high", faddr);
163*4882a593Smuzhiyun env_set_hex("initrd_high", raddr);
164*4882a593Smuzhiyun env_set("bootm-reloc-at", "y");
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun return 0;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
uimage_sysmem_free_each(image_header_t * img,u32 ramdisk_sz)169*4882a593Smuzhiyun int uimage_sysmem_free_each(image_header_t *img, u32 ramdisk_sz)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun ulong raddr, kaddr, faddr;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun raddr = env_get_ulong("ramdisk_addr_r", 16, 0);
174*4882a593Smuzhiyun kaddr = env_get_ulong("kernel_addr_r", 16, 0);
175*4882a593Smuzhiyun faddr = env_get_ulong("fdt_addr_r", 16, 0);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun sysmem_free((phys_addr_t)img);
178*4882a593Smuzhiyun sysmem_free((phys_addr_t)kaddr);
179*4882a593Smuzhiyun sysmem_free((phys_addr_t)faddr);
180*4882a593Smuzhiyun if (ramdisk_sz)
181*4882a593Smuzhiyun sysmem_free((phys_addr_t)raddr);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
uimage_init_resource(struct blk_desc * dev_desc)187*4882a593Smuzhiyun int uimage_init_resource(struct blk_desc *dev_desc)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun disk_partition_t part;
190*4882a593Smuzhiyun ulong data, offset, size;
191*4882a593Smuzhiyun image_header_t *hdr;
192*4882a593Smuzhiyun char *part_name = PART_BOOT;
193*4882a593Smuzhiyun int ret, idx = 3;
194*4882a593Smuzhiyun void *buf;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (!dev_desc)
197*4882a593Smuzhiyun return -ENODEV;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #ifndef CONFIG_ANDROID_AB
200*4882a593Smuzhiyun if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
201*4882a593Smuzhiyun part_name = PART_RECOVERY;
202*4882a593Smuzhiyun #endif
203*4882a593Smuzhiyun if (part_get_info_by_name(dev_desc, part_name, &part) < 0) {
204*4882a593Smuzhiyun UIMG_I("No %s partition\n", part_name);
205*4882a593Smuzhiyun return -ENODEV;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun hdr = uimage_get_hdr(dev_desc, &part);
209*4882a593Smuzhiyun if (!hdr)
210*4882a593Smuzhiyun return -EAGAIN;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun image_multi_getimg(hdr, idx, &data, &size);
213*4882a593Smuzhiyun offset = data - (ulong)hdr;
214*4882a593Smuzhiyun free(hdr);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun buf = memalign(ARCH_DMA_MINALIGN, ALIGN(size, dev_desc->blksz));
217*4882a593Smuzhiyun if (!buf)
218*4882a593Smuzhiyun return -ENOMEM;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun printf("RESC: '%s', blk@0x%08lx\n", part.name,
221*4882a593Smuzhiyun part.start + (offset / dev_desc->blksz));
222*4882a593Smuzhiyun ret = uimage_load_one(dev_desc, &part, offset, size, buf);
223*4882a593Smuzhiyun if (ret)
224*4882a593Smuzhiyun return ret;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun ret = resource_setup_ram_list(dev_desc, buf);
227*4882a593Smuzhiyun if (ret) {
228*4882a593Smuzhiyun UIMG_I("Failed to setup resource ram list, ret=%d\n", ret);
229*4882a593Smuzhiyun return ret;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun #endif
235