make armeb specific header (set AROS_BIG_ENDIAN to one)
[AROS.git] / arch / arm-raspi / boot / boot.c
blob374f016bdddd9624a9f2180e129cdb64f5fa13ab
1 /*
2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: boot.c
6 Lang: english
7 */
9 #include <inttypes.h>
10 #include <asm/cpu.h>
11 #include <utility/tagitem.h>
12 #include <aros/macros.h>
13 #include <aros/kernel.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <stdint.h>
18 #include <hardware/bcm2708.h>
19 #include <hardware/bcm2708_boot.h>
20 #include <hardware/videocore.h>
22 #include "boot.h"
23 #include "serialdebug.h"
24 #include "bootconsole.h"
25 #include "atags.h"
26 #include "elf.h"
27 #include "mmu.h"
29 #include "vc_mb.h"
30 #include "vc_fb.h"
32 #define DBOOT(x) x
34 #undef ARM_PERIIOBASE
35 #define ARM_PERIIOBASE (__arm_periiobase)
37 uint32_t __arm_periiobase;
39 extern void mem_init(void);
40 extern unsigned int uartclock;
41 extern unsigned int uartdivint;
42 extern unsigned int uartdivfrac;
43 extern unsigned int uartbaud;
45 asm(" .section .aros.startup \n"
46 " .globl bootstrap \n"
47 " .type bootstrap,%function \n"
48 "bootstrap: \n"
49 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
50 " ldr sp, tmp_stack_ptr \n"
51 " b boot \n"
52 " .section .text \n"
54 ".string \"$VER: arosraspi.img v40.45 (" __DATE__ ")\"" "\n\t\n\t"
57 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
58 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
59 static struct TagItem *boottag;
60 static unsigned long *mem_upper;
61 static void *pkg_image;
62 static uint32_t pkg_size;
64 static void parse_atags(struct tag *tags)
66 struct tag *t = NULL;
68 kprintf("[BOOT] Parsing ATAGS\n");
70 for_each_tag(t, tags)
72 kprintf("[BOOT] %08x: ", t->hdr.tag);
73 switch (t->hdr.tag)
75 case 0:
76 kprintf("ATAG_NONE - Ignored\n");
77 break;
79 case ATAG_CORE:
80 kprintf("ATAG_CORE - Ignored\n");
81 break;
83 case ATAG_MEM:
84 kprintf("ATAG_MEM (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
85 boottag->ti_Tag = KRN_MEMLower;
86 if ((boottag->ti_Data = t->u.mem.start) < sizeof(struct bcm2708bootmem))
87 boottag->ti_Data = sizeof(struct bcm2708bootmem); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
89 boottag++;
90 boottag->ti_Tag = KRN_MEMUpper;
91 boottag->ti_Data = t->u.mem.start + t->u.mem.size;
93 mem_upper = &boottag->ti_Data;
95 boottag++;
97 mmu_map_section(t->u.mem.start, t->u.mem.start, t->u.mem.size, 1, 1, 3, 1);
99 break;
101 case ATAG_VIDEOTEXT:
102 kprintf("ATAG_VIDEOTEXT - Ignored\n");
103 break;
105 case ATAG_RAMDISK:
106 kprintf("ATAG_RAMDISK - Ignored\n");
107 break;
109 case ATAG_INITRD2:
110 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
111 pkg_image = (void *)t->u.initrd.start;
112 pkg_size = t->u.initrd.size;
113 break;
115 case ATAG_SERIAL:
116 kprintf("ATAG_SERIAL - Ignored\n");
117 break;
119 case ATAG_REVISION:
120 kprintf("ATAG_REVISION - Ignored\n");
121 break;
123 case ATAG_VIDEOLFB:
124 kprintf("ATAG_VIDEOLFB - Ignored\n");
125 break;
127 case ATAG_CMDLINE:
129 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
130 strcpy(cmdline, t->u.cmdline.cmdline);
131 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline);
133 boottag->ti_Tag = KRN_CmdLine;
134 boottag->ti_Data = (intptr_t)cmdline;
135 boottag++;
137 break;
139 default:
140 kprintf("(UNKNOWN)...\n");
141 break;
146 void query_vmem()
148 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
150 kprintf("[BOOT] Query VC memory\n");
151 vc_msg[0] = 8 * 4;
152 vc_msg[1] = VCTAG_REQ;
153 vc_msg[2] = VCTAG_GETVCRAM;
154 vc_msg[3] = 8;
155 vc_msg[4] = 0;
156 vc_msg[5] = 0;
157 vc_msg[6] = 0;
158 vc_msg[7] = 0;
160 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, vc_msg);
161 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
163 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg[5], vc_msg[6]);
165 boottag->ti_Tag = KRN_VMEMLower;
166 boottag->ti_Data = vc_msg[5];
167 boottag++;
169 boottag->ti_Tag = KRN_VMEMUpper;
170 boottag->ti_Data = vc_msg[5] + vc_msg[6];
171 boottag++;
173 mmu_map_section(vc_msg[5], vc_msg[5], vc_msg[6], 1, 0, 3, 0);
176 static const char bootstrapName[] = "Bootstrap/ARM BCM2708";
178 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
180 uint32_t tmp, initcr;
181 int plus_board = 0;
182 void (*entry)(struct TagItem *);
185 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
186 * access
188 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
189 tmp = initcr;
190 tmp &= ~1; /* Disable MMU */
191 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
192 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
193 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
195 mmu_init();
198 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
199 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
201 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
203 tmp = (tmp >> 4) & 0xfff;
205 /* tmp == 7 means armv6 architecture. */
206 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
208 __arm_periiobase = BCM2836_PERIPHYSBASE;
209 plus_board = 1;
211 /* prepare map for core boot vector(s) */
212 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
214 else
216 __arm_periiobase = BCM2835_PERIPHYSBASE;
217 /* Need to detect the plus board here in order to control LEDs properly */
220 /* Prepare map for MMIO registers */
221 mmu_map_section(__arm_periiobase, __arm_periiobase, ARM_PERIIOSIZE, 1, 0, 3, 0);
223 mem_init();
225 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
227 /* first of all, store the arch for the kernel to use .. */
228 boottag->ti_Tag = KRN_Platform;
229 boottag->ti_Data = (IPTR)arch;
230 boottag++;
232 /* Init LED */
234 if (plus_board)
237 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
238 * 47 and 35. Enable both leds as output and turn both of them off.
240 * The power led will be brought back up once AROS boots.
243 tmp = *(volatile unsigned int *)GPFSEL4;
244 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
245 tmp |= (1 << 21);
246 *(volatile unsigned int *)GPFSEL4 = tmp;
248 tmp = *(volatile unsigned int *)GPFSEL3;
249 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
250 tmp |= (1 << 15);
251 *(volatile unsigned int *)GPFSEL3 = tmp;
253 /* LEDS off */
254 *(volatile unsigned int *)GPCLR1 = (1 << (47-32));
255 *(volatile unsigned int *)GPCLR1 = (1 << (35-32));
257 else
260 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
261 * off now, kernel.resource will bring it back later.
264 tmp = *(volatile unsigned int *)GPFSEL1;
265 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
266 tmp |= (1 << 18);
267 *(volatile unsigned int *)GPFSEL1 = tmp;
269 *(volatile unsigned int *)GPSET0 = (1 << 16);
273 serInit();
275 boottag->ti_Tag = KRN_BootLoader;
276 boottag->ti_Data = (IPTR)bootstrapName;
277 boottag++;
279 if (vcfb_init())
281 boottag->ti_Tag = KRN_FuncPutC;
282 boottag->ti_Data = (IPTR)fb_Putc;
283 boottag++;
286 kprintf("[BOOT] AROS %s\n", bootstrapName);
288 DBOOT({
289 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
290 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
292 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
293 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
295 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
296 kprintf("[BOOT] main id register: %08x\n", tmp);
299 parse_atags(atags);
300 query_vmem();
302 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
304 boottag->ti_Tag = KRN_ProtAreaStart;
305 boottag->ti_Data = (IPTR)&__bootstrap_start;
306 boottag++;
308 boottag->ti_Tag = KRN_ProtAreaEnd;
309 boottag->ti_Data = (IPTR)&__bootstrap_end;
310 boottag++;
312 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
314 if (mem_upper)
316 *mem_upper = *mem_upper & ~4095;
318 unsigned long kernel_phys = *mem_upper;
319 unsigned long kernel_virt = kernel_phys;
321 unsigned long total_size_ro, total_size_rw;
322 uint32_t size_ro, size_rw;
324 /* Calculate total size of kernel and modules */
325 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
327 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
328 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
330 if (pkg_image && pkg_size)
332 uint8_t *base = pkg_image;
334 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
336 getElfSize(base, &size_rw, &size_ro);
338 total_size_ro += (size_ro + 4095) & ~4095;
339 total_size_rw += (size_rw + 4095) & ~4095;
341 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
343 uint8_t *file = base+4;
344 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
345 const uint8_t *file_end = base+total_length;
346 uint32_t len, cnt = 0;
348 file = base + 8;
350 while(file < file_end)
352 const char *filename = remove_path(file+4);
354 /* get text length */
355 len = AROS_BE2LONG(*(uint32_t*)file);
357 file += len + 5;
359 len = AROS_BE2LONG(*(uint32_t *)file);
360 file += 4;
362 /* load it */
363 getElfSize(file, &size_rw, &size_ro);
365 total_size_ro += (size_ro + 4095) & ~4095;
366 total_size_rw += (size_rw + 4095) & ~4095;
368 /* go to the next file */
369 file += len;
370 cnt++;
375 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
376 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
378 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
379 kernel_virt = 0xf8000000;
381 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
382 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
384 *mem_upper = kernel_phys;
386 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
388 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
389 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
391 /* map kernel memory for user access */
392 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
393 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
395 entry = (void (*)(struct TagItem))kernel_virt;
397 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
399 boottag->ti_Tag = KRN_KernelLowest;
400 boottag->ti_Data = kernel_virt;
401 boottag++;
403 boottag->ti_Tag = KRN_KernelHighest;
404 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
405 boottag++;
407 boottag->ti_Tag = KRN_KernelPhysLowest;
408 boottag->ti_Data = kernel_phys;
409 boottag++;
411 loadElf(&_binary_core_bin_start);
413 if (pkg_image && pkg_size)
415 uint8_t *base = pkg_image;
417 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
419 kprintf("[BOOT] Kernel image is ELF file\n");
421 getElfSize(base, &size_rw, &size_ro);
423 total_size_ro += (size_ro + 4095) & ~4095;
424 total_size_rw += (size_rw + 4095) & ~4095;
426 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
428 kprintf("[BOOT] Kernel image is a package:\n");
430 uint8_t *file = base+4;
431 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
432 const uint8_t *file_end = base+total_length;
433 uint32_t len, cnt = 0;
435 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
437 file = base + 8;
439 while(file < file_end)
441 const char *filename = remove_path(file+4);
443 /* get text length */
444 len = AROS_BE2LONG(*(uint32_t*)file);
445 /* display the file name */
446 if (cnt % 4 == 0)
447 kprintf("\n[BOOT] %s", filename);
448 else
449 kprintf(", %s", filename);
451 file += len + 5;
453 len = AROS_BE2LONG(*(uint32_t *)file);
454 file += 4;
456 /* load it */
457 loadElf(file);
459 total_size_ro += (size_ro + 4095) & ~4095;
460 total_size_rw += (size_rw + 4095) & ~4095;
462 /* go to the next file */
463 file += len;
464 cnt++;
466 kprintf("\n");
470 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
472 boottag->ti_Tag = KRN_KernelBss;
473 boottag->ti_Data = (IPTR)tracker;
474 boottag++;
477 boottag->ti_Tag = TAG_DONE;
478 boottag->ti_Data = 0;
480 kprintf("[BOOT] Kernel taglist contains %d entries\n", ((intptr_t)boottag - (intptr_t)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE))/sizeof(struct TagItem));
481 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
483 mmu_load();
485 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
487 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
489 kprintf("[BOOT] Back? Something wrong happened...\n");
491 while(1);