Merge tag 'xilinx-for-v2021.01' of https://gitlab.denx.de/u-boot/custodians/u-boot...
[platform/kernel/u-boot.git] / arch / xtensa / lib / bootm.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008 - 2013 Tensilica Inc.
4  * (C) Copyright 2014 Cadence Design Systems Inc.
5  */
6
7 #include <common.h>
8 #include <bootstage.h>
9 #include <command.h>
10 #include <cpu_func.h>
11 #include <env.h>
12 #include <u-boot/zlib.h>
13 #include <asm/byteorder.h>
14 #include <asm/addrspace.h>
15 #include <asm/bootparam.h>
16 #include <asm/cache.h>
17 #include <image.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 /*
22  * Setup boot-parameters.
23  */
24
25 static struct bp_tag *setup_first_tag(struct bp_tag *params)
26 {
27         params->id = BP_TAG_FIRST;
28         params->size = sizeof(long);
29         *(unsigned long *)&params->data = BP_VERSION;
30
31         return bp_tag_next(params);
32 }
33
34 static struct bp_tag *setup_last_tag(struct bp_tag *params)
35 {
36         params->id = BP_TAG_LAST;
37         params->size = 0;
38
39         return bp_tag_next(params);
40 }
41
42 static struct bp_tag *setup_memory_tag(struct bp_tag *params)
43 {
44         struct meminfo *mem;
45
46         params->id = BP_TAG_MEMORY;
47         params->size = sizeof(struct meminfo);
48         mem = (struct meminfo *)params->data;
49         mem->type = MEMORY_TYPE_CONVENTIONAL;
50         mem->start = PHYSADDR(gd->ram_base);
51         mem->end = PHYSADDR(gd->ram_base + gd->ram_size);
52
53         printf("   MEMORY:          tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n",
54                BP_TAG_MEMORY, mem->type, mem->start, mem->end);
55
56         return bp_tag_next(params);
57 }
58
59 static struct bp_tag *setup_commandline_tag(struct bp_tag *params,
60                                             char *cmdline)
61 {
62         int len;
63
64         if (!cmdline)
65                 return params;
66
67         len = strlen(cmdline);
68
69         params->id = BP_TAG_COMMAND_LINE;
70         params->size = (len + 3) & -4;
71         strcpy((char *)params->data, cmdline);
72
73         printf("   COMMAND_LINE:    tag:0x%04x, size:%u, data:'%s'\n",
74                BP_TAG_COMMAND_LINE, params->size, cmdline);
75
76         return bp_tag_next(params);
77 }
78
79 static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params,
80                                         unsigned long rd_start,
81                                         unsigned long rd_end)
82 {
83         struct meminfo *mem;
84
85         if (rd_start == rd_end)
86                 return params;
87
88         /* Add a single banked memory */
89
90         params->id = BP_TAG_INITRD;
91         params->size = sizeof(struct meminfo);
92
93         mem = (struct meminfo *)params->data;
94         mem->type =  MEMORY_TYPE_CONVENTIONAL;
95         mem->start = PHYSADDR(rd_start);
96         mem->end = PHYSADDR(rd_end);
97
98         printf("   INITRD:          tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n",
99                BP_TAG_INITRD, mem->type, mem->start, mem->end);
100
101         return bp_tag_next(params);
102 }
103
104 static struct bp_tag *setup_serial_tag(struct bp_tag *params)
105 {
106         params->id = BP_TAG_SERIAL_BAUDRATE;
107         params->size = sizeof(unsigned long);
108         params->data[0] = gd->baudrate;
109
110         printf("   SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n",
111                BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]);
112
113         return bp_tag_next(params);
114 }
115
116 #ifdef CONFIG_OF_LIBFDT
117
118 static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
119 {
120         params->id = BP_TAG_FDT;
121         params->size = sizeof(unsigned long);
122         params->data[0] = (unsigned long)fdt_start;
123
124         printf("   FDT:             tag:0x%04x, size:%u, start:0x%lx\n",
125                BP_TAG_FDT, params->size, params->data[0]);
126
127         return bp_tag_next(params);
128 }
129
130 #endif
131
132 /*
133  * Boot Linux.
134  */
135
136 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
137 {
138         struct bp_tag *params, *params_start;
139         ulong initrd_start, initrd_end;
140         char *commandline = env_get("bootargs");
141
142         if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
143                 return 0;
144
145         show_boot_progress(15);
146
147         if (images->rd_start) {
148                 initrd_start = images->rd_start;
149                 initrd_end = images->rd_end;
150         } else {
151                 initrd_start = 0;
152                 initrd_end = 0;
153         }
154
155         params_start = (struct bp_tag *)gd->bd->bi_boot_params;
156         params = params_start;
157         params = setup_first_tag(params);
158         params = setup_memory_tag(params);
159         params = setup_commandline_tag(params, commandline);
160         params = setup_serial_tag(params);
161
162         if (initrd_start)
163                 params = setup_ramdisk_tag(params, initrd_start, initrd_end);
164
165 #ifdef CONFIG_OF_LIBFDT
166         if (images->ft_addr)
167                 params = setup_fdt_tag(params, images->ft_addr);
168 #endif
169
170         printf("\n");
171
172         params = setup_last_tag(params);
173
174         show_boot_progress(15);
175
176         printf("Transferring Control to Linux @0x%08lx ...\n\n",
177                (ulong)images->ep);
178
179         flush_dcache_range((unsigned long)params_start, (unsigned long)params);
180
181         if (flag & BOOTM_STATE_OS_FAKE_GO)
182                 return 0;
183
184         /*
185          * _start() in vmlinux expects boot params in register a2.
186          * NOTE:
187          *    Disable/delete your u-boot breakpoints before stepping into linux.
188          */
189         asm volatile ("mov      a2, %0\n\t"
190                       "jx       %1\n\t"
191                       : : "a" (params_start), "a" (images->ep)
192                       : "a2");
193
194         /* Does not return */
195
196         return 1;
197 }
198