revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / bootstrap / bootstrap.c
blob26b27c41833c8e47a2e2d696e1f1b41f5fb07f7d
1 /*
2 Copyright © 2006-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: 32-bit bootstrap code used to boot the 64-bit AROS kernel.
6 Lang: English
7 */
9 //#define DEBUG
10 //#define DEBUG_MEM
11 //#define DEBUG_MEM_TYPE MMAP_TYPE_RAM
12 //#define DEBUG_TAGLIST
14 #include <aros/kernel.h>
15 #include <aros/multiboot.h>
16 #include <aros/multiboot2.h>
17 //#include <asm/cpu.h>
18 #include <asm/x86_64/cpu.h>
20 #include <bootconsole.h>
21 #include <elfloader.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <ctype.h>
26 #include "bootstrap.h"
27 #include "elfloader.h"
28 #include "support.h"
29 #include "vesa.h"
31 #ifdef MULTIBOOT_64BIT
32 #define DEF_SYSBASE 8
33 #else
34 #define DEF_SYSBASE 4
35 #endif
38 * The Multiboot-compliant header has to be within the first 4KB (1KB??) of ELF file,
39 * therefore it will be packed into the .aros.startup section. I hope, that turning debug on
40 * will not shift it into some distinct location.
41 * We support both legacy Multiboot v1 specification (for backwards compatibility with GRUB1)
42 * and new Multiboot v2 specification (EFI-compatible).
45 #ifdef BOOTLOADER_grub2
46 #define MB_FLAGS (MB_PAGE_ALIGN|MB_MEMORY_INFO|MB_VIDEO_MODE)
47 #else
49 * This makes the bootstrap working with GRUB 1 which doesn't
50 * support MB_VIDEO_MODE. However, this disables framebuffer support in the GRUB,
51 * so this would not work on Mac.
53 #define MB_FLAGS (MB_PAGE_ALIGN|MB_MEMORY_INFO)
54 #endif
56 const struct multiboot_header __header __attribute__((used,section(".aros.startup"))) =
58 MB_MAGIC,
59 MB_FLAGS,
60 -(MB_MAGIC + MB_FLAGS),
66 1, /* We prefer text mode, but will accept also framebuffer */
67 640,
68 200,
72 struct my_mb2_header
74 struct mb2_header header;
75 struct mb2_header_tag_framebuffer tag_fb __attribute__((aligned(8)));
76 struct mb2_header_tag tag_end __attribute__((aligned(8)));
79 const struct my_mb2_header __header_v2 __attribute__((used,section(".aros.startup"),aligned(8))) =
82 MB2_MAGIC,
83 MB2_ARCH_I386,
84 sizeof(struct my_mb2_header),
85 -(MB2_MAGIC + MB2_ARCH_I386 + sizeof(struct my_mb2_header))
88 MB2_HEADER_TAG_FRAMEBUFFER,
89 MBTF_OPTIONAL,
90 sizeof(struct mb2_header_tag_framebuffer),
91 640,
92 200,
96 MB2_HEADER_TAG_END,
98 sizeof(struct mb2_header_tag)
103 First portion of code, called from GRUB directly. It has to set the stack
104 up, disable interrupts and jump to the regular C code
106 asm(" .text\n\t"
107 " .globl kernel_bootstrap\n\t"
108 " .type kernel_bootstrap,@function\n"
109 "kernel_bootstrap: movl $__stack + 65536, %esp\n\t" /* Load stack pointer */
110 " pushl %ebx\n\t" /* store parameters passed by GRUB in registers */
111 " pushl %eax\n\t"
112 " pushl $0\n\t"
113 " cld\n\t"
114 " cli\n\t" /* Lock interrupts (by flag)... */
115 " movb $-1,%al\n\t"
116 " outb %al, $0x21\n\t" /* And disable them physically */
117 " outb %al, $0xa1\n\t"
118 " jmp __bootstrap"
122 * Global variables.
124 * Stack is used only by bootstrap and is located just "somewhere" in memory.
125 * Boot taglist, BSS list, GDT and MMU tables (see cpu.c) are stored in .bss.aros.tables
126 * section which is remapped to the begin of 0x00100000. Therefore these data
127 * may be re-used by the 64-bit kickstart (we pass this area using KRN_ProtAreaStart
128 * and KRN_ProtAreaEnd).
129 * It's up to the kickstart to preserve data pointed to by boot taglist (memory map,
130 * drive tables, VBE structures, etc), because they may originate from the machine's
131 * firmware and not from us.
133 extern char *_prot_lo, *_prot_hi;
136 * Structures to be passed to the kickstart.
137 * They are placed in protected area in order to guarantee that the kickstart
138 * won't overwrite them while starting up.
140 __attribute__((section(".bss.aros.tables"))) static unsigned char __bss_track[32768];
141 __attribute__((section(".bss.aros.tables"))) struct TagItem64 km[32];
142 __attribute__((section(".bss.aros.tables"))) struct mb_mmap MemoryMap[2];
143 __attribute__((section(".bss.aros.tables"))) struct vbe_mode VBEModeInfo;
144 __attribute__((section(".bss.aros.tables"))) struct vbe_controller VBEControllerInfo;
146 /* A pointer used for building a taglist */
147 struct TagItem64 *tag = &km[0];
149 /* Our modules list */
150 static struct ELFNode *firstMod = NULL;
151 static struct ELFNode *lastMod = (struct ELFNode *)&firstMod;
153 /* Our stack */
154 static unsigned char __stack[65536] __attribute__((used));
157 * External modules.
159 * If GRUB has loaded any external modules, they will be loaded here. The modules to be loaded
160 * are stored in a list. If a module with given name is loaded more than once, the last version
161 * loaded by GRUB is used.
163 * Once the list is ready, the modules will be loaded and linked with kernel one after another. Please
164 * note that no information exchange between the modules is allowed. Each of them is absolutely
165 * independent and has to care about itself (it has to clear its own .bss region itself). Kernel knows
166 * about all modules only thanks to the list of resident modules, which is created during a memory scan
167 * over the whole kernel.
169 * Theoretically, such behaviour can guarantee us, that the GPL'ed modules do not conflict with kernel
170 * and may be "part" of it, but since I am not a lawyer, I may be wrong.
174 * Find the storage for module with given name. If such module already exists, return a pointer to it,
175 * so that it can be overridden by the new one. Otherwise, alloc space for new module.
177 static struct ELFNode *module_prepare(const char *s)
179 struct ELFNode *mo;
181 if (s)
183 /* Repeat for every module in the list */
184 for (mo = firstMod; mo; mo = mo->Next)
186 /* Module exists? Break here to allow overriding it */
187 if (strcmp(s, mo->Name) == 0)
188 return mo;
192 mo = __bs_malloc(sizeof(struct ELFNode));
193 mo->Next = NULL;
195 lastMod->Next = mo;
196 lastMod = mo;
198 return mo;
201 struct ar_header {
202 char name[16]; /* ASCII, 0x20 padded */
203 char timestamp[12]; /* Decimal */
204 char owner[6]; /* Decimal */
205 char group[6]; /* Decimal */
206 char mode[8]; /* Octal */
207 char size[10]; /* Decimal */
208 char magic[2]; /* 0x60 0x0a */
211 static const void *ar_data(const struct ar_header *header)
213 unsigned int pad = 0;
215 if (header->magic[0] != 0x60 || header->magic[1] != 0x0a)
216 return NULL;
218 /* BSD extension - name is appended after the header */
219 if (memcmp(header->name, "#1/", 3) == 0) {
220 pad = strtoul(&header->name[3], NULL, 10);
223 return ((const char *)(&header[1])) + pad;
227 static const struct ar_header *ar_next(const struct ar_header *header)
229 unsigned int len;
230 char size[11];
232 if (header->magic[0] != 0x60 || header->magic[1] != 0x0a)
233 return NULL;
235 /* All 10 characters may be used! */
236 memcpy(size, header->size, 10);
237 size[10] = 0;
239 len = strtoul(size, NULL, 10);
240 if (len & 1)
241 len++;
243 /* BSD extension - name is appended after the header */
244 if (memcmp(header->name, "#1/", 3) == 0) {
245 int extra = strtoul(&header->name[3], NULL, 10);
246 if (extra & 1)
247 extra++;
248 len += extra;
251 return (((const void *)(&header[1])) + len);
254 static char *ar_name(const struct ar_header *header, const struct ar_header *longnames)
256 const char *name;
257 char *tmp;
258 int len;
260 name = &header->name[0];
262 if (name[0] == '/' && isdigit(name[1]) && longnames != NULL) {
263 /* GNU style long names */
264 const char *cp;
265 int offset = strtoul(&name[1], NULL, 10);
267 name = ar_data(longnames) + offset;
268 for (len = 0, cp = name; *cp != '\n'; len++, cp++) {
269 if (*cp == '/')
270 break;
272 } else if (name[0] == '#' && name[1] == '1' && name[2] == '/') {
273 /* BSD style long names */
274 len = strtoul(&name[3], NULL, 0);
275 name = ((char *)(&header[1]));
276 } else {
277 const char *cp;
279 for (len = 0, cp = name; *cp != ' '; len++, cp++)
280 if (longnames != NULL && *cp == '/')
281 break;
284 tmp = __bs_malloc(len + 1);
285 memcpy(tmp, name, len);
286 tmp[len] = 0;
288 return tmp;
291 unsigned long AddModule(unsigned long mod_start, unsigned long mod_end, unsigned long end)
293 char *p = (char *)mod_start;
295 if (p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F')
298 * The loaded file is an ELF object. It may be put directly into our list of modules.
299 * Unfortunately GRUB doesn't give us names of loaded modules
301 struct ELFNode *mo = module_prepare(NULL);
303 mo->Name = "Kickstart ELF";
304 mo->eh = (void*)mod_start;
306 D(kprintf("[BOOT] * ELF module %s @ %p\n", mo->Name, mo->eh));
308 if (mod_end > end)
309 end = mod_end;
311 else if (p[0] == 'P' && p[1] == 'K' && p[2] == 'G' && p[3] == 0x01)
314 * The loaded file is an PKG\0 archive. Scan it to find all modules which are
315 * stored here.
317 void *file = p + 8;
319 D(kprintf("[BOOT] * package @ %p:\n", mod_start));
321 while (file < (void*)mod_end)
323 int len = LONG2BE(*(int *)file);
324 char *s = __bs_remove_path(file+4);
325 struct ELFNode *mo = module_prepare(s);
327 file += 5+len;
328 len = LONG2BE(*(int *)file);
329 file += 4;
331 mo->Name = s;
332 mo->eh = file;
333 D(kprintf("[BOOT] * PKG module %s @ %p\n", mo->Name, mo->eh));
335 file += len;
338 if (mod_end > end)
339 end = mod_end;
341 else if (memcmp(p,"!<arch>\n",8) == 0) {
342 const struct ar_header *file;
343 char *name;
344 const struct ar_header *longnames = NULL;
346 /* ar(1) archive */
347 D(kprintf("[BOOT] * archive @ %p:\n", mod_start));
349 /* Look for the GNU extended name section */
350 for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
352 name = ar_name(file, NULL);
353 if (strcmp(name, "//") == 0)
355 longnames = file;
356 break;
359 D(kprintf("[BOOT] * longnames @ %p\n", longnames));
361 for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
363 const char *data = ar_data(file);
364 char *s = ar_name(file, longnames);
366 if (memcmp(data,"\177ELF",4) == 0) {
367 struct ELFNode *mo = module_prepare(s);
369 mo->Name = s;
370 mo->eh = (void *)data;
371 D(kprintf("[BOOT] * ar module %s @ %p\n", mo->Name, mo->eh));
372 } else {
373 D(kprintf("[BOOT] * Ignored @ %p (%s)\n", file, s));
377 if (mod_end > end)
378 end = mod_end;
381 else
382 kprintf("[BOOT] Unknown module 0x%p\n", p);
384 return end;
387 /* Marks console mirror buffer as allocated */
388 void AllocFB(void)
390 if (scr_Type == SCR_GFX)
392 D(kprintf("[BOOT] Allocating %u bytes for console mirror (%ux%u)\n", scr_Width * scr_Height, scr_Width, scr_Height));
394 __bs_malloc(scr_Width * scr_Height);
398 int ParseCmdLine(const char *cmdline)
400 if (cmdline)
403 * If vesa= option was given, set up the specified video mode explicitly.
404 * Otherwise specify to AROS what has been passed to us by the bootloader.
406 char *vesa = strstr(cmdline, "vesa=");
408 tag->ti_Tag = KRN_CmdLine;
409 tag->ti_Data = KERNEL_OFFSET | (unsigned long)cmdline;
410 tag++;
412 if (vesa)
414 setupVESA(&vesa[5]);
415 return 0;
418 return 1;
421 struct mb_mmap *mmap_make(unsigned long *len, unsigned long mem_lower, unsigned long long mem_upper)
423 D(kprintf("[BOOT] No memory map supplied by the bootloader, using defaults\n"));
425 MemoryMap[0].size = 20;
426 MemoryMap[0].addr = 0;
427 MemoryMap[0].len = mem_lower;
428 MemoryMap[0].type = MMAP_TYPE_RAM;
430 MemoryMap[1].size = 20;
431 MemoryMap[1].addr = 0x100000;
432 MemoryMap[1].len = mem_upper;
433 MemoryMap[1].type = MMAP_TYPE_RAM;
435 *len = sizeof(MemoryMap);
436 return MemoryMap;
439 static void prepare_message(unsigned long kick_start, unsigned long kick_base, void *kick_end, void *DebugInfo_ptr)
441 D(kprintf("[BOOT] Kickstart 0x%p - 0x%p (base 0x%p), protection 0x%p - 0x%p\n", kick_start, kick_end, kick_base,
442 &_prot_lo, &_prot_hi));
444 tag->ti_Tag = KRN_KernelBase;
445 tag->ti_Data = KERNEL_OFFSET | kick_base;
446 tag++;
448 tag->ti_Tag = KRN_KernelLowest;
449 tag->ti_Data = KERNEL_OFFSET | kick_start;
450 tag++;
452 tag->ti_Tag = KRN_KernelHighest;
453 tag->ti_Data = KERNEL_OFFSET | (unsigned long)kick_end;
454 tag++;
456 tag->ti_Tag = KRN_KernelBss;
457 tag->ti_Data = KERNEL_OFFSET | (unsigned long)__bss_track;
458 tag++;
460 tag->ti_Tag = KRN_DebugInfo;
461 tag->ti_Data = KERNEL_OFFSET | (unsigned long)DebugInfo_ptr;
462 tag++;
464 tag->ti_Tag = KRN_ProtAreaStart;
465 tag->ti_Data = (unsigned long)&_prot_lo;
466 tag++;
468 tag->ti_Tag = KRN_ProtAreaEnd;
469 tag->ti_Data = (unsigned long)&_prot_hi;
470 tag++;
472 tag->ti_Tag = TAG_DONE;
475 void panic(const char *str)
477 kprintf("%s\n", str);
478 kprintf("*** SYSTEM PANIC!!! ***\n");
480 for(;;)
481 HALT;
485 * The entry point in C.
487 * The bootstrap routine has to load the kickstart at 0x01000000, with RO sections growing up the memory and
488 * RW sections stored beneath the 0x01000000 address. It is supposed to transfer the GRUB information further
489 * into the 64-bit kickstart.
491 * The kickstart is assembled from modules which have been loaded by GRUB. The modules may be loaded separately,
492 * or as a collection in PKG file. If some file is specified in both PKG file and list of separate modules, the
493 * copy in PKG will be skipped.
495 static void __bootstrap(unsigned int magic, void *mb)
497 struct mb_mmap *mmap = NULL;
498 unsigned long len = 0;
499 unsigned long ro_size = 0;
500 unsigned long rw_size = 0;
501 unsigned long ksize;
502 unsigned long mod_end = 0;
503 unsigned long kbase = 0;
504 unsigned long kstart = 0;
505 void *kend = NULL;
506 kernel_entry_fun_t kentry = NULL;
507 struct ELF_ModuleInfo *kdebug = NULL;
508 #ifdef DEBUG_MEM
509 struct mb_mmap *mm2;
510 #endif
513 * This will set fb_Mirror address to start of our working memory.
514 * We don't know its size yet, we will allocate it later.
516 fb_Mirror = __bs_malloc(0);
518 #ifdef MULTIBOOT_64BIT
520 * tell the CPU that we will support SSE. We do it here because x86-64 compiler
521 * with -m32 switch will use SSE for operations on long longs.
523 wrcr(cr4, rdcr(cr4) | (3 << 9));
524 /* Clear the EM and MP flags of CR0 */
525 wrcr(cr0, rdcr(cr0) & ~6);
526 #endif
528 switch(magic)
530 case MB_STARTUP_MAGIC:
531 /* Parse multiboot v1 information */
532 mod_end = mb1_parse(mb, &mmap, &len);
533 break;
535 case MB2_STARTUP_MAGIC:
536 /* Parse multiboot v2 information */
537 mod_end = mb2_parse(mb, &mmap, &len);
538 break;
540 default:
541 /* What to do here? We have no console... Die silently... */
542 return;
545 #ifdef DEBUG_MEM
546 ksize = len;
547 mm2 = mmap;
549 kprintf("[BOOT] Memory map contents:\n", mmap);
550 while (ksize >= sizeof(struct mb_mmap))
552 #ifdef DEBUG_MEM_TYPE
553 if (mm2->type == DEBUG_MEM_TYPE)
554 #endif
555 kprintf("[BOOT] Type %lu addr %p len %p\n", mm2->type, mm2->addr, mm2->len);
557 ksize -= mm2->size+4;
558 mm2 = (struct mb_mmap *)(mm2->size + (unsigned long)mm2 + 4);
560 #endif
562 D(kprintf("[BOOT] Modules end at 0x%p\n", mod_end));
563 if (!firstMod)
565 panic("No kickstart modules found, nothing to run");
568 tag->ti_Tag = KRN_MMAPAddress;
569 tag->ti_Data = KERNEL_OFFSET | (unsigned long)mmap;
570 tag++;
572 tag->ti_Tag = KRN_MMAPLength;
573 tag->ti_Data = len;
574 tag++;
576 /* Setup stage - prepare the environment */
577 setup_mmu();
579 /* Count kickstart size */
580 if (!GetKernelSize(firstMod, &ro_size, &rw_size, NULL))
582 panic("Failed to determine kickstart size");
585 D(kprintf("[BOOT] Code %u, data %u\n", ro_size, rw_size));
588 * Total kickstart size + alignment window (page size - 1) + some free space (512KB) for
589 * boot-time memory allocator.
590 * TODO: This is a temporary thing. Currently our kernel expects that it can use addresses beyond
591 * KRN_KernelHighest to store boot-time private data, supervisor stack, segment descriptors, MMU stuff, etc.
592 * The area is joined with read-only section because it's accessed only by supervisor-mode code
593 * and can safely be marked as read-only for users.
594 * Boot-time allocator needs to be smarter.
596 ksize = ro_size + rw_size + PAGE_SIZE - 1 + 0x80000;
598 /* Now locate the highest appropriate region */
599 while (len >= sizeof(struct mb_mmap))
601 if (mmap->type == MMAP_TYPE_RAM)
603 unsigned long long start = mmap->addr;
604 unsigned long long end = mmap->addr + mmap->len;
607 * The region must be located in 32-bit memory and must not overlap
608 * our modules.
609 * Here we assume the following:
610 * 1. Multiboot data from GRUB is placed in low memory.
611 * 2. At least one module is placed in upper memory, above ourselves.
612 * 3. There's no usable space below our modules.
614 if ((start <= 0x100000000ULL - ksize) && (end >= mod_end + ksize))
616 unsigned long size;
618 if (start < mod_end)
619 start = mod_end;
621 if (end > 0x100000000ULL)
622 end = 0x100000000ULL;
624 /* Remember the region if it fits in */
625 size = end - start;
626 if (size >= ksize)
629 * We place .data section at the start of the region, followed by .code section
630 * at page-aligned 'kbase' address.
631 * There must be a space beyond kickstart's read-only section, because the kickstart
632 * will extend it in order to store boot-time configuration and own private data.
634 kstart = start;
635 kbase = start + rw_size;
636 kbase = (kbase + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
641 len -= mmap->size+4;
642 mmap = (struct mb_mmap *)(mmap->size + (unsigned long)mmap+4);
645 if (!kbase)
647 panic("Failed to find %u bytes for the kickstart.\n"
648 "Your system doesn't have enough memory.");
651 kprintf("[BOOT] Loading kickstart, data 0x%p, code 0x%p...\n", kstart, kbase);
653 if (!LoadKernel(firstMod, (void *)kbase, (void *)kstart, (char *)__bss_track, DEF_SYSBASE, &kend, &kentry, &kdebug))
655 panic("Failed to load the kickstart");
658 /* Prepare the rest of boot taglist */
659 prepare_message(kstart, kbase, kend, kdebug);
661 #ifdef DEBUG_TAGLIST
662 kprintf("[BOOT] Boot taglist:\n");
663 for (tag = km; tag->ti_Tag != TAG_DONE; tag++)
664 kprintf("[BOOT] 0x%llp 0x%llp\n", tag->ti_Tag, tag->ti_Data);
665 #endif
667 /* Jump to the kickstart */
668 kick(kentry, km);
670 panic("Failed to run the kickstart");
673 void Hello(void)
675 kprintf ("[BOOT] Entered AROS Bootstrap @ 0x%p\n", __bootstrap);
676 D(kprintf("[BOOT] Stack @ 0x%p, [%d bytes]\n", __stack, sizeof(__stack)));