bios/boot/netboot: only get boot.bin as default, add linux_vexriscv netboot config
[litex.git] / litex / soc / software / bios / boot.c
1 #include <stdio.h>
2 #include <console.h>
3 #include <uart.h>
4 #include <system.h>
5 #include <crc.h>
6 #include <string.h>
7 #include <irq.h>
8
9 #include <generated/mem.h>
10 #include <generated/csr.h>
11
12 #ifdef CSR_ETHMAC_BASE
13 #include <net/microudp.h>
14 #include <net/tftp.h>
15 #endif
16
17 #include "sfl.h"
18 #include "boot.h"
19
20 extern void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr);
21
22 static void __attribute__((noreturn)) boot(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr)
23 {
24 printf("Executing booted program at 0x%08x\n", addr);
25 uart_sync();
26 irq_setmask(0);
27 irq_setie(0);
28 /* FIXME: understand why flushing icache on Vexriscv make boot fail */
29 #ifndef __vexriscv__
30 flush_cpu_icache();
31 #endif
32 flush_cpu_dcache();
33 #ifdef L2_SIZE
34 flush_l2_cache();
35 #endif
36 boot_helper(r1, r2, r3, addr);
37 while(1);
38 }
39
40 enum {
41 ACK_TIMEOUT,
42 ACK_CANCELLED,
43 ACK_OK
44 };
45
46 static int check_ack(void)
47 {
48 int recognized;
49 static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK;
50
51 timer0_en_write(0);
52 timer0_reload_write(0);
53 timer0_load_write(SYSTEM_CLOCK_FREQUENCY/4);
54 timer0_en_write(1);
55 timer0_update_value_write(1);
56 recognized = 0;
57 while(timer0_value_read()) {
58 if(uart_read_nonblock()) {
59 char c;
60 c = uart_read();
61 if((c == 'Q') || (c == '\e'))
62 return ACK_CANCELLED;
63 if(c == str[recognized]) {
64 recognized++;
65 if(recognized == SFL_MAGIC_LEN)
66 return ACK_OK;
67 } else {
68 if(c == str[0])
69 recognized = 1;
70 else
71 recognized = 0;
72 }
73 }
74 timer0_update_value_write(1);
75 }
76 return ACK_TIMEOUT;
77 }
78
79 #define MAX_FAILED 5
80
81 /* Returns 1 if other boot methods should be tried */
82 int serialboot(void)
83 {
84 struct sfl_frame frame;
85 int failed;
86 unsigned long cmdline_adr, initrdstart_adr, initrdend_adr;
87 static const char str[SFL_MAGIC_LEN+1] = SFL_MAGIC_REQ;
88 const char *c;
89 int ack_status;
90
91 printf("Booting from serial...\n");
92 printf("Press Q or ESC to abort boot completely.\n");
93
94 c = str;
95 while(*c) {
96 uart_write(*c);
97 c++;
98 }
99 ack_status = check_ack();
100 if(ack_status == ACK_TIMEOUT) {
101 printf("Timeout\n");
102 return 1;
103 }
104 if(ack_status == ACK_CANCELLED) {
105 printf("Cancelled\n");
106 return 0;
107 }
108 /* assume ACK_OK */
109
110 failed = 0;
111 cmdline_adr = initrdstart_adr = initrdend_adr = 0;
112 while(1) {
113 int i;
114 int actualcrc;
115 int goodcrc;
116
117 /* Grab one frame */
118 frame.length = uart_read();
119 frame.crc[0] = uart_read();
120 frame.crc[1] = uart_read();
121 frame.cmd = uart_read();
122 for(i=0;i<frame.length;i++)
123 frame.payload[i] = uart_read();
124
125 /* Check CRC */
126 actualcrc = ((int)frame.crc[0] << 8)|(int)frame.crc[1];
127 goodcrc = crc16(&frame.cmd, frame.length+1);
128 if(actualcrc != goodcrc) {
129 failed++;
130 if(failed == MAX_FAILED) {
131 printf("Too many consecutive errors, aborting");
132 return 1;
133 }
134 uart_write(SFL_ACK_CRCERROR);
135 continue;
136 }
137
138 /* CRC OK */
139 switch(frame.cmd) {
140 case SFL_CMD_ABORT:
141 failed = 0;
142 uart_write(SFL_ACK_SUCCESS);
143 return 1;
144 case SFL_CMD_LOAD: {
145 char *writepointer;
146
147 failed = 0;
148 writepointer = (char *)(
149 ((unsigned long)frame.payload[0] << 24)
150 |((unsigned long)frame.payload[1] << 16)
151 |((unsigned long)frame.payload[2] << 8)
152 |((unsigned long)frame.payload[3] << 0));
153 for(i=4;i<frame.length;i++)
154 *(writepointer++) = frame.payload[i];
155 uart_write(SFL_ACK_SUCCESS);
156 break;
157 }
158 case SFL_CMD_JUMP: {
159 unsigned long addr;
160
161 failed = 0;
162 addr = ((unsigned long)frame.payload[0] << 24)
163 |((unsigned long)frame.payload[1] << 16)
164 |((unsigned long)frame.payload[2] << 8)
165 |((unsigned long)frame.payload[3] << 0);
166 uart_write(SFL_ACK_SUCCESS);
167 boot(cmdline_adr, initrdstart_adr, initrdend_adr, addr);
168 break;
169 }
170 case SFL_CMD_CMDLINE:
171 failed = 0;
172 cmdline_adr = ((unsigned long)frame.payload[0] << 24)
173 |((unsigned long)frame.payload[1] << 16)
174 |((unsigned long)frame.payload[2] << 8)
175 |((unsigned long)frame.payload[3] << 0);
176 uart_write(SFL_ACK_SUCCESS);
177 break;
178 case SFL_CMD_INITRDSTART:
179 failed = 0;
180 initrdstart_adr = ((unsigned long)frame.payload[0] << 24)
181 |((unsigned long)frame.payload[1] << 16)
182 |((unsigned long)frame.payload[2] << 8)
183 |((unsigned long)frame.payload[3] << 0);
184 uart_write(SFL_ACK_SUCCESS);
185 break;
186 case SFL_CMD_INITRDEND:
187 failed = 0;
188 initrdend_adr = ((unsigned long)frame.payload[0] << 24)
189 |((unsigned long)frame.payload[1] << 16)
190 |((unsigned long)frame.payload[2] << 8)
191 |((unsigned long)frame.payload[3] << 0);
192 uart_write(SFL_ACK_SUCCESS);
193 break;
194 default:
195 failed++;
196 if(failed == MAX_FAILED) {
197 printf("Too many consecutive errors, aborting");
198 return 1;
199 }
200 uart_write(SFL_ACK_UNKNOWN);
201 break;
202 }
203 }
204 return 1;
205 }
206
207 #ifdef CSR_ETHMAC_BASE
208
209 #ifndef LOCALIP1
210 #define LOCALIP1 192
211 #define LOCALIP2 168
212 #define LOCALIP3 1
213 #define LOCALIP4 50
214 #endif
215
216 #ifndef REMOTEIP1
217 #define REMOTEIP1 192
218 #define REMOTEIP2 168
219 #define REMOTEIP3 1
220 #define REMOTEIP4 100
221 #endif
222
223 #define DEFAULT_TFTP_SERVER_PORT 69 /* IANA well known port: UDP/69 */
224 #ifndef TFTP_SERVER_PORT
225 #define TFTP_SERVER_PORT DEFAULT_TFTP_SERVER_PORT
226 #endif
227
228 static int tftp_get_v(unsigned int ip, unsigned short server_port,
229 const char *filename, char *buffer)
230 {
231 int r;
232
233 r = tftp_get(ip, server_port, filename, buffer);
234 if(r > 0)
235 printf("Successfully downloaded %d bytes from %s over TFTP\n", r, filename);
236 else
237 printf("Unable to download %s over TFTP\n", filename);
238 return r;
239 }
240
241 static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
242
243 void netboot(void)
244 {
245 int size;
246 unsigned int ip;
247 unsigned long tftp_dst_addr;
248 unsigned short tftp_port;
249
250 printf("Booting from network...\n");
251 printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
252 printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
253
254 ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
255
256 microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
257
258 tftp_port = TFTP_SERVER_PORT;
259 printf("Fetching from: UDP/%d\n", tftp_port);
260
261 #ifdef NETBOOT_LINUX_VEXRISCV
262 tftp_dst_addr = MAIN_RAM_BASE;
263 size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr);
264 if (size <= 0) {
265 printf("Network boot failed\n");
266 return;
267 }
268
269 tftp_dst_addr = MAIN_RAM_BASE + 0x02000000;
270 size = tftp_get_v(ip, tftp_port, "rootfs.cpio", (void *)tftp_dst_addr);
271 if(size <= 0) {
272 printf("No rootfs.cpio found\n");
273 return;
274 }
275
276 tftp_dst_addr = MAIN_RAM_BASE + 0x03000000;
277 size = tftp_get_v(ip, tftp_port, "rv32.dtb", (void *)tftp_dst_addr);
278 if(size <= 0) {
279 printf("No rv32.dtb found\n");
280 return;
281 }
282
283 tftp_dst_addr = MM_RAM_BASE;
284 size = tftp_get_v(ip, tftp_port, "emulator.bin", (void *)tftp_dst_addr);
285 if(size <= 0) {
286 printf("No emulator.bin found\n");
287 return;
288 }
289
290 boot(0, 0, 0, MM_RAM_BASE);
291 #else
292 tftp_dst_addr = MAIN_RAM_BASE;
293 size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)tftp_dst_addr);
294 if (size <= 0) {
295 printf("Network boot failed\n");
296 return;
297 }
298
299 boot(0, 0, 0, MAIN_RAM_BASE);
300 #endif
301
302 }
303
304 #endif
305
306 #ifdef FLASH_BOOT_ADDRESS
307
308 /* On systems with exernal SDRAM we copy out of the SPI flash into the SDRAM
309 before running, as it is faster. If we have no SDRAM then we have to
310 execute directly out of the SPI flash. */
311 #ifdef MAIN_RAM_BASE
312 #define FIRMWARE_BASE_ADDRESS MAIN_RAM_BASE
313 #else
314 /* Firmware code starts after (a) length and (b) CRC -- both unsigned ints */
315 #define FIRMWARE_BASE_ADDRESS (FLASH_BOOT_ADDRESS + 2 * sizeof(unsigned int))
316 #endif
317
318 void flashboot(void)
319 {
320 unsigned int *flashbase;
321 unsigned int length;
322 unsigned int crc;
323 unsigned int got_crc;
324
325 printf("Booting from flash...\n");
326 flashbase = (unsigned int *)FLASH_BOOT_ADDRESS;
327 length = *flashbase++;
328 crc = *flashbase++;
329 if((length < 32) || (length > 4*1024*1024)) {
330 printf("Error: Invalid flash boot image length 0x%08x\n", length);
331 return;
332 }
333
334 #ifdef MAIN_RAM_BASE
335 printf("Loading %d bytes from flash...\n", length);
336 memcpy((void *)MAIN_RAM_BASE, flashbase, length);
337 #endif
338
339 got_crc = crc32((unsigned char *)FIRMWARE_BASE_ADDRESS, length);
340 if(crc != got_crc) {
341 printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc);
342 return;
343 }
344 boot(0, 0, 0, FIRMWARE_BASE_ADDRESS);
345 }
346 #endif
347
348 #ifdef ROM_BOOT_ADDRESS
349 /* When firmware is small enough, it can be interesting to run code from an
350 embedded blockram memory (faster and not impacted by memory controller
351 activity). Define ROM_BOOT_ADDRESS for that and initialize the blockram
352 with the firmware data. */
353 void romboot(void)
354 {
355 boot(0, 0, 0, ROM_BOOT_ADDRESS);
356 }
357 #endif