#include #include #include #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(;;); }