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