xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-rockchip/uimage.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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