1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2011-2012
4 * Pali Rohár <pali@kernel.org>
5 */
6
7#include <config.h>
8#include <linux/linkage.h>
9
10kernoffs:		/* offset of kernel image from this address */
11	.word . - CONFIG_TEXT_BASE - KERNEL_OFFSET
12
13kernaddr:		/* address of kernel after copying */
14	.word KERNEL_ADDRESS
15
16kernsize:		/* maximal size of kernel image */
17	.word KERNEL_MAXSIZE
18
19imagesize:		/* maximal size of image */
20	.word IMAGE_MAXSIZE
21
22ih_magic:		/* IH_MAGIC in big endian from include/image.h */
23	.word 0x56190527
24
25z_magic:		/* LINUX_ARM_ZIMAGE_MAGIC */
26	.word 0x016f2818
27
28/*
29 * Routine: save_boot_params (called after reset from start.S)
30 * Description: Copy attached kernel to address KERNEL_ADDRESS
31 */
32
33ENTRY(save_boot_params)
34
35/*
36 * Copy valid attached kernel to absolute address KERNEL_ADDRESS
37 *
38 * Nokia X-Loader is loading secondary image to address 0x80400000.
39 * NOLO is loading boot image to random place, so it doesn't really
40 * matter what is set in CONFIG_TEXT_BASE. We have to detect
41 * KERNEL_OFFSET from the current execution address and copy it to
42 * absolute address KERNEL_ADDRESS.
43 *
44 * Note that U-Boot has to be compiled with CONFIG_POSITION_INDEPENDENT
45 * because it is loaded at random address and not to the fixed address
46 * (CONFIG_TEXT_BASE).
47 */
48
49	/* r0 - start of kernel before */
50	adr	r0, kernoffs	/* r0 - current address of kernoffs section */
51	ldr	r1, kernoffs	/* r1 - offset of kernel image from kernoffs section */
52	sub	r0, r0, r1
53
54	/* r3 - start of kernel after */
55	ldr	r3, kernaddr
56
57	/* r2 - end of kernel after */
58	ldr	r1, kernsize
59	add	r2, r3, r1
60
61	/* r1 - end of kernel before */
62	add	r1, r0, r1
63
64	/* remove header in target kernel */
65	mov	r5, #0
66	str	r5, [r3]	/* remove 4 bytes header of kernel uImage */
67	str	r5, [r3, #36]	/* remove 4 bytes header of kernel zImage */
68
69	/* check for valid kernel uImage */
70	ldr	r4, [r0]	/* r4 - 4 bytes header of kernel */
71	ldr	r5, ih_magic	/* r5 - IH_MAGIC */
72	cmp	r4, r5
73	beq	copy_kernel_loop
74
75	/* check for valid kernel zImage */
76	ldr	r4, [r0, #36]	/* r4 - 4 bytes header of kernel at offset 36 */
77	ldr	r5, z_magic	/* r5 - LINUX_ARM_ZIMAGE_MAGIC */
78	cmp	r4, r5
79	bne	skip_copy	/* skip if invalid image */
80
81copy_kernel_loop:
82	ldmdb	r1!, {r3 - r10}
83	stmdb	r2!, {r3 - r10}
84	cmp	r1, r0
85	bhi	copy_kernel_loop
86
87	/* remove header in source kernel image */
88	mov	r5, #0
89	str	r5, [r0]	/* remove 4 bytes header of kernel uImage */
90	str	r5, [r0, #36]	/* remove 4 bytes header of kernel zImage */
91
92skip_copy:
93
94	/* Returns */
95	b	save_boot_params_ret
96
97ENDPROC(save_boot_params)
98