Use correct CPU include file
[AROS.git] / arch / x86_64-pc / bootstrap / bootstrap.c
blob13a462708b2895ed94abca0a337536f7d437a65f
1 /*
2 Copyright (C) 2006-2011 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 <asm/x86_64/cpu.h>
18 #include <bootconsole.h>
19 #include <stdlib.h>
20 #include <string.h>
22 #include "bootstrap.h"
23 #include "elfloader.h"
24 #include "support.h"
25 #include "vesa.h"
28 The Multiboot-compliant header has to be within the first 4KB (1KB??) of ELF file,
29 therefore it will be packed into the .aros.startup section. I hope, that turning debug on
30 will not shift it into some distinct location.
33 #define MB_FLAGS (MB_PAGE_ALIGN|MB_MEMORY_INFO|MB_VIDEO_MODE)
35 static const struct multiboot_header __header __attribute__((used,section(".aros.startup"))) =
37 MB_MAGIC,
38 MB_FLAGS,
39 -(MB_MAGIC + MB_FLAGS),
45 1, /* We prefer text mode, but will accept also framebuffer */
46 640,
47 200,
48 32,
52 First portion of code, called from GRUB dirrectly. It has to set the stack up, disable interrupts
53 and jump to the regular C code
55 asm(" .text\n\t"
56 " .globl kernel_bootstrap\n\t"
57 " .type kernel_bootstrap,@function\n"
58 "kernel_bootstrap: movl $__stack+65536, %esp\n\t" /* Load stack pointer */
59 " pushl %ebx\n\t" /* store parameters passed by GRUB in registers */
60 " pushl %eax\n\t"
61 " pushl $0\n\t"
62 " cld\n\t"
63 " cli\n\t" /* Lock interrupts (by flag)... */
64 " movb $-1,%al\n\t"
65 " outb %al, $0x21\n\t" /* And disable them physically */
66 " outb %al, $0xa1\n\t"
67 " jmp __bootstrap"
71 * Global variables.
73 * Stack is used only by bootstrap and is located just "somewhere" in memory.
74 * Boot taglist, BSS list, GDT and MMU tables (see cpu.c) are stored in .bss.aros.tables
75 * section which is remapped to the begin of 0x00100000. Therefore these data
76 * may be re-used by the 64-bit kickstart (we pass this area using KRN_ProtAreaStart
77 * and KRN_ProtAreaEnd).
78 * It's up to the kickstart to preserve data pointed to by boot taglist (memory map,
79 * drive tables, VBE structures, etc), because they may originate from the machine's
80 * firmware and not from us.
82 extern char *_prot_lo, *_prot_hi;
84 /* Structures to be passed to the kickstart */
85 static unsigned char __bss_track[32768] __attribute__((section(".bss.aros.tables")));
86 struct TagItem64 km[32] __attribute__((section(".bss.aros.tables")));
87 static struct mb_mmap MemoryMap[2];
88 static struct vbe_mode VBEModeInfo;
89 static struct vbe_controller VBEControllerInfo;
91 /* A pointer used for building a taglist */
92 struct TagItem64 *tag = &km[0];
94 static unsigned char __stack[65536] __attribute__((used));
96 static const char default_mod_name[] = "<unknown>";
99 * External modules.
101 * If GRUB has loaded any external modules, they will be loaded here. The modules to be loaded
102 * are stored in a list. If a module with given name is loaded more than once, the last version
103 * loaded by GRUB is used.
105 * Once the list is ready, the modules will be loaded and linked with kernel one after another. Please
106 * note that no information exchange between the modules is allowed. Each of them is absolutely
107 * independent and has to care about itself (it has to clear its own .bss region itself). Kernel knows
108 * about all modules only thanks to the list of resident modules, which is created during a memory scan
109 * over the whole kernel.
111 * Theoretically, such behaviour can guarantee us, that the GPL'ed modules do not conflict with kernel
112 * and may be "part" of it, but since I am not a lawyer, I may be wrong.
116 * Find the storage for module with given name. If such module already exists, return a pointer to it,
117 * so that it can be overridden by the new one. Otherwise, alloc space for new module.
119 static struct module *module_prepare(const char *s, const struct module *m, int *count)
121 struct module *mo = (struct module *)m;
122 int c = *count;
124 /* Repeat for every module in the list */
125 while (c>0)
127 /* Module exists? Break here to allow overriding it */
128 #if 0
129 // FIXME: we do not know the names of ELF modules
130 if (strcmp(s, mo->name) == 0)
131 break;
132 #endif
134 /* Iterate... */
135 c--;
136 mo++;
139 /* If the module has not been found on the list, increase the counter */
140 if (c==0) *count = *count + 1;
142 return mo;
146 * Search for modules
148 static int find_modules(struct multiboot *mb, const struct module *m)
150 int count = 0;
152 /* Are there any modules at all? */
153 if (mb->flags && MB_FLAGS_MODS)
155 int i;
156 struct mb_module *mod = (struct mb_module *)mb->mods_addr;
157 D(kprintf("[BOOT] GRUB has loaded %d files\n", mb->mods_count));
159 /* Go through the list of modules loaded by GRUB */
160 for (i=0; i < mb->mods_count; i++, mod++)
162 char *p = (char *)mod->mod_start;
164 if (p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F')
167 * The loaded file is an ELF object. It may be put directly into our list of modules
169 const char *s = default_mod_name;
170 struct module *mo = module_prepare(s, m, &count);
172 mo->name = s;
173 mo->address = (void*)mod->mod_start;
175 D(kprintf("[BOOT] * ELF module %s @ %p\n", mo->name, mo->address));
177 else if (p[0] == 'P' && p[1] == 'K' && p[2] == 'G' && p[3] == 0x01)
180 * The loaded file is an PKG\0 archive. Scan it to find all modules which are
181 * stored here.
183 void *file = p + 8;
185 D(kprintf("[BOOT] * package %s @ %p:\n", __bs_remove_path((char *)mod->cmdline), mod->mod_start));
187 while (file < (void*)mod->mod_end)
189 int len = LONG2BE(*(int *)file);
190 const char *s = __bs_remove_path(file+4);
191 struct module *mo = module_prepare(s, m, &count);
193 file += 5+len;
194 len = LONG2BE(*(int *)file);
195 file += 4;
197 mo->name = s;
198 mo->address = file;
199 D(kprintf("[BOOT] * PKG module %s @ %p\n", mo->name, mo->address));
201 file += len;
207 /* Return the real amount of modules to load */
208 return count;
211 static void setupVESA(char *vesa)
213 long x=0, y=0, d=0;
214 long mode;
216 void *vesa_start = &_binary_vesa_start;
217 unsigned long vesa_size = (unsigned long)&_binary_vesa_size;
219 x = strtoul(vesa, &vesa, 10);
220 vesa++;
222 y = strtoul(vesa, &vesa, 10);
223 vesa++;
225 d = strtoul(vesa, &vesa, 10);
228 * 16-bit VBE trampoline is needed only once only here, so
229 * we can simply copy it to some address, do what we need, and
230 * then forget.
232 kprintf("[BOOT] setupVESA: vesa.bin @ %p [size=%d]\n", &_binary_vesa_start, &_binary_vesa_size);
233 __bs_memcpy((void *)0x1000, vesa_start, vesa_size);
235 kprintf("[BOOT] setupVESA: BestModeMatch for %dx%dx%d = ",x,y,d);
236 mode = findMode(x,y,d);
238 /* Get information and copy it from 16-bit memory space to our 32-bit memory */
239 getModeInfo(mode);
240 __bs_memcpy(&VBEModeInfo, modeinfo, sizeof(struct vbe_mode));
241 getControllerInfo();
242 __bs_memcpy(&VBEControllerInfo, controllerinfo, sizeof(struct vbe_controller));
244 /* Activate linear framebuffer is supported by the mode */
245 if (VBEModeInfo.mode_attributes & VM_LINEAR_FB)
246 mode |= VBE_MODE_LINEAR_FB;
248 kprintf("%x\n",mode);
250 if (setVbeMode(mode) == VBE_RC_SUPPORTED)
252 unsigned char palwidth = 6;
254 /* Try to switch palette width to 8 bits if possible */
255 if (VBEControllerInfo.capabilities & VC_PALETTE_WIDTH)
256 paletteWidth(0x0800, &palwidth);
258 /* Reinitialize our console */
259 con_InitVESA(VBEControllerInfo.version, &VBEModeInfo);
261 tag->ti_Tag = KRN_VBEModeInfo;
262 tag->ti_Data = KERNEL_OFFSET | (unsigned long)&VBEModeInfo;
263 tag++;
265 tag->ti_Tag = KRN_VBEControllerInfo;
266 tag->ti_Data = KERNEL_OFFSET | (unsigned long)&VBEControllerInfo;
267 tag++;
269 tag->ti_Tag = KRN_VBEMode;
270 tag->ti_Data = mode;
271 tag++;
273 tag->ti_Tag = KRN_VBEPaletteWidth;
274 tag->ti_Data = palwidth;
275 tag++;
278 kprintf("[BOOT] setupVESA: VESA setup complete\n");
281 static void setupFB(struct multiboot *mb)
283 if (mb->flags & MB_FLAGS_GFX)
285 kprintf("[BOOT] Got VESA display mode 0x%x from the bootstrap\n", mb->vbe_mode);
287 * We are already running in VESA mode set by the bootloader.
288 * Pass on the mode information to AROS.
290 tag->ti_Tag = KRN_VBEModeInfo;
291 tag->ti_Data = KERNEL_OFFSET | mb->vbe_mode_info;
292 tag++;
294 tag->ti_Tag = KRN_VBEControllerInfo;
295 tag->ti_Data = KERNEL_OFFSET | mb->vbe_control_info;
296 tag++;
298 tag->ti_Tag = KRN_VBEMode;
299 tag->ti_Data = mb->vbe_mode;
300 tag++;
302 return;
305 if (mb->flags & MB_FLAGS_FB)
307 kprintf("[BOOT] Got framebuffer display %dx%dx%d from the bootstrap\n",
308 mb->framebuffer_width, mb->framebuffer_height, mb->framebuffer_bpp);
309 D(kprintf("[BOOT] Address 0x%llp, type %d, %d bytes per line\n", mb->framebuffer_addr, mb->framebuffer_type, mb->framebuffer_pitch));
312 * AROS VESA driver supports only RGB framebuffer because we are
313 * unlikely to have VGA palette registers for other cases.
314 * FIXME: we have some pointer to palette registers. We just need to
315 * pass it to the bootstrap and handle it there (how? Is it I/O port
316 * address or memory-mapped I/O address?)
318 if (mb->framebuffer_type != MB_FRAMEBUFFER_RGB)
319 return;
322 * We have a framebuffer but no VBE information.
323 * Looks like we are running on EFI machine with no VBE support (Mac).
324 * Convert framebuffer data to VBEModeInfo and hand it to AROS.
326 VBEModeInfo.mode_attributes = VM_SUPPORTED|VM_COLOR|VM_GRAPHICS|VM_NO_VGA_HW|VM_NO_VGA_MEM|VM_LINEAR_FB;
327 VBEModeInfo.bytes_per_scanline = mb->framebuffer_pitch;
328 VBEModeInfo.x_resolution = mb->framebuffer_width;
329 VBEModeInfo.y_resolution = mb->framebuffer_height;
330 VBEModeInfo.bits_per_pixel = mb->framebuffer_bpp;
331 VBEModeInfo.memory_model = VMEM_RGB;
332 VBEModeInfo.red_mask_size = mb->framebuffer_red_mask_size;
333 VBEModeInfo.red_field_position = mb->framebuffer_red_field_position;
334 VBEModeInfo.green_mask_size = mb->framebuffer_green_mask_size;
335 VBEModeInfo.green_field_position = mb->framebuffer_green_field_position;
336 VBEModeInfo.blue_mask_size = mb->framebuffer_blue_mask_size;
337 VBEModeInfo.blue_field_position = mb->framebuffer_blue_field_position;
338 VBEModeInfo.phys_base = mb->framebuffer_addr;
339 VBEModeInfo.linear_bytes_per_scanline = mb->framebuffer_pitch;
340 VBEModeInfo.linear_red_mask_size = mb->framebuffer_red_mask_size;
341 VBEModeInfo.linear_red_field_position = mb->framebuffer_red_field_position;
342 VBEModeInfo.linear_green_mask_size = mb->framebuffer_green_mask_size;
343 VBEModeInfo.linear_green_field_position = mb->framebuffer_green_field_position;
344 VBEModeInfo.linear_blue_mask_size = mb->framebuffer_blue_mask_size;
345 VBEModeInfo.linear_blue_field_position = mb->framebuffer_blue_field_position;
347 tag->ti_Tag = KRN_VBEModeInfo;
348 tag->ti_Data = KERNEL_OFFSET | (unsigned long)&VBEModeInfo;
349 tag++;
353 static void prepare_message(void *kick_base)
355 D(kprintf("[BOOT] Kickstart 0x%p - 0x%p (entry 0x%p), protection 0x%p - 0x%p\n", kernel_lowest(), kernel_highest(), kick_base,
356 &_prot_lo, &_prot_hi));
358 tag->ti_Tag = KRN_KernelBase;
359 tag->ti_Data = KERNEL_OFFSET | (unsigned long)kick_base;
360 tag++;
362 tag->ti_Tag = KRN_KernelLowest;
363 tag->ti_Data = KERNEL_OFFSET | (unsigned long)kernel_lowest();
364 tag++;
366 tag->ti_Tag = KRN_KernelHighest;
367 tag->ti_Data = KERNEL_OFFSET | (unsigned long)kernel_highest();
368 tag++;
370 tag->ti_Tag = KRN_KernelBss;
371 tag->ti_Data = KERNEL_OFFSET | (unsigned long)__bss_track;
372 tag++;
374 tag->ti_Tag = KRN_ProtAreaStart;
375 tag->ti_Data = (unsigned long)&_prot_lo;
376 tag++;
378 tag->ti_Tag = KRN_ProtAreaEnd;
379 tag->ti_Data = (unsigned long)&_prot_hi;
380 tag++;
382 tag->ti_Tag = TAG_DONE;
385 static void panic(const char *str)
387 kprintf("%s\n", str);
388 kprintf("*** SYSTEM PANIC!!! ***\n");
390 for(;;)
391 HALT;
395 * The entry point in C.
397 * The bootstrap routine has to load the kickstart at 0x01000000, with RO sections growing up the memory and
398 * RW sections stored beneath the 0x01000000 address. It is supposed to transfer the GRUB information further
399 * into the 64-bit kickstart.
401 * The kickstart is assembled from modules which have been loaded by GRUB. The modules may be loaded separately,
402 * or as a collection in PKG file. If some file is specified in both PKG file and list of separate modules, the
403 * copy in PKG will be skipped.
405 static void __attribute__((used)) __bootstrap(unsigned int magic, unsigned int addr)
407 struct multiboot *mb = (struct multiboot *)addr;/* Multiboot structure from GRUB */
408 struct module *mod = (struct module *)__stack; /* The list of modules at the bottom of stack */
409 char *vesa = NULL;
410 int module_count = 0;
411 void *kick_base = (void *)KERNEL_TARGET_ADDRESS;
412 struct module *m;
413 const char *cmdline = NULL;
414 struct mb_mmap *mmap = NULL;
415 unsigned long len = 0;
418 * We are loaded at 0x200000, so we can use one megabyte at 0x100000
419 * as our working area. Let's put console mirror there.
420 * I hope every PC has memory at this address.
422 fb_Mirror = (char *)0x100000;
423 con_InitMultiboot(mb);
425 kprintf("[BOOT] Entered AROS Bootstrap @ %p\n", __bootstrap);
426 D(kprintf("[BOOT] Stack @ %p, [%d bytes]\n", __stack, sizeof(__stack)));
427 D(kprintf("[BOOT] Multiboot structure @ %p\n", mb));
429 if (mb->flags & MB_FLAGS_CMDLINE)
431 cmdline = (const char *)mb->cmdline;
432 D(kprintf("[BOOT] Command line @ %p : '%s'\n", mb->cmdline, cmdline));
435 if (cmdline)
437 char *kern = strstr(cmdline, "base_address=");
439 if (kern)
441 unsigned long p = strtoul(&kern[13], NULL, 0);
443 if (p >= 0x00200000)
445 kick_base = (void *)p;
446 kprintf("[BOOT] Kernel base address changed to %p\n", kick_base);
448 else
449 kprintf("[BOOT] Kernel base address too low (%p). Keeping default.\n", p);
452 vesa = strstr(cmdline, "vesa=");
454 tag->ti_Tag = KRN_CmdLine;
455 tag->ti_Data = KERNEL_OFFSET | (unsigned long)cmdline;
456 tag++;
459 if ((mb->flags & MB_FLAGS_MMAP))
461 mmap = (struct mb_mmap *)mb->mmap_addr;
462 len = mb->mmap_length;
464 #ifdef DEBUG_MEM
465 kprintf("[BOOT] Memory map at 0x%p:\n", mmap);
466 while (len >= sizeof(struct mb_mmap))
468 #ifdef DEBUG_MEM_TYPE
469 if (mmap->type == DEBUG_MEM_TYPE)
470 #endif
471 kprintf("[BOOT] Type %d addr %llp len %llp\n", mmap->type, mmap->addr, mmap->len);
473 len -= mmap->size+4;
474 mmap = (struct mb_mmap *)(mmap->size + (unsigned long)mmap+4);
477 mmap = (struct mb_mmap *)mb->mmap_addr;
478 len = mb->mmap_length;
479 #endif
483 if (mb->flags & MB_FLAGS_MEM)
485 D(kprintf("[BOOT] Low memory %u KB, upper memory %u KB\n", mb->mem_lower, mb->mem_upper));
487 if (!mmap)
490 * To simplify things down, memory map is mandatory for our kickstart.
491 * So we create an implicit one if the bootloader didn't supply it.
493 D(kprintf("[BOOT] No memory map supplied by the bootloader, using defaults\n"));
495 MemoryMap[0].size = 20;
496 MemoryMap[0].addr = 0;
497 MemoryMap[0].len = mb->mem_lower << 10;
498 MemoryMap[0].type = MMAP_TYPE_RAM;
500 MemoryMap[1].size = 20;
501 MemoryMap[1].addr = 0x100000;
502 MemoryMap[1].len = mb->mem_upper << 10;
503 MemoryMap[1].type = MMAP_TYPE_RAM;
505 mmap = MemoryMap;
506 len = sizeof(MemoryMap);
509 /* Kickstart wants size in bytes */
510 tag->ti_Tag = KRN_MEMLower;
511 tag->ti_Data = mb->mem_lower << 10;
512 tag++;
514 tag->ti_Tag = KRN_MEMUpper;
515 tag->ti_Data = mb->mem_upper << 10;
516 tag++;
519 if (!mmap)
520 panic("No memory information provided by the bootloader");
522 tag->ti_Tag = KRN_MMAPAddress;
523 tag->ti_Data = KERNEL_OFFSET | (unsigned long)mmap;
524 tag++;
526 tag->ti_Tag = KRN_MMAPLength;
527 tag->ti_Data = len;
528 tag++;
531 * If vesa= option was given, set up the specified video mode explicitly.
532 * Otherwise specify to AROS what has been passed to us by the bootloader.
534 if (vesa)
535 setupVESA(&vesa[5]);
536 else
537 setupFB(mb);
539 /* Setup stage - prepare the environment */
540 setup_mmu(kick_base);
542 kprintf("[BOOT] Loading kickstart...\n");
543 set_base_address(kick_base, __bss_track);
545 /* Search for external modules loaded by GRUB */
546 module_count = find_modules(mb, mod);
548 if (module_count == 0)
549 panic("No kickstart modules found, nothing to run");
551 /* If any external modules are found, load them now */
552 for (m = mod; module_count > 0; module_count--, m++)
554 kprintf("[BOOT] Loading %s... ", m->name);
555 load_elf_file(m->address, 0);
556 kprintf("\n");
559 /* Prepare the rest of boot taglist */
560 prepare_message(kick_base);
562 #ifdef DEBUG_TAGLIST
563 kprintf("[BOOT] Boot taglist:\n");
564 for (tag = km; tag->ti_Tag != TAG_DONE; tag++)
565 kprintf("[BOOT] 0x%llp 0x%llp\n", tag->ti_Tag, tag->ti_Data);
566 #endif
568 /* Jump to the kickstart */
569 kick(km);
571 panic("Failed to run the kickstart");