summaryrefslogtreecommitdiff
path: root/bootblocks
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-11-03 22:33:35 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:33:35 +0200
commitc218c617b5be443b7968308506969ad2b726d73c (patch)
tree0051f396af56133d24fcf2ab757fabc78c1a09bf /bootblocks
parent0936b9aeab611665645a4e6bafaded7ca76dd189 (diff)
parent0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (diff)
downloaddev86-c218c617b5be443b7968308506969ad2b726d73c.tar.gz
Import Dev86src-0.0.8.tar.gzv0.0.8
Diffstat (limited to 'bootblocks')
-rw-r--r--bootblocks/Makefile65
-rw-r--r--bootblocks/README62
-rw-r--r--bootblocks/bootlist.s256
-rw-r--r--bootblocks/com_bcc.s65
-rw-r--r--bootblocks/i86_funcs.c190
-rw-r--r--bootblocks/makeboot.c187
-rw-r--r--bootblocks/minix.c537
-rw-r--r--bootblocks/monitor.c353
-rw-r--r--bootblocks/relocate.c77
-rw-r--r--bootblocks/standalone.c309
-rw-r--r--bootblocks/sysboot.s77
-rw-r--r--bootblocks/tarboot.s509
-rw-r--r--bootblocks/tich.s38
-rw-r--r--bootblocks/tiny.s55
14 files changed, 2780 insertions, 0 deletions
diff --git a/bootblocks/Makefile b/bootblocks/Makefile
new file mode 100644
index 0000000..0ed6e1d
--- /dev/null
+++ b/bootblocks/Makefile
@@ -0,0 +1,65 @@
+
+HOSTCC=cc
+HOSTCCFLAGS=-O
+
+CC=bcc
+CFLAGS=-ansi -O -Ms
+AS=as86
+ASFLAGS=-0
+# LST=-l $*.lst
+
+nothing:
+ @more README
+
+all: makeboot monitor.out bin
+
+CSRC=minix.c
+SSRC=tarboot.s tiny.s com_bcc.s tich.s sysboot.s bootlist.s
+
+encap: $(SSRC:s=v) $(CSRC:c=v)
+bin: $(SSRC:s=bin) $(CSRC:c=bin)
+
+MOBJ=monitor.o i86_funcs.o relocate.o
+MSRC=monitor.c i86_funcs.c relocate.c
+
+install:
+
+monitor.out: $(MOBJ)
+ $(CC) $(CFLAGS) $(MOBJ) -o monitor.out
+
+monitor: $(MSRC)
+ @rm -f $(MOBJ)
+ make 'CFLAGS=-ansi -O' monitor.out
+ mv monitor.out monitor
+ @rm -f $(MOBJ)
+
+minix.s: minix.c
+ bcc -Mf -O -S minix.c
+
+makeboot: tarboot.v sysboot.v makeboot.c
+ $(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c
+
+clean:
+ rm -f monitor makeboot minix.s *.o *.bin *.out *.lst *.sym *.v
+
+tgz: minix.bin monitor.out makeboot
+ tar cfV bootblocks.tar ENIAC monitor.out \
+ README Makefile \
+ $(MSRC) standalone.c makeboot.c \
+ $(CSRC) $(SSRC) \
+ makeboot minix.bin
+ makeboot bootblocks.tar
+ gzip -f9 bootblocks.tar
+
+distribution:
+ tar czf /tmp/bootblocks.tar.gz README Makefile \
+ $(MSRC) standalone.c makeboot.c \
+ $(CSRC) $(SSRC)
+
+.SUFFIXES: .bin .v
+
+.s.bin:
+ $(AS) $(ASFLAGS) -b $*.bin -s $*.sym -l $*.lst $*.s
+
+.s.v:
+ as86_encap $*.s $*.v $*_ $(ASFLAGS) $(LST)
diff --git a/bootblocks/README b/bootblocks/README
new file mode 100644
index 0000000..c57f3aa
--- /dev/null
+++ b/bootblocks/README
@@ -0,0 +1,62 @@
+
+To install the tarfile bootsector
+---------------------------------
+
+ Create the makeboot program:
+
+$ make makeboot
+
+Create the tarfile
+
+$ tar cvfV /dev/fd0 ENIAC monitor.out item2 item3
+
+Make it bootable
+
+$ makeboot /dev/fd0
+
+Note, the distribution tar file is made using this procedure and can be booted
+if uncompressed and copied onto a raw floppy.
+
+To install the minixfs boot sector
+----------------------------------
+
+ Make a minix filesystem on the floppy:
+
+$ mkfs -t minix /dev/fd0 1440
+
+$ mkfs -t minix /dev/fd0 1200
+
+ Make the bootblock program.
+
+$ make minix.bin
+
+ Install it
+
+$ cp minix.bin /dev/fd0
+
+ Place a Linux-8086 executable in the root directory.
+
+$ make monitor.out
+$ mount -t minix /dev/fd0 /mnt
+$ cp monitor.out /mnt/linux
+$ umount /dev/fd0
+
+ Or in a tar file:
+
+$ make monitor.out
+$ mount -t minix /dev/fd0 /mnt
+$ tar cvf /mnt/linux monitor.out long list of other files
+$ umount /dev/fd0
+
+ This works on my 3 1/4 floppy, and it _should_ work on any double sided
+ drive. Be sure to make the filesystem the full size of the floppy.
+
+To boot the floppy in DOSEMU
+----------------------------
+
+$ dos -A
+
+ Press ^C to exit DOSEMU from inside monitor.c
+
+Rob.
+
diff --git a/bootblocks/bootlist.s b/bootblocks/bootlist.s
new file mode 100644
index 0000000..889842a
--- /dev/null
+++ b/bootblocks/bootlist.s
@@ -0,0 +1,256 @@
+! This bootsector is modified by the installer to have a list of sectors at
+! offset 256.
+
+! Table format is a list of dwords. Each dword has a partition offest in
+! the low 24 bits and a count in the high.
+!
+! Prob better to make it: HH DD MM LL rather than DD HH MM LL
+! as this matches the BIOS better
+!
+! Note:
+! Stack top is at abs location 64k.
+!
+
+BOOTSEG = 0x07c0
+LOADSEG = 0x07e0 ! Just after boot sector.
+
+public linear
+linear = 1 ! Is linear processing done ?
+
+public floppy
+floppy = 0 *linear ! Allow for floppy drive ?
+public reloc
+reloc = 1 *linear ! Auto configure of bootpart.
+
+macro locn
+ if *-start>?1
+ fail
+ endif
+ .blkb ?1 + start-*
+mend
+
+use16
+entry start
+
+org $7b00
+
+! temporary space
+
+n_cyl: .blkw 1
+n_secs: .blkw 1
+t_drive: .blkb 1
+t_sector: .blkb 1
+t_secs: .blkw 1
+
+org $7c00
+start:
+ j code
+
+runit:
+ jmpi 0,0 ! This instruction is altered by the installer
+
+public execaddr ! Via this label.
+execaddr = *-4
+
+public bootpart
+bootpart:
+ .data4 0x80000011
+code:
+
+ if reloc
+ mov cx,[si+8] ! Fetch the linear address of part from DS:SI
+ mov dh,[si+10] ! DL is drive number
+ xchg dl,dh ! Into normal form.
+ endif
+
+ xor ax,ax
+ mov ds,ax
+ mov ss,ax
+ mov sp,ax
+
+ if reloc
+ mov [bootpart],cx
+ mov [bootpart+2],dx
+ endif
+
+! ASSUME ds=ss= 0 (cs should also be zero)
+
+ mov ax,#LOADSEG
+ mov es,ax
+
+ mov si,#table
+load_addrs:
+ cld
+
+ if linear
+ lodsw
+ mov cx,ax
+ add cx,[bootpart]
+ lodsw
+ mov dx,[bootpart+2]
+ adc dl,al
+ mov al,ah
+ else
+ lodsw
+ mov cx,ax
+ lodsw
+ mov dx,ax
+ lodsb
+ endif
+
+ test al,al
+ jz runit
+
+loadem:
+ xor bx,bx
+ push ax
+ call cread
+ jc failed
+ pop ax
+ mov cl,#5
+ sal ax,cl
+ mov bx,es
+ add ax,bx
+ mov es,ax
+ j load_addrs
+
+! Humm, something goes wrong, not much we can do ...
+! Let`s squeak then try again
+failed:
+ mov ax,#$0E45
+ mov bx,#7
+ int $10
+ pop ax
+
+ j loadem
+
+cread:
+ ! This function is like BIOS 1302 but it`s linear.
+ ! It's taken, almost, intact from LILO.
+
+ ! DH is drive, DL:CX is linear address, AL is count.
+ ! ES:BX is load address, beware of DMA limitations
+
+ ! All registers except AX and flags are preserved.
+
+ mov t_secs,al ! save number of sectors
+lnread: push cx ! keep linear address
+ push dx
+ xchg dl,dh
+
+ if linear
+ if floppy
+ test dl,#0x80 ! Floppy is physical only.
+ jz lrd
+ endif
+
+ push bx ! BX is used as scratch
+ push cx ! LSW
+ push dx ! MSW with drive
+ mov ah,#8 ! get drive geometry (do not clobber ES:DI)
+ push es
+ push di
+ int 0x13
+ pop di
+ pop es
+ mov bl,dh ! BL <- #heads
+ pop dx ! get MSW
+
+ jnc int_ok ! error -> quit
+
+ pop cx ! discard stack contents
+ pop bx
+ pop dx
+ pop cx
+ ret ! (carry is already set)
+int_ok:
+ mov t_drive,dl ! save drive
+ mov dl,dh ! linear address into DX:AX
+ xor dh,dh
+ mov bh,dh ! (clear BH too)
+ pop ax
+ push cx ! compute #cyls-1
+ xchg ch,cl
+ rol ch,1
+ rol ch,1
+ and ch,#3
+ mov n_cyl,cx ! save #cyls-1
+ pop cx
+ and cx,#0x3f ! CX <- #secs
+ mov n_secs,cx
+ div cx ! AX <- track, DX <- sector
+ inc dl
+ mov t_sector,dl
+ xor dx,dx ! divide by #heads
+ inc bx
+ div bx ! AX <- cylinder, DX <- head
+ mov dh,dl ! set up DX (head:drive)
+ mov dl,t_drive
+ cmp ax,n_cyl ! valid cylinder number ?
+ ja linerr3 ! no -> error
+ xchg ah,al ! build cylinder number
+ ror al,1
+ ror al,1
+ or al,t_sector
+ mov cx,ax
+ pop bx ! restore BX
+ and ax,#0x3f ! read beyond end of track ?
+ add ax,t_secs
+ cmp ax,n_secs
+ jna intrk ! no -> go on
+ mov al,n_secs ! read to end of track
+ sub al,t_sector
+ inc al
+ jmp lrd ! read it
+intrk: mov al,t_secs ! read all sectors
+
+ endif
+
+lrd: push ax ! save AX and BX
+ push bx
+
+ mov ah,#2 !
+ int 0x13 ! read sectors
+
+ pop bx ! restore AX and BX and the linear address
+ pop ax
+ pop dx
+ pop cx
+
+ if linear
+
+ jc linerr ! error -> quit
+ sub t_secs,al ! adjust sector count
+ jz lindone ! zero -> done
+ xor ah,ah ! increase linear address
+ add cx,ax
+ adc dh,#0
+ xchg ah,al ! move BX
+ add ah,ah
+ add bx,ax
+ jc interr ! crossing segment boundaries -> error
+ br lnread ! process remaining sectors
+
+linerr3:pop bx ! pop BX and linear address
+ pop dx
+ pop cx
+interr: xor ax,ax ! zero indicates internal error
+
+ else
+ jnc lindone
+ endif
+
+linerr: stc ! error
+ ret
+lindone:clc ! no error
+ ret ! done
+
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+public table
+table:
+! .long 0x80000012
+! .byte 1
+! .long 0x07e00000
+! .byte 0
diff --git a/bootblocks/com_bcc.s b/bootblocks/com_bcc.s
new file mode 100644
index 0000000..26daff3
--- /dev/null
+++ b/bootblocks/com_bcc.s
@@ -0,0 +1,65 @@
+
+! This header assumes only that we're loaded at a 16 byte boundry
+
+ENDOFF=4 ! If you add code adjust this till it stops failing.
+
+org 0
+entry start
+public start
+start:
+ call chk ! This chunk allows this code to exist at _any_ click
+chk:
+ pop ax
+ mov cl,#4
+ shr ax,cl
+ mov bx,cs
+ add ax,bx
+ push ax
+ mov bx,#going
+ push bx
+ retf
+going:
+ mov ds,ax
+
+ add ax,#ENDOFF+2 ! New CS
+ mov bx,ax ! Saved
+ mov dx,[a_entry] ! Save the entry - zero
+ mov ax,[btype]
+ and ax,#$20 ! Split I/D ?
+ jz impure
+ mov cl,#4
+ mov ax,[a_text]
+ shr ax,cl
+impure: ! ax is now offset 'tween CS&DS
+ add ax,bx ! ax = DS
+ mov ss,ax
+ mov sp,[a_total] ! SS:SP is now ready for prog.
+ mov ds,ax
+ xor cx,cx ! argc, argv and envp = 0
+ push cx
+ push cx
+ push cx
+ push bx ! CS
+ push dx ! Entry address
+ retf ! Gone.
+
+! Check for overlap
+end_of_code:
+ if end_of_code>hitme
+ fail
+ endif
+
+.org ((ENDOFF)<<4)-1
+hitme:
+.byte 0xFF ! Marker
+
+magic: .space 2 ! A.out header
+btype: .space 2
+headerlen: .space 4
+a_text: .space 4
+a_data: .space 4
+a_bss: .space 4
+a_entry: .space 4
+a_total: .space 4
+a_syms: .space 4
+.org (ENDOFF+2)<<4 ! Code start.
diff --git a/bootblocks/i86_funcs.c b/bootblocks/i86_funcs.c
new file mode 100644
index 0000000..a17e7a4
--- /dev/null
+++ b/bootblocks/i86_funcs.c
@@ -0,0 +1,190 @@
+
+#include <stdio.h>
+#include <errno.h>
+#include "i86_funcs.h"
+
+int x86 = 0; /* CPU major number */
+char *x86_name = ""; /* and it's name */
+int x86_emu = 0; /* Is this a PC emulator ? */
+int x86_a20_closed = 1; /* Is the A20 gate closed ? */
+int x86_test = 0; /* In test mode */
+int x86_fpu = 0;
+
+unsigned boot_mem_top = 0x4000; /* Default 64k, the minimum */
+long main_mem_top = 0; /* K of extended memory */
+
+int a20_closed()
+{
+ register int v, rv = 0;
+ if (x86_test)
+ return 1; /* If not standalone don't try */
+
+ __set_es(0);
+ v = __peek_es(512);
+ __set_es(0xFFFF);
+ if (v == __peek_es(512+16))
+ {
+ __set_es(0);
+ __poke_es(512, v+1);
+ __set_es(0xFFFF);
+ if (v+1 == __peek_es(512+16))
+ rv = 1;
+ __set_es(0);
+ __poke_es(512, v);
+ }
+ return x86_a20_closed = rv;
+}
+
+void open_a20()
+{
+#asm
+ call empty_8042
+ mov al,#0xD1 ! command write
+ out #0x64,al
+ call empty_8042
+ mov al,#0xDF ! A20 on
+ out #0x60,al
+empty_8042:
+ .word 0x00eb,0x00eb
+ in al,#0x64 ! 8042 status port
+ test al,#2 ! is input buffer full?
+ jnz empty_8042 ! yes - loop, with no timeout!
+#endasm
+}
+
+void cpu_check()
+{
+ static char *name_808x[] =
+ {
+ "8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone"
+ };
+
+ static char *name_8018x[] =
+ {
+ "80188", "80186", "8018x Clone"
+ };
+ static char cpubuf[] = "80x86+";
+ int c, major;
+
+ c = cputype(0);
+ x86_fpu = (c < 0);
+ major = ((c >> 8) & 0x1F);
+ c &= 0xFF;
+ x86 = (major&0xF);
+ if (major == 0)
+ {
+ if (c > 6) c = 6;
+ x86_name = name_808x[c];
+ }
+ else if (major == 1)
+ {
+ if (c > 3) c = 3;
+ x86_name = name_8018x[c];
+ }
+ else
+ {
+ cpubuf[2] = (major&0xF)+'0';
+ cpubuf[5] = (major > 15 ? '+' : '\0');
+ x86_name = cpubuf;
+ if (c & 0x01) x86_emu = 1; /* Already in protected mode !!! */
+ }
+}
+
+void mem_check()
+{
+ if (x86_test) return; /* If not standalone don't try */
+ {
+#asm
+ int 0x12 ! Amount of boot memory
+ mov cl,#6
+ sal ax,cl ! In segments
+ mov [_boot_mem_top],ax
+
+ ! Next check for extended
+ mov al,[_x86] ! If we ain't got a 286+ we can't access it anyway
+ cmp al,#2
+ jl is_xt
+
+ mov ah,#0x88 !
+ int 0x15
+ jnc got_ext ! Error!? This should _not_ happen ... but ...
+is_xt:
+ xor ax,ax
+got_ext:
+ mov word ptr [_main_mem_top+2],#0
+ mov [_main_mem_top],ax
+
+#endasm
+ }
+
+ if( main_mem_top == 0xFFFFL )
+ {
+ /* It say 64Mb-1k - Hmmmm I think it might be 128! */
+ }
+}
+
+#define RIGHTS (0x93000000L)
+
+static struct {
+ char gdt0[8];
+ char gdt1[8];
+ unsigned short src_len;
+ long src_seg;
+ unsigned int spad;
+ unsigned short dst_len;
+ long dst_seg;
+ unsigned int dpad;
+ char gdt5[8];
+} GDT = {
+ "","",
+ 0xFFFF, RIGHTS, 0,
+ 0xFFFF, RIGHTS, 0,
+ ""
+};
+
+ext_put(from, to, length)
+unsigned int from, to, length;
+{
+ if(x86_test) return 3;
+ GDT.src_seg = RIGHTS + from + ((long)__get_ds()<<4);
+ GDT.dst_seg = RIGHTS + ((long)to<<8);
+ if( length == 0xFFFF ) length = 0x8000;
+ else length = ((length+1)>>1);
+ return asm_copy(length);
+}
+
+ext_get(from, to, length)
+unsigned int from, to, length;
+{
+ if(x86_test) return 3;
+ GDT.src_seg = RIGHTS + ((long)from<<8);
+ GDT.dst_seg = RIGHTS + to + ((long)__get_ds()<<4);
+ if( length == 0xFFFF ) length = 0x8000;
+ else length = ((length+1)>>1);
+ return asm_copy(length);
+}
+
+static asm_copy(length)
+{
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ push es
+ push si
+ mov cx,ax
+ mov ah,$87
+ push ds
+ pop es
+ mov si,#_GDT
+ int $15
+ jc err
+ xor ax,ax
+err:
+ mov al,ah
+ xor ah,ah
+ push si
+ push es
+#endasm
+}
diff --git a/bootblocks/makeboot.c b/bootblocks/makeboot.c
new file mode 100644
index 0000000..5a6348d
--- /dev/null
+++ b/bootblocks/makeboot.c
@@ -0,0 +1,187 @@
+
+#include <stdio.h>
+
+#include "tarboot.v"
+#include "sysboot.v"
+
+char tarblock[512];
+
+char *bootblock = tarboot_data;
+
+struct tar_head {
+ char name[100];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char linkflag;
+ char linkname[100];
+ char magic[8];
+ char uname[32];
+ char gname[32];
+ char devmajor[8];
+ char devminor[8];
+ char padding[167];
+} ;
+
+#define head (*(struct tar_head*) tarblock)
+#define boothead (*(struct tar_head*) bootblock)
+
+int force = 0;
+int relocatable = 0;
+int tableload = 0;
+long loadaddress = 0x8000;
+long execaddress = 0x8000;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ int ar;
+ int done=0;
+
+ if( sizeof(head) != sizeof(tarblock) )
+ { fprintf(stderr, "Program structure error\n"); exit(1); }
+
+ for(ar=1; ar<argc; ar++) if(argv[ar][0]=='-') switch(argv[ar][1])
+ {
+ case 'f': force++; break;
+ case 'r': relocatable++; break;
+ case 't': tableload++; break;
+ case 'l': sscanf(argv[ar]+2, "%li", &loadaddress); break;
+ case 'x': sscanf(argv[ar]+2, "%li", &execaddress); break;
+
+ case '?': Usage(1); break;
+ default: Usage(0); break;
+ }
+ else
+ {
+ mktarboot(argv[ar]);
+ done++;
+ }
+}
+
+Usage(flg)
+int flg;
+{
+ fprintf(stderr, "Usage: makeboot [-f] device\n");
+ exit(9);
+}
+
+mktarboot(fname)
+char * fname;
+{
+ FILE * fd;
+
+ fd = fopen(fname, "r+");
+ if( !fd ) { perror(fname); exit(1); }
+
+ if( fread(tarblock, sizeof(tarblock), 1, fd) != 1 )
+ { fprintf(stderr, "Cannot read boot block\n"); exit(1); }
+
+ check_tar(1);
+ mangle_tarvol();
+
+ rewind(fd);
+ if( fwrite(tarblock, sizeof(tarblock), 1, fd) != 1 )
+ { fprintf(stderr, "Cannot write boot block\n"); exit(1); }
+
+ rewind(fd);
+ if( fread(tarblock, sizeof(tarblock), 1, fd) != 1 )
+ { fprintf(stderr, "Cannot re-read boot block\n"); exit(1); }
+
+ if( fread(tarblock, sizeof(tarblock), 1, fd) == 1 && head.linkflag == '0' )
+ printf("Boot block installed to boot file %s\n", head.name);
+
+ fclose(fd);
+ exit(0);
+}
+
+unsigned int oct(s)
+char *s;
+{
+ unsigned int val = 0;
+ int i;
+ for(i=0; i<8; i++) if( s[i] >= '0' && s[i] <= '7' )
+ val = (val<<3) + s[i] - '0';
+ return val;
+}
+
+check_tar(fatal)
+int fatal;
+{
+ char vbuf[100], *p;
+ unsigned int csum = 0;
+ long osum = -1;
+
+ osum = oct(head.chksum);
+ memset(head.chksum, ' ', sizeof(head.chksum));
+
+ for(p=tarblock; p<tarblock+sizeof(tarblock); p++)
+ csum += (*p & 0xFF);
+
+ if( csum != osum )
+ {
+ fprintf(stderr, "TAR file checksum failed, this isn't a tar file.\n");
+ if(fatal) exit(9);
+ return -1;
+ }
+ if( head.linkflag != 'V' )
+ {
+ fprintf(stderr, "Tar file doesn't start with a volume label\n");
+ if(fatal) exit(8);
+ return -1;
+ }
+
+ strcpy(vbuf, boothead.name); strcat(vbuf, " Volume 1");
+ if( !force && strcmp(boothead.name, head.name) != 0
+ && strcmp(vbuf, head.name) != 0 )
+ {
+ fprintf(stderr, "Volume is labeled as '%s' not '%s'\n",
+ head.name, boothead.name);
+ fprintf(stderr, "Use -f flag to force write\n");
+ if(fatal) exit(1);
+ return -1;
+ }
+ return 0;
+}
+
+mangle_tarvol()
+{
+ char lbuf[20];
+ char * p;
+ unsigned int csum = 0;
+ int i;
+
+ struct tar_head temp;
+
+ temp = boothead;
+
+ /* Copy preserved fields
+ */
+ memcpy(temp.mtime, head.mtime, sizeof(temp.mtime));
+
+ memset(temp.name, 0x90, 16);
+ for(i=0; head.name[i] && head.name[i] != ' ' && i<14; i++)
+ {
+ int ch = head.name[i];
+ if( islower(ch) ) ch = toupper(ch);
+ if( strchr("/?@ABCDEFGHIJKLMNO", ch) == 0 )
+ ch = '?';
+ temp.name[i] = ch;
+ }
+ temp.name[i++] = 0;
+ temp.name[i] = 0xC0;
+
+ head = temp;
+ /* Calculate the checksum */
+ memset(head.chksum, ' ', sizeof(head.chksum));
+
+ for(p=tarblock; p<tarblock+sizeof(tarblock); p++)
+ csum += (*p & 0xFF);
+
+ sprintf(head.chksum, "%7o", csum);
+}
+
diff --git a/bootblocks/minix.c b/bootblocks/minix.c
new file mode 100644
index 0000000..f6ba7b4
--- /dev/null
+++ b/bootblocks/minix.c
@@ -0,0 +1,537 @@
+/*
+ * This bootblock loads the linux-8086 executable in the file 'linux'
+ * from the root directory of a minix filesystem.
+ *
+ * Copyright (C) 1990-1996 Robert de Bath, distributed under the GPL Version 2
+ * Based on minix filesystem definitions.
+ */
+
+#include <a.out.h>
+
+#undef DOTS /* define to have dots printed */
+#define zone_shift 0 /* for any < 32M (non-zero not supported yet) */
+
+#define seg_at(k) ((k)*64)
+#define seg_of(p) ((unsigned int)p >>4)
+#define BOOTSEG (0x07c0)
+#define LOADSEG (0x1000)
+
+#asm
+BOOTSEG = 0x07c0
+BOOTADDR = 0x7c00
+LOADSEG = 0x1000 ! This must be sector aligned
+
+.text
+! Apparently on startup the only things we can assume are that we start at
+! `start` (ABS addr $07C00) ...
+
+! So first set CS=DS=ES=SS=0
+! The we move this to $0500 and put the stack at the top of the first 64k.
+! The directory 'file' is loaded $1500 and scanned there.
+! The final executable will be loaded in the 2nd 64k chunk.
+!
+org $0500 ! The lowest available address.
+start:
+ include sysboot.s
+ org codestart
+
+ xor ax,ax
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,ax
+
+ mov ax,#$0204 ! Read 4 sectors, code + superblock.
+ mov bx,#start ! Where this _should_ be
+ mov cx,#$0001 ! From sector 1
+ xor dx,dx ! Of the floppy drive head zero
+ int $13
+
+ jmpi code,#0
+
+#endasm
+
+/****************************************************************************/
+/* Super block table. The root file system and every mounted file system
+ * has an entry here. The entry holds information about the sizes of the bit
+ * maps and inodes. The s_ninodes field gives the number of inodes available
+ * for files and directories, including the root directory. Inode 0 is
+ * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be
+ * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
+ * for files and directories. The disk layout is:
+ *
+ * Item # blocks
+ * boot block 1
+ * super block 1
+ * inode map s_imap_blocks
+ * zone map s_zmap_blocks
+ * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK
+ * unused whatever is needed to fill out the current zone
+ * data zones (s_nzones - s_firstdatazone) << s_log_zone_size
+ *
+ * A super_block slot is free if s_dev == NO_DEV.
+ */
+
+#define BLOCK_SIZE 1024 /* # bytes in a disk block */
+
+/* Flag bits for i_mode in the inode. */
+#define I_TYPE 0170000 /* this field gives inode type */
+#define I_REGULAR 0100000 /* regular file, not dir or special */
+#define I_BLOCK_SPECIAL 0060000 /* block special file */
+#define I_DIRECTORY 0040000 /* file is a directory */
+#define I_CHAR_SPECIAL 0020000 /* character special file */
+#define I_SET_UID_BIT 0004000 /* set effective uid on exec */
+#define I_SET_GID_BIT 0002000 /* set effective gid on exec */
+#define ALL_MODES 0006777 /* all bits for user, group and others */
+#define RWX_MODES 0000777 /* mode bits for RWX only */
+#define R_BIT 0000004 /* Rwx protection bit */
+#define W_BIT 0000002 /* rWx protection bit */
+#define X_BIT 0000001 /* rwX protection bit */
+#define I_NOT_ALLOC 0000000 /* this inode is free */
+
+/* Type definitions */
+typedef unsigned short unshort; /* must be 16-bit unsigned */
+typedef unshort block_nr; /* block number */
+typedef unshort inode_nr; /* inode number */
+typedef unshort zone_nr; /* zone number */
+typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort,
+ then also unshort, else long */
+
+typedef unshort sect_nr;
+
+typedef long zone_type; /* zone size */
+typedef unshort mask_bits; /* mode bits */
+typedef unshort dev_nr; /* major | minor device number */
+typedef char links; /* number of links to an inode */
+typedef long real_time; /* real time in seconds since Jan 1, 1970 */
+typedef long file_pos; /* position in, or length of, a file */
+typedef short uid; /* user id */
+typedef char gid; /* group id */
+
+/* Tables sizes */
+#define NR_ZONE_NUMS 9 /* # zone numbers in an inode */
+#define NAME_SIZE 14 /* # bytes in a directory component */
+
+/* Miscellaneous constants */
+#define SUPER_MAGIC 0x137F /* magic number contained in super-block */
+
+#define BOOT_BLOCK (block_nr)0 /* block number of boot block */
+#define SUPER_BLOCK (block_nr)1 /* block number of super block */
+#define ROOT_INODE (inode_nr)1 /* inode number for root directory */
+
+/* Derived sizes */
+#define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */
+#define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */
+#define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */
+#define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */
+
+struct super_block {
+ inode_nr s_ninodes; /* # usable inodes on the minor device */
+ zone_nr s_nzones; /* total device size, including bit maps etc */
+ unshort s_imap_blocks; /* # of blocks used by inode bit map */
+ unshort s_zmap_blocks; /* # of blocks used by zone bit map */
+ zone_nr s_firstdatazone; /* number of first data zone */
+ short s_log_zone_size; /* log2 of blocks/zone */
+ file_pos s_max_size; /* maximum file size on this device */
+ short s_magic; /* magic number to recognize super-blocks */
+
+} ;
+
+/* Type definitions local to the File System. */
+typedef struct { /* directory entry */
+ inode_nr d_inum; /* inode number */
+ char d_name[NAME_SIZE]; /* character string */
+} dir_struct;
+
+/* Declaration of the disk inode used in rw_inode(). */
+typedef struct { /* disk inode. Memory inode is in "inotab.h" */
+ mask_bits i_mode; /* file type, protection, etc. */
+ uid i_uid; /* user id of the file's owner */
+ file_pos i_size; /* current file size in bytes */
+ real_time i_modtime; /* when was file data last changed */
+ gid i_gid; /* group number */
+ links i_nlinks; /* how many links to this file */
+ zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */
+} d_inode;
+
+/****************************************************************************/
+
+#ifdef zone_shift
+#if zone_shift == 0
+#define load_zone load_block
+#endif
+#else
+static short zone_shift;
+#endif
+
+/* The name of the file and inode to start */
+extern char bootfile[];
+extern inode_nr inode;
+
+/* For multi-sector reads */
+extern sect_nr lastsect;
+extern sect_nr firstsect;
+extern unsigned loadaddr;
+extern unsigned loadcount;
+
+/* Keep track of zones to load */
+extern zone_nr * next_zone;
+extern zone_nr * end_zone;
+extern zone_nr indirect;
+
+/* Where to load zones */
+extern unsigned ldaddr;
+
+/* Directory reading */
+extern dir_struct * dirptr;
+extern unsigned flength;
+
+/* The 'shape' of the floppy - intuit from superblock */
+extern unsigned n_sectors;
+
+/*
+ * #define b_super (*(struct super_block *) 1024)
+ * #define b_inode ((d_inode *)2048)
+ * #define b_zone ((zone_nr *)3072)
+ */
+
+extern struct super_block b_super;
+extern d_inode b_inode[INODES_PER_BLOCK];
+extern zone_nr b_zone[NR_INDIRECTS];
+extern dir_struct directory[];
+
+/****************************************************************************/
+
+#asm
+! A few variables we need to know the positions of for patching, so export
+! them and as86_encaps will make some variables.
+.text
+export _inode ! Inode to search
+_inode: .word 1 ! ROOT_INODE
+
+export _bootfile ! File to boot, make this whatever you like,
+_bootfile: ! 'boot' is good too.
+ .ascii "linux"
+ .byte 0,0,0,0,0,0,0,0,0
+
+_loadcount: .word 0
+_firstsect: .word 0
+_loadaddr: .word 0
+_lastsect: .word 0
+
+code:
+ call _loadprog
+ call _runprog
+ br _nogood
+#endasm
+
+static
+load_block(address, blkno)
+unsigned address, blkno;
+{
+ register sect_nr sectno;
+ if(blkno == 0) { zero_block(address); return; }
+#ifdef DOTS
+ bios_putc('.');
+#endif
+
+ sectno = (sect_nr)blkno * 2;
+ load_sect(address, sectno);
+ load_sect(address+32, sectno+1);
+}
+
+static
+load_sect(address, sectno)
+unsigned address;
+sect_nr sectno;
+{
+ register sect_nr nsect;
+
+ nsect = sectno%n_sectors +1;
+ sectno /= n_sectors;
+ nsect |= (sectno<<8);
+
+ if( loadcount )
+ {
+ lastsect++;
+ if( ( address & 4095 ) && nsect == lastsect )
+ {
+ loadcount++;
+ return;
+ }
+ get_now();
+ }
+
+ lastsect = firstsect = nsect;
+ loadaddr = address;
+ loadcount = 1;
+}
+
+static
+get_now()
+{
+#asm
+ xor dx,dx
+ mov cx,[_firstsect]
+ shr ch,#1
+ adc dh,#0
+ mov es,[_loadaddr]
+ xor bx,bx
+ mov ax,[_loadcount]
+ test ax,ax
+ jz no_load
+ mov ah,#2
+ int $13
+ jc nogood
+no_load:
+ xor ax,ax
+ mov [_loadcount],ax
+#endasm
+}
+
+#asm
+nogood:
+ j _nogood
+#endasm
+
+static
+zero_block(address)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov es,ax
+#else
+ mov bx,sp
+ mov es,[bx+2]
+#endif
+ push di
+ mov cx,#512
+ xor ax,ax
+ mov di,ax
+ rep
+ stosw
+ pop di
+#endasm
+}
+
+#ifndef load_zone
+NOT_DEFINED_load_zone(address, zoneno)
+{
+}
+#endif
+
+#ifdef DOTS
+static
+bios_putc(c)
+{
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ mov ah,#$0E
+ mov bx,#7
+ int $10
+#endasm
+}
+#endif
+
+static
+nogood()
+{
+/* This didn't work, chain the boot sector of the HD */
+#asm
+ push cs
+ pop es
+hcode:
+ mov ax,#$0201 ! Read 1 sector
+ mov bx,#BOOTADDR ! In the boot area
+ mov cx,#$0001 ! From sector 1
+ mov dx,#$0080 ! Of the hard drive head zero
+ int $13
+ jc hcode ! Keep trying forever!
+ jmpi BOOTADDR,0
+#endasm
+}
+
+#asm
+end_of_part1:
+ if *>start+0x200
+ fail
+ endif
+ .blkb 0x200+start-*
+#endasm
+
+static
+loadprog()
+{
+#ifdef DOTS
+ bios_putc('+');
+#endif
+ if( b_super.s_magic != SUPER_MAGIC ) nogood();
+ n_sectors = b_super.s_nzones / 80;
+ if( n_sectors < 5 ) n_sectors = b_super.s_nzones / 40;
+
+try_again:;
+#ifdef zone_shift
+ if( zone_shift != b_super.s_log_zone_size) nogood();
+#else
+ zone_shift = b_super.s_log_zone_size;
+#endif
+
+ inode--;
+ load_block(seg_of(b_inode), inode/INODES_PER_BLOCK
+ + b_super.s_imap_blocks
+ + b_super.s_zmap_blocks
+ + 2);
+ get_now();
+
+ ldaddr = LOADSEG; /* Load at 64k mark */
+
+ {
+ register d_inode * i_ptr;
+ i_ptr = b_inode + inode%INODES_PER_BLOCK;
+ next_zone = i_ptr->i_zone;
+ flength = i_ptr->i_size;
+ if( (i_ptr->i_mode & I_TYPE) == I_DIRECTORY )
+ {
+ ldaddr = seg_of(directory);
+ inode = 0; /* Mark - we've no _file_ inode yet */
+ }
+ }
+
+ end_zone = next_zone+NR_DZONE_NUM;
+ load_zone(seg_of(b_zone), (indirect = next_zone[NR_DZONE_NUM]));
+ get_now();
+
+ for(;;)
+ {
+ if( next_zone >= end_zone )
+ {
+ if( indirect != 0 )
+ {
+ next_zone = b_zone;
+ end_zone = next_zone + NR_INDIRECTS;
+ indirect = 0;
+ continue;
+ }
+ break;
+ }
+ load_zone(ldaddr, *next_zone);
+ next_zone++;
+ ldaddr += (seg_at(1) << zone_shift);
+ }
+ get_now();
+
+#ifdef DOTS
+ bios_putc('\r');
+ bios_putc('\n');
+#endif
+ if(!inode)
+ {
+#ifdef DOTS
+ bios_putc('+');
+#endif
+ dirptr = directory;
+ while(flength > 0)
+ {
+register char * s = bootfile;
+register char * p = dirptr->d_name;
+
+ if( dirptr->d_inum )
+ {
+ for(;;)
+ {
+ if( *s == '\0')
+ {
+ if(*p == '\0')
+ {
+ inode = dirptr->d_inum;
+ goto try_again;
+ }
+ break;
+ }
+ if( *s++ != *p++ ) break;
+ }
+ }
+ flength -= 16;
+ dirptr++;
+ }
+ nogood();
+ }
+}
+
+static
+runprog()
+{
+/* This did work, run the loaded executable */
+#asm
+ xor dx,dx ! DX=0 => floppy drive
+ push dx ! CX=0 => partition offset = 0
+ mov si,[_n_sectors] ! Save for monitor.out
+
+ mov bx,#LOADSEG
+ mov ds,bx ! DS = loadaddress
+ inc bx
+ inc bx ! bx = initial CS
+ xor di,di ! Zero
+ mov ax,[di]
+ cmp ax,#0x0301 ! Right magic ?
+ bne nogood ! Yuk ...
+ mov ax,[di+2]
+ and ax,#$20 ! Is it split I/D ?
+ jz impure ! No ...
+ mov cl,#4
+ mov ax,[di+8]
+ shr ax,cl
+impure:
+ pop cx
+ add ax,bx
+ mov ss,ax
+ mov sp,[di+24] ! Chmem value
+ mov ds,ax
+
+ push bx
+ push di ! jmpi 0,#LOADSEG+2
+ retf
+#endasm
+}
+
+#asm
+! These functions are pulled from the C library.
+libstuff:
+imodu:
+ xor dx,dx
+ div bx
+ mov ax,dx ! instruction queue full so xchg slower
+ ret
+idiv_u:
+ xor dx,dx
+ div bx
+ ret
+libend:
+
+vars:
+_n_sectors: .word 0
+_next_zone: .word 0
+_end_zone: .word 0
+_indirect: .word 0
+_ldaddr: .word 0
+_dirptr: .word 0
+_flength: .word 0
+varend:
+
+end_of_prog:
+ if *>start+0x400
+ fail
+ endif
+
+ .blkb 0x3FF+start-*
+ .byte 0xFF
+
+_b_super: .blkb 1024
+_b_inode: .blkb 1024
+_b_zone: .blkb 1024
+_directory: .blkb 32768
+
+#endasm
diff --git a/bootblocks/monitor.c b/bootblocks/monitor.c
new file mode 100644
index 0000000..6c1d9eb
--- /dev/null
+++ b/bootblocks/monitor.c
@@ -0,0 +1,353 @@
+
+#define VERSION "0.0.0-ALPHA"
+#define NOT_ANSICOLOUR
+#define VT52COLOUR
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <i86_funcs.h>
+#include <dos.h>
+
+char command_buf[256];
+
+typedef int (*proc)();
+
+int cmd_quit(), cmd_dump(), cmd_seg(), cmd_rel();
+void init_prog();
+
+extern struct t_cmd_list {
+ char * command;
+ proc func;
+} cmd_list[];
+
+static unsigned int current_address;
+static int number_base = 16;
+
+#ifdef __STANDALONE__
+main()
+#else
+main(argc, argv)
+int argc;
+char ** argv;
+#endif
+{
+static char minibuf[2] = " ";
+ int ch, i;
+ char *cmd, *args, *ptr;
+ struct t_cmd_list * cptr;
+
+ printf("\n\n");
+#ifdef ANSICOLOUR
+ printf("\033[H\033[0;44;37m\033[2J");
+#endif
+#ifdef VT52COLOUR
+ printf("\033E\033Rg\033Sa\033J");
+#endif
+ printf("Linux x86 boot monitor Version %s\n", VERSION);
+
+#ifndef __STANDALONE__
+ if( argc > 1 && strcmp(argv[1], "-t") == 0 ) x86_test=0; else x86_test=1;
+#endif
+
+ init_prog();
+#ifdef __STANDALONE__
+ {
+ extern union REGS __argr;
+ printf("REGS: AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x\n",
+ __argr.x.ax, __argr.x.bx, __argr.x.cx, __argr.x.dx,
+ __argr.x.si, __argr.x.di);
+ }
+#endif
+#ifdef VT52COLOUR
+ printf("Colours: ");
+ printf("\033S \033R_UNL ");
+ printf("\033S \033R*BLK ");
+ printf("\033S \033R+BLD ");
+ printf("\033S \033R!REV");
+ printf("\033Sa\033Rg ");
+ printf("\033R@@\033Raa\033Rbb\033Rcc\033Rdd\033Ree\033Rff\033Rgg");
+ printf("\033Rhh\033Rii\033Rjj\033Rkk\033Rll\033Rmm\033Rnn\033Roo");
+ printf("\033Sa\033Rg\n");
+#endif
+
+ printf("Type ^C to exit\n");
+
+ for (;;)
+ {
+#ifdef ANSICOLOUR
+ printf("\033[36m");
+#endif
+#ifdef VT52COLOUR
+ printf("\033S \033R+\033Sa\033Rc");
+#endif
+ printf(">");
+ fflush(stdout);
+ ch = read(0, command_buf, sizeof(command_buf)-1) ;
+ if( ch <= 0 ) break;
+ command_buf[ch] = '\0';
+ if( ch == 1 && command_buf[0] != '\n' )
+ {
+ sprintf(command_buf, "func 0x%02x\n", command_buf[0]&0xFF);
+ printf("%s", command_buf);
+ }
+ if( command_buf[ch-1] == '\n' ) command_buf[ch-1] = 0;
+
+ for(ptr=command_buf; *ptr; ptr++)
+ {
+ if(*ptr=='"') do { ptr++; } while(*ptr && *ptr != '"');
+ if( isupper(*ptr) ) *ptr = tolower(*ptr);
+ }
+
+ cmd = command_buf;
+ while(*cmd == ' ') cmd++;
+ if( !isalpha(cmd[0]) || !isalpha(cmd[1]) )
+ {
+ minibuf[0] = cmd[0];
+ args = cmd+1;
+ cmd = minibuf;
+ }
+ else
+ {
+ args = strchr(cmd, ' ');
+ if( args ) *args++ = 0;
+ else args = cmd + strlen(cmd);
+ }
+
+ if( *cmd == 0 ) continue;
+
+ for(cptr = cmd_list; cptr->command; cptr++)
+ {
+ if( strcmp(cptr->command, cmd) == 0 )
+ break;
+ }
+#ifdef ANSICOLOUR
+ printf("\033[37m");
+#endif
+#ifdef VT52COLOUR
+ printf("\033S \033Sa\033Rg");
+#endif
+ if( cptr->command )
+ (void) (*cptr->func)(args);
+ else
+ printf("Command not found.\n");
+ }
+}
+
+/****************************************************************************/
+
+void init_prog()
+{
+ cpu_check();
+ mem_check();
+
+ printf("Processor: %s", x86_name);
+ if(x86_fpu) printf(" with FPU");
+ if(x86_emu) printf(" in protected mode");
+ if(!x86_test && x86 > 1)
+ {
+ printf(", A20 gate ");
+ if( a20_closed() )
+ {
+ open_a20();
+ if( a20_closed() )
+ printf("won't open!!");
+ else
+ printf("is now open");
+ }
+ else printf("is already open.");
+ }
+ printf("\n");
+
+ printf("There is %dk of boot memory", boot_mem_top/64);
+ if( main_mem_top )
+ {
+ printf(" %ld.%ldM of main memory",
+ main_mem_top/1024,
+ (10*main_mem_top)/1024%10
+ );
+ }
+ printf("\n");
+
+ if( main_mem_top >= 0xFC00L )
+ printf("There may be more main memory available but the BIOS don't say\n");
+}
+
+/****************************************************************************/
+
+int
+getnum(numptr, valptr)
+char ** numptr;
+unsigned int * valptr;
+{
+ char * ptr = *numptr;
+ unsigned int val = 0;
+ int base = number_base;
+ int flg = 0;
+
+ while( *ptr && *ptr <= ' ' ) ptr++;
+ switch(*ptr)
+ {
+ case '$': case '&': case 'X':
+ base=16; ptr++; break;
+ case '#':
+ base=10; ptr++; break;
+ case '%':
+ base=2; ptr++; break;
+ case '0':
+ if( ptr[1] == 'X' ) { base=16; ptr+=2; }
+ break;
+ case '-':
+ *numptr = ptr+1;
+ return 0;
+ }
+
+ while(*ptr)
+ {
+ int d = -1, ch;
+ ch = *ptr;
+ if( ch >= '0' && ch <= '9' ) d = ch - '0';
+ if( ch >= 'a' && ch <= 'z' ) d = ch - 'a' + 10;
+ if( ch >= 'A' && ch <= 'Z' ) d = ch - 'A' + 10;
+
+ if( d>=0 && d<base )
+ {
+ val = val * base + d;
+ ptr++;
+ flg=1;
+ }
+ else
+ break;
+ }
+ if( flg )
+ {
+ *numptr = ptr;
+ if(valptr) *valptr = val;
+ else return val;
+ }
+ return flg;
+}
+
+/****************************************************************************/
+
+int cmd_quit(args)
+char * args;
+{
+ printf("Bye\n");
+ exit(0);
+}
+
+cmd_memdump(ptr)
+char * ptr;
+{
+ int count = 128;
+ int i,j;
+ int es = __get_es();
+
+#define rmem(x) __peek_es( (x)+current_address )
+
+ getnum(&ptr, &current_address);
+ getnum(&ptr, &count);
+
+ for(i=0; i<count; i+=16)
+ {
+ printf("%04x:%04x:", es, current_address);
+ for(j=0; j<16; j++)
+ printf(" %02x", rmem(j));
+ printf(" ");
+ for(j=0; j<16; j++)
+ if( rmem(j) >= ' ' && rmem(j) <= '~' )
+ putchar(rmem(j));
+ else
+ putchar('.');
+ putchar('\n');
+ current_address += 16;
+ current_address &= 0xFFFF;
+ }
+
+#undef rmem
+}
+
+int cmd_nop(ptr)
+char * ptr;
+{
+}
+
+int cmd_seg(ptr)
+char * ptr;
+{
+ int es = __get_es();
+
+ if( getnum(&ptr, &es) )
+ {
+ __set_es(es);
+ current_address = 0;
+ }
+ else
+ printf("Current segment 0x%04x\n", es);
+ return 0;
+}
+
+int cmd_set_base(ptr)
+{
+ int obase = number_base;
+ int nbase;
+ number_base = 10;
+
+ if( getnum(&ptr, &nbase) )
+ {
+ if( nbase < 2 || nbase > 36 )
+ printf("Can't use that base\n");
+ else
+ obase = nbase;
+ }
+ else printf("Current base is %d\n", obase);
+
+ number_base = obase;
+ return 0;
+}
+
+int cmd_rel(ptr)
+char * ptr;
+{
+ int nseg = 0xFFFF;
+
+ getnum(&ptr, &nseg);
+
+ printf("Monitor code seg from 0x%04x ", __get_cs());
+ fflush(stdout);
+ relocator(nseg);
+ printf("to 0x%04x\n", __get_cs());
+}
+
+/****************************************************************************/
+
+struct t_cmd_list cmd_list[] =
+{
+ {"exit", cmd_quit}, {"quit", cmd_quit}, {"q", cmd_quit},
+ {"memdump",cmd_memdump}, {"m", cmd_memdump},
+ /* Display bytes */
+ {"seg", cmd_seg}, /* Set default segment */
+ {"rel", cmd_rel}, /* Relocate self */
+ {"base", cmd_set_base},
+ {"n", cmd_set_base},
+ {"#", cmd_nop},
+/*
+ {"edit", cmd_edit}, Alter memory
+ {"move", cmd_move}, Move memory contents
+
+ {"dir", cmd_dir}, Display dir of inode
+ {"load", cmd_load}, Load file of inode
+ {"stat", cmd_stat}, Stat info of inode
+
+ {"zimage", cmd_zimage}, Load and run 386 zimage from inode or tar file
+ {"bimage", cmd_bimage}, Load and run 386 bzimage from inode or tar file
+ {"image", cmd_image}, Load and run 8086 image from inode or tar file
+
+ {"read", cmd_read}, Read sector
+ {"write", cmd_write}, Write sector
+
+ {"call", cmd_call}, load and run a bcc linux-8086 program.
+*/
+ {0,0}
+};
diff --git a/bootblocks/relocate.c b/bootblocks/relocate.c
new file mode 100644
index 0000000..121699e
--- /dev/null
+++ b/bootblocks/relocate.c
@@ -0,0 +1,77 @@
+
+#include <i86_funcs.h>
+
+static unsigned memseg = 0, memlen = 0;
+
+char buf[1];
+
+void
+relocator(newseg)
+unsigned newseg;
+{
+ unsigned moved, codelen;
+ unsigned es = __get_es();
+
+ if( x86_test ) return; /* I don't think so! */
+
+ /* Where do we start */
+ if(memseg == 0)
+ {
+ memseg = __get_cs();
+ codelen = __get_ds()-memseg;
+ __set_es(memseg-2);
+ memlen = __deek_es( 24 );
+ memlen >>=4;
+ if( memlen == 0 ) memlen = 0x1000;
+ memlen += codelen;
+ __set_es(es);
+ }
+
+ if( newseg < 0x50 ) return;
+
+ if( newseg == 0xFFFF )
+ {
+ newseg = boot_mem_top;
+ if( newseg > 0x90000 ) newseg = 0x90000;
+ newseg -= memlen;
+ }
+
+ /* If the old area overlaps the new then fail */
+ if( newseg >= memseg && newseg < memseg+memlen ) return;
+ if( memseg >= newseg && memseg < newseg+memlen ) return;
+
+ /* Copy segments, done in 32k chunks */
+ for(moved=0; moved < memlen; )
+ {
+ unsigned int lump;
+ if( memlen <= 0x800 ) lump = memlen; else lump = 0x800;
+
+ __movedata(memseg+moved, 0, newseg+moved, 0, (lump<<4));
+ moved += lump;
+ }
+
+ /* re-link int 0x80
+ __set_es(0);
+ __doke_es(0x80*4+2, newseg);
+ __set_es(es);
+ */
+
+ /* The actual jump ... */
+ memseg = newseg;
+#asm
+ mov ax,ds
+ mov bx,cs
+ sub ax,bx
+ mov bx,[_memseg]
+ add ax,bx
+ push bx
+ call L_x
+ mov ds,ax
+ mov ss,ax
+ mov [_memseg],bx
+#endasm
+}
+#asm
+L_x:
+ retf
+#endasm
diff --git a/bootblocks/standalone.c b/bootblocks/standalone.c
new file mode 100644
index 0000000..57634d4
--- /dev/null
+++ b/bootblocks/standalone.c
@@ -0,0 +1,309 @@
+
+#include <errno.h>
+#asm
+entry _int_80 ! Tell ld86 we really do need this file.
+ ! then call the init stuff before main.
+
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _pre_main ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+
+void int_80();
+
+static void pre_main()
+{
+ /* Set the int 0x80 pointer to here */
+ __set_es(0);
+ __doke_es(0x80*4+0, int_80);
+ __doke_es(0x80*4+2, __get_cs());
+ bios_coninit();
+}
+
+void int_80()
+{
+#asm
+SYS_EXIT=1
+SYS_FORK=2
+SYS_READ=3
+SYS_WRITE=4
+SYS_OPEN=5
+SYS_CLOSE=6
+SYS_CHDIR=12
+SYS_LSEEK=19
+ENOSYS=38
+
+ push es
+ push si
+ push di
+ push dx
+ push cx
+ push bx
+ cmp ax,#SYS_READ
+ jne L1
+ call _func_read
+ jmp L0
+L1:
+ cmp ax,#SYS_WRITE
+ jne L2
+ call _func_write
+ jmp L0
+L2:
+ cmp ax,#SYS_LSEEK
+ jne L3
+ call _func_lseek
+ jmp L0
+L3:
+ cmp ax,#SYS_EXIT
+ jne L4
+ call _func_exit
+ jmp L0
+L4:
+ mov ax,#-ENOSYS
+L0:
+ pop bx
+ pop cx
+ pop dx
+ pop di
+ pop si
+ pop es
+ iret
+#endasm
+}
+
+func_lseek() { return -38; }
+
+func_write(bx,cx,dx,di,si,es)
+int bx,dx;
+char * cx;
+{
+ register int v, c;
+ if(bx == 1 || bx == 2)
+ {
+ for(v=dx; v>0; v--)
+ {
+ c= *cx++;
+ if( c == '\n') bios_putc('\r');
+ bios_putc(c);
+ }
+ return dx;
+ }
+ return -EBADF;
+}
+
+func_read(bx,cx,dx,di,si,es)
+int bx,dx;
+char * cx;
+{
+ if(bx == 0) return read_line(cx, dx);
+ return -EBADF;
+}
+
+read_line(buf, len)
+char * buf;
+int len;
+{
+ int ch;
+ int pos=0;
+
+ if( len == 1 )
+ {
+ buf[0]=((ch=bios_getc())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80));
+ return 1;
+ }
+
+ for(ch=0;;)
+ {
+ if(ch != '\003')
+ {
+ ch = bios_getc();
+ if( pos == 0 && (ch&0xFF) == 0 )
+ {
+ buf[0] = ((ch>>8)|0x80);
+ return 1;
+ }
+ ch &= 0x7F;
+ }
+ if( ch == '\r' )
+ {
+ bios_putc('\r'); bios_putc('\n');
+ buf[pos++] = '\n';
+ return pos;
+ }
+ if( ch >= ' ' && ch != 0x7F && pos < len-1)
+ bios_putc(buf[pos++] = ch);
+ else if( (ch == '\003' || ch == '\b') && pos > 0 )
+ {
+ bios_putc('\b'); bios_putc(' '); bios_putc('\b');
+ pos--;
+ }
+ else if( ch == '\003' )
+ return 0;
+ else
+ bios_putc('\007');
+ }
+}
+
+#define CTRL(x) ((x)&0x1F)
+static int last_attr = 0x07;
+static int con_mode;
+static int con_size = 0x184F;
+static int con_colour = 0;
+
+bios_coninit()
+{
+#asm
+ mov ax,#$0F00
+ int $10
+ mov _con_mode,ax
+#endasm
+ if( (con_mode &0xFF) > 39 ) con_size = (con_size&0xFF00) + (con_mode&0xFF);
+ if( (con_mode&0xFF00) != 0x700)
+ con_colour = 1;
+}
+
+bios_putc(c)
+int c;
+{
+static char tbuf[3];
+static int tcnt=0;
+ if(tcnt)
+ {
+ tbuf[tcnt++] = c;
+ if( tcnt < 3 && (tbuf[0] != CTRL(']') || tbuf[1] < '`' || tbuf[1] > 'p'))
+ return;
+ if( tbuf[0] == CTRL('P') )
+ {
+ if( tbuf[1] >= 32 && tbuf[1] <= 56
+ && tbuf[2] >= 32 && tbuf[2] <= 111 )
+ asm_cpos((tbuf[1]-32), (tbuf[2]-32));
+ }
+ else
+ {
+ if( tbuf[1] >= '`' )
+ last_attr = ( (tbuf[1]&0xF) | (last_attr&0xF0));
+ else
+ last_attr = ( (tbuf[2]&0xF) | ((tbuf[1]&0xF)<<4));
+
+ if( !con_colour )
+ last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70);
+ }
+ tcnt=0;
+ return;
+ }
+ if( c & 0xE0 ) { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('P'):
+ case CTRL(']'):
+ tbuf[tcnt++] = c;
+ break;
+ default:
+ asm_putc(c);
+ break;
+ }
+ return;
+}
+
+static asm_putc(c)
+{
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ mov ah,#$0E
+ mov bx,#7
+ int $10
+#endasm
+}
+
+static asm_colour(c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ mov ah,#$08
+ int $10
+ mov ah,#$09
+ mov cx,#1
+ int $10
+#endasm
+}
+
+static asm_cls()
+{
+#asm
+ push bp ! Bug in some old BIOS's
+ !mov ax,#$0500
+ !int $10
+ mov ax,#$0600
+ mov bh,_last_attr
+ mov cx,#$0000
+ mov dx,_con_size
+ int $10
+ pop bp
+#endasm
+}
+
+static asm_cpos(r,c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov dh,al
+ mov ax,[bx+2]
+ mov dl,al
+#else
+ mov bx,sp
+ mov ax,[bx+2]
+ mov dh,al
+ mov ax,[bx+4]
+ mov dl,al
+#endif
+ mov ah,#$02
+ mov bx,#7
+ int $10
+#endasm
+}
+
+bios_getc()
+{
+#asm
+ xor ax,ax
+ int $16
+#endasm
+}
+
+static void be_safe()
+{
+#asm
+ iret
+#endasm
+}
+
+func_exit(bx,cx,dx,di,si,es) /* AKA reboot! */
+{
+ __set_es(0);
+ __doke_es(0xE6*4+2,__get_cs());
+ __doke_es(0xE6*4+0,be_safe);
+#asm
+ mov ax,#$FFFF
+ int $E6 ! Try to exit DOSEMU
+ mov ax,#$0040 ! If we get here we're not in dosemu.
+ mov es,ax
+ seg es
+ mov [$72],#$1234 ! Warm reboot.
+ jmpi $0000,$FFFF
+#endasm
+}
diff --git a/bootblocks/sysboot.s b/bootblocks/sysboot.s
new file mode 100644
index 0000000..496b7a5
--- /dev/null
+++ b/bootblocks/sysboot.s
@@ -0,0 +1,77 @@
+
+! The master boot sector will have setup a stack,
+! this is normally at 0:7c00 down.
+! DS, SS, CS and ES will all have value 0 so the execution address is 0:7c00
+! On entry the register SI will be pointer to the partition entry that
+! this sector was loaded from, DL is the drive.
+
+! Also if it's a standard Master boot DH will be the head, CX will be the
+! sector and cylinder, BX=7C00, AX=1, DI=7DFE, BP=SI. There's a reasonable
+! chance that this isn't true though.
+
+! The Master boot itself will have been loaded and run at $07c00
+! The BIOS must have setup a stack because interrupts are enabled
+! Little else can be assumed because DOS doesn`t assume anything either
+
+sysboot_start:
+j codestart
+
+.blkb sysboot_start+3-*
+public dosfs_stat
+dosfs_stat:
+.blkb 8 ! System ID
+.word 0 ! Sector size
+.byte 0 ! Cluster size
+.word 0 ! Res-sector
+.byte 0 ! FAT count
+.word 0 ! Root dir entries
+.word 0 ! Sector count (=0 if large FS)
+.byte 0 ! Media code
+.word 0 ! FAT length
+.word 0 ! Sect/Track
+.word 0 ! Heads
+.long 0 ! Hidden sectors
+! Here down is DOS 4+
+.long 0 ! Large FS sector count
+.byte 0 ! Phys drive
+.byte 0 ! Reserved
+.byte 0 ! DOS 4
+.long 0 ! Serial number
+.blkb 11 ! Disk Label (DOS 4+)
+.blkb 8 ! FAT type
+
+.blkb sysboot_start+0x3E-*
+public codestart
+codestart:
+ hlt
+
+! Partition table
+public partition_1
+public partition_2
+public partition_3
+public partition_4
+
+.blkb sysboot_start+0x1BE-*
+partition_1:
+.byte 0,0,0,0,0,0,0,0 ! IN,SH,SS,ST,OS,EH,ES,ET
+.long 0 ! Linear position (0 based)
+.long 0 ! Linear length
+.blkb sysboot_start+0x1CE-*
+partition_2:
+.byte 0,0,0,0,0,0,0,0 ! IN,SH,SS,ST,OS,EH,ES,ET
+.long 0 ! Linear position (0 based)
+.long 0 ! Linear length
+.blkb sysboot_start+0x1DE-*
+partition_3:
+.byte 0,0,0,0,0,0,0,0 ! IN,SH,SS,ST,OS,EH,ES,ET
+.long 0 ! Linear position (0 based)
+.long 0 ! Linear length
+.blkb sysboot_start+0x1EE-*
+partition_4:
+.byte 0,0,0,0,0,0,0,0 ! IN,SH,SS,ST,OS,EH,ES,ET
+.long 0 ! Linear position (0 based)
+.long 0 ! Linear length
+
+.blkb sysboot_start+0x1FE-*
+.word 0xAA55
+
diff --git a/bootblocks/tarboot.s b/bootblocks/tarboot.s
new file mode 100644
index 0000000..ffa8db6
--- /dev/null
+++ b/bootblocks/tarboot.s
@@ -0,0 +1,509 @@
+!
+! This is floppy bootblock to load the first item from a tar file.
+!
+! The tar file is constructed with a GNU TAR label at the start
+! which is replaced with this by the makeboot.c program.
+!
+! The first item must be a Linux-8086 executable compiled with the -Ms option
+!
+! Copyright (C) 1996 Robert de Bath, distributed under the GPL Version 2.
+!
+
+BOOTADDR= 0x7C00 ! The address that the boot seg is loaded.
+
+RELADDR = 0x0600 ! This is floppy, so we can relocate to 'super' address
+ ! It appears the 0500 is also ok as that's DOS memory
+ ! But then where can we get 200 bytes of stack!
+
+STACK = 0x0600 ! Inital stack, 0 makes bad_magic
+
+LOADSEG = 0x0080 ! Segment for program load, this must be 512b aligned
+ ! The first 32 bytes are the a.out header.
+DEBUG=1 ! Print dots ...
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+macro locn
+ if *-start>?1
+ fail
+ endif
+ .blkb ?1 + start-*
+mend
+
+! On startup from a floppy boot it`s probably best if we assume _nothing_
+! that we don`t have to ...
+!
+! So, `start` is, erm, right here :-)
+! The boot block is re-loaded from the floppy for relocation.
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ use16
+ org RELADDR
+
+start:
+ ! Don't even _think_ of changing this unless you're 110% sure!
+ .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
+ .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
+
+ block start
+ .asciz "ENIAC"
+ .byte $C0
+ endb
+
+ ! All right, I'll help, you can use any of these chars:
+ ! "/?@ABCDEFGHIJKLMNO"
+ ! Others are likely to cause ... problems.
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+! Beware; the assumption is this code is relocatable.
+
+ xor ax,ax
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ if STACK = 0
+ mov sp,ax
+ else
+ mov sp,#STACK ! Stack location
+ endif
+ cld
+
+! ASSUME ds=ss=es=cs=0
+keep_trying1:
+! Get the tar block after this program, and relocate this code.
+ mov ax,#$0202 ! Read 2 sectors
+ mov bx,#start ! Where this _should_ be
+ mov cx,#$0001 ! From sector 1
+ xor dx,dx ! Of the floppy drive head zero
+ int $13
+ jc keep_trying1
+ jmpi going,#0
+going:
+
+! OK. Code will now be run at correct address.
+
+if DEBUG
+ call pboot
+endif
+
+ mov al,tar_link
+ cmp al,#'0
+ jnz nogood ! Make sure next item is file.
+
+ call probe_floppy
+
+ call get_size ! Get number of clicks in di
+ cmp di,#0
+ jz nogood ! If it`s zero .. Hmm
+
+ if STACK = 0
+ mov sp,#bad_magic ! Real bad magic :-)
+ endif
+
+ call load_sectors
+
+! This requires that we have been relocated, so we can't call it too soon.
+nogood:
+ push cs
+ pop es
+
+hcode:
+ mov ax,#$0201 ! Read 1 sector
+ mov bx,#BOOTADDR ! into the boot area
+ mov cx,#1 ! sector 1
+ mov dx,#$0080 ! hard drive head zero
+ int $13
+ jc hcode ! Keep trying forever!
+ jmpi BOOTADDR,#0
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! These are the number of sectors per track that will be scanned for.
+! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on
+! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies.
+
+disksizes: .byte 36,21,18,15,9
+
+! End of part 1
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+! This is important bits of the TAR Block.
+! The chksum field will need to be changed if any mods are done to this
+! file so that the bare header is a TAR file. If it's installed using
+! makeboot that program will correct the sum as it also changes the time.
+
+ locn(100)
+blk_mode: .asciz " 4111"
+blk_uid: .blkb 8
+blk_gid: .blkb 8
+blk_size: .blkb 12
+blk_mtime: .asciz "6141567743 "
+blk_chksum: .asciz " 131141"
+blk_link: .byte 'V
+
+! Sneaks here, overlay zero init vars on tar data.
+
+ block blk_mode
+public sectors
+sectors: .blkw 1 ! POSITION OF THIS FIELD IS MAGIC!
+ ! other programs know it's at pos 100
+
+bios_disk: .blkb 12 ! BPB for FD0
+head: .word 0 ! current head
+track: .word 0 ! current track
+
+ endb
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! This code taken from the Linux bootsector and adjusted to suit
+!
+! Many BIOS's default disk parameter tables will not
+! recognize multi-sector reads beyond the maximum sector number
+! specified in the default diskette parameter tables - this may
+! mean 7 sectors in some cases.
+!
+! Since single sector reads are slow and out of the question,
+! we must take care of this by creating new parameter tables
+! (for the first disk) in RAM. We will set the maximum sector
+! count to 36 - the most we will encounter on an ED 2.88.
+!
+! High doesn't hurt. Low does.
+!
+! Segments are as follows: ds=es=ss=cs=0
+!
+
+probe_floppy:
+ mov di,#bios_disk
+
+ mov bx,#0x78
+! 0:bx is parameter table address
+ push ds
+ lds si,[bx]
+
+! ds:si is source
+
+ mov cl,#6
+! copy 12 bytes
+ cld
+ push di
+
+ rep
+ movsw
+
+ pop di
+ pop ds
+ movb 4[di],*36 ! patch sector count
+
+ mov [bx],di
+ mov 2[bx],es
+
+! It seems that there is no BIOS call to get the number of sectors. Guess
+! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
+! 15 if sector 15 can be read. Otherwise guess 9.
+
+ mov si,#disksizes ! table of sizes to try
+
+probe_loop:
+ lodsb
+ cbw ! extend to word
+ mov sectors, ax
+ cmp al,#9
+ je got_sectors ! if all else fails, try 9
+ xchg ax, cx ! cx = track and sector
+ xor dx, dx ! drive 0, head 0
+ mov bx,#probe_buf ! address after setup (es = cs)
+ mov ax,#0x0201 ! service 2, 1 sector
+ int 0x13
+ jc probe_loop ! try next value
+got_sectors:
+
+ ret
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! This function reads the size of the first file in the TAR image. It's
+! stored in octal in the tar header that was loaded just after this block.
+
+get_size:
+ mov di,#tar_size
+ xor dx,dx
+ xor bx,bx
+ xor cx,cx
+
+next_dig:
+ mov al,[di]
+ and al,#$F8
+ cmp al,#'0
+ jne no_dig
+
+ mov al,[di]
+ and al,#$07
+
+ mov cl,#3
+mul_loop:
+ sal bx,#1 ! Double prec * 8
+ rcl dx,#1
+ loop mul_loop
+ or bl,al
+
+no_dig:
+ inc di
+ cmp di,#tar_mtime
+ jne next_dig
+
+ add bx,#15 ! How many clicks ?
+ adc dx,cx ! AKA zero
+ mov cl,#4
+div_loop:
+ shr dx,#1
+ rcr bx,#1
+ loop div_loop
+
+ mov di,bx
+bad_magic:
+ ret
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! This is good so far, is it an 8086 a.out file ?
+! If so start it.
+
+go_go_go:
+ xor dx,dx ! DX=0 => floppy drive
+ push dx ! CX=0 => partition offset = 0
+ mov si,[sectors] ! Save for monitor.out
+
+ mov bx,#LOADSEG
+ mov ds,bx ! DS = loadaddress
+ inc bx
+ inc bx ! bx = initial CS
+ xor di,di ! Zero
+ mov ax,[di]
+ cmp ax,#0x0301 ! Right magic ?
+ jnz bad_magic ! Yuk ...
+ mov ax,[di+2]
+ and ax,#$20 ! Is it split I/D ?
+ jz impure ! No ...
+ mov cl,#4
+ mov ax,[di+8]
+ shr ax,cl
+impure:
+ pop cx ! Partition offset.
+ add ax,bx
+ mov ss,ax
+ mov sp,[di+24] ! Chmem value
+ mov ds,ax
+
+ push bx ! jmpi 0,#LOADSEG+2
+ push di
+
+ ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=*
+ retf
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+! This isn't in a normal volume lable, no problem it leaves more space.
+!
+! locn(257)
+! blk_magic: .ascii "ustar "
+! .blkb 1
+! blk_uname: .ascii "TarBoot/Copyright"
+! blk_uname_end:
+! .blkb 32+blk_uname-blk_uname_end
+! blk_gname: .ascii "R de Bath"
+! blk_gname_end:
+! .blkb 32+blk_gname-blk_gname_end
+! blk_devmaj: .blkb 8
+! blk_devmin: .blkb 8
+!
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+if DEBUG
+dot: mov al,#'.
+putc:
+ push bx
+ mov bx,#7
+ mov ah,#$E
+ int $10
+ pop bx
+ ret
+
+endif
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! This code taken from the Linux bootsector and adjusted to suit
+!
+! This routine loads the system at address LOADSEG, making sure
+! no 64kB boundaries are crossed. We try to load it as fast as
+! possible, loading whole tracks whenever we can.
+!
+! LOADSEG must be sector aligned and sectors will be loaded upto
+! the next 64k boundry past the segment specified by DI.
+
+load_sectors:
+ if LOADSEG & $F000 = 0
+ xor ax,ax
+ else
+ mov ax,#LOADSEG & $F000 ! segment to load to
+ endif
+ mov es,ax
+
+! dx=sectors read of current track
+! bx=offset in memory of block
+! si=sectors read to block
+! al=number to read
+
+read_it:
+ mov dx,#2 ! Volume lable + tar header
+ if LOADSEG & $0FFF = 0
+ xor si,si
+ else
+ mov si,#(LOADSEG & $FFF)>>5
+ endif
+ add di,#LOADSEG
+rp_read:
+if DEBUG
+ call dot
+endif
+ mov ax,es
+ cmp ax,di ! have we loaded all yet?
+ jbe ok1_read
+ jmp go_go_go ! Loaded, run it.
+ok1_read:
+ mov ax,sectors ! nr of sectors/track
+
+ sub ax,dx ! remaining of track
+
+ mov cx,ax ! cx= remaining
+
+ add cx,si ! boundary check
+ cmp cl,#128
+ jbe ok2_read !
+ ! to much-> fill block
+ mov ax,#128 ! ax=0
+ sub ax,si ! so much may be read
+
+ok2_read:
+ mov bx,si
+ mov cx,#9
+ shl bx,cl
+ call read_track ! do it
+ mov cx,ax ! cl=read blocks
+
+ add ax,dx ! ax=new sectors
+
+ cmp ax,sectors ! track done?
+ jne ok3_read
+ mov ax,#1 ! yes
+ sub ax,head
+ jne ok4_read ! next head
+ inc track ! next track
+ok4_read:
+ mov head,ax
+ xor ax,ax
+ok3_read:
+ mov dx,ax
+
+ add si,cx
+ cmp si,#128
+ jne rp_read
+
+ mov ax,es
+ add ah,#0x10
+ mov es,ax
+
+ xor si,si
+ jmp rp_read
+
+read_track:
+ push dx
+ push ax
+ push bx
+
+ mov cx,dx
+ mov dx,track
+ inc cx
+ mov ch,dl
+ mov dx,head
+ mov dh,dl
+ and dx,#0x0100
+ mov ah,#2
+
+ int 0x13
+! ah=02h al=nr sectors to read
+! ch=cylinder
+! cl=sector
+! dh=head
+! dl=drive
+! es:bx=buffer
+
+ jc bad_rt
+ pop bx
+ pop ax
+ pop dx
+ ret
+
+bad_rt: xor ah,ah
+ xor dl,dl
+ int 0x13
+
+ pop bx
+ pop ax
+ pop dx
+ jmp read_track
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! This is the GNU-TAR 'isextended' field. It must be zero or gtar goes apeshit.
+ locn(482)
+ .byte 0
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+if DEBUG
+pboot:
+ mov si,#mesg
+nextc:
+ lodsb
+ call putc
+ cmp al,#0
+ jnz nextc
+ ret
+
+locn(512-16)
+mesg:
+.ascii "Tarboot loading "
+endif
+
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+if DEBUG = 0
+ locn(510)
+! This isn't a hard disk boot sector so don't give it an HD magic
+! .word 0xAA55
+ .word 0
+endif
+
+! From here down is where we load stuff.
+
+blk_load: ! Address of block load
+tar_name: .blkb 100
+tar_mode: .blkb 8
+tar_uid: .blkb 8
+tar_gid: .blkb 8
+tar_size: .blkb 12
+tar_mtime: .blkb 12
+tar_chksum: .blkb 8
+tar_link: .blkb 1 ! "0"
+tar_linkname: .blkb 100
+tar_magic: .blkb 8 ! "ustar "
+tar_uname: .blkb 32
+tar_gname: .blkb 32
+tar_devmaj: .blkb 8
+tar_devmin: .blkb 8
+tar_padd:
+
+
+ locn(1024)
+probe_buf: .blkb 512
+
+
diff --git a/bootblocks/tich.s b/bootblocks/tich.s
new file mode 100644
index 0000000..830f742
--- /dev/null
+++ b/bootblocks/tich.s
@@ -0,0 +1,38 @@
+!
+
+org 0
+ call chk !This chunk allows this code to exist at _any_ click
+chk:
+ pop ax
+ mov cl,#4
+ shr ax,cl
+ mov bx,cs
+ add ax,bx
+ push ax
+ mov bx,#going
+ push bx
+ retf
+going:
+ mov ds,ax
+ mov es,ax
+
+! Print 'mesg'
+ mov ah,#0x03 ! read cursor pos
+ xor bh,bh
+ int 0x10
+
+ mov cx,#(emesg-mesg)
+ mov bp,#mesg
+ mov bx,#$7 ! page 0, attribute 7 (normal)
+ mov ax,#$1301 ! write string, move cursor
+ int $10
+
+nogood:
+ j nogood
+
+mesg:
+.ascii "Hello world"
+emesg:
+
+org 510
+ .word 0xAA55
diff --git a/bootblocks/tiny.s b/bootblocks/tiny.s
new file mode 100644
index 0000000..6090cd3
--- /dev/null
+++ b/bootblocks/tiny.s
@@ -0,0 +1,55 @@
+!
+! This floppy bootblock bypasses the floppy boot ...
+!
+
+BOOTSEG = 0x07c0
+BOOTDISK = 0x80
+
+! Apparently on startup the only things we can assume are that we start at
+! `start` (ABS addr $07C00) and we`ll have a few bytes of stack storage...
+
+! So first set DS=ES= 0x07c0
+ include sysboot.s
+ .blkb codestart-*
+
+start:
+ mov ax,#BOOTSEG
+ mov ds,ax
+ mov es,ax
+
+! Print 'mesg'
+ mov ah,#0x03 ! read cursor pos
+ xor bh,bh
+ int 0x10
+
+ mov cx,#(emesg-mesg)
+ mov bp,#mesg
+ mov bx,#$7 ! page 0, attribute 7 (normal)
+ mov ax,#$1301 ! write string, move cursor
+ int $10
+
+nogood:
+ xor si,si
+ mov di,#$0200
+ mov cx,#$0100
+ rep
+ movw
+ jmpi hcode,#BOOTSEG+$20
+
+hcode:
+ mov ax,#$0201 ! Read 1 sector
+ xor bx,bx ! In the boot area
+ mov cx,#$0001 ! From sector 1
+ mov dx,#BOOTDISK ! Of the hard drive head zero
+ int $13
+ jc hcode ! Keep trying forever!
+ jmpi $7c00,0
+
+
+mesg:
+ if BOOTDISK = 0x80
+.ascii "Bypassing floppy boot\r\n"
+ else
+.ascii "Booting drive two\r\n"
+ endif
+emesg: