Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / all-linux / exec / init.c
blob6e34b00a09992338cbb43c45bbe147a340f09b9f
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Linux init code for emulated (Unix) systems.
6 Lang: english
7 */
9 #define DEBUG 0
11 #define _XOPEN_SOURCE 600L /* for posix_memalign */
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <string.h>
17 #define __USE_MISC /* for MAP_ANON */
18 #include <sys/mman.h>
19 #include <sys/param.h>
20 #include <sys/stat.h>
21 #include <sys/termios.h>
22 #include <sys/utsname.h>
24 #include <exec/types.h>
25 #include <exec/memory.h>
26 #include <exec/memheaderext.h>
27 #include <exec/resident.h>
28 #include <exec/execbase.h>
30 #include <proto/exec.h>
31 #include <aros/debug.h>
33 #if (AROS_BIG_ENDIAN == 0)
34 #define SWAP(x) ((((ULONG)x >> 24) & 0x000000ff) |\
35 (((ULONG)x >> 8 ) & 0x0000ff00) |\
36 (((ULONG)x << 8 ) & 0x00ff0000) |\
37 (((ULONG)x << 24) & 0xff000000) )
38 #else
39 #define SWAP(x) x
40 #endif
42 #include "../../../rom/exec/memory.h" /* From $(TOP)/rom/exec */
44 extern const struct Resident
45 Expansion_ROMTag,
46 Exec_resident,
47 Utility_ROMTag,
48 Aros_ROMTag,
49 Bootloader_ROMTag,
50 OOP_ROMTag,
51 HIDDCl_ROMTag,
52 UXIO_ROMTag,
53 HostLib_ROMTag,
54 Graphics_ROMTag,
55 Layers_ROMTag,
56 Timer_ROMTag,
57 Battclock_ROMTag,
58 Keyboard_ROMTag,
59 Gameport_ROMTag,
60 Keymap_ROMTag,
61 Input_ROMTag,
62 Intuition_ROMTag,
63 LinuxFB_ROMTag,
64 Cybergraphics_ROMTag,
65 Console_ROMTag,
66 #if ENABLE_DBUS == 1
67 Dbus_ROMTag,
68 #endif
69 Dos_ROMTag,
70 LDDemon_resident,
71 emul_handler_ROMTag,
72 Packet_ROMTag,
73 UXSer_ROMTag,
74 UXPar_ROMTag,
75 boot_resident,
76 Con_ROMTag,
77 Nil_ROMTag,
78 Ram_ROMTag,
79 PCI_ROMTag,
80 PCILx_ROMTag,
81 Dosboot_ROMTag,
82 GFX_ROMTag,
83 #if ENABLE_X11 == 1
84 X11Cl_ROMTag,
85 #endif
86 Bootmenu_ROMTag;
88 /* This list MUST be in the correct order (priority). */
89 static const struct Resident *romtagList[] =
91 /* On other architectures Exec starts up before expansion, but
92 here it renders emul.handler non-functional, so left as is
93 for now. */
94 &Expansion_ROMTag, /* SingleTask, 110 */
95 &Exec_resident, /* SingleTask, 126 */
96 // &Partition_ROMTag, /* ColdStart, 104 */
97 &Utility_ROMTag, /* ColdStart, 103 */
98 &Aros_ROMTag, /* ColdStart, 102 */
99 &Bootloader_ROMTag, /* ColdStart, 100 */
100 &OOP_ROMTag, /* ColdStart, 94 */
101 &HIDDCl_ROMTag, /* ColdStart, 92 */
102 &UXIO_ROMTag, /* ColdStart, 91 */
103 &HostLib_ROMTag, /* ColdStart, 91 */
104 #if defined(__i386__) || defined(__x86_64__)
105 &PCI_ROMTag, /* ColdStart, 90 */
106 // &PCILx_ROMTag, /* ColdStart, 89 */
107 #endif
108 &Graphics_ROMTag, /* ColdStart, 65 */
109 &Layers_ROMTag, /* ColdStart, 60 */
110 &Timer_ROMTag, /* ColdStart, 50 */
111 &Battclock_ROMTag, /* ColdStart, 45 */
112 &Keyboard_ROMTag, /* ColdStart, 44 */
113 &Gameport_ROMTag, /* ColdStart, 44 */
114 &Keymap_ROMTag, /* ColdStart, 40 */
115 &Input_ROMTag, /* ColdStart, 30 */
116 &Intuition_ROMTag, /* ColdStart, 15 */
117 &GFX_ROMTag, /* ColdStart, 10 */
118 /* This driver now causes segmentation fault and trashes the
119 display. Probably previously it failed to initialize because
120 its superclass was not initialized. Now everything is OK.
121 I've looked at the code, it creates input task during
122 resident initialization, not during driver instantiation.
123 I guess this causes some weird conflicts with running X server.
124 Disabled for now, needs to be seriously rewritten.
125 Pavel Fedin <sonic.amiga@gmail.com>
126 &LinuxFB_ROMTag,*/ /* ColdStart, 9 */
127 #if ENABLE_X11 == 1
128 &X11Cl_ROMTag, /* ColdStart, 9 */
129 #endif
130 &Cybergraphics_ROMTag, /* ColdStart, 8 */
131 &Console_ROMTag, /* ColdStart, 5 */
132 #if ENABLE_DBUS == 1
133 &Dbus_ROMTag, /* ColdStart, 0 */
134 #endif
135 &emul_handler_ROMTag, /* ColdStart, 0 */
136 &UXSer_ROMTag, /* ColdStart, 0 */
137 &UXPar_ROMTag, /* ColdStart, 0 */
140 NOTE: You must not put anything between these two; the code
141 which initialized boot_resident will directly call
142 Dos_resident and anything between the two will be skipped.
144 &boot_resident, /* ColdStart, -50 */
145 &Dos_ROMTag, /* None, -120 */
146 &LDDemon_resident, /* AfterDOS, -123 */
147 &Con_ROMTag, /* AfterDOS, -124 */
148 &Packet_ROMTag, /* AfterDOS, -124 */
149 &Nil_ROMTag, /* AfterDOS, -125 */
150 &Ram_ROMTag, /* AfterDOS, -125 */
151 &Bootmenu_ROMTag, /* AfterDOS, -127 */
152 &Dosboot_ROMTag, /* AfterDOS, -128 */
153 NULL
156 /* So we can examine the memory */
157 static struct MemHeaderExt mhe;
158 struct MemHeader *mh = &mhe.mhe_MemHeader;
159 UBYTE *memory, *space;
160 int memSize = 32;
162 extern void InitCore(void);
163 extern struct ExecBase *PrepareExecBase(struct MemHeader *mh);
164 extern ULONG **Exec_RomTagScanner(struct ExecBase*, UWORD**);
166 extern APTR __libc_malloc(size_t);
167 extern VOID __libc_free(APTR);
168 extern APTR __libc_calloc(size_t, size_t);
169 extern APTR __libc_realloc(APTR mem, size_t newsize);
172 static int memnest;
173 #define MEMLOCK Forbid();
174 #define MEMUNLOCK Permit();
176 static APTR myAlloc(struct MemHeaderExt *mhe, ULONG size, ULONG *flags)
178 APTR ret;
180 if (flags && (*flags & MEMF_CLEAR))
181 ret = __libc_calloc(1, size);
182 else
183 ret = __libc_malloc(size);
185 if (ret)
187 if (flags) *flags &= ~MEMF_CLEAR;
188 mhe->mhe_MemHeader.mh_Free -= size;
191 return ret;
194 static VOID myFree(struct MemHeaderExt *mhe, APTR mem, ULONG size)
196 mhe->mhe_MemHeader.mh_Free += size;
198 return __libc_free(mem);
201 static ULONG myAvail(struct MemHeaderExt *mhe, ULONG flags)
203 if (flags & MEMF_TOTAL)
204 return memSize << 20;
206 return mhe->mhe_MemHeader.mh_Free;
209 BOOL use_hostmem = FALSE;
211 APTR malloc(size_t size)
213 APTR retval;
215 if (use_hostmem)
216 return AllocVec(size, MEMF_ANY);
218 //kprintf("malloc %s\n", FindTask(0)->tc_Node.ln_Name);
219 MEMLOCK
221 memnest++;
222 if (memnest > 1) kprintf("==== NESTING in malloc %d %s\n", memnest, FindTask(0)->tc_Node.ln_Name);
224 retval = __libc_malloc(size);
226 memnest--;
228 MEMUNLOCK
230 return retval;
233 VOID free(APTR mem)
235 if (use_hostmem)
236 return FreeVec(mem);
238 MEMLOCK
239 memnest++;
240 if (memnest > 1) kprintf("==== NESTING in free %d\n", memnest);
242 __libc_free(mem);
243 memnest--;
244 MEMUNLOCK
247 APTR calloc(size_t n, size_t size)
249 APTR retval;
251 if (use_hostmem)
252 return AllocVec(size * n, MEMF_CLEAR);
254 MEMLOCK
255 memnest++;
256 if (memnest > 1) kprintf("==== NESTING in calloc %d\n", memnest);
258 retval = __libc_calloc(n, size);
260 memnest--;
261 MEMUNLOCK
263 return retval;
267 static APTR ReAllocVec(APTR old, size_t size, ULONG flags)
269 APTR new = AllocVec(size, flags);
271 if (new)
273 if (old)
275 ULONG oldsize = *(ULONG *)((char *)old - AROS_ALIGN(sizeof(ULONG)));
277 memcpy(new, old, oldsize > size ? size : oldsize);
278 FreeVec(old);
280 old = new;
283 return old;
286 APTR realloc(APTR mem, size_t size)
288 APTR retval;
290 if (use_hostmem)
291 return ReAllocVec(mem, size, MEMF_ANY);
293 MEMLOCK
294 memnest++;
295 if (memnest > 1) kprintf("==== NESTING in realloc %d\n", memnest);
297 retval = __libc_realloc(mem, size);
299 memnest--;
300 MEMUNLOCK
302 return retval;
305 char *join_string(int argc, char **argv)
307 char *str, *s;
308 int j;
309 int x = 0;
311 for (j = 0; j < argc; j++)
312 x += (strlen(argv[j]) + 1);
313 D(printf("[Init] Allocating %lu bytes for string\n", x));
314 str = __libc_malloc(x);
315 if (str) {
316 s = str;
317 for (j = 0; j < argc; j++) {
318 strcpy(s, argv[j]);
319 s += strlen(s);
320 *s++ = ' ';
322 s[-1] = 0;
323 D(printf("[Init] Joined line: %s\n", str));
325 return str;
329 This is where AROS is first called by whatever system loaded it,
330 either some kind of boot loader, or a "parent" operating system.
332 For boot loaded $(ARCH), you don't need to define main() like this,
333 you can have it anyway your bootloader likes.
336 extern char _start, _end;
337 char bootstrapdir[PATH_MAX];
338 char *BootLoader_Name = NULL;
339 char *Kernel_Args = NULL;
340 char **Kernel_ArgV;
342 int main(int argc, char **argv)
344 struct ExecBase *SysBase;
345 int psize = 0;
346 int i = 1, x;
347 struct stat st;
348 struct utsname sysinfo;
349 char *nameparts[4];
350 int ticrate = 100;
351 BOOL mapSysBase = FALSE;
352 BOOL _use_hostmem = FALSE;
354 getcwd(bootstrapdir, PATH_MAX);
356 while (i < argc)
358 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
360 printf
362 "AROS for Linux\n"
363 "usage: %s [options] [kernel arguments]\n"
364 "Availible options:\n"
365 " -h show this page\n"
366 " -m <size> allocate <size> Megabytes of memory for AROS\n"
367 " -M allows programs to read SysBase from Address $4\n"
368 " -t <value> timer ticks per second. Must be Multiple of 50; max value\n"
369 " working on 2.4 kernels is 100; on 2.6 kernels it is 1000;\n"
370 " default is 100.\n"
371 " --help same as '-h'\n"
372 " --memsize <size> same as '-m <size>'\n"
373 " --mapsysbase same as '-M'\n"
374 " --tickrate <value> same as '-t <value>'\n"
375 " --hostmem Let AROS use the host operating system's facilities to\n"
376 " manage memory, rather than the AROS' builtin ones.\n"
377 "\n"
378 "Please report bugs to the AROS development team. http://www.aros.org/\n",
379 argv[0]
381 return 0;
383 else if (!strcmp(argv[i], "--memsize") || !strcmp(argv[i], "-m"))
385 i++;
386 x = 0;
387 memSize = 0;
388 while ((argv[i])[x] >= '0' && (argv[i])[x] <= '9')
390 memSize = memSize * 10 + (argv[i])[x] - '0';
391 x++;
393 i++;
395 else if (!strcmp(argv[i], "--mapsysbase") || !strcmp(argv[i], "-M"))
397 mapSysBase = TRUE;
398 i++;
400 else if (!strcmp(argv[i], "--ticrate") || !strcmp(argv[i], "-t"))
402 i++;
403 x = 0;
404 ticrate = 0;
405 while ((argv[i])[x] >= '0' && (argv[i])[x] <= '9')
407 ticrate = ticrate * 10 + (argv[i])[x] - '0';
408 x++;
410 i++;
412 else if (!strcmp(argv[i], "--hostmem"))
414 _use_hostmem = TRUE;
415 i++;
417 else
418 break;
421 if (i < argc)
422 Kernel_Args = join_string(argc - i, &argv[i]);
424 uname(&sysinfo);
425 nameparts[0] = sysinfo.sysname;
426 nameparts[1] = sysinfo.machine;
427 nameparts[2] = sysinfo.release;
428 nameparts[3] = sysinfo.version;
429 BootLoader_Name = join_string(4, nameparts);
430 Kernel_ArgV = argv;
432 if (!stat("../AROS.boot", &st))
433 chdir("..");
435 First up, set up the memory.
437 If your memory starts at 0 (I think Linux does, FreeBSD doesn't),
438 then you can allocate 4K at that address, and do whatever you want
439 to make that invalid to trap NULL dereference errors.
442 if (TRUE == mapSysBase)
444 psize = getpagesize();
445 space = mmap((APTR)0, (memSize << 20), PROT_READ|PROT_WRITE,
446 MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
447 if (space != (UBYTE *)-1)
449 int size = psize/sizeof(ULONG);
450 memory = (UBYTE *)((IPTR)space + psize);
451 while(--size)
452 ((ULONG *)space)[size] = 0xDEADBEEF;
454 else
456 perror("mmap");
457 exit(20);
460 else
461 if (!_use_hostmem)
463 /* We allocate memSize megabytes */
464 #ifdef __x86_64__
465 /* Allocate AROS memory in the first 2GB on x86-64 machines,
466 * otherwise relocations won't work correctly */
467 memory = mmap((APTR)0, (memSize << 20), PROT_READ|PROT_WRITE,
468 MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0);
469 if( memory == (UBYTE *)-1 )
470 #else
471 if( posix_memalign(&memory, getpagesize(), (memSize << 20)) != 0 )
472 #endif
474 /*fprintf(stderr, "Cannot allocate any memory!\n");*/
475 exit(20);
477 /* Make whole AROS memory area executable */
478 if (mprotect(memory, memSize << 20, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
479 perror("mprotect failed");
481 else
483 /* The host system is going to allocate memory through AROS,
484 allocate some more memory for it. */
485 memSize += 8;
488 /* Prepare the first mem header */
489 mh->mh_Node.ln_Type = NT_MEMORY;
490 mh->mh_Node.ln_Name = "chip memory";
491 mh->mh_Node.ln_Pri = -5;
492 mh->mh_Attributes = MEMF_CHIP | MEMF_PUBLIC | MEMF_LOCAL |
493 MEMF_24BITDMA | MEMF_KICK;
495 if (_use_hostmem)
497 mh->mh_Attributes |= MEMF_MANAGED;
498 mh->mh_First = NULL;
499 mh->mh_Lower = (char *)&_end + 1;
500 mh->mh_Upper = (APTR)(~(IPTR)0 / 2); /* Should use getrlimit here. */
501 mh->mh_Free = memSize << 20;
503 ((struct MemHeaderExt *)mh)->mhe_Alloc = myAlloc;
504 ((struct MemHeaderExt *)mh)->mhe_Free = myFree;
505 ((struct MemHeaderExt *)mh)->mhe_Avail = myAvail;
507 else
509 mh->mh_First = (struct MemChunk *)memory;
510 mh->mh_First->mc_Next = NULL;
511 mh->mh_First->mc_Bytes = (memSize << 20) - psize;
513 mh->mh_Lower = mh->mh_First;
514 mh->mh_Upper = (APTR)(memory + (memSize << 20) - psize);
515 mh->mh_Free = mh->mh_First->mc_Bytes;
519 This will prepare enough of ExecBase to allow us to
520 call functions, it will also set up the memory list.
522 SysBase = PrepareExecBase(mh);
523 SysBase->PowerSupplyFrequency = ticrate / SysBase->VBlankFrequency;
525 use_hostmem = _use_hostmem;
527 /* ROM memory header. This special memory header covers all ROM code and data sections
528 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
530 if ((mh = (struct MemHeader *)AllocMem(sizeof(struct MemHeader), MEMF_PUBLIC)))
532 /* These symbols are provided by the linker on most platforms */
533 mh->mh_Node.ln_Type = NT_MEMORY;
534 mh->mh_Node.ln_Name = "rom memory";
535 mh->mh_Node.ln_Pri = -128;
536 mh->mh_Attributes = MEMF_KICK;
537 mh->mh_First = NULL;
538 mh->mh_Lower = (APTR)&_start;
539 mh->mh_Upper = (APTR)&_end;
540 mh->mh_Free = 0; /* Never allocate from this chunk! */
541 Forbid();
542 Enqueue(&SysBase->MemList, &mh->mh_Node);
544 /* Ok, lets start up the kernel, we are probably using the UNIX
545 kernel, or a variant of that (see config/unix).
547 InitCore();
549 /* On Linux/m68k where we can run old Amiga binaries, we should
550 put SysBase at location 4. On other systems, DON'T DO THIS.
553 if (TRUE == mapSysBase)
555 *(APTR *)4 = SysBase;
556 if (mprotect((APTR)0, psize, PROT_READ))
558 perror("mprotect");
559 exit(10);
563 /* There is nothing more system dependant to set up,
564 so lets start that ball rolling...
566 The InitCode() call should never return in a working system.
568 /* Exec_RomTagScanner() crashes, probably this happens because ELF segments
569 are laid out in memory non-continuously. A solution needs to be found.
570 UWORD *ranges[] = {&_start, &_end, (UWORD *)~0};
572 SysBase->ResModules = Exec_RomTagScanner(SysBase,ranges);*/
573 SysBase->ResModules = romtagList;
574 InitCode(RTF_SINGLETASK, 0);
575 fprintf(stderr,"Returned from InitCode()\n");
576 return 1;