2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
11 #include <utility/tagitem.h>
12 #include <aros/macros.h>
13 #include <aros/kernel.h>
18 #include <hardware/bcm2708.h>
19 #include <hardware/bcm2708_boot.h>
20 #include <hardware/videocore.h>
23 #include "serialdebug.h"
24 #include "bootconsole.h"
35 #define ARM_PERIIOBASE (__arm_periiobase)
37 uint32_t __arm_periiobase
;
39 extern void mem_init(void);
40 extern unsigned int uartclock
;
41 extern unsigned int uartdivint
;
42 extern unsigned int uartdivfrac
;
43 extern unsigned int uartbaud
;
45 asm(" .section .aros.startup \n"
46 " .globl bootstrap \n"
47 " .type bootstrap,%function \n"
49 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
50 " ldr sp, tmp_stack_ptr \n"
54 ".string \"$VER: arosraspi.img v40.45 (" __DATE__
")\"" "\n\t\n\t"
57 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
58 static __used
void * tmp_stack_ptr
__attribute__((used
, section(".aros.startup"))) = (void *)(0x1000 - 16);
59 static struct TagItem
*boottag
;
60 static unsigned long *mem_upper
;
61 static void *pkg_image
;
62 static uint32_t pkg_size
;
64 static void parse_atags(struct tag
*tags
)
68 kprintf("[BOOT] Parsing ATAGS\n");
72 kprintf("[BOOT] %08x: ", t
->hdr
.tag
);
76 kprintf("ATAG_NONE - Ignored\n");
80 kprintf("ATAG_CORE - Ignored\n");
84 kprintf("ATAG_MEM (%08x-%08x)\n", t
->u
.mem
.start
, t
->u
.mem
.size
+ t
->u
.mem
.start
- 1);
85 boottag
->ti_Tag
= KRN_MEMLower
;
86 if ((boottag
->ti_Data
= t
->u
.mem
.start
) < sizeof(struct bcm2708bootmem
))
87 boottag
->ti_Data
= sizeof(struct bcm2708bootmem
); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
90 boottag
->ti_Tag
= KRN_MEMUpper
;
91 boottag
->ti_Data
= t
->u
.mem
.start
+ t
->u
.mem
.size
;
93 mem_upper
= &boottag
->ti_Data
;
97 mmu_map_section(t
->u
.mem
.start
, t
->u
.mem
.start
, t
->u
.mem
.size
, 1, 1, 3, 1);
102 kprintf("ATAG_VIDEOTEXT - Ignored\n");
106 kprintf("ATAG_RAMDISK - Ignored\n");
110 kprintf("ATAG_INITRD2 (%08x-%08x)\n", t
->u
.initrd
.start
, t
->u
.initrd
.size
+ t
->u
.initrd
.start
- 1);
111 pkg_image
= (void *)t
->u
.initrd
.start
;
112 pkg_size
= t
->u
.initrd
.size
;
116 kprintf("ATAG_SERIAL - Ignored\n");
120 kprintf("ATAG_REVISION - Ignored\n");
124 kprintf("ATAG_VIDEOLFB - Ignored\n");
129 char *cmdline
= malloc(strlen(t
->u
.cmdline
.cmdline
) + 1);
130 strcpy(cmdline
, t
->u
.cmdline
.cmdline
);
131 kprintf("ATAG_CMDLINE \"%s\"\n", cmdline
);
133 boottag
->ti_Tag
= KRN_CmdLine
;
134 boottag
->ti_Data
= (intptr_t)cmdline
;
140 kprintf("(UNKNOWN)...\n");
148 volatile unsigned int *vc_msg
= (unsigned int *) BOOTMEMADDR(bm_mboxmsg
);
150 kprintf("[BOOT] Query VC memory\n");
152 vc_msg
[1] = VCTAG_REQ
;
153 vc_msg
[2] = VCTAG_GETVCRAM
;
160 vcmb_write(VCMB_BASE
, VCMB_PROPCHAN
, vc_msg
);
161 vc_msg
= vcmb_read(VCMB_BASE
, VCMB_PROPCHAN
);
163 kprintf("[BOOT] Base = %08x, Size = %08x\n", vc_msg
[5], vc_msg
[6]);
165 boottag
->ti_Tag
= KRN_VMEMLower
;
166 boottag
->ti_Data
= vc_msg
[5];
169 boottag
->ti_Tag
= KRN_VMEMUpper
;
170 boottag
->ti_Data
= vc_msg
[5] + vc_msg
[6];
173 mmu_map_section(vc_msg
[5], vc_msg
[5], vc_msg
[6], 1, 0, 3, 0);
176 static const char bootstrapName
[] = "Bootstrap/ARM BCM2708";
178 void boot(uintptr_t dummy
, uintptr_t arch
, struct tag
* atags
)
180 uint32_t tmp
, initcr
;
182 void (*entry
)(struct TagItem
*);
185 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
188 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(initcr
));
190 tmp
&= ~1; /* Disable MMU */
191 tmp
|= (1 << 2) | (1 << 12) | (1 << 11); /* I and D caches, branch prediction */
192 tmp
= (tmp
& ~2) | (1 << 22); /* Unaligned access enable */
193 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp
));
198 Check processor type - armv6 is old raspberry pi with SOC IO base at 0x20000000.
199 armv7 will be raspberry pi 2 with SOC IO base at 0x3f000000
201 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (tmp
));
203 tmp
= (tmp
>> 4) & 0xfff;
205 /* tmp == 7 means armv6 architecture. */
206 if (tmp
== 0xc07) /* armv7, also RaspberryPi 2 */
208 __arm_periiobase
= BCM2836_PERIPHYSBASE
;
211 /* prepare map for core boot vector(s) */
212 mmu_map_section(0x40000000, 0x40000000, 0x100000, 0, 0, 3, 0);
216 __arm_periiobase
= BCM2835_PERIPHYSBASE
;
217 /* Need to detect the plus board here in order to control LEDs properly */
220 /* Prepare map for MMIO registers */
221 mmu_map_section(__arm_periiobase
, __arm_periiobase
, ARM_PERIIOSIZE
, 1, 0, 3, 0);
225 boottag
= tmp_stack_ptr
- BOOT_STACK_SIZE
- BOOT_TAGS_SIZE
;
227 /* first of all, store the arch for the kernel to use .. */
228 boottag
->ti_Tag
= KRN_Platform
;
229 boottag
->ti_Data
= (IPTR
)arch
;
237 * Either B+ or rpi2 board. Uses two leds (power and activity) on GPIOs
238 * 47 and 35. Enable both leds as output and turn both of them off.
240 * The power led will be brought back up once AROS boots.
243 tmp
= *(volatile unsigned int *)GPFSEL4
;
244 tmp
&= ~(7 << 21); // GPIO 47 = 001 - output
246 *(volatile unsigned int *)GPFSEL4
= tmp
;
248 tmp
= *(volatile unsigned int *)GPFSEL3
;
249 tmp
&= ~(7 << 15); // GPIO 35 = 001 - output
251 *(volatile unsigned int *)GPFSEL3
= tmp
;
254 *(volatile unsigned int *)GPCLR1
= (1 << (47-32));
255 *(volatile unsigned int *)GPCLR1
= (1 << (35-32));
260 * Classic rpi board has only one controlable LED - activity on GPIO 16. Turn it
261 * off now, kernel.resource will bring it back later.
264 tmp
= *(volatile unsigned int *)GPFSEL1
;
265 tmp
&= ~(7 << 18); // GPIO 16 = 001 - output
267 *(volatile unsigned int *)GPFSEL1
= tmp
;
269 *(volatile unsigned int *)GPSET0
= (1 << 16);
275 boottag
->ti_Tag
= KRN_BootLoader
;
276 boottag
->ti_Data
= (IPTR
)bootstrapName
;
281 boottag
->ti_Tag
= KRN_FuncPutC
;
282 boottag
->ti_Data
= (IPTR
)fb_Putc
;
286 kprintf("[BOOT] AROS %s\n", bootstrapName
);
289 kprintf("[BOOT] UART clock speed: %d\n", uartclock
);
290 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint
, uartdivfrac
, uartbaud
);
292 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp
));
293 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr
, tmp
);
295 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp
));
296 kprintf("[BOOT] main id register: %08x\n", tmp
);
302 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start
, &__bootstrap_end
);
304 boottag
->ti_Tag
= KRN_ProtAreaStart
;
305 boottag
->ti_Data
= (IPTR
)&__bootstrap_start
;
308 boottag
->ti_Tag
= KRN_ProtAreaEnd
;
309 boottag
->ti_Data
= (IPTR
)&__bootstrap_end
;
312 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper
);
316 *mem_upper
= *mem_upper
& ~4095;
318 unsigned long kernel_phys
= *mem_upper
;
319 unsigned long kernel_virt
= kernel_phys
;
321 unsigned long total_size_ro
, total_size_rw
;
322 uint32_t size_ro
, size_rw
;
324 /* Calculate total size of kernel and modules */
325 getElfSize(&_binary_core_bin_start
, &size_rw
, &size_ro
);
327 total_size_ro
= size_ro
= (size_ro
+ 4095) & ~4095;
328 total_size_rw
= size_rw
= (size_rw
+ 4095) & ~4095;
330 if (pkg_image
&& pkg_size
)
332 uint8_t *base
= pkg_image
;
334 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
336 getElfSize(base
, &size_rw
, &size_ro
);
338 total_size_ro
+= (size_ro
+ 4095) & ~4095;
339 total_size_rw
+= (size_rw
+ 4095) & ~4095;
341 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
343 uint8_t *file
= base
+4;
344 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
345 const uint8_t *file_end
= base
+total_length
;
346 uint32_t len
, cnt
= 0;
350 while(file
< file_end
)
352 const char *filename
= remove_path(file
+4);
354 /* get text length */
355 len
= AROS_BE2LONG(*(uint32_t*)file
);
359 len
= AROS_BE2LONG(*(uint32_t *)file
);
363 getElfSize(file
, &size_rw
, &size_ro
);
365 total_size_ro
+= (size_ro
+ 4095) & ~4095;
366 total_size_rw
+= (size_rw
+ 4095) & ~4095;
368 /* go to the next file */
375 total_size_ro
= (total_size_ro
+ 1024*1024-1) & 0xfff00000;
376 total_size_rw
= (total_size_rw
+ 1024*1024-1) & 0xfff00000;
378 kernel_phys
= *mem_upper
- total_size_ro
- total_size_rw
;
379 kernel_virt
= 0xf8000000;
381 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys
);
382 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt
);
384 *mem_upper
= kernel_phys
;
386 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper
));
388 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
389 mmu_unmap_section(kernel_phys
, total_size_ro
+ total_size_rw
);
391 /* map kernel memory for user access */
392 mmu_map_section(kernel_phys
, kernel_virt
, total_size_ro
, 1, 1, 2, 1);
393 mmu_map_section(kernel_phys
+ total_size_ro
, kernel_virt
+ total_size_ro
, total_size_rw
, 1, 1, 3, 1);
395 entry
= (void (*)(struct TagItem
))kernel_virt
;
397 initAllocator(kernel_phys
, kernel_phys
+ total_size_ro
, kernel_virt
- kernel_phys
);
399 boottag
->ti_Tag
= KRN_KernelLowest
;
400 boottag
->ti_Data
= kernel_virt
;
403 boottag
->ti_Tag
= KRN_KernelHighest
;
404 boottag
->ti_Data
= kernel_virt
+ ((total_size_ro
+ 4095) & ~4095) + ((total_size_rw
+ 4095) & ~4095);
407 boottag
->ti_Tag
= KRN_KernelPhysLowest
;
408 boottag
->ti_Data
= kernel_phys
;
411 loadElf(&_binary_core_bin_start
);
413 if (pkg_image
&& pkg_size
)
415 uint8_t *base
= pkg_image
;
417 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
419 kprintf("[BOOT] Kernel image is ELF file\n");
421 getElfSize(base
, &size_rw
, &size_ro
);
423 total_size_ro
+= (size_ro
+ 4095) & ~4095;
424 total_size_rw
+= (size_rw
+ 4095) & ~4095;
426 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
428 kprintf("[BOOT] Kernel image is a package:\n");
430 uint8_t *file
= base
+4;
431 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
432 const uint8_t *file_end
= base
+total_length
;
433 uint32_t len
, cnt
= 0;
435 kprintf("[BOOT] Package size: %dKB", total_length
>> 10);
439 while(file
< file_end
)
441 const char *filename
= remove_path(file
+4);
443 /* get text length */
444 len
= AROS_BE2LONG(*(uint32_t*)file
);
445 /* display the file name */
447 kprintf("\n[BOOT] %s", filename
);
449 kprintf(", %s", filename
);
453 len
= AROS_BE2LONG(*(uint32_t *)file
);
459 total_size_ro
+= (size_ro
+ 4095) & ~4095;
460 total_size_rw
+= (size_rw
+ 4095) & ~4095;
462 /* go to the next file */
470 arm_flush_cache(kernel_phys
, total_size_ro
+ total_size_rw
);
472 boottag
->ti_Tag
= KRN_KernelBss
;
473 boottag
->ti_Data
= (IPTR
)tracker
;
477 boottag
->ti_Tag
= TAG_DONE
;
478 boottag
->ti_Data
= 0;
480 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
));
481 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
485 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry
);
487 entry((struct TagItem
*)(tmp_stack_ptr
- BOOT_STACK_SIZE
- BOOT_TAGS_SIZE
));
489 kprintf("[BOOT] Back? Something wrong happened...\n");