xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-rockchip/rk_atags.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier:     GPL-2.0+
2 /*
3  * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
4  *
5  */
6 
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/arch/bootrom.h>
10 #include <asm/arch/rk_atags.h>
11 #if CONFIG_IS_ENABLED(TINY_FRAMEWORK)
12 #include <debug_uart.h>
13 #endif
14 
15 #define HASH_LEN	sizeof(u32)
16 
17 #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
18 /*
19  * The array is used to transform rom bootsource type to rk atags boot type.
20  */
21 static int bootdev_map[] = {
22 	BOOT_TYPE_UNKNOWN,
23 	BOOT_TYPE_NAND,
24 	BOOT_TYPE_EMMC,
25 	BOOT_TYPE_SPI_NOR,
26 	BOOT_TYPE_SPI_NAND,
27 	BOOT_TYPE_SD0,
28 	BOOT_TYPE_UNKNOWN,
29 	BOOT_TYPE_UNKNOWN,
30 	BOOT_TYPE_UNKNOWN,
31 	BOOT_TYPE_UNKNOWN,
32 	BOOT_TYPE_UNKNOWN
33 };
34 
35 static int spl_bootdev_map[] = {
36 	BOOT_TYPE_RAM,
37 	BOOT_TYPE_EMMC,
38 	BOOT_TYPE_SD0,
39 	BOOT_TYPE_UNKNOWN,
40 	BOOT_TYPE_NAND,
41 	BOOT_TYPE_UNKNOWN,
42 	BOOT_TYPE_UNKNOWN,
43 	BOOT_TYPE_UNKNOWN,
44 	BOOT_TYPE_UNKNOWN,
45 	BOOT_TYPE_UNKNOWN,
46 	BOOT_TYPE_UNKNOWN,
47 	BOOT_TYPE_UNKNOWN,
48 	BOOT_TYPE_UNKNOWN,
49 	BOOT_TYPE_UNKNOWN,
50 	BOOT_TYPE_UNKNOWN,
51 	BOOT_TYPE_UNKNOWN,
52 	BOOT_TYPE_MTD_BLK_NAND,
53 	BOOT_TYPE_MTD_BLK_SPI_NAND,
54 	BOOT_TYPE_MTD_BLK_SPI_NOR
55 };
56 #endif
57 
58 #if CONFIG_IS_ENABLED(TINY_FRAMEWORK) &&		\
59 	!CONFIG_IS_ENABLED(LIBGENERIC_SUPPORT) &&	\
60 	!CONFIG_IS_ENABLED(USE_ARCH_MEMSET)
61 /**
62  * memset - Fill a region of memory with the given value
63  * @s: Pointer to the start of the area.
64  * @c: The byte to fill the area with
65  * @count: The size of the area.
66  *
67  * Do not use memset() to access IO space, use memset_io() instead.
68  */
memset(void * s,int c,size_t count)69 void *memset(void *s, int c, size_t count)
70 {
71 	unsigned long *sl = (unsigned long *)s;
72 	char *s8;
73 
74 	s8 = (char *)sl;
75 	while (count--)
76 		*s8++ = c;
77 
78 	return s;
79 }
80 #endif
81 
82 #if CONFIG_IS_ENABLED(TINY_FRAMEWORK) &&		\
83 	!CONFIG_IS_ENABLED(LIBGENERIC_SUPPORT) &&	\
84 	!CONFIG_IS_ENABLED(USE_ARCH_MEMCPY)
85 /**
86  * memcpy - Copy one area of memory to another
87  * @dest: Where to copy to
88  * @src: Where to copy from
89  * @count: The size of the area.
90  *
91  * You should not use this function to access IO space, use memcpy_toio()
92  * or memcpy_fromio() instead.
93  */
memcpy(void * dest,const void * src,size_t count)94 void *memcpy(void *dest, const void *src, size_t count)
95 {
96 	unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
97 	char *d8, *s8;
98 
99 	if (src == dest)
100 		return dest;
101 
102 	/* while all data is aligned (common case), copy a word at a time */
103 	if ((((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) {
104 		while (count >= sizeof(*dl)) {
105 			*dl++ = *sl++;
106 			count -= sizeof(*dl);
107 		}
108 	}
109 	/* copy the reset one byte at a time */
110 	d8 = (char *)dl;
111 	s8 = (char *)sl;
112 	while (count--)
113 		*d8++ = *s8++;
114 
115 	return dest;
116 }
117 #endif
118 
js_hash(void * buf,u32 len)119 static u32 js_hash(void *buf, u32 len)
120 {
121 	u32 i, hash = 0x47C6A7E6;
122 	char *data = buf;
123 
124 	if (!buf || !len)
125 		return hash;
126 
127 	for (i = 0; i < len; i++)
128 		hash ^= ((hash << 5) + data[i] + (hash >> 2));
129 
130 	return hash;
131 }
132 
atags_bad_magic(u32 magic)133 int atags_bad_magic(u32 magic)
134 {
135 	bool bad;
136 
137 	bad = ((magic != ATAG_CORE) &&
138 	       (magic != ATAG_NONE) &&
139 	       (magic < ATAG_SERIAL || magic > ATAG_MAX));
140 	if (bad) {
141 #if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
142 		printf("Magic(%x) is not support\n", magic);
143 #else
144 		printascii("Magic is not support\n");
145 #endif
146 	}
147 
148 	return bad;
149 }
150 
atags_size_overflow(struct tag * t,u32 tag_size)151 static int inline atags_size_overflow(struct tag *t, u32 tag_size)
152 {
153 	return (unsigned long)t + (tag_size << 2) - ATAGS_PHYS_BASE > ATAGS_SIZE;
154 }
155 
atags_overflow(struct tag * t)156 int atags_overflow(struct tag *t)
157 {
158 	bool overflow;
159 
160 	overflow = atags_size_overflow(t, 0) ||
161 		   atags_size_overflow(t, t->hdr.size);
162 	if (overflow) {
163 #if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
164 		printf("Tag is overflow\n");
165 #else
166 		printascii("Tag is overflow\n");
167 #endif
168 	}
169 
170 	return overflow;
171 }
172 
atags_is_available(void)173 int atags_is_available(void)
174 {
175 	struct tag *t = (struct tag *)ATAGS_PHYS_BASE;
176 
177 	return (t->hdr.magic == ATAG_CORE);
178 }
179 
atags_set_tag(u32 magic,void * tagdata)180 int atags_set_tag(u32 magic, void *tagdata)
181 {
182 	u32 length, size = 0, hash;
183 	struct tag *t = (struct tag *)ATAGS_PHYS_BASE;
184 
185 #if !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_FPGA_ROCKCHIP)
186 	if (!atags_is_available())
187 		return -EPERM;
188 #endif
189 
190 	if (!tagdata)
191 		return -ENODATA;
192 
193 	if (atags_bad_magic(magic))
194 		return -EINVAL;
195 
196 	/* Not allowed to be set by user directly, so do nothing */
197 	if ((magic == ATAG_CORE) || (magic == ATAG_NONE))
198 		return -EPERM;
199 
200 	/* If not initialized, setup now! */
201 	if (t->hdr.magic != ATAG_CORE) {
202 		t->hdr.magic = ATAG_CORE;
203 		t->hdr.size = tag_size(tag_core);
204 		t->u.core.flags = 0;
205 		t->u.core.pagesize = 0;
206 		t->u.core.rootdev = 0;
207 
208 		t = tag_next(t);
209 	} else {
210 		/* Find the end, and use it as a new tag */
211 		for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
212 			if (atags_overflow(t))
213 				return -EINVAL;
214 
215 			if (atags_bad_magic(t->hdr.magic))
216 				return -EINVAL;
217 
218 			/* This is an old tag, override it */
219 			if (t->hdr.magic == magic)
220 				break;
221 
222 			if (t->hdr.magic == ATAG_NONE)
223 				break;
224 		}
225 	}
226 
227 	/* Initialize new tag */
228 	switch (magic) {
229 	case ATAG_SERIAL:
230 		size = tag_size(tag_serial);
231 		break;
232 	case ATAG_BOOTDEV:
233 		size = tag_size(tag_bootdev);
234 		break;
235 	case ATAG_TOS_MEM:
236 		size = tag_size(tag_tos_mem);
237 		break;
238 	case ATAG_DDR_MEM:
239 		size = tag_size(tag_ddr_mem);
240 		break;
241 	case ATAG_RAM_PARTITION:
242 		size = tag_size(tag_ram_partition);
243 		break;
244 	case ATAG_ATF_MEM:
245 		size = tag_size(tag_atf_mem);
246 		break;
247 	case ATAG_PUB_KEY:
248 		size = tag_size(tag_pub_key);
249 		break;
250 	case ATAG_SOC_INFO:
251 		size = tag_size(tag_soc_info);
252 		break;
253 	case ATAG_BOOT1_PARAM:
254 		size = tag_size(tag_boot1p);
255 		break;
256 	case ATAG_PSTORE:
257 		size = tag_size(tag_pstore);
258 		break;
259 	};
260 
261 	if (!size)
262 		return -EINVAL;
263 
264 	if (atags_size_overflow(t, size))
265 		return -ENOMEM;
266 
267 	/* It's okay to setup a new tag */
268 	t->hdr.magic = magic;
269 	t->hdr.size = size;
270 	length = (t->hdr.size << 2) - sizeof(struct tag_header) - HASH_LEN;
271 	memcpy(&t->u, (char *)tagdata, length);
272 	hash = js_hash(t, (size << 2) - HASH_LEN);
273 	memcpy((char *)&t->u + length, &hash, HASH_LEN);
274 
275 	/* Next tag */
276 	t = tag_next(t);
277 
278 	/* Setup done */
279 	t->hdr.magic = ATAG_NONE;
280 	t->hdr.size = 0;
281 
282 	return 0;
283 }
284 
285 #ifndef CONFIG_TPL_BUILD
atags_get_tag(u32 magic)286 struct tag *atags_get_tag(u32 magic)
287 {
288 	u32 *hash, calc_hash, size;
289 	struct tag *t;
290 
291 	if (!atags_is_available())
292 		return NULL;
293 
294 	for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
295 		if (atags_overflow(t))
296 			return NULL;
297 
298 		if (atags_bad_magic(t->hdr.magic))
299 			return NULL;
300 
301 		if (t->hdr.magic != magic)
302 			continue;
303 
304 		size = t->hdr.size;
305 		hash = (u32 *)((ulong)t + (size << 2) - HASH_LEN);
306 		if (!*hash) {
307 			debug("No hash, magic(%x)\n", magic);
308 			return t;
309 		} else {
310 			calc_hash = js_hash(t, (size << 2) - HASH_LEN);
311 			if (calc_hash == *hash) {
312 				debug("Hash okay, magic(%x)\n", magic);
313 				return t;
314 			} else {
315 				debug("Hash bad, magic(%x), orgHash=%x, nowHash=%x\n",
316 				      magic, *hash, calc_hash);
317 				return NULL;
318 			}
319 		}
320 	}
321 
322 	return NULL;
323 }
324 #else
atags_get_tag(u32 magic)325 struct tag *atags_get_tag(u32 magic) { return NULL; }
326 #endif
327 
328 #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
get_bootdev_by_brom_bootsource(void)329 int get_bootdev_by_brom_bootsource(void)
330 {
331 	int bootsource = 0;
332 
333 	bootsource = readl(BROM_BOOTSOURCE_ID_ADDR);
334 	if (bootsource > ARRAY_SIZE(bootdev_map) - 1 || bootsource < 0)
335 		return 0;
336 	else
337 		return bootdev_map[bootsource];
338 }
339 
atags_set_bootdev_by_brom_bootsource(void)340 int atags_set_bootdev_by_brom_bootsource(void)
341 {
342 	struct tag_bootdev boot_dev;
343 
344 	memset(&boot_dev, 0, sizeof(struct tag_bootdev));
345 	boot_dev.devtype = get_bootdev_by_brom_bootsource();
346 
347 	return atags_set_tag(ATAG_BOOTDEV, &boot_dev);
348 }
349 
get_bootdev_by_spl_bootdevice(int bootdevice)350 int get_bootdev_by_spl_bootdevice(int bootdevice)
351 {
352 	if (bootdevice > ARRAY_SIZE(spl_bootdev_map) - 1)
353 		return -ENODEV;
354 
355 	return spl_bootdev_map[bootdevice];
356 }
357 
atags_set_bootdev_by_spl_bootdevice(int bootdevice)358 int atags_set_bootdev_by_spl_bootdevice(int bootdevice)
359 {
360 	struct tag_bootdev boot_dev;
361 
362 	memset(&boot_dev, 0, sizeof(struct tag_bootdev));
363 	boot_dev.devtype = get_bootdev_by_spl_bootdevice(bootdevice);
364 	if (boot_dev.devtype < 0)
365 		boot_dev.devtype = BOOT_TYPE_UNKNOWN;
366 
367 	return atags_set_tag(ATAG_BOOTDEV, &boot_dev);
368 }
369 
atags_set_pub_key(void * data,int len,int flag)370 int atags_set_pub_key(void *data, int len, int flag)
371 {
372 	struct tag_pub_key pub_key;
373 
374 	if (!data)
375 		return -ENOMEM;
376 
377 	memset(&pub_key, 0, sizeof(struct tag_pub_key));
378 	pub_key.len = len;
379 	pub_key.flag = flag;
380 	memcpy(pub_key.data, data, len);
381 
382 	return atags_set_tag(ATAG_PUB_KEY, &pub_key);
383 }
384 #endif
385 
atags_destroy(void)386 void atags_destroy(void)
387 {
388 	if (atags_is_available())
389 		memset((char *)ATAGS_PHYS_BASE, 0, sizeof(struct tag));
390 }
391 
392