be less verbose
[AROS.git] / arch / arm-efika / boot / boot.c
blobf3290db23e28fde8b41f08b9f90db86dade7f0d9
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: boot.c
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 "serialdebug.h"
19 #include "atags.h"
20 #include "elf.h"
22 asm(" .section .aros.startup \n"
23 " .globl bootstrap \n"
24 " .type bootstrap,%function \n"
25 "bootstrap: \n"
26 " movw r0,#:lower16:tmp_stack_ptr\n"
27 " movt r0,#:upper16:tmp_stack_ptr\n"
28 " ldr sp,[r0,#0] \n"
29 " b boot \n"
32 static __used unsigned char __stack[BOOT_STACK_SIZE];
33 static __used void * tmp_stack_ptr = &__stack[BOOT_STACK_SIZE-16];
35 static struct TagItem tags[128];
36 static struct TagItem *tag = &tags[0];
37 static unsigned long mem_upper;
38 static unsigned long mem_lower;
39 static void *pkg_image;
40 static uint32_t pkg_size;
42 #define MAX_PAGE_TABLES 10
44 static pde_t page_dir[4096] __attribute__((aligned(16384)));
45 static pte_t page_tables[MAX_PAGE_TABLES][256] __attribute__((aligned(1024)));
47 static void parse_atags(struct tag *tags)
49 struct tag *t = NULL;
51 kprintf("[BOOT] Parsing ATAGS\n");
53 for_each_tag(t, tags)
55 kprintf("[BOOT] %08x (%04x): ", t->hdr.tag, t->hdr.size);
56 switch (t->hdr.tag)
58 case ATAG_MEM:
59 kprintf("Memory (%08x-%08x)\n", t->u.mem.start, t->u.mem.size + t->u.mem.start - 1);
60 tag->ti_Tag = KRN_MEMLower;
61 tag->ti_Data = t->u.mem.start;
62 tag++;
63 tag->ti_Tag = KRN_MEMUpper;
64 tag->ti_Data = t->u.mem.start + t->u.mem.size;
65 tag++;
67 mem_upper = t->u.mem.start + t->u.mem.size;
68 mem_lower = t->u.mem.start;
70 break;
71 case ATAG_CMDLINE:
73 char *cmdline = malloc(strlen(t->u.cmdline.cmdline) + 1);
74 strcpy(cmdline, t->u.cmdline.cmdline);
75 kprintf("CMDLine: \"%s\"\n", cmdline);
77 tag->ti_Tag = KRN_CmdLine;
78 tag->ti_Data = (intptr_t)cmdline;
79 tag++;
81 break;
82 case ATAG_INITRD2:
83 kprintf("RAMDISK: (%08x-%08x)\n", t->u.initrd.start, t->u.initrd.size + t->u.initrd.start - 1);
84 pkg_image = (void *)t->u.initrd.start;
85 pkg_size = t->u.initrd.size;
86 break;
87 default:
88 kprintf("IGN...\n");
89 break;
94 void setup_mmu(uintptr_t kernel_phys, uintptr_t kernel_virt, uintptr_t length)
96 int i;
97 uintptr_t first_1M_page = kernel_virt & 0xfff00000;
98 uintptr_t last_1M_page = ((kernel_virt + length + 0x000fffff) & 0xfff00000) - 1;
100 kprintf("[BOOT] Preparing initial MMU map\n");
102 /* Clear page dir */
103 for (i=0; i < 4096; i++)
104 page_dir[i].raw = 0;
106 /* 1:1 memory mapping */
107 for (i=(mem_lower >> 20); i < (mem_upper >> 20); i++)
109 page_dir[i].section.type = PDE_TYPE_SECTION;
110 page_dir[i].section.b = 0;
111 page_dir[i].section.c = 1; /* Cacheable */
112 page_dir[i].section.ap = 3; /* All can read&write */
113 page_dir[i].section.base_address = i;
116 /* 0x70000000 - 0x7fffffff */
117 for (i = (0x70000000 >> 20); i < (0x80000000 >> 20); i++)
119 page_dir[i].section.type = PDE_TYPE_SECTION;
120 page_dir[i].section.b = 1; /* Shared device */
121 page_dir[i].section.c = 0; /* Non-Cacheable */
122 page_dir[i].section.ap = 3; /* All can read&write */
123 page_dir[i].section.base_address = i;
126 kprintf("[BOOT] Preparing mapping for kernel (%d bytes, pages %08x to %08x)\n",
127 length, first_1M_page, last_1M_page);
129 int fp = first_1M_page >> 20;
130 int lp = last_1M_page >> 20;
131 int used_pte = 0;
133 if (lp == fp) lp++;
135 for (i = fp; i < lp; i++)
137 if (used_pte >= MAX_PAGE_TABLES)
139 kprintf("[BOOT] Run out of free page tables. Kernel larger than 10MB?\n");
140 for(;;);
143 page_dir[i].coarse.type = PDE_TYPE_COARSE;
144 page_dir[i].coarse.domain = 0;
145 page_dir[i].coarse.sbz = 0;
146 page_dir[i].coarse.imp = 0;
147 page_dir[i].coarse.base_address = (intptr_t)&page_tables[used_pte] >> 10;
149 int j;
150 for (j = 0; j < 256; j++)
152 uintptr_t synth_addr = (i << 20) + (j << 12);
154 if (synth_addr < kernel_virt)
155 page_tables[used_pte][j].raw = 0;
156 else if (synth_addr < kernel_virt + length)
158 page_tables[used_pte][j].raw = 0;
159 page_tables[used_pte][j].page.base_address = (synth_addr - kernel_virt + kernel_phys) >> 12;
160 page_tables[used_pte][j].page.b = 0;
161 page_tables[used_pte][j].page.c = 1;
162 page_tables[used_pte][j].page.ap = 3;
163 page_tables[used_pte][j].page.type = PTE_TYPE_PAGE;
165 else
166 page_tables[used_pte][j].raw = 0;
169 used_pte++;
174 void boot(uintptr_t dummy, uintptr_t arch, struct tag * atags)
176 uint32_t tmp;
177 void (*entry)(struct TagItem *tags);
179 /* Enable NEON and VFP */
180 asm volatile ("mrc p15, 0, %0, c1, c0, 2":"=r"(tmp));
181 tmp |= 3 << 20;
182 tmp |= 3 << 22;
183 asm volatile ("mcr p15, 0, %0, c1, c0, 2"::"r"(tmp));
185 fmxr(cr8, fmrx(cr8) | 1 << 30);
187 kprintf("[BOOT] AROS for EfikaMX bootstrap\n");
189 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
190 kprintf("[BOOT] control register %08x\n", tmp);
191 tmp &= ~2; /* Disable MMU and caches */
192 tmp |= 1 << 13; /* Exception vectors at 0xffff0000 */
193 asm volatile ("mcr p15, 0, %0, c1, c0, 0"::"r"(tmp));
195 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
196 kprintf("[BOOT] control register %08x\n", tmp);
198 tag->ti_Tag = KRN_BootLoader;
199 tag->ti_Data = (IPTR)"Bootstrap/EfikaMX ARM";
200 tag++;
202 parse_atags(atags);
204 kprintf("[BOOT] Bootstrap @ %08x-%08x\n", &__bootstrap_start, &__bootstrap_end);
205 kprintf("[BOOT] Topmost address for kernel: %p\n", mem_upper);
207 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)
226 uint8_t *base = pkg_image;
228 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
230 kprintf("[BOOT] Kernel image is ELF file\n");
232 getElfSize(base, &size_rw, &size_ro);
234 total_size_ro += (size_ro + 4095) & ~4095;
235 total_size_rw += (size_rw + 4095) & ~4095;
237 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
239 kprintf("[BOOT] Kernel image is a package:\n");
241 uint8_t *file = base+4;
242 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
243 const uint8_t *file_end = base+total_length;
244 uint32_t len;
246 kprintf("[BOOT] Package size: %dKB\n", total_length >> 10);
248 file = base + 8;
250 while(file < file_end)
252 const char *filename = remove_path(file+4);
254 /* get text length */
255 len = AROS_BE2LONG(*(uint32_t*)file);
256 /* display the file name */
257 kprintf("[BOOT] %s \n", filename);
259 file += len + 5;
261 len = AROS_BE2LONG(*(uint32_t *)file);
262 file += 4;
264 /* load it */
265 getElfSize(file, &size_rw, &size_ro);
267 total_size_ro += (size_ro + 4095) & ~4095;
268 total_size_rw += (size_rw + 4095) & ~4095;
270 /* go to the next file */
271 file += len;
276 kernel_phys = mem_upper - total_size_ro - total_size_rw;
277 kernel_virt = 0xffff0000 - total_size_ro - total_size_rw;
279 kprintf("[BOOT] Physical address of kernel: %p\n", kernel_phys);
280 kprintf("[BOOT] Virtual address of kernel: %p\n", kernel_virt);
282 entry = (void (*)(struct TagItem))kernel_virt;
284 initAllocator(kernel_phys, kernel_phys + total_size_ro, kernel_virt - kernel_phys);
286 tag->ti_Tag = KRN_KernelLowest;
287 tag->ti_Data = kernel_phys;
288 tag++;
290 tag->ti_Tag = KRN_KernelHighest;
291 tag->ti_Data = kernel_phys + ((total_size_ro + 4095) & ~4095) + ((total_size_rw + 4095) & ~4095);
292 tag++;
294 loadElf(&_binary_kernel_bin_start);
296 if (pkg_image && pkg_size)
298 uint8_t *base = pkg_image;
300 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
302 kprintf("[BOOT] Kernel image is ELF file\n");
304 /* load it */
305 loadElf(base);
307 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
309 kprintf("[BOOT] Kernel image is a package:\n");
311 uint8_t *file = base+4;
312 uint32_t total_length = AROS_BE2LONG(*(uint32_t*)file); /* Total length of the module */
313 const uint8_t *file_end = base+total_length;
314 uint32_t len;
316 kprintf("[BOOT] Package size: %dKB\n", total_length >> 10);
318 file = base + 8;
320 while(file < file_end)
322 const char *filename = remove_path(file+4);
324 /* get text length */
325 len = AROS_BE2LONG(*(uint32_t*)file);
326 /* display the file name */
327 kprintf("[BOOT] %s ", filename);
329 file += len + 5;
331 len = AROS_BE2LONG(*(uint32_t *)file);
332 file += 4;
334 /* load it */
335 loadElf(file);
337 /* go to the next file */
338 file += len;
343 arm_flush_cache(kernel_phys, total_size_ro + total_size_rw);
345 tag->ti_Tag = KRN_KernelBss;
346 tag->ti_Data = (IPTR)tracker;
347 tag++;
350 kprintf("[BOOT] First level MMU page at %08x\n", page_dir);
352 setup_mmu(kernel_phys, kernel_virt, total_size_ro + total_size_rw);
355 tag->ti_Tag = TAG_DONE;
356 tag->ti_Data = 0;
358 kprintf("[BOOT] Kernel taglist contains %d entries\n", ((intptr_t)tag - (intptr_t)tags)/sizeof(struct TagItem));
359 kprintf("[BOOT] Bootstrap wasted %d bytes of memory for kernels use\n", mem_used() );
362 /* Write page_dir address to ttbr0 */
363 asm volatile ("mcr p15, 0, %0, c2, c0, 0"::"r"(page_dir));
364 /* Write ttbr control N = 0 (use only ttbr0) */
365 asm volatile ("mcr p15, 0, %0, c2, c0, 2"::"r"(0));
367 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
368 kprintf("[BOOT] control register %08x\n", tmp);
369 tmp |= 1; /* Enable MMU */
370 asm volatile ("mcr p15, 0, %0, c1, c0, 0"::"r"(tmp));
372 asm volatile ("mrc p15, 0, %0, c1, c0, 0":"=r"(tmp));
373 kprintf("[BOOT] control register %08x\n", tmp);
375 kprintf("[BOOT] Heading over to AROS kernel @ %08x\n", entry);
377 entry(tags);
379 kprintf("[BOOT] Back? Something wrong happened...\n");
381 while(1);