Fixed compatibility of output.
[AROS.git] / arch / arm-raspi / boot / boot.c
blobfe360eb10e741bedf3364a388b64919218dd69f9
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"
51 " .section .text \n"
53 ".string \"$VER: arosraspi.img v40.45 (" __DATE__ ")\"" "\n\t\n\t"
56 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
57 static __used void * tmp_stack_ptr __attribute__((used, section(".aros.startup"))) = (void *)(0x1000 - 16);
58 static struct TagItem *boottag;
59 static unsigned long *mem_upper;
60 static void *pkg_image;
61 static uint32_t pkg_size;
63 static void parse_atags(struct tag *tags)
65 struct tag *t = NULL;
67 kprintf("[BOOT] Parsing ATAGS\n");
69 for_each_tag(t, tags)
71 kprintf("[BOOT] %08x: ", t->hdr.tag);
72 switch (t->hdr.tag)
74 case 0:
75 kprintf("ATAG_NONE - Ignored\n");
76 break;
78 case ATAG_CORE:
79 kprintf("ATAG_CORE - Ignored\n");
80 break;
82 case ATAG_MEM:
83 kprintf("ATAG_MEM (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
84 boottag->ti_Tag = KRN_MEMLower;
85 if ((boottag->ti_Data = t->u.mem.start) < sizeof(struct bcm2708bootmem))
86 boottag->ti_Data = sizeof(struct bcm2708bootmem); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
88 boottag++;
89 boottag->ti_Tag = KRN_MEMUpper;
90 boottag->ti_Data = t->u.mem.start + t->u.mem.size;
92 mem_upper = &boottag->ti_Data;
94 boottag++;
96 mmu_map_section(t->u.mem.start, t->u.mem.start, t->u.mem.size, 1, 1, 3, 1);
98 break;
100 case ATAG_VIDEOTEXT:
101 kprintf("ATAG_VIDEOTEXT - Ignored\n");
102 break;
104 case ATAG_RAMDISK:
105 kprintf("ATAG_RAMDISK - Ignored\n");
106 break;
108 case ATAG_INITRD2:
109 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
110 pkg_image = (void *)t->u.initrd.start;
111 pkg_size = t->u.initrd.size;
112 break;
114 case ATAG_SERIAL:
115 kprintf("ATAG_SERIAL - Ignored\n");
116 break;
118 case ATAG_REVISION:
119 kprintf("ATAG_REVISION - Ignored\n");
120 break;
122 case ATAG_VIDEOLFB:
123 kprintf("ATAG_VIDEOLFB - Ignored\n");
124 break;
126 case ATAG_CMDLINE:
128 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
129 strcpy(cmdline, t->u.cmdline.cmdline);
130 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline);
132 boottag->ti_Tag = KRN_CmdLine;
133 boottag->ti_Data = (intptr_t)cmdline;
134 boottag++;
136 break;
138 default:
139 kprintf("(UNKNOWN)...\n");
140 break;
145 void query_vmem()
147 volatile unsigned int *vc_msg = (unsigned int *) BOOTMEMADDR(bm_mboxmsg);
149 kprintf("[BOOT] Query VC memory\n");
150 vc_msg[0] = 8 * 4;
151 vc_msg[1] = VCTAG_REQ;
152 vc_msg[2] = VCTAG_GETVCRAM;
153 vc_msg[3] = 8;
154 vc_msg[4] = 0;
155 vc_msg[5] = 0;
156 vc_msg[6] = 0;
157 vc_msg[7] = 0;
159 vcmb_write(VCMB_BASE, VCMB_PROPCHAN, vc_msg);
160 vc_msg = vcmb_read(VCMB_BASE, VCMB_PROPCHAN);
162 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg[5], vc_msg[6]);
164 boottag->ti_Tag = KRN_VMEMLower;
165 boottag->ti_Data = vc_msg[5];
166 boottag++;
168 boottag->ti_Tag = KRN_VMEMUpper;
169 boottag->ti_Data = vc_msg[5] + vc_msg[6];
170 boottag++;
172 mmu_map_section(vc_msg[5], vc_msg[5], vc_msg[6], 1, 0, 3, 0);
175 static const char bootstrapName[] = "Bootstrap/ARM BCM2708";
177 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
179 uint32_t tmp, initcr;
180 int plus_board = 0;
181 void (*entry)(struct TagItem *);
184 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
185 * access
187 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr));
188 tmp = initcr;
189 tmp &= ~1; /* Disable MMU */
190 tmp |= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
191 tmp = (tmp & ~2) | (1 << 22); /* Unaligned access enable */
192 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp));
194 mmu_init();
197 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
198 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
200 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp));
202 tmp = (tmp >> 4) & 0xfff;
204 /* tmp == 7 means armv6 architecture. */
205 if (tmp == 0xc07) /* armv7, also RaspberryPi 2 */
207 __arm_periiobase = BCM2836_PERIPHYSBASE;
208 plus_board = 1;
210 /* prepare map for core boot vector(s) */
211 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
213 else
215 __arm_periiobase = BCM2835_PERIPHYSBASE;
216 /* Need to detect the plus board here in order to control LEDs properly */
219 /* Prepare map for MMIO registers */
220 mmu_map_section(__arm_periiobase, __arm_periiobase, ARM_PERIIOSIZE, 1, 0, 3, 0);
222 mem_init();
224 boottag = tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE;
226 /* first of all, store the arch for the kernel to use .. */
227 boottag->ti_Tag = KRN_Platform;
228 boottag->ti_Data = (IPTR)arch;
229 boottag++;
231 /* Init LED */
233 if (plus_board)
236 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
237 * 47 and 35. Enable both leds as output and turn both of them off.
239 * The power led will be brought back up once AROS boots.
242 tmp = *(volatile unsigned int *)GPFSEL4;
243 tmp &= ~(7 << 21); // GPIO 47 = 001 - output
244 tmp |= (1 << 21);
245 *(volatile unsigned int *)GPFSEL4 = tmp;
247 tmp = *(volatile unsigned int *)GPFSEL3;
248 tmp &= ~(7 << 15); // GPIO 35 = 001 - output
249 tmp |= (1 << 15);
250 *(volatile unsigned int *)GPFSEL3 = tmp;
252 /* LEDS off */
253 *(volatile unsigned int *)GPCLR1 = (1 << (47-32));
254 *(volatile unsigned int *)GPCLR1 = (1 << (35-32));
256 else
259 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
260 * off now, kernel.resource will bring it back later.
263 tmp = *(volatile unsigned int *)GPFSEL1;
264 tmp &= ~(7 << 18); // GPIO 16 = 001 - output
265 tmp |= (1 << 18);
266 *(volatile unsigned int *)GPFSEL1 = tmp;
268 *(volatile unsigned int *)GPSET0 = (1 << 16);
272 serInit();
274 boottag->ti_Tag = KRN_BootLoader;
275 boottag->ti_Data = (IPTR)bootstrapName;
276 boottag++;
278 if (vcfb_init())
280 boottag->ti_Tag = KRN_FuncPutC;
281 boottag->ti_Data = (IPTR)fb_Putc;
282 boottag++;
285 kprintf("[BOOT] AROS %s\n", bootstrapName);
287 DBOOT({
288 kprintf("[BOOT] UART clock speed: %d\n", uartclock);
289 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint, uartdivfrac, uartbaud);
291 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp));
292 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr, tmp);
294 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp));
295 kprintf("[BOOT] main id register: %08x\n", tmp);
298 parse_atags(atags);
299 query_vmem();
301 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
303 boottag->ti_Tag = KRN_ProtAreaStart;
304 boottag->ti_Data = (IPTR)&__bootstrap_start;
305 boottag++;
307 boottag->ti_Tag = KRN_ProtAreaEnd;
308 boottag->ti_Data = (IPTR)&__bootstrap_end;
309 boottag++;
311 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
313 if (mem_upper)
315 *mem_upper = *mem_upper & ~4095;
317 unsigned long kernel_phys = *mem_upper;
318 unsigned long kernel_virt = kernel_phys;
320 unsigned long total_size_ro, total_size_rw;
321 uint32_t size_ro, size_rw;
323 /* Calculate total size of kernel and modules */
324 getElfSize(&_binary_core_bin_start, &size_rw, &size_ro);
326 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
327 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
329 if (pkg_image && pkg_size)
331 uint8_t *base = pkg_image;
333 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
335 getElfSize(base, &size_rw, &size_ro);
337 total_size_ro += (size_ro + 4095) & ~4095;
338 total_size_rw += (size_rw + 4095) & ~4095;
340 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
342 uint8_t *file = base+4;
343 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
344 const uint8_t *file_end = base+total_length;
345 uint32_t len, cnt = 0;
347 file = base + 8;
349 while(file < file_end)
351 const char *filename = remove_path(file+4);
353 /* get text length */
354 len = AROS_BE2LONG(*(uint32_t*)file);
356 file += len + 5;
358 len = AROS_BE2LONG(*(uint32_t *)file);
359 file += 4;
361 /* load it */
362 getElfSize(file, &size_rw, &size_ro);
364 total_size_ro += (size_ro + 4095) & ~4095;
365 total_size_rw += (size_rw + 4095) & ~4095;
367 /* go to the next file */
368 file += len;
369 cnt++;
374 total_size_ro = (total_size_ro + 1024*1024-1) & 0xfff00000;
375 total_size_rw = (total_size_rw + 1024*1024-1) & 0xfff00000;
377 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
378 kernel_virt = 0xf8000000;
380 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
381 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
383 *mem_upper = kernel_phys;
385 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper));
387 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
388 mmu_unmap_section(kernel_phys, total_size_ro + total_size_rw);
390 /* map kernel memory for user access */
391 mmu_map_section(kernel_phys, kernel_virt, total_size_ro, 1, 1, 2, 1);
392 mmu_map_section(kernel_phys + total_size_ro, kernel_virt + total_size_ro, total_size_rw, 1, 1, 3, 1);
394 entry = (void (*)(struct TagItem))kernel_virt;
396 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
398 boottag->ti_Tag = KRN_KernelLowest;
399 boottag->ti_Data = kernel_virt;
400 boottag++;
402 boottag->ti_Tag = KRN_KernelHighest;
403 boottag->ti_Data = kernel_virt + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
404 boottag++;
406 boottag->ti_Tag = KRN_KernelPhysLowest;
407 boottag->ti_Data = kernel_phys;
408 boottag++;
410 loadElf(&_binary_core_bin_start);
412 if (pkg_image && pkg_size)
414 uint8_t *base = pkg_image;
416 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
418 kprintf("[BOOT] Kernel image is ELF file\n");
420 getElfSize(base, &size_rw, &size_ro);
422 total_size_ro += (size_ro + 4095) & ~4095;
423 total_size_rw += (size_rw + 4095) & ~4095;
425 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
427 kprintf("[BOOT] Kernel image is a package:\n");
429 uint8_t *file = base+4;
430 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
431 const uint8_t *file_end = base+total_length;
432 uint32_t len, cnt = 0;
434 kprintf("[BOOT] Package size: %dKB", total_length >> 10);
436 file = base + 8;
438 while(file < file_end)
440 const char *filename = remove_path(file+4);
442 /* get text length */
443 len = AROS_BE2LONG(*(uint32_t*)file);
444 /* display the file name */
445 if (cnt % 4 == 0)
446 kprintf("\n[BOOT] %s", filename);
447 else
448 kprintf(", %s", filename);
450 file += len + 5;
452 len = AROS_BE2LONG(*(uint32_t *)file);
453 file += 4;
455 /* load it */
456 loadElf(file);
458 total_size_ro += (size_ro + 4095) & ~4095;
459 total_size_rw += (size_rw + 4095) & ~4095;
461 /* go to the next file */
462 file += len;
463 cnt++;
465 kprintf("\n");
469 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
471 boottag->ti_Tag = KRN_KernelBss;
472 boottag->ti_Data = (IPTR)tracker;
473 boottag++;
476 boottag->ti_Tag = TAG_DONE;
477 boottag->ti_Data = 0;
479 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));
480 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
482 mmu_load();
484 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
486 entry((struct TagItem *)(tmp_stack_ptr - BOOT_STACK_SIZE - BOOT_TAGS_SIZE));
488 kprintf("[BOOT] Back? Something wrong happened...\n");
490 while(1);