#include <u.h>
#include <libc.h>
#include <a.out.h>
#include "load.h"
#define MB (1024*1024)
uchar *kernel = (uchar*)MB;
ulong
swap(ulong p)
{
return (p<<24)|(p>>24)|((p<<8)&0x00FF0000)|((p>>8)&0x0000FF00);
}
void
_main(void)
{
extern char edata, end;
int n;
memmove(kernel, &edata, MB);
memset(&edata, 0, &end-&edata);
cgainit();
if(iskernel(kernel))
run(kernel);
if(isgzip(kernel)){
print("GZ...");
if((n=gunzip((uchar*)(2*MB), 2*MB, kernel, MB)) < 0){
print("gzip failed.");
exits(0);
}
if(n >= 2*MB){
print("too big.");
exits(0);
}
memmove(kernel, (uchar*)(2*MB), n);
if(iskernel(kernel))
run(kernel);
}
print("unrecognized file");
exits(0);
}
int
iskernel(void *v)
{
Exec *exec;
exec = v;
if(swap(exec->magic) == I_MAGIC)
return 1;
return 0;
}
void
run(void *v)
{
ulong entry, text, data;
uchar *base;
Exec *exec;
base = v;
exec = v;
entry = swap(exec->entry);
text = swap(exec->text);
data = swap(exec->data);
entry &= ~0xF0000000;
memmove(base+ROUND(32+text, 4096), base+32+text, data);
print("LOAD...\n");
((void(*)(void))entry)();
print("exec failed");
exits(0);
}
int
isgzip(void *v)
{
uchar *p;
p = v;
if(p[0] == 0x1F && p[1] == 0x8B)
return 1;
return 0;
}
void*
malloc(ulong n)
{
static char *brk;
extern char end;
void *v;
if(brk == nil)
brk = (char*)0x00400000;
n = (n+3)&~3;
v = brk;
brk += n;
return v;
}
void
free(void*)
{
}
void
putc(char c)
{
cgaputc(c);
}
void
puts(char *s)
{
for(; *s; s++)
putc(*s);
}
int
print(char *fmt, ...)
{
char *p, *s, buf[20];
static char *hex = "0123456789abcdef";
ulong x;
long d;
int sign;
va_list arg;
va_start(arg, fmt);
for(p=fmt; *p; p++){
if(*p == '%'){
p++;
switch(*p){
case 'p':
case 'x':
x = va_arg(arg, ulong);
s = buf+sizeof buf;
*--s = 0;
while(x > 0){
*--s = hex[x&15];
x /= 16;
}
if(s == buf+sizeof buf)
*--s = '0';
puts(s);
break;
case 'd':
d = va_arg(arg, ulong);
if(d == 0){
puts("0");
break;
}
if(d < 0){
d = -d;
sign = -1;
}else
sign = 1;
s = buf+sizeof buf;
*--s = 0;
while(d > 0){
*--s = (d%10)+'0';
d /= 10;
}
if(sign < 0)
*--s = '-';
puts(s);
break;
case 's':
s = va_arg(arg, char*);
puts(s);
break;
case 0:
return 0;
default:
break;
}
continue;
}
putc(*p);
}
return 0;
}
void
exits(char*)
{
for(;;);
}
|