xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/uimage.c (revision f36ea2f6e17621c4d9dd97c4dbfab62d03d061df)
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 
15 static 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 
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 
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 
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 
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 int uimage_init_resource(void)
187 {
188 	struct blk_desc *dev_desc;
189 	disk_partition_t part;
190 	image_header_t *hdr;
191 	char *part_name;
192 	ulong data, offset;
193 	ulong size;
194 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
195 	ulong dst;
196 	int idx = 3;
197 #endif
198 	int ret;
199 
200 	dev_desc = rockchip_get_bootdev();
201 	if (!dev_desc) {
202 		printf("No dev_desc!\n");
203 		return ENODEV;
204 	}
205 
206 	if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
207 		part_name = PART_RECOVERY;
208 	else
209 		part_name = PART_BOOT;
210 
211 	if (part_get_info_by_name(dev_desc, part_name, &part) < 0) {
212 		UIMG_I("No %s partition\n", part_name);
213 		return -ENODEV;
214 	}
215 
216 	hdr = uimage_get_hdr(dev_desc, &part);
217 	if (!hdr)
218 		return -ENODEV;
219 
220 	image_multi_getimg(hdr, idx, &data, &size);
221 	offset = data - (ulong)hdr;
222 	free(hdr);
223 
224 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
225 	ulong fdt_addr;
226 
227 	/* reserve enough space before fdt */
228 	fdt_addr = env_get_ulong("fdt_addr_r", 16, 0);
229 	dst = (ulong)fdt_addr -
230 		   ALIGN(size, dev_desc->blksz) - CONFIG_SYS_FDT_PAD;
231 	ret = uimage_load_one(dev_desc, &part, offset, size, (void *)dst);
232 	if (ret) {
233 		UIMG_I("Failed to load resource file, ret=%d\n", ret);
234 		return ret;
235 	}
236 
237 	if (!sysmem_alloc_base(MEM_RESOURCE, (phys_addr_t)dst,
238 			       ALIGN(size, RK_BLK_SIZE)))
239 		return -ENOMEM;
240 
241 	ret = resource_create_ram_list(dev_desc, (void *)dst);
242 	if (ret) {
243 		UIMG_I("Failed to create resource list, ret=%d\n", ret);
244 		return ret;
245 	}
246 #endif
247 
248 	return 0;
249 }
250