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