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