- More sunifigations and hardware definitions
[AROS.git] / arch / arm-sun4i / boot / boot.c
blobdafd6fc7511b6fffb27a75e38b8afee52e77d1d7
1 /*
2 Copyright © 2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <inttypes.h>
10 #include <asm/cpu.h>
11 #include <asm/arm/mmu.h>
12 #include <utility/tagitem.h>
13 #include <aros/macros.h>
14 #include <string.h>
15 #include <stdlib.h>
17 #include "boot.h"
18 #include "atags.h"
19 #include "elf.h"
21 #include <hardware/sun4i/platform.h>
23 asm(" .section .aros.startup \n"
24 " .globl bootstrap \n"
25 " .type bootstrap,%function \n"
26 "bootstrap: \n"
27 " movw r0,#:lower16:tmp_stack_ptr\n"
28 " movt r0,#:upper16:tmp_stack_ptr\n"
29 " ldr sp,[r0,#0] \n"
30 " b boot \n"
33 static __used unsigned char __stack[BOOT_STACK_SIZE];
34 static __used void * tmp_stack_ptr = &__stack[BOOT_STACK_SIZE-16];
36 static struct TagItem tags[128];
37 static struct TagItem *tag = &tags[0];
38 static unsigned long *mem_upper = NULL;
39 static unsigned long *mem_lower = NULL;
40 static void *pkg_image;
41 static uint32_t pkg_size;
43 static void parse_atags(struct tag *tags) {
44 struct tag *t = NULL;
46 kprintf("[BOOT] Parsing ATAGS\n");
48 for_each_tag(t, tags) {
49 kprintf("[BOOT] %08x (%04x): ", t->hdr.tag, t->hdr.size);
51 switch (t->hdr.tag) {
53 case ATAG_MEM: {
54 kprintf("Memory (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
55 tag->ti_Tag = KRN_MEMLower;
56 tag->ti_Data = t->u.mem.start;
57 mem_lower = &tag->ti_Data;
58 tag++;
60 tag->ti_Tag = KRN_MEMUpper;
61 tag->ti_Data = t->u.mem.start + t->u.mem.size;
62 mem_upper = &tag->ti_Data;
63 tag++;
65 break;
67 case ATAG_CMDLINE: {
68 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
69 strcpy(cmdline, t->u.cmdline.cmdline);
70 kprintf("CMDLine: \"%s\"\n", cmdline);
72 tag->ti_Tag = KRN_CmdLine;
73 tag->ti_Data = (intptr_t)cmdline;
74 tag++;
76 break;
78 case ATAG_INITRD2: {
79 kprintf("RAMDISK: (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
80 pkg_image = (void *)t->u.initrd.start;
81 pkg_size = t->u.initrd.size;
83 break;
85 default: {
86 kprintf("IGN...\n");
88 break;
94 void setup_mmu(uintptr_t kernel_phys, uintptr_t kernel_virt, uintptr_t length) {
95 int i;
96 uintptr_t first_1M_page = kernel_virt & 0xfff00000;
97 uintptr_t last_1M_page = ((kernel_virt + length + 0x000fffff) & 0xfff00000) - 1;
99 kprintf("[BOOT] Preparing initial MMU map\n");
101 /* Use memory right below kernel for page dir */
102 pde_t *page_dir = (pde_t *)(((uintptr_t)kernel_phys - 16384) & ~ 16383);
104 kprintf("[BOOT] First level MMU page at %08x\n", page_dir);
106 /* Clear page dir */
107 for (i=0; i < 4096; i++)
108 page_dir[i].raw = 0;
110 /* 1:1 memory mapping */
111 for (i=(*mem_lower >> 20); i < (*mem_upper >> 20); i++) {
112 //page_dir[i].raw = 0;
113 page_dir[i].section.type = PDE_TYPE_SECTION;
114 page_dir[i].section.b = 0;
115 page_dir[i].section.c = 1; /* Cacheable */
116 page_dir[i].section.ap = 3; /* All can read&write */
117 page_dir[i].section.base_address = i;
120 kprintf("[BOOT] Preparing mapping for kernel (%d bytes, pages %08x to %08x)\n", length, first_1M_page, last_1M_page);
122 int fp = first_1M_page >> 20;
123 int lp = last_1M_page >> 20;
125 pte_t *current_pte = (pte_t *)page_dir;
127 if (lp == fp) lp++;
129 for (i = fp; i < lp; i++) {
130 current_pte = (pte_t *)((uintptr_t)current_pte - 1024);
132 page_dir[i].coarse.type = PDE_TYPE_COARSE;
133 page_dir[i].coarse.domain = 0;
134 page_dir[i].coarse.sbz = 0;
135 page_dir[i].coarse.imp = 0;
136 page_dir[i].coarse.base_address = (intptr_t)current_pte >> 10;
138 int j;
139 for (j = 0; j < 256; j++) {
140 uintptr_t synth_addr = (i << 20) + (j << 12);
142 if (synth_addr < kernel_virt) {
143 current_pte[j].raw = 0;
144 } else if (synth_addr < kernel_virt + length) {
145 current_pte[j].raw = 0;
146 current_pte[j].page.base_address = (synth_addr - kernel_virt + kernel_phys) >> 12;
147 current_pte[j].page.b = 0;
148 current_pte[j].page.c = 1;
149 current_pte[j].page.ap = 3;
150 current_pte[j].page.type = PTE_TYPE_PAGE;
151 } else {
152 current_pte[j].raw = 0;
157 /* Write page_dir address to ttbr0 */
158 asm volatile ("mcr p15, 0, %0, c2, c0, 0"::"r"(page_dir));
159 /* Write ttbr control N = 0 (use only ttbr0) */
160 asm volatile ("mcr p15, 0, %0, c2, c0, 2"::"r"(0));
162 *mem_upper = (intptr_t)current_pte;
165 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags) {
166 uint32_t tmp;
167 void (*entry)(struct TagItem *tags) = NULL;
169 kprintf("[BOOT] AROS for sun4i (" SUN4I_PLATFORM_NAME ") bootstrap\n");
171 /* Enable NEON and VFP */
172 asm volatile ("mrc p15, 0, %0, c1, c0, 2":"=r"(tmp));
173 tmp |= 3 << 20;
174 tmp |= 3 << 22;
175 asm volatile ("mcr p15, 0, %0, c1, c0, 2"::"r"(tmp));
177 fmxr(cr8, fmrx(cr8) | 1 << 30);
179 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
180 kprintf("[BOOT] control register %08x\n", tmp);
181 tmp &= ~2; /* Disable MMU and caches */
182 tmp |= 1 << 13; /* Exception vectors at 0xffff0000 */
183 asm volatile ("mcr p15, 0, %0, c1, c0, 0"::"r"(tmp));
185 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
186 kprintf("[BOOT] control register %08x\n", tmp);
188 tag->ti_Tag = KRN_BootLoader;
189 tag->ti_Data = (IPTR)"Bootstrap/sun4i (" SUN4I_PLATFORM_NAME ") ARM";
190 tag++;
192 parse_atags(atags);
194 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
195 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
197 if(*mem_upper){
198 if((*mem_upper &0x0000ffff)==0x0000ffff) {
199 *mem_upper = (*mem_upper & 0xffff0000);
200 }else{
201 *mem_upper = (*mem_upper & 0xffff0000) - 0x10000;
205 kprintf("[BOOT] Topmost address for kernel: %p\n", *mem_upper);
208 if (*mem_upper) {
209 *mem_upper = *mem_upper & ~4095;
211 unsigned long kernel_phys = *mem_upper;
212 unsigned long kernel_virt = kernel_phys;
214 unsigned long total_size_ro, total_size_rw;
215 uint32_t size_ro, size_rw;
217 /* Calculate total size of kernel and modules */
219 getElfSize(&_binary_kernel_bin_start, &size_rw, &size_ro);
221 total_size_ro = size_ro = (size_ro + 4095) & ~4095;
222 total_size_rw = size_rw = (size_rw + 4095) & ~4095;
224 if (pkg_image && pkg_size) {
225 uint8_t *base = pkg_image;
227 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F') {
228 kprintf("[BOOT] Kernel image is ELF file\n");
230 getElfSize(base, &size_rw, &size_ro);
232 total_size_ro += (size_ro + 4095) & ~4095;
233 total_size_rw += (size_rw + 4095) & ~4095;
234 } else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01) {
235 kprintf("[BOOT] Kernel image is a package:\n");
237 uint8_t *file = base+4;
238 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
239 const uint8_t *file_end = base+total_length;
240 uint32_t len;
242 kprintf("[BOOT] Package size: %dKB\n", total_length >> 10);
244 file = base + 8;
246 while(file < file_end) {
247 const char *filename = remove_path(file+4);
249 /* get text length */
250 len = AROS_BE2LONG(*(uint32_t*)file);
251 /* display the file name */
252 kprintf("[BOOT] %s \n", filename);
254 file += len + 5;
256 len = AROS_BE2LONG(*(uint32_t *)file);
257 file += 4;
259 /* load it */
260 getElfSize(file, &size_rw, &size_ro);
262 total_size_ro += (size_ro + 4095) & ~4095;
263 total_size_rw += (size_rw + 4095) & ~4095;
265 /* go to the next file */
266 file += len;
271 kernel_phys = *mem_upper - total_size_ro - total_size_rw;
272 kernel_virt = 0xffff0000 - total_size_ro - total_size_rw;
274 /* Adjust "top of memory" pointer */
275 *mem_upper = kernel_phys;
277 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
278 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
280 entry = (void (*)(struct TagItem *))kernel_virt;
282 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
284 tag->ti_Tag = KRN_KernelLowest;
285 tag->ti_Data = kernel_phys;
286 tag++;
288 tag->ti_Tag = KRN_KernelHighest;
289 tag->ti_Data = kernel_phys + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
290 tag++;
292 loadElf(&_binary_kernel_bin_start);
294 if (pkg_image && pkg_size) {
295 uint8_t *base = pkg_image;
297 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F') {
298 kprintf("[BOOT] Kernel image is ELF file\n");
300 /* load it */
301 loadElf(base);
302 } else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01) {
303 kprintf("[BOOT] Kernel image is a package:\n");
305 uint8_t *file = base+4;
306 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
307 const uint8_t *file_end = base+total_length;
308 uint32_t len;
310 kprintf("[BOOT] Package size: %dKB\n", total_length >> 10);
312 file = base + 8;
314 while(file < file_end) {
315 const char *filename = remove_path(file+4);
317 /* get text length */
318 len = AROS_BE2LONG(*(uint32_t*)file);
319 /* display the file name */
320 kprintf("[BOOT] %s ", filename);
322 file += len + 5;
324 len = AROS_BE2LONG(*(uint32_t *)file);
325 file += 4;
327 /* load it */
328 loadElf(file);
330 /* go to the next file */
331 file += len;
336 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
338 tag->ti_Tag = KRN_KernelBss;
339 tag->ti_Data = (IPTR)tracker;
340 tag++;
342 setup_mmu(kernel_phys, kernel_virt, total_size_ro + total_size_rw);
345 tag->ti_Tag = TAG_DONE;
346 tag->ti_Data = 0;
348 kprintf("[BOOT] Kernel taglist contains %d entries\n", ((intptr_t)tag - (intptr_t)tags)/sizeof(struct TagItem));
349 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
351 if (entry) {
352 /* Set domains - Dom0 is usable, rest is disabled */
353 asm volatile ("mrc p15, 0, %0, c3, c0, 0":"=r"(tmp));
354 kprintf("[BOOT] Domain access control register: %08x\n", tmp);
355 asm volatile ("mcr p15, 0, %0, c3, c0, 0"::"r"(0x00000001));
357 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
358 kprintf("[BOOT] control register %08x\n", tmp);
359 tmp |= 1; /* Enable MMU */
360 asm volatile ("mcr p15, 0, %0, c1, c0, 0"::"r"(tmp));
362 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
363 kprintf("[BOOT] control register %08x\n", tmp);
365 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
367 entry(tags);
369 kprintf("[BOOT] Back? Something wrong happened...\n");
370 } else {
371 kprintf("[BOOT] kernel entry pointer not set?\n");
374 while(1);