2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
5 Desc: Linux init code for emulated (Unix) systems.
11 #define _XOPEN_SOURCE 600L /* for posix_memalign */
17 #define __USE_MISC /* for MAP_ANON */
19 #include <sys/param.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) )
42 #include "../../../rom/exec/memory.h" /* From $(TOP)/rom/exec */
44 extern const struct Resident
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
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 */
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 */
128 &X11Cl_ROMTag
, /* ColdStart, 9 */
130 &Cybergraphics_ROMTag
, /* ColdStart, 8 */
131 &Console_ROMTag
, /* ColdStart, 5 */
133 &Dbus_ROMTag
, /* ColdStart, 0 */
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 */
156 /* So we can examine the memory */
157 static struct MemHeaderExt mhe
;
158 struct MemHeader
*mh
= &mhe
.mhe_MemHeader
;
159 UBYTE
*memory
, *space
;
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
);
173 #define MEMLOCK Forbid();
174 #define MEMUNLOCK Permit();
176 static APTR
myAlloc(struct MemHeaderExt
*mhe
, ULONG size
, ULONG
*flags
)
180 if (flags
&& (*flags
& MEMF_CLEAR
))
181 ret
= __libc_calloc(1, size
);
183 ret
= __libc_malloc(size
);
187 if (flags
) *flags
&= ~MEMF_CLEAR
;
188 mhe
->mhe_MemHeader
.mh_Free
-= size
;
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
)
216 return AllocVec(size
, MEMF_ANY
);
218 //kprintf("malloc %s\n", FindTask(0)->tc_Node.ln_Name);
222 if (memnest
> 1) kprintf("==== NESTING in malloc %d %s\n", memnest
, FindTask(0)->tc_Node
.ln_Name
);
224 retval
= __libc_malloc(size
);
240 if (memnest
> 1) kprintf("==== NESTING in free %d\n", memnest
);
247 APTR
calloc(size_t n
, size_t size
)
252 return AllocVec(size
* n
, MEMF_CLEAR
);
256 if (memnest
> 1) kprintf("==== NESTING in calloc %d\n", memnest
);
258 retval
= __libc_calloc(n
, size
);
267 static APTR
ReAllocVec(APTR old
, size_t size
, ULONG flags
)
269 APTR
new = AllocVec(size
, flags
);
275 ULONG oldsize
= *(ULONG
*)((char *)old
- AROS_ALIGN(sizeof(ULONG
)));
277 memcpy(new, old
, oldsize
> size
? size
: oldsize
);
286 APTR
realloc(APTR mem
, size_t size
)
291 return ReAllocVec(mem
, size
, MEMF_ANY
);
295 if (memnest
> 1) kprintf("==== NESTING in realloc %d\n", memnest
);
297 retval
= __libc_realloc(mem
, size
);
305 char *join_string(int argc
, char **argv
)
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
);
317 for (j
= 0; j
< argc
; j
++) {
323 D(printf("[Init] Joined line: %s\n", 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
;
342 int main(int argc
, char **argv
)
344 struct ExecBase
*SysBase
;
348 struct utsname sysinfo
;
351 BOOL mapSysBase
= FALSE
;
352 BOOL _use_hostmem
= FALSE
;
354 getcwd(bootstrapdir
, PATH_MAX
);
358 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h"))
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"
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"
378 "Please report bugs to the AROS development team. http://www.aros.org/\n",
383 else if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m"))
388 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
390 memSize
= memSize
* 10 + (argv
[i
])[x
] - '0';
395 else if (!strcmp(argv
[i
], "--mapsysbase") || !strcmp(argv
[i
], "-M"))
400 else if (!strcmp(argv
[i
], "--ticrate") || !strcmp(argv
[i
], "-t"))
405 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
407 ticrate
= ticrate
* 10 + (argv
[i
])[x
] - '0';
412 else if (!strcmp(argv
[i
], "--hostmem"))
422 Kernel_Args
= join_string(argc
- i
, &argv
[i
]);
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
);
432 if (!stat("../AROS.boot", &st
))
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
);
452 ((ULONG
*)space
)[size
] = 0xDEADBEEF;
463 /* We allocate memSize megabytes */
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 )
471 if( posix_memalign(&memory
, getpagesize(), (memSize
<< 20)) != 0 )
474 /*fprintf(stderr, "Cannot allocate any memory!\n");*/
477 /* Make whole AROS memory area executable */
478 if (mprotect(memory
, memSize
<< 20, PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
479 perror("mprotect failed");
483 /* The host system is going to allocate memory through AROS,
484 allocate some more memory for it. */
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
;
497 mh
->mh_Attributes
|= MEMF_MANAGED
;
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
;
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
;
538 mh
->mh_Lower
= (APTR
)&_start
;
539 mh
->mh_Upper
= (APTR
)&_end
;
540 mh
->mh_Free
= 0; /* Never allocate from this chunk! */
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).
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
))
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");