blob: 1de06b7fb53daaf3bb978957f633b441f72075d8 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Chris Zankel1387dab2016-08-10 18:36:44 +03002/*
3 * (C) Copyright 2008 - 2013 Tensilica Inc.
4 * (C) Copyright 2014 Cadence Design Systems Inc.
Chris Zankel1387dab2016-08-10 18:36:44 +03005 */
6
Simon Glass0726d9d2023-12-15 20:14:13 -07007#include <bootm.h>
Simon Glass1ea97892020-05-10 11:40:00 -06008#include <bootstage.h>
Chris Zankel1387dab2016-08-10 18:36:44 +03009#include <command.h>
Simon Glass63334482019-11-14 12:57:39 -070010#include <cpu_func.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -060011#include <env.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060012#include <asm/global_data.h>
Chris Zankel1387dab2016-08-10 18:36:44 +030013#include <u-boot/zlib.h>
14#include <asm/byteorder.h>
15#include <asm/addrspace.h>
16#include <asm/bootparam.h>
17#include <asm/cache.h>
18#include <image.h>
19
20DECLARE_GLOBAL_DATA_PTR;
21
22/*
23 * Setup boot-parameters.
24 */
25
26static struct bp_tag *setup_first_tag(struct bp_tag *params)
27{
28 params->id = BP_TAG_FIRST;
29 params->size = sizeof(long);
30 *(unsigned long *)&params->data = BP_VERSION;
31
32 return bp_tag_next(params);
33}
34
35static struct bp_tag *setup_last_tag(struct bp_tag *params)
36{
37 params->id = BP_TAG_LAST;
38 params->size = 0;
39
40 return bp_tag_next(params);
41}
42
43static struct bp_tag *setup_memory_tag(struct bp_tag *params)
44{
Chris Zankel1387dab2016-08-10 18:36:44 +030045 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;
Stefan Roesea13a2aa2020-08-12 13:16:36 +020051 mem->start = PHYSADDR(gd->ram_base);
52 mem->end = PHYSADDR(gd->ram_base + gd->ram_size);
Chris Zankel1387dab2016-08-10 18:36:44 +030053
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
60static 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
80static 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
105static 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
119static 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
Simon Glass0726d9d2023-12-15 20:14:13 -0700137int do_bootm_linux(int flag, struct bootm_info *bmi)
Chris Zankel1387dab2016-08-10 18:36:44 +0300138{
Simon Glass0726d9d2023-12-15 20:14:13 -0700139 struct bootm_headers *images = bmi->images;
Chris Zankel1387dab2016-08-10 18:36:44 +0300140 struct bp_tag *params, *params_start;
141 ulong initrd_start, initrd_end;
Simon Glass64b723f2017-08-03 12:22:12 -0600142 char *commandline = env_get("bootargs");
Chris Zankel1387dab2016-08-10 18:36:44 +0300143
144 if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
145 return 0;
146
147 show_boot_progress(15);
148
149 if (images->rd_start) {
150 initrd_start = images->rd_start;
151 initrd_end = images->rd_end;
152 } else {
153 initrd_start = 0;
154 initrd_end = 0;
155 }
156
157 params_start = (struct bp_tag *)gd->bd->bi_boot_params;
158 params = params_start;
159 params = setup_first_tag(params);
160 params = setup_memory_tag(params);
161 params = setup_commandline_tag(params, commandline);
162 params = setup_serial_tag(params);
163
164 if (initrd_start)
165 params = setup_ramdisk_tag(params, initrd_start, initrd_end);
166
167#ifdef CONFIG_OF_LIBFDT
168 if (images->ft_addr)
169 params = setup_fdt_tag(params, images->ft_addr);
170#endif
171
172 printf("\n");
173
174 params = setup_last_tag(params);
175
176 show_boot_progress(15);
177
178 printf("Transferring Control to Linux @0x%08lx ...\n\n",
179 (ulong)images->ep);
180
181 flush_dcache_range((unsigned long)params_start, (unsigned long)params);
182
183 if (flag & BOOTM_STATE_OS_FAKE_GO)
184 return 0;
185
186 /*
187 * _start() in vmlinux expects boot params in register a2.
188 * NOTE:
189 * Disable/delete your u-boot breakpoints before stepping into linux.
190 */
191 asm volatile ("mov a2, %0\n\t"
192 "jx %1\n\t"
193 : : "a" (params_start), "a" (images->ep)
194 : "a2");
195
196 /* Does not return */
197
198 return 1;
199}
200
Marek Vasut0701ff32021-09-10 22:47:17 +0200201static ulong get_sp(void)
202{
203 ulong ret;
204
205 asm("mov %0, a1" : "=r"(ret) : );
206 return ret;
207}
208
209void arch_lmb_reserve(struct lmb *lmb)
210{
211 arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096);
212}