blob: b17368647d357581e0866c55029968ab923019d7 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Macpaul Lin463d47f2011-10-11 22:33:19 +00002/*
3 * Copyright (C) 2011 Andes Technology Corporation
4 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
5 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
Macpaul Lin463d47f2011-10-11 22:33:19 +00006 */
7
8#include <common.h>
Simon Glass52f24232020-05-10 11:40:00 -06009#include <bootstage.h>
Macpaul Lin463d47f2011-10-11 22:33:19 +000010#include <command.h>
Simon Glass7b51b572019-08-01 09:46:52 -060011#include <env.h>
Simon Glassdb41d652019-12-28 10:45:07 -070012#include <hang.h>
Macpaul Lin463d47f2011-10-11 22:33:19 +000013#include <image.h>
14#include <u-boot/zlib.h>
15#include <asm/byteorder.h>
rickb841b6e2017-05-18 14:37:53 +080016#include <asm/bootm.h>
Macpaul Lin463d47f2011-10-11 22:33:19 +000017
18DECLARE_GLOBAL_DATA_PTR;
19
20#if defined(CONFIG_SETUP_MEMORY_TAGS) || \
21 defined(CONFIG_CMDLINE_TAG) || \
22 defined(CONFIG_INITRD_TAG) || \
23 defined(CONFIG_SERIAL_TAG) || \
24 defined(CONFIG_REVISION_TAG)
25static void setup_start_tag(bd_t *bd);
26
27# ifdef CONFIG_SETUP_MEMORY_TAGS
28static void setup_memory_tags(bd_t *bd);
29# endif
30static void setup_commandline_tag(bd_t *bd, char *commandline);
31
32# ifdef CONFIG_INITRD_TAG
33static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end);
34# endif
35static void setup_end_tag(bd_t *bd);
36
37static struct tag *params;
38#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
39
40int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
41{
42 bd_t *bd = gd->bd;
43 char *s;
44 int machid = bd->bi_arch_number;
45 void (*theKernel)(int zero, int arch, uint params);
46
47#ifdef CONFIG_CMDLINE_TAG
Simon Glass00caae62017-08-03 12:22:12 -060048 char *commandline = env_get("bootargs");
Macpaul Lin463d47f2011-10-11 22:33:19 +000049#endif
50
Andreas Bießmann2cb0e552013-07-02 13:57:44 +020051 /*
52 * allow the PREP bootm subcommand, it is required for bootm to work
53 */
54 if (flag & BOOTM_STATE_OS_PREP)
55 return 0;
56
Macpaul Lin463d47f2011-10-11 22:33:19 +000057 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
58 return 1;
59
60 theKernel = (void (*)(int, int, uint))images->ep;
61
Simon Glass00caae62017-08-03 12:22:12 -060062 s = env_get("machid");
Macpaul Lin463d47f2011-10-11 22:33:19 +000063 if (s) {
64 machid = simple_strtoul(s, NULL, 16);
65 printf("Using machid 0x%x from environment\n", machid);
66 }
67
Simon Glass770605e2012-02-13 13:51:18 +000068 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
Macpaul Lin463d47f2011-10-11 22:33:19 +000069
70 debug("## Transferring control to Linux (at address %08lx) ...\n",
71 (ulong)theKernel);
72
rickb841b6e2017-05-18 14:37:53 +080073 if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
74#ifdef CONFIG_OF_LIBFDT
75 debug("using: FDT\n");
76 if (image_setup_linux(images)) {
77 printf("FDT creation failed! hanging...");
78 hang();
79 }
80#endif
81 } else if (BOOTM_ENABLE_TAGS) {
Macpaul Lin463d47f2011-10-11 22:33:19 +000082#if defined(CONFIG_SETUP_MEMORY_TAGS) || \
83 defined(CONFIG_CMDLINE_TAG) || \
84 defined(CONFIG_INITRD_TAG) || \
85 defined(CONFIG_SERIAL_TAG) || \
86 defined(CONFIG_REVISION_TAG)
87 setup_start_tag(bd);
88#ifdef CONFIG_SERIAL_TAG
89 setup_serial_tag(&params);
90#endif
91#ifdef CONFIG_REVISION_TAG
92 setup_revision_tag(&params);
93#endif
94#ifdef CONFIG_SETUP_MEMORY_TAGS
95 setup_memory_tags(bd);
96#endif
97#ifdef CONFIG_CMDLINE_TAG
98 setup_commandline_tag(bd, commandline);
99#endif
100#ifdef CONFIG_INITRD_TAG
101 if (images->rd_start && images->rd_end)
102 setup_initrd_tag(bd, images->rd_start, images->rd_end);
103#endif
104 setup_end_tag(bd);
105#endif
106
107 /* we assume that the kernel is in place */
108 printf("\nStarting kernel ...\n\n");
109
110#ifdef CONFIG_USB_DEVICE
111 {
112 extern void udc_disconnect(void);
113 udc_disconnect();
114 }
115#endif
rickb841b6e2017-05-18 14:37:53 +0800116 }
Macpaul Lin463d47f2011-10-11 22:33:19 +0000117 cleanup_before_linux();
rickb841b6e2017-05-18 14:37:53 +0800118 if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
119 theKernel(0, machid, (unsigned long)images->ft_addr);
120 else
121 theKernel(0, machid, bd->bi_boot_params);
Macpaul Lin463d47f2011-10-11 22:33:19 +0000122 /* does not return */
123
124 return 1;
125}
126
Macpaul Lin463d47f2011-10-11 22:33:19 +0000127#if defined(CONFIG_SETUP_MEMORY_TAGS) || \
128 defined(CONFIG_CMDLINE_TAG) || \
129 defined(CONFIG_INITRD_TAG) || \
130 defined(CONFIG_SERIAL_TAG) || \
131 defined(CONFIG_REVISION_TAG)
132static void setup_start_tag(bd_t *bd)
133{
134 params = (struct tag *)bd->bi_boot_params;
135
136 params->hdr.tag = ATAG_CORE;
137 params->hdr.size = tag_size(tag_core);
138
139 params->u.core.flags = 0;
140 params->u.core.pagesize = 0;
141 params->u.core.rootdev = 0;
142
143 params = tag_next(params);
144}
145
Macpaul Lin463d47f2011-10-11 22:33:19 +0000146#ifdef CONFIG_SETUP_MEMORY_TAGS
147static void setup_memory_tags(bd_t *bd)
148{
149 int i;
150
151 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
152 params->hdr.tag = ATAG_MEM;
153 params->hdr.size = tag_size(tag_mem32);
154
155 params->u.mem.start = bd->bi_dram[i].start;
156 params->u.mem.size = bd->bi_dram[i].size;
157
158 params = tag_next(params);
159 }
160}
161#endif /* CONFIG_SETUP_MEMORY_TAGS */
162
Macpaul Lin463d47f2011-10-11 22:33:19 +0000163static void setup_commandline_tag(bd_t *bd, char *commandline)
164{
165 char *p;
166
167 if (!commandline)
168 return;
169
170 /* eat leading white space */
171 for (p = commandline; *p == ' '; p++)
172 ;
173
174 /* skip non-existent command lines so the kernel will still
175 * use its default command line.
176 */
177 if (*p == '\0')
178 return;
179
180 params->hdr.tag = ATAG_CMDLINE;
181 params->hdr.size =
182 (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
183
184 strcpy(params->u.cmdline.cmdline, p)
185 ;
186
187 params = tag_next(params);
188}
189
Macpaul Lin463d47f2011-10-11 22:33:19 +0000190#ifdef CONFIG_INITRD_TAG
191static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end)
192{
193 /* an ATAG_INITRD node tells the kernel where the compressed
194 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
195 */
196 params->hdr.tag = ATAG_INITRD2;
197 params->hdr.size = tag_size(tag_initrd);
198
199 params->u.initrd.start = initrd_start;
200 params->u.initrd.size = initrd_end - initrd_start;
201
202 params = tag_next(params);
203}
204#endif /* CONFIG_INITRD_TAG */
205
206#ifdef CONFIG_SERIAL_TAG
207void setup_serial_tag(struct tag **tmp)
208{
209 struct tag *params = *tmp;
210 struct tag_serialnr serialnr;
211 void get_board_serial(struct tag_serialnr *serialnr);
212
213 get_board_serial(&serialnr);
214 params->hdr.tag = ATAG_SERIAL;
215 params->hdr.size = tag_size(tag_serialnr);
216 params->u.serialnr.low = serialnr.low;
217 params->u.serialnr.high = serialnr.high;
218 params = tag_next(params);
219 *tmp = params;
220}
221#endif
222
223#ifdef CONFIG_REVISION_TAG
224void setup_revision_tag(struct tag **in_params)
225{
226 u32 rev = 0;
227 u32 get_board_rev(void);
228
229 rev = get_board_rev();
230 params->hdr.tag = ATAG_REVISION;
231 params->hdr.size = tag_size(tag_revision);
232 params->u.revision.rev = rev;
233 params = tag_next(params);
234}
235#endif /* CONFIG_REVISION_TAG */
236
Macpaul Lin463d47f2011-10-11 22:33:19 +0000237static void setup_end_tag(bd_t *bd)
238{
239 params->hdr.tag = ATAG_NONE;
240 params->hdr.size = 0;
241}
242
243#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */