2 Copyright © 2014, The AROS Development Team. All rights reserved.
11 #include <asm/arm/mmu.h>
12 #include <asm/arm/cp15.h>
13 #include <utility/tagitem.h>
14 #include <aros/macros.h>
22 #include <hardware/sun4i/platform.h>
24 /* Parse ATAGS to find end of DRAM (align on mebibyte (or megabyte...) boundary) and set stack pointer there. "Push" ATAGS in stack and jump to C */
25 asm(" .section .aros.startup \n"
26 " .globl bootstrap \n"
27 " .type bootstrap,%function \n"
31 " mov r4, #2 \n" /* Size of ATAGS + ATAG_NONE */
36 " mov r3, #0x0002 \n" /* ATAG_MEM */
37 " movt r3, #0x5441 \n"
41 " ldr ip, [r0, #4] \n"
45 " cmp sp, #0 \n" /* Allow only one ATAG_MEM tag, else we get confused */
46 " bne .fancy_error_loop \n"
48 " ldr sp, [r0, #12] \n" /* Initial stackpointer is end of DRAM */
49 " ldr r5, [r0, #8] \n"
50 " add sp, sp, r5 \n" /* Align on last mebibyte (or megabyte...) */
52 " lsl sp, sp, #20 \n" /* sp = 0x8000 0000 on pcDuino (0x4000 0000 - 0x7fff ffff DRAM)*/
57 " add r0, r0, ip, lsl #2 \n"
59 " bne .tag_compare \n"
62 " beq .fancy_error_loop \n"
64 " sub sp, sp, r4, lsl #2 \n" /* "Push" ATAGs in the stack */
67 " ldr r3, [r2], #4 \n"
68 " str r3, [r0], #4 \n"
76 ".fancy_error_loop: \n"
79 void setup_mmu(uint32_t kernel_phys
, uint32_t kernel_virt
, uint32_t mem_lower
, uint32_t mem_upper
) {
83 kprintf("[BOOT] MMU kernel_phys %08x\n", kernel_phys
);
84 kprintf("[BOOT] MMU kernel_virt %08x\n", kernel_virt
);
85 kprintf("[BOOT] MMU mem_lower %08x\n", mem_lower
);
86 kprintf("[BOOT] MMU mem_upper %08x\n", mem_upper
-1);
88 /* We know the virtual address but not the physical */
89 pde_t
*page_dir
= 0xfffec000-(kernel_virt
-kernel_phys
);
90 kprintf("[BOOT] First level MMU page at %08x\n", page_dir
);
93 for (i
=0; i
< 4096; i
++) {
98 for (i
=(mem_lower
>> 20); i
< (mem_upper
>> 20); i
++) {
99 //kprintf("[BOOT] Memory mapping page %d\n", i);
100 //page_dir[i].raw = 0;
101 page_dir
[i
].section
.type
= PDE_TYPE_SECTION
;
102 page_dir
[i
].section
.b
= 0;
103 page_dir
[i
].section
.c
= 1; // Cacheable
104 page_dir
[i
].section
.ap
= 3; // All can read&write
105 page_dir
[i
].section
.base_address
= i
;
108 // v:p memory mapping
109 for (i
=(kernel_virt
>> 20); i
<= (0xffffffff >> 20); i
++) {
110 kprintf("[BOOT] Kernel mapping page %d phys %08x -> virt %08x\n", i
, (kernel_phys
)+((i
<< 20)-(kernel_virt
)), i
<< 20);
111 //page_dir[i].raw = 0;
112 page_dir
[i
].section
.type
= PDE_TYPE_SECTION
;
113 page_dir
[i
].section
.b
= 0;
114 page_dir
[i
].section
.c
= 1; // Cacheable
115 page_dir
[i
].section
.ap
= 3; // All can read&write
116 page_dir
[i
].section
.base_address
= (kernel_phys
>> 20)+(i
-(kernel_virt
>> 20));
119 /* Write page_dir address to ttbr0 */
120 asm volatile ("mcr p15, 0, %0, c2, c0, 0"::"r"(page_dir
));
121 /* Write ttbr control N = 0 (use only ttbr0) */
122 asm volatile ("mcr p15, 0, %0, c2, c0, 2"::"r"(0));
126 void boot(uintptr_t dummy
, uintptr_t arch
, struct tag
*atags
) {
128 struct tag
*t
= NULL
;
129 struct TagItem tags
[128];
130 struct TagItem
*tag
= &tags
[0];
132 uint32_t mem_upper
= 0;
133 uint32_t mem_lower
= 0;
134 uint32_t kernel_phys
= 0;
135 uint32_t kernel_virt
= 0;
142 /* Disable MMU, level one data cache and strict alignment fault checking */
143 CP15_C1CR_Clear(C1CRF_C
|C1CRF_A
|C1CRF_M
);
145 /* High exception vectors selected, address range = 0xFFFF0000-0xFFFF001C */
146 CP15_C1CR_Set(C1CRF_V
);
148 /* Set cp10 and cp11 for Privileged and User mode access */
149 CP15_C1CACR_All(C1CACRV_CPAP(10)|C1CACRV_CPAP(11));
151 /* Enable VFP (NEON in our case) */
152 fmxr(cr8
, fmrx(cr8
) | 1 << 30);
154 void (*entry
)(struct TagItem
*tags
) = NULL
;
156 kprintf("[BOOT] AROS for sun4i (" SUN4I_PLATFORM_NAME
") bootstrap\n");
157 asm volatile ("mov %0, sp":"=r"(tmp
));
158 kprintf("[BOOT] Stack @ %08x\n", tmp
);
160 tag
->ti_Tag
= KRN_BootLoader
;
161 tag
->ti_Data
= (IPTR
)"Bootstrap/sun4i (" SUN4I_PLATFORM_NAME
") ARM";
164 kprintf("[BOOT] Parsing ATAGS %x\n", tags
);
166 for_each_tag(t
, atags
) {
167 kprintf("[BOOT] (%x-%x) tag %08x (%d): ", t
, (uint32_t)t
+(t
->hdr
.size
<<2)-1, t
->hdr
.tag
, t
->hdr
.size
);
169 switch (t
->hdr
.tag
) {
172 mem_lower
= t
->u
.mem
.start
;
173 mem_upper
= t
->u
.mem
.start
+t
->u
.mem
.size
;
174 kprintf("Memory (%08x-%08x)\n", mem_lower
, mem_upper
-1);
179 kprintf("CMDLine: \"%s\"\n", t
->u
.cmdline
.cmdline
);
180 tag
->ti_Tag
= KRN_CmdLine
;
181 tag
->ti_Data
= (intptr_t)t
->u
.cmdline
.cmdline
;
187 kprintf("RAMDISK: (%08x-%08x)\n", t
->u
.initrd
.start
, t
->u
.initrd
.size
+ t
->u
.initrd
.start
- 1);
188 pkg_image
= (void *)t
->u
.initrd
.start
;
189 pkg_size
= t
->u
.initrd
.size
;
201 if(t
->hdr
.size
== 0) {
202 kprintf("[BOOT] (%x-%x) tag %08x (%d): ATAG_NONE\n", t
, (uint32_t)t
+(2<<2)-1, t
->hdr
.tag
, 2);
205 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start
, &__bootstrap_end
);
209 mem_upper
-= MEM_OFFSET_VECTOR
; /* Preserve DRAM for vectors (virtual 0xffff 0000 - 0xffff 003f) */
210 kprintf("[BOOT] Vectors @%p\n", mem_upper
);
212 mem_upper
-= MEM_OFFSET_MMU1
; /* Preserve DRAM for top level mmu table (MMU1) 16kb boundary and size */
213 kprintf("[BOOT] MMU1 @%p\n", mem_upper
);
215 kernel_phys
= mem_upper
;
216 kernel_virt
= kernel_phys
;
218 uint32_t total_size_ro
;
219 uint32_t total_size_rw
;
223 /* Calculate total size of kernel and modules */
225 getElfSize(&_binary_kernel_bin_start
, &size_rw
, &size_ro
);
227 total_size_ro
= size_ro
= (size_ro
+ 4095) & ~4095;
228 total_size_rw
= size_rw
= (size_rw
+ 4095) & ~4095;
230 if (pkg_image
&& pkg_size
) {
231 uint8_t *base
= pkg_image
;
233 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F') {
234 kprintf("[BOOT] Kernel image is ELF file\n");
236 getElfSize(base
, &size_rw
, &size_ro
);
238 total_size_ro
+= (size_ro
+ 4095) & ~4095;
239 total_size_rw
+= (size_rw
+ 4095) & ~4095;
240 } else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01) {
241 kprintf("[BOOT] Kernel image is a package:\n");
243 uint8_t *file
= base
+4;
244 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
245 const uint8_t *file_end
= base
+total_length
;
248 kprintf("[BOOT] Package size: %dKB\n", total_length
>> 10);
252 while(file
< file_end
) {
253 const char *filename
= remove_path(file
+4);
255 /* get text length */
256 len
= AROS_BE2LONG(*(uint32_t*)file
);
257 /* display the file name */
258 kprintf("[BOOT] %s \n", filename
);
262 len
= AROS_BE2LONG(*(uint32_t *)file
);
266 getElfSize(file
, &size_rw
, &size_ro
);
268 total_size_ro
+= (size_ro
+ 4095) & ~4095;
269 total_size_rw
+= (size_rw
+ 4095) & ~4095;
271 /* go to the next file */
278 On asm bootstrap we aligned top of memory to 1Mb and set the stack pointer there and "pushed" ATAGS in stack
279 We then substracted vector space and mmu1
281 ffff ffff (Serial debug port base,) ATAGS and stack
283 ffff 003c routine address FIQ
284 ffff 0038 routine address IRQ
285 ffff 0034 routine address Reserved
286 ffff 0030 routine address Data Abort
287 ffff 002c routine address Prefetch Abort
288 ffff 0028 routine address Software interrupt
289 ffff 0024 routine address Undefined instruction
290 ffff 0020 routine address Reset
295 ffff 000c Prefetch Abort
296 ffff 0008 Software interrupt
297 ffff 0004 Undefined instruction
300 fffa ffff End of kernel
306 kernel_phys
= mem_upper
- total_size_ro
- total_size_rw
;
307 kernel_virt
= (kernel_phys
| 0xfff00000);
309 /* Adjust top of memory to last mebibyte (or megabyte...)*/
310 mem_upper
= AROS_ROUNDDOWN2(kernel_phys
, 1024*1024-1);
312 tag
->ti_Tag
= KRN_MEMLower
;
313 tag
->ti_Data
= mem_lower
;
316 tag
->ti_Tag
= KRN_MEMUpper
;
317 tag
->ti_Data
= mem_upper
;
320 tag
->ti_Tag
= KRN_KernelLowest
;
321 tag
->ti_Data
= kernel_virt
;
324 tag
->ti_Tag
= KRN_KernelHighest
;
325 tag
->ti_Data
= kernel_virt
+ ((total_size_ro
+ 4095) & ~4095) + ((total_size_rw
+ 4095) & ~4095); // 0xfffe c000
328 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys
);
329 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt
);
331 entry
= (void (*)(struct TagItem
*))kernel_virt
;
333 initAllocator(kernel_phys
, kernel_phys
+ total_size_ro
, kernel_virt
- kernel_phys
);
335 loadElf(&_binary_kernel_bin_start
);
337 if (pkg_image
&& pkg_size
) {
338 uint8_t *base
= pkg_image
;
340 if (base
[0] == 0x7f && base
[1] == 'E' && base
[2] == 'L' && base
[3] == 'F') {
341 kprintf("[BOOT] Kernel image is ELF file\n");
345 } else if (base
[0] == 'P' && base
[1] == 'K' && base
[2] == 'G' && base
[3] == 0x01) {
346 kprintf("[BOOT] Kernel image is a package:\n");
348 uint8_t *file
= base
+4;
349 uint32_t total_length
= AROS_BE2LONG(*(uint32_t*)file
); /* Total length of the module */
350 const uint8_t *file_end
= base
+total_length
;
353 kprintf("[BOOT] Package size: %dKB\n", total_length
>> 10);
357 while(file
< file_end
) {
358 const char *filename
= remove_path(file
+4);
360 /* get text length */
361 len
= AROS_BE2LONG(*(uint32_t*)file
);
362 /* display the file name */
363 kprintf("[BOOT] %s ", filename
);
367 len
= AROS_BE2LONG(*(uint32_t *)file
);
373 /* go to the next file */
379 arm_flush_cache(kernel_phys
, total_size_ro
+ total_size_rw
);
381 tag
->ti_Tag
= KRN_KernelBss
;
382 tag
->ti_Data
= (IPTR
)tracker
;
385 setup_mmu(kernel_phys
, kernel_virt
, mem_lower
, mem_upper
);
388 tag
->ti_Tag
= TAG_DONE
;
391 kprintf("[BOOT] Kernel taglist contains %d entries\n", ((intptr_t)tag
- (intptr_t)tags
)/sizeof(struct TagItem
));
392 kprintf("[BOOT] mem_upper: %p\n", mem_upper
);
395 /* Set domains - Dom0 is usable, rest is disabled */
396 asm volatile ("mrc p15, 0, %0, c3, c0, 0":"=r"(tmp
));
397 kprintf("[BOOT] Domain access control register: %08x\n", tmp
);
398 asm volatile ("mcr p15, 0, %0, c3, c0, 0"::"r"(0x00000001));
401 CP15_C1CR_Set(C1CRF_M
);
403 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry
);
407 kprintf("[BOOT] Back? Something wrong happened...\n");
409 kprintf("[BOOT] kernel entry pointer not set?\n");