Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / arch / i386-pc / exec / exec_init.c
blobdd66538bd1c3f1bd12b5c63b33463ad1874fe223
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Early bootup section
6 Lang: english
7 */
9 /*
10 AROS MemoryMap:
12 First 4KB of RAM (page 0x0000-0x0FFF) are READ ONLY!
14 +------------+-----------+-------------------------------------------------+
15 | address | length | description |
16 +------------+-----------+-------------------------------------------------+
17 | System page. Read only! Addresses undefined here are not allowed!!!! |
18 +------------------------+-------------------------------------------------+
19 | 0x00000004 | 0x0000004 | ExecBase pointer. |
20 | 0x00000020 | 0x0000020 | CPU information |
21 | 0x00000040 | 0x0000068 | TSS structure. Do not use! |
22 | 0x000000a8 | 0x0000004 | INT server! cached_irq_mask |
23 | 0x000000ac | 0x0000004 | INT server! io_apic_irqs |
24 | 0x00000100 | 0x0000800 | 256 interrupt vectors |
25 | 0x00000900 | 0x0000040 | Global Descriptor Table |<---- needs changed! - must have space for GDT x No CPUs (NicJA)
26 | 0x00000940 | 0x0000001 | INT server! softblock |
27 | 0x00000a00 | 0x0000200 | INT server! irq_desc[] |
28 +------------+-----------+-------------------------------------------------+
29 | 0x00001000 | 0x0001000 | MultiBoot information |
30 | 0x00002000 | ......... | System RAM |
31 | .......... | ......... | Temporary stack frame for bootup process |
32 ......0x0009e000 0x0001000 SMP Trampoline (NicJA)
33 | 0x000a0000 | 0x0060000 | Data reserved for BIOS, VGA and some MMIO cards |
34 ......0x000f7070 ACPI<-
35 1MB| 0x00100000 | ......... | AROS KERNEL |
36 | .......... | ......... | System RAM divided into DMA and rest. |
37 +------------+-----------+-------------------------------------------------+
38 0fef7f80
39 WARNING!
41 AROS Kernel will not be placed in first 1MB of ram anymore. Instead it
42 will be either somewhere in DMA memory (eg at 2nd MByte), at the end of
43 available memory or placed at Virtual address. Don't trust its position.
45 When ROM module called from loader, the ExecBase should be cleared.
47 This file has been completely rewritten from assembler source!
51 #include <exec/resident.h>
52 #include <exec/types.h>
53 #include <exec/nodes.h>
54 #include <exec/execbase.h>
55 #include <exec/memory.h>
56 #include <hardware/intbits.h>
57 #include <asm/segments.h>
58 #include <asm/linkage.h>
59 #include <asm/ptrace.h>
60 #include <dos/dosextens.h>
62 #include <aros/arossupportbase.h>
63 #include <aros/asmcall.h>
64 #include <aros/config.h>
66 #include <aros/kernel.h>
68 #define DEBUG 1
70 #include <aros/debug.h>
71 #include <aros/multiboot.h>
73 #include <utility/tagitem.h>
75 #include <hardware/custom.h>
76 #include <resources/acpi.h>
78 #include <proto/alib.h>
79 #include <proto/exec.h>
81 #include <stddef.h>
82 #include <stdio.h>
83 #include <string.h>
85 #include <inttypes.h>
87 #include LC_LIBDEFS_FILE
89 #include "etask.h"
90 #include "exec_intern.h"
91 #include "exec_util.h"
92 #include "memory.h"
93 #include "traps.h"
94 #include "vesa.h"
96 #define SMP_SUPPORT 0
99 * Here the history starts. We are already in flat, 32bit mode. All protections
100 * are off, CPU is working in Supervisor level (CPL0). This state can be emu-
101 * lated by ColdReboot() routine as it may freely use Supervisor()
103 * kernel_startup can be executed only from CPL0 without vmm. Interrupts should
104 * be disabled.
106 * Note that kernel_startup is declared as entry symbol for output ELF file.
109 asm( ".section .aros.init,\"ax\"\n\t.globl kernel_startup \n\t"
110 ".type kernel_startup,@function\n"
111 "kernel_startup: jmp exec_init\n\t.text");
114 #if SMP_SUPPORT
115 extern void prepare_primary_cpu(struct ExecBase *SysBase); /* FUNCTION FROM "cpu.resource"!!!!!!! */
116 #endif
118 /* As long as we don't have CPU detection routine, assume FPU to be present */
120 #define ASSUME_FPU 1
123 * Some macro definitions. __text will place given structure in .text section.
124 * __no_ret will force function type to be no-return function. __packed will
125 * force any structure to be non-aligned (we don't need alignment in native
126 * AROS).
129 #define __text __attribute__((section(".text")))
130 #define __no_ret __attribute__((noreturn))
131 #define __packed __attribute__((packed))
133 #define rdcr(reg) \
134 ({ long val; asm volatile("mov %%" #reg ",%0":"=r"(val)); val; })
136 #define wrcr(reg, val) \
137 do { asm volatile("mov %0,%%" #reg::"r"(val)); } while(0)
139 #define cpuid(num, eax, ebx, ecx, edx) \
140 do { asm volatile("cpuid":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx):"a"(num)); } while(0)
144 * Some declarations
146 void get_ACPI_RSDPTR(struct arosmb *mb);
147 void exec_init() __no_ret; /* init NEVER returns */
148 void exec_cinit() __no_ret; /* c-style init NEVER returns */
149 int exec_check_base();
150 void exec_DefaultTrap();
151 void exec_DefaultTaskExit();
152 //void exec_CheckCPU();
153 int exec_RamCheck_fast();
154 int exec_RamCheck_dma();
155 unsigned char setupVesa(struct multiboot *mbinfo);
158 asmlinkage void Exec_SystemCall(struct pt_regs);
159 ULONG **exec_RomTagScanner(struct ExecBase *, struct TagItem *);
160 void irqSetup(void);
162 extern const UBYTE LIBEND __text; /* Somewhere in library */
163 extern ULONG _edata,_end; /* They are standard for ELF */
164 extern const APTR LIBFUNCTABLE[] __text;
166 extern struct Library * PrepareAROSSupportBase (void);
167 extern ULONG SoftIntDispatch();
168 extern void AROS_SLIB_ENTRY(SerialRawIOInit, Exec, 84)();
169 extern void AROS_SLIB_ENTRY(SerialRawPutChar, Exec, 86)(UBYTE chr);
170 extern void AROS_SLIB_ENTRY(MemoryRawIOInit, Exec, 84)();
171 extern void AROS_SLIB_ENTRY(MemoryRawPutChar, Exec, 86)(UBYTE chr);
173 extern void AROS_SLIB_ENTRY(Switch_FPU, Exec, 9)();
174 extern void AROS_SLIB_ENTRY(PrepareContext_FPU, Exec, 6)();
175 extern void AROS_SLIB_ENTRY(Dispatch_FPU, Exec, 10)();
177 extern void AROS_SLIB_ENTRY(Switch_SSE, Exec, 9)();
178 extern void AROS_SLIB_ENTRY(PrepareContext_SSE, Exec, 6)();
179 extern void AROS_SLIB_ENTRY(Dispatch_SSE, Exec, 10)();
180 extern void AROS_SLIB_ENTRY(CopyMem_SSE, Exec, 104)();
182 extern ULONG Exec_15_MakeFunctions(APTR, APTR, APTR, APTR);
184 AROS_UFP5S(void, IntServer,
185 AROS_UFPA(ULONG, intMask, D0),
186 AROS_UFPA(struct Custom *, custom, A0),
187 AROS_UFPA(struct List *, intList, A1),
188 AROS_UFPA(APTR, intCode, A5),
189 AROS_UFPA(struct ExecBase *, SysBase, A6));
191 #undef memcpy
192 #define memcpy(_d, _s, _len) \
194 int len = _len; \
195 while (len) \
197 ((char *)_d)[len-1] = ((char *)_s)[len-1];\
198 len--; \
203 /* Temporary information */
205 #if 1
207 void clr();
208 void scr_RawPutChars(char *, int);
210 char tab[127];
212 #ifdef rkprintf
213 # undef rkprintf
214 #endif
215 #define rkprintf(x...) scr_RawPutChars(tab, snprintf(tab,126, x))
217 #else
219 #define clr() /* eps */
220 #define rkprintf(x...) /* eps */
222 #endif
225 * Make SysBase global. This way we will have no problems with all crapy modules
226 * which rely on global SysBase. They will get what they want - they will access
227 * it :)
230 asm( ".globl aros_intern\n\t"
231 ".globl SysBase \n\t"
232 ".set aros_intern,0\n\t"
233 ".set SysBase,4 ");
236 const char exec_core[] __text = "Native/CORE v2.0.1";
239 * First, we will define exec.library (global) to make it usable outside this
240 * file.
242 const char exec_name[] __text = "exec.library";
244 /* Now ID string as it will be used in a minute in resident structure. */
245 const char exec_idstring[] __text = VERSION_STRING;
247 /* We would need also version and revision fields placed somewhere here. */
248 const short exec_Version __text = VERSION_NUMBER;
249 const short exec_Revision __text = REVISION_NUMBER;
252 * The RomTag structure. It has to be placed inside .text block as there will
253 * be no public RomTagList. In future we may change RTC_MATCHWORD to be machine
254 * specific.
256 const struct Resident Exec_resident __text=
258 RTC_MATCHWORD, /* Magic value used to find resident */
259 &Exec_resident, /* Points to Resident itself */
260 (APTR)&LIBEND, /* Where could we find next Resident? */
261 0, /* There are no flags!! */
262 VERSION_NUMBER, /* Version */
263 NT_LIBRARY, /* Type */
264 126, /* Very high startup priority. */
265 (char *)exec_name, /* Pointer to name string */
266 (char *)exec_idstring, /* Ditto */
267 exec_init /* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
270 struct view { unsigned char sign; unsigned char attr; };
273 * Init the exec.library and as well whole system. This routine has to prepare
274 * all needed structures, GDT and IDT tables, TSS structure and many other.
276 * We have to use asm creature because there is no stack at the moment
278 asm("\nexec_init: \n\t"
279 "movl $0x93000,%esp\n\t" /* Start with setting up a temporary stack */
280 "pushl %edx \n\t" /* TagList from bootstrap */
281 "pushl %ebx \n\t" /* Then store the MultiBoot info pointer */
282 "pushl %eax \n\t" /* Store multiboot magic cookie */
283 "pushl $0x0 \n\t" /* And fake a C code call */
285 "cld \n\t" /* At the startup it's very important */
286 "cli \n\t" /* to lock all interrupts. Both on the */
287 "movb $-1,%al \n\t" /* CPU side and hardware side. We don't */
288 "outb %al,$0x21 \n\t" /* have proper structures in RAM yet. */
289 "outb %al,$0xa1 \n\n\t"
291 "jmp exec_cinit"); /* Jump to C function :))) */
294 * This routine is used by kernel to change all colors on the screen according
295 * to R,G,B values passed here
297 void exec_SetColors(char r, char g, char b)
299 int i;
300 short reg = 0x3c8; /* IO reg to control PEL */
302 asm("movb $0,%%al\n\t" /* Start with color 0 */
303 "outb %%al,%w0\n\t"
304 : /* no output */
305 : "Nd"(reg));
307 reg++; /* Here we have to put R, G, B */
309 for (i=0; i<256; i++) /* Set whole palette */
311 asm("outb %b0,%w1"::"a"(r),"Nd"(reg));
312 asm("outb %b0,%w1"::"a"(g),"Nd"(reg));
313 asm("outb %b0,%w1"::"a"(b),"Nd"(reg));
314 asm("nop \n\t"
315 "nop \n\t"
316 "nop \n\t"
317 "nop");
322 * Mixed stuff used to control TSS/GDT/IDT stuff. This is strictly machine
323 * specific
326 asm(".globl TSS\n\t" /* Make these three global in case one would */
327 ".globl SSP\n\t" /* decide to use them directly */
328 ".globl EIP\n\t"
329 ".set TSS, 0x00000040\n\t" /* See Memory Map at the top of the file */
330 ".set SSP, 0x00000044\n\t"
331 ".set EIP, 0x00000060");
334 * Two defines used to keep control over interrupt server
337 asm(".globl cached_irq_mask\n\t"
338 ".globl io_apic_irqs\n\t"
339 ".globl softblock\n\t"
340 ".globl irq_desc\n\t"
341 ".set cached_irq_mask, 0x000000a8\n\t"
342 ".set io_apic_irqs, 0x000000ac\n\t"
343 ".set softblock, 0x00000940\n\t"
344 ".set irq_desc, 0x00000a00");
347 * TaskStateStructure, defined only in matter of making life (setup)
348 * more human-readable
350 struct _tss {
351 ULONG link, /* link to previous task - UNUSED */
352 ssp, /* Supervisor Stack Pointer */
353 ssp_seg, /* SSP descriptor */
354 t0,t1, /* Stack for CPL1 code - USE IN FUTURE */
355 t2,t3, /* Stack for CPL2 code - UNUSED */
356 cr3, /* used in paging */
357 eip, /* Instruction pointer */
358 eflags, /* Flags for given task */
359 r0,r1,r2,r3, /* 8 general purpouse registers */
360 r4,r5,r6,r7,
361 es,cs,ss,ds,fs,gs, /* segment descriptors */
362 ldt; /* LocalDescriptorTable - UNUSED */
363 UWORD trap,iomap; /* trap flag and iomap pointer */
367 * Nice macro used for setting given gate to specified type.
368 * dpl is used to control access of this gate - setting to something
369 * lower than 3 makes gate impossible to use from User Mode
371 #define set_gate(gate_addr,type,dpl,addr) \
372 do { \
373 int __d0, __d1; \
374 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
375 "movw %4,%%dx\n\t" \
376 "movl %%eax,%0\n\t" \
377 "movl %%edx,%1" \
378 :"=m" (*((long *) (gate_addr))), \
379 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
380 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
381 "3" ((char *) (addr)),"2" (KERNEL_CS << 16)); \
382 } while (0)
384 /* Empty interrupt. Used for short while */
385 void exec_DummyInt();
386 asm("\nexec_DummyInt: iret");
389 * RO copy of GlobalDescriptorTable. It's easier to copy this table than
390 * to generate completely new one
392 const struct {UWORD l1, l2, l3, l4;}
393 GDT_Table[] __text = {
394 { 0x0000, 0x0000, 0x0000, 0x0000 },
395 { 0xffff, 0x0000, 0x9a00, 0x00cf },
396 { 0xffff, 0x0000, 0x9200, 0x00cf },
397 { 0xffff, 0x0000, 0xfa00, 0x00cf },
398 { 0xffff, 0x0000, 0xf200, 0x00cf },
399 { 0x0000, 0x0000, 0x0000, 0x0000 },
400 { 0x0067, 0x0040, 0x8900, 0x0000 },
401 { 0x0000, 0x0000, 0x0000, 0x0000 }};
403 /* Two magic registers pointing to Global Descriptor Table and Interrupt
404 * Descriptor Table */
405 const struct
407 UWORD l1 __packed;
408 ULONG l3 __packed;
410 GDT_reg __text = {0x3f, 0x900},
411 IDT_reg __text = {0x7ff, 0x100};
413 const char exec_chipname[] __text = "Chip Memory";
414 const char exec_fastname[] __text = "Fast Memory";
416 struct arosmb *arosmb;
419 * C/ASM mixed initialization routine. Here the real game begins...
421 void exec_cinit(unsigned long magic, unsigned long addr, struct TagItem *tags)
423 struct ExecBase *ExecBase;
424 struct multiboot *mbinfo;
426 ULONG locmem, extmem;
428 APTR KickMemPtr,
429 KickTagPtr,
430 KickCheckSum;
432 struct _tss *tss = (struct _tss *)0x40; /* Dummy pointer making life easier */
433 long long *idt = (long long *)0x100; /* Ditto */
435 int i; /* Whatever? Counter? Erm... */
437 // exec_SetColors(0x10,0x10,0x10); /* Set screen to almost black */
439 /* Check whether we have .bss block */
440 if ((int)&_end - (int)&_edata)
443 * Damn! We have to GET RID OF THIS!!! But now the only thing I can do
444 * is clearing it. GRUB have done it already but we have to repeat that
445 * (it may NEED that as it might be ColdReboot())
447 bzero(&_edata,(int)&_end-(int)&_edata);
450 clr();
451 rkprintf("AROS - The AROS Research OS\nCompiled %s\n\n",__DATE__);
453 /* MultiBoot
454 * This messy bit here will store away useful information we receive from
455 * the bootloader. It will happen when we are loaded, and not on when we
456 * are here from ColdReboot().
457 * This is just the first stage of it. Later this information will be extracted
458 * by bootloader.resource, but we do this here anyway. Both to keep the info
459 * safe, and also since we will use some of it in here.
461 arosmb = (struct arosmb *)0x1000;
462 if (magic == 0x2badb002)
464 mbinfo = (struct multiboot *)addr;
465 if (mbinfo->flags & MB_FLAGS_CMDLINE)
466 arosmb->vbe_palette_width = setupVesa(mbinfo);
467 rkprintf("Copying multiboot information into storage\n");
468 arosmb->magic = MBRAM_VALID;
469 arosmb->flags = 0L;
470 if (mbinfo->flags & MB_FLAGS_MEM)
472 arosmb->flags |= MB_FLAGS_MEM;
473 arosmb->mem_lower = mbinfo->mem_lower;
474 arosmb->mem_upper = mbinfo->mem_upper;
476 if (mbinfo->flags & MB_FLAGS_LDRNAME)
478 arosmb->flags |= MB_FLAGS_LDRNAME;
479 snprintf(arosmb->ldrname,29,"%s",(char *)mbinfo->loader_name);
481 if (mbinfo->flags & MB_FLAGS_CMDLINE)
483 arosmb->flags |= MB_FLAGS_CMDLINE;
484 snprintf(arosmb->cmdline,199,"%s",(char *)mbinfo->cmdline);
486 if (mbinfo->flags & MB_FLAGS_MMAP)
488 arosmb->flags |= MB_FLAGS_MMAP;
489 arosmb->mmap_addr = ((IPTR)(0x1000 + sizeof(struct arosmb)));
490 arosmb->mmap_len = mbinfo->mmap_length;
491 memcpy((void *)arosmb->mmap_addr,(void *)mbinfo->mmap_addr,mbinfo->mmap_length);
493 if (mbinfo->flags & MB_FLAGS_DRIVES)
495 if (mbinfo->drives_length > 0)
497 arosmb->flags |= MB_FLAGS_DRIVES;
498 arosmb->drives_addr = ((ULONG)(arosmb->mmap_addr + arosmb->mmap_len));
499 arosmb->drives_len = mbinfo->drives_length;
500 memcpy((void *)arosmb->drives_addr,(void *)mbinfo->drives_addr,mbinfo->drives_length);
503 if (mbinfo->flags & MB_FLAGS_GFX)
505 arosmb->flags |= MB_FLAGS_GFX;
506 arosmb->vbe_mode = mbinfo->vbe_mode;
507 memcpy((void *)&arosmb->vmi,(void *)mbinfo->vbe_mode_info,sizeof(struct vbe_mode));
508 memcpy((void *)&arosmb->vci,(void *)mbinfo->vbe_control_info,sizeof(struct vbe_controller));
511 rkprintf("Done\n");
513 /* TODO: WE MUST PARSE THE BIOS MEMORY MAP HERE AND PROTECT NECESSARY STRUCTS (i.e ACPI stores its data in the last few meg of physical ram..) */
515 /* save the RSP PTR */
516 get_ACPI_RSDPTR(arosmb);
518 rkprintf("Clearing system area...");
521 * Well, if we all in clearing moode, then it's the best occasion to clear
522 * some areas in AROS private 4KB ram area. Hmmm. If there would occur any
523 * interrupt at this moment, AROS would be really dead as it is going to
524 * destroy its private stuff (which is really needed to make CPU operate
525 * properly)
527 bzero((void *)8, 4096-8);
530 * Feel better? Now! Quick. We will have to build new tables for our CPU to
531 * make it work nicely.
533 tss->ssp = 0x00090000; /* temporary Supervisor Stack Pointer */
534 tss->ssp_seg = KERNEL_DS; /* SSP segment descriptor */
535 tss->cs = USER_CS;
536 tss->ds = USER_DS;
537 tss->es = USER_DS;
538 tss->ss = USER_DS;
539 tss->iomap = 104;
541 /* Restore IDT structure. */
542 for (i=0; i<256; i++)
544 /* Feed all vectors with dummy interrupt */
545 set_gate(idt + i, 14, 0, exec_DummyInt);
549 * Fix Global Descriptor Table. Because I'm too lazy I'll just copy one from
550 * here. I've already prepared such a nice one :)
552 memcpy((void *)0x900, &GDT_Table, 64);
555 * As we prepared all necessary stuff, we can hopefully load GDT and LDT
556 * into CPU. We may also play a bit with TSS
558 asm("lgdt %0\n\t"
559 "lidt %1"
561 :"m"(GDT_reg),"m"(IDT_reg));
563 asm("mov %0,%%ds\n\t" /* Now it's high time to set segment */
564 "mov %0,%%es\n\t" /* registers (segment descriptors). */
565 "mov %0,%%ss\n\t" /* AROS uses only %CS %SS %DS and %ES */
566 "mov %1,%%fs\n\t" /* %FS and %GS are set to 0 so we can */
567 "mov %1,%%gs\n\t" /* generate GP if someone uses them. */
568 "ljmp %2,$1f\n1:\n\t" /* And finally, set the %CS!!! */
570 :"a"(KERNEL_DS),"b"(0),"i"(KERNEL_CS));
572 asm("ltr %%ax"::"ax"(0x30));
574 rkprintf("OK\nSystem restored\n");
577 * Wew have to do some stuff from setup.S due to remove of it.
579 * Remap IRQs. We really HAVE TO do that because IBM did it in a very bad
580 * way - they've ignored what Intel said about interrupts. See intel manual
581 * for further information.
582 * For now all irq's are placed in range 0x20 - 0x30 as vectors 0x00 - 0x1f
583 * are reserved by Intel
585 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0x20)); /* Initialization sequence for 8259A-1 */
586 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0xa0)); /* Initialization sequence for 8259A-2 */
587 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x20),"i"(0x21)); /* IRQs at 0x20 - 0x27 */
588 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x28),"i"(0xa1)); /* IRQs at 0x28 - 0x2f */
589 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x04),"i"(0x21)); /* 8259A-1 is master */
590 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x02),"i"(0xa1)); /* 8259A-2 is slave */
591 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0x21)); /* 8086 mode for both */
592 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0xa1));
593 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0x21)); /* Enable cascade int */
594 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0xa1)); /* Mask all interrupts */
596 rkprintf("Interrupts redirected\n");
599 // for(;;);
602 * Check for valid ExecBase. This is quite important part, because this way
603 * we may determine whether to clear and reconfigure memory or whether we
604 * already know everything and may continue further initialisation.
606 if (!exec_check_base())
608 ULONG negsize = 0; /* size of vector table */
609 void **fp = (void **)LIBFUNCTABLE; /* pointer to a function in the table */
611 rkprintf("Reallocating ExecBase...");
613 * If we managed to reach this point, it means that there was no ExecBase in
614 * the memory. That means that we have to calculate amount of memory available.
616 * We will guess ExecBase pointer by taking the lowest possible address and
617 * subtracting from it the offset of lowest vector used by Exec. This way the ExecBase
618 * will be placed in the lowest address possible while fitting all functions :)
621 /* Calculate the size of the vector table */
622 while (*fp++ != (VOID *) -1) negsize += LIB_VECTSIZE;
624 ExecBase = (struct ExecBase *) 0x00002000; /* Got ExecBase at the lowest possible addr */
625 ExecBase += negsize; /* Subtract lowest vector so jump table would fit */
627 /* Check whether we have some FAST memory,
628 * If not, then use calculated ExecBase */
629 if ((extmem = exec_RamCheck_fast(arosmb)))
631 rkprintf("%x Fastmem\n",extmem);
632 /* We have found some FAST memory. Let's use it for ExecBase */
633 ExecBase = (struct ExecBase *) 0x01000000;
634 ExecBase += negsize;
637 /* Clear portion of ExecBase that won't be cleared later */
638 bzero(ExecBase, offsetof(struct ExecBase, IntVects[0]));
641 * Now, ExecBase is reserved and partially cleared. We have only to
642 * determine how much CHIP memory we have.
645 locmem = exec_RamCheck_dma(arosmb);
646 rkprintf("%x Chipmem\n",locmem);
648 rkprintf("OK\nExecBase=%p\n", ExecBase);
650 else
652 ExecBase = *(struct ExecBase **)4UL;
654 locmem = ExecBase->MaxLocMem;
655 extmem = (ULONG)ExecBase->MaxExtMem;
657 rkprintf("Got old ExecBase = %p\n",ExecBase);
660 * We happen to be here with local ExecBase properly set as well as
661 * local locmem and extmem
664 // exec_SetColors(0x20,0x20,0x20);
666 /* Store this values as they may point to interesting stuff */
667 KickMemPtr = ExecBase->KickMemPtr;
668 KickTagPtr = ExecBase->KickTagPtr;
669 KickCheckSum = ExecBase->KickCheckSum;
671 rkprintf("Clearing ExecBase\n");
673 /* How about clearing most of ExecBase structure? */
674 bzero(&ExecBase->IntVects[0], sizeof(struct IntExecBase) - offsetof(struct ExecBase, IntVects[0]));
676 ExecBase->KickMemPtr = KickMemPtr;
677 ExecBase->KickTagPtr = KickTagPtr;
678 ExecBase->KickCheckSum = KickCheckSum;
681 * Now everything is prepared to store ExecBase at the location 4UL and set
682 * it complement in ExecBase structure
685 rkprintf("Initializing library...");
687 *(struct ExecBase **)4 = ExecBase;
688 ExecBase->ChkBase = ~(ULONG)ExecBase;
690 /* Set up system stack */
691 tss->ssp = (extmem) ? extmem : locmem; /* Either in FAST or in CHIP */
692 ExecBase->SysStkUpper = (APTR)tss->ssp;
693 ExecBase->SysStkLower = (APTR)tss->ssp - 0x10000; /* 64KB of system stack */
695 /* Store memory configuration */
696 ExecBase->MaxLocMem = (IPTR)locmem;
697 ExecBase->MaxExtMem = (APTR)extmem;
699 /* TODO: Write first step of alert.hook here!!! */
702 * Initialize exec lists. This is done through information table which consist
703 * of offset from begining of ExecBase and type of the list.
705 NEWLIST(&ExecBase->MemList);
706 ExecBase->MemList.lh_Type = NT_MEMORY;
707 NEWLIST(&ExecBase->ResourceList);
708 ExecBase->ResourceList.lh_Type = NT_RESOURCE;
709 NEWLIST(&ExecBase->DeviceList);
710 ExecBase->DeviceList.lh_Type = NT_DEVICE;
711 NEWLIST(&ExecBase->LibList);
712 ExecBase->LibList.lh_Type = NT_LIBRARY;
713 NEWLIST(&ExecBase->PortList);
714 ExecBase->PortList.lh_Type = NT_MSGPORT;
715 NEWLIST(&ExecBase->TaskReady);
716 ExecBase->TaskReady.lh_Type = NT_TASK;
717 NEWLIST(&ExecBase->TaskWait);
718 ExecBase->TaskWait.lh_Type = NT_TASK;
719 NEWLIST(&ExecBase->IntrList);
720 ExecBase->IntrList.lh_Type = NT_INTERRUPT;
721 NEWLIST(&ExecBase->SemaphoreList);
722 ExecBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
723 NEWLIST(&ExecBase->ex_MemHandlers);
725 for (i=0; i<5; i++)
727 NEWLIST(&ExecBase->SoftInts[i].sh_List);
728 ExecBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
732 * Exec.library initializer. Prepares exec.library for future use. All
733 * lists have to be initialized, some values from ROM are copied.
736 ExecBase->TaskTrapCode = exec_DefaultTrap;
737 ExecBase->TaskExceptCode = exec_DefaultTrap;
738 ExecBase->TaskExitCode = exec_DefaultTaskExit;
739 ExecBase->TaskSigAlloc = 0x0000ffff;
740 ExecBase->TaskTrapAlloc = 0x8000;
742 /* Prepare values for execBase (like name, type, pri and other) */
744 ExecBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
745 ExecBase->LibNode.lib_Node.ln_Pri = 0;
746 ExecBase->LibNode.lib_Node.ln_Name = (char *)exec_name;
747 ExecBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
748 ExecBase->LibNode.lib_PosSize = sizeof(struct IntExecBase);
749 ExecBase->LibNode.lib_OpenCnt = 1;
750 ExecBase->LibNode.lib_IdString = (char *)exec_idstring;
751 ExecBase->LibNode.lib_Version = exec_Version;
752 ExecBase->LibNode.lib_Revision = exec_Revision;
754 ExecBase->Quantum = 4;
755 ExecBase->VBlankFrequency = 50;
756 ExecBase->PowerSupplyFrequency = 1;
758 NEWLIST(&PrivExecBase(ExecBase)->ResetHandlers);
759 NEWLIST(&PrivExecBase(ExecBase)->AllocMemList);
761 rkprintf("OK\nBuilding JumpTable...");
763 /* Build the jumptable */
764 ExecBase->LibNode.lib_NegSize =
765 Exec_15_MakeFunctions(ExecBase, (APTR)LIBFUNCTABLE, NULL, ExecBase);
767 rkprintf("OK\n");
769 InitSemaphore(&PrivExecBase(ExecBase)->MemListSem);
770 InitSemaphore(&PrivExecBase(ExecBase)->LowMemSem);
772 /* Enable mungwall before the first allocation call */
773 if (strstr(arosmb->cmdline, "mungwall"))
774 PrivExecBase(SysBase)->IntFlags = EXECF_MungWall;
776 /* Add FAST memory at 0x01000000 to free memory lists */
777 if (extmem)
779 ULONG base = ((ULONG)ExecBase + sizeof(struct IntExecBase) + 15) & ~15;
781 AddMemList(extmem - (base + 0x10000),
782 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
784 (APTR)base,
785 (STRPTR)exec_fastname);
787 AddMemList(locmem - 0x2000,
788 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
789 -10,
790 (APTR)0x2000,
791 (STRPTR)exec_chipname);
793 rkprintf("Chip Memory : %uMB\nFast Memory : %uMB\n",
794 locmem >> 20, (extmem - locmem) >> 20);
796 else
798 ULONG base = ((ULONG)ExecBase + sizeof(struct IntExecBase) + 15) & ~15;
799 AddMemList(locmem - (base + 0x10000),
800 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
801 -10,
802 (APTR)base,
803 (STRPTR)exec_chipname);
805 rkprintf("Chip Memory : %uMB\n", locmem >> 20);
808 rkprintf("Memory added\n");
810 /* Protect kernel and RO data from being allocated by software */
811 IPTR kernel_highest =
812 LibGetTagData(KRN_KernelHighest, (ULONG)&_end, tags);
813 IPTR kernel_lowest =
814 LibGetTagData(KRN_KernelLowest, (ULONG)&_end - 0x000a0000, tags);
815 InternalAllocAbs((APTR)kernel_lowest, kernel_highest - kernel_lowest, ExecBase);
817 /* Protect bootup stack from being allocated */
818 InternalAllocAbs((APTR)0x90000, 0x3000, SysBase);
820 /* Protect ACPI & other spaces returned by GRUB loader */
822 /* Protect the RSD PTR which is always in the first MB for later use */
823 if(arosmb->acpirsdp)
824 InternalAllocAbs((APTR)arosmb->acpirsdp, arosmb->acpilength, ExecBase);
827 // tcheko : GRUB returns end of uppermem (fastmem) always lower than ACPI table data
828 // protecting TYPE_RESERVED hangs boot process
830 struct mb_mmap* mmap = arosmb->mmap_addr;
831 for (mmap = (struct mb_mmap *) arosmb->mmap_addr;
832 (unsigned long) mmap < arosmb->mmap_addr + arosmb->mmap_len;
833 mmap = (struct mb_mmap *) ((unsigned long) mmap + mmap->size + sizeof (mmap->size)))
835 if(mmap->type == MMAP_TYPE_ACPIDATA)
837 rkprintf("Protecting ACPI DATA memory space (%x:%lu)\n", mmap->addr_low, mmap->len_low);
838 InternalAllocAbs(mmap->addr_low, mmap->len_low, ExecBase);
840 if(mmap->type == MMAP_TYPE_ACPINVS)
842 rkprintf("Protecting ACPI NVS memory space (%x:%lu)\n", mmap->addr_low, mmap->len_low);
843 InternalAllocAbs(mmap->addr_low, mmap->len_low, ExecBase);
845 if(mmap->type == MMAP_TYPE_RESERVED)
847 rkprintf("Protecting reserved memory space (%x:%lu)\n", mmap->addr_low, mmap->len_low);
848 InternalAllocAbs(mmap->addr_low, mmap->len_low, ExecBase);
853 rkprintf("Kernel protected\n");
856 rkprintf("Adding \"exec.library\"...");
858 /* Add exec.library to system library list */
859 SumLibrary((struct Library *)SysBase);
860 Enqueue(&SysBase->LibList,&SysBase->LibNode.lib_Node);
862 rkprintf("OK\n");
864 ExecBase->DebugAROSBase = PrepareAROSSupportBase();
866 #if SMP_SUPPORT
867 /* Early Boot CPU preperation.. */
868 prepare_primary_cpu( ExecBase );
869 #endif
871 rkprintf( "[CPU] Primary CPU Probed ..\n" );
873 for (i=0; i<16; i++)
875 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
877 struct Interrupt *is;
878 struct SoftIntList *sil;
879 is = AllocMem
881 sizeof(struct Interrupt) + sizeof(struct SoftIntList),
882 MEMF_CLEAR | MEMF_PUBLIC
884 if( is == NULL )
886 rkprintf("ERROR: Cannot install Interrupt Servers!\n");
888 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
890 is->is_Code = &IntServer;
891 is->is_Data = sil;
892 NEWLIST((struct List *)sil);
893 SetIntVector(i,is);
895 else
897 struct Interrupt *is;
898 switch (i)
900 case INTB_SOFTINT :
901 is = AllocMem
903 sizeof(struct Interrupt),
904 MEMF_CLEAR | MEMF_PUBLIC
906 if (is == NULL)
908 rkprintf("Error: Cannot install Interrupt Servers!\n");
909 // Alert(AT_DeadEnd | AN_IntrMem);
911 is->is_Node.ln_Type = NT_SOFTINT; //INTERRUPT;
912 is->is_Node.ln_Pri = 0;
913 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
914 is->is_Data = NULL;
915 is->is_Code = (void *)SoftIntDispatch;
916 SetIntVector(i,is);
917 break;
922 /* TODO: Write CPU detailed detection scheme. Patch proper functions?? */
924 Init_Traps();
925 irqSetup();
926 rkprintf("IRQ services initialized\n");
928 /* Create user interrupt used to enter supervisor mode */
929 set_gate(idt + 0x80, 14, 3, Exec_SystemCall);
931 /* Enable interrupts and set int disable level to -1 */
932 asm("sti");
933 ExecBase->TDNestCnt = -1;
934 ExecBase->IDNestCnt = -1;
936 /* Now it's time to calculate exec checksum. It will be used
937 * in future to distinguish whether we'd had proper execBase
938 * before restart */
940 UWORD sum=0, *ptr = &ExecBase->SoftVer;
941 int i=((int)&ExecBase->IntVects[0] - (int)&ExecBase->SoftVer) / 2,
944 /* Calculate sum for every static part from SoftVer to ChkSum */
945 for (j=0;j < i;j++)
947 sum+=*(ptr++);
950 ExecBase->ChkSum = ~sum;
953 rkprintf("Creating the very first task...");
955 /* Create boot task. Sigh, we actually create a Process sized Task,
956 since DOS needs to call things which think it has a Process and
957 we don't want to overwrite memory with something strange do we?
959 We do this until at least we can boot dos more cleanly.
962 struct Task *t;
963 struct MemList *ml;
965 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
966 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
968 if( !ml || !t )
970 rkprintf("ERROR: Cannot create Boot Task!\n");
972 ml->ml_NumEntries = 1;
973 ml->ml_ME[0].me_Addr = t;
974 ml->ml_ME[0].me_Length = sizeof(struct Process);
976 NEWLIST(&t->tc_MemEntry);
977 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
979 /* It's the boot process that RunCommand()s the boot shell, so we
980 must have this list initialized */
981 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
983 AddHead(&t->tc_MemEntry,&ml->ml_Node);
985 t->tc_Node.ln_Name = (char *)exec_name;
986 t->tc_Node.ln_Pri = 0;
987 t->tc_Node.ln_Type = NT_TASK;
988 t->tc_State = TS_RUN;
989 t->tc_SigAlloc = 0xFFFF;
990 t->tc_SPLower = 0; /* This is the system's stack */
991 t->tc_SPUpper = (APTR)~0UL;
992 t->tc_Flags |= TF_ETASK;
994 if (t->tc_Flags & TF_ETASK)
996 t->tc_UnionETask.tc_ETask = AllocVec
998 sizeof(struct IntETask),
999 MEMF_ANY|MEMF_CLEAR
1002 if (!t->tc_UnionETask.tc_ETask)
1004 rkprintf("Not enough memory for first task\n");
1007 /* Initialise the ETask data. */
1008 InitETask(t, t->tc_UnionETask.tc_ETask);
1010 GetIntETask(t)->iet_Context = AllocTaskMem(t
1011 , SIZEOF_ALL_REGISTERS
1012 , MEMF_PUBLIC|MEMF_CLEAR
1015 if (!GetIntETask(t)->iet_Context)
1017 rkprintf("Not enough memory for first task\n");
1021 ExecBase->ThisTask = t;
1024 rkprintf("Done\n");
1027 Check whether the CPU supports SSE and FXSAVE.
1029 Dirty check, without use of any defines and human readable constants. The
1030 cpuid instruction with %eax=1 will return some essential cpu informations in %edx back,
1031 including:
1032 - bit 24: CPU does support FXSAVE and FXRSTOR for MMX/FPU/SSE context saving and restoring
1033 - bit 25: CPU supports SSE
1034 - bit 26: CPU supports SSE2
1037 ULONG v1,v2,v3,v4;
1038 cpuid(1, v1,v2,v3,v4);
1040 rkprintf("cpuid 1 = %08x %08x %08x %08x\n", v1, v2, v3, v4);
1042 if (v4 & (1 << 24))
1044 rkprintf("The CPU supports FXSAVE and FXRSTOR. Good.\n");
1045 rkprintf("CPU Supports ");
1047 switch ((v4 >> 25) & 3)
1049 case 3:
1050 case 2:
1051 rkprintf("SSE2 ");
1052 case 1:
1053 rkprintf("SSE\n");
1054 /* Patch exec with some SSE-aware functions */
1055 SetFunction(&ExecBase->LibNode, -6*LIB_VECTSIZE, AROS_SLIB_ENTRY(PrepareContext_SSE, Exec, 6));
1056 SetFunction(&ExecBase->LibNode, -9*LIB_VECTSIZE, AROS_SLIB_ENTRY(Switch_SSE, Exec, 9));
1057 SetFunction(&ExecBase->LibNode, -10*LIB_VECTSIZE, AROS_SLIB_ENTRY(Dispatch_SSE, Exec, 10));
1058 SetFunction(&ExecBase->LibNode, -104*LIB_VECTSIZE, AROS_SLIB_ENTRY(CopyMem_SSE, Exec, 104));
1059 SetFunction(&ExecBase->LibNode, -105*LIB_VECTSIZE, AROS_SLIB_ENTRY(CopyMem_SSE, Exec, 104));
1060 /* tell the CPU that we will support SSE */
1061 wrcr(cr4, rdcr(cr4) | (3 << 9));
1062 /* Clear the EM and MP flags of CR0 */
1063 wrcr(cr0, rdcr(cr0) & ~6);
1064 rkprintf("SSE enabled.\n");
1065 break;
1067 default:
1069 Ha! Bloody PentiumII does supports MMX/FPU/SSE saving instructions,
1070 but it does not support SSE
1072 rkprintf("no SSE. Sorry :)\n");
1073 break;
1076 else
1078 #if ASSUME_FPU
1079 SetFunction(&ExecBase->LibNode, -6*LIB_VECTSIZE, AROS_SLIB_ENTRY(PrepareContext_FPU, Exec, 6));
1080 SetFunction(&ExecBase->LibNode, -9*LIB_VECTSIZE, AROS_SLIB_ENTRY(Switch_FPU, Exec, 9));
1081 SetFunction(&ExecBase->LibNode, -10*LIB_VECTSIZE, AROS_SLIB_ENTRY(Dispatch_FPU, Exec, 10));
1083 rkprintf("FPU enabled.\n");
1084 #endif
1088 rkprintf("Jumping out from Supervisor mode...");
1090 #if 0
1092 asm("mov %0,%%ds\n\t" /* User DS */
1093 "mov %0,%%es\n\t" /* User ES */
1094 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1095 "pushl %0\n\t" /* User SS */
1096 "pushl %%ebx\n\t" /* Stack frame */
1097 "pushl $0x3002\n\t" /* IOPL:3 */
1098 "pushl %1\n\t" /* User CS */
1099 "pushl $1f\n\t" /* Entry address */
1100 "iret\n" /* Go down to the user mode */
1101 "1:\tsti" /* Enable interrupts */
1103 : "eax"(USER_DS),"ecx"(USER_CS));
1104 #else
1105 # define _stringify(x) #x
1106 # define stringify(x) _stringify(x)
1108 asm("movl $" stringify(USER_DS) ",%%eax\n\t"
1109 "mov %%eax,%%ds\n\t" /* User DS */
1110 "mov %%eax,%%es\n\t" /* User ES */
1111 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1112 "pushl %%eax\n\t" /* User SS */
1113 "pushl %%ebx\n\t" /* Stack frame */
1114 "pushl $0x3002\n\t" /* IOPL:3 */
1115 "pushl $" stringify(USER_CS) "\n\t" /* User CS */
1116 "pushl $1f\n\t" /* Entry address */
1117 "iret\n" /* Go down to the user mode */
1118 "1:\tsti":::"eax","ebx"); /* Enable interrupts */
1120 # undef stringify
1121 # undef _stringify
1122 #endif
1124 rkprintf("Done\n");
1126 ExecBase->TDNestCnt++;
1127 Permit();
1129 /* Enable type of debug output chosen by user */
1130 if (strstr(arosmb->cmdline, "debug=serial"))
1132 SetFunction(&ExecBase->LibNode, -84 * LIB_VECTSIZE,
1133 AROS_SLIB_ENTRY(SerialRawIOInit, Exec, 84));
1134 SetFunction(&ExecBase->LibNode, -86 * LIB_VECTSIZE,
1135 AROS_SLIB_ENTRY(SerialRawPutChar, Exec, 86));
1137 else if (strstr(arosmb->cmdline, "debug=memory"))
1139 SetFunction(&ExecBase->LibNode, -84 * LIB_VECTSIZE,
1140 AROS_SLIB_ENTRY(MemoryRawIOInit, Exec, 84));
1141 SetFunction(&ExecBase->LibNode, -86 * LIB_VECTSIZE,
1142 AROS_SLIB_ENTRY(MemoryRawPutChar, Exec, 86));
1144 PrivExecBase(SysBase)->PageSize = MEMCHUNK_TOTAL; /* temp fix for debug=memory */
1145 RawIOInit();
1147 /* Scan for valid RomTags */
1148 ExecBase->ResModules = exec_RomTagScanner(ExecBase, tags);
1150 if (ExecBase->CoolCapture)
1152 void (*p)() = ExecBase->CoolCapture;
1153 (*p)();
1156 InitCode(RTF_SINGLETASK, 0);
1157 KernelBase = OpenResource("kernel.resource");
1158 PrivExecBase(SysBase)->PageSize = MEMCHUNK_TOTAL;
1159 InitCode(RTF_COLDSTART, 0);
1162 * We suppose that at this point dos.library has already taken over.
1163 * The last thing to do is to call WarmCapture vector. After that this
1164 * task has completely nothing to do so it may execute Debug() in
1165 * forever loop
1168 if (ExecBase->WarmCapture)
1170 void (*p)() = ExecBase->WarmCapture;
1171 (*p)();
1174 do { Debug(0); } while(1);
1177 /* Small delay routine used by exec_cinit initializer */
1178 asm("\ndelay:\t.short 0x00eb\n\tret");
1180 /* Exec default trap routine */
1181 asm("\nexec_DefaultTrap:\n\t"
1182 "popl %eax\n\t"
1183 "popl %eax\n\t"
1184 "pushl 4\n\t"
1185 "pushl %eax\n\t"
1186 "call Exec_18_Alert");
1190 void get_ACPI_RSDPTR(struct arosmb* mb)
1192 unsigned char *j, *k, sum=0;
1194 /* Finding RSD PTR */
1195 for (j = (unsigned char*)0x000E0000; j < (unsigned char*)(0x000E0000 + 0x00020000); j += 16)
1198 /* The signature and checksum must both be correct */
1199 if(j[0] == 'R' && j[1] == 'S' && j[2] == 'D' && j[3] == ' ' && j[4] == 'P' && j[5] == 'T' && j[6] == 'R' && j[7] == ' ')
1202 /* We have the signature, let's check the checksum*/
1203 k = j + ((((struct ACPI_TABLE_TYPE_RSDP*)j)->revision < 2)?20:36); /* revision is stored at index 15 */
1205 for (; j < k; sum += *(j++));
1207 if(!sum)
1209 rkprintf("ACPI RSD PTR address found at %p!\n", j);
1210 mb->acpirsdp = (IPTR)j;
1211 mb->acpilength = (((struct ACPI_TABLE_TYPE_RSDP*)j)->revision < 2)?20:36;
1212 break;
1214 else
1216 rkprintf("Wrong ACPI RSDP checksum\n");
1217 break;
1225 /* TODO: We should use info from BIOS here. */
1226 int exec_RamCheck_dma(struct arosmb *arosmb)
1228 ULONG volatile *ptr,tmp;
1230 ptr = (ULONG *)(((int)&_end + 0x0FFF) &~0x0FFF);
1232 if(arosmb->flags & MB_FLAGS_MEM)
1234 /* If there is upper memory, assume that lower is 1MB. Dirty hack++ */
1235 if(arosmb->mem_upper)
1237 if ((arosmb->mem_upper<<10) & 0xff000000)
1239 /* More than 16MB in total, return 16 */
1240 return 16<<20;
1242 /* Lower 16MB is marked as DMA memory */
1243 tmp = (arosmb->mem_upper * 1024) & 0x00ffffff;
1244 tmp += 0x100000;
1245 return tmp;
1247 else
1249 /* No upper memory, return only lower mem.
1250 * Most likely fatal, can't see aros working with less than one MB of ram */
1251 return (arosmb->mem_lower * 1024);
1254 /* No memory info from bios, do a scan */
1257 tmp = *ptr;
1258 *ptr = 0xdeadbeef;
1259 if (*ptr != 0xdeadbeef)
1260 break;
1261 *ptr = tmp;
1262 ptr += 4;
1263 } while ((int)ptr < 0x01000000);
1265 return (int)ptr;
1268 int exec_RamCheck_fast(struct arosmb *arosmb)
1270 ULONG volatile *ptr, tmp;
1272 ptr = (ULONG *)0x01000000;
1274 if(arosmb->flags & MB_FLAGS_MEM)
1276 /* If less than 15MB upper, no fastmem here */
1277 if ((arosmb->mem_upper * 1024) <= 0xF00000)
1279 return 0;
1281 /* Found memory, so we need to do some quick math */
1282 tmp = (arosmb->mem_upper * 1024) + 0x100000;
1283 return tmp;
1285 /* No memory info from bios, do a scan */
1288 tmp = *ptr;
1289 *ptr = 0xdeadbeef;
1290 if (*ptr != 0xdeadbeef)
1291 break;
1292 *ptr = tmp;
1293 ptr += 4;
1294 } while(1);
1296 return ((int)ptr > 0x01000000) ? (int)ptr : 0;
1299 void exec_DefaultTaskExit()
1301 struct ExecBase *SysBase = *(struct ExecBase **)4UL;
1302 RemTask(SysBase->ThisTask);
1306 * Check for valid ExecBase
1308 int exec_check_base()
1310 /* Get ExecBase from 0x00000004 */
1311 struct ExecBase *ExecBase=*(struct ExecBase **)4UL;
1313 /* Attempt first test. If ExecBase is not aligned to 4 byte boundary then
1314 * it is not proper ExecBase */
1315 if (!((ULONG)ExecBase & 0x3))
1318 * Assume for a while, that it is ExecBase indeed. Check complement of
1319 * this pointer, which is stored in ExecBase->ChkBase
1321 if (!~((LONG)ExecBase + ExecBase->ChkBase))
1324 * Still here? Nice, let's check one more thing. Static part of
1325 * ExecBase has its checksum calculated. Verify it please...
1327 UWORD sum=0, *ptr = &ExecBase->SoftVer;
1328 int i=((int)&ExecBase->IntVects[0] - (int)&ExecBase->SoftVer) / 2,
1331 /* Calculate sum for every static part from SoftVer to ChkSum */
1332 for (j=0;j < i;j++)
1334 sum+=*(ptr++);
1337 /* Do we have proper checksum? */
1338 if (!~sum)
1340 /* Well well, almost sure that we have ExecBase here. Hey, it's
1341 * time to execute ColdCapture code! */
1342 void (*p)() = ExecBase->ColdCapture;
1344 /* Only if there is ColdCapture code... */
1345 if (p)
1347 ExecBase->ColdCapture = NULL;
1348 (*p)();
1352 * Let's check ExecBase last time. Compare library version and
1353 * revision vs ones stored deep in the core. If they will differ
1354 * then ExecBase is damaged
1357 if ((ExecBase->LibNode.lib_Version == exec_Version) &&
1358 (ExecBase->LibNode.lib_Revision == exec_Revision))
1361 * Really last thing. Check MaxLocMem and MaxExtMem fields
1362 * in ExecBase. First cannot be greater than 16MB and smaller
1363 * than 2MB, second, if is not zero then has to be greater
1364 * than 16MB
1367 if ((ExecBase->MaxLocMem >= 0x00200000) &&
1368 (ExecBase->MaxLocMem <= 0x01000000))
1370 if (ExecBase->MaxExtMem && ((ULONG)ExecBase->MaxExtMem < 0x01000000))
1372 return 0;
1374 return 1;
1380 return 0;
1383 void _aros_not_implemented()
1388 * RomTag scanner.
1390 * This function scans kernel for existing Resident modules. If two modules
1391 * with the same name are found, the one with higher version or priority wins.
1393 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
1394 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
1395 * be allocated, then all modules from KickTagPtr are added to RT list
1397 * Afterwards the proper RomTagList is created (see InitCode() for details) and
1398 * memory after list and nodes is freed.
1401 struct rt_node
1403 struct Node node;
1404 struct Resident *module;
1407 ULONG **exec_RomTagScanner(struct ExecBase *SysBase, struct TagItem *tags)
1409 struct List rtList; /* List of modules */
1410 UWORD *ptr = (UWORD*)LibGetTagData(KRN_KernelLowest, (ULONG)&_end, tags); /* Start looking here */
1412 struct Resident *res; /* module found */
1414 int i;
1415 ULONG **RomTag;
1417 /* Initialize list */
1418 NEWLIST(&rtList);
1420 kprintf("Resident modules (addr: pri version name):\n");
1422 /* Look in whole kernel for resident modules */
1425 /* Do we have RTC_MATCHWORD? */
1426 if (*ptr == RTC_MATCHWORD)
1428 /* Yes, assume we have Resident */
1429 res = (struct Resident *)ptr;
1431 /* Does rt_MatchTag point to Resident? */
1432 if (res == res->rt_MatchTag
1433 && !(strstr(arosmb->cmdline, "debug=serial") != NULL
1434 && strcmp(res->rt_Name, "serial.hidd") == 0))
1436 /* Yes, it is Resident module */
1437 struct rt_node *node;
1439 /* Check if there is module with such name already */
1440 node = (struct rt_node*)FindName(&rtList, res->rt_Name);
1441 if (node)
1443 /* Yes, there was such module. It it had lower pri then replace it */
1444 if (node->node.ln_Pri <= res->rt_Pri)
1446 /* If they have the same Pri but new one has higher Version, replace */
1447 if ((node->node.ln_Pri == res->rt_Pri) &&
1448 (node->module->rt_Version < res->rt_Version))
1450 node->node.ln_Pri = res->rt_Pri;
1451 node->module = res;
1455 else
1457 /* New module. Allocate some memory for it */
1458 node = (struct rt_node *)
1459 AllocMem(sizeof(struct rt_node),MEMF_PUBLIC|MEMF_CLEAR);
1461 if (node)
1463 node->node.ln_Name = (char *)res->rt_Name;
1464 node->node.ln_Pri = res->rt_Pri;
1465 node->module = res;
1467 Enqueue(&rtList,(struct Node*)node);
1471 /* Get address of EndOfResident from RomTag but only when it's
1472 * higher then present one - this avoids strange locks when
1473 * not all modules have Resident structure in .text section */
1474 ptr = ((ULONG)res->rt_EndSkip > (ULONG)ptr) ? (UWORD *)res->rt_EndSkip : ptr + 2;
1475 if ((ULONG)ptr & 0x01)
1476 ptr = (UWORD *)((ULONG)ptr+1);
1477 continue;
1481 /* Get next address... */
1482 ptr++;
1483 } while (ptr < (UWORD*)LibGetTagData(KRN_KernelHighest, (ULONG)&_end, tags));
1486 * By now we have valid (and sorted) list of kernel resident modules.
1488 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
1489 * KickMemPtr)
1491 /* TODO: Implement external modules! */
1494 * Everything is done now. Allocate buffer for normal RomTag and convert
1495 * list to RomTag
1498 ListLength(&rtList,i); /* Get length of the list */
1500 RomTag = AllocMem((i+1)*4,MEMF_PUBLIC | MEMF_CLEAR);
1502 if (RomTag)
1504 int j;
1505 struct rt_node *n;
1507 for (j=0; j<i; j++)
1509 n = (struct rt_node *)RemHead(&rtList);
1510 kprintf("+ 0x%08.8lx: %4d %3d \"%s\"\n",
1511 n->module,
1512 n->node.ln_Pri,
1513 n->module->rt_Version,
1514 n->node.ln_Name);
1515 RomTag[j] = (ULONG*)n->module;
1517 FreeMem(n, sizeof(struct rt_node));
1519 RomTag[i] = 0;
1522 return RomTag;
1525 struct vbe_controller my_vbe_control;
1526 struct vbe_mode my_vbe_mode;
1528 unsigned char setupVesa(struct multiboot *mbinfo)
1530 char *str = (char *)mbinfo->cmdline;
1531 char *vesa = strstr(str, "vesa=");
1532 short r;
1533 unsigned char palwidth = 0;
1534 BOOL prioritise_depth = FALSE, set_refresh = FALSE;
1536 if (vesa)
1538 long x=0, y=0, d=0, vfreq=0;
1539 long mode, setmode;
1540 unsigned long vesa_size = (unsigned long)&_binary_vesa_size;
1541 void *vesa_start = &_binary_vesa_start;
1542 vesa+=5;
1544 while (*vesa >= '0' && *vesa <= '9')
1545 x = x * 10 + *vesa++ - '0';
1546 if (*vesa++ == 'x')
1548 while (*vesa >= '0' && *vesa <= '9')
1549 y = y * 10 + *vesa++ - '0';
1550 if (*vesa++ == 'x')
1552 while (*vesa >= '0' && *vesa <= '9')
1553 d = d * 10 + *vesa++ - '0';
1555 else
1556 d = 32;
1558 else
1559 d = x, x = 10000, y = 10000, prioritise_depth = TRUE;
1561 /* Check for user-set refresh rate */
1562 if (*(vesa - 1) == '@')
1564 while (*vesa >= '0' && *vesa <= '9')
1565 vfreq = vfreq * 10 + *vesa++ - '0';
1566 set_refresh = TRUE;
1568 else
1569 vfreq = 60;
1571 rkprintf("[VESA] module (@ %p) size=%ld\n", &_binary_vesa_start, (long)&_binary_vesa_size);
1572 memcpy((void *)0x1000, vesa_start, vesa_size);
1573 rkprintf("[VESA] Module installed\n");
1575 rkprintf("[VESA] BestModeMatch for %ldx%ldx%ld = ", x, y, d);
1576 mode = findMode(x, y, d, vfreq, prioritise_depth);
1578 getModeInfo(mode);
1580 rkprintf("%lx\n",mode);
1581 if (modeinfo->mode_attributes & 0x80)
1582 setmode = mode | 0x4000;
1583 else
1584 setmode = mode;
1585 r = setVbeMode(setmode, set_refresh);
1586 if (r == 0x004f) {
1587 rkprintf("\x03");
1588 if (controllerinfo->capabilities & 0x01)
1589 paletteWidth(0x0800, &palwidth);
1590 else
1591 palwidth = 6;
1592 memcpy(&my_vbe_mode, modeinfo, sizeof(struct vbe_mode));
1593 memcpy(&my_vbe_control, controllerinfo, sizeof(struct vbe_controller));
1594 mbinfo->vbe_mode_info = (ULONG)&my_vbe_mode;
1595 mbinfo->vbe_control_info = (ULONG)&my_vbe_control;
1596 mbinfo->flags |= MB_FLAGS_GFX;
1597 mbinfo->vbe_mode = mode;
1598 } else
1599 rkprintf("[VESA] mode setting error: 0x%04X\n", r);
1601 return palwidth;
1604 AROS_LH1(struct ExecBase *, open,
1605 AROS_LHA(ULONG, version, D0),
1606 struct ExecBase *, SysBase, 1, Exec)
1608 AROS_LIBFUNC_INIT
1610 /* I have one more opener. */
1611 SysBase->LibNode.lib_OpenCnt++;
1612 return SysBase;
1613 AROS_LIBFUNC_EXIT
1616 AROS_LH0(BPTR, close,
1617 struct ExecBase *, SysBase, 2, Exec)
1619 AROS_LIBFUNC_INIT
1621 /* I have one fewer opener. */
1622 SysBase->LibNode.lib_OpenCnt--;
1623 return 0;
1624 AROS_LIBFUNC_EXIT
1627 AROS_LH0I(int, null,
1628 struct ExecBase *, SysBase, 3, Exec)
1630 AROS_LIBFUNC_INIT
1631 return 0;
1632 AROS_LIBFUNC_EXIT
1635 AROS_LH0I(int, null,
1636 struct ExecBase *, SysBase, 4, Exec)
1638 AROS_LIBFUNC_INIT
1639 return 0;
1640 AROS_LIBFUNC_EXIT
1644 We temporarily redefine kprintf() so we use the real version in case
1645 we have one of these two fn's called before AROSSupportBase is ready.
1648 #undef kprintf
1649 #undef rkprintf
1650 #undef vkprintf
1652 #define kprintf(x...)
1653 #define rkprintf(x...)
1654 #define vkprintf(x...)
1656 struct Library * PrepareAROSSupportBase(void)
1658 struct AROSSupportBase *AROSSupportBase =
1659 AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR);
1661 AROSSupportBase->kprintf = (void *)kprintf;
1662 AROSSupportBase->rkprintf = (void *)rkprintf;
1663 AROSSupportBase->vkprintf = (void *)vkprintf;
1665 return (struct Library *)AROSSupportBase;
1668 /* IntServer:
1669 This interrupt handler will send an interrupt to a series of queued
1670 interrupt servers. Servers should return D0 != 0 (Z clear) if they
1671 believe the interrupt was for them, and no further interrupts will
1672 be called. This will only check the value in D0 for non-m68k systems,
1673 however it SHOULD check the Z-flag on 68k systems.
1675 Hmm, in that case I would have to separate it from this file in order
1676 to replace it...
1678 AROS_UFH5S(void, IntServer,
1679 AROS_UFHA(ULONG, intMask, D0),
1680 AROS_UFHA(struct Custom *, custom, A0),
1681 AROS_UFHA(struct List *, intList, A1),
1682 AROS_UFHA(APTR, intCode, A5),
1683 AROS_UFHA(struct ExecBase *, SysBase, A6))
1685 AROS_USERFUNC_INIT
1687 struct Interrupt * irq;
1689 ForeachNode(intList, irq)
1691 if( AROS_UFC4(int, irq->is_Code,
1692 AROS_UFCA(struct Custom *, custom, A0),
1693 AROS_UFCA(APTR, irq->is_Data, A1),
1694 AROS_UFCA(APTR, irq->is_Code, A5),
1695 AROS_UFCA(struct ExecBase *, SysBase, A6)
1697 break;
1700 AROS_USERFUNC_EXIT