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