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>
17 #include <aros/debug.h>
19 #if (AROS_BIG_ENDIAN == 0)
20 #define SWAP(x) ((((ULONG)x >> 24) & 0x000000ff) |\
21 (((ULONG)x >> 8 ) & 0x0000ff00) |\
22 (((ULONG)x << 8 ) & 0x00ff0000) |\
23 (((ULONG)x << 24) & 0xff000000) )
28 #define _XOPEN_SOURCE 600L /* for posix_memalign */
33 #define __USE_MISC /* for MAP_ANON */
35 #include <sys/termios.h>
37 #include "../../../rom/exec/memory.h" /* From $(TOP)/rom/exec */
39 extern const struct Resident
65 Mathieeesingbas_ROMTag
,
81 /* This list MUST be in the correct order (priority). */
82 static const struct Resident
*romtagList
[] =
84 &Expansion_ROMTag
, /* SingleTask, 110 */
85 &Exec_resident
, /* SingleTask, 105 */
86 &Utility_ROMTag
, /* ColdStart, 103 */
87 &Aros_ROMTag
, /* ColdStart, 102 */
88 &Mathieeesingbas_ROMTag
, /* ColdStart, 101 */
90 &BOOPSI_resident
, /* ColdStart, 95 */
92 &OOP_ROMTag
, /* ColdStart, 94 */
93 &HIDDCl_ROMTag
, /* ColdStart, 92 */
94 &UXIO_ROMTag
, /* ColdStart, 91 */
95 &HostLib_ROMTag
, /* ColdStart, 91 */
96 #if defined(__i386__) || defined(__x86_64__)
97 &PCI_ROMTag
, /* ColdStart, 90 */
98 // &PCILx_ROMTag, /* ColdStart, 89 */
100 &Graphics_ROMTag
, /* ColdStart, 65 */
101 &Layers_ROMTag
, /* ColdStart, 60 */
102 &Timer_ROMTag
, /* ColdStart, 50 */
103 &Battclock_ROMTag
, /* ColdStart, 45 */
104 &Keyboard_ROMTag
, /* ColdStart, 44 */
105 &Gameport_ROMTag
, /* ColdStart, 43 */
106 &Keymap_ROMTag
, /* ColdStart, 40 */
107 &Input_ROMTag
, /* ColdStart, 30 */
108 &Intuition_ROMTag
, /* ColdStart, 10 */
109 &LinuxFB_ROMTag
, /* ColdStart, 9 */
110 &Cybergraphics_ROMTag
, /* ColdStart, 8 */
111 &Console_ROMTag
, /* ColdStart, 5 */
113 &Dbus_ROMTag
, /* ColdStart, 0 */
115 &emul_handler_ROMTag
, /* ColdStart, 0 */
116 &Packet_ROMTag
, /* ColdStart, 0 */
117 &UXSer_ROMTag
, /* ColdStart, 0 */
118 &UXPar_ROMTag
, /* ColdStart, 0 */
119 &Workbench_ROMTag
, /* ColdStart, -120 */
120 &Mathffp_ROMTag
, /* ColdStart, -120 */
123 NOTE: You must not put anything between these two; the code
124 which initialized boot_resident will directly call
125 Dos_resident and anything between the two will be skipped.
127 &boot_resident
, /* ColdStart, -50 */
128 &Dos_ROMTag
, /* None, -120 */
129 &LDDemon_resident
, /* AfterDOS, -125 */
130 &Con_ROMTag
, /* AfterDOS, -126 */
131 &Nil_ROMTag
, /* AfterDOS, -127 */
132 &Ram_ROMTag
, /* AfterDOS, -128 */
133 // &Partition_ROMTag,
138 /* So we can examine the memory */
139 static struct MemHeaderExt mhe
;
140 struct MemHeader
*mh
= &mhe
.mhe_MemHeader
;
141 UBYTE
*memory
, *space
;
144 extern void InitCore(void);
145 extern struct ExecBase
*PrepareExecBase(struct MemHeader
*mh
);
147 extern APTR
__libc_malloc(size_t);
148 extern VOID
__libc_free(APTR
);
149 extern APTR
__libc_calloc(size_t, size_t);
150 extern APTR
__libc_realloc(APTR mem
, size_t newsize
);
154 #define MEMLOCK Forbid();
155 #define MEMUNLOCK Permit();
157 static APTR
myAlloc(struct MemHeaderExt
*mhe
, ULONG size
, ULONG
*flags
)
161 if (flags
&& (*flags
& MEMF_CLEAR
))
162 ret
= __libc_calloc(1, size
);
164 ret
= __libc_malloc(size
);
168 if (flags
) *flags
&= ~MEMF_CLEAR
;
169 mhe
->mhe_MemHeader
.mh_Free
-= size
;
175 static VOID
myFree(struct MemHeaderExt
*mhe
, APTR mem
, ULONG size
)
177 mhe
->mhe_MemHeader
.mh_Free
+= size
;
179 return __libc_free(mem
);
182 static ULONG
myAvail(struct MemHeaderExt
*mhe
, ULONG flags
)
184 if (flags
& MEMF_TOTAL
)
185 return memSize
<< 20;
187 return mhe
->mhe_MemHeader
.mh_Free
;
190 BOOL use_hostmem
= FALSE
;
192 APTR
malloc(size_t size
)
197 return AllocVec(size
, MEMF_ANY
);
199 //kprintf("malloc %s\n", FindTask(0)->tc_Node.ln_Name);
203 if (memnest
> 1) kprintf("==== NESTING in malloc %d %s\n", memnest
, FindTask(0)->tc_Node
.ln_Name
);
205 retval
= __libc_malloc(size
);
221 if (memnest
> 1) kprintf("==== NESTING in free %d\n", memnest
);
228 APTR
calloc(size_t n
, size_t size
)
233 return AllocVec(size
* n
, MEMF_CLEAR
);
237 if (memnest
> 1) kprintf("==== NESTING in calloc %d\n", memnest
);
239 retval
= __libc_calloc(n
, size
);
248 static APTR
ReAllocVec(APTR old
, size_t size
, ULONG flags
)
250 APTR
new = AllocVec(size
, flags
);
256 ULONG oldsize
= *(ULONG
*)((char *)old
- AROS_ALIGN(sizeof(ULONG
)));
258 memcpy(new, old
, oldsize
> size
? size
: oldsize
);
267 APTR
realloc(APTR mem
, size_t size
)
272 return ReAllocVec(mem
, size
, MEMF_ANY
);
276 if (memnest
> 1) kprintf("==== NESTING in realloc %d\n", memnest
);
278 retval
= __libc_realloc(mem
, size
);
287 This is where AROS is first called by whatever system loaded it,
288 either some kind of boot loader, or a "parent" operating system.
290 For boot loaded $(ARCH), you don't need to define main() like this,
291 you can have it anyway your bootloader likes.
294 extern char _start
, _end
;
296 int main(int argc
, char **argv
)
298 /* Well, if you want you can take in command line arguments here,
299 but that is not necessary, or perhaps rather complex...
301 eg: say you wished to allow people to specify the root directory
302 arosshell --rootdir /usr/local/AROS --memsize 4
304 For an example, you could ask how much memory you want for the
305 system, chip/fast whatever...
308 struct ExecBase
*SysBase
;
313 BOOL mapSysBase
= FALSE
;
314 BOOL _use_hostmem
= FALSE
;
318 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h"))
323 "usage: %s [options]\n"
324 " -h show this page\n"
325 " -m <size> allocate <size> Megabytes of memory for AROS\n"
326 " -M allows programs to read SysBase from Address $4; SysBase is\n"
327 " found there in big endian format\n"
328 " -t <value> timer ticks per second. Must be Multiple of 50; max value\n"
329 " working on 2.4 kernels is 100; on 2.6 kernels it is 1000;\n"
331 " --help same as '-h'\n"
332 " --memsize <size> same as '-m <size>'\n"
333 " --mapsysbase same as '-M'\n"
334 " --tickrate <value> same as '-t <value>'\n"
335 " --hostmem Let AROS use the host operating system's facilities to\n"
336 " manage memory, rather than the AROS' builtin ones.\n"
338 "Please report bugs to the AROS development team. http://www.aros.org/\n",
344 if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m"))
349 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
351 memSize
= memSize
* 10 + (argv
[i
])[x
] - '0';
357 if (!strcmp(argv
[i
], "--mapsysbase") || !strcmp(argv
[i
], "-M"))
363 if (!strcmp(argv
[i
], "--ticrate") || !strcmp(argv
[i
], "-t"))
368 while ((argv
[i
])[x
] >= '0' && (argv
[i
])[x
] <= '9')
370 ticrate
= ticrate
* 10 + (argv
[i
])[x
] - '0';
376 if (!strcmp(argv
[i
], "--hostmem"))
386 First up, set up the memory.
388 If your memory starts at 0 (I think Linux does, FreeBSD doesn't),
389 then you can allocate 4K at that address, and do whatever you want
390 to make that invalid to trap NULL dereference errors.
394 #if defined(__linux__) && defined(__mc68000__)
396 if (TRUE
== mapSysBase
)
398 psize
= getpagesize();
399 space
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
400 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
, -1, 0);
401 if (space
!= (UBYTE
*)-1)
403 int size
= psize
/sizeof(ULONG
);
404 memory
= (UBYTE
*)((IPTR
)space
+ psize
);
406 ((ULONG
*)space
)[size
] = 0xDEADBEEF;
420 /* We allocate memSize megabytes */
422 /* Allocate AROS memory in the first 2GB on x86-64 machines,
423 * otherwise relocations won't work correctly */
424 memory
= mmap((APTR
)0, (memSize
<< 20), PROT_READ
|PROT_WRITE
,
425 MAP_ANONYMOUS
|MAP_PRIVATE
|MAP_32BIT
, -1, 0);
426 if( memory
== (UBYTE
*)-1 )
428 if( posix_memalign(&memory
, getpagesize(), (memSize
<< 20)) != 0 )
431 /*fprintf(stderr, "Cannot allocate any memory!\n");*/
434 /* Make whole AROS memory area executable */
435 if (mprotect(memory
, memSize
<< 20, PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
436 perror("mprotect failed");
440 /* The host system is going to allocate memory through AROS,
441 allocate some more memory for it. */
447 /* Prepare the first mem header */
448 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
449 mh
->mh_Node
.ln_Name
= "chip memory";
450 mh
->mh_Node
.ln_Pri
= -5;
451 mh
->mh_Attributes
= MEMF_CHIP
| MEMF_PUBLIC
| MEMF_LOCAL
|
452 MEMF_24BITDMA
| MEMF_KICK
;
456 mh
->mh_Attributes
|= MEMF_MANAGED
;
458 mh
->mh_Lower
= (char *)&_end
+ 1;
459 mh
->mh_Upper
= (APTR
)(~(IPTR
)0 / 2); /* Should use getrlimit here. */
460 mh
->mh_Free
= memSize
<< 20;
462 ((struct MemHeaderExt
*)mh
)->mhe_Alloc
= myAlloc
;
463 ((struct MemHeaderExt
*)mh
)->mhe_Free
= myFree
;
464 ((struct MemHeaderExt
*)mh
)->mhe_Avail
= myAvail
;
468 mh
->mh_First
= (struct MemChunk
*)memory
;
469 mh
->mh_First
->mc_Next
= NULL
;
470 mh
->mh_First
->mc_Bytes
= (memSize
<< 20) - psize
;
472 mh
->mh_Lower
= mh
->mh_First
;
473 mh
->mh_Upper
= (APTR
)(memory
+ (memSize
<< 20) - psize
);
474 mh
->mh_Free
= mh
->mh_First
->mc_Bytes
;
478 This will prepare enough of ExecBase to allow us to
479 call functions, it will also set up the memory list.
481 SysBase
= PrepareExecBase(mh
);
482 SysBase
->PowerSupplyFrequency
= ticrate
/ SysBase
->VBlankFrequency
;
484 use_hostmem
= _use_hostmem
;
486 /* ROM memory header. This special memory header covers all ROM code and data sections
487 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
489 if ((mh
= (struct MemHeader
*)AllocMem(sizeof(struct MemHeader
), MEMF_PUBLIC
)))
491 /* These symbols are provided by the linker on most platforms */
492 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
493 mh
->mh_Node
.ln_Name
= "rom memory";
494 mh
->mh_Node
.ln_Pri
= -128;
495 mh
->mh_Attributes
= MEMF_KICK
;
497 mh
->mh_Lower
= (APTR
)&_start
;
498 mh
->mh_Upper
= (APTR
)&_end
;
499 mh
->mh_Free
= 0; /* Never allocate from this chunk! */
501 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);
503 /* Ok, lets start up the kernel, we are probably using the UNIX
504 kernel, or a variant of that (see config/unix).
508 /* On Linux/m68k where we can run old Amiga binaries, we should
509 put SysBase at location 4. On other systems, DON'T DO THIS.
512 #if defined(__linux__) && defined(__mc68000__)
514 if (TRUE
== mapSysBase
)
516 *(APTR
*)4 = (APTR
)SWAP(SysBase
);
517 if (mprotect((APTR
)0, psize
, PROT_READ
))
526 /* We might also be interested in using the BS key instead of the
527 delete key, this will do that
529 #if 0 /* !defined(__x86_64__) */
531 t
.c_cc
[VERASE
] = '\b';
535 tcsetattr(0, TCSANOW
|TCSASOFT
, &t
);
537 /* There is nothing more system dependant to set up,
538 so lets start that ball rolling...
540 The InitCode() call should never return in a working system.
542 SysBase
->ResModules
= romtagList
;
543 InitCode(RTF_SINGLETASK
, 0);
544 fprintf(stderr
,"Returned from InitCode()\n");