2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 Desc: Linux init code for emulated (Unix) systems.
10 #include <exec/types.h>
11 #include <exec/memory.h>
12 #include <exec/memheaderext.h>
13 #include <exec/resident.h>
14 #include <exec/execbase.h>
16 #include <proto/exec.h>
18 #if (AROS_BIG_ENDIAN == 0)
19 #define SWAP(x) ((((ULONG)x >> 24) & 0x000000ff) |\
20 (((ULONG)x >> 8 ) & 0x0000ff00) |\
21 (((ULONG)x << 8 ) & 0x00ff0000) |\
22 (((ULONG)x << 24) & 0xff000000) )
27 #define _XOPEN_SOURCE 600L /* for posix_memalign */
32 #define __USE_MISC /* for MAP_ANON */
34 #include <sys/termios.h>
36 #include "../../../rom/exec/memory.h" /* From $(TOP)/rom/exec */
38 extern const struct Resident
64 Mathieeesingbas_ROMTag
,
80 /* This list MUST be in the correct order (priority). */
81 static const struct Resident
*romtagList
[] =
83 &Expansion_ROMTag
, /* SingleTask, 110 */
84 &Exec_resident
, /* SingleTask, 105 */
85 &Utility_ROMTag
, /* ColdStart, 103 */
86 &Aros_ROMTag
, /* ColdStart, 102 */
87 &Mathieeesingbas_ROMTag
, /* ColdStart, 101 */
89 &BOOPSI_resident
, /* ColdStart, 95 */
91 &OOP_ROMTag
, /* ColdStart, 94 */
92 &HIDDCl_ROMTag
, /* ColdStart, 92 */
93 &UXIO_ROMTag
, /* ColdStart, 91 */
94 &HostLib_ROMTag
, /* ColdStart, 91 */
95 #if defined(__i386__) || defined(__x86_64__)
96 &PCI_ROMTag
, /* ColdStart, 90 */
97 // &PCILx_ROMTag, /* ColdStart, 89 */
99 &Graphics_ROMTag
, /* ColdStart, 65 */
100 &Layers_ROMTag
, /* ColdStart, 60 */
101 &Timer_ROMTag
, /* ColdStart, 50 */
102 &Battclock_ROMTag
, /* ColdStart, 45 */
103 &Keyboard_ROMTag
, /* ColdStart, 44 */
104 &Gameport_ROMTag
, /* ColdStart, 43 */
105 &Keymap_ROMTag
, /* ColdStart, 40 */
106 &Input_ROMTag
, /* ColdStart, 30 */
107 &Intuition_ROMTag
, /* ColdStart, 10 */
108 &LinuxFB_ROMTag
, /* ColdStart, 9 */
109 &Cybergraphics_ROMTag
, /* ColdStart, 8 */
110 &Console_ROMTag
, /* ColdStart, 5 */
112 &Dbus_ROMTag
, /* ColdStart, 0 */
114 &emul_handler_ROMTag
, /* ColdStart, 0 */
115 &Packet_ROMTag
, /* ColdStart, 0 */
116 &UXSer_ROMTag
, /* ColdStart, 0 */
117 &UXPar_ROMTag
, /* ColdStart, 0 */
118 &Workbench_ROMTag
, /* ColdStart, -120 */
119 &Mathffp_ROMTag
, /* ColdStart, -120 */
122 NOTE: You must not put anything between these two; the code
123 which initialized boot_resident will directly call
124 Dos_resident and anything between the two will be skipped.
126 &boot_resident
, /* ColdStart, -50 */
127 &Dos_ROMTag
, /* None, -120 */
128 &LDDemon_resident
, /* AfterDOS, -125 */
129 &Con_ROMTag
, /* AfterDOS, -126 */
130 &Nil_ROMTag
, /* AfterDOS, -127 */
131 &Ram_ROMTag
, /* AfterDOS, -128 */
132 // &Partition_ROMTag,
137 /* So we can examine the memory */
138 static struct MemHeaderExt mhe
;
139 struct MemHeader
*mh
= &mhe
.mhe_MemHeader
;
140 UBYTE
*memory
, *space
;
143 extern void InitCore(void);
144 extern struct ExecBase
*PrepareExecBase(struct MemHeader
*mh
);
146 extern APTR
__libc_malloc(size_t);
147 extern VOID
__libc_free(APTR
);
148 extern APTR
__libc_calloc(size_t, size_t);
149 extern APTR
__libc_realloc(APTR mem
, size_t newsize
);
152 static APTR
myAlloc(struct MemHeaderExt
*mhe
, ULONG size
, ULONG
*flags
)
156 if (flags
&& (*flags
& MEMF_CLEAR
))
157 ret
= __libc_calloc(1, size
);
159 ret
= __libc_malloc(size
);
163 if (flags
) *flags
&= ~MEMF_CLEAR
;
164 mhe
->mhe_MemHeader
.mh_Free
-= size
;
170 static VOID
myFree(struct MemHeaderExt
*mhe
, APTR mem
, ULONG size
)
172 mhe
->mhe_MemHeader
.mh_Free
+= size
;
174 return __libc_free(mem
);
177 static ULONG
myAvail(struct MemHeaderExt
*mhe
, ULONG flags
)
179 if (flags
& MEMF_TOTAL
)
180 return memSize
<< 20;
182 return mhe
->mhe_MemHeader
.mh_Free
;
185 BOOL use_hostmem
= FALSE
;
187 APTR
malloc(size_t size
)
190 return AllocVec(size
, MEMF_ANY
);
192 return __libc_malloc(size
);
200 return __libc_free(mem
);
203 APTR
calloc(size_t n
, size_t size
)
206 return AllocVec(size
* n
, MEMF_CLEAR
);
208 return __libc_calloc(n
, size
);
212 static APTR
ReAllocVec(APTR old
, size_t size
, ULONG flags
)
214 APTR
new = AllocVec(size
, flags
);
218 ULONG oldsize
= *(ULONG
*)((char *)old
- AROS_ALIGN(sizeof(ULONG
)));
220 memcpy(new, old
, oldsize
> size
? size
: oldsize
);
228 APTR
realloc(APTR mem
, size_t size
)
231 return ReAllocVec(mem
, size
, MEMF_ANY
);
233 return __libc_realloc(mem
, size
);
237 This is where AROS is first called by whatever system loaded it,
238 either some kind of boot loader, or a "parent" operating system.
240 For boot loaded $(ARCH), you don't need to define main() like this,
241 you can have it anyway your bootloader likes.
244 extern char _start
, _end
;
246 int main(int argc
, char **argv
)
248 /* Well, if you want you can take in command line arguments here,
249 but that is not necessary, or perhaps rather complex...
251 eg: say you wished to allow people to specify the root directory
252 arosshell --rootdir /usr/local/AROS --memsize 4
254 For an example, you could ask how much memory you want for the
255 system, chip/fast whatever...
258 struct ExecBase
*SysBase
;
263 BOOL mapSysBase
= FALSE
;
264 BOOL _use_hostmem
= FALSE
;
268 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h"))
273 "usage: %s [options]\n"
274 " -h show this page\n"
275 " -m <size> allocate <size> Megabytes of memory for AROS\n"
276 " -M allows programs to read SysBase from Address $4; SysBase is\n"
277 " found there in big endian format\n"
278 " -t <value> timer ticks per second. Must be Multiple of 50; max value\n"
279 " working on 2.4 kernels is 100; on 2.6 kernels it is 1000;\n"
281 " --help same as '-h'\n"
282 " --memsize <size> same as '-m <size>'\n"
283 " --mapsysbase same as '-M'\n"
284 " --tickrate <value> same as '-t <value>'\n"
285 " --hostmem Let AROS use the host operating system's facilities to\n"
286 " manage memory, rather than the AROS' builtin ones.\n"
288 "Please report bugs to the AROS development team. http://www.aros.org/\n",
294 if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m"))
299 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
301 memSize
= memSize
* 10 + (argv
[i
])[x
] - '0';
307 if (!strcmp(argv
[i
], "--mapsysbase") || !strcmp(argv
[i
], "-M"))
313 if (!strcmp(argv
[i
], "--ticrate") || !strcmp(argv
[i
], "-t"))
318 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
320 ticrate
= ticrate
* 10 + (argv
[i
])[x
] - '0';
326 if (!strcmp(argv
[i
], "--hostmem"))
336 First up, set up the memory.
338 If your memory starts at 0 (I think Linux does, FreeBSD doesn't),
339 then you can allocate 4K at that address, and do whatever you want
340 to make that invalid to trap NULL dereference errors.
344 #if defined(__linux__) && defined(__mc68000__)
346 if (TRUE
== mapSysBase
)
348 psize
= getpagesize();
349 space
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
350 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
, -1, 0);
351 if (space
!= (UBYTE
*)-1)
353 int size
= psize
/sizeof(ULONG
);
354 memory
= (UBYTE
*)((IPTR
)space
+ psize
);
356 ((ULONG
*)space
)[size
] = 0xDEADBEEF;
370 /* We allocate memSize megabytes */
372 /* Allocate AROS memory in the first 2GB on x86-64 machines,
373 * otherwise relocations won't work correctly */
374 memory
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
375 MAP_ANONYMOUS
|MAP_PRIVATE
|MAP_32BIT
, -1, 0);
376 if( memory
== (UBYTE
*)-1 )
378 if( posix_memalign(&memory
, getpagesize(), (memSize
<< 20)) != 0 )
381 /*fprintf(stderr, "Cannot allocate any memory!\n");*/
384 /* Make whole AROS memory area executable */
385 if (mprotect(memory
, memSize
<< 20, PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
386 perror("mprotect failed");
390 /* The host system is going to allocate memory through AROS,
391 allocate some more memory for it. */
397 /* Prepare the first mem header */
398 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
399 mh
->mh_Node
.ln_Name
= "chip memory";
400 mh
->mh_Node
.ln_Pri
= -5;
401 mh
->mh_Attributes
= MEMF_CHIP
| MEMF_PUBLIC
| MEMF_LOCAL
|
402 MEMF_24BITDMA
| MEMF_KICK
;
406 mh
->mh_Attributes
|= MEMF_MANAGED
;
408 mh
->mh_Lower
= (char *)&_end
+ 1;
409 mh
->mh_Upper
= (APTR
)(~(IPTR
)0 / 2); /* Should use getrlimit here. */
410 mh
->mh_Free
= memSize
<< 20;
412 ((struct MemHeaderExt
*)mh
)->mhe_Alloc
= myAlloc
;
413 ((struct MemHeaderExt
*)mh
)->mhe_Free
= myFree
;
414 ((struct MemHeaderExt
*)mh
)->mhe_Avail
= myAvail
;
418 mh
->mh_First
= (struct MemChunk
*)memory
;
419 mh
->mh_First
->mc_Next
= NULL
;
420 mh
->mh_First
->mc_Bytes
= (memSize
<< 20) - psize
;
422 mh
->mh_Lower
= mh
->mh_First
;
423 mh
->mh_Upper
= (APTR
)(memory
+ (memSize
<< 20) - psize
);
424 mh
->mh_Free
= mh
->mh_First
->mc_Bytes
;
428 This will prepare enough of ExecBase to allow us to
429 call functions, it will also set up the memory list.
431 SysBase
= PrepareExecBase(mh
);
432 SysBase
->PowerSupplyFrequency
= ticrate
/ SysBase
->VBlankFrequency
;
434 use_hostmem
= _use_hostmem
;
436 /* ROM memory header. This special memory header covers all ROM code and data sections
437 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
439 if ((mh
= (struct MemHeader
*)AllocMem(sizeof(struct MemHeader
), MEMF_PUBLIC
)))
441 /* These symbols are provided by the linker on most platforms */
442 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
443 mh
->mh_Node
.ln_Name
= "rom memory";
444 mh
->mh_Node
.ln_Pri
= -128;
445 mh
->mh_Attributes
= MEMF_KICK
;
447 mh
->mh_Lower
= (APTR
)&_start
;
448 mh
->mh_Upper
= (APTR
)&_end
;
449 mh
->mh_Free
= 0; /* Never allocate from this chunk! */
451 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);
453 /* Ok, lets start up the kernel, we are probably using the UNIX
454 kernel, or a variant of that (see config/unix).
458 /* On Linux/m68k where we can run old Amiga binaries, we should
459 put SysBase at location 4. On other systems, DON'T DO THIS.
462 #if defined(__linux__) && defined(__mc68000__)
464 if (TRUE
== mapSysBase
)
466 *(APTR
*)4 = (APTR
)SWAP(SysBase
);
467 if (mprotect((APTR
)0, psize
, PROT_READ
))
476 /* We might also be interested in using the BS key instead of the
477 delete key, this will do that
479 #if 0 /* !defined(__x86_64__) */
481 t
.c_cc
[VERASE
] = '\b';
485 tcsetattr(0, TCSANOW
|TCSASOFT
, &t
);
487 /* There is nothing more system dependant to set up,
488 so lets start that ball rolling...
490 The InitCode() call should never return in a working system.
492 SysBase
->ResModules
= romtagList
;
493 InitCode(RTF_SINGLETASK
, 0);
494 fprintf(stderr
,"Returned from InitCode()\n");