Merge branch '2020-05-18-reduce-size-of-common.h'
[oweals/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 bd_info *bd = gd->bd;
45         struct meminfo *mem;
46
47         params->id = BP_TAG_MEMORY;
48         params->size = sizeof(struct meminfo);
49         mem = (struct meminfo *)params->data;
50         mem->type = MEMORY_TYPE_CONVENTIONAL;
51         mem->start = bd->bi_memstart;
52         mem->end = bd->bi_memstart + bd->bi_memsize;
53
54         printf("   MEMORY:          tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n",
55                BP_TAG_MEMORY, mem->type, mem->start, mem->end);
56
57         return bp_tag_next(params);
58 }
59
60 static struct bp_tag *setup_commandline_tag(struct bp_tag *params,
61                                             char *cmdline)
62 {
63         int len;
64
65         if (!cmdline)
66                 return params;
67
68         len = strlen(cmdline);
69
70         params->id = BP_TAG_COMMAND_LINE;
71         params->size = (len + 3) & -4;
72         strcpy((char *)params->data, cmdline);
73
74         printf("   COMMAND_LINE:    tag:0x%04x, size:%u, data:'%s'\n",
75                BP_TAG_COMMAND_LINE, params->size, cmdline);
76
77         return bp_tag_next(params);
78 }
79
80 static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params,
81                                         unsigned long rd_start,
82                                         unsigned long rd_end)
83 {
84         struct meminfo *mem;
85
86         if (rd_start == rd_end)
87                 return params;
88
89         /* Add a single banked memory */
90
91         params->id = BP_TAG_INITRD;
92         params->size = sizeof(struct meminfo);
93
94         mem = (struct meminfo *)params->data;
95         mem->type =  MEMORY_TYPE_CONVENTIONAL;
96         mem->start = PHYSADDR(rd_start);
97         mem->end = PHYSADDR(rd_end);
98
99         printf("   INITRD:          tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n",
100                BP_TAG_INITRD, mem->type, mem->start, mem->end);
101
102         return bp_tag_next(params);
103 }
104
105 static struct bp_tag *setup_serial_tag(struct bp_tag *params)
106 {
107         params->id = BP_TAG_SERIAL_BAUDRATE;
108         params->size = sizeof(unsigned long);
109         params->data[0] = gd->baudrate;
110
111         printf("   SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n",
112                BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]);
113
114         return bp_tag_next(params);
115 }
116
117 #ifdef CONFIG_OF_LIBFDT
118
119 static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
120 {
121         params->id = BP_TAG_FDT;
122         params->size = sizeof(unsigned long);
123         params->data[0] = (unsigned long)fdt_start;
124
125         printf("   FDT:             tag:0x%04x, size:%u, start:0x%lx\n",
126                BP_TAG_FDT, params->size, params->data[0]);
127
128         return bp_tag_next(params);
129 }
130
131 #endif
132
133 /*
134  * Boot Linux.
135  */
136
137 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
138 {
139         struct bp_tag *params, *params_start;
140         ulong initrd_start, initrd_end;
141         char *commandline = env_get("bootargs");
142
143         if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
144                 return 0;
145
146         show_boot_progress(15);
147
148         if (images->rd_start) {
149                 initrd_start = images->rd_start;
150                 initrd_end = images->rd_end;
151         } else {
152                 initrd_start = 0;
153                 initrd_end = 0;
154         }
155
156         params_start = (struct bp_tag *)gd->bd->bi_boot_params;
157         params = params_start;
158         params = setup_first_tag(params);
159         params = setup_memory_tag(params);
160         params = setup_commandline_tag(params, commandline);
161         params = setup_serial_tag(params);
162
163         if (initrd_start)
164                 params = setup_ramdisk_tag(params, initrd_start, initrd_end);
165
166 #ifdef CONFIG_OF_LIBFDT
167         if (images->ft_addr)
168                 params = setup_fdt_tag(params, images->ft_addr);
169 #endif
170
171         printf("\n");
172
173         params = setup_last_tag(params);
174
175         show_boot_progress(15);
176
177         printf("Transferring Control to Linux @0x%08lx ...\n\n",
178                (ulong)images->ep);
179
180         flush_dcache_range((unsigned long)params_start, (unsigned long)params);
181
182         if (flag & BOOTM_STATE_OS_FAKE_GO)
183                 return 0;
184
185         /*
186          * _start() in vmlinux expects boot params in register a2.
187          * NOTE:
188          *    Disable/delete your u-boot breakpoints before stepping into linux.
189          */
190         asm volatile ("mov      a2, %0\n\t"
191                       "jx       %1\n\t"
192                       : : "a" (params_start), "a" (images->ep)
193                       : "a2");
194
195         /* Does not return */
196
197         return 1;
198 }
199