pass the arch to kernel.resource
[AROS.git] / arch / arm-raspi / boot / boot.c
blob62197a4f41e8b1b3da0168d7f1b13586fd3f4b27
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/videocore.h>
20 #include "boot.h"
21 #include "serialdebug.h"
22 #include "bootconsole.h"
23 #include "atags.h"
24 #include "elf.h"
25 #include "mmu.h"
27 #include "vc_mb.h"
28 #include "vc_fb.h"
30 #define DBOOT(x) x
32 #undef ARM_PERIIOBASE
33 #define ARM_PERIIOBASE (__arm_periiobase)
35 uint32_t __arm_periiobase;
37 extern void mem_init(void);
38 extern unsigned int uartclock;
39 extern unsigned int uartdivint;
40 extern unsigned int uartdivfrac;
41 extern unsigned int uartbaud;
43 asm(" .section .aros.startup \n"
44 " .globl bootstrap \n"
45 " .type bootstrap,%function \n"
46 "bootstrap: \n"
47 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
48 " ldr sp, tmp_stack_ptr \n"
49 " b boot \n"
51 ".string \"$VER: arosraspi.img v40.45 (" __DATE__ ")\"" "\n\t\n\t"
54 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
55 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
56 static struct TagItem *boottag;
57 static unsigned long *mem_upper;
58 static void *pkg_image;
59 static uint32_t pkg_size;
61 static void parse_atags(struct tag *tags)
63 struct tag *t = NULL;
65 kprintf("[BOOT] Parsing ATAGS\n");
67 for_each_tag(t, tags)
69 kprintf("[BOOT] %08x: ", t->hdr.tag);
70 switch (t->hdr.tag)
72 case 0:
73 kprintf("ATAG_NONE - Ignored\n");
74 break;
76 case ATAG_CORE:
77 kprintf("ATAG_CORE - Ignored\n");
78 break;
80 case ATAG_MEM:
81 kprintf("ATAG_MEM (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
82 boottag->ti_Tag = KRN_MEMLower;
83 if ((boottag->ti_Data = t->u.mem.start) == 0)
84 boottag->ti_Data = 0x1000; // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
86 boottag++;
87 boottag->ti_Tag = KRN_MEMUpper;
88 boottag->ti_Data = t->u.mem.start + t->u.mem.size;
90 mem_upper = &boottag->ti_Data;
92 boottag++;
94 mmu_map_section(t->u.mem.start, t->u.mem.start, t->u.mem.size, 1, 1, 3, 1);
96 break;
98 case ATAG_VIDEOTEXT:
99 kprintf("ATAG_VIDEOTEXT - Ignored\n");
100 break;
102 case ATAG_RAMDISK:
103 kprintf("ATAG_RAMDISK - Ignored\n");
104 break;
106 case ATAG_INITRD2:
107 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
108 pkg_image = (void *)t->u.initrd.start;
109 pkg_size = t->u.initrd.size;
110 break;
112 case ATAG_SERIAL:
113 kprintf("ATAG_SERIAL - Ignored\n");
114 break;
116 case ATAG_REVISION:
117 kprintf("ATAG_REVISION - Ignored\n");
118 break;
120 case ATAG_VIDEOLFB:
121 kprintf("ATAG_VIDEOLFB - Ignored\n");
122 break;
124 case ATAG_CMDLINE:
126 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
127 strcpy(cmdline, t->u.cmdline.cmdline);
128 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline);
130 boottag->ti_Tag = KRN_CmdLine;
131 boottag->ti_Data = (intptr_t)cmdline;
132 boottag++;
134 break;
136 default:
137 kprintf("(UNKNOWN)...\n");
138 break;
143 void query_vmem()
145 volatile unsigned int *vc_msg = (unsigned int *) MESSAGE_BUFFER;
147 kprintf("[BOOT] Query VC memory\n");
148 vc_msg[0] = 8 * 4;
149 vc_msg[1] = VCTAG_REQ;
150 vc_msg[2] = VCTAG_GETVCRAM;
151 vc_msg[3] = 8;
152 vc_msg[4] = 0;
153 vc_msg[5] = 0;
154 vc_msg[6] = 0;
155 vc_msg[7] = 0;
157 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, vc_msg);
158 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
160 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg[5], vc_msg[6]);
162 boottag->ti_Tag = KRN_VMEMLower;
163 boottag->ti_Data = vc_msg[5];
164 boottag++;
166 boottag->ti_Tag = KRN_VMEMUpper;
167 boottag->ti_Data = vc_msg[5] + vc_msg[6];
168 boottag++;
170 mmu_map_section(vc_msg[5], vc_msg[5], vc_msg[6], 1, 0, 3, 0);
173 static const char bootstrapName[] = "Bootstrap/ARM BCM2708";
175 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
177 uint32_t tmp, initcr;
178 int plus_board = 0;
179 void (*entry)(struct TagItem *);
182 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
183 * access
185 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
186 tmp = initcr;
187 tmp &= ~1; /* Disable MMU */
188 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
189 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
190 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
192 mmu_init();
195 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
196 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
198 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
200 tmp = (tmp >> 4) & 0xfff;
202 /* tmp == 7 means armv6 architecture. */
203 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
205 __arm_periiobase = BCM2836_PERIPHYSBASE;
206 plus_board = 1;
208 /* prepare map for core boot vector(s) */
209 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
211 else
213 __arm_periiobase = BCM2835_PERIPHYSBASE;
214 /* Need to detect the plus board here in order to control LEDs properly */
217 /* Prepare map for MMIO registers */
218 mmu_map_section(__arm_periiobase, __arm_periiobase, ARM_PERIIOSIZE, 1, 0, 3, 0);
220 mem_init();
222 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
224 /* first of all, store the arch for the kernel to use .. */
225 boottag->ti_Tag = KRN_Platform;
226 boottag->ti_Data = (IPTR)arch;
227 boottag++;
229 /* Init LED */
231 if (plus_board)
234 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
235 * 47 and 35. Enable both leds as output and turn both of them off.
237 * The power led will be brought back up once AROS boots.
240 tmp = *(volatile unsigned int *)GPFSEL4;
241 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
242 tmp |= (1 << 21);
243 *(volatile unsigned int *)GPFSEL4 = tmp;
245 tmp = *(volatile unsigned int *)GPFSEL3;
246 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
247 tmp |= (1 << 15);
248 *(volatile unsigned int *)GPFSEL3 = tmp;
250 /* LEDS off */
251 *(volatile unsigned int *)GPCLR1 = (1 << (47-32));
252 *(volatile unsigned int *)GPCLR1 = (1 << (35-32));
254 else
257 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
258 * off now, kernel.resource will bring it back later.
261 tmp = *(volatile unsigned int *)GPFSEL1;
262 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
263 tmp |= (1 << 18);
264 *(volatile unsigned int *)GPFSEL1 = tmp;
266 *(volatile unsigned int *)GPSET0 = (1 << 16);
270 serInit();
272 boottag->ti_Tag = KRN_BootLoader;
273 boottag->ti_Data = (IPTR)bootstrapName;
274 boottag++;
276 if (vcfb_init())
278 boottag->ti_Tag = KRN_FuncPutC;
279 boottag->ti_Data = (IPTR)fb_Putc;
280 boottag++;
283 kprintf("[BOOT] AROS %s\n", bootstrapName);
285 DBOOT({
286 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
287 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
289 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
290 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
292 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
293 kprintf("[BOOT] main id register: %08x\n", tmp);
296 parse_atags(atags);
297 query_vmem();
299 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
301 boottag->ti_Tag = KRN_ProtAreaStart;
302 boottag->ti_Data = (IPTR)&__bootstrap_start;
303 boottag++;
305 boottag->ti_Tag = KRN_ProtAreaEnd;
306 boottag->ti_Data = (IPTR)&__bootstrap_end;
307 boottag++;
309 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
311 if (mem_upper)
313 *mem_upper = *mem_upper & ~4095;
315 unsigned long kernel_phys = *mem_upper;
316 unsigned long kernel_virt = kernel_phys;
318 unsigned long total_size_ro, total_size_rw;
319 uint32_t size_ro, size_rw;
321 /* Calculate total size of kernel and modules */
322 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
324 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
325 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
327 if (pkg_image && pkg_size)
329 uint8_t *base = pkg_image;
331 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
333 getElfSize(base, &size_rw, &size_ro);
335 total_size_ro += (size_ro + 4095) & ~4095;
336 total_size_rw += (size_rw + 4095) & ~4095;
338 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
340 uint8_t *file = base+4;
341 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
342 const uint8_t *file_end = base+total_length;
343 uint32_t len, cnt = 0;
345 file = base + 8;
347 while(file < file_end)
349 const char *filename = remove_path(file+4);
351 /* get text length */
352 len = AROS_BE2LONG(*(uint32_t*)file);
354 file += len + 5;
356 len = AROS_BE2LONG(*(uint32_t *)file);
357 file += 4;
359 /* load it */
360 getElfSize(file, &size_rw, &size_ro);
362 total_size_ro += (size_ro + 4095) & ~4095;
363 total_size_rw += (size_rw + 4095) & ~4095;
365 /* go to the next file */
366 file += len;
367 cnt++;
372 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
373 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
375 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
376 kernel_virt = 0xf8000000;
378 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
379 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
381 *mem_upper = kernel_phys;
383 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
385 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
386 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
388 /* map kernel memory for user access */
389 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
390 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
392 entry = (void (*)(struct TagItem))kernel_virt;
394 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
396 boottag->ti_Tag = KRN_KernelLowest;
397 boottag->ti_Data = kernel_virt;
398 boottag++;
400 boottag->ti_Tag = KRN_KernelHighest;
401 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
402 boottag++;
404 boottag->ti_Tag = KRN_KernelPhysLowest;
405 boottag->ti_Data = kernel_phys;
406 boottag++;
408 loadElf(&_binary_core_bin_start);
410 if (pkg_image && pkg_size)
412 uint8_t *base = pkg_image;
414 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
416 kprintf("[BOOT] Kernel image is ELF file\n");
418 getElfSize(base, &size_rw, &size_ro);
420 total_size_ro += (size_ro + 4095) & ~4095;
421 total_size_rw += (size_rw + 4095) & ~4095;
423 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
425 kprintf("[BOOT] Kernel image is a package:\n");
427 uint8_t *file = base+4;
428 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
429 const uint8_t *file_end = base+total_length;
430 uint32_t len, cnt = 0;
432 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
434 file = base + 8;
436 while(file < file_end)
438 const char *filename = remove_path(file+4);
440 /* get text length */
441 len = AROS_BE2LONG(*(uint32_t*)file);
442 /* display the file name */
443 if (cnt % 4 == 0)
444 kprintf("\n[BOOT] %s", filename);
445 else
446 kprintf(", %s", filename);
448 file += len + 5;
450 len = AROS_BE2LONG(*(uint32_t *)file);
451 file += 4;
453 /* load it */
454 loadElf(file);
456 total_size_ro += (size_ro + 4095) & ~4095;
457 total_size_rw += (size_rw + 4095) & ~4095;
459 /* go to the next file */
460 file += len;
461 cnt++;
463 kprintf("\n");
467 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
469 boottag->ti_Tag = KRN_KernelBss;
470 boottag->ti_Data = (IPTR)tracker;
471 boottag++;
474 boottag->ti_Tag = TAG_DONE;
475 boottag->ti_Data = 0;
477 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));
478 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
480 mmu_load();
482 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
484 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
486 kprintf("[BOOT] Back? Something wrong happened...\n");
488 while(1);