2 Copyright © 2013-2019, The AROS Development Team. All rights reserved.
9 #include <exec/types.h>
10 #include <aros/macros.h>
13 #include <utility/tagitem.h>
14 #include <aros/macros.h>
15 #include <aros/kernel.h>
20 #include <hardware/bcm2708.h>
21 #include <hardware/bcm2708_boot.h>
22 #include <hardware/videocore.h>
25 #include "serialdebug.h"
31 #include "devicetree.h"
37 #define ARM_PERIIOBASE (__arm_periiobase)
39 uint32_t __arm_periiobase
= 0;
41 extern void mem_init(void);
42 extern unsigned int uartclock
;
43 extern unsigned int uartdivint
;
44 extern unsigned int uartdivfrac
;
45 extern unsigned int uartbaud
;
47 asm(" .section .aros.startup \n"
48 " .globl bootstrap \n"
49 " .type bootstrap,%function \n"
51 " mrs r4, cpsr_all \n" /* Check if in hypervisor mode */
52 " and r4, r4, #0x1f \n"
57 " cps #0x13 \n" /* Should be in SVC (supervisor) mode already, but just incase.. */
59 " setend be \n" /* Switch to big endian mode */
61 " ldr sp, tmp_stack_ptr \n"
62 " mrc p15,0,r4,c1,c0,2 \n" /* Enable signle and double VFP coprocessors */
63 " orr r4, r4, #0x00f00000 \n" /* This is necessary since gcc might want to use vfp registers */
64 " mcr p15,0,r4,c1,c0,2 \n" /* Either as cache for general purpose regs or e.g. for division. This is the case with gcc9 */
65 " mov r4,#0x40000000 \n"
66 " fmxr fpexc,r4 \n" /* Enable VFP now */
72 " adr r4, continue_boot \n"
73 " .byte 0x04,0xf3,0x2e,0xe1 \n" /* msr ELR_hyp, r4 */
74 " mrs r4, cpsr_all \n"
75 " and r4, r4, #0x1f \n"
76 " orr r4, r4, #0x13 \n"
77 " .byte 0x04,0xf3,0x6e,0xe1 \n" /* msr SPSR_hyp, r4 */
78 " .byte 0x6e,0x00,0x60,0xe1 \n" /* eret */
82 ".string \"$VER: arosraspi-be.img v40.46 (" __DATE__
")\"\n"
84 ".string \"$VER: arosraspi.img v40.46 (" __DATE__
")\"\n"
90 // The bootstrap tmp stack is re-used by the reset handler so we store it at this fixed location
91 static __used
void * tmp_stack_ptr
__attribute__((used
, section(".aros.startup"))) = (void *)(0x1000 - 16);
92 static struct TagItem
*boottag
;
93 static unsigned long *mem_upper
;
94 static void *pkg_image
= NULL
;
95 static uint32_t pkg_size
= 0;
100 static const char bootstrapName
[] = "Bootstrap/ARM v7-a BigEndian";
102 static const char bootstrapName
[] = "Bootstrap/ARM v7-a LittleEndian";
107 volatile unsigned int *vc_msg
= (unsigned int *) BOOTMEMADDR(bm_mboxmsg
);
109 kprintf("[BOOT] Query VC memory\n");
110 vc_msg
[0] = AROS_LONG2LE(8 * 4);
111 vc_msg
[1] = AROS_LONG2LE(VCTAG_REQ
);
112 vc_msg
[2] = AROS_LONG2LE(VCTAG_GETVCRAM
);
113 vc_msg
[3] = AROS_LONG2LE(8);
119 vcmb_write(VCMB_BASE
, VCMB_PROPCHAN
, (void *)vc_msg
);
120 vc_msg
= vcmb_read(VCMB_BASE
, VCMB_PROPCHAN
);
122 kprintf("[BOOT] Base = %08x, Size = %08x\n", AROS_LE2LONG(vc_msg
[5]), AROS_LE2LONG(vc_msg
[6]));
124 boottag
->ti_Tag
= KRN_VMEMLower
;
125 boottag
->ti_Data
= AROS_LE2LONG(vc_msg
[5]);
128 boottag
->ti_Tag
= KRN_VMEMUpper
;
129 boottag
->ti_Data
= AROS_LE2LONG(vc_msg
[5]) + AROS_LE2LONG(vc_msg
[6]);
132 mmu_map_section(AROS_LE2LONG(vc_msg
[5]), AROS_LE2LONG(vc_msg
[5]), AROS_LE2LONG(vc_msg
[6]), 1, 0, 3, 0);
137 of_node_t
*mem
= dt_find_node("/memory");
139 kprintf("[BOOT] Query system memory\n");
142 of_property_t
*p
= dt_find_property(mem
, "reg");
144 if (p
!= NULL
&& p
->op_length
)
146 uint32_t *addr
= p
->op_value
;
147 uint32_t lower
= AROS_BE2LONG(*addr
++);
148 uint32_t upper
= AROS_BE2LONG(*addr
++);
150 kprintf("[BOOT] System memory range: %08x-%08x\n", lower
, upper
-1);
152 if (((upper
- lower
) >> 20) < 256) {
153 kprintf("[BOOT] MISMATCHED FILES: start.elf and fixup.dat do not fit to each other!\n");
154 while(1) asm volatile("wfi");
157 boottag
->ti_Tag
= KRN_MEMLower
;
158 if ((boottag
->ti_Data
= lower
) < sizeof(struct bcm2708bootmem
))
159 boottag
->ti_Data
= sizeof(struct bcm2708bootmem
); // Skip the *reserved* space for the cpu vectors/boot tmp stack/kernel private data.
162 boottag
->ti_Tag
= KRN_MEMUpper
;
163 boottag
->ti_Data
= upper
;
165 mem_upper
= &boottag
->ti_Data
;
169 mmu_map_section(lower
, lower
, upper
- lower
, 1, 1, 3, 1);
174 void boot(uintptr_t dummy
, uintptr_t arch
, struct tag
* atags
, uintptr_t a
)
176 uint32_t tmp
, initcr
;
177 void (*entry
)(struct TagItem
*);
179 boottag
= tmp_stack_ptr
- BOOT_STACK_SIZE
- BOOT_TAGS_SIZE
;
182 * Disable MMU, enable caches and branch prediction. Also enabled unaligned memory
183 * access. Exceptions are set to run in big-endian mode and this is the mode
184 * in which page tables are written.
186 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(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 */
192 tmp
|= (1 << 25); /* EE bit for exceptions set - big endian */
193 /* This bit sets also endianess of page tables */
195 asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r"(tmp
));
197 /* Prepare MMU tables but do not load them yet */
200 /* Initialize simplistic local memory allocator */
203 int dt_mem_usage
= mem_avail();
204 /* Parse device tree */
206 dt_mem_usage
-= mem_avail();
208 /* Prepare mapping for peripherals. Use the data from device tree here */
209 of_node_t
*e
= dt_find_node("/soc");
212 of_property_t
*p
= dt_find_property(e
, "ranges");
213 uint32_t *ranges
= p
->op_value
;
214 int32_t len
= p
->op_length
;
218 uint32_t addr_bus
, addr_cpu
;
221 addr_bus
= AROS_BE2LONG(*ranges
++);
222 addr_cpu
= AROS_BE2LONG(*ranges
++);
223 addr_len
= AROS_BE2LONG(*ranges
++);
227 /* If periiobase was not set yet, do it now */
228 if (__arm_periiobase
== 0) {
229 __arm_periiobase
= (uint32_t)addr_cpu
;
232 /* Prepare mapping - device type */
233 mmu_map_section(addr_cpu
, addr_cpu
, addr_len
, 1, 0, 3, 0);
239 while(1) asm volatile("wfe");
244 kprintf("\n\n[BOOT] Big-Endian AROS %s\n", bootstrapName
);
246 kprintf("\n\n[BOOT] Little-Endian AROS %s\n", bootstrapName
);
248 kprintf("[BOOT] Booted on %s\n", dt_find_property(dt_find_node("/"), "model")->op_value
);
250 /* first of all, store the arch for the kernel to use .. */
251 boottag
->ti_Tag
= KRN_Platform
;
252 boottag
->ti_Data
= (IPTR
)arch
;
256 Check if device tree contains /soc/local_intc entry. In this case assume RasPi 2 or 3 with smp setup.
257 Neither PiZero nor classic Pi provide this entry.
259 e
= dt_find_node("/__symbols__");
262 of_property_t
*p
= dt_find_property(e
, "local_intc");
266 kprintf("[BOOT] local_intc points to %s\n", p
->op_value
);
268 e
= dt_find_node(p
->op_value
);
269 p
= dt_find_property(e
, "reg");
270 uint32_t *reg
= p
->op_value
;
272 kprintf("[BOOT] Mapping local interrupt area at %p-%p\n", AROS_BE2LONG(reg
[0]), AROS_BE2LONG(reg
[0]) + AROS_BE2LONG(reg
[1]) - 1);
274 /* Prepare mapping - device type */
275 mmu_map_section(AROS_BE2LONG(reg
[0]), AROS_BE2LONG(reg
[0]), AROS_BE2LONG(reg
[1]) < 0x100000 ? 0x100000 : AROS_BE2LONG(reg
[1]), 0, 0, 3, 0);
281 e
= dt_find_node("/leds");
285 kprintf("[BOOT] Configuring LEDs\n");
286 ForeachNode(&e
->on_children
, led
)
288 of_property_t
*p
= dt_find_property(led
, "gpios");
290 if (p
&& p
->op_length
>= 8) {
291 uint32_t *data
= p
->op_value
;
292 uint32_t phandle
= AROS_BE2LONG(data
[0]);
293 gpio
= AROS_BE2LONG(data
[1]);
294 of_node_t
*bus
= dt_find_node_by_phandle(phandle
);
296 kprintf("[BOOT] %s: GPIO%d (%08x %08x %08x)\n", led
->on_name
, gpio
,
297 AROS_BE2LONG(data
[0]), AROS_BE2LONG(data
[1]), AROS_BE2LONG(data
[2]));
300 kprintf("[BOOT] LED attached to %s\n", bus
->on_name
);
302 if (strncmp(bus
->on_name
, "gpio", 4) == 0)
304 int gpio_sel
= gpio
/ 10;
305 int gpio_soff
= 3 * (gpio
- 10 * gpio_sel
);
307 kprintf("[BOOT] GPFSEL=%x, bit=%d\n", gpio_sel
* 4, gpio_soff
);
309 /* Configure GPIO as output */
310 tmp
= rd32le(GPFSEL0
+ 4*gpio_sel
);
311 tmp
&= ~(7 << gpio_soff
); // GPIO 47 = 001 - output
312 tmp
|= (1 << gpio_soff
);
313 wr32le(GPFSEL0
+ 4*gpio_sel
, tmp
);
316 wr32le(GPCLR0
+ 4 * (gpio
/ 32), 1 << (gpio
% 32));
323 kprintf("[BOOT] DT memory usage: %d\n", dt_mem_usage
);
325 boottag
->ti_Tag
= KRN_BootLoader
;
326 boottag
->ti_Data
= (IPTR
)bootstrapName
;
331 boottag
->ti_Tag
= KRN_FuncPutC
;
332 boottag
->ti_Data
= (IPTR
)fb_Putc
;
337 kprintf("[BOOT] UART clock speed: %d\n", uartclock
);
338 kprintf("[BOOT] using %d.%d divisor for %d baud\n", uartdivint
, uartdivfrac
, uartbaud
);
340 asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(tmp
));
341 kprintf("[BOOT] control register init:%08x, now:%08x\n", initcr
, tmp
);
343 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(tmp
));
344 kprintf("[BOOT] main id register: %08x\n", tmp
);
350 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start
, &__bootstrap_end
);
352 boottag
->ti_Tag
= KRN_ProtAreaStart
;
353 boottag
->ti_Data
= (IPTR
)&__bootstrap_start
;
356 boottag
->ti_Tag
= KRN_ProtAreaEnd
;
357 boottag
->ti_Data
= (IPTR
)&__bootstrap_end
;
360 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper
);
362 e
= dt_find_node("/chosen");
365 of_property_t
*p
= dt_find_property(e
, "linux,initrd-start");
367 pkg_image
= (void*)AROS_BE2LONG((*((uint32_t *)p
->op_value
)));
371 p
= dt_find_property(e
, "linux,initrd-end");
373 pkg_size
= AROS_BE2LONG(*((uint32_t *)p
->op_value
)) - (uint32_t)pkg_image
;
378 kprintf("[BOOT] BSP image: %08x-%08x\n", pkg_image
, (int32_t)pkg_image
+ pkg_size
- 1);
380 kprintf("[BOOT] mem_avail=%d\n", mem_avail());
382 unsigned long total_size_ro
= 0, total_size_rw
= 0;
387 *mem_upper
= *mem_upper
& ~4095;
389 unsigned long kernel_phys
= *mem_upper
;
390 unsigned long kernel_virt
= kernel_phys
;
392 uint32_t size_ro
, size_rw
;
394 /* Calculate total size of kernel and modules */
395 getElfSize(&_binary_core_bin_start
, &size_rw
, &size_ro
);
397 total_size_ro
= size_ro
= (size_ro
+ 4095) & ~4095;
398 total_size_rw
= size_rw
= (size_rw
+ 4095) & ~4095;
400 if (pkg_image
&& pkg_size
)
402 uint8_t *base
= pkg_image
;
404 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
406 getElfSize(base
, &size_rw
, &size_ro
);
408 total_size_ro
+= (size_ro
+ 4095) & ~4095;
409 total_size_rw
+= (size_rw
+ 4095) & ~4095;
411 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
413 uint8_t *file
= base
+4;
414 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
415 const uint8_t *file_end
= base
+total_length
;
416 uint32_t len
, cnt
= 0;
420 while(file
< file_end
)
422 //const char *filename = remove_path(file+4);
424 /* get text length */
425 len
= AROS_BE2LONG(*(uint32_t*)file
);
429 len
= AROS_BE2LONG(*(uint32_t *)file
);
433 getElfSize(file
, &size_rw
, &size_ro
);
435 total_size_ro
+= (size_ro
+ 4095) & ~4095;
436 total_size_rw
+= (size_rw
+ 4095) & ~4095;
438 /* go to the next file */
445 /* Reserve space for flattened device tree */
446 total_size_ro
+= (dt_total_size() + 31) & ~31;
448 /* Reserve space for unpacked device tree */
449 total_size_ro
+= (dt_mem_usage
+ 31) & ~31;
451 /* Align space to 1MB boundary - it will save some space in MMU tables */
452 total_size_ro
= (total_size_ro
+ 1024*1024-1) & 0xfff00000;
453 total_size_rw
= (total_size_rw
+ 1024*1024-1) & 0xfff00000;
455 kernel_phys
= *mem_upper
- total_size_ro
- total_size_rw
;
456 kernel_virt
= KERNEL_VIRT_ADDRESS
;
458 bzero((void*)kernel_phys
, total_size_ro
+ total_size_rw
);
460 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys
);
461 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt
);
463 if (dt_total_size() > 0)
465 long dt_size
= (dt_total_size() + 31) & ~31;
466 /* Copy device tree to the end of kernel RO area */
467 memcpy((void*)(kernel_phys
+ total_size_ro
- dt_size
), atags
, dt_size
);
468 fdt
= (void*)(kernel_virt
+ total_size_ro
- dt_size
);
470 /* Store device tree */
471 boottag
->ti_Tag
= KRN_FlattenedDeviceTree
;
472 boottag
->ti_Data
= (IPTR
)kernel_virt
+ total_size_ro
- dt_size
;
475 kprintf("[BOOT] Device tree (size: %d) moved to %p, phys %p\n", dt_total_size(), boottag
[-1].ti_Data
, kernel_phys
+ total_size_ro
- dt_size
);
478 *mem_upper
= kernel_phys
;
480 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper
));
482 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
483 mmu_unmap_section(kernel_phys
, total_size_ro
+ total_size_rw
);
485 /* map kernel memory for user access */
486 mmu_map_section(kernel_phys
, kernel_virt
, total_size_ro
, 1, 1, 2, 1);
487 mmu_map_section(kernel_phys
+ total_size_ro
, kernel_virt
+ total_size_ro
, total_size_rw
, 1, 1, 3, 1);
489 entry
= (void (*)(struct TagItem
*))kernel_virt
;
491 initAllocator(kernel_phys
, kernel_phys
+ total_size_ro
, kernel_virt
- kernel_phys
);
493 boottag
->ti_Tag
= KRN_KernelLowest
;
494 boottag
->ti_Data
= kernel_virt
;
497 boottag
->ti_Tag
= KRN_KernelHighest
;
498 boottag
->ti_Data
= kernel_virt
+ ((total_size_ro
+ 4095) & ~4095) + ((total_size_rw
+ 4095) & ~4095);
501 boottag
->ti_Tag
= KRN_KernelPhysLowest
;
502 boottag
->ti_Data
= kernel_phys
;
505 loadElf(&_binary_core_bin_start
);
507 if (pkg_image
&& pkg_size
)
509 uint8_t *base
= pkg_image
;
511 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
513 kprintf("[BOOT] Kernel image is ELF file\n");
517 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
519 kprintf("[BOOT] Kernel image is a package:\n");
521 uint8_t *file
= base
+4;
522 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
523 const uint8_t *file_end
= base
+total_length
;
524 uint32_t len
, cnt
= 0;
526 kprintf("[BOOT] Package size: %dKB", total_length
>> 10);
530 while(file
< file_end
)
532 const char *filename
= remove_path(file
+4);
534 /* get text length */
535 len
= AROS_BE2LONG(*(uint32_t*)file
);
536 /* display the file name */
538 kprintf("\n[BOOT] %s", filename
);
540 kprintf(", %s", filename
);
544 len
= AROS_BE2LONG(*(uint32_t *)file
);
550 /* go to the next file */
558 arm_flush_cache(kernel_phys
, total_size_ro
+ total_size_rw
);
560 boottag
->ti_Tag
= KRN_KernelBss
;
561 boottag
->ti_Data
= (IPTR
)tracker
;
567 int memory_used
= mem_used();
569 /* If device tree is in high kernel memory then parse it again */
570 if (dt_total_size() > 0)
572 void * dt_location
= (void *)(KERNEL_VIRT_ADDRESS
+ total_size_ro
- ((dt_total_size() + 31) & ~31) - ((dt_mem_usage
+ 31) & ~31));
573 kprintf("[BOOT] Creating device tree in kernel area at %p\n", dt_location
);
575 explicit_mem_init(dt_location
, (dt_mem_usage
+ 31) & ~31);
578 boottag
->ti_Tag
= KRN_OpenFirmwareTree
;
579 boottag
->ti_Data
= (IPTR
)dt_location
;
582 e
= dt_find_node("/chosen");
585 of_property_t
*p
= dt_find_property(e
, "bootargs");
588 boottag
->ti_Tag
= KRN_CmdLine
;
589 boottag
->ti_Data
= (IPTR
)p
->op_value
;
592 kprintf("[BOOT] Kernel parameters @ %p: %s\n", p
->op_value
, p
->op_value
);
597 boottag
->ti_Tag
= TAG_DONE
;
598 boottag
->ti_Data
= 0;
600 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
));
601 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", memory_used
);
603 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry
);
605 entry((struct TagItem
*)(tmp_stack_ptr
- BOOT_STACK_SIZE
- BOOT_TAGS_SIZE
));
607 kprintf("[BOOT] Back? Something wrong happened...\n");
609 while(1) asm volatile("wfe");