detect if the compiler supports -fno-builtin and -fno-builtin-vsnprintf. (NicJA)
[AROS.git] / arch / armeb-raspi / boot / boot.c
blobad1963fb21c88c18276e0ed0cb221b77d4599d8f
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 "vc_fb.h"
30 #include "elf.h"
31 #include "devicetree.h"
32 #include "io.h"
34 #define DBOOT(x) x
36 #undef ARM_PERIIOBASE
37 #define ARM_PERIIOBASE (__arm_periiobase)
39 uint32_t __arm_periiobase = 0;
41 extern void mem_init(void);
42 extern unsigned int uartclock;
43 extern unsigned int uartdivint;
44 extern unsigned int uartdivfrac;
45 extern unsigned int uartbaud;
47 asm(" .section .aros.startup \n"
48 " .globl bootstrap \n"
49 " .type bootstrap,%function \n"
50 "bootstrap: \n"
51 " mrs r4, cpsr_all \n" /* Check if in hypervisor mode */
52 " and r4, r4, #0x1f \n"
53 " mov r8, #0x1a \n"
54 " cmp r4, r8 \n"
55 " beq leave_hyper \n"
56 "continue_boot: \n"
57 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
58 " setend be \n" /* Switch to big endian mode */
59 " ldr sp, tmp_stack_ptr \n"
60 " b boot \n"
61 "leave_hyper: \n"
62 " setend be \n"
63 " adr r4, continue_boot \n"
64 " msr ELR_hyp, r4 \n"
65 " mrs r4, cpsr_all \n"
66 " and r4, r4, #0x1f \n"
67 " orr r4, r4, #0x13 \n"
68 " msr SPSR_hyp, r4 \n"
69 " eret \n"
70 " .section .text \n"
71 ".byte 0 \n"
72 ".string \"$VER: arosraspi-be.img v40.46 (" __DATE__ ")\"\n"
73 ".byte 0 \n"
74 "\n\t\n\t"
77 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
78 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
79 static struct TagItem *boottag;
80 static unsigned long *mem_upper;
81 static void *pkg_image = NULL;
82 static uint32_t pkg_size = 0;
84 struct tag;
86 static const char bootstrapName[] = "Bootstrap/ARM v7-a BigEndian";
88 void query_vmem()
90 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
92 kprintf("[BOOT] Query VC memory\n");
93 vc_msg[0] = AROS_LONG2LE(8 * 4);
94 vc_msg[1] = AROS_LONG2LE(VCTAG_REQ);
95 vc_msg[2] = AROS_LONG2LE(VCTAG_GETVCRAM);
96 vc_msg[3] = AROS_LONG2LE(8);
97 vc_msg[4] = 0;
98 vc_msg[5] = 0;
99 vc_msg[6] = 0;
100 vc_msg[7] = 0;
102 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, (void *)vc_msg);
103 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
105 kprintf("[BOOT] Base = %08x, Size = %08x\n", AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]));
107 boottag->ti_Tag = KRN_VMEMLower;
108 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]);
109 boottag++;
111 boottag->ti_Tag = KRN_VMEMUpper;
112 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]) + AROS_LE2LONG(vc_msg[6]);
113 boottag++;
115 mmu_map_section(AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]), 1, 0, 3, 0);
118 void query_memory()
120 of_node_t *mem = dt_find_node("/memory");
122 kprintf("[BOOT] Query system memory\n");
123 if (mem)
125 of_property_t *p = dt_find_property(mem, "reg");
127 if (p != NULL && p->op_length)
129 uint32_t *addr = p->op_value;
130 uint32_t lower = AROS_BE2LONG(*addr++);
131 uint32_t upper = AROS_BE2LONG(*addr++);
133 kprintf("[BOOT] System memory range: %08x-%08x\n", lower, upper-1);
135 if (((upper - lower) >> 20) < 256) {
136 kprintf("[BOOT] MISMATCHED FILES: start.elf and fixup.dat do not fit to each other!\n");
137 while(1) asm volatile("wfi");
140 boottag->ti_Tag = KRN_MEMLower;
141 if ((boottag->ti_Data = lower) < sizeof(struct bcm2708bootmem))
142 boottag->ti_Data = sizeof(struct bcm2708bootmem); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
144 boottag++;
145 boottag->ti_Tag = KRN_MEMUpper;
146 boottag->ti_Data = upper;
148 mem_upper = &boottag->ti_Data;
150 boottag++;
152 mmu_map_section(lower, lower, upper - lower, 1, 1, 3, 1);
157 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags, uintptr_t a)
159 uint32_t tmp, initcr;
160 void (*entry)(struct TagItem *);
162 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
165 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
166 * access. Exceptions are set to run in big-endian mode and this is the mode
167 * in which page tables are written.
169 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
170 tmp = initcr;
171 tmp &= ~1; /* Disable MMU */
172 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
173 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
174 tmp |= (1 << 25); /* EE bit for exceptions set - big endian */
175 /* This bit sets also endianess of page tables */
176 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
178 /* Prepare MMU tables but do not load them yet */
179 mmu_init();
181 /* Initialize simplistic local memory allocator */
182 mem_init();
184 int dt_mem_usage = mem_avail();
185 /* Parse device tree */
186 dt_parse(atags);
187 dt_mem_usage -= mem_avail();
189 /* Prepare mapping for peripherals. Use the data from device tree here */
190 of_node_t *e = dt_find_node("/soc");
191 if (e)
193 of_property_t *p = dt_find_property(e, "ranges");
194 uint32_t *ranges = p->op_value;
195 int32_t len = p->op_length;
197 while(len > 0)
199 uint32_t addr_bus, addr_cpu;
200 uint32_t addr_len;
202 addr_bus = AROS_BE2LONG(*ranges++);
203 addr_cpu = AROS_BE2LONG(*ranges++);
204 addr_len = AROS_BE2LONG(*ranges++);
206 (void)addr_bus;
208 /* If periiobase was not set yet, do it now */
209 if (__arm_periiobase == 0) {
210 __arm_periiobase = (uint32_t)addr_cpu;
213 /* Prepare mapping - device type */
214 mmu_map_section(addr_cpu, addr_cpu, addr_len, 1, 0, 3, 0);
216 len -= 12;
219 else
220 while(1) asm volatile("wfe");
222 serInit();
224 kprintf("\n\n[BOOT] Big-Endian AROS %s\n", bootstrapName);
225 kprintf("[BOOT] Booted on %s\n", dt_find_property(dt_find_node("/"), "model")->op_value);
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++;
233 Check if device tree contains /soc/local_intc entry. In this case assume RasPi 2 or 3 with smp setup.
234 Neither PiZero nor classic Pi provide this entry.
236 e = dt_find_node("/__symbols__");
237 if (e)
239 of_property_t *p = dt_find_property(e, "local_intc");
241 if (p)
243 kprintf("[BOOT] local_intc points to %s\n", p->op_value);
245 e = dt_find_node(p->op_value);
246 p = dt_find_property(e, "reg");
247 uint32_t *reg = p->op_value;
249 kprintf("[BOOT] Mapping local interrupt area at %p-%p\n", reg[0], reg[0] + reg[1] - 1);
251 /* Prepare mapping - device type */
252 mmu_map_section(reg[0], reg[0], reg[1] < 0x100000 ? 0x100000 : reg[1], 0, 0, 3, 0);
257 /* Init LED(s) */
258 e = dt_find_node("/leds");
259 if (e)
261 of_node_t *led;
262 kprintf("[BOOT] Configuring LEDs\n");
263 ForeachNode(&e->on_children, led)
265 of_property_t *p = dt_find_property(led, "gpios");
266 int32_t gpio = 0;
267 if (p && p->op_length >= 8) {
268 uint32_t *data = p->op_value;
269 uint32_t phandle = AROS_BE2LONG(data[0]);
270 gpio = AROS_BE2LONG(data[1]);
271 of_node_t *bus = dt_find_node_by_phandle(phandle);
273 kprintf("[BOOT] %s: GPIO%d (%08x %08x %08x)\n", led->on_name, gpio,
274 AROS_BE2LONG(data[0]), AROS_BE2LONG(data[1]), AROS_BE2LONG(data[2]));
275 if (bus)
277 kprintf("[BOOT] LED attached to %s\n", bus->on_name);
279 if (strncmp(bus->on_name, "gpio", 4) == 0)
281 int gpio_sel = gpio / 10;
282 int gpio_soff = 3 * (gpio - 10 * gpio_sel);
284 kprintf("[BOOT] GPFSEL=%x, bit=%d\n", gpio_sel * 4, gpio_soff);
286 /* Configure GPIO as output */
287 tmp = rd32le(GPFSEL0 + 4*gpio_sel);
288 tmp &= ~(7 << gpio_soff); // GPIO 47 = 001 - output
289 tmp |= (1 << gpio_soff);
290 wr32le(GPFSEL0 + 4*gpio_sel, tmp);
292 /* Turn LED off */
293 wr32le(GPCLR0 + 4 * (gpio / 32), 1 << (gpio % 32));
300 kprintf("[BOOT] DT memory usage: %d\n", dt_mem_usage);
302 boottag->ti_Tag = KRN_BootLoader;
303 boottag->ti_Data = (IPTR)bootstrapName;
304 boottag++;
306 if (vcfb_init())
308 boottag->ti_Tag = KRN_FuncPutC;
309 boottag->ti_Data = (IPTR)fb_Putc;
310 boottag++;
313 DBOOT({
314 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
315 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
317 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
318 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
320 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
321 kprintf("[BOOT] main id register: %08x\n", tmp);
324 query_memory();
325 query_vmem();
327 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
329 boottag->ti_Tag = KRN_ProtAreaStart;
330 boottag->ti_Data = (IPTR)&__bootstrap_start;
331 boottag++;
333 boottag->ti_Tag = KRN_ProtAreaEnd;
334 boottag->ti_Data = (IPTR)&__bootstrap_end;
335 boottag++;
337 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
339 e = dt_find_node("/chosen");
340 if (e)
342 of_property_t *p = dt_find_property(e, "linux,initrd-start");
343 if (p)
344 pkg_image = (void*)(*((uint32_t *)p->op_value));
345 else
346 pkg_image = NULL;
348 p = dt_find_property(e, "linux,initrd-end");
349 if (p)
350 pkg_size = *((uint32_t *)p->op_value) - (uint32_t)pkg_image;
351 else
352 pkg_size = 0;
355 kprintf("[BOOT] BSP image: %08x-%08x\n", pkg_image, (int32_t)pkg_image + pkg_size - 1);
357 kprintf("[BOOT] mem_avail=%d\n", mem_avail());
359 unsigned long total_size_ro = 0, total_size_rw = 0;
360 void *fdt = NULL;
362 if (mem_upper)
364 *mem_upper = *mem_upper & ~4095;
366 unsigned long kernel_phys = *mem_upper;
367 unsigned long kernel_virt = kernel_phys;
369 uint32_t size_ro, size_rw;
371 /* Calculate total size of kernel and modules */
372 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
374 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
375 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
377 if (pkg_image && pkg_size)
379 uint8_t *base = pkg_image;
381 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
383 getElfSize(base, &size_rw, &size_ro);
385 total_size_ro += (size_ro + 4095) & ~4095;
386 total_size_rw += (size_rw + 4095) & ~4095;
388 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
390 uint8_t *file = base+4;
391 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
392 const uint8_t *file_end = base+total_length;
393 uint32_t len, cnt = 0;
395 file = base + 8;
397 while(file < file_end)
399 //const char *filename = remove_path(file+4);
401 /* get text length */
402 len = AROS_BE2LONG(*(uint32_t*)file);
404 file += len + 5;
406 len = AROS_BE2LONG(*(uint32_t *)file);
407 file += 4;
409 /* load it */
410 getElfSize(file, &size_rw, &size_ro);
412 total_size_ro += (size_ro + 4095) & ~4095;
413 total_size_rw += (size_rw + 4095) & ~4095;
415 /* go to the next file */
416 file += len;
417 cnt++;
422 /* Reserve space for flattened device tree */
423 total_size_ro += (dt_total_size() + 31) & ~31;
425 /* Reserve space for unpacked device tree */
426 total_size_ro += (dt_mem_usage + 31) & ~31;
428 /* Align space to 1MB boundary - it will save some space in MMU tables */
429 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
430 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
432 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
433 kernel_virt = KERNEL_VIRT_ADDRESS;
435 bzero((void*)kernel_phys, total_size_ro + total_size_rw);
437 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
438 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
440 if (dt_total_size() > 0)
442 long dt_size = (dt_total_size() + 31) & ~31;
443 /* Copy device tree to the end of kernel RO area */
444 memcpy((void*)(kernel_phys + total_size_ro - dt_size), atags, dt_size);
445 fdt = (void*)(kernel_virt + total_size_ro - dt_size);
447 /* Store device tree */
448 boottag->ti_Tag = KRN_FlattenedDeviceTree;
449 boottag->ti_Data = (IPTR)kernel_virt + total_size_ro - dt_size;
450 boottag++;
452 kprintf("[BOOT] Device tree (size: %d) moved to %p, phys %p\n", dt_total_size(), boottag[-1].ti_Data, kernel_phys + total_size_ro - dt_size);
455 *mem_upper = kernel_phys;
457 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
459 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
460 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
462 /* map kernel memory for user access */
463 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
464 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
466 entry = (void (*)(struct TagItem *))kernel_virt;
468 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
470 boottag->ti_Tag = KRN_KernelLowest;
471 boottag->ti_Data = kernel_virt;
472 boottag++;
474 boottag->ti_Tag = KRN_KernelHighest;
475 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
476 boottag++;
478 boottag->ti_Tag = KRN_KernelPhysLowest;
479 boottag->ti_Data = kernel_phys;
480 boottag++;
482 loadElf(&_binary_core_bin_start);
484 if (pkg_image && pkg_size)
486 uint8_t *base = pkg_image;
488 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
490 kprintf("[BOOT] Kernel image is ELF file\n");
492 loadElf(base);
494 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
496 kprintf("[BOOT] Kernel image is a package:\n");
498 uint8_t *file = base+4;
499 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
500 const uint8_t *file_end = base+total_length;
501 uint32_t len, cnt = 0;
503 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
505 file = base + 8;
507 while(file < file_end)
509 const char *filename = remove_path(file+4);
511 /* get text length */
512 len = AROS_BE2LONG(*(uint32_t*)file);
513 /* display the file name */
514 if (cnt % 4 == 0)
515 kprintf("\n[BOOT] %s", filename);
516 else
517 kprintf(", %s", filename);
519 file += len + 5;
521 len = AROS_BE2LONG(*(uint32_t *)file);
522 file += 4;
524 /* load it */
525 loadElf(file);
527 /* go to the next file */
528 file += len;
529 cnt++;
531 kprintf("\n");
535 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
537 boottag->ti_Tag = KRN_KernelBss;
538 boottag->ti_Data = (IPTR)tracker;
539 boottag++;
542 mmu_load();
544 int memory_used = mem_used();
546 /* If device tree is in high kernel memory then parse it again */
547 if (dt_total_size() > 0)
549 void * dt_location = (void *)(KERNEL_VIRT_ADDRESS + total_size_ro - ((dt_total_size() + 31) & ~31) - ((dt_mem_usage + 31) & ~31));
550 kprintf("[BOOT] Creating device tree in kernel area at %p\n", dt_location);
552 explicit_mem_init(dt_location, (dt_mem_usage + 31) & ~31);
553 dt_parse(fdt);
555 boottag->ti_Tag = KRN_OpenFirmwareTree;
556 boottag->ti_Data = (IPTR)dt_location;
557 boottag++;
559 e = dt_find_node("/chosen");
560 if (e)
562 of_property_t *p = dt_find_property(e, "bootargs");
563 if (p)
565 boottag->ti_Tag = KRN_CmdLine;
566 boottag->ti_Data = (IPTR)p->op_value;
567 boottag++;
569 kprintf("[BOOT] Kernel parameters @ %p: %s\n", p->op_value, p->op_value);
574 boottag->ti_Tag = TAG_DONE;
575 boottag->ti_Data = 0;
577 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));
578 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", memory_used);
580 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
582 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
584 kprintf("[BOOT] Back? Something wrong happened...\n");
586 while(1) asm volatile("wfe");