use the locations specified in the bcm2708_boot header
[AROS.git] / arch / arm-raspi / boot / boot.c
blob38ca1b21024fdf37d5fbb5a2311fa2b583020742
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/bcm2708.h>
18 #include <hardware/bcm2708_boot.h>
19 #include <hardware/videocore.h>
21 #include "boot.h"
22 #include "serialdebug.h"
23 #include "bootconsole.h"
24 #include "atags.h"
25 #include "elf.h"
26 #include "mmu.h"
28 #include "vc_mb.h"
29 #include "vc_fb.h"
31 #define DBOOT(x) x
33 #undef ARM_PERIIOBASE
34 #define ARM_PERIIOBASE (__arm_periiobase)
36 uint32_t __arm_periiobase;
38 extern void mem_init(void);
39 extern unsigned int uartclock;
40 extern unsigned int uartdivint;
41 extern unsigned int uartdivfrac;
42 extern unsigned int uartbaud;
44 asm(" .section .aros.startup \n"
45 " .globl bootstrap \n"
46 " .type bootstrap,%function \n"
47 "bootstrap: \n"
48 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
49 " ldr sp, tmp_stack_ptr \n"
50 " b boot \n"
52 ".string \"$VER: arosraspi.img v40.45 (" __DATE__ ")\"" "\n\t\n\t"
55 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
56 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
57 static struct TagItem *boottag;
58 static unsigned long *mem_upper;
59 static void *pkg_image;
60 static uint32_t pkg_size;
62 static void parse_atags(struct tag *tags)
64 struct tag *t = NULL;
66 kprintf("[BOOT] Parsing ATAGS\n");
68 for_each_tag(t, tags)
70 kprintf("[BOOT] %08x: ", t->hdr.tag);
71 switch (t->hdr.tag)
73 case 0:
74 kprintf("ATAG_NONE - Ignored\n");
75 break;
77 case ATAG_CORE:
78 kprintf("ATAG_CORE - Ignored\n");
79 break;
81 case ATAG_MEM:
82 kprintf("ATAG_MEM (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
83 boottag->ti_Tag = KRN_MEMLower;
84 if ((boottag->ti_Data = t->u.mem.start) == 0)
85 boottag->ti_Data = sizeof(struct bcm2708bootmem); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
87 boottag++;
88 boottag->ti_Tag = KRN_MEMUpper;
89 boottag->ti_Data = t->u.mem.start + t->u.mem.size;
91 mem_upper = &boottag->ti_Data;
93 boottag++;
95 mmu_map_section(t->u.mem.start, t->u.mem.start, t->u.mem.size, 1, 1, 3, 1);
97 break;
99 case ATAG_VIDEOTEXT:
100 kprintf("ATAG_VIDEOTEXT - Ignored\n");
101 break;
103 case ATAG_RAMDISK:
104 kprintf("ATAG_RAMDISK - Ignored\n");
105 break;
107 case ATAG_INITRD2:
108 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
109 pkg_image = (void *)t->u.initrd.start;
110 pkg_size = t->u.initrd.size;
111 break;
113 case ATAG_SERIAL:
114 kprintf("ATAG_SERIAL - Ignored\n");
115 break;
117 case ATAG_REVISION:
118 kprintf("ATAG_REVISION - Ignored\n");
119 break;
121 case ATAG_VIDEOLFB:
122 kprintf("ATAG_VIDEOLFB - Ignored\n");
123 break;
125 case ATAG_CMDLINE:
127 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
128 strcpy(cmdline, t->u.cmdline.cmdline);
129 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline);
131 boottag->ti_Tag = KRN_CmdLine;
132 boottag->ti_Data = (intptr_t)cmdline;
133 boottag++;
135 break;
137 default:
138 kprintf("(UNKNOWN)...\n");
139 break;
144 void query_vmem()
146 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
148 kprintf("[BOOT] Query VC memory\n");
149 vc_msg[0] = 8 * 4;
150 vc_msg[1] = VCTAG_REQ;
151 vc_msg[2] = VCTAG_GETVCRAM;
152 vc_msg[3] = 8;
153 vc_msg[4] = 0;
154 vc_msg[5] = 0;
155 vc_msg[6] = 0;
156 vc_msg[7] = 0;
158 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, vc_msg);
159 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
161 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg[5], vc_msg[6]);
163 boottag->ti_Tag = KRN_VMEMLower;
164 boottag->ti_Data = vc_msg[5];
165 boottag++;
167 boottag->ti_Tag = KRN_VMEMUpper;
168 boottag->ti_Data = vc_msg[5] + vc_msg[6];
169 boottag++;
171 mmu_map_section(vc_msg[5], vc_msg[5], vc_msg[6], 1, 0, 3, 0);
174 static const char bootstrapName[] = "Bootstrap/ARM BCM2708";
176 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
178 uint32_t tmp, initcr;
179 int plus_board = 0;
180 void (*entry)(struct TagItem *);
183 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
184 * access
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 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
193 mmu_init();
196 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
197 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
199 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
201 tmp = (tmp >> 4) & 0xfff;
203 /* tmp == 7 means armv6 architecture. */
204 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
206 __arm_periiobase = BCM2836_PERIPHYSBASE;
207 plus_board = 1;
209 /* prepare map for core boot vector(s) */
210 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
212 else
214 __arm_periiobase = BCM2835_PERIPHYSBASE;
215 /* Need to detect the plus board here in order to control LEDs properly */
218 /* Prepare map for MMIO registers */
219 mmu_map_section(__arm_periiobase, __arm_periiobase, ARM_PERIIOSIZE, 1, 0, 3, 0);
221 mem_init();
223 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
225 /* first of all, store the arch for the kernel to use .. */
226 boottag->ti_Tag = KRN_Platform;
227 boottag->ti_Data = (IPTR)arch;
228 boottag++;
230 /* Init LED */
232 if (plus_board)
235 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
236 * 47 and 35. Enable both leds as output and turn both of them off.
238 * The power led will be brought back up once AROS boots.
241 tmp = *(volatile unsigned int *)GPFSEL4;
242 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
243 tmp |= (1 << 21);
244 *(volatile unsigned int *)GPFSEL4 = tmp;
246 tmp = *(volatile unsigned int *)GPFSEL3;
247 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
248 tmp |= (1 << 15);
249 *(volatile unsigned int *)GPFSEL3 = tmp;
251 /* LEDS off */
252 *(volatile unsigned int *)GPCLR1 = (1 << (47-32));
253 *(volatile unsigned int *)GPCLR1 = (1 << (35-32));
255 else
258 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
259 * off now, kernel.resource will bring it back later.
262 tmp = *(volatile unsigned int *)GPFSEL1;
263 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
264 tmp |= (1 << 18);
265 *(volatile unsigned int *)GPFSEL1 = tmp;
267 *(volatile unsigned int *)GPSET0 = (1 << 16);
271 serInit();
273 boottag->ti_Tag = KRN_BootLoader;
274 boottag->ti_Data = (IPTR)bootstrapName;
275 boottag++;
277 if (vcfb_init())
279 boottag->ti_Tag = KRN_FuncPutC;
280 boottag->ti_Data = (IPTR)fb_Putc;
281 boottag++;
284 kprintf("[BOOT] AROS %s\n", bootstrapName);
286 DBOOT({
287 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
288 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
290 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
291 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
293 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
294 kprintf("[BOOT] main id register: %08x\n", tmp);
297 parse_atags(atags);
298 query_vmem();
300 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
302 boottag->ti_Tag = KRN_ProtAreaStart;
303 boottag->ti_Data = (IPTR)&__bootstrap_start;
304 boottag++;
306 boottag->ti_Tag = KRN_ProtAreaEnd;
307 boottag->ti_Data = (IPTR)&__bootstrap_end;
308 boottag++;
310 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
312 if (mem_upper)
314 *mem_upper = *mem_upper & ~4095;
316 unsigned long kernel_phys = *mem_upper;
317 unsigned long kernel_virt = kernel_phys;
319 unsigned long total_size_ro, total_size_rw;
320 uint32_t size_ro, size_rw;
322 /* Calculate total size of kernel and modules */
323 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
325 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
326 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
328 if (pkg_image && pkg_size)
330 uint8_t *base = pkg_image;
332 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
334 getElfSize(base, &size_rw, &size_ro);
336 total_size_ro += (size_ro + 4095) & ~4095;
337 total_size_rw += (size_rw + 4095) & ~4095;
339 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
341 uint8_t *file = base+4;
342 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
343 const uint8_t *file_end = base+total_length;
344 uint32_t len, cnt = 0;
346 file = base + 8;
348 while(file < file_end)
350 const char *filename = remove_path(file+4);
352 /* get text length */
353 len = AROS_BE2LONG(*(uint32_t*)file);
355 file += len + 5;
357 len = AROS_BE2LONG(*(uint32_t *)file);
358 file += 4;
360 /* load it */
361 getElfSize(file, &size_rw, &size_ro);
363 total_size_ro += (size_ro + 4095) & ~4095;
364 total_size_rw += (size_rw + 4095) & ~4095;
366 /* go to the next file */
367 file += len;
368 cnt++;
373 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
374 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
376 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
377 kernel_virt = 0xf8000000;
379 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
380 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
382 *mem_upper = kernel_phys;
384 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
386 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
387 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
389 /* map kernel memory for user access */
390 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
391 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
393 entry = (void (*)(struct TagItem))kernel_virt;
395 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
397 boottag->ti_Tag = KRN_KernelLowest;
398 boottag->ti_Data = kernel_virt;
399 boottag++;
401 boottag->ti_Tag = KRN_KernelHighest;
402 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
403 boottag++;
405 boottag->ti_Tag = KRN_KernelPhysLowest;
406 boottag->ti_Data = kernel_phys;
407 boottag++;
409 loadElf(&_binary_core_bin_start);
411 if (pkg_image && pkg_size)
413 uint8_t *base = pkg_image;
415 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
417 kprintf("[BOOT] Kernel image is ELF file\n");
419 getElfSize(base, &size_rw, &size_ro);
421 total_size_ro += (size_ro + 4095) & ~4095;
422 total_size_rw += (size_rw + 4095) & ~4095;
424 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
426 kprintf("[BOOT] Kernel image is a package:\n");
428 uint8_t *file = base+4;
429 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
430 const uint8_t *file_end = base+total_length;
431 uint32_t len, cnt = 0;
433 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
435 file = base + 8;
437 while(file < file_end)
439 const char *filename = remove_path(file+4);
441 /* get text length */
442 len = AROS_BE2LONG(*(uint32_t*)file);
443 /* display the file name */
444 if (cnt % 4 == 0)
445 kprintf("\n[BOOT] %s", filename);
446 else
447 kprintf(", %s", filename);
449 file += len + 5;
451 len = AROS_BE2LONG(*(uint32_t *)file);
452 file += 4;
454 /* load it */
455 loadElf(file);
457 total_size_ro += (size_ro + 4095) & ~4095;
458 total_size_rw += (size_rw + 4095) & ~4095;
460 /* go to the next file */
461 file += len;
462 cnt++;
464 kprintf("\n");
468 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
470 boottag->ti_Tag = KRN_KernelBss;
471 boottag->ti_Data = (IPTR)tracker;
472 boottag++;
475 boottag->ti_Tag = TAG_DONE;
476 boottag->ti_Data = 0;
478 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));
479 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
481 mmu_load();
483 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
485 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
487 kprintf("[BOOT] Back? Something wrong happened...\n");
489 while(1);