# HG changeset patch # User Pascal Bellard # Date 1479845941 -3600 # Node ID bb42796dcd3b2f28ea3e336dba545b3270293899 # Parent 099a4d67f199d639761e51b1d042b9d0aea04012 linld: multi initrd support diff -r 099a4d67f199 -r bb42796dcd3b linld/receipt --- a/linld/receipt Tue Nov 22 18:08:00 2016 +0100 +++ b/linld/receipt Tue Nov 22 21:19:01 2016 +0100 @@ -19,21 +19,25 @@ { mv DIST $src 2> /dev/null cd $src - patch -p0 < $stuff/load.u - patch -p0 < $stuff/jump.u - patch -p0 < $stuff/a20.u - patch -p0 < $stuff/memcpy32.u - sed -i 's/^@pause/rem &/;s|^tasm|& /l|' LINLD$SUFFIX/*.BAT + rm LINLD$SUFFIX/CRTL.CPP + cp $stuff/src/* LINLD$SUFFIX/ + cp -a LINLD$SUFFIX TAZBOOT + sed -i 's/-3/-DNO386/' TAZBOOT/BCCOPT.OPT unix2dos > MAKE.BAT < linld.lst upx linld.com + upx tazboot.com cc -o tobzimage.o -Wa,-algms=tobzimage.lst -c $stuff/tobzimage.S objcopy -O binary tobzimage.o tobzimage.bin cp $stuff/tobzimage . diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/!COMPILE.BAT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/!COMPILE.BAT Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,16 @@ +path ..\BC31;%PATH% +call !clean.bat +tasm > help.log +bcc > help2.log +tlink > help3.log +tasm /l /m *.asm > asm.log +rem @pause +bcc @bccopt.opt -S -mt *.cpp +tasm /l /m load.asm +tasm /l /m himem.asm +tasm /l /m linld.asm +tasm /l /m iso9660.asm +bcc @bccopt.opt -c -mt *.cpp > cpp.log +rem @pause +tlink /m /s /t @link.cmd > lnk.log +rem @pause diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/!COMPILEX.BAT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/!COMPILEX.BAT Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,13 @@ +path ..\BC31;%PATH% +call !clean.bat +tasm /l /m /dNO386 *.asm > asm.log +rem @pause +bcc @bccopt.opt -S -mt *.cpp +tasm /l /m load.asm +tasm /l /m himem.asm +tasm /l /m tazboot.asm +tasm /l /m iso9660.asm +bcc @bccopt.opt -c -mt *.cpp > cpp.log +rem @pause +tlink /m /s /t @linkx.cmd > lnk.log +rem @pause diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/A20.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/A20.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,145 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_DATA + assume cs:DGROUP,ds:DGROUP + + segment _DATA byte public use16 'DATA' + + global die:near +enable_a20_methods: + dw _enable_a20_fast, _enable_a20_kbd, _enable_a20_xmm, die +msg_a20 db "Can't enable A20",0 + + ends _DATA + + segment _TEXT byte public use16 'CODE' + + global xmm_driver:near + global _enable_a20_xmm:near + +;*************************************************************** +;void enable_a20_kbd(); +;*************************************************************** + proc _enable_a20_kbd near + + call @@empty_8042 + mov al,0D1h ; command write + out 64h,al + call @@empty_8042 + mov al,0DFh ; A20 on + out 60h,al + +; This routine checks that the keyboard command queue is empty +; (after emptying the output buffers) +; Some machines have delusions that the keyboard buffer is always full +; with no keyboard attached... +; If there is no keyboard controller, we will usually get 0xff +; to all the reads. With each IO taking a microsecond and +; a timeout of 100,000 iterations, this can take about half a +; second ("delay" == out to port 0x80). That should be ok, +; and should also be plenty of time for a real keyboard controller +; to empty. + +@@empty_8042: + xor cx,cx ; 64K iterations +@@loop: + call @@delay ; 8042 status port + in al,64h ; output buffer? + test al,1 ; + jz @@no_output + call @@delay ; yes: read it + in al,60h ; + jmp @@cont ; +@@no_output: + test al,2 ; is input buffer full? + jz @@break ; no - break loop +@@cont: + loop @@loop +@@break: + ret + +@@delay: out 80h,al + ret + + endp _enable_a20_kbd + +;*************************************************************** +;void enable_a20_fast(); +;*************************************************************** + proc _enable_a20_fast near + +; You must preserve the other bits here. Otherwise embarrasing things +; like laptops powering off on boot happen. Corrected version by Kira +; Brown from Linux 2.2 + in al,92h ; + or al,02h ; "fast A20" version + out 92h,al ; some chips have only this + ret + + endp _enable_a20_fast + +;*************************************************************** +;int check_a20(); +;*************************************************************** + proc _check_a20 near + +; From linux kernel setup.S: +; wait until a20 really *is* enabled; it can take a fair amount of +; time on certain systems; Toshiba Tecras are known to have this +; problem. + + push ds es + xor bx,bx + mov ds,bx + mov cx,0FFFFh + mov es,cx +a20lp: + cli + mov ax,0AA55h + xchg al,[bx] + xchg ah,[es:bx+10h] + xchg al,[bx] + xchg ah,[es:bx+10h] + cmp al,55h + sti +a20ko: + loopne a20lp + xchg ax,cx + pop es ds + ret + + endp _check_a20 + +;*************************************************************** +;void enable_a20_or_die(); +;*************************************************************** + global _enable_a20_or_die:near + proc _enable_a20_or_die near + + push si + mov si,offset enable_a20_methods + jmp @@check +@@loop: + lodsw + mov bx,offset msg_a20 + call ax +@@check: + call _check_a20 + jne @@loop + pop si + ret + + endp _enable_a20_or_die + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/COMMON.H --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/COMMON.H Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,82 @@ +// This file is distributed under GPL +// +// Common defs not belonging to CRTL + +#define NL "\r\n" +#define VERSION_STR "0.97" + +#if 0 // DEBUG + #undef NDEBUG + #define DEBUG + #define static +#else // not DEBUG + #define NDEBUG + #undef DEBUG +#endif + +typedef unsigned long u32; typedef signed long s32; +typedef unsigned short u16; typedef signed short s16; +typedef unsigned char u8; typedef signed char s8; + +const u16 _16k = 16*1024u; +const u16 _32k = 32*1024u; +const u32 _64k = 64*1024ul; +const u32 _1m = 1024ul*1024ul; + +const PAGE_BITS = 12; +const PAGE_SIZE = 1<fd + call close + ifndef NO386 + xor eax,eax + else + xor ax,ax + endif + cwd + mov [di],ax ; m->fd + mov bx,[di+28] ; m->state + cmp al,[bx] ; "" + jz @@end + push si + mov si,bx +@@scan: + lodsb + mov cx,si + cmp al,',' + jz @@eos + cmp al,0 + jnz @@scan + dec cx +@@eos: + mov [di+28],cx ; m->state + dec si + push [word si] + mov [byte si],dl ; set temp eos + xchg ax,dx ; O_RDONLY + call open + pop [word si] ; restore string + pop si + jc @@die + mov [di],ax ; m->fd + mov dx,2 ; SEEK_END + xchg ax,bx + ifndef NO386 + xor ecx,ecx + else + xor ax,ax + xor cx,cx + endif + call lseek +@@die: + mov bx,[di+20] ; m->errmsg + jc die + mov bx,[di] ; m->fd + ifndef NO386 + push eax + call rewind + pop eax +@@end: + mov [di+22],eax ; m->chunk_size + else + push ax + push dx + call rewind + pop dx + pop ax +@@end: + mov [di+22],ax ; m->chunk_size + mov [di+24],dx + endif + pop di + ret + + endp _next_chunk + + +;*************************************************************** +;void open_image(const char *name, struct image_himem *m); +;struct image_himem { +; 0 int fd; +; 2 u32 fallback; +; 6 u32 size; +;10 u32 remaining; +;14 u32 buf; +;18 u32 *bufv; +;20 char *errmsg; +;22 u32 chunk_size; +;26 void (*next_chunk)(struct image_himem *); +;28 u16 state; +;}; +;*************************************************************** + global _open_image:near + proc _open_image near + + arg fname :word, \ + m :word = PARAM_SIZE + + push bp + mov bp,sp + push si di + ifndef NO386 + xor eax,eax ; 1st loop flag + eos + else + xor ax,ax ; 1st loop flag + eos + endif + mov di,[m] + cmp [di],ax ; m->fd + jnz @@alreadydone + ifndef NO386 + mov [di+6],eax ; m->size = 0L + else + mov [di+6],ax ; m->size = 0L + mov [di+8],ax + endif + mov [word di+26],offset _next_chunk + mov si,[fname] + mov [di+28],si ; m->state +@@next: + push di + call [word di+26] ; m->next_chunk() + pop di + ifndef NO386 + add eax,3 + and al,0FCh + add [di+6],eax ; m->size += m->chunk_size + or eax,eax + jnz @@next + else + mov cx,ax + or cx,dx + add ax,3 + adc dx,0 + and al,0FCh + add [di+6],ax ; m->size += m->chunk_size + adc [di+8],dx + inc cx + loop @@next + endif + mov [di+28],si ; m->state + push di + call [word di+26] ; m->next_chunk() + pop di +@@alreadydone: + push ax +image_done: + pop ax + pop di si bp + ret + + endp _open_image + + +;*************************************************************** +;int read_image(struct image_himem *m, void* data, int sz); +;*************************************************************** + global _read_image:near + proc _read_image near + + arg m :word, \ + data :word, \ + sz :word = PARAM_SIZE + + push bp + mov bp,sp + push si di + ifndef NO386 + push 0 ; return value + else + xor ax,ax + push ax + endif + mov di,[m] +@@loop: + mov ax,[word sz] + mov cx,[di+22] ; m->chunk_size + cmp ax,cx + jb @@szok + cmp [word di+24],0 ; hi m->chunk_size + jne @@szok + xchg ax,cx +@@szok: + push ax + push [word data] + push [word di] + call _read + pop cx + pop bx + add bx,ax + pop cx + xor cx,cx + sub [di+22],ax + sbb [di+24],cx +@@fill: + test al,3 + je @@filled + mov [bx],cl + inc bx + inc ax + jmp @@fill +@@filled: + add [bp-4-2],ax + add [word data],ax + sub [word sz],ax + jz image_done + mov cx,[di+22] ; lo m->chunk_size + or cx,[di+24] ; hi m->chunk_size + jnz image_done + or cx,[di+26] ; m->next_chunk + jz image_done + push di + call cx ; m->next_chunk() + pop di + mov cx,[di+22] ; lo m->chunk_size + or cx,[di+24] ; hi m->chunk_size + jz image_done + jmp @@loop + + endp _read_image + + +;*************************************************************** +;unsigned long strtol(const char *s); +;*************************************************************** + global _strtol:near + proc _strtol near + +;TODO NO386 + ifndef NO386 + pop ax ;caller return address + pop cx ; s + push cx + push ax + xor ebx,ebx + jcxz @@end + push si + mov si,cx + xor ecx,ecx + xor eax,eax + mov cl,10 ; radix + lodsb + cmp al,'+' + je @@radixskip + cmp al,'-' + clc + jne @@radixkeep + stc +@@radixskip: + lodsb +@@radixkeep: + pushf + cmp al,'0' + jne @@radixok + mov cl,8 + lodsb + mov dl,20h + or dl,al + cmp dl,'x' + jne @@radixok + mov cl,16 +@@strtollp: + lodsb +@@radixok: + sub al,'0' + jb @@endstrtol + cmp al,9 + jbe @@digitok + or al,20h + cmp al,'a'-'0' + jb @@endstrtol + sub al,'a'-'0'-10 +@@digitok: + cmp al,cl + jae @@endstrtol + xchg eax,ebx + mul ecx + add eax,ebx + xchg eax,ebx + jmp @@strtollp +@@endstrtol: + mov cl,10 + cmp al,'k'-'a'+10 + je @@shift + mov cl,20 + cmp al,'m'-'a'+10 + je @@shift + mov cl,30 + cmp al,'g'-'a'+10 + jne @@noshift +@@shift: + shl ebx,cl +@@noshift: + popf + jnc @@end + neg ebx +@@end: + push ebx + pop ax + pop dx +popsiret: + pop si + else + pop ax ;caller return address + pop cx ; s + push cx + push ax + push si + push di + xor ax,ax + cwd + xchg ax,di + jcxz @@end + mov si,cx + mov cx,10 ; radix + lodsb + cmp al,'+' + je @@radixskip + cmp al,'-' + clc + jne @@radixkeep + stc +@@radixskip: + lodsb +@@radixkeep: + pushf + cmp al,'0' + jne @@radixok + mov cl,8 + lodsb + mov ah,20h + or ah,al + cmp ah,'x' + jne @@radixok + mov cl,16 +@@strtollp: + lodsb +@@radixok: + sub al,'0' + jb @@endstrtol + cmp al,9 + jbe @@digitok + or al,20h + cmp al,'a'-'0' + jb @@endstrtol + sub al,'a'-'0'-10 +@@digitok: + cmp al,cl + jae @@endstrtol + + push ax + push si + push dx + xchg ax,di + mul cx + xchg ax,di + xchg ax,dx + xchg ax,si + pop ax + mul cx + add ax,si + pop si + xchg ax,dx + pop ax + mov ah,0 + add di,ax + adc dx,0 + + jmp @@strtollp +@@endstrtol: + mov cl,10 + cmp al,'k'-'a'+10 + je @@shift + mov cl,20 + cmp al,'m'-'a'+10 + je @@shift + mov cl,30 + cmp al,'g'-'a'+10 + jne @@noshift +@@shift: + rcl di,1 + shl dx,1 + loop @@shift +@@noshift: + popf + jnc @@end + not dx + neg di + jne @@end + inc dx +@@end: + xchg ax,di + pop di +popsiret: + pop si + endif + ret + + endp _strtol + + +;*************************************************************** +;>void sort(unsigned long *base:BX!, size_t nel:CX) +;NO386 safe: only used by VCPI +;*************************************************************** + global _sort:near + proc _sort near + + pop ax ;caller return address + pop bx ; base + pop cx ; nel + push cx + push bx + push ax + global sort:near +sort: + ifndef fastsort +; bubble sort + push si + cmp cx,2 + jl popsiret + shl cx,2 +@@loop: + xor ax,ax + jcxz popsiret + mov si,4 +@@next: + mov edx,[bx+si-4] + cmp edx,[bx+si] + jbe @@ok + xchg edx,[bx+si] + mov [bx+si-4],edx + mov ax,si +@@ok: + add si,4 + cmp si,cx + jb @@next + xchg ax,cx + jmp @@loop + else +; shell sort (c) uclibc GPL + push si di +; { +;> size_t wgap:SI; +; +; if (nel > 1) { + cmp cx,1 + jbe @@end +; wgap = 0; + xor ax,ax +; do { +@@wgaplp: + mov si,ax +; wgap = 3 * wgap + 1; + mov dx,3 + mul dx + inc ax +; } while (wgap < (nel-1)/3); + cmp ax,cx + jb @@wgaplp +; /* From the above, we know that either wgap == 1 < nel or */ +; /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */ +; wgap *= 4; /* So this can not overflow if wnel doesn't. */ + shl si,2 +; nel *= 4; /* Convert nel to 'wnel' */ + shl cx,2 +; do { +@@lp1: +;> size_t i:DI; +; i = wgap; + mov di,si +; do { +@@lp2: +;> size_t j:DX; +; j = i; + mov dx,di +; do { +@@lp3: +;> register char *a:BX!; +; +; j -= wgap; + sub dx,si +; a = j + ((char *)base); + push bx + add bx,dx +; if (cmp(a, a + wgap) <= 0) { + mov eax,[bx] + cmp eax,[bx+si] + jbe @@brk3 +; break; +; } + xchg eax,[bx+si] + mov [bx],eax +; swap(a, a + wgap); + pop bx +; } while (j >= wgap); + cmp dx,si + jae @@lp3 + push bx +@@brk3: + pop bx +; i += 4; + add di,4 +; } while (i < nel); + cmp di,cx + jb @@lp2 +; wgap = (wgap - 4)/3; + sub si,4 + xchg ax,si + cwd + mov si,3 + div si ; kill dx + xchg ax,si +; } while (wgap); + or si,si + jnz @@lp1 +@@end: +; } +;} + pop di si + ret +endif + + endp _sort + + +;*************************************************************** +;void* malloc(unsigned sz); +;*************************************************************** + global _malloc:near + proc _malloc near + + pop ax ;caller return address + pop cx ; sz + push cx + push ax + global malloc:near ; malloc(cx) +malloc: + mov ax,[_heap_top] + mov bx,sp + sub bh,14h ; MIN_STACK=_1k+PAGE_SIZE + sub bx,cx + jb @@outofmem + cmp bx,ax + jb @@outofmem + add [_heap_top],cx ; _BEG has zero'd heap + ;mov bx,ax +@@zalloc: + ;mov [byte bx],0 + ;inc bx ; ZF=0 + ;loop @@zalloc + ret +@@outofmem: + mov bx,offset msg_malloc + call puts + xor ax,ax ; ZF=1 + ret + + endp _malloc + + + ifdef NO386 +;*************************************************************** +;u16 topseg(); +;*************************************************************** + global _topseg:near + proc _topseg near + + int 12h + jnc @@max640k + mov ax,640 ; 9000 +@@max640k: + sub al,040h + and al,0C0h + mov cl,6 + shl ax,cl + ret + + endp _topseg + endif + + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/CRTL.H --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/CRTL.H Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,53 @@ +// This file is distributed under GPL +// +// Bare bones of C runtime library + +#define MK_FP(seg,ofs) ((void _seg *)(seg) + (void near *)(ofs)) +#define FP_SEG(fp) ((unsigned) (void _seg*) (void far*)(fp)) +#define FP_OFF(fp) ((unsigned) (fp)) + +const unsigned MIN_STACK = 0x400; +const unsigned MAX_MALLOC = 0xF000; + +const O_RDONLY = 0; // for open() +const O_BINARY = 0; + +const SEEK_SET = 0; // for lseek() +const SEEK_CUR = 1; +const SEEK_END = 2; + +extern char text_start; extern char text_end; +extern char data_start; extern char data_end; +extern char bss_start; extern char bss_end; +extern char* heap_top; + +extern int ximage_size, ximage_fd; + +void parse_cmdline(); +extern "C" int strlen(const char* s); +extern "C" int strhead(const char* a,const char* b); +extern "C" int open(const char* name, int flags); +extern "C" int close(int fd); +extern "C" void exit(int n); +extern "C" void abort(); +extern "C" int read(int fd, void* data, int sz); +extern "C" int write(int fd, const void* data, int sz); +extern "C" long lseek(int fd, long sz, int dir); +extern "C" long rewind(int fd); +extern "C" void* malloc(unsigned sz); +extern "C" void puts(const char* s); +extern "C" void putsz(const char* s); +extern "C" unsigned long strtol(const char *s); + +// Extensions +//static void barrier() {} +//static void cli() { asm { cli } } +//static void sti() { asm { sti } } +#define barrier() do {} while(0) +#define cli() do { asm { cli } } while(0) +#define sti() do { asm { sti } } while(0) +#define int3() do { asm { db 0cch } } while(0) +#define nop() do { asm { db 90h } } while(0) +extern char no_exit; +extern "C" int die(const char* msg); +extern "C" char* malloc_or_die(unsigned size); diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/CRTLX.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/CRTLX.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,401 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_DATA,_BSS + assume cs:DGROUP,ds:DGROUP + + segment _DATA byte public use16 'DATA' + ends _DATA + + segment _BSS byte public use16 'BSS' + +ultoabuf db 12 dup (?) + + ends _BSS + + segment _TEXT byte public use16 'CODE' + +;*************************************************************** +;char* strcpy(const char* a,const char* b); +;*************************************************************** + global _strcpy:near + proc _strcpy near + + mov dl,0 +cat: + pop cx ;caller return address + pop ax ; a + pop bx ; b + push bx + push ax + push cx + push ax si + xchg ax,si + shr dl,1 + jnc @@nocat +@@catlp: + lodsb + cmp al,0 + jne @@catlp + dec si +@@nocat: + sub bx,si +@@cpylp: + mov al,[bx+si] + test dl,1 + jnz @@nocpy + mov [si],al + inc si + cmp al,0 + jne @@cpylp + pop si ax + ret +@@nocpy: + sub al,[si] + jnz @@out + lodsb + cmp al,0 + jne @@cpylp +@@out: + cbw + pop si dx + ret + + endp _strcpy + + +;*************************************************************** +;char* strcat(const char* a,const char* b); +;*************************************************************** + global _strcat:near + proc _strcat near + + mov dl,1 + jmp cat + + endp _strcat + + +;*************************************************************** +;int strcmp(const char* a,const char* b); +;*************************************************************** + global _strcmp:near + proc _strcmp near + + mov dl,2 + jmp cat + + endp _strcmp + + +;*************************************************************** +;char strstr(const char* a,const char* b); +;*************************************************************** + global _strstr:near + proc _strstr near + + pop ax ;caller return address + pop bx ; a + pop dx ; b + push dx + push bx + push ax + push di +@@loop: + xor ax,ax + cmp [bx],al + jz @@end + mov cx,bx + mov di,dx + sub di,bx +@@match: + mov al,[bx+di] + or al,al + jz @@found + inc bx + cmp al,[bx-1] + jnz @@loop + jmp @@match +@@found: + xchg ax,cx +@@end: + pop di + ret + + endp _strstr + + +;*************************************************************** +;int cpuhaslm(void) +;*************************************************************** + global _cpuhaslm:near + proc _cpuhaslm near + + pushf +; Check for oldies + mov ax, 0F000h + push ax ; < 286 : flags[12..15] are forced 1 + popf ; = 286 : flags[12..15] are forced 0 + pushf ; > 286 : only flags[15] is forced 0 + pop dx + popf + add dh,ah ; NS=386+, NC=286 + cbw + clc + js @@bad ;it is a 86/186/286, not a 386+ + pushfd + pushfd + pop ebx + mov ecx,ebx + xor ebx,00100000h ; toggle CPUID feature bit 21 + push ebx + popfd + pushfd + pop ebx + popfd + xor ebx,ecx + shr ebx,1+21 ; CPUID feature bit ? + jnc @@bad + mov eax,80000001h ; Extended Processor Info and Feature Bits + db 0Fh,0A2h ; cpuid + xor ax,ax + shr edx,1+29 ; LM feature bit ? +@@bad: + sbb ax,ax + ret + + endp _cpuhaslm + + +;*************************************************************** +;char *progname(void) +;*************************************************************** + global _progname:near + proc _progname near + + push si di es + mov ah,30h + int 21h + cmp al,3 + mov ax,0 + jb @@skip + mov es,[cs:2Ch] + mov cx,-1 + xor di,di + xor al,al +@@loop1: + repne + scasb + scasb + jne @@loop1 + lea si,[di+2] + mov bx, si + extrn strlen:near + call near strlen + xchg ax,cx + inc cx + extrn malloc_or_die:near + call near malloc_or_die + xchg ax,di + push ds + push ds + push es + pop ds + pop es + push di +@@loop2: + lodsb + stosb + or al,al + jnz @@loop2 + pop ax + pop ds +@@skip: + pop es di si + ret + + endp _progname + + +;*************************************************************** +;int chdir(char *path); +;*************************************************************** + global _chdir:near + proc _chdir near + + pop ax + pop dx + push dx + push ax +chdir: + stc + mov ax,713Bh + int 21h + jnc @@end + mov ah,3Bh + int 21h +@@end: + sbb ax,ax + ret + + endp _chdir + + +;*************************************************************** +;int chdirname(char *path) +;*************************************************************** + global _chdirname:near + proc _chdirname near + + pop ax + pop bx + push bx + push ax + + cmp [byte bx+1],3Ah + jne @@nodisk + mov dl,[bx] + or dl,20h + sub dl,61h + mov ah,0Eh + push bx + int 21h + pop bx + inc bx + inc bx +@@nodisk: + mov dx,bx + xor cx,cx +@@next: + mov al,[bx] + cmp al,5Ch + jne @@tsteos + mov cx,bx +@@tsteos: + inc bx + or al,al + jnz @@next + cbw + jcxz @@end + mov bx,cx + push [word bx] + mov [bx],al + push bx + call chdir + pop bx + pop [word bx] +@@end: + ret + + endp _chdirname + + +;*************************************************************** +;char *ultoa(unsigned long n); +;*************************************************************** + global _ultoa:near + proc _ultoa near + + pop ax + pop cx + pop dx + push dx + push cx + push ax ; DX:CX = n + push si + mov si,10 + mov bx,offset ultoabuf+11 +@@loop: + dec bx + xchg ax,dx + xor dx,dx + div si ; DX:AX = 0000:hi(n) + xchg ax,cx ; CX = hi(n)/10 + div si ; DX:AX = hi(n)%10:lo(n) + xchg ax,cx ; CX = lo(n/10) + xchg ax,dx ; DX = hi(n)/10 = hi(n/10) + add al,'0' + mov [bx],al + mov ax,cx + or ax,dx + jnz @@loop + xchg ax,bx + pop si + ret + + endp _ultoa + + +;*************************************************************** +;unsigned long kver2ul(char *kernel_version); +;*************************************************************** + global _kver2ul:near + proc _kver2ul near + + pop ax + pop dx + push dx + push ax + push bp si di + xor di,di + push di + push di + mov bp,sp + mov si,dx + inc di + inc di + mov cl,4 +@@number: + xor ax,ax +@@digit: + shl al,cl + shl ax,cl + lodsb + sub al,30h + cmp al,9 + jbe @@digit + mov [bp+di],ah + dec di + jns @@number + pop ax + pop dx + pop di si bp + ret + + endp _kver2ul + + global N_LXURSH@:near + proc N_LXURSH@ near + + mov ch,0 +@@loop: + shr dx,1 + rcr ax,1 + loop @@loop + ret + + endp N_LXURSH@ + + global N_LXLSH@:near + proc N_LXLSH@ near + + mov ch,0 +@@loop: + shl ax,1 + rcl dx,1 + loop @@loop + ret + + endp N_LXLSH@ + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/CRTLX.H --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/CRTLX.H Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,13 @@ +// This file is distributed under GPL +// +#define NULL 0 +extern "C" char* strstr(const char* a,const char* b); +extern "C" char* strcat(const char* a,const char* b); +extern "C" char* strcpy(const char* a,const char* b); +extern "C" int strcmp(const char* a,const char* b); +extern "C" int cpuhaslm(); +extern "C" char *progname(void); +extern "C" int chdir(char *path); +extern "C" int chdirname(char *path); +extern "C" unsigned long kver2ul(char *kernel_version); +extern "C" char *ultoa(unsigned long n); diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/HIMEM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/HIMEM.CPP Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,96 @@ +// This file is distributed under GPL +// +// High mem handling routines +// C++ part of VCPI madness is here + +#include "crtl.h" +#include "common.h" + +// Returns physical addr of allocated himem chunk +// Never fails (will use fallback if not enough mem/no xmm) +// TODO: with proper cleanup it is possible to exit to DOS +// even after XMM alloc - do dealloc, then exit... +// don't forget to clean up the mess then, especially +// XMM handle which is lost inside xmm_alloc()... +// (don't drop fallback: use it if no XMM driver detected) +static void read2mem(struct image_himem *m) { + u32 buf=m->buf; + while(1) { + u8 xfer_buf[PAGE_SIZE]; + u16 size = read_image(m, xfer_buf, sizeof(xfer_buf)); + if(s16(size) <= 0) break; + memcpy32(0, buf, seg(xfer_buf), ofs(xfer_buf), size); + buf += size; + m->remaining -= size; + } +} + +extern "C" void sort(u32* v, int size); + +// Returns ptr to mallocated zero-terminated list of physical page addrs +// Never fails (will die if not enough mem) +// Addresses are sorted in ascending order +// static void malloc_vcpi(struct image_himem *m) { +static void read2vcpi(struct image_himem *m) { + u16 cnt = (m->size+PAGE_MASK)/PAGE_SIZE; + u32* bufv = (u32*)malloc_or_die((cnt+1)*sizeof(u32)); + // our malloc zeroes allocated mem: buf[cnt]=0; + // Allocate pages, storing addrs in addrbuf + {for(int i=0;ibufv = bufv; +//} + +// Reads opened fd data into malloc_vcpi'ed memory +// Dies if file isn't exactly 'size' bytes long +// Needs intermediate buffer of exactly Nx4k bytes +// static void read2vcpi(struct image_himem *m) { + while(1) { + u8 xfer_buf[PAGE_SIZE]; + u16 size = read_image(m, xfer_buf, PAGE_SIZE); + if(s16(size) <= 0 || !*bufv) break; + m->remaining -= size; + memcpy_vcpi(*bufv++, seg(xfer_buf), ofs(xfer_buf)); + } +} + +void init_vcpi() { + heap_top = prepare_vcpi(malloc_or_die(8*1024+4)); + get_vcpi_interface() || die("VCPI: low 640k: need 1:1 mapping"); +} + +int skip_xmmalloc; +void load_image(struct image_himem *m) { + no_exit++; // die() won't return to DOS + m->remaining = m->size; + m->buf = m->fallback; + if(m->fallback < _1m) { + read2mem(m); + } else if(vcpi==0) { + if (!skip_xmmalloc) { + u32 v = xmm_alloc(m->size); + if(v) m->buf = v; + } + read2mem(m); + } else { + //malloc_vcpi(m); + read2vcpi(m); + } + if(m->remaining) die("Read error"); +//break iso case close(m->fd); +} + diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/ISO9660.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/ISO9660.CPP Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,172 @@ +#include "crtl.h" +#include "crtlx.h" +#include "iso9660.h" +#define __ROCKRIDGE + +char *isofilename; +unsigned long isofileofs, isofilesize; +unsigned short isofilemod; +int isofd; + +#define SECTORSZ 2048 +#define SECTORBITS 11 +static char buffer[SECTORSZ]; + +static int readsector(unsigned long offset) +{ + return (lseek(isofd, offset, SEEK_SET) != -1 + && read(isofd, buffer, SECTORSZ) == SECTORSZ); +} + +int isoread(char *data, unsigned size) +{ + int get, n; + + if (size > isofilesize) + size = isofilesize; + if (lseek(isofd, isofileofs, SEEK_SET) == -1) + return -1; + for (get = size; get; get -= n, data += n) { + n = read(isofd,data,get); + if (n < 0) + return n; + if (n == 0) + break; + isofileofs += n; + isofilesize -= n; + } + return size - get; +} + +static unsigned long isodirofs, isodirsize; +int isoreset(char *name) +{ + if (name) + isofd = open(name, O_RDONLY); + if (!readsector(16UL * 2048) || strhead(buffer+1,"CD001")) { + //close(isofd); + return -1; + } + isodirofs = * (unsigned long *) (buffer + 0x9E); + isodirofs <<= SECTORBITS; + isodirsize = * (unsigned long *) (buffer + 0xA6); + return 0; +} + +int isoreaddir(int restart) +{ + static unsigned long pos, dirofs, dirsize; + static char dots[] = ".."; + int size, n; +#ifdef __ROCKRIDGE + char *endname; +#endif + + if (restart) { + dirofs = isodirofs; + dirsize = isodirsize; + pos = SECTORSZ; + } + if (pos >= SECTORSZ || * (short *) (buffer + pos) == 0) { + if (dirsize < SECTORSZ) return -1; + readsector(dirofs); + dirofs += SECTORSZ; + dirsize -= SECTORSZ; + pos = 0; + } + size = * (short *) (buffer + pos); + if (size == 0) + return -1; + isofileofs = (* (unsigned long *) (buffer + pos + 2)) << SECTORBITS; + isofilesize = * (unsigned long *) (buffer + pos + 10); + isofilemod = (buffer[pos + 25] & 2) ? 0040755 : 0100755; +#ifdef __ROCKRIDGE + endname = NULL; + n = (buffer[pos + 32] + pos + 34) & -2; + do { + int len = buffer[n + 2]; + switch (* (short *) (buffer + n)) { + case 0x4D4E: // NM + isofilename = buffer + n + 5; + endname = buffer + n + len; + break; + case 0x5850: // PX + isofilemod = * (short *) (buffer + n + 4); + break; + } + n += len; + } + while (n + 2 < pos + size); + if (endname) + *endname = 0; + else +#endif + { + isofilename = buffer + pos + 33; + switch (* (short *) (isofilename - 1)) { + case 0x0101: + isofilename = dots; + break; + case 0x0001: + isofilename = dots + 1; + break; + default: + n = isofilename[-1]; + if (* (short *) (isofilename + n - 2) == 0x313B) + n -= 2; // remove ;1 + if (isofilename[n - 1] == '.') n--; + isofilename[n] = 0; + } + } + pos += size; + return 0; +} + +#define IS_DIR(x)( ((x) & ~0777) == 040000) +int isoopen(char *filename) +{ + int restart; + char *name, *s, c; + int _64bits = cpuhaslm(); + +retry32: + name = filename; + while (*name == '/') { + name++; + isoreset(NULL); + } + s = name; + while (1) { + while (*s && *s != '/') s++; + c = *s; + *s = 0; + for (restart = 1; isoreaddir(restart) == 0; restart = 0) { + char *n = name, *i = isofilename; + if (_64bits) { + int len = strlen(name); + if (strhead(isofilename, name)) continue; + n = "64"; + i += len; + } + if (strcmp(n, i)) continue; + if (IS_DIR(isofilemod)) { + isodirofs = isofileofs; + isodirsize = isofilesize; + if (c) { + *s++ = c; + name = s; + goto next; + } + } + lseek(isofd, isofileofs, SEEK_SET); + return 0; + } + if (_64bits) { + _64bits = 0; + *s = c; + goto retry32; + } + return -1; + next: ; + } +} diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/ISO9660.H --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/ISO9660.H Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,12 @@ +#ifndef __ISO9660_H +#define __ISO9660_H +extern char *isofilename; +extern unsigned long isofileofs, isofilesize; +extern unsigned short isofilemod; +extern int isofd; +extern int isoreset(char *name); +extern int isoopen(char *name); +extern int isoreaddir(int restart); +extern int isoread(char *data, unsigned size); +#define isolabel() do { isofileofs=0x8028; isofilesize=32; } while (0) +#endif diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/JUMP.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/JUMP.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,133 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_BSS + assume cs:DGROUP,ds:DGROUP + + segment _BSS byte public use16 'BSS' + + global _pm_high:byte + global _pm:dword + + ends _BSS + + + segment _TEXT byte public use16 'CODE' + +;*************************************************************** +;void set_sregs_jump_seg_ofs(u32 csip, u32 sssp); +;****** Never returns +;*************************************************************** + global _set_sregs_jump_seg_ofs:near + proc _set_sregs_jump_seg_ofs near + + extrn dos_shutdown:near + + pop ax ;caller return address + test [byte _pm_high],-1 ; load high ? clear CF + jne isbzimage + ; finish loading + extrn @last_ditch$qv:near + push cs + call @last_ditch$qv + mov bx,[word _pm+2+2] ; get pm->fallback high word + ; self move + cld + ; push 9940h ; 5120 bytes for cmdline + push 9820h ; 512 bytes for cmdline + pop es ; min 1024 bytes for stack + xor si,si ; A000 -9400 -0800(>movedend) + xor di,di ; set ZF + ; mov cx,offset movedend + global _bss_end:byte + mov cx,offset _bss_end + rep + movsb + push es + call near doretf ; mov cs,es + stc +isbzimage: + pop cx ; ip + pop dx ; cs + pop ax ; sp + pop ss ; ss + xchg sp,ax + push dx cx + jnc nomove + push cs + pop ds + call near dos_shutdown + ; move zImage pm + mov ax,8 + cwd + cmp bx,ax + jnb bufhigh + sub ax,bx + inc ax +bufhigh: + push ax + push dx ; size=up to 512k + push bx ; src ofs= pm.fallback + push dx + push dx ; srcseg=0 + push 1 ; dst + push dx ; ofs=64k + push dx ; dstseg=0 + extrn _memcpy32:near + call _memcpy32 + add sp,16 + + ifndef noelks + push ss + pop ds + ifndef NO386 + cmp [dword 1E6h],'SKLE' + else + cmp [word 1E6h],'LE' + jne notelks + cmp [word 1E8h],'SK' + endif + jne notelks + push 100h + pop es + xor si,si + xor di,di + mov ch,05h + rep + movsw + push es + pop ss + push 120h + push 0 +notelks: + endif + +nomove: + push ss + pop ds + push ss + pop es + push ss + pop fs + push ss + pop gs + assume nothing + assume cs:DGROUP + +doretf: + retf + +movedend: + endp _set_sregs_jump_seg_ofs + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/LINK.CMD --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/LINK.CMD Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,1 @@ +_beg.obj memcpy32.obj jump.obj vcpi.obj himem.obj crtl.obj memtop.obj xmm.obj a20.obj load.obj linld.obj _end.obj, linld diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/LINKX.CMD --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/LINKX.CMD Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,1 @@ +_beg.obj memcpy32.obj jump.obj vcpi.obj himem.obj crtl.obj crtlx.obj memtop.obj xmm.obj a20.obj load.obj iso9660.obj tazboot.obj _end.obj, tazboot diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/LINLD.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/LINLD.CPP Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,113 @@ +// This file is distributed under GPL +// +// LINLD main() lives here + +#include "crtl.h" +#include "common.h" + +static struct image_himem image; +static const char msg_cmdline[] = "Error reading cl=@file"; +static char* read_cmdline_or_die(const char* fn) { + image.errmsg = msg_cmdline; + open_image(fn, &image); + u16 size=image.size; + char *cmdline_buf; + if(size>=PAGE_SIZE || + !(cmdline_buf=(char *)malloc(size)) || + read(image.fd, cmdline_buf, size) != size) + die(msg_cmdline); + // Strip any trailing cr/lf + char *p=cmdline_buf+size; + char c='\0'; + do { + // Replace all other cr/lfs with spaces + if(*--p>=' ') c=' '; + else *p = c; + } while (p>cmdline_buf); + return cmdline_buf; +} + +const char* kernel_name = "bzImage"; +const char* initrd_name; +const char* cmdline = "auto"; +u16 root_dev; +u16 vid_mode; // -3 = ask + // -2 = Extended VGA + // -1 = Normal VGA + // n = as "n" was pressed + +inline void syntax() { + die("Syntax:" NL + "LINLD [image=file] [initrd=files] [vga=mode] [root=num] [mem=max] [cl=cmdline]" NL + "vga mode: ask,extended,normal or dec/oct/hex number" NL + "Defaults:" NL + "\timage=bzImage" NL + "\tinitrd,vga,root=(void)" NL + "\tmem=256m" NL + "\tcl=auto" NL + "Use quotes: \"cl=...\" if you need spaces in cmdline" NL + "Use cl=@filename to take cmdline from file" +#if 1 + NL NL "Examples:" NL + "\tlinld initrd=rootfs4.gz,rootfs3.gz,rootfs2.gz,rootfs1.gz \"cl=rw root=/dev/null video=-32\"" + NL NL "\tlinld image=memtest" +#endif + ); +} + +int main(int argc, char *argv[]) { + // Believe it or not - this enables A20 + // on my box! Must be DOS in HMA... -vda + puts("LINLD v" VERSION_STR "+"); + + // Parse command line + + if(argc<2) { +dosyntax: + syntax(); + } + {for(int i=1;i pm kernel info is lost if it was here... + So I had to stick to 90000. + +10000000+------------------------+ <- 256m + | initrd | initrd is at top of mem, but + | | not higher than 256m + +------------------------+ + +------------------------+ + | bzImage | bzImage is at 1m + | | VCPI/XMS/64k offset tricks used... +00100000+------------------------+ <- 1m + | video, BIOS etc | Do not use. +000A0000+------------------------+ + | Reserved for BIOS | Do not use. Reserved for BIOS EBDA. +0009A000+------------------------+ <- stack top for kernel rm code + | Cmdline | +00098000+------------------------+ <- heap top for kernel rm code + | Kernel setup | The kernel real-mode code. +00090200+------------------------+ + | Kernel boot sector | The kernel legacy boot sector. +00090000+------------------------+ + | Zapped by ungzip | Historically zImages were loaded here + | (zImage once was here) | bzImages use this space for ungzipping +00010000+------------------------+ + | Boot loader | <- Boot sector entry point 0000:7C00 +00001000+------------------------+ + | Reserved for MBR/BIOS | +00000800+------------------------+ + | Typically used by MBR | +00000600+------------------------+ + | BIOS use only | +00000000+------------------------+ +*/ + +struct first1k_t { + // these two set by rm setup: + u16 curr_curs; // 0000 saved cursor position + u16 ext_mem_size; // 0002 extended memory size in Kb (from int 0x15 fn 0x88) + u8 pad00[0x20-4]; + // old-style cmdline (not used in LINLD (yet?)) + u16 cl_magic; // 0020 commandline magic number (=0xA33F) + u16 cl_ofs; // 0022 commandline offset + u8 pad10[0x80-0x24]; + // these two set by rm setup: + u8 hd0_disk_par[16]; // 0080 hd0-disk-parameter from intvector 0x41 + u8 hd1_disk_par[16]; // 0090 hd1-disk-parameter from intvector 0x46 + u8 pad20[0x01e0-0xa0]; + // this is set by rm setup: + u32 alt_mem_size; // 01E0 extended memory size in Kb (from int 0x15 fn 0xe801) + u8 pad28[0x01f1-0x1e4]; + + u8 setup_sects; // 01F1 The size of the setup in sectors + // boot sector is NOT included here + u16 ro_flag; // 01F2 If set, the root is mounted readonly + u16 syssize; // 01F4 DO NOT USE - for bootsect.S use only: + // size of pm part of kernel + // (in 16 byte units, rounded up) + u16 swap_dev; // 01F6 DO NOT USE - obsolete + u16 ram_size; // 01F8 DO NOT USE - for bootsect.S use only: + // if nonzero then kernel + // (driver/block/ramdisk.c: rd_load()) + // will try to load the contents for the ramdisk + // from the "root_dev" which MUST then have the + // floppyMAJOR + // The file-system on that floppy must be MINIX + // If rd_load() succeeds it sets the root_dev + // to the ramdisk for mounting it + u16 vid_mode; // 01FA Video mode control + u16 root_dev; // 01FC Default root device number + u16 boot_flag; // 01FE 0xAA55 magic number + u16 jump; // 0200 Jump instruction + u32 header; // 0202 Magic signature "HdrS" + u16 version; // 0206 Boot protocol version supported + u16 realmode_switch_ofs; // 0208 Hook called just before rm->pm + u16 realmode_switch_seg; + u16 start_sys_seg; // 020E + u16 kernel_version; // 020C Points to kernel version string + u8 type_of_loader; // 0210 Boot loader identifier + u8 loadflags; // 0211 Boot protocol option flags + u16 setup_move_size;// 0212 Move to high memory size (used with hooks) + u32 code32_start; // 0214 Boot loader hook (see below) + u32 initrd_buf; // 0218 initrd load address (set by boot loader) + u32 initrd_size; // 021C initrd size (set by boot loader) + u32 bootsect_kludge;// 0220 DO NOT USE - for bootsect.S use only + u16 heap_end_ptr; // 0224 Free memory after setup end + u16 pad1; // 0226 Unused + u32 cmd_line_ptr; // 0228 32-bit pointer to the kernel command line + u8 pad30[0x400-0x22c]; // 022C + // 02D0 up to 32 20-byte mem info structs from + // int 0x15 fn 0xe820 +}; //__attribute((packed)); + +#if sizeof(first1k_t)!=0x400 +#error BUG: Bad first1k +#endif + +const u32 HdrS = 'H' + ('d'<<8) + (u32('r')<<16) + (u32('S')<<24); + +u8* rm_buf; +static u16 rm_size; +u8 pm_high; +struct image_himem pm; +struct image_himem initrd; + +static void memcpy_image(struct image_himem *m) { + if (m->fallback != m->buf) + memcpy32( + 0, m->fallback, // dst seg,ofs + 0, m->buf, // src seg,ofs + m->size // size + ); +} + +// Called from inside kernel just before rm->pm +// _loadds _saveregs: done by hand +void far last_ditch() { + cli(); // we start doing *really* destructive things to DOS/BIOS + // it means: do not even try to enable ints + // or call BIOS services after this + asm { + push ds + push cs + pop ds +#ifndef NO386 + pusha +#else + push ax + push bx + push cx + push dx +#endif + } + if(pm.fallback > _1m) pm.fallback = _1m; + if(vcpi==0) { + // Move kernel + memcpy_image(&pm); + // Move initrd + memcpy_image(&initrd); + } else { //vcpi + vm2rm(); + // Move kernel + // 'Gathering' copy in chunks of PAGE_SIZE + // No risk of overlapping: kernel is copied from above to 1m mark + pm.size = PAGE_SIZE; + u32 *p = pm.bufv; + if (p) while(*p) { + pm.buf = *p; + memcpy_image(&pm); + p++; pm.fallback+=PAGE_SIZE; + } + // Move initrd + if(initrd.fallback) { + // This is tricky: copy initrd backwards to reduce + // risk of overlapping: use the fact that initrd is copied + // to the very top of ram + // (overlapping still can happen with more than 256mb ram) + // (generic solution for this overwrite problem, anyone?) + p=initrd.bufv; + initrd.size = PAGE_SIZE; + do { + p++; initrd.fallback+=PAGE_SIZE; + } while(*p); + do { + p--; initrd.fallback-=PAGE_SIZE; + initrd.buf = *p; + memcpy_image(&initrd); + } while(p != initrd.bufv); + } + } + asm { +#ifndef NO386 + popa +#else + pop dx + pop cx + pop bx + pop ax +#endif + pop ds + } +} + +// register value to launch the kernel real mode code +#ifdef NO386 +static u32 sssp; +static u32 csip; +extern "C" u16 topseg(); +#else +const u32 sssp=0x9000A000; +static u32 csip=0x90200000; +#define topseg() 0x9000 +#endif + +static const char kernel_file_error[] = "Can't use kernel file"; +char* load_kernel() { + +#ifdef NO386 + sssp=((u32)topseg()<<16)+0xA000; + csip=((u32)(topseg()+0x20)<<16); +#endif + // Open kernel, read first kb, check it + pm.errmsg = kernel_file_error; + open_image(kernel_name, &pm); + + char *version_string; + { + struct first1k_t *first1k; + first1k = (first1k_t*) (rm_buf = malloc_or_die(_32k)); + { + u16 rm_seek; + + // Do not use malloc below until heap_top adjustment (see <*>) + if (read(pm.fd, rm_buf, rm_seek=0x400) != 0x400) { + readfail: + die(kernel_file_error); + } + + if(!first1k->setup_sects) { +#if 1 + if(* (int *) &first1k->pad10[0x3F-0x24] == 0x3AE8) { + lseek(pm.fd,rm_seek=0x200,SEEK_SET); + csip=((u32)topseg()<<16)+0x0042; + } + else +#endif + first1k->setup_sects=4; + } + rm_size = 0x200*(first1k->setup_sects+1); // 0th sector is not counted there + if(rm_size>_32k || first1k->boot_flag != 0xAA55) + die("It's not a kernel"); + heap_top = rm_buf+rm_size; // <*> + + // Read remaining rm loader + + { + u16 cnt = rm_size-rm_seek; + if (read(pm.fd, rm_buf+rm_seek, cnt) != cnt) goto readfail; + } + } + + // Tell rm loader some info + + if(vid_mode) first1k->vid_mode = vid_mode; + if(root_dev) first1k->root_dev = root_dev; + version_string = 0; + +#if 1 + if(first1k->header == HdrS) { // starting linux 1.3.73 + if(first1k->loadflags & 1) { +#else + if((first1k->header != HdrS) || (first1k->loadflags & 1) == 0) + die("I can't load bzImage low"); + { + { +#endif + pm_high++; + + // Hook on int15 to work around fn 88 DOS breakage + hook_int15_88(); + + // * will be called just before rm -> pm + first1k->realmode_switch_ofs = ofs(last_ditch); + first1k->realmode_switch_seg = seg(last_ditch); + } + if(first1k->kernel_version) + version_string = (char *) first1k+first1k->kernel_version+0x200; + first1k->type_of_loader = 0xff; // kernel do not know us (yet :-) + if(first1k->version >= 0x201) { + // * offset limit of the setup heap + // heap_end_ptr appears to be relative to the start of setup (ofs 0x0200) + first1k->heap_end_ptr = _32k-0x0200; + first1k->loadflags |= 0x80; // says to rm loader it's ok to use heap + } + // * if we will ever stop moving ourself to 0x90000 + // we must say setup.S how much to move + //first1k->setup_move_size = _32k; + if(first1k->version >= 0x202) { // starting linux 2.4.0-test3-pre3 + first1k->cmd_line_ptr = (((u32)(topseg()+0x0800))<<4); + goto cmd_line_ok; + } + } + first1k->cl_magic = 0xA33F; + first1k->cl_ofs = 0x8000; + } + +cmd_line_ok: + // Check and enable A20 if needed + enable_a20_or_die(); + + // Read remaining kernel (pm part) + // Try to load kernel high, maybe even blindly storing it + // in unallocated memory as a last resort + + pm.fallback = (u32((u16(_CS)+0x1FFF)&0xF000)<<4); + pm.size -= rm_size; + if(pm.fallback+pm.size > (((u32)topseg())<<4) || pm_high) { + pm.fallback = _1m+_64k; + } + + load_image(&pm); + return version_string; +} + +// Read initrd if needed + +static const char msg_initrd[] = "Can't use initrd file"; +void load_initrd() { + struct image_himem *m = &initrd; + if (!initrd_name && !initrd.fd) return; + if (!pm.fd) { +noinitrd: + puts(msg_initrd); + return; + } + m->errmsg = msg_initrd; + open_image(initrd_name, m); + + m->fallback = (memtop()-m->size) & (~PAGE_MASK); + if (m->fallback < pm.fallback + pm.size) { + close(m->fd); + goto noinitrd; + } + + load_image(m); + struct first1k_t *first1k = (first1k_t*)rm_buf; + if(first1k->header == HdrS) { + first1k->initrd_buf = m->fallback; + first1k->initrd_size = m->size; + } +} + +void boot_kernel() { + + // Shrink stack: we won't need much of it now and have no malloc() plans + { + u16 new_SP=u16(heap_top)+0x100; + if(_SP>new_SP) _SP=new_SP; + } + if( u16(_CS)+(u16(_SP)>>4) >= topseg() ) { + // Oops! We can stomp on our toes... better stop now + die("Loaded too close to 9000:0"); + } + + cli(); // we start doing destructive things to DOS + + // Move rm loader & commandline to 0x90000 + if(vcpi==0) { + memcpy32( + topseg(),0, + seg(rm_buf),ofs(rm_buf), + rm_size //_32k + ); + memcpy32( + topseg()+0x0800,0, + seg(cmdline),ofs(cmdline), + PAGE_SIZE + ); + } else { //vcpi + u32 dst=((u32)topseg()<<4); + u16 pos=ofs(rm_buf); + do { + memcpy_vcpi(dst,seg(rm_buf),pos); + dst+=PAGE_SIZE; + pos+=PAGE_SIZE; + rm_size-=PAGE_SIZE; + } while(s16(rm_size) > 0); + // overkill: copy PAGE_SIZE bytes + memcpy_vcpi(((u32)(topseg()+0x0800)<<4),seg(cmdline),ofs(cmdline)); + } + + // Jump to kernel rm code + set_sregs_jump_seg_ofs(csip, sssp); +} diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/MEMCPY32.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/MEMCPY32.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,351 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_DATA + assume cs:DGROUP,ds:DGROUP + + segment _DATA byte public use16 'DATA' +msg_badcpu db "I need 386+ CPU in real mode or under VCPI manager",0 + ends _DATA + + segment _TEXT byte public use16 'CODE' + +;*************************************************************** +;int _is_vm86(); +;****** Return: AX=1 - it is a 386+ in virtual86 mode with vcpi +;****** AX=0 - it is a 386+ in real mode +;****** otherwise abort program +;****** Uses: Flags +;*************************************************************** + global _is_vm86:near + proc _is_vm86 near + +; Check for oldies + mov ax, 0F000h + pushf + push ax ; < 286 : flags[12..15] are forced 1 + popf ; = 286 : flags[12..15] are forced 0 + pushf ; > 286 : only flags[15] is forced 0 + pop dx + popf + add dh,ah ; NS=386+, NC=286 + ifndef NO386 + js @@no_vcpi ;it is a 86/186/286, not a 386+ + else + js @@ret + endif +; Check for vm + smsw ax ;SMSW cannot be trapped! :-) + and ax,1 ;MSW_PE +; We're in vm + jnz check_vcpi + +; It's a 386 in real mode, chk for paging (crazy but possible) + mov edx,cr0 + shl edx,1 ;CR0_PG to CF + jc @@no_vcpi +@@ret: + ret + +;*************************************************************** +;****** Helper: checks for vcpi +;*************************************************************** +label check_vcpi near + push ds +; Check whether it is safe to call 67h (we trust only known EMM managers) + push 0 + pop ds + mov ds,[word 67h*4+2] + cmp [dword 10+4],'0XXX' + jne @@skip + mov eax,[dword 10] + cmp eax,'XMME' + je @@skip + ; this also works (as told by ) + cmp eax,'QMME' +@@skip: + pop ds + jne @@no_vcpi +; Check emm manager status and version + mov ah,40h ; get status + int 67h + test ah,ah + jnz @@no_vcpi + mov ah,46h ; get version + int 67h + test ah,ah + jnz @@no_vcpi + cmp al,40h ; version must be >= 4.0 + jb @@no_vcpi +; Check vcpi manager status + ;;mov ax,5A01h ; ALLOCATE RAW PAGES + ;;mov bx,4 + ;;int 67h + ;;test ah,ah + ;;jnz @@no_vcpi + ;;push dx ;$ save handle + mov ax,0DE00h ; check for vcpi present + int 67h + mov al,1 + test ah,ah + jz @@386vcpi + ;;pop dx ;$ handle + ;;mov ax,4500h ; DEALLOCATE PAGES + ;;int 67h +@@no_vcpi: + mov bx,offset msg_badcpu + extrn die:near + jmp near die +@@386vcpi: + mov [_vcpi],al + extrn @init_vcpi$qv:near + jmp near @init_vcpi$qv + + endp _is_vm86 + + +;*************************************************************** +;void dos_shutdown() +;*************************************************************** + global dos_shutdown:near + proc dos_shutdown near + +;TODO NO386 +dos_shutdown: + pusha + xor bx,bx + mov ds,bx + push [dword bx+4] ; save step + mov ax,sp + push ss + push ax + pop [dword cs:sssp] + ;cmp [byte bx+7],0F0h + ;jnc notdos + mov [word bx+4],offset step19 + mov [bx+6],cs + pushf + pop ax + inc ah ; set TF + push ax + popf + jmp small [dword bx+4*19h] +doiret: + iret +sssp: + dd 0 +step19: + push bx + push ds + mov bx,sp + lds bx,[dword ss:bx+4] ; read cs:ip + cmp [word bx],19CDh ; int 19h ? + pop ds + pop bx + jne doiret +notdos: + lss sp,[dword cs:sssp] + xor bx,bx + mov ds,bx + pop [dword bx+4] ; restore step + popa + push cs + pop ds + ret + + endp dos_shutdown + + +;*************************************************************** +;void memcpy32(u16 dstseg,u32 dstofs,u16 srcseg,u32 srcofs,u32 size); +;*************************************************************** +;****** Uses: Flags +;*************************************************************** + global _memcpy32:near + proc _memcpy32 near + +;TODO NO386 +; rm32,imm16 helper +macro addzx_e rm,i + db 66h + add rm,i + dw 0 +endm + arg dstseg :word, \ + dstofs :dword, \ + srcseg :word, \ + srcofs :dword, \ + sz :dword = PARAM_SIZE + + local GDTR :pword, \ + oldGDTR :pword = TEMP_SIZE + +;****** Init *************************************************** + enter TEMP_SIZE,0 + pushf + push es ds esi edi + movzx esi,[srcseg] + shl esi,4 + add esi,[srcofs] + movzx edi,[dstseg] + shl edi,4 + add edi,[dstofs] + ifndef pm_only + mov eax,00100000h + cmp esi,eax + jnb pmcopy + cmp edi,eax + jnb pmcopy + mov eax,esi + shr eax,4 + mov ds,ax + mov edx,edi + shr edx,4 +@@movlp: + mov ds,ax + mov es,dx + and si,0Fh + and di,0Fh + mov cx,08h + cld + rep movsw + inc ax + inc dx + sub [sz],10h + ja @@movlp + jmp done + endif +pmcopy: + mov ecx,[sz] + mov dx,-1 + + ifdef keep_int15 + jecxz godone + test [_vcpi],dl + jne with_movsw + + push ss + pop es + inc ecx + shr ecx,1 + mov bx,9318h +clear: + push 0 + dec bl + jnz clear + xchg eax,esi + mov si,sp + mov [si+12h],eax + mov [si+1Ah],edi + mov [si+10h],dx + mov [si+18h],dx + mov edi,ecx + mov dh,93h + xchg bx,[si+14h] + xchg dx,[si+1Ch] +mvlp: + mov [si+14h],bl + mov [si+17h],bh + mov [si+1Ch],dl + mov [si+1Fh],dh + xor ecx,ecx + mov ch,80h + sub edi,ecx + pushf + jnc domv + add ecx,edi +domv: + ;push bx dx si edi + mov ah,87h + int 15h + ;pop edi si dx bx + inc bx + inc dx + popf + jnc mvlp + add sp,30h +godone: + jmp done + else + jecxz done + endif + +with_movsw: + cld + cmp esi,edi + jae @@do_copy + add esi,ecx ;src + mov [word GDTR],dx ;GDT limit = 0FFFFh + mov [dword GDTR+2],eax ;GDT base + lgdt [GDTR] + +;****** Go into pm ********************************************* + mov eax,cr0 + or al,01h ;CR0_PE on + mov cr0,eax + jmp short $+2 ;*Required*! + ;3+ NOPs also work fine (chkd on 386) +;****** Move data ********************************************** + push 0008h + pop ds ;base=0, lim = 4gb + push ds ; + pop es ; + db 66h ;operand width override for ecx + db 67h ;address width override for esi/edi + rep movsb + cld + +;****** Return to rm ******************************************* + dec ax ;CR0_PE off + mov cr0,eax ;ds/es limits are *not* reset to 64kb + ; but who cares :-) + jmp short $+2 + +;****** Return ************************************************* + lgdt [oldGDTR] +done: + cld + pop edi esi ds es + popf + leave + ret + +;****** Const data ********************************************* + org $-8 ;save 8 bytes - they are unused anyway +;0000: unused +GDT dd ?,? +;0008: Data seg [0,FFFFFFFF] + ; lim_lo base_lo + dw 1111111111111111b, 0000000000000000b + db 00000000b,10010010b,10001111b,00000000b + ; base_med P S D A G ??l_hi base_hi + ; Pl E W D + + global _vcpi:byte +_vcpi db 0 + + endp _memcpy32 + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/MEMTOP.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/MEMTOP.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,213 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_DATA,_BSS + assume cs:DGROUP,ds:DGROUP + + + segment _DATA byte public use16 'DATA' + + global _topmem:dword + +_topmem dd 10000000h ; max 256m + + ends _DATA + + segment _BSS byte public use16 'BSS' + +saved15 dd ? + + ends _BSS + + + segment _TEXT byte public use16 'CODE' + +;*************************************************************** +;u32 memtopz(); +;*************************************************************** + global _memtopz:near + proc _memtopz near +;*************************************************************** +;u32 memtop_e801() +;*************************************************************** +; proc _memtop_e801 near + + push cx bx + xor cx,cx ;fix to work around buggy + xor dx,dx ; BIOSes which dont clear/set + stc ; carry on pass/error of + mov ax,0E801h + int 15h + jc @@err + test cx,cx ;kludge to handle BIOSes + jnz @@use_cxdx ; which report their extended + test dx,dx ; memory in AX/BX rather than + jnz @@use_cxdx ; CX/DX. The spec I have read +@@use_axbx: mov dx,bx ; seems to indicate AX/BX + jmp @@end_kludge ; are more reasonable anyway... +@@use_cxdx: xchg ax,cx +@@end_kludge: ;now: dx=64k units above 16m + ; ax=1k units above 1m below 16m (max 3c00h) + pop bx cx + test dx,dx + jz tokb ;dx=0 here, ax=kbs above 1m + xor ax,ax ;ignore info on low 16M (assume full) + ;add dx,100h ;account for low 16M + inc dh ;account for low 16M (optimized) + ret +@@err: +; xor ax,ax +; cwd +; ret +; endp _memtop_e801 + + +;*************************************************************** +;u32 memtop_88() +;*************************************************************** +; proc _memtop_88 near + + mov ah,88h + int 15h ;ax=kbs above 1m + jnc @@ok ; error: cf=1 or ax=0 + xor ax,ax ; +@@ok: + xor dx,dx + test ax,ax ;happens on big mem systems + jz @@fail +tokb: + add ah,4h ;account for 1024 low kb + adc dx,dx ; (optimized to death) + ifndef NO386 + shld dx,ax,10 ;multiply by 1024 + shl ax,10 ; (kbytes -> bytes) + else +@@lp: + mov cx,10 + shl ax,1 ;multiply by 1024 + rcl dx,1 + loop @@lp + endif +; mov cx,ax +; or cx,dx ;update ZF +;@@fail: + ret +; endp _memtop_88 + +@@fail: + +; proc _memtopz near + +; call _memtop_e801 +; jnz @@ok +; call _memtop_88 +; jnz @@ok + +;*************************************************************** +;u32 memtop_cmos() +;*************************************************************** + + pushf + cli + call rdcmos17 + popf + xor dx,dx + jmp tokb + +rdcmos17: mov al,18h ; read bytes 17-18 from CMOS + call @@rdcmos + mov ah,al + mov al,17h +@@rdcmos: out 70h,al + call @@ret + in al,71h +@@ret: + ret + + +;*************************************************************** +;u32 memtop(); +;*************************************************************** + global _memtop:near +_memtop: + call _memtopz + mov cx,40h ; min 4m +; If reported mem is ridiculously low, presume +; we had trouble detecting memory size + cmp dx,cx + jb @@set + mov cx,[word _topmem+2] ; max 256m ? +; Kernel can have trouble with initrd at very high addr: +; limit mem top to 256m + cmp dh,ch + jb @@done +@@set: + xchg ax,cx + cwd + xchg ax,dx +@@done: +; Round down to page boundary. +; Or else initrd's tail may end up in last, partial page. +; Kernel will refuse to use such initrd. + and ax,0f000h +;@@ok: + ret + + endp _memtopz + +;*************************************************************** +;void hook_int15_88(); +;*************************************************************** + global _hook_int15_88:near + proc _hook_int15_88 near + + ifndef xmm_hook + mov ax,4300h + int 2fh + cmp al,80h + je @@skip + endif + push 0 + pop es + mov bx,15*4 + ifndef NO386 + mov eax,[bx] + mov [saved15],eax + else + mov ax,[bx] + mov [word saved15],ax + mov ax,[bx+2] + mov [word saved15+2],ax + endif + mov [word bx],offset int15_88 + mov [bx+2],cs +@@skip: + ret +int15_88: + cmp ah,88h + je @@do88 + jmp [saved15] +@@do88: + pushf + call [saved15] + test ax,ax + jnz @@iret + +;****** Read extended mem size (CMOS bytes 17h,18h (lo,hi)) + call rdcmos17 +@@iret: + iret + + endp _hook_int15_88 + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/TAZBOOT.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/TAZBOOT.CPP Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,228 @@ +// This file is distributed under GPL +// +// TAZBOOT main() lives here + +#include "crtl.h" +#include "crtlx.h" +#include "common.h" +#include "iso9660.h" + +static void usage() +{ + puts("Usage: tazboot [[@commands]|[kernel=] \ +[initrd=[,...]] [bootfrom=] ...]\r\n\n\ +Defaults: tazboot kernel=bzImage auto\r\n\n\ +Examples for tazboot.cmd:\r\n\n\ + bootfrom=\\isos\\slitaz-4.0.iso\r\n\ + kernel=boot/bzImage\r\n\ + initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz,\\slitaz\\extrafs.gz\r\n\ + rw root=/dev/null vga=normal autologin\r\n\n\ + kernel=\\slitaz\\elks\r\n\ + root=/dev/bda1 ro\r\n"); + exit(1); +} + +#define MAXINITRD 10 +static struct initrd_state { + u32 ofs[MAXINITRD]; + u32 size[MAXINITRD]; + u16 cnt; +} initrd_state; + +static void next_chunk(struct image_himem *m) +{ + m->chunk_size = 0; + if (m->state >= initrd_state.cnt) return; + lseek(m->fd,initrd_state.ofs[m->state],SEEK_SET); + m->chunk_size = initrd_state.size[m->state]; + m->state++; +} + +static void addinitrd() +{ + if (initrd_state.cnt >= MAXINITRD) return; + initrd_state.size[initrd_state.cnt] = isofilesize; + initrd_state.ofs[initrd_state.cnt] = isofileofs; + initrd_state.cnt++; + initrd.size += (isofilesize+3)&-4; +} + +static void load_initrds() +{ + if (!initrd.size) return; + initrd.next_chunk = next_chunk; + initrd.fd = isofd; + initrd.state = 0; + next_chunk(&initrd); + load_initrd(); +} + +static void pm_next_chunk(struct image_himem *m) +{ + if (!m->state++) m->chunk_size = m->size; +} + +static void isokernel() +{ + pm.size = (isofilesize+3)&-4; + pm.fd = isofd; + pm.next_chunk = pm_next_chunk; +} + +char _cmdline[256]; +const char *cmdline = (const char *) _cmdline; +extern int skip_xmmalloc; +static void bootiso(char **iso) +{ + char *init = " rdinit=/init.exe", *mode="menu"; + char *s, c, rootfs[16], fallback[16]; + int restart, isknoppix = 0; + unsigned long magic; + + if (!*iso || isoreset(*iso) < 0) return; + skip_xmmalloc++; + isoopen("boot") >= 0 || + isoopen("live") >= 0 || // debian + isoopen("casper") >= 0; // ubuntu + if (iso[1] && !strcmp(mode = iso[1], "text")) + init = ""; + do { + if (isoopen(mode) >= 0 || // custom + isoopen("bzImage") >= 0 || // SliTaz + isoopen("vmlinuz") >= 0 || // misc + (isoopen("linux") >= 0 && ++isknoppix)) { + isokernel(); + magic = kver2ul(load_kernel()); + break; + } + } while (isoopen("isolinux") >= 0); // Knoppix + fallback[0] = 0; + for (c = 0, restart = 1; isoreaddir(restart) == 0; restart = 0) { + if (strstr(isofilename, ".gz")) + strcpy(fallback, isofilename); + if (strhead(isofilename, "rootfs") + || c > isofilename[6]) continue; + strcpy(rootfs, isofilename); + c = isofilename[6]; + } + + strcpy(_cmdline,"rw root=/dev/null autologin bootfrom="); + strcat(_cmdline,*iso); + if (magic < 0x20630) + init = ""; // Does not support multiple initramfs + + if (magic > 0) { + char *initrd = fallback; + + if (rootfs[0]) { + initrd = rootfs; + if (rootfs[6] != '.' && isoopen("rootfs.gz") >= 0) + addinitrd(); // for loram + } + if (isoopen(initrd) >= 0) { + addinitrd(); + } + if (*init && lseek(isofd, 20L, SEEK_SET) != -1 && + read(isofd, &isofileofs, 4) == 4 && + read(isofd, &magic, 4) == 4) { + isofileofs &= 0xFFFFL; + isofilesize = magic & 0xFFFFL; + isofileofs -= 0xC0L + isofilesize; + if (isofilesize) addinitrd(); + else init=""; + } + load_initrds(); + strcat(_cmdline,init); + strcat(_cmdline," mode="); + strcat(_cmdline,mode); + strcat(_cmdline," magic="); + strcat(_cmdline,ultoa(magic)); + } + if (isknoppix) { + if (iso[0][1] == ':') + *iso += 2; + for (s = *iso; *s; s++) + if (*s == '\\') *s = '/'; + } + close(isofd); + boot_kernel(); +} + +u16 root_dev; +u16 vid_mode; +const char* kernel_name = "bzImage"; +const char* initrd_name; +int main(int argc, char *argv[]) +{ + char *iso = NULL; + argv[0] = progname(); + bootiso(argv); // iso ? parsing is /init.exe stuff ! + if (argc >= 2) + bootiso(argv + 1); + + chdirname(*argv); + if (argc < 2) { +dousage: + usage(); + } + for (int i=1; i < argc; i++) { + char *s=argv[i]; + if (strhead(s,"kernel=") == 0) + kernel_name = s + 7; + if (strhead(s,"image=") == 0) + kernel_name = s + 6; + else if (strhead(s,"initrd=") == 0) + initrd_name = s + 7; + else if (strhead(s,"bootfrom=") == 0) + iso = s + 9; + else if (strhead(s,"iso=") == 0) + iso = s + 4; + else if(strhead(s,"vga=") == 0) { + s+=4; + const char c = *s|0x20; + if (c == 'a') vid_mode = -3; + else if (c == 'e') vid_mode = -2; + else if (c == 'n') vid_mode = -1; + else vid_mode = strtol(s); + } + else if(strhead(s,"-f") == 0) { + skip_xmmalloc++; + } + else { + if(strhead(s,"root=") == 0) { + root_dev = strtol(s+5); + } + if(strhead(s,"mem=") == 0) { + topmem = strtol(s+4); + } + if (_cmdline[0]) strcat(_cmdline," "); + strcat(_cmdline,s); + } + } + if (iso && isoreset(iso) >= 0) { + char *s = (char *) initrd_name; + if (isoopen((char *) kernel_name) >= 0) { + isokernel(); + load_kernel(); + } + if (s) { + while (*s) { + char *p, c; + for (p = s; *s && *s != ','; s++); + c = *s; *s = 0; + if (isoopen(p) >= 0) { + addinitrd(); + } + *s = c; + if (c) s++; + } + load_initrds(); + } + } + else { + load_kernel(); + load_initrd(); + } + boot_kernel(); + return _AX; +} diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/XMM.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/XMM.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,117 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_BSS + assume cs:DGROUP,ds:DGROUP + + segment _BSS byte public use16 'BSS' + + global xmm_handler:dword +xmm_handler dd ? + + ends _BSS + + segment _TEXT byte public use16 'CODE' + +;*************************************************************** +;void enable_a20_xmm(); +;*************************************************************** + global _enable_a20_xmm:near + proc _enable_a20_xmm near + + mov ah,03h ;global enable a20 + call xmm_driver ; + mov ah,05h ;local enable a20 + ;jmp xmm_driver ; + + endp _enable_a20_xmm + +;*************************************************************** +;Call xmm driver addr or 0 if no xmm +;void xmm_driver() +;*************************************************************** + global xmm_driver:near + proc xmm_driver near + + cmp [xmm_handler],0 + jne @@gotit + + xchg ax,cx ; save cmd + mov ax,4300h + int 2fh + mov bx,offset xmm_fail + push cs + pop es + cmp al,80h + jne @@err + mov ax,4310h + int 2fh +@@err: + xchg ax,cx ; restore cmd + push es + push bx + pop [xmm_handler] +@@gotit: + call [xmm_handler] + ret + endp xmm_driver + + +;*************************************************************** +;u32 xmm_alloc(void* drv, u32 size) +;*************************************************************** + global _xmm_alloc:near + proc _xmm_alloc near + + pop bx + ifndef NO386 + pop edx + push edx + dec edx + shr edx,10 ; to Kb + else + pop ax + pop dx + push dx + push ax + sub ax,1 + sbb dx,0 + mov cx,10 +@@tokblp: + shr dx,1 + rcr ax,1 + loop @@tokblp + endif + inc dx + push cs + push bx + mov ah,09h ;allocate blk + call xmm_driver ; + dec ax + jnz @@err + ;now: dx=handle of the blk + mov ah,0Ch ;lock blk + call xmm_driver ; + dec ax + ;now: dx:bx=addr of blk + xchg ax,bx + jz @@ok +@@err: +xmm_fail: + xor ax,ax + cwd +@@ok: + retf + endp _xmm_alloc + + ends _TEXT + + end + +;###### END OF FILE ############################################ diff -r 099a4d67f199 -r bb42796dcd3b linld/stuff/src/_BEG.ASM --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linld/stuff/src/_BEG.ASM Tue Nov 22 21:19:01 2016 +0100 @@ -0,0 +1,139 @@ +;*************************************************************** +;****** This file is distributed under GPL +;*************************************************************** + ideal + %crefref + %noincl + %nomacs + p386 + + group DGROUP _TEXT,_DATA,_BSS + assume cs:DGROUP,ds:DGROUP + + segment _TEXT byte public use16 'CODE' + + org 100h + global _text_start:byte + label _text_start byte + extrn _bss_end +;*************************************************************** +; clear bss +;*************************************************************** + xor ax,ax + mov di,offset _bss_start +clearbss: + mov [di],al + inc di + cmp di,sp ; clear bss + heap + jbe clearbss + mov di,offset _bss_end +;*************************************************************** +; build argv & argc +;*************************************************************** +; push ax ; envp (int 20h do it for us) + ;mov [word di],ax ; argv[0] = 0 + mov si,80h + cld + lodsb + cmp al,7Eh + jbe alok + mov al,7Eh +alok: + xchg ax,bx + mov [bx+si],bh ; set eos +argbuild: + mov bx,2 ; argc * 2 +argeos: + mov dl,1 ; look for a start of string + mov [byte si-1],bh ; mark eos + mov ah,20h ; space will be eos +arglp: + lodsb + cmp al,0h + je argdone + cmp al,20h + jb argeos + cmp al,ah + je argeos + cmp al,27h + je isargstr + cmp al,22h + je isargstr + or dl,dl + je arglp ; not start of string + dec si + jmp newarg +isargstr: + mov ah,al ; expected eos +newarg: + mov [word bx+di],si ; argv[argc++] = si + inc bx + inc bx + dec dx + jmp arglp +argdone: + ;mov [word bx+di],0 ; argv[argc] = 0 + lea si,[bx+di+2] + extrn _heap_top:word + mov [_heap_top],si + push di ; argv + shr bx,1 + push bx ; argc + ifndef filearg + mov bx,[di+2] ; argv[1] + cmp [byte bx],'@' + jne argend + inc bx ; al=0 RDONLY + extrn open:near + call near open + jc argend + pop bx ; trash argc, argv >> 1Kb ! + push di + push ax + extrn _read:near + call near _read + pop bx ; fd for close + pop si ; si=buffer=argv + add di,ax + pop ax ; trash sizemax=argv + extrn close:near + call near close + jmp argbuild +argend: + endif + +;*************************************************************** + extrn _is_vm86:near + call _is_vm86 ; load_image needs that + +;*************************************************************** + extrn _main:near + call _main + push ax + push ax +;*************************************************************** +;void exit(int n); +;*************************************************************** + global _exit:near + global exit:near +_exit: + pop bx ;caller return address + pop ax ; n +exit: + mov ah,4Ch + int 21h + ends _TEXT + + segment _DATA byte public use16 'DATA' + global _data_start:byte + label _data_start byte + ends _DATA + + segment _BSS byte public use16 'BSS' + global _bss_start:byte + label _bss_start byte + ends _BSS + + end _text_start + +;###### END OF FILE ############################################