add device tree support
[AROS.git] / arch / armeb-raspi / boot / boot.c
blob7c0448774772ea91c6700e6f41d595738055cc1a
1 /*
2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: boot.c
6 Lang: english
7 */
9 #include <exec/types.h>
10 #include <aros/macros.h>
11 #include <inttypes.h>
12 #include <asm/cpu.h>
13 #include <utility/tagitem.h>
14 #include <aros/macros.h>
15 #include <aros/kernel.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stdint.h>
20 #include <hardware/bcm2708.h>
21 #include <hardware/bcm2708_boot.h>
22 #include <hardware/videocore.h>
24 #include "boot.h"
25 #include "serialdebug.h"
26 #include "mmu.h"
27 #include "atags.h"
28 #include "vc_mb.h"
29 #include "elf.h"
30 #include "devicetree.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 " mrs r4, cpsr_all \n" /* Check if in hypervisor mode */
50 " and r4, r4, #0x1f \n"
51 " mov r8, #0x1a \n"
52 " cmp r4, r8 \n"
53 " beq leave_hyper \n"
54 "continue_boot: \n"
55 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
56 " setend be \n" /* Switch to big endian mode */
57 " ldr sp, tmp_stack_ptr \n"
58 " b boot \n"
59 "leave_hyper: \n"
60 " setend be \n"
61 " ldr r4, =continue_boot \n"
62 " msr ELR_hyp, r4 \n"
63 " mrs r4, cpsr_all \n"
64 " and r4, r4, #0x1f \n"
65 " orr r4, r4, #0x13 \n"
66 " msr SPSR_hyp, r4 \n"
67 " eret \n"
68 " .section .text \n"
69 ".byte 0 \n"
70 ".string \"$VER: arosraspi.img v40.46 (" __DATE__ ")\"\n"
71 ".byte 0 \n"
72 "\n\t\n\t"
75 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
76 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
77 static struct TagItem *boottag;
78 static unsigned long *mem_upper;
79 static void *pkg_image = NULL;
80 static uint32_t pkg_size = 0;
82 struct tag;
84 static const char bootstrapName[] = "Bootstrap/ARM BCM2708";
87 void check_device_tree(void *dt)
89 struct fdt_header *hdr = dt;
90 char * strings = NULL;
91 uint32_t * data = NULL;
92 uint32_t token = 0;
94 kprintf("[BOOT] Checking device tree at %p\n", dt);
95 kprintf("[BOOT] magic=%08x\n", hdr->magic);
96 kprintf("[BOOT] size=%d\n", hdr->totalsize);
97 kprintf("[BOOT] off_dt_struct=%d\n", hdr->off_dt_struct);
98 kprintf("[BOOT] off_dt_strings=%d\n", hdr->off_dt_strings);
99 kprintf("[BOOT] off_mem_rsvmap=%d\n", hdr->off_mem_rsvmap);
101 strings = dt + hdr->off_dt_strings;
102 data = dt + hdr->off_dt_struct;
104 if (hdr->off_mem_rsvmap) {
105 struct fdt_reserve_entry *rsrvd = dt + hdr->off_mem_rsvmap;
107 while (rsrvd->address != 0 || rsrvd->size != 0) {
108 kprintf("[BOOT] reserved: %08x-%08x\n", (uint32_t)rsrvd->address, (uint32_t)(rsrvd->address + rsrvd->size - 1));
109 rsrvd++;
113 char fill[] = " ";
114 int depth = 25;
118 token = *data++;
120 switch (token)
122 case FDT_BEGIN_NODE:
123 kprintf("[BOOT] %snode: %s\n", &fill[depth], (char *)data);
124 depth -= 2;
125 data += (strlen((char *)data) + 4) / 4;
126 break;
127 case FDT_PROP:
129 uint32_t len = *data++;
130 uint32_t nameoff = *data++;
131 uint8_t *propval = (uint8_t *)data;
132 kprintf("[BOOT] %s %s = ", &fill[depth], &strings[nameoff], len);
133 data += (len + 3)/4;
134 while (len--)
136 kprintf(" %02x", *propval++);
138 kprintf("\n");
139 break;
141 case FDT_END_NODE:
142 depth += 2;
143 break;
145 } while (token != FDT_END);
148 void query_vmem()
150 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
152 kprintf("[BOOT] Query VC memory\n");
153 vc_msg[0] = AROS_LONG2LE(8 * 4);
154 vc_msg[1] = AROS_LONG2LE(VCTAG_REQ);
155 vc_msg[2] = AROS_LONG2LE(VCTAG_GETVCRAM);
156 vc_msg[3] = AROS_LONG2LE(8);
157 vc_msg[4] = 0;
158 vc_msg[5] = 0;
159 vc_msg[6] = 0;
160 vc_msg[7] = 0;
162 vcmb_write((void *)VCMB_BASE, VCMB_PROPCHAN, (void *)vc_msg);
163 vc_msg = vcmb_read((void *)VCMB_BASE, VCMB_PROPCHAN);
165 kprintf("[BOOT] Base = %08x, Size = %08x\n", AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]));
167 boottag->ti_Tag = KRN_VMEMLower;
168 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]);
169 boottag++;
171 boottag->ti_Tag = KRN_VMEMUpper;
172 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]) + AROS_LE2LONG(vc_msg[6]);
173 boottag++;
175 mmu_map_section(AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]), 1, 0, 3, 0);
178 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags, uintptr_t a)
180 uint32_t tmp, initcr;
181 int plus_board = 0;
182 void (*entry)(struct TagItem *);
184 (void)entry;
185 (void)plus_board;
188 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
189 * access. Exceptions are set to run in big-endian mode and this is the mode
190 * in which page tables are written.
192 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
193 tmp = initcr;
194 tmp &= ~1; /* Disable MMU */
195 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
196 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
197 tmp |= (1 << 25); /* EE bit for exceptions set - big endian */
198 /* This bit sets also endianess of page tables */
199 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
201 mmu_init();
203 mem_init();
205 dt_parse(atags);
208 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
209 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
211 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
213 tmp = (tmp >> 4) & 0xfff;
215 /* tmp == 7 means armv6 architecture. */
216 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
218 __arm_periiobase = BCM2836_PERIPHYSBASE;
219 plus_board = 1;
221 /* Clear terminal screen */
222 kprintf("\033[0H\033[0J");
224 /* prepare map for core boot vector(s) */
225 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
227 else
229 __arm_periiobase = BCM2835_PERIPHYSBASE;
230 /* Need to detect the plus board here in order to control LEDs properly */
232 kprintf("\033[0H\033[0J");
235 /* Prepare map for MMIO registers */
236 mmu_map_section(__arm_periiobase, __arm_periiobase, ARM_PERIIOSIZE, 1, 0, 3, 0);
238 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
240 /* first of all, store the arch for the kernel to use .. */
241 boottag->ti_Tag = KRN_Platform;
242 boottag->ti_Data = (IPTR)arch;
243 boottag++;
245 /* Init LED */
247 if (plus_board)
250 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
251 * 47 and 35. Enable both leds as output and turn both of them off.
253 * The power led will be brought back up once AROS boots.
256 tmp = AROS_LE2LONG(*(volatile unsigned int *)GPFSEL4);
257 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
258 tmp |= (1 << 21);
259 *(volatile unsigned int *)GPFSEL4 = AROS_LONG2LE(tmp);
261 tmp = AROS_LE2LONG(*(volatile unsigned int *)GPFSEL3);
262 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
263 tmp |= (1 << 15);
264 *(volatile unsigned int *)GPFSEL3 = AROS_LONG2LE(tmp);
266 /* LEDS off */
267 *(volatile unsigned int *)GPCLR1 = AROS_LONG2LE((1 << (47-32)));
268 *(volatile unsigned int *)GPCLR1 = AROS_LONG2LE((1 << (35-32)));
270 else
273 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
274 * off now, kernel.resource will bring it back later.
277 tmp = AROS_LE2LONG(*(volatile unsigned int *)GPFSEL1);
278 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
279 tmp |= (1 << 18);
280 *(volatile unsigned int *)GPFSEL1 = AROS_LONG2LE(tmp);
282 *(volatile unsigned int *)GPSET0 = AROS_LONG2LE((1 << 16));
286 serInit();
288 boottag->ti_Tag = KRN_BootLoader;
289 boottag->ti_Data = (IPTR)bootstrapName;
290 boottag++;
292 #if 0
293 if (vcfb_init())
295 boottag->ti_Tag = KRN_FuncPutC;
296 boottag->ti_Data = (IPTR)fb_Putc;
297 boottag++;
299 #endif
302 kprintf("[BOOT] Big-Endian AROS %s\n", bootstrapName);
303 kprintf("[BOOT] Arguments: %08x, %08x, %08x, %08x\n", dummy, arch, atags, a);
305 DBOOT({
306 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
307 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
309 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
310 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
312 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
313 kprintf("[BOOT] main id register: %08x\n", tmp);
318 kprintf("[BOOT] Booted on %s\n", dt_find_property(dt_find_node("/"), "model")->dtp_value);
320 // parse_atags((void *)0x100);
321 query_vmem();
323 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
325 boottag->ti_Tag = KRN_ProtAreaStart;
326 boottag->ti_Data = (IPTR)&__bootstrap_start;
327 boottag++;
329 boottag->ti_Tag = KRN_ProtAreaEnd;
330 boottag->ti_Data = (IPTR)&__bootstrap_end;
331 boottag++;
333 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
335 if (mem_upper)
337 *mem_upper = *mem_upper & ~4095;
339 unsigned long kernel_phys = *mem_upper;
340 unsigned long kernel_virt = kernel_phys;
342 unsigned long total_size_ro, total_size_rw;
343 uint32_t size_ro, size_rw;
345 /* Calculate total size of kernel and modules */
346 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
348 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
349 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
351 if (pkg_image && pkg_size)
353 uint8_t *base = pkg_image;
355 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
357 getElfSize(base, &size_rw, &size_ro);
359 total_size_ro += (size_ro + 4095) & ~4095;
360 total_size_rw += (size_rw + 4095) & ~4095;
362 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
364 uint8_t *file = base+4;
365 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
366 const uint8_t *file_end = base+total_length;
367 uint32_t len, cnt = 0;
369 file = base + 8;
371 while(file < file_end)
373 //const char *filename = remove_path(file+4);
375 /* get text length */
376 len = AROS_BE2LONG(*(uint32_t*)file);
378 file += len + 5;
380 len = AROS_BE2LONG(*(uint32_t *)file);
381 file += 4;
383 /* load it */
384 getElfSize(file, &size_rw, &size_ro);
386 total_size_ro += (size_ro + 4095) & ~4095;
387 total_size_rw += (size_rw + 4095) & ~4095;
389 /* go to the next file */
390 file += len;
391 cnt++;
396 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
397 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
399 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
400 kernel_virt = 0xf8000000;
402 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
403 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
405 *mem_upper = kernel_phys;
407 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
409 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
410 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
412 /* map kernel memory for user access */
413 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
414 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
416 entry = (void (*)(struct TagItem *))kernel_virt;
418 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
420 boottag->ti_Tag = KRN_KernelLowest;
421 boottag->ti_Data = kernel_virt;
422 boottag++;
424 boottag->ti_Tag = KRN_KernelHighest;
425 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
426 boottag++;
428 boottag->ti_Tag = KRN_KernelPhysLowest;
429 boottag->ti_Data = kernel_phys;
430 boottag++;
432 loadElf(&_binary_core_bin_start);
434 if (pkg_image && pkg_size)
436 uint8_t *base = pkg_image;
438 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
440 kprintf("[BOOT] Kernel image is ELF file\n");
442 getElfSize(base, &size_rw, &size_ro);
444 total_size_ro += (size_ro + 4095) & ~4095;
445 total_size_rw += (size_rw + 4095) & ~4095;
447 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
449 kprintf("[BOOT] Kernel image is a package:\n");
451 uint8_t *file = base+4;
452 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
453 const uint8_t *file_end = base+total_length;
454 uint32_t len, cnt = 0;
456 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
458 file = base + 8;
460 while(file < file_end)
462 const char *filename = remove_path(file+4);
464 /* get text length */
465 len = AROS_BE2LONG(*(uint32_t*)file);
466 /* display the file name */
467 if (cnt % 4 == 0)
468 kprintf("\n[BOOT] %s", filename);
469 else
470 kprintf(", %s", filename);
472 file += len + 5;
474 len = AROS_BE2LONG(*(uint32_t *)file);
475 file += 4;
477 /* load it */
478 loadElf(file);
480 total_size_ro += (size_ro + 4095) & ~4095;
481 total_size_rw += (size_rw + 4095) & ~4095;
483 /* go to the next file */
484 file += len;
485 cnt++;
487 kprintf("\n");
491 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
493 boottag->ti_Tag = KRN_KernelBss;
494 boottag->ti_Data = (IPTR)tracker;
495 boottag++;
498 boottag->ti_Tag = TAG_DONE;
499 boottag->ti_Data = 0;
501 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));
502 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
504 mmu_load();
506 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
508 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
510 kprintf("[BOOT] Back? Something wrong happened...\n");
512 while(1) asm volatile("wfe");