revert between 56095 -> 55830 in arch
[AROS.git] / arch / arm-raspi / boot / boot.c
blob438c319dfee88ff97b75008a26c78e47a96656dd
1 /*
2 Copyright © 2013-2019, 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 #if AROS_BIG_ENDIAN
59 " setend be \n" /* Switch to big endian mode */
60 #endif
61 " ldr sp, tmp_stack_ptr \n"
62 " mrc p15,0,r4,c1,c0,2 \n" /* Enable signle and double VFP coprocessors */
63 " orr r4, r4, #0x00f00000 \n" /* This is necessary since gcc might want to use vfp registers */
64 " mcr p15,0,r4,c1,c0,2 \n" /* Either as cache for general purpose regs or e.g. for division. This is the case with gcc9 */
65 " mov r4,#0x40000000 \n"
66 " fmxr fpexc,r4 \n" /* Enable VFP now */
67 " b boot \n"
68 "leave_hyper: \n"
69 #if AROS_BIG_ENDIAN
70 " setend be \n"
71 #endif
72 " adr r4, continue_boot \n"
73 " .byte 0x04,0xf3,0x2e,0xe1 \n" /* msr ELR_hyp, r4 */
74 " mrs r4, cpsr_all \n"
75 " and r4, r4, #0x1f \n"
76 " orr r4, r4, #0x13 \n"
77 " .byte 0x04,0xf3,0x6e,0xe1 \n" /* msr SPSR_hyp, r4 */
78 " .byte 0x6e,0x00,0x60,0xe1 \n" /* eret */
79 " .section .text \n"
80 ".byte 0 \n"
81 #if AROS_BIG_ENDIAN
82 ".string \"$VER: arosraspi-be.img v40.46 (" __DATE__ ")\"\n"
83 #else
84 ".string \"$VER: arosraspi.img v40.46 (" __DATE__ ")\"\n"
85 #endif
86 ".byte 0 \n"
87 "\n\t\n\t"
90 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
91 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
92 static struct TagItem *boottag;
93 static unsigned long *mem_upper;
94 static void *pkg_image = NULL;
95 static uint32_t pkg_size = 0;
97 struct tag;
99 #if AROS_BIG_ENDIAN
100 static const char bootstrapName[] = "Bootstrap/ARM v7-a BigEndian";
101 #else
102 static const char bootstrapName[] = "Bootstrap/ARM v7-a LittleEndian";
103 #endif
105 void query_vmem()
107 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
109 kprintf("[BOOT] Query VC memory\n");
110 vc_msg[0] = AROS_LONG2LE(8 * 4);
111 vc_msg[1] = AROS_LONG2LE(VCTAG_REQ);
112 vc_msg[2] = AROS_LONG2LE(VCTAG_GETVCRAM);
113 vc_msg[3] = AROS_LONG2LE(8);
114 vc_msg[4] = 0;
115 vc_msg[5] = 0;
116 vc_msg[6] = 0;
117 vc_msg[7] = 0;
119 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, (void *)vc_msg);
120 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
122 kprintf("[BOOT] Base = %08x, Size = %08x\n", AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]));
124 boottag->ti_Tag = KRN_VMEMLower;
125 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]);
126 boottag++;
128 boottag->ti_Tag = KRN_VMEMUpper;
129 boottag->ti_Data = AROS_LE2LONG(vc_msg[5]) + AROS_LE2LONG(vc_msg[6]);
130 boottag++;
132 mmu_map_section(AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[5]), AROS_LE2LONG(vc_msg[6]), 1, 0, 3, 0);
135 void query_memory()
137 of_node_t *mem = dt_find_node("/memory");
139 kprintf("[BOOT] Query system memory\n");
140 if (mem)
142 of_property_t *p = dt_find_property(mem, "reg");
144 if (p != NULL && p->op_length)
146 uint32_t *addr = p->op_value;
147 uint32_t lower = AROS_BE2LONG(*addr++);
148 uint32_t upper = AROS_BE2LONG(*addr++);
150 kprintf("[BOOT] System memory range: %08x-%08x\n", lower, upper-1);
152 if (((upper - lower) >> 20) < 256) {
153 kprintf("[BOOT] MISMATCHED FILES: start.elf and fixup.dat do not fit to each other!\n");
154 while(1) asm volatile("wfi");
157 boottag->ti_Tag = KRN_MEMLower;
158 if ((boottag->ti_Data = lower) < sizeof(struct bcm2708bootmem))
159 boottag->ti_Data = sizeof(struct bcm2708bootmem); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
161 boottag++;
162 boottag->ti_Tag = KRN_MEMUpper;
163 boottag->ti_Data = upper;
165 mem_upper = &boottag->ti_Data;
167 boottag++;
169 mmu_map_section(lower, lower, upper - lower, 1, 1, 3, 1);
174 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags, uintptr_t a)
176 uint32_t tmp, initcr;
177 void (*entry)(struct TagItem *);
179 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
182 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
183 * access. Exceptions are set to run in big-endian mode and this is the mode
184 * in which page tables are written.
186 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
187 tmp = initcr;
188 tmp &= ~1; /* Disable MMU */
189 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
190 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
191 #if AROS_BIG_ENDIAN
192 tmp |= (1 << 25); /* EE bit for exceptions set - big endian */
193 /* This bit sets also endianess of page tables */
194 #endif
195 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
197 /* Prepare MMU tables but do not load them yet */
198 mmu_init();
200 /* Initialize simplistic local memory allocator */
201 mem_init();
203 int dt_mem_usage = mem_avail();
204 /* Parse device tree */
205 dt_parse(atags);
206 dt_mem_usage -= mem_avail();
208 /* Prepare mapping for peripherals. Use the data from device tree here */
209 of_node_t *e = dt_find_node("/soc");
210 if (e)
212 of_property_t *p = dt_find_property(e, "ranges");
213 uint32_t *ranges = p->op_value;
214 int32_t len = p->op_length;
216 while(len > 0)
218 uint32_t addr_bus, addr_cpu;
219 uint32_t addr_len;
221 addr_bus = AROS_BE2LONG(*ranges++);
222 addr_cpu = AROS_BE2LONG(*ranges++);
223 addr_len = AROS_BE2LONG(*ranges++);
225 (void)addr_bus;
227 /* If periiobase was not set yet, do it now */
228 if (__arm_periiobase == 0) {
229 __arm_periiobase = (uint32_t)addr_cpu;
232 /* Prepare mapping - device type */
233 mmu_map_section(addr_cpu, addr_cpu, addr_len, 1, 0, 3, 0);
235 len -= 12;
238 else
239 while(1) asm volatile("wfe");
241 serInit();
243 #if AROS_BIG_ENDIAN
244 kprintf("\n\n[BOOT] Big-Endian AROS %s\n", bootstrapName);
245 #else
246 kprintf("\n\n[BOOT] Little-Endian AROS %s\n", bootstrapName);
247 #endif
248 kprintf("[BOOT] Booted on %s\n", dt_find_property(dt_find_node("/"), "model")->op_value);
250 /* first of all, store the arch for the kernel to use .. */
251 boottag->ti_Tag = KRN_Platform;
252 boottag->ti_Data = (IPTR)arch;
253 boottag++;
256 Check if device tree contains /soc/local_intc entry. In this case assume RasPi 2 or 3 with smp setup.
257 Neither PiZero nor classic Pi provide this entry.
259 e = dt_find_node("/__symbols__");
260 if (e)
262 of_property_t *p = dt_find_property(e, "local_intc");
264 if (p)
266 kprintf("[BOOT] local_intc points to %s\n", p->op_value);
268 e = dt_find_node(p->op_value);
269 p = dt_find_property(e, "reg");
270 uint32_t *reg = p->op_value;
272 kprintf("[BOOT] Mapping local interrupt area at %p-%p\n", AROS_BE2LONG(reg[0]), AROS_BE2LONG(reg[0]) + AROS_BE2LONG(reg[1]) - 1);
274 /* Prepare mapping - device type */
275 mmu_map_section(AROS_BE2LONG(reg[0]), AROS_BE2LONG(reg[0]), AROS_BE2LONG(reg[1]) < 0x100000 ? 0x100000 : AROS_BE2LONG(reg[1]), 0, 0, 3, 0);
280 /* Init LED(s) */
281 e = dt_find_node("/leds");
282 if (e)
284 of_node_t *led;
285 kprintf("[BOOT] Configuring LEDs\n");
286 ForeachNode(&e->on_children, led)
288 of_property_t *p = dt_find_property(led, "gpios");
289 int32_t gpio = 0;
290 if (p && p->op_length >= 8) {
291 uint32_t *data = p->op_value;
292 uint32_t phandle = AROS_BE2LONG(data[0]);
293 gpio = AROS_BE2LONG(data[1]);
294 of_node_t *bus = dt_find_node_by_phandle(phandle);
296 kprintf("[BOOT] %s: GPIO%d (%08x %08x %08x)\n", led->on_name, gpio,
297 AROS_BE2LONG(data[0]), AROS_BE2LONG(data[1]), AROS_BE2LONG(data[2]));
298 if (bus)
300 kprintf("[BOOT] LED attached to %s\n", bus->on_name);
302 if (strncmp(bus->on_name, "gpio", 4) == 0)
304 int gpio_sel = gpio / 10;
305 int gpio_soff = 3 * (gpio - 10 * gpio_sel);
307 kprintf("[BOOT] GPFSEL=%x, bit=%d\n", gpio_sel * 4, gpio_soff);
309 /* Configure GPIO as output */
310 tmp = rd32le(GPFSEL0 + 4*gpio_sel);
311 tmp &= ~(7 << gpio_soff); // GPIO 47 = 001 - output
312 tmp |= (1 << gpio_soff);
313 wr32le(GPFSEL0 + 4*gpio_sel, tmp);
315 /* Turn LED off */
316 wr32le(GPCLR0 + 4 * (gpio / 32), 1 << (gpio % 32));
323 kprintf("[BOOT] DT memory usage: %d\n", dt_mem_usage);
325 boottag->ti_Tag = KRN_BootLoader;
326 boottag->ti_Data = (IPTR)bootstrapName;
327 boottag++;
329 if (vcfb_init())
331 boottag->ti_Tag = KRN_FuncPutC;
332 boottag->ti_Data = (IPTR)fb_Putc;
333 boottag++;
336 DBOOT({
337 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
338 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
340 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
341 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
343 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
344 kprintf("[BOOT] main id register: %08x\n", tmp);
347 query_memory();
348 query_vmem();
350 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
352 boottag->ti_Tag = KRN_ProtAreaStart;
353 boottag->ti_Data = (IPTR)&__bootstrap_start;
354 boottag++;
356 boottag->ti_Tag = KRN_ProtAreaEnd;
357 boottag->ti_Data = (IPTR)&__bootstrap_end;
358 boottag++;
360 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
362 e = dt_find_node("/chosen");
363 if (e)
365 of_property_t *p = dt_find_property(e, "linux,initrd-start");
366 if (p)
367 pkg_image = (void*)AROS_BE2LONG((*((uint32_t *)p->op_value)));
368 else
369 pkg_image = NULL;
371 p = dt_find_property(e, "linux,initrd-end");
372 if (p)
373 pkg_size = AROS_BE2LONG(*((uint32_t *)p->op_value)) - (uint32_t)pkg_image;
374 else
375 pkg_size = 0;
378 kprintf("[BOOT] BSP image: %08x-%08x\n", pkg_image, (int32_t)pkg_image + pkg_size - 1);
380 kprintf("[BOOT] mem_avail=%d\n", mem_avail());
382 unsigned long total_size_ro = 0, total_size_rw = 0;
383 void *fdt = NULL;
385 if (mem_upper)
387 *mem_upper = *mem_upper & ~4095;
389 unsigned long kernel_phys = *mem_upper;
390 unsigned long kernel_virt = kernel_phys;
392 uint32_t size_ro, size_rw;
394 /* Calculate total size of kernel and modules */
395 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
397 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
398 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
400 if (pkg_image && pkg_size)
402 uint8_t *base = pkg_image;
404 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
406 getElfSize(base, &size_rw, &size_ro);
408 total_size_ro += (size_ro + 4095) & ~4095;
409 total_size_rw += (size_rw + 4095) & ~4095;
411 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
413 uint8_t *file = base+4;
414 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
415 const uint8_t *file_end = base+total_length;
416 uint32_t len, cnt = 0;
418 file = base + 8;
420 while(file < file_end)
422 //const char *filename = remove_path(file+4);
424 /* get text length */
425 len = AROS_BE2LONG(*(uint32_t*)file);
427 file += len + 5;
429 len = AROS_BE2LONG(*(uint32_t *)file);
430 file += 4;
432 /* load it */
433 getElfSize(file, &size_rw, &size_ro);
435 total_size_ro += (size_ro + 4095) & ~4095;
436 total_size_rw += (size_rw + 4095) & ~4095;
438 /* go to the next file */
439 file += len;
440 cnt++;
445 /* Reserve space for flattened device tree */
446 total_size_ro += (dt_total_size() + 31) & ~31;
448 /* Reserve space for unpacked device tree */
449 total_size_ro += (dt_mem_usage + 31) & ~31;
451 /* Align space to 1MB boundary - it will save some space in MMU tables */
452 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
453 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
455 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
456 kernel_virt = KERNEL_VIRT_ADDRESS;
458 bzero((void*)kernel_phys, total_size_ro + total_size_rw);
460 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
461 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
463 if (dt_total_size() > 0)
465 long dt_size = (dt_total_size() + 31) & ~31;
466 /* Copy device tree to the end of kernel RO area */
467 memcpy((void*)(kernel_phys + total_size_ro - dt_size), atags, dt_size);
468 fdt = (void*)(kernel_virt + total_size_ro - dt_size);
470 /* Store device tree */
471 boottag->ti_Tag = KRN_FlattenedDeviceTree;
472 boottag->ti_Data = (IPTR)kernel_virt + total_size_ro - dt_size;
473 boottag++;
475 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);
478 *mem_upper = kernel_phys;
480 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
482 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
483 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
485 /* map kernel memory for user access */
486 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
487 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
489 entry = (void (*)(struct TagItem *))kernel_virt;
491 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
493 boottag->ti_Tag = KRN_KernelLowest;
494 boottag->ti_Data = kernel_virt;
495 boottag++;
497 boottag->ti_Tag = KRN_KernelHighest;
498 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
499 boottag++;
501 boottag->ti_Tag = KRN_KernelPhysLowest;
502 boottag->ti_Data = kernel_phys;
503 boottag++;
505 loadElf(&_binary_core_bin_start);
507 if (pkg_image && pkg_size)
509 uint8_t *base = pkg_image;
511 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
513 kprintf("[BOOT] Kernel image is ELF file\n");
515 loadElf(base);
517 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
519 kprintf("[BOOT] Kernel image is a package:\n");
521 uint8_t *file = base+4;
522 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
523 const uint8_t *file_end = base+total_length;
524 uint32_t len, cnt = 0;
526 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
528 file = base + 8;
530 while(file < file_end)
532 const char *filename = remove_path(file+4);
534 /* get text length */
535 len = AROS_BE2LONG(*(uint32_t*)file);
536 /* display the file name */
537 if (cnt % 4 == 0)
538 kprintf("\n[BOOT] %s", filename);
539 else
540 kprintf(", %s", filename);
542 file += len + 5;
544 len = AROS_BE2LONG(*(uint32_t *)file);
545 file += 4;
547 /* load it */
548 loadElf(file);
550 /* go to the next file */
551 file += len;
552 cnt++;
554 kprintf("\n");
558 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
560 boottag->ti_Tag = KRN_KernelBss;
561 boottag->ti_Data = (IPTR)tracker;
562 boottag++;
565 mmu_load();
567 int memory_used = mem_used();
569 /* If device tree is in high kernel memory then parse it again */
570 if (dt_total_size() > 0)
572 void * dt_location = (void *)(KERNEL_VIRT_ADDRESS + total_size_ro - ((dt_total_size() + 31) & ~31) - ((dt_mem_usage + 31) & ~31));
573 kprintf("[BOOT] Creating device tree in kernel area at %p\n", dt_location);
575 explicit_mem_init(dt_location, (dt_mem_usage + 31) & ~31);
576 dt_parse(fdt);
578 boottag->ti_Tag = KRN_OpenFirmwareTree;
579 boottag->ti_Data = (IPTR)dt_location;
580 boottag++;
582 e = dt_find_node("/chosen");
583 if (e)
585 of_property_t *p = dt_find_property(e, "bootargs");
586 if (p)
588 boottag->ti_Tag = KRN_CmdLine;
589 boottag->ti_Data = (IPTR)p->op_value;
590 boottag++;
592 kprintf("[BOOT] Kernel parameters @ %p: %s\n", p->op_value, p->op_value);
597 boottag->ti_Tag = TAG_DONE;
598 boottag->ti_Data = 0;
600 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));
601 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", memory_used);
603 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
605 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
607 kprintf("[BOOT] Back? Something wrong happened...\n");
609 while(1) asm volatile("wfe");