Blame |
Last modification |
View Log
| RSS feed
/* Project: OSLib
* Description: The OS Construction Kit
* Date: 1.6.2000
* Idea by: Luca Abeni & Gerardo Lamastra
*
* OSLib is an SO project aimed at developing a common, easy-to-use
* low-level infrastructure for developing OS kernels and Embedded
* Applications; it partially derives from the HARTIK project but it
* currently is independently developed.
*
* OSLib is distributed under GPL License, and some of its code has
* been derived from the Linux kernel source; also some important
* ideas come from studying the DJGPP go32 extender.
*
* We acknowledge the Linux Community, Free Software Foundation,
* D.J. Delorie and all the other developers who believe in the
* freedom of software and ideas.
*
* For legalese, check out the included GPL license.
*/
/* Address Spaces test file */
#include <ll/i386/stdlib.h>
#include <ll/i386/error.h>
#include <ll/i386/mem.h>
#include <ll/i386/hw-arch.h>
#include <ll/i386/farptr.h>
#include <ll/sys/ll/ll-func.h>
#include <ll/sys/ll/aspace.h>
#include <ll/sys/ll/event.h>
#include <ll/string.h>
#define USE_NEW_HANDLERS
#define T 1000
#define WAIT() for (w = 0; w < 0x5FFFFF; w++)
extern DWORD GDT_base
;
extern void int0x31
(void);
#ifndef USE_NEW_HANDLERS
struct regs
{
DWORD flags
;
DWORD egs
;
DWORD efs
;
DWORD ees
;
DWORD eds
;
DWORD edi
;
DWORD esi
;
DWORD ebp
;
DWORD esp
;
DWORD ebx
;
DWORD edx
;
DWORD ecx
;
DWORD eax
;
};
#endif
BYTE space
[2048];
WORD th1
, th2
, thm
;
char outstring
[] = "Hi there!!!\n";
#ifdef USE_NEW_HANDLERS
void chandler
(DWORD intnum
, struct registers r
)
#else
void chandler
(struct regs r
, DWORD intnum
)
#endif
{
message
("[System Call] EAX = 0x%lx EBX = 0x%lx ECX = 0x%lx...\n",
r.
eax, r.
ebx, r.
ecx);
if (r.
eax == 1) {
message
("Exit!!!\n");
ll_context_load
(thm
);
}
if (r.
eax == 2) {
char string
[20];
DWORD p
;
unsigned int size
;
p
= GDT_read
(r.
eds, NULL
, NULL
, NULL
);
p
+= r.
ebx;
size
= r.
ecx;
if (size
> 20) {
size
= 20;
}
#if 0
message
("Buffer @0x%lx, len %u\n", p
, size
);
l1_end
();
sti
();
l1_exit
(0);
#endif
memcpy(string
, (void *)p
, size
);
string
[19] = 0;
message
("Write...\n");
message
("%s", string
);
return;
}
message
("Unsupported System Call!!!\n");
}
/* For now, this is not called */
void killer
(void)
{
cli
();
message
("Killer!!!\n");
ll_context_load
(thm
);
}
/*
And this is the thread that runs in the new AS... It cannot call
any function (it is alone in its AS), so it simply plots a star
on the screen and loops waiting for an event that switches to the
main thread.
*/
void nullfun
(void *p
)
{
/* Some asm to write on the screen (we cannot use libc... it is not
linked in this AS */
__asm__ __volatile__
("movl $2, %eax");
__asm__ __volatile__
("movl $1000, %ebx");
__asm__ __volatile__
("movl $16, %ecx");
__asm__ __volatile__
("int $0x31");
__asm__ __volatile__
("movl $1, %eax");
__asm__ __volatile__
("int $0x31");
/* should not arrive here... */
for(;;);
halt
();
}
int main
(int argc
, char *argv
[])
{
DWORD sp1
, sp2
;
void *res
;
AS as
, ds
;
int ok
;
sp1
= get_SP
();
cli
();
res
= ll_init
();
if (res
== NULL
) {
message
("Error in LowLevel initialization code...\n");
sti
();
l1_exit
(-1);
}
message
("LowLevel started...\n");
#ifdef USE_NEW_HANDLERS
l1_int_bind
(0x31, chandler
);
#else
IDT_place
(0x31, int0x31
);
#endif
as_init
();
message
("Creating an Address Space\n");
as
= as_create
();
message
("Created: ID = %d %x\n", as
, as
);
message
("Binding array @ 0x%lx\n", (DWORD
)space
);
ok
= as_bind
(as
, (DWORD
)space
, 0, sizeof(space
));
if (ok
< 0) {
message
("Error in as_bind!!!\n");
} else {
message
("Bound\n");
}
ds
= get_DS
();
/* Let's create the image of the process...
* 0 --> 1000 : text
* 1000 --> 1000 + strlen(outstring) : initialized data
* ? <-- 2048 : stack
*/
fmemcpy
(as
, 0, ds
, (DWORD
)nullfun
, 1000);
fmemcpy
(as
, 1000, ds
, (DWORD
)outstring
, strlen(outstring
));
/* Create a thread (in our AS) and a task (in a different AS) */
th1
= ll_context_create
(0, (void *)2048, NULL
,killer
, 0);
ll_context_setspace
(th1
, as
);
/* Save our context, in order to permit to switch back to main */
thm
= ll_context_save
();
message
("I am thread %x\n", thm
);
message
("Thread 1 created\n");
message
("Switching to it...\n");
ll_context_load
(th1
);
message
("Back to Main\n");
cli
();
ll_end
();
sp2
= get_SP
();
message
("End reached!\n");
message
("Actual stack : %lx - ", sp2
);
message
("Begin stack : %lx\n", sp1
);
message
("Check if same : %s\n",sp1
== sp2
? "Ok :-)" : "No :-(");
return 1;
}