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 */
13 #include <exec/types.h>
14 #include <exec/memory.h>
15 #include <exec/memheaderext.h>
16 #include <exec/resident.h>
17 #include <exec/execbase.h>
19 #include <proto/exec.h>
20 #include <aros/debug.h>
22 #if (AROS_BIG_ENDIAN == 0)
23 #define SWAP(x) ((((ULONG)x >> 24) & 0x000000ff) |\
24 (((ULONG)x >> 8 ) & 0x0000ff00) |\
25 (((ULONG)x << 8 ) & 0x00ff0000) |\
26 (((ULONG)x << 24) & 0xff000000) )
35 #define __USE_MISC /* for MAP_ANON */
37 #include <sys/termios.h>
38 #include <sys/utsname.h>
40 #include "../../../rom/exec/memory.h" /* From $(TOP)/rom/exec */
42 extern const struct Resident
69 Mathieeesingbas_ROMTag
,
90 /* This list MUST be in the correct order (priority). */
91 static const struct Resident
*romtagList
[] =
93 &Expansion_ROMTag
, /* SingleTask, 110 */
94 &Exec_resident
, /* SingleTask, 105 */
95 &Utility_ROMTag
, /* ColdStart, 103 */
96 &Aros_ROMTag
, /* ColdStart, 102 */
97 &Mathieeesingbas_ROMTag
, /* ColdStart, 101 */
98 &Bootloader_ROMTag
, /* ColdStart, 100 */
100 &BOOPSI_resident
, /* ColdStart, 95 */
102 &OOP_ROMTag
, /* ColdStart, 94 */
103 &HIDDCl_ROMTag
, /* ColdStart, 92 */
104 &UXIO_ROMTag
, /* ColdStart, 91 */
105 &HostLib_ROMTag
, /* ColdStart, 91 */
106 #if defined(__i386__) || defined(__x86_64__)
107 &PCI_ROMTag
, /* ColdStart, 90 */
108 // &PCILx_ROMTag, /* ColdStart, 89 */
110 &Graphics_ROMTag
, /* ColdStart, 65 */
111 &Layers_ROMTag
, /* ColdStart, 60 */
112 &Timer_ROMTag
, /* ColdStart, 50 */
113 &Battclock_ROMTag
, /* ColdStart, 45 */
114 &Keyboard_ROMTag
, /* ColdStart, 44 */
115 &Gameport_ROMTag
, /* ColdStart, 43 */
116 &Keymap_ROMTag
, /* ColdStart, 40 */
117 &Input_ROMTag
, /* ColdStart, 30 */
118 &Intuition_ROMTag
, /* ColdStart, 10 */
119 &GFX_ROMTag
, /* ColdStart, 10 */
120 /* This driver now causes segmentation fault and trashes the
121 display. Probably previously it failed to initialize because
122 its superclass was not initialized. Now everything is OK.
123 I've looked at the code, it creates input task during
124 resident initialization, not during driver instantiation.
125 I guess this causes some weird conflicts with running X server.
126 Disabled for now, needs to be seriously rewritten.
127 Pavel Fedin <sonic.amiga@gmail.com>
128 &LinuxFB_ROMTag,*/ /* ColdStart, 9 */
130 &X11Cl_ROMTag
, /* ColdStart, 9 */
132 &Cybergraphics_ROMTag
, /* ColdStart, 8 */
133 &Console_ROMTag
, /* ColdStart, 5 */
135 &Dbus_ROMTag
, /* ColdStart, 0 */
137 &emul_handler_ROMTag
, /* ColdStart, 0 */
138 &UXSer_ROMTag
, /* ColdStart, 0 */
139 &UXPar_ROMTag
, /* ColdStart, 0 */
140 &Workbench_ROMTag
, /* ColdStart, -120 */
141 &Mathffp_ROMTag
, /* ColdStart, -120 */
144 NOTE: You must not put anything between these two; the code
145 which initialized boot_resident will directly call
146 Dos_resident and anything between the two will be skipped.
148 &boot_resident
, /* ColdStart, -50 */
149 &Dos_ROMTag
, /* None, -120 */
150 &LDDemon_resident
, /* AfterDOS, -123 */
151 &Con_ROMTag
, /* AfterDOS, -124 */
152 &Packet_ROMTag
, /* AfterDOS, -124 */
153 &Nil_ROMTag
, /* AfterDOS, -125 */
154 &Ram_ROMTag
, /* AfterDOS, -125 */
155 // &Partition_ROMTag,
156 &Bootmenu_ROMTag
, /* AfterDOS, -127 */
157 &Dosboot_ROMTag
, /* AfterDOS, -128 */
161 /* So we can examine the memory */
162 static struct MemHeaderExt mhe
;
163 struct MemHeader
*mh
= &mhe
.mhe_MemHeader
;
164 UBYTE
*memory
, *space
;
167 extern void InitCore(void);
168 extern struct ExecBase
*PrepareExecBase(struct MemHeader
*mh
);
170 extern APTR
__libc_malloc(size_t);
171 extern VOID
__libc_free(APTR
);
172 extern APTR
__libc_calloc(size_t, size_t);
173 extern APTR
__libc_realloc(APTR mem
, size_t newsize
);
177 #define MEMLOCK Forbid();
178 #define MEMUNLOCK Permit();
180 static APTR
myAlloc(struct MemHeaderExt
*mhe
, ULONG size
, ULONG
*flags
)
184 if (flags
&& (*flags
& MEMF_CLEAR
))
185 ret
= __libc_calloc(1, size
);
187 ret
= __libc_malloc(size
);
191 if (flags
) *flags
&= ~MEMF_CLEAR
;
192 mhe
->mhe_MemHeader
.mh_Free
-= size
;
198 static VOID
myFree(struct MemHeaderExt
*mhe
, APTR mem
, ULONG size
)
200 mhe
->mhe_MemHeader
.mh_Free
+= size
;
202 return __libc_free(mem
);
205 static ULONG
myAvail(struct MemHeaderExt
*mhe
, ULONG flags
)
207 if (flags
& MEMF_TOTAL
)
208 return memSize
<< 20;
210 return mhe
->mhe_MemHeader
.mh_Free
;
213 BOOL use_hostmem
= FALSE
;
215 APTR
malloc(size_t size
)
220 return AllocVec(size
, MEMF_ANY
);
222 //kprintf("malloc %s\n", FindTask(0)->tc_Node.ln_Name);
226 if (memnest
> 1) kprintf("==== NESTING in malloc %d %s\n", memnest
, FindTask(0)->tc_Node
.ln_Name
);
228 retval
= __libc_malloc(size
);
244 if (memnest
> 1) kprintf("==== NESTING in free %d\n", memnest
);
251 APTR
calloc(size_t n
, size_t size
)
256 return AllocVec(size
* n
, MEMF_CLEAR
);
260 if (memnest
> 1) kprintf("==== NESTING in calloc %d\n", memnest
);
262 retval
= __libc_calloc(n
, size
);
271 static APTR
ReAllocVec(APTR old
, size_t size
, ULONG flags
)
273 APTR
new = AllocVec(size
, flags
);
279 ULONG oldsize
= *(ULONG
*)((char *)old
- AROS_ALIGN(sizeof(ULONG
)));
281 memcpy(new, old
, oldsize
> size
? size
: oldsize
);
290 APTR
realloc(APTR mem
, size_t size
)
295 return ReAllocVec(mem
, size
, MEMF_ANY
);
299 if (memnest
> 1) kprintf("==== NESTING in realloc %d\n", memnest
);
301 retval
= __libc_realloc(mem
, size
);
309 char *join_string(int argc
, char **argv
)
315 for (j
= 0; j
< argc
; j
++)
316 x
+= (strlen(argv
[j
]) + 1);
317 D(printf("[Init] Allocating %lu bytes for string\n", x
));
318 str
= __libc_malloc(x
);
321 for (j
= 0; j
< argc
; j
++) {
327 D(printf("[Init] Joined line: %s\n", str
));
333 This is where AROS is first called by whatever system loaded it,
334 either some kind of boot loader, or a "parent" operating system.
336 For boot loaded $(ARCH), you don't need to define main() like this,
337 you can have it anyway your bootloader likes.
340 extern char _start
, _end
;
341 char *BootLoader_Name
= NULL
;
342 char *Kernel_Args
= NULL
;
345 int main(int argc
, char **argv
)
347 struct ExecBase
*SysBase
;
350 struct utsname sysinfo
;
353 BOOL mapSysBase
= FALSE
;
354 BOOL _use_hostmem
= FALSE
;
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; SysBase is\n"
368 " found there in big endian format\n"
369 " -t <value> timer ticks per second. Must be Multiple of 50; max value\n"
370 " working on 2.4 kernels is 100; on 2.6 kernels it is 1000;\n"
372 " --help same as '-h'\n"
373 " --memsize <size> same as '-m <size>'\n"
374 " --mapsysbase same as '-M'\n"
375 " --tickrate <value> same as '-t <value>'\n"
376 " --hostmem Let AROS use the host operating system's facilities to\n"
377 " manage memory, rather than the AROS' builtin ones.\n"
379 "Please report bugs to the AROS development team. http://www.aros.org/\n",
384 else if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m"))
389 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
391 memSize
= memSize
* 10 + (argv
[i
])[x
] - '0';
396 else if (!strcmp(argv
[i
], "--mapsysbase") || !strcmp(argv
[i
], "-M"))
401 else if (!strcmp(argv
[i
], "--ticrate") || !strcmp(argv
[i
], "-t"))
406 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
408 ticrate
= ticrate
* 10 + (argv
[i
])[x
] - '0';
413 else if (!strcmp(argv
[i
], "--hostmem"))
423 Kernel_Args
= join_string(argc
- i
, &argv
[i
]);
426 nameparts
[0] = sysinfo
.sysname
;
427 nameparts
[1] = sysinfo
.machine
;
428 nameparts
[2] = sysinfo
.release
;
429 nameparts
[3] = sysinfo
.version
;
430 BootLoader_Name
= join_string(4, nameparts
);
434 First up, set up the memory.
436 If your memory starts at 0 (I think Linux does, FreeBSD doesn't),
437 then you can allocate 4K at that address, and do whatever you want
438 to make that invalid to trap NULL dereference errors.
442 #if defined(__linux__) && defined(__mc68000__)
444 if (TRUE
== mapSysBase
)
446 psize
= getpagesize();
447 space
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
448 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
, -1, 0);
449 if (space
!= (UBYTE
*)-1)
451 int size
= psize
/sizeof(ULONG
);
452 memory
= (UBYTE
*)((IPTR
)space
+ psize
);
454 ((ULONG
*)space
)[size
] = 0xDEADBEEF;
468 /* We allocate memSize megabytes */
470 /* Allocate AROS memory in the first 2GB on x86-64 machines,
471 * otherwise relocations won't work correctly */
472 memory
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
473 MAP_ANONYMOUS
|MAP_PRIVATE
|MAP_32BIT
, -1, 0);
474 if( memory
== (UBYTE
*)-1 )
476 if( posix_memalign(&memory
, getpagesize(), (memSize
<< 20)) != 0 )
479 /*fprintf(stderr, "Cannot allocate any memory!\n");*/
482 /* Make whole AROS memory area executable */
483 if (mprotect(memory
, memSize
<< 20, PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
484 perror("mprotect failed");
488 /* The host system is going to allocate memory through AROS,
489 allocate some more memory for it. */
495 /* Prepare the first mem header */
496 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
497 mh
->mh_Node
.ln_Name
= "chip memory";
498 mh
->mh_Node
.ln_Pri
= -5;
499 mh
->mh_Attributes
= MEMF_CHIP
| MEMF_PUBLIC
| MEMF_LOCAL
|
500 MEMF_24BITDMA
| MEMF_KICK
;
504 mh
->mh_Attributes
|= MEMF_MANAGED
;
506 mh
->mh_Lower
= (char *)&_end
+ 1;
507 mh
->mh_Upper
= (APTR
)(~(IPTR
)0 / 2); /* Should use getrlimit here. */
508 mh
->mh_Free
= memSize
<< 20;
510 ((struct MemHeaderExt
*)mh
)->mhe_Alloc
= myAlloc
;
511 ((struct MemHeaderExt
*)mh
)->mhe_Free
= myFree
;
512 ((struct MemHeaderExt
*)mh
)->mhe_Avail
= myAvail
;
516 mh
->mh_First
= (struct MemChunk
*)memory
;
517 mh
->mh_First
->mc_Next
= NULL
;
518 mh
->mh_First
->mc_Bytes
= (memSize
<< 20) - psize
;
520 mh
->mh_Lower
= mh
->mh_First
;
521 mh
->mh_Upper
= (APTR
)(memory
+ (memSize
<< 20) - psize
);
522 mh
->mh_Free
= mh
->mh_First
->mc_Bytes
;
526 This will prepare enough of ExecBase to allow us to
527 call functions, it will also set up the memory list.
529 SysBase
= PrepareExecBase(mh
);
530 SysBase
->PowerSupplyFrequency
= ticrate
/ SysBase
->VBlankFrequency
;
532 use_hostmem
= _use_hostmem
;
534 /* ROM memory header. This special memory header covers all ROM code and data sections
535 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
537 if ((mh
= (struct MemHeader
*)AllocMem(sizeof(struct MemHeader
), MEMF_PUBLIC
)))
539 /* These symbols are provided by the linker on most platforms */
540 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
541 mh
->mh_Node
.ln_Name
= "rom memory";
542 mh
->mh_Node
.ln_Pri
= -128;
543 mh
->mh_Attributes
= MEMF_KICK
;
545 mh
->mh_Lower
= (APTR
)&_start
;
546 mh
->mh_Upper
= (APTR
)&_end
;
547 mh
->mh_Free
= 0; /* Never allocate from this chunk! */
549 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);
551 /* Ok, lets start up the kernel, we are probably using the UNIX
552 kernel, or a variant of that (see config/unix).
556 /* On Linux/m68k where we can run old Amiga binaries, we should
557 put SysBase at location 4. On other systems, DON'T DO THIS.
560 #if defined(__linux__) && defined(__mc68000__)
562 if (TRUE
== mapSysBase
)
564 *(APTR
*)4 = (APTR
)SWAP(SysBase
);
565 if (mprotect((APTR
)0, psize
, PROT_READ
))
574 /* We might also be interested in using the BS key instead of the
575 delete key, this will do that
577 #if 0 /* !defined(__x86_64__) */
579 t
.c_cc
[VERASE
] = '\b';
583 tcsetattr(0, TCSANOW
|TCSASOFT
, &t
);
585 /* There is nothing more system dependant to set up,
586 so lets start that ball rolling...
588 The InitCode() call should never return in a working system.
590 SysBase
->ResModules
= romtagList
;
591 InitCode(RTF_SINGLETASK
, 0);
592 fprintf(stderr
,"Returned from InitCode()\n");