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