Query VideoCore for VMEM (needed for further MMU mapping)
[AROS.git] / arch / arm-raspi / boot / boot.c
blob4d9e626bdcacdb36c57e64cfa12415fb5bf53b6a
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 <string.h>
14 #include <stdlib.h>
15 #include <stdint.h>
17 #include <hardware/bcm283x.h>
18 #include <hardware/videocore.h>
20 #include "boot.h"
21 #include "serialdebug.h"
22 #include "bootconsole.h"
23 #include "atags.h"
24 #include "elf.h"
26 #include "vc_mb.h"
27 #include "vc_fb.h"
29 #define DBOOT(x) x
31 #undef ARM_PERIIOBASE
32 #define ARM_PERIIOBASE (__arm_periiobase)
34 uint32_t __arm_periiobase;
36 extern void mem_init(void);
37 extern unsigned int uartclock;
38 extern unsigned int uartdivint;
39 extern unsigned int uartdivfrac;
40 extern unsigned int uartbaud;
42 asm(" .section .aros.startup \n"
43 " .globl bootstrap \n"
44 " .type bootstrap,%function \n"
45 "bootstrap: \n"
46 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
47 " ldr sp, tmp_stack_ptr \n"
48 " b boot \n"
50 ".string \"$VER: arosraspi.img v40.45 (" __DATE__ ")\"" "\n\t\n\t"
53 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
54 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
55 static struct TagItem *boottag;
56 static unsigned long mem_upper;
57 static void *pkg_image;
58 static uint32_t pkg_size;
60 static void parse_atags(struct tag *tags)
62 struct tag *t = NULL;
64 kprintf("[BOOT] Parsing ATAGS\n");
66 for_each_tag(t, tags)
68 kprintf("[BOOT] %08x: ", t->hdr.tag, t->hdr.size);
69 switch (t->hdr.tag)
71 case 0:
72 kprintf("ATAG_NONE - Ignored\n");
73 break;
75 case ATAG_CORE:
76 kprintf("ATAG_CORE - Ignored\n");
77 break;
79 case ATAG_MEM:
80 kprintf("ATAG_MEM (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
81 boottag->ti_Tag = KRN_MEMLower;
82 if ((boottag->ti_Data = t->u.mem.start) == 0)
83 boottag->ti_Data = 0x1000; // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
85 boottag++;
86 boottag->ti_Tag = KRN_MEMUpper;
87 boottag->ti_Data = t->u.mem.start + t->u.mem.size;
88 boottag++;
90 mem_upper = t->u.mem.start + t->u.mem.size;
92 break;
94 case ATAG_VIDEOTEXT:
95 kprintf("ATAG_VIDEOTEXT - Ignored\n");
96 break;
98 case ATAG_RAMDISK:
99 kprintf("ATAG_RAMDISK - Ignored\n");
100 break;
102 case ATAG_INITRD2:
103 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
104 pkg_image = (void *)t->u.initrd.start;
105 pkg_size = t->u.initrd.size;
106 break;
108 case ATAG_SERIAL:
109 kprintf("ATAG_SERIAL - Ignored\n");
110 break;
112 case ATAG_REVISION:
113 kprintf("ATAG_REVISION - Ignored\n");
114 break;
116 case ATAG_VIDEOLFB:
117 kprintf("ATAG_VIDEOLFB - Ignored\n");
118 break;
120 case ATAG_CMDLINE:
122 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
123 strcpy(cmdline, t->u.cmdline.cmdline);
124 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline);
126 boottag->ti_Tag = KRN_CmdLine;
127 boottag->ti_Data = (intptr_t)cmdline;
128 boottag++;
130 break;
132 default:
133 kprintf("(UNKNOWN)...\n");
134 break;
139 void query_vmem()
141 volatile unsigned int *vc_msg = (unsigned int *) MESSAGE_BUFFER;
143 kprintf("[BOOT] Query VC memory\n");
144 vc_msg[0] = 8 * 4;
145 vc_msg[1] = VCTAG_REQ;
146 vc_msg[2] = VCTAG_GETVCRAM;
147 vc_msg[3] = 8;
148 vc_msg[4] = 0;
149 vc_msg[5] = 0;
150 vc_msg[6] = 0;
151 vc_msg[7] = 0;
153 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, vc_msg);
154 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
156 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg[5], vc_msg[6]);
158 boottag->ti_Tag = KRN_VMEMLower;
159 boottag->ti_Data = vc_msg[5];
160 boottag++;
162 boottag->ti_Tag = KRN_VMEMUpper;
163 boottag->ti_Data = vc_msg[5] + vc_msg[6];
164 boottag++;
167 static const char bootstrapName[] = "Bootstrap/RasPI ARM";
169 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
171 uint32_t tmp, initcr;
172 int plus_board = 0;
173 void (*entry)(struct TagItem *);
176 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
177 * access
179 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
180 tmp = initcr;
181 tmp &= ~1; /* Disable MMU */
182 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
183 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
184 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
187 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
188 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
190 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
192 tmp = (tmp >> 4) & 0xfff;
194 /* tmp == 7 means armv6 architecture. */
195 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
197 __arm_periiobase = BCM2836_PERIPHYSBASE;
198 plus_board = 1;
200 else
202 __arm_periiobase = BCM2835_PERIPHYSBASE;
203 /* Need to detect the plus board here in order to control LEDs properly */
206 mem_init();
208 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
210 /* Init LED */
212 if (plus_board)
215 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
216 * 47 and 35. Enable both leds as output and turn both of them off.
218 * The power led will be brought back up once AROS boots.
221 tmp = *(volatile unsigned int *)GPFSEL4;
222 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
223 tmp |= (1 << 21);
224 *(volatile unsigned int *)GPFSEL4 = tmp;
226 tmp = *(volatile unsigned int *)GPFSEL3;
227 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
228 tmp |= (1 << 15);
229 *(volatile unsigned int *)GPFSEL3 = tmp;
231 /* LEDS off */
232 *(volatile unsigned int *)GPCLR1 = (1 << (47-32));
233 *(volatile unsigned int *)GPCLR1 = (1 << (35-32));
235 else
238 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
239 * off now, kernel.resource will bring it back later.
242 tmp = *(volatile unsigned int *)GPFSEL1;
243 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
244 tmp |= (1 << 18);
245 *(volatile unsigned int *)GPFSEL1 = tmp;
247 *(volatile unsigned int *)GPSET0 = (1 << 16);
251 serInit();
253 boottag->ti_Tag = KRN_BootLoader;
254 boottag->ti_Data = (IPTR)bootstrapName;
255 boottag++;
257 if (vcfb_init())
259 boottag->ti_Tag = KRN_FuncPutC;
260 boottag->ti_Data = (IPTR)fb_Putc;
261 boottag++;
264 kprintf("[BOOT] AROS %s\n", bootstrapName);
266 DBOOT({
267 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
268 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
270 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
271 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
273 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
274 kprintf("[BOOT] main id register: %08x\n", tmp);
277 parse_atags(atags);
278 query_vmem();
280 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
282 boottag->ti_Tag = KRN_ProtAreaStart;
283 boottag->ti_Data = (IPTR)&__bootstrap_start;
284 boottag++;
286 boottag->ti_Tag = KRN_ProtAreaEnd;
287 boottag->ti_Data = (IPTR)&__bootstrap_end;
288 boottag++;
290 kprintf("[BOOT] Topmost address for kernel: %p\n", mem_upper);
292 if (mem_upper)
294 mem_upper = mem_upper & ~4095;
296 unsigned long kernel_phys = mem_upper;
297 unsigned long kernel_virt = kernel_phys;
299 unsigned long total_size_ro, total_size_rw;
300 uint32_t size_ro, size_rw;
302 /* Calculate total size of kernel and modules */
303 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
305 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
306 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
308 if (pkg_image && pkg_size)
310 uint8_t *base = pkg_image;
312 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
314 kprintf("[BOOT] Kernel image is ELF file\n");
316 getElfSize(base, &size_rw, &size_ro);
318 total_size_ro += (size_ro + 4095) & ~4095;
319 total_size_rw += (size_rw + 4095) & ~4095;
321 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
323 kprintf("[BOOT] Kernel image is a package:\n");
325 uint8_t *file = base+4;
326 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
327 const uint8_t *file_end = base+total_length;
328 uint32_t len, cnt = 0;
330 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
332 file = base + 8;
334 while(file < file_end)
336 const char *filename = remove_path(file+4);
338 /* get text length */
339 len = AROS_BE2LONG(*(uint32_t*)file);
340 /* display the file name */
341 if (cnt % 4 == 0)
342 kprintf("\n[BOOT] %s", filename);
343 else
344 kprintf(", %s", filename);
346 file += len + 5;
348 len = AROS_BE2LONG(*(uint32_t *)file);
349 file += 4;
351 /* load it */
352 getElfSize(file, &size_rw, &size_ro);
354 total_size_ro += (size_ro + 4095) & ~4095;
355 total_size_rw += (size_rw + 4095) & ~4095;
357 /* go to the next file */
358 file += len;
359 cnt++;
361 kprintf("\n");
365 kernel_phys = mem_upper - total_size_ro - total_size_rw;
366 kernel_virt = kernel_phys;
368 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
369 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
371 entry = (void (*)(struct TagItem))kernel_virt;
373 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
375 boottag->ti_Tag = KRN_KernelLowest;
376 boottag->ti_Data = kernel_phys;
377 boottag++;
379 boottag->ti_Tag = KRN_KernelHighest;
380 boottag->ti_Data = kernel_phys + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
381 boottag++;
383 loadElf(&_binary_core_bin_start);
385 if (pkg_image && pkg_size)
387 uint8_t *base = pkg_image;
389 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
391 kprintf("[BOOT] Kernel image is ELF file\n");
393 getElfSize(base, &size_rw, &size_ro);
395 total_size_ro += (size_ro + 4095) & ~4095;
396 total_size_rw += (size_rw + 4095) & ~4095;
398 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
400 kprintf("[BOOT] Kernel image is a package:\n");
402 uint8_t *file = base+4;
403 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
404 const uint8_t *file_end = base+total_length;
405 uint32_t len, cnt = 0;
407 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
409 file = base + 8;
411 while(file < file_end)
413 const char *filename = remove_path(file+4);
415 /* get text length */
416 len = AROS_BE2LONG(*(uint32_t*)file);
417 /* display the file name */
418 if (cnt % 4 == 0)
419 kprintf("\n[BOOT] %s", filename);
420 else
421 kprintf(", %s", filename);
423 file += len + 5;
425 len = AROS_BE2LONG(*(uint32_t *)file);
426 file += 4;
428 /* load it */
429 loadElf(file);
431 total_size_ro += (size_ro + 4095) & ~4095;
432 total_size_rw += (size_rw + 4095) & ~4095;
434 /* go to the next file */
435 file += len;
436 cnt++;
438 kprintf("\n");
442 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
444 boottag->ti_Tag = KRN_KernelBss;
445 boottag->ti_Data = (IPTR)tracker;
446 boottag++;
449 boottag->ti_Tag = TAG_DONE;
450 boottag->ti_Data = 0;
452 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));
453 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
455 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
457 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
459 kprintf("[BOOT] Back? Something wrong happened...\n");
461 while(1);