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 */
396 getElfSize(&_binary_core_be_bin_start
, &size_rw
, &size_ro
);
398 getElfSize(&_binary_core_bin_start
, &size_rw
, &size_ro
);
400 total_size_ro
= size_ro
= (size_ro
+ 4095) & ~4095;
401 total_size_rw
= size_rw
= (size_rw
+ 4095) & ~4095;
403 if (pkg_image
&& pkg_size
)
405 uint8_t *base
= pkg_image
;
407 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
409 getElfSize(base
, &size_rw
, &size_ro
);
411 total_size_ro
+= (size_ro
+ 4095) & ~4095;
412 total_size_rw
+= (size_rw
+ 4095) & ~4095;
414 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
416 uint8_t *file
= base
+4;
417 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
418 const uint8_t *file_end
= base
+total_length
;
419 uint32_t len
, cnt
= 0;
423 while(file
< file_end
)
425 //const char *filename = remove_path(file+4);
427 /* get text length */
428 len
= AROS_BE2LONG(*(uint32_t*)file
);
432 len
= AROS_BE2LONG(*(uint32_t *)file
);
436 getElfSize(file
, &size_rw
, &size_ro
);
438 total_size_ro
+= (size_ro
+ 4095) & ~4095;
439 total_size_rw
+= (size_rw
+ 4095) & ~4095;
441 /* go to the next file */
448 /* Reserve space for flattened device tree */
449 total_size_ro
+= (dt_total_size() + 31) & ~31;
451 /* Reserve space for unpacked device tree */
452 total_size_ro
+= (dt_mem_usage
+ 31) & ~31;
454 /* Align space to 1MB boundary - it will save some space in MMU tables */
455 total_size_ro
= (total_size_ro
+ 1024*1024-1) & 0xfff00000;
456 total_size_rw
= (total_size_rw
+ 1024*1024-1) & 0xfff00000;
458 kernel_phys
= *mem_upper
- total_size_ro
- total_size_rw
;
459 kernel_virt
= KERNEL_VIRT_ADDRESS
;
461 bzero((void*)kernel_phys
, total_size_ro
+ total_size_rw
);
463 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys
);
464 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt
);
466 if (dt_total_size() > 0)
468 long dt_size
= (dt_total_size() + 31) & ~31;
469 /* Copy device tree to the end of kernel RO area */
470 memcpy((void*)(kernel_phys
+ total_size_ro
- dt_size
), atags
, dt_size
);
471 fdt
= (void*)(kernel_virt
+ total_size_ro
- dt_size
);
473 /* Store device tree */
474 boottag
->ti_Tag
= KRN_FlattenedDeviceTree
;
475 boottag
->ti_Data
= (IPTR
)kernel_virt
+ total_size_ro
- dt_size
;
478 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
);
481 *mem_upper
= kernel_phys
;
483 DBOOT(kprintf("[BOOT] Topmost memory address: %p\n", *mem_upper
));
485 /* Unmap memory at physical location of kernel. In future this has to be eventually changed */
486 mmu_unmap_section(kernel_phys
, total_size_ro
+ total_size_rw
);
488 /* map kernel memory for user access */
489 mmu_map_section(kernel_phys
, kernel_virt
, total_size_ro
, 1, 1, 2, 1);
490 mmu_map_section(kernel_phys
+ total_size_ro
, kernel_virt
+ total_size_ro
, total_size_rw
, 1, 1, 3, 1);
492 entry
= (void (*)(struct TagItem
*))kernel_virt
;
494 initAllocator(kernel_phys
, kernel_phys
+ total_size_ro
, kernel_virt
- kernel_phys
);
496 boottag
->ti_Tag
= KRN_KernelLowest
;
497 boottag
->ti_Data
= kernel_virt
;
500 boottag
->ti_Tag
= KRN_KernelHighest
;
501 boottag
->ti_Data
= kernel_virt
+ ((total_size_ro
+ 4095) & ~4095) + ((total_size_rw
+ 4095) & ~4095);
504 boottag
->ti_Tag
= KRN_KernelPhysLowest
;
505 boottag
->ti_Data
= kernel_phys
;
509 loadElf(&_binary_core_be_bin_start
);
511 loadElf(&_binary_core_bin_start
);
514 if (pkg_image
&& pkg_size
)
516 uint8_t *base
= pkg_image
;
518 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F')
520 kprintf("[BOOT] Kernel image is ELF file\n");
524 else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01)
526 kprintf("[BOOT] Kernel image is a package:\n");
528 uint8_t *file
= base
+4;
529 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
530 const uint8_t *file_end
= base
+total_length
;
531 uint32_t len
, cnt
= 0;
533 kprintf("[BOOT] Package size: %dKB", total_length
>> 10);
537 while(file
< file_end
)
539 const char *filename
= remove_path(file
+4);
541 /* get text length */
542 len
= AROS_BE2LONG(*(uint32_t*)file
);
543 /* display the file name */
545 kprintf("\n[BOOT] %s", filename
);
547 kprintf(", %s", filename
);
551 len
= AROS_BE2LONG(*(uint32_t *)file
);
557 /* go to the next file */
565 arm_flush_cache(kernel_phys
, total_size_ro
+ total_size_rw
);
567 boottag
->ti_Tag
= KRN_KernelBss
;
568 boottag
->ti_Data
= (IPTR
)tracker
;
574 int memory_used
= mem_used();
576 /* If device tree is in high kernel memory then parse it again */
577 if (dt_total_size() > 0)
579 void * dt_location
= (void *)(KERNEL_VIRT_ADDRESS
+ total_size_ro
- ((dt_total_size() + 31) & ~31) - ((dt_mem_usage
+ 31) & ~31));
580 kprintf("[BOOT] Creating device tree in kernel area at %p\n", dt_location
);
582 explicit_mem_init(dt_location
, (dt_mem_usage
+ 31) & ~31);
585 boottag
->ti_Tag
= KRN_OpenFirmwareTree
;
586 boottag
->ti_Data
= (IPTR
)dt_location
;
589 e
= dt_find_node("/chosen");
592 of_property_t
*p
= dt_find_property(e
, "bootargs");
595 boottag
->ti_Tag
= KRN_CmdLine
;
596 boottag
->ti_Data
= (IPTR
)p
->op_value
;
599 kprintf("[BOOT] Kernel parameters @ %p: %s\n", p
->op_value
, p
->op_value
);
604 boottag
->ti_Tag
= TAG_DONE
;
605 boottag
->ti_Data
= 0;
607 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
));
608 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", memory_used
);
610 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry
);
612 entry((struct TagItem
*)(tmp_stack_ptr
- BOOT_STACK_SIZE
- BOOT_TAGS_SIZE
));
614 kprintf("[BOOT] Back? Something wrong happened...\n");
616 while(1) asm volatile("wfe");