2 Copyright © 2006-2012, The AROS Development Team. All rights reserved.
5 Desc: 32-bit bootstrap code used to boot the 64-bit AROS kernel.
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>
26 #include "bootstrap.h"
27 #include "elfloader.h"
31 #ifdef MULTIBOOT_64BIT
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)
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)
56 const struct multiboot_header __header
__attribute__((used
,section(".aros.startup"))) =
60 -(MB_MAGIC
+ MB_FLAGS
),
66 1, /* We prefer text mode, but will accept also framebuffer */
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))) =
84 sizeof(struct my_mb2_header
),
85 -(MB2_MAGIC
+ MB2_ARCH_I386
+ sizeof(struct my_mb2_header
))
88 MB2_HEADER_TAG_FRAMEBUFFER
,
90 sizeof(struct mb2_header_tag_framebuffer
),
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
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 */
114 " cli\n\t" /* Lock interrupts (by flag)... */
116 " outb %al, $0x21\n\t" /* And disable them physically */
117 " outb %al, $0xa1\n\t"
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
;
154 static unsigned char __stack
[65536] __attribute__((used
));
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
)
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)
192 mo
= __bs_malloc(sizeof(struct ELFNode
));
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)
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
)
232 if (header
->magic
[0] != 0x60 || header
->magic
[1] != 0x0a)
235 /* All 10 characters may be used! */
236 memcpy(size
, header
->size
, 10);
239 len
= strtoul(size
, NULL
, 10);
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);
251 return (((const void *)(&header
[1])) + len
);
254 static char *ar_name(const struct ar_header
*header
, const struct ar_header
*longnames
)
260 name
= &header
->name
[0];
262 if (name
[0] == '/' && isdigit(name
[1]) && longnames
!= NULL
) {
263 /* GNU style long names */
265 int offset
= strtoul(&name
[1], NULL
, 10);
267 name
= ar_data(longnames
) + offset
;
268 for (len
= 0, cp
= name
; *cp
!= '\n'; len
++, cp
++) {
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]));
279 for (len
= 0, cp
= name
; *cp
!= ' '; len
++, cp
++)
280 if (longnames
!= NULL
&& *cp
== '/')
284 tmp
= __bs_malloc(len
+ 1);
285 memcpy(tmp
, name
, len
);
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
));
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
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
);
328 len
= LONG2BE(*(int *)file
);
333 D(kprintf("[BOOT] * PKG module %s @ %p\n", mo
->Name
, mo
->eh
));
341 else if (memcmp(p
,"!<arch>\n",8) == 0) {
342 const struct ar_header
*file
;
344 const struct ar_header
*longnames
= NULL
;
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)
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
);
370 mo
->eh
= (void *)data
;
371 D(kprintf("[BOOT] * ar module %s @ %p\n", mo
->Name
, mo
->eh
));
373 D(kprintf("[BOOT] * Ignored @ %p (%s)\n", file
, s
));
382 kprintf("[BOOT] Unknown module 0x%p\n", p
);
387 /* Marks console mirror buffer as allocated */
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
)
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
;
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
);
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
;
448 tag
->ti_Tag
= KRN_KernelLowest
;
449 tag
->ti_Data
= KERNEL_OFFSET
| kick_start
;
452 tag
->ti_Tag
= KRN_KernelHighest
;
453 tag
->ti_Data
= KERNEL_OFFSET
| (unsigned long)kick_end
;
456 tag
->ti_Tag
= KRN_KernelBss
;
457 tag
->ti_Data
= KERNEL_OFFSET
| (unsigned long)__bss_track
;
460 tag
->ti_Tag
= KRN_DebugInfo
;
461 tag
->ti_Data
= KERNEL_OFFSET
| (unsigned long)DebugInfo_ptr
;
464 tag
->ti_Tag
= KRN_ProtAreaStart
;
465 tag
->ti_Data
= (unsigned long)&_prot_lo
;
468 tag
->ti_Tag
= KRN_ProtAreaEnd
;
469 tag
->ti_Data
= (unsigned long)&_prot_hi
;
472 tag
->ti_Tag
= TAG_DONE
;
475 void panic(const char *str
)
477 kprintf("%s\n", str
);
478 kprintf("*** SYSTEM PANIC!!! ***\n");
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;
502 unsigned long mod_end
= 0;
503 unsigned long kbase
= 0;
504 unsigned long kstart
= 0;
506 kernel_entry_fun_t kentry
= NULL
;
507 struct ELF_ModuleInfo
*kdebug
= NULL
;
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);
530 case MB_STARTUP_MAGIC
:
531 /* Parse multiboot v1 information */
532 mod_end
= mb1_parse(mb
, &mmap
, &len
);
535 case MB2_STARTUP_MAGIC
:
536 /* Parse multiboot v2 information */
537 mod_end
= mb2_parse(mb
, &mmap
, &len
);
541 /* What to do here? We have no console... Die silently... */
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
)
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);
562 D(kprintf("[BOOT] Modules end at 0x%p\n", mod_end
));
565 panic("No kickstart modules found, nothing to run");
568 tag
->ti_Tag
= KRN_MMAPAddress
;
569 tag
->ti_Data
= KERNEL_OFFSET
| (unsigned long)mmap
;
572 tag
->ti_Tag
= KRN_MMAPLength
;
576 /* Setup stage - prepare the environment */
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
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
))
621 if (end
> 0x100000000ULL
)
622 end
= 0x100000000ULL
;
624 /* Remember the region if it fits in */
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.
635 kbase
= start
+ rw_size
;
636 kbase
= (kbase
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
642 mmap
= (struct mb_mmap
*)(mmap
->size
+ (unsigned long)mmap
+4);
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
);
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
);
667 /* Jump to the kickstart */
670 panic("Failed to run the kickstart");
675 kprintf ("[BOOT] Entered AROS Bootstrap @ 0x%p\n", __bootstrap
);
676 D(kprintf("[BOOT] Stack @ 0x%p, [%d bytes]\n", __stack
, sizeof(__stack
)));