summaryrefslogtreecommitdiff
path: root/bootblocks
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1997-02-25 20:42:19 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:38:07 +0200
commit4c36e9a0c125ccfff37aa440dab2cf58c4152fff (patch)
treea5d9c84ba2661029ddb2223dacd50529a361c3d5 /bootblocks
parentf8de35da65c5d93bb733073cf40da154bc1c0748 (diff)
parent9696d7b0e1f3a1b0f5fd4a0428eb75afe8ad4ed6 (diff)
downloaddev86-4c36e9a0c125ccfff37aa440dab2cf58c4152fff.tar.gz
Import Dev86src-0.0.11.tar.gzv0.0.11
Diffstat (limited to 'bootblocks')
-rw-r--r--bootblocks/Makefile42
-rw-r--r--bootblocks/README80
-rw-r--r--bootblocks/bzimage.c555
-rw-r--r--bootblocks/dosboot.c72
-rw-r--r--bootblocks/dosfs.c419
-rw-r--r--bootblocks/help.c93
-rw-r--r--bootblocks/i86_funcs.c28
-rw-r--r--bootblocks/makeboot.c634
-rw-r--r--bootblocks/mbr.s4
-rw-r--r--bootblocks/monitor.c161
-rw-r--r--bootblocks/msdos.s214
-rw-r--r--bootblocks/nofs.c55
-rw-r--r--bootblocks/relocate.c9
-rw-r--r--bootblocks/skip.s1
-rw-r--r--bootblocks/sysboot.s64
15 files changed, 2068 insertions, 363 deletions
diff --git a/bootblocks/Makefile b/bootblocks/Makefile
index 9a4ccd9..85393a7 100644
--- a/bootblocks/Makefile
+++ b/bootblocks/Makefile
@@ -1,17 +1,16 @@
HOSTCC=cc
HOSTCCFLAGS=-O
+BCC=bcc
-CC=bcc
-CFLAGS=-ansi -O -Ms
-AS=as86
+CC=$(BCC)
+CFLAGS=-ansi -Ms -H0x10000 -s
ASFLAGS=-0
# LST=-l $*.lst
-nothing:
- @more README
+default: makeboot makeboot.com monitor.out
-all: makeboot monitor.out bin
+all: default tgz bin
CSRC=minix.c
SSRC=tarboot.s skip.s com_bcc.s tich.s sysboot.s bootlist.s mbr.s msdos.s
@@ -19,8 +18,8 @@ SSRC=tarboot.s skip.s com_bcc.s tich.s sysboot.s bootlist.s mbr.s msdos.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
+MOBJ=monitor.o i86_funcs.o relocate.o help.o bzimage.o dosfs.o nofs.o
+MSRC=monitor.c i86_funcs.c relocate.c help.c bzimage.c dosfs.c nofs.c
install:
@@ -29,40 +28,41 @@ monitor.out: $(MOBJ)
monitor: $(MSRC)
@rm -f $(MOBJ)
- make 'CFLAGS=-ansi -O' monitor.out
+ make 'CFLAGS=-ansi' monitor.out
mv monitor.out monitor
@rm -f $(MOBJ)
minix.s: minix.c
- bcc -Mf -O -S minix.c
+ $(BCC) -Mc -S minix.c
-makeboot: tarboot.v sysboot.v makeboot.c
+makeboot: makeboot.c sysboot.v skip.v msdos.v tarboot.v
$(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c
-dosboot: dosboot.c sysboot.v skip.v msdos.v
- $(HOSTCC) $(HOSTCCFLAGS) -o dosboot dosboot.c
+makeboot.com: makeboot.c sysboot.v skip.v msdos.v tarboot.v
+ $(BCC) -Md -o makeboot.com makeboot.c
-clean:
- rm -f monitor makeboot dosboot minix.s *.o *.bin *.out *.lst *.sym *.v
+clean realclean:
+ rm -f monitor makeboot bootblocks.tar.gz
+ rm -f minix.s *.com *.o *.bin *.out *.lst *.sym *.v
-tgz: minix.bin monitor.out makeboot
+tgz: minix.bin monitor.out makeboot.com makeboot
tar cfV bootblocks.tar ENIAC monitor.out \
README Makefile \
- $(MSRC) dosboot.c makeboot.c \
+ $(MSRC) makeboot.c \
$(CSRC) $(SSRC) \
- makeboot minix.bin
- makeboot bootblocks.tar
+ makeboot.com minix.bin
+ makeboot tar bootblocks.tar
gzip -f9 bootblocks.tar
distribution:
tar czf /tmp/bootblocks.tar.gz README Makefile \
- $(MSRC) dosboot.c makeboot.c \
+ $(MSRC) makeboot.c \
$(CSRC) $(SSRC)
.SUFFIXES: .bin .v
.s.bin:
- $(AS) $(ASFLAGS) -b $*.bin -s $*.sym -l $*.lst $*.s
+ $(BCC) -c $*.s -A-b -A$*.bin -A-s -A$*.sym -A-l -A$*.lst
.s.v:
as86_encap $*.s $*.v $*_ $(ASFLAGS) $(LST)
diff --git a/bootblocks/README b/bootblocks/README
index c57f3aa..5d2344b 100644
--- a/bootblocks/README
+++ b/bootblocks/README
@@ -12,18 +12,43 @@ $ tar cvfV /dev/fd0 ENIAC monitor.out item2 item3
Make it bootable
-$ makeboot /dev/fd0
+$ makeboot tar /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 dosfs boot sector
+--------------------------------
+
+$ make makeboot
+$ makeboot dosfs /dev/fd0
+
+or
+$ make makeboot.com
+C:\> makeboot dos a:
+
+ Place a Linux-8086 executable in the root directory of the floppy.
+
+$ make monitor.out
+$ mount -t msdos /dev/fd0 /mnt
+$ cp monitor.out /mnt/bootfile.sys
+$ umount /dev/fd0
+
+or
+C:\> copy monitor.out a:\bootfile.sys
+
+ This works on my 3 1/5 floppy and my 5 1/4, and it _should_ work on
+ any double sided drive. (It does work on a 3.5/720k floppy too)
+ For single sided floppies you need to alter msdos.s (the heads var)
+ and remove the check in makeboot.c
+
To install the minixfs boot sector
----------------------------------
Make a minix filesystem on the floppy:
$ mkfs -t minix /dev/fd0 1440
-
+or
$ mkfs -t minix /dev/fd0 1200
Make the bootblock program.
@@ -41,22 +66,51 @@ $ mount -t minix /dev/fd0 /mnt
$ cp monitor.out /mnt/linux
$ umount /dev/fd0
- Or in a tar file:
+ 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.
-$ make monitor.out
-$ mount -t minix /dev/fd0 /mnt
-$ tar cvf /mnt/linux monitor.out long list of other files
+
+Booting a Linux-386 bzImage
+---------------------------
+
+NOTE: This only works with bzImage files NOT zImage files.
+
+Take 1 msdos floppy.
+
+$ makeboot dos /dev/fd0
+$ mount -t msdos /dev/fd0 /mnt
+$ cp monitor.out /mnt/bootfile.sys
+$ umount /dev/fd0
+$ cp /usr/src/linux/arch/i386/boot/bzImage /mnt/fd0/vmlinuz
+$ echo 'root=/dev/ram ramdisk_file=ramdisk.gz mem=80M' > /mnt/fd0/vmlinuz.cmd
+$ cp /archive/ramdisk.gz /mnt/fd0/ramdisk.gz
$ 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.
+The stuff about ramdisk is only if you want an init ramdisk. You can also use:
+
+vmlinuz.app: Arguments prepended to the Linux command line.
+vmlinuz.cmd: Arguments appended to the Linux command line.
+vmlinux.dfl: Arguments appended to the Linux command line.
+
+If there's a *.cmd file you won't be asked anything. If there's a *.dfl or
+neither you'll be asked:
+
+vmlinuz:
-To boot the floppy in DOSEMU
-----------------------------
+where you can type a command line to override the *.dfl file. If there's
+a *.cmd file the *.dfl file is ignored, the *.app file is placed at the
+start of the line whichever you do.
-$ dos -A
+If the file isn't called 'vmlinuz' you can still boot it by typing "=linux"
+at the prompt '>' where 'linux' is the name of the bzImage file.
- Press ^C to exit DOSEMU from inside monitor.c
+Escape or ^C will interrupt the boot and drop you to the '>' prompt.
+Esacpe or ^C at the '>' prompt will reboot
+ (This may be a little sensitive :-)
-Rob.
+A file called 'help.txt' will be displayed upto the first line that starts
+with a '%', chunks after that (seperated by '%'s) will be displayed when
+the user presses a function key, home, page up or page down. (Note it's
+best if you try to ensure 'help.txt' is completely contained on one track
+so the file is entirely in the track buffer)
diff --git a/bootblocks/bzimage.c b/bootblocks/bzimage.c
new file mode 100644
index 0000000..8d38753
--- /dev/null
+++ b/bootblocks/bzimage.c
@@ -0,0 +1,555 @@
+/*
+ * Load and execute a bzImage file from the device the 'open_file' and
+ * friends use.
+ */
+
+#include <stdio.h>
+#include "i86_funcs.h"
+#include "readfs.h"
+
+int auto_flag = 1;
+char * append_line = 0; /* A preset append line value */
+
+static char * initrd_name = 0; /* Name of init_ramdisk to load */
+static int vga_mode = -1; /* SVGA_MODE = normal */
+
+static char * read_cmdfile();
+static char * input_cmd();
+
+cmd_bzimage(ptr)
+char * ptr;
+{
+ char * image;
+ int ch;
+
+ if( (auto_flag=(ptr==0)) ) ptr="";
+
+ while(*ptr == ' ') ptr++;
+ image = ptr;
+ while(*ptr != ' ' && *ptr) ptr++;
+ ch = *ptr;
+ *ptr = '\0';
+ if( ch ) ptr++;
+ while(*ptr == '\n' || *ptr == ' ') ptr++;
+
+ if( *ptr == '\0' ) ptr = 0;
+ if( *image )
+ bzimage(image, ptr);
+ else
+ bzimage("vmlinuz", ptr);
+}
+
+bzimage(fname, command_line)
+char * fname;
+char * command_line;
+{
+ char buffer[1024];
+ long len;
+ char * ptr;
+ int low_sects;
+ unsigned int address;
+
+ if( open_file(fname) < 0 )
+ {
+ if( auto_flag == 0 )
+ printf("Cannot find file %s\n", fname);
+ return -1;
+ }
+
+ printf("Loading %s\n", fname);
+
+ if( read_block(buffer) < 0 || check_magics(buffer) < 0 )
+ {
+ printf("File %s isn't a bzImage.\n", fname);
+ return -1;
+ }
+
+ if( boot_mem_top < 0x9500 )
+ {
+ printf("There must be 640k of boot memory to load Linux\n");
+ return -1;
+ }
+
+ /* Guestimate how much the uncompressed kernel will use.
+ * I expect we could lookup the size in the gzip header but
+ * this is probably close enough (3*the size of the bzimage)
+ */
+ len = file_length() * 3 / 1024;
+ if( main_mem_top < len )
+ {
+ printf("This kernel needs at least %ld.%ldM of main memory\n",
+ len/1024, len*10/1024%10);
+ return -1;
+ }
+ if( main_mem_top < 3072 )
+ printf("RTFM warning: Linux really needs at least 4MB of memory.\n");
+
+ low_sects = buffer[497] + 1; /* setup sects + boot sector */
+ address = 0x900;
+
+ /* load the blocks */
+ rewind_file();
+ for(len = file_length(); len>0; len-=1024)
+ {
+ int v;
+
+ printf("%ldk to go \r", len/1024); fflush(stdout);
+
+ v = (bios_khit()&0x7F);
+ if( v == 3 || v == 27 )
+ {
+ printf("User interrupt!\n");
+ bios_getc();
+ return -1;
+ }
+
+ if( read_block(buffer) < 0 )
+ {
+ printf("Error loading %s\n", fname);
+ return -1;
+ }
+
+ for(v=0; v<1024; v+=512)
+ {
+ if( putsect(buffer+v, address) < 0 )
+ return -1;
+
+ address += 2;
+
+ if( low_sects )
+ {
+ low_sects--;
+ if( low_sects == 0 ) address = 0x1000;
+ }
+ }
+ }
+
+ /* Yesss, loaded! */
+ printf("Loaded, "); fflush(stdout);
+
+ /* Ok, deal with the command line */
+ if( build_linuxarg(auto_flag, fname, append_line, command_line) < 0 )
+ return -1;
+
+ if( initrd_name )
+ if( load_initrd(address) < 0 )
+ return -1;
+
+ printf("Starting ...\n");
+
+ if( x86 < 3 )
+ {
+ printf("RTFM error: Linux-i386 needs a CPU >= 80386\n");
+ if( !keep_going() ) return -1;
+ }
+
+ if( a20_closed() ) open_a20();
+ if( a20_closed() )
+ {
+ printf("Normal routine for opening A20 Gate failed, Trying PS/2 Bios\n");
+ bios_open_a20();
+ }
+ if( a20_closed() )
+ {
+ printf("All routines for opening A20 Gate failed, if I can't open it\n");
+ printf("then Linux probably can't either!\n");
+ if( !keep_going() ) return -1;
+ }
+
+ /* Patch setup to deactivate safety switch */
+ __set_es(0x9000);
+ __poke_es(0x210, 0xFF);
+
+ /* Set SVGA_MODE if not 'normal' */
+ if( vga_mode != -1 ) __doke_es(506, vga_mode);
+
+ /* Default boot drive is auto-detected floppy */
+ if( __peek_es(508) == 0 ) __poke_es(508, 0x200);
+
+ /* Finally do the deed */
+ {
+#asm
+ ! Kill the floppy motor, needed in case the kernel has no floppy driver.
+ mov dx,#0x3f2
+ xor al, al
+ outb
+
+ ! Setup required registers and go ...
+ mov ax,$9000
+ mov bx,$4000-12 ! Fix this to use boot_mem_top
+ mov es,ax
+ mov ds,ax
+ mov ss,ax
+ mov sp,bx
+ jmpi 0,$9020 ! Note SETUPSEG NOT INITSEG
+#endasm
+ }
+}
+
+check_magics(buffer)
+char * buffer;
+{
+ /* Boot sector magic number */
+ if( *(unsigned short*)(buffer+510) != 0xAA55 ) return -1;
+
+ /* Setup start */
+ if( memcmp(buffer+0x202, "HdrS", 4) != 0 ) return -1;
+
+ /* Setup version */
+ if( *(unsigned short*)(buffer+0x206) < 0x200 ) return -1;
+
+ /* Check load flags for bzImage */
+ if( (buffer[0x211] & 1) == 0 ) return -1;
+
+ /* Code 32 start address */
+ if( *(unsigned long*)(buffer+0x214) != 0x100000 ) return -1;
+
+ return 0;
+}
+
+putsect(buffer, address)
+char * buffer;
+unsigned int address;
+{
+ int rv, tc=3;
+retry:
+ tc--;
+#if 1
+ if( x86_emu )
+ {
+static unsigned int last_address = 0;
+ if( address <= last_address )
+ printf("Problem %d<=%d\n", address, last_address);
+ if( address < 0xA00 )
+ {
+ int i;
+ __set_es(address*16);
+ for(i=0; i<512; i++)
+ __poke_es(i, buffer[i]);
+ }
+ return 0;
+ }
+#endif
+ if( (rv=ext_put(buffer, address, 512)) != 0 )
+ {
+ switch(rv)
+ {
+ case 1:
+ printf("Parity error while copying to extended memory\n");
+ break;
+ case 2:
+ printf("Interrupt error while copying to extended memory\n");
+ if ( tc>0 ) goto retry;
+ break;
+ case 3:
+ printf("BIOS cannot open A20 Gate\n");
+ break;
+ case 0x80: case 0x86:
+ printf("BIOS has no extended memory support\n");
+ break;
+ default:
+ printf("Error %d while copying to extended memory\n", rv);
+ break;
+ }
+ if( x86 < 3 )
+ printf("RTFM error: Linux-i386 needs a CPU >= 80386\n");
+ else if( x86_emu )
+ printf("RTFM error: Linux-i386 cannot be run in an emulator.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static char *
+read_cmdfile(iname, extno)
+char * iname;
+int extno;
+{
+ char buffer[1024];
+ char buf[16];
+ long len;
+ char * ptr = strchr(iname, '.');
+
+ buf[8] = '\0';
+ strncpy(buf, iname, 8);
+ switch(extno)
+ {
+ case 1: strcat(buf, ".cmd"); break;
+ case 2: strcat(buf, ".app"); break;
+ case 3: strcat(buf, ".dfl"); break;
+ default: return 0;
+ }
+
+ if( ptr == 0 && open_file(buf) >= 0 )
+ {
+ /* Ah, a command line ... */
+ if( extno == 1 ) printf("Loading %s\n", buf);
+ len = file_length();
+ if( len > 1023 )
+ {
+ printf("Command line file %s truncated to 1023 characters\n", buf);
+ len = 1023;
+ }
+ if( read_block(buffer) >= 0 )
+ {
+ int i;
+ for(i=0; i<len; i++)
+ if( buffer[i] < ' ' ) buffer[i] = ' ';
+ buffer[len] = '\0';
+
+ return strdup(buffer);
+ }
+ }
+ return 0;
+}
+
+char *
+input_cmd(iname)
+char * iname;
+{
+ char buffer[1024];
+ char lbuf[20];
+ int cc;
+
+ for(;;)
+ {
+ printf("%s: ", iname); fflush(stdout);
+
+ cc = read(0, buffer, sizeof(buffer)-1);
+ if( cc <= 0 ) return 0;
+ buffer[cc] = 0;
+ if( cc == 1 && *buffer != '\n' )
+ {
+ putchar('\n');
+ cc = (buffer[0] & 0xFF);
+
+ if( cc == 0xAD ) /* ALT-X */
+ return 0;
+
+ sprintf(lbuf, "$%02x", cc);
+ cmd_help(lbuf);
+ continue;
+ }
+ if( buffer[cc-1] == '\n' ) buffer[cc-1] = '\0';
+
+ break;
+ }
+
+ return strdup(buffer);
+}
+
+build_linuxarg(auto_flg, image, append, cmd)
+int auto_flg;
+char *image, *append, *cmd;
+{
+static char * auto_str = "auto";
+static char * image_str = "BOOT_IMAGE=";
+ int len = 0;
+ char * ptr, *s, *d;
+
+ char * free_cmd = 0;
+ char * free_app = 0;
+ char * free_dfl = 0;
+
+ if( append == 0 )
+ append = free_app = read_cmdfile(image, 2);
+
+ if( cmd == 0 )
+ cmd = free_cmd = read_cmdfile(image, 1);
+
+ if( cmd == 0 )
+ free_dfl = read_cmdfile(image, 3);
+
+ close_file(); /* Free up loads a room */
+
+ if( cmd == 0 )
+ {
+ cmd = free_cmd = input_cmd(image);
+ auto_flg = 0;
+ }
+
+ if( cmd == 0 )
+ {
+ printf("Aborted execution\n");
+ return -1;
+ }
+ else if( *cmd == 0 )
+ cmd = free_dfl;
+
+ if( auto_flg ) len += strlen(auto_str) + 1;
+ if( image ) len += strlen(image_str) + strlen(image) + 1;
+ if( append ) len += strlen(append) + 1;
+ if( cmd ) len += strlen(cmd) + 1;
+
+ if( len == 0 ) return 0;
+
+ ptr = malloc(len+1);
+ if( ptr == 0 )
+ {
+ printf("Unable to create linux command line\n");
+ if( free_cmd ) free(free_cmd);
+ if( free_app ) free(free_app);
+ if( free_dfl ) free(free_dfl);
+ return -1;
+ }
+
+ *ptr = 0; ptr[1] = 0;
+ if( auto_flg ) { strcat(ptr, " "); strcat(ptr, auto_str); }
+ if( image ) { strcat(ptr, " "); strcat(ptr, image_str); strcat(ptr, image); }
+ if( append ) { strcat(ptr, " "); strcat(ptr, append); }
+ if( cmd ) { strcat(ptr, " "); strcat(ptr, cmd); }
+
+ if( free_cmd ) free(free_cmd);
+ if( free_app ) free(free_app);
+ if( free_dfl ) free(free_dfl);
+
+ if( (d = malloc(len+1)) == 0 )
+ {
+ printf("Unable to compact linux command line\n");
+ free(ptr);
+ return -1;
+ }
+ *d = '\0';
+ for(s=strtok(ptr, " "); s; s=strtok((char*)0, " "))
+ {
+ if( strncmp(s, "vga=",4) == 0 )
+ {
+ if( strncmp(s+4, "ask", 3) == 0 )
+ vga_mode = -3;
+ else
+ {
+ s+=4; getnum(&s, &vga_mode);
+ }
+ }
+ else if( strncmp(s, "ramdisk_file=", 13) == 0 )
+ {
+ if( initrd_name ) free(initrd_name);
+ if( s[13] )
+ initrd_name = strdup(s+13);
+ else
+ initrd_name = 0;
+ }
+ else
+ {
+ strcat(d, " ");
+ strcat(d, s);
+ }
+ }
+ free(ptr); ptr = d;
+ len = strlen(ptr);
+
+ if( len > 2048 )
+ {
+ printf("Linux command line truncated to 2047 characters\n");
+ ptr[2048] = 0;
+ len = 2048;
+ }
+
+ __set_es(0x9000);
+ __doke_es(0x0020, 0xA33F);
+ __doke_es(0x0022, 0x4000);
+
+ __movedata(__get_ds(), (unsigned)ptr+1, 0x9000, 0x4000, len);
+
+ free(ptr);
+
+ return 0;
+}
+
+keep_going()
+{
+static int burning = 0;
+ char buf[1];
+ int cc;
+
+ printf("Keep going ? "); fflush(stdout);
+
+ cc = read(0, buf, 1);
+ if( cc == 1 && (*buf == 'Y' || *buf == 'y') )
+ {
+ printf("Yes, Ok%s\n", burning?"":", burn baby burn!");
+ return burning=1;
+ }
+ printf("No, Ok returning to monitor prompt\n");
+ return 0;
+}
+
+load_initrd(k_top)
+unsigned int k_top;
+{
+ unsigned int address, rd_start, rd_len;
+ long file_len;
+ char * fname = initrd_name;
+
+ char buffer[1024];
+
+ /* Top of accessable memory */
+ if( main_mem_top >= 15360 ) address = 0xFFFF;
+ else address = 0x1000 + main_mem_top*4;
+
+ if( *initrd_name == '+' )
+ {
+ char buf[2];
+ fname++;
+ close_file();
+ printf("Insert root floppy and press return:"); fflush(stdout);
+ read(0, buf, 2);
+ }
+
+ if( open_file(fname) < 0 )
+ {
+ printf("Cannot open %s\n", fname);
+ return -1;
+ }
+ file_len = file_length();
+ rd_len = (file_len+1023)/1024;
+
+ if( file_len > 15000000L || k_top + rd_len*4 > address )
+ {
+ printf("Ramdisk file %s is too large to load\n", fname);
+ return -1;
+ }
+
+ rd_start = address - rd_len*4;
+ rd_start &= -16; /* Page boundry */
+ address = rd_start;
+
+ printf("Loading %s at 0x%x00\n", fname, rd_start);
+
+ for( ; rd_len>0 ; rd_len--)
+ {
+ int v = (bios_khit()&0x7F);
+ if( v == 3 || v == 27 )
+ {
+ printf("User interrupt!\n");
+ bios_getc();
+ return -1;
+ }
+
+ printf("%dk to go \r", rd_len); fflush(stdout);
+ if( read_block(buffer) < 0 )
+ {
+ printf("Read error loading ramdisk\n");
+ return -1;
+ }
+ if( putsect(buffer, address) < 0 ) return -1;
+ address+=2;
+ if( putsect(buffer+512, address) < 0 ) return -1;
+ address+=2;
+ }
+ printf("Loaded, ");
+
+ /* Tell the kernel where it is */
+ {
+ long tmp = ((long)rd_start << 8);
+
+ __set_es(0x9000);
+ __doke_es(0x218, (unsigned) tmp);
+ __doke_es(0x21A, (unsigned)(tmp>>16));
+
+ __doke_es(0x21C, (unsigned) file_len);
+ __doke_es(0x21E, (unsigned)(file_len>>16));
+ }
+
+ return 0;
+}
diff --git a/bootblocks/dosboot.c b/bootblocks/dosboot.c
deleted file mode 100644
index 72b8d25..0000000
--- a/bootblocks/dosboot.c
+++ /dev/null
@@ -1,72 +0,0 @@
-
-#include <stdio.h>
-
-#include "sysboot.v"
-#include "msdos.v"
-#include "skip.v"
-
-char buffer[512];
-
-struct bblist {
- char * name;
- char * data;
- char * desc;
-} bblocks[] = {
- { "bare", sysboot_data, "Bare bootblock, lockup if booted" },
- { "dosfs", msdos_data, "Boots file BOOTFILE.SYS from dosfs" },
- { "skip", skip_data, "Bypasses floppy boot with message" },
- 0
-};
-
-char * progname = "";
-
-main(argc, argv)
-int argc;
-char ** argv;
-{
- FILE * fd;
- struct bblist *ptr = bblocks;
- int i;
-
- progname = argv[0];
-
- if( argc != 3 ) Usage();
-
- for(;ptr->name; ptr++) if( strcmp(argv[1], ptr->name) == 0 ) break;
- if( ptr->name == 0 ) Usage();
-
- fd = fopen(argv[2], "r+");
- if( fd == 0 )
- {
- fprintf(stderr, "Cannot open %s\n", argv[2]);
- exit(1);
- }
- if( fread(buffer, 512, 1, fd) != 1 )
- {
- fprintf(stderr, "Cannot read boot block\n");
- exit(1);
- }
- for(i=0; i<sysboot_dosfs_stat; i++)
- buffer[i] = ptr->data[i];
- for(i=sysboot_codestart; i<512; i++)
- buffer[i] = ptr->data[i];
-
- rewind(fd);
- if( fwrite(buffer, 512, 1, fd) != 1 )
- {
- fprintf(stderr, "Cannot write boot block\n");
- exit(1);
- }
- fclose(fd);
-}
-
-Usage()
-{
- struct bblist *ptr = bblocks;
-
- fprintf(stderr, "Usage: %s bootname /dev/fd0\n", progname);
- fprintf(stderr, "Blocks\n");
- for(;ptr->name; ptr++)
- fprintf(stderr, "\t%s\t%s\n", ptr->name, ptr->desc);
- exit(1);
-}
diff --git a/bootblocks/dosfs.c b/bootblocks/dosfs.c
new file mode 100644
index 0000000..a545b28
--- /dev/null
+++ b/bootblocks/dosfs.c
@@ -0,0 +1,419 @@
+
+#ifdef __STANDALONE__
+
+#include <ctype.h>
+#include <malloc.h>
+#include "readfs.h"
+
+#define DOS_SECT(P) get_uint(P,0x0B)
+#define DOS_CLUST(P) get_byte(P,0x0D)
+#define DOS_RESV(P) get_uint(P,0x0E)
+#define DOS_NFAT(P) get_byte(P,0x10)
+#define DOS_NROOT(P) get_uint(P,0x11)
+#define DOS_MAXSECT(P) get_uint(P,0x13)
+#define DOS_MEDIA(P) get_byte(P,0x15)
+#define DOS_FATLEN(P) get_uint(P,0x16)
+#define DOS_SPT(P) get_uint(P,0x18)
+#define DOS_HEADS(P) get_uint(P,0x1A)
+#define DOS_HIDDEN(P) get_long(P,0x1C)
+#define DOS4_MAXSECT(P) get_long(P,0x20)
+#define DOS4_PHY_DRIVE(P) get_byte(P,0x24)
+#define DOS4_SERIAL(P) get_long(P,0x27)
+
+/* These assume alignment is not a problem */
+#define get_byte(P,Off) *((unsigned char*)((char*)(P)+(Off)))
+#define get_uint(P,Off) *((unsigned short*)((char*)(P)+(Off)))
+#define get_long(P,Off) *((long*)((char*)(P)+(Off)))
+
+static int alloc_trackbuf();
+static char * read_sector();
+static int read_bootblock();
+
+int disk_drive = 0;
+
+static int track_number = -1;
+static char * track_buffer = 0;
+static int track_len = 0;
+static int disk_spt = -1;
+static int disk_heads = 2;
+
+static int dir_nentry, dir_sect;
+static int dos_clust0, dos_spc;
+
+static char * fat_buf = 0;
+
+struct filestatus {
+ char fname[12];
+ unsigned short first_cluster;
+ unsigned short cur_cluster;
+ unsigned short sector_no;
+ long file_length;
+}
+ cur_file = { "", 0, 0, 0 };
+
+open_file(fname)
+char * fname;
+{
+ char conv_name[12];
+ char *s, *d;
+ int i;
+ int dodir = 0;
+
+ if(strcmp(fname, ".") == 0) dodir = 1;
+ else
+ {
+ /* Convert the name to MSDOS directory format */
+ strcpy(conv_name, " ");
+ for(s=fname, d=conv_name; *s && *d && *s != '.' && *s != ' '; s++)
+ {
+ if( islower(*s) ) *d++ = toupper(*s);
+ else *d++ = *s;
+ }
+ while( *s && *s != '.' ) s++;
+ strcpy(d=(conv_name+8), " ");
+ if( *s == '.' )
+ {
+ for(s++; *s && *d; s++)
+ {
+ if( islower(*s) ) *d++ = toupper(*s);
+ else *d++ = *s;
+ }
+ }
+
+ /* Already opened ? Then just rewind it */
+ if( cur_file.first_cluster && strcmp(cur_file.fname, conv_name) == 0 )
+ return rewind_file();
+ }
+
+ memset(&cur_file, '\0', sizeof(cur_file));
+
+ /* Get the superblock */
+ s = read_sector(0);
+ if( s == 0 ) return -1;
+
+ /* Collect important data */
+ dir_sect = DOS_RESV(s) + DOS_NFAT(s)*DOS_FATLEN(s);
+ dir_nentry = DOS_NROOT(s);
+
+ dos_spc = DOS_CLUST(s);
+ if( dos_spc < 1 ) dos_spc = 1;
+ dos_clust0 = dir_sect + (dir_nentry+15)/16 - 2*dos_spc;
+
+ if( !dodir )
+ {
+ /* Read in and buffer the FAT */
+ if( fat_buf ) free(fat_buf);
+ fat_buf = malloc(DOS_FATLEN(s) * 512);
+ if( fat_buf == 0 ) return -1;
+ else
+ {
+ int fatsec = DOS_RESV(s);
+ int nsec = DOS_FATLEN(s);
+
+ for(i=0; i<nsec; i++)
+ {
+ s = read_sector(fatsec+i);
+ if(s == 0) return -1;
+ memcpy(fat_buf+i*512, s, 512);
+ }
+ }
+ }
+
+ /* Scan the root directory for the file */
+ for(i=0; i<dir_nentry; i++)
+ {
+ s = read_sector(dir_sect+i/16);
+ if( s == 0 ) return -1;
+ d = s + (i%16)*32;
+ if( dodir )
+ {
+ char dtime[20];
+ sprintf(dtime, " %02d/%02d/%04d %02d:%02d",
+ (get_uint(d,24)&0x1F),
+ ((get_uint(d,24)>>5)&0xF),
+ ((get_uint(d,24)>>9)&0x7F)+1980,
+ ((get_uint(d,22)>>11)&0x1F),
+ ((get_uint(d,22)>>5)&0x3F)
+ );
+ if( *d > ' ' && *d <= '~' ) switch(d[11]&0x18)
+ {
+ case 0:
+ printf("%-8.8s %-3.3s %10ld%s\n", d, d+8, get_long(d,28), dtime);
+ break;
+ case 0x10:
+ printf("%-8.8s %-3.3s <DIR> %s\n", d, d+8, dtime);
+ break;
+ case 8:
+ if( (d[11] & 7) == 0 )
+ printf("%-11.11s <LBL> %s\n", d, dtime);
+ break;
+ }
+ }
+ else if( memcmp(d, conv_name, 11) == 0 && (d[11]&0x18) == 0 )
+ { /* Name matches and is normal file */
+
+ strcpy(cur_file.fname, conv_name);
+ cur_file.first_cluster = get_uint(d,26);
+ cur_file.file_length = get_long(d,28);
+
+ cur_file.cur_cluster = cur_file.first_cluster;
+ cur_file.sector_no = 0;
+
+ return 0;
+ }
+ }
+ return -1;
+}
+
+rewind_file()
+{
+ /* Is there an opened file ? */
+ if( cur_file.fname[0] == 0 ) return -1;
+
+ cur_file.sector_no = 0;
+ cur_file.cur_cluster = cur_file.first_cluster;
+ return 0;
+}
+
+close_file()
+{
+ if( fat_buf ) free(fat_buf);
+ if( track_buffer ) free(track_buffer);
+ memset(&cur_file, '\0', sizeof(cur_file));
+ fat_buf = 0;
+ track_buffer = 0;
+ track_len = 0;
+ track_number = -1;
+ disk_spt = -1;
+ disk_heads = 2;
+ return 0;
+}
+
+long
+file_length()
+{
+ /* Is there an opened file ? */
+ if( cur_file.fname[0] == 0 ) return -1;
+
+ return cur_file.file_length;
+}
+
+read_block(buffer)
+char * buffer;
+{
+ int s;
+ char * ptr;
+
+ /* Is there an opened file ? */
+ if( cur_file.fname[0] == 0 ) return -1;
+
+ /* Are we before the EOF ? NB: FAT12 ONLY! */
+ if( cur_file.cur_cluster >= 0xFF0 || cur_file.cur_cluster < 2 ) return -1;
+
+ for(s=0; s<2; s++)
+ {
+ unsigned int sectno;
+
+ if( cur_file.cur_cluster >= 0xFF0 || cur_file.cur_cluster < 2 )
+ {
+ memset(buffer, '\0', 512);
+ buffer += 512;
+ continue;
+ }
+
+ sectno = dos_clust0
+ + cur_file.cur_cluster * dos_spc
+ + cur_file.sector_no % dos_spc;
+
+ ptr = read_sector(sectno);
+ if( ptr == 0 ) return -1;
+ memcpy(buffer, ptr, 512);
+
+ cur_file.sector_no++;
+ if( cur_file.sector_no % dos_spc == 0 )
+ {
+ int odd = (cur_file.cur_cluster&1);
+ unsigned int val;
+
+ val = cur_file.cur_cluster + (cur_file.cur_cluster>>1);
+ val = get_uint(fat_buf, val);
+
+ if( odd ) val>>=4;
+
+ val &= 0xFFF;
+
+ cur_file.cur_cluster = val;
+ }
+
+ buffer += 512;
+ }
+
+ return 0;
+}
+
+static char * read_sector(sectno)
+int sectno;
+{
+ int track_no, track_off, track_start, linsect;
+ if( disk_spt == -1 && read_bootblock() < 0 ) return 0;
+
+ track_no = sectno / track_len;
+ track_off= sectno % track_len;
+
+ if( track_no != track_number )
+ {
+ track_number = -1;
+ track_start = track_no * track_len;
+
+ for(linsect=0; linsect<track_len; linsect++)
+ {
+ if( raw_read(disk_drive, track_start+linsect,
+ track_buffer+linsect*512) <0 )
+ return 0;
+ }
+ if( raw_read(disk_drive, 0, 0) <0 )
+ return 0;
+
+ track_number = track_no;
+ }
+ return track_buffer + 512*track_off;
+}
+
+static int raw_read(drive, linsect, buffer)
+int drive, linsect;
+char * buffer;
+{
+static char * pend_buf = 0, *buf_start = 0;
+static int pend_s, pend_h, pend_c, pend_len = 0;
+
+ int phy_s = linsect%disk_spt;
+ int phy_h = linsect/disk_spt%disk_heads;
+ int phy_c = linsect/disk_spt/disk_heads;
+ int tries = 5;
+ int rv = 0;
+
+ if( buffer != pend_buf ||
+ pend_s+pend_len != phy_s ||
+ pend_h != phy_h ||
+ pend_c != phy_c )
+ {
+/*
+printf("phy_read(%d,%d,%d,%d,%d,%d);\n",
+ drive, pend_c, pend_h, pend_s+1, pend_len, buf_start);
+*/
+ if( buf_start ) do
+ {
+ rv = phy_read(drive, pend_c, pend_h, pend_s+1, pend_len, buf_start);
+ tries--;
+ }
+ while(rv && tries > 0);
+
+ pend_c = phy_c;
+ pend_h = phy_h;
+ pend_s = phy_s;
+ pend_len = 0;
+ pend_buf = buf_start = buffer;
+ }
+
+ pend_len++;
+ pend_buf += 512;
+
+ return rv;
+}
+
+static int read_bootblock()
+{
+ char * sptr;
+ int rv, media_byte = 0;
+ if( alloc_trackbuf(2) ) return -1;
+
+ disk_spt = 2;
+ sptr = read_sector(1);
+ disk_spt = -1;
+ if( sptr == 0 ) return -1;
+ media_byte = *(unsigned char*)sptr;
+
+ /* Valid media byte ? */
+ if( (media_byte & 0xF0) != 0xF0 ) return -1;
+ disk_spt = 2;
+ sptr = read_sector(0);
+ disk_spt = -1;
+ if( sptr == 0 ) return -1;
+
+ if( DOS_MEDIA(sptr) != media_byte ) return -1;
+ if( DOS_SPT(sptr) > 63 ) return -1;
+ if( DOS_SECT(sptr) != 512 ) return -1;
+
+ disk_spt = DOS_SPT(sptr);
+ disk_heads = DOS_HEADS(sptr);
+
+ rv = alloc_trackbuf(disk_spt*disk_heads); /* Cylinder buffer */
+ if( rv < 0 ) rv = alloc_trackbuf(disk_spt); /* Track buffer */
+ if( rv < 0 ) rv = alloc_trackbuf(disk_spt/2); /* 1/2 Track buffer */
+ if( rv < 0 ) rv = alloc_trackbuf(2); /* Block buffer */
+ if( rv < 0 ) disk_spt = -1;
+ return rv;
+}
+
+static int alloc_trackbuf(sectors)
+int sectors;
+{
+ char * new_track;
+ int seg_start, seg_end;
+ if( sectors <= track_len ) return 0;
+
+ if( track_buffer ) free(track_buffer);
+ track_buffer = 0;
+ track_len = 0;
+ track_number = -1;
+
+ if( sectors < 1 || sectors > 63 ) /* WTF! */ return -1;
+
+ new_track = malloc(sectors*512);
+ if( new_track == 0 ) return -1;
+
+ seg_start = __get_ds() + (unsigned int)new_track / 16;
+ seg_end = __get_ds() + (unsigned int)(new_track+sectors*512-1) / 16;
+
+ if( (seg_start&0xF000) != (seg_end&0xF000) ) /* Bugger */
+ {
+ int rv = alloc_trackbuf(sectors);
+ free(new_track);
+ return rv;
+ }
+
+ track_len = sectors;
+ track_buffer = new_track;
+ return 0;
+}
+
+#endif
+
+#if defined(__MSDOS__) || defined(__STANDALONE__)
+phy_read(drive, cyl, head, sect, length, buffer)
+{
+#asm
+ push bp
+ mov bp,sp
+
+ push ds
+ pop es
+
+ mov dl,[bp+2+_phy_read.drive]
+ mov ch,[bp+2+_phy_read.cyl]
+ mov dh,[bp+2+_phy_read.head]
+ mov cl,[bp+2+_phy_read.sect]
+ mov al,[bp+2+_phy_read.length]
+ mov bx,[bp+2+_phy_read.buffer]
+
+ mov ah,#$02
+ int $13
+ jc read_err
+ mov ax,#0
+read_err:
+
+ pop bp
+#endasm
+}
+#endif
+
diff --git a/bootblocks/help.c b/bootblocks/help.c
new file mode 100644
index 0000000..5083fdc
--- /dev/null
+++ b/bootblocks/help.c
@@ -0,0 +1,93 @@
+
+/*
+ * Display a page from help.txt, the argument is the scan code of a function
+ * key. F1..F10 display pages 1..10, HOME is page zero, PGUP and PGDN are
+ * previous and next page.
+ */
+
+#include <stdio.h>
+#include "readfs.h"
+
+struct keys {
+ int key;
+ int rel;
+ int abs;
+} keys[] = {
+ {0xC7, 0, 0}, /* HOME page 0*/
+ {0xBB, 0, 1}, /* F1 page 1 */
+ {0xBC, 0, 2}, /* F2 page 2 */
+ {0xBD, 0, 3}, /* F3 page 3 */
+ {0xBE, 0, 4}, /* F4 page 4 */
+ {0xBF, 0, 5}, /* F5 page 5 */
+ {0xC0, 0, 6}, /* F6 page 6 */
+ {0xC1, 0, 7}, /* F7 page 7 */
+ {0xC2, 0, 8}, /* F8 page 8 */
+ {0xC3, 0, 9}, /* F9 page 9 */
+ {0xC4, 0, 10}, /* F10 page 10 */
+
+ {0xC9, -1,0}, /* PGUP page-- */
+ {0xD1, 1,0}, /* PGDN page++ */
+
+ {0,0,1}
+};
+
+cmd_help(ptr)
+char * ptr;
+{
+static int lastpage = 0;
+ int helpkey = 1;
+ int i;
+
+ getnum(&ptr, &helpkey);
+
+ for(i=0; keys[i].key; i++)
+ if( keys[i].key == helpkey || i == helpkey )
+ break;
+
+ if( keys[i].key == 0 )
+ {
+ printf("Unbound key, press F1 for general help\n");
+ return -1;
+ }
+
+ if( keys[i].rel ) lastpage += keys[i].rel;
+ else lastpage = keys[i].abs;
+
+ if( lastpage < 0 ) { lastpage=0; return 0; }
+
+ return display_help(lastpage);
+}
+
+display_help(page)
+int page;
+{
+ char buffer[1024];
+ long length= -1;
+ int left = 0;
+ int ch,lastch = '\n';
+ int flg = 0;
+
+ if( open_file("help.txt") < 0 )
+ {
+ if( page == 1 )
+ printf("Help file 'help.txt' is not available, sorry.\n");
+ return -1;
+ }
+
+ for(length = file_length(); length>0; length--)
+ {
+ if( left==0 )
+ {
+ if( read_block(buffer) < 0 ) break;
+ left = 1024;
+ }
+ ch = buffer[1024-left]; left--;
+ if( ch == '%' && lastch == '\n' ) { flg = 1; page--; }
+ if( page < 0 ) break;
+ if( page == 0 && flg == 0 ) putchar(ch);
+ if( ch == '\n' ) flg = 0;
+ lastch = ch;
+ }
+ return 0;
+}
+
diff --git a/bootblocks/i86_funcs.c b/bootblocks/i86_funcs.c
index a17e7a4..c17a158 100644
--- a/bootblocks/i86_funcs.c
+++ b/bootblocks/i86_funcs.c
@@ -10,7 +10,7 @@ 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 */
+unsigned boot_mem_top = 0x2000; /* Default 128k, the minimum */
long main_mem_top = 0; /* K of extended memory */
int a20_closed()
@@ -52,6 +52,22 @@ empty_8042:
#endasm
}
+/* This calls the BIOS to open the A20 gate, officially this is only supported
+ on PS/2s but if the normal routine fails we may as well try this.
+ */
+void bios_open_a20()
+{
+#asm
+ mov ax,#$2401
+ int $15
+ jc bios_failed_a20
+ xor ax,ax
+bios_failed_a20:
+ mov al,ah
+ xor ah,ah
+#endasm
+}
+
void cpu_check()
{
static char *name_808x[] =
@@ -130,10 +146,10 @@ static struct {
char gdt1[8];
unsigned short src_len;
long src_seg;
- unsigned int spad;
+ unsigned short spad;
unsigned short dst_len;
long dst_seg;
- unsigned int dpad;
+ unsigned short dpad;
char gdt5[8];
} GDT = {
"","",
@@ -174,7 +190,7 @@ static asm_copy(length)
push es
push si
mov cx,ax
- mov ah,$87
+ mov ah,#$87
push ds
pop es
mov si,#_GDT
@@ -184,7 +200,7 @@ static asm_copy(length)
err:
mov al,ah
xor ah,ah
- push si
- push es
+ pop si
+ pop es
#endasm
}
diff --git a/bootblocks/makeboot.c b/bootblocks/makeboot.c
index 5a6348d..28d7ded 100644
--- a/bootblocks/makeboot.c
+++ b/bootblocks/makeboot.c
@@ -1,103 +1,328 @@
#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
-#include "tarboot.v"
#include "sysboot.v"
+#include "msdos.v"
+#include "skip.v"
+#include "tarboot.v"
-char tarblock[512];
+char buffer[1024];
+
+#define FS_NONE 0
+#define FS_ADOS 1
+#define FS_DOS 2
+#define FS_TAR 3
+#define FS_STAT 4
+
+struct bblist {
+ char * name;
+ char * data;
+ int fstype;
+ char * desc;
+} bblocks[] = {
+ { "tar", tarboot_data, FS_TAR, "Bootable GNU tar volume lable" },
+ { "dosfs", msdos_data, FS_ADOS, "Boots file BOOTFILE.SYS from dosfs" },
+ { "bare", sysboot_data, FS_DOS, "Bare bootblock, lockup if booted" },
+ { "skip", skip_data, FS_DOS, "Bypasses floppy boot with message" },
+ { "stat", 0, FS_STAT, "Display dosfs superblock" },
+ { "copy", 0, FS_STAT, "Copy boot block to makeboot.sav" },
+ { "Zap", 0, FS_NONE, "Clear boot block to NULs" },
+ 0
+};
+
+char * progname = "";
+
+int disktype = 0;
+FILE * diskfd;
+
+int disk_sect = 63; /* These are initilised to the maximums */
+int disk_head = 256; /* Set to the correct values when an MSDOS disk is */
+int disk_trck = 256; /* successfully identified */
-char *bootblock = tarboot_data;
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ FILE * fd;
+ struct bblist *ptr;
+ int i;
-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];
-} ;
+ progname = argv[0];
-#define head (*(struct tar_head*) tarblock)
-#define boothead (*(struct tar_head*) bootblock)
+ if( argc != 3 ) Usage();
-int force = 0;
-int relocatable = 0;
-int tableload = 0;
-long loadaddress = 0x8000;
-long execaddress = 0x8000;
+ if( (i=strlen(argv[1])) < 2 ) Usage();
+ for(ptr = bblocks; ptr->name; ptr++)
+ if( strncmp(argv[1], ptr->name, i) == 0 ) break;
+ if( ptr->name == 0 ) Usage();
-main(argc, argv)
-int argc;
-char ** argv;
+ open_disk(argv[2]);
+ if( read_sector(0, buffer) != 0 )
+ exit(1);
+ read_sector(1, buffer+512);
+
+ switch(ptr->fstype)
+ {
+ case FS_NONE: /* override */
+ break;
+ case FS_ADOS:
+ check_simpledos();
+ break;
+ case FS_DOS:
+ case FS_STAT:
+ check_msdos();
+ break;
+ case FS_TAR:
+ check_tar();
+ break;
+
+ default:
+ fprintf(stderr, "Program error, unknown filesystem requirement\n");
+ exit(2);
+ }
+
+ switch(ptr->fstype)
+ {
+ case FS_STAT:
+ print_super(buffer);
+ if( strcmp(ptr->name, "copy") == 0 )
+ save_super(buffer);
+ close_disk();
+ exit(0);
+ case FS_ADOS:
+ case FS_DOS:
+ for(i=0; i<sysboot_dosfs_stat; i++)
+ buffer[i] = ptr->data[i];
+ for(i=sysboot_codestart; i<512; i++)
+ buffer[i] = ptr->data[i];
+ break;
+
+ case FS_TAR:
+ copy_tarblock();
+ break;
+
+ case FS_NONE:
+ if( ptr->data )
+ memcpy(buffer, ptr->data, 512);
+ else
+ memset(buffer, '\0', 512);
+ break;
+ }
+
+ write_sector(0, buffer);
+ close_disk();
+ exit(0);
+}
+
+Usage()
{
- int ar;
- int done=0;
+ struct bblist *ptr = bblocks;
+
+ if( progname == 0 || *progname == 0 || progname[1] == 0 )
+ progname = "makeboot";
+
+#ifdef __MSDOS__
+ fprintf(stderr, "Usage: %s bootname a:\n", progname);
+#else
+ fprintf(stderr, "Usage: %s bootname /dev/fd0\n", progname);
+#endif
+ fprintf(stderr, "Blocks\n");
+ for(;ptr->name; ptr++)
+ fprintf(stderr, "\t%s\t%s\n", ptr->name, ptr->desc);
+ exit(1);
+}
- 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])
+int
+open_disk(diskname)
+char * diskname;
+{
+#ifdef __MSDOS__
+ if( strcmp("a:", diskname) == 0 ) { disktype = 1; return 0; }
+ if( strcmp("b:", diskname) == 0 ) { disktype = 2; return 0; }
+ if( strcmp("A:", diskname) == 0 ) { disktype = 1; return 0; }
+ if( strcmp("B:", diskname) == 0 ) { disktype = 2; return 0; }
+#endif
+ disktype = 0;
+ diskfd = fopen(diskname, "r+");
+ if( diskfd == 0 )
{
- 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;
+ fprintf(stderr, "Cannot open %s\n", diskname);
+ exit(1);
+ }
+ return 0;
+}
- case '?': Usage(1); break;
- default: Usage(0); break;
+close_disk()
+{
+ if( diskfd && disktype == 0 ) fclose(diskfd);
+ diskfd = 0;
+ disktype = 0;
+}
+
+int
+write_sector(sectno, loadaddr)
+int sectno;
+char * loadaddr;
+{
+#ifdef __MSDOS__
+ if( disktype == 1 || disktype == 2 )
+ {
+ int tries, rv;
+ int s,h,c;
+ s = sectno%disk_sect + 1;
+ h = sectno/disk_sect%disk_head;
+ c = sectno/disk_sect/disk_head;
+
+ for(tries=0; tries<6; tries++)
+ if( (rv = dos_sect_write(disktype-1, c, h, s, loadaddr)) == 0 )
+ break;
+ if( rv )
+ {
+ fprintf(stderr, "Error writing sector %d, (%d)\n", sectno, rv/256);
+ return -1;
+ }
+ return 0;
}
- else
+#endif
+ if( disktype )
{
- mktarboot(argv[ar]);
- done++;
+ fprintf(stderr, "Cannot write sector %d\n", sectno);
+ return -1;
}
+ fseek(diskfd, (long)sectno*512, 0);
+ if( fwrite(loadaddr, 512, 1, diskfd) != 1 )
+ {
+ fprintf(stderr, "Cannot write sector %d\n", sectno);
+ return -1;
+ }
+ return 0;
}
-Usage(flg)
-int flg;
+int
+read_sector(sectno, loadaddr)
+int sectno;
+char * loadaddr;
{
- fprintf(stderr, "Usage: makeboot [-f] device\n");
- exit(9);
+ int cc;
+#ifdef __MSDOS__
+ if( disktype == 1 || disktype == 2 )
+ {
+ int tries, rv;
+ int s,h,c;
+ s = sectno%disk_sect + 1;
+ h = sectno/disk_sect%disk_head;
+ c = sectno/disk_sect/disk_head;
+
+ for(tries=0; tries<6; tries++)
+ if( (rv = dos_sect_read(disktype-1, c, h, s, loadaddr)) == 0 )
+ break;
+ if( rv )
+ {
+ fprintf(stderr, "Error reading sector %d, (%d)\n", sectno, rv/256);
+ memset(loadaddr, '\0', 512);
+ return -1;
+ }
+ return 0;
+ }
+#endif
+ if( disktype )
+ {
+ fprintf(stderr, "Cannot read sector %d\n", sectno);
+ return -1;
+ }
+ fseek(diskfd, (long)sectno*512, 0);
+ if( (cc=fread(loadaddr, 1, 512, diskfd)) != 512 )
+ {
+ fprintf(stderr, "Cannot read sector %d, clearing\n", sectno);
+ if(cc<0) cc=0;
+ memset(loadaddr+cc, '\0', 512-cc);
+ }
+ return 0;
}
+/**************************************************************************/
-mktarboot(fname)
-char * fname;
+#ifdef __MSDOS__
+dos_sect_read(drv, track, head, sector, loadaddr)
{
- FILE * fd;
+#asm
+ push bp
+ mov bp,sp
- fd = fopen(fname, "r+");
- if( !fd ) { perror(fname); exit(1); }
+ push ds
+ pop es
- if( fread(tarblock, sizeof(tarblock), 1, fd) != 1 )
- { fprintf(stderr, "Cannot read boot block\n"); exit(1); }
+ mov dh,[bp+2+_dos_sect_read.head]
+ mov dl,[bp+2+_dos_sect_read.drv]
+ mov cl,[bp+2+_dos_sect_read.sector]
+ mov ch,[bp+2+_dos_sect_read.track]
- check_tar(1);
- mangle_tarvol();
+ mov bx,[bp+2+_dos_sect_read.loadaddr]
- rewind(fd);
- if( fwrite(tarblock, sizeof(tarblock), 1, fd) != 1 )
- { fprintf(stderr, "Cannot write boot block\n"); exit(1); }
+ mov ax,#$0201
+ int $13
+ jc read_err
+ mov ax,#0
+read_err:
- rewind(fd);
- if( fread(tarblock, sizeof(tarblock), 1, fd) != 1 )
- { fprintf(stderr, "Cannot re-read boot block\n"); exit(1); }
+ pop bp
+#endasm
+}
+#endif
- if( fread(tarblock, sizeof(tarblock), 1, fd) == 1 && head.linkflag == '0' )
- printf("Boot block installed to boot file %s\n", head.name);
+#ifdef __MSDOS__
+dos_sect_write(drv, track, head, sector, loadaddr)
+{
+#asm
+ push bp
+ mov bp,sp
- fclose(fd);
- exit(0);
+ push ds
+ pop es
+
+ mov dh,[bp+2+_dos_sect_write.head]
+ mov dl,[bp+2+_dos_sect_write.drv]
+ mov cl,[bp+2+_dos_sect_write.sector]
+ mov ch,[bp+2+_dos_sect_write.track]
+
+ mov bx,[bp+2+_dos_sect_write.loadaddr]
+
+ mov ax,#$0301
+ int $13
+ jc write_err
+ mov ax,#0
+write_err:
+
+ pop bp
+#endasm
}
+#endif
+
+/**************************************************************************/
+
+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 buff_tar (*(struct tar_head*) buffer)
+#define boot_tar (*(struct tar_head*) tarboot_data)
unsigned int oct(s)
char *s;
@@ -109,46 +334,46 @@ char *s;
return val;
}
-check_tar(fatal)
-int fatal;
+check_tar()
{
char vbuf[100], *p;
unsigned int csum = 0;
long osum = -1;
- osum = oct(head.chksum);
- memset(head.chksum, ' ', sizeof(head.chksum));
+ for(p=buffer; p<buffer+512; p++)
+ if( *p ) goto not_zapped;
+ /* Block zapped, ok */
+ return 0;
+not_zapped:
+
+ osum = oct(buff_tar.chksum);
+ memset(buff_tar.chksum, ' ', sizeof(buff_tar.chksum));
- for(p=tarblock; p<tarblock+sizeof(tarblock); p++)
+ for(p=buffer; p<buffer+512; 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;
+ exit(9);
}
- if( head.linkflag != 'V' )
+ if( buff_tar.linkflag != 'V' )
{
fprintf(stderr, "Tar file doesn't start with a volume label\n");
- if(fatal) exit(8);
- return -1;
+ exit(8);
}
- strcpy(vbuf, boothead.name); strcat(vbuf, " Volume 1");
- if( !force && strcmp(boothead.name, head.name) != 0
- && strcmp(vbuf, head.name) != 0 )
+ strcpy(vbuf, boot_tar.name); strcat(vbuf, " Volume 1");
+ if( strcmp(boot_tar.name, buff_tar.name) != 0
+ && strcmp(vbuf, buff_tar.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;
+ fprintf(stderr, "WARNING: Volume is labeled as '%s' not '%s'\n",
+ buff_tar.name, boot_tar.name);
}
return 0;
}
-mangle_tarvol()
+copy_tarblock()
{
char lbuf[20];
char * p;
@@ -157,31 +382,232 @@ mangle_tarvol()
struct tar_head temp;
- temp = boothead;
+ temp = boot_tar;
/* 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++)
+ if( buff_tar.name[0] )
{
- int ch = head.name[i];
- if( islower(ch) ) ch = toupper(ch);
- if( strchr("/?@ABCDEFGHIJKLMNO", ch) == 0 )
- ch = '?';
- temp.name[i] = ch;
+ memcpy(temp.mtime, buff_tar.mtime, sizeof(temp.mtime));
+
+ memset(temp.name, 0x90, 16);
+ for(i=0; buff_tar.name[i] && buff_tar.name[i] != ' ' && i<14; i++)
+ {
+ int ch = buff_tar.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;
}
- temp.name[i++] = 0;
- temp.name[i] = 0xC0;
+ else
+ sprintf(temp.mtime, "%11lo", time((void*)0));
+
+ buff_tar = temp;
- head = temp;
- /* Calculate the checksum */
- memset(head.chksum, ' ', sizeof(head.chksum));
+ /* Re-calculate the checksum */
+ memset(buff_tar.chksum, ' ', sizeof(buff_tar.chksum));
- for(p=tarblock; p<tarblock+sizeof(tarblock); p++)
+ for(p=buffer; p<buffer+512; p++)
csum += (*p & 0xFF);
- sprintf(head.chksum, "%7o", csum);
+ sprintf(buff_tar.chksum, "%7o", csum);
+
+ printf("Boot block installed");
+ if( ((struct tar_head*)buffer)[1].name[0] )
+ printf(" to boot file '%s'\n",
+ ((struct tar_head*)buffer)[1].name);
+ else
+ printf(", use 'tar -r' to add executable\n");
+}
+
+/**************************************************************************/
+
+#define DOS_SYSID 0
+#define DOS_SECT 1
+#define DOS_CLUST 2
+#define DOS_RESV 3
+#define DOS_NFAT 4
+#define DOS_NROOT 5
+#define DOS_MAXSECT 6
+#define DOS_MEDIA 7
+#define DOS_FATLEN 8
+#define DOS_SPT 9
+#define DOS_HEADS 10
+#define DOS_HIDDEN 11
+#define DOS4_MAXSECT 12
+#define DOS4_PHY_DRIVE 13
+#define DOS4_SERIAL 14
+#define DOS4_LABEL 15
+#define DOS4_FATTYPE 16
+
+struct bootfields {
+ int offset;
+ int length;
+ int value;
+}
+ dosflds[] =
+{
+ { 0x03, 8, 0},
+ { 0x0B, 2, 0},
+ { 0x0D, 1, 0},
+ { 0x0E, 2, 0},
+ { 0x10, 1, 0},
+ { 0x11, 2, 0},
+ { 0x13, 2, 0},
+ { 0x15, 1, 0},
+ { 0x16, 2, 0},
+ { 0x18, 2, 0},
+ { 0x1A, 2, 0},
+ { 0x1C, 4, 0},
+ { 0x20, 4, 0},
+ { 0x24, 1, 0},
+ { 0x27, 4, 0},
+ { 0x2B, 11, 0},
+ { 0x36, 8, 0},
+ { -1,0,0}
+};
+
+print_super(bootsect)
+char * bootsect;
+{
+static char * fieldnames[] = {
+ "System ID",
+ "Sector size",
+ "Cluster size",
+ "Reserved sectors",
+ "FAT count",
+ "Root dir entries",
+ "Sector count (=0 if large FS)",
+ "Media code",
+ "FAT length",
+ "Sect/Track",
+ "Heads",
+ "Hidden sectors (Partition offset)",
+ "Large FS sector count",
+ "Phys drive",
+ "Serial number",
+ "Disk Label (DOS 4+)",
+ "FAT type",
+ 0
+};
+ int i;
+
+ for(i=0; dosflds[i].offset >= 0; i++)
+ {
+ printf("%-35s", fieldnames[i]);
+ if( dosflds[i].length <= 4 )
+ {
+ long v = 0; int j;
+ for(j=dosflds[i].length-1; j>=0; j--)
+ {
+ v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] ));
+ }
+ printf("%ld\n", v);
+ }
+ else
+ {
+ int ch, j;
+ for(j=0; j<dosflds[i].length; j++)
+ {
+ ch = bootsect[dosflds[i].offset+j];
+ if( ch <= ' ' || ch > '~' ) putchar('.');
+ else putchar(ch);
+ }
+ putchar('\n');
+ }
+ }
+}
+
+decode_super(bootsect)
+char * bootsect;
+{
+ int i;
+
+ for(i=0; dosflds[i].offset >= 0; i++)
+ {
+ if( dosflds[i].length <= 4 )
+ {
+ long v = 0; int j;
+ for(j=dosflds[i].length-1; j>=0; j--)
+ {
+ v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] ));
+ }
+ dosflds[i].value = v;
+ }
+ else
+ dosflds[i].value = 0;
+ }
+}
+
+save_super(bootsect)
+char * bootsect;
+{
+ FILE * fd;
+ fd = fopen("makeboot.sav", "wb");
+ fwrite(bootsect, 1024, 1, fd);
+ fclose(fd);
+}
+
+/**************************************************************************/
+
+check_msdos()
+{
+ decode_super(buffer);
+ if( dosflds[DOS_CLUST].value == 0 ) /* MSDOS v1.0 */
+ dosflds[DOS_CLUST].value = 1;
+
+ if( dosflds[DOS_MEDIA].value < 0xF0 )
+ fprintf(stderr, "Dos media descriptor is invalid\n");
+ else if( dosflds[DOS_MEDIA].value != (0xFF&buffer[512])
+ && dosflds[DOS_RESV].value == 1 )
+ fprintf(stderr, "Dos media descriptor check failed\n");
+ else
+ {
+ disk_sect = dosflds[DOS_SPT].value;
+ disk_head = dosflds[DOS_HEADS].value;
+ disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect;
+ return;
+ }
+ exit(2);
+}
+
+check_simpledos()
+{
+ int numclust;
+ char * err = 0;
+ check_msdos();
+
+ /* Work out how many real clusters there are */
+ numclust = ( dosflds[DOS_MAXSECT].value
+ - dosflds[DOS_RESV].value
+ - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value
+ - ((dosflds[DOS_NROOT].value+15)/16)
+ ) / dosflds[DOS_MAXSECT].value + 2;
+
+ if( dosflds[DOS_NFAT].value > 2 )
+ err = "Too many fat copies on disk";
+ else if( dosflds[DOS_HIDDEN].value != 0 )
+ err = "Dubious MSDOS floppy, it's got hidden sectors.";
+ else if( dosflds[DOS_NROOT].value < 15 )
+ err = "Root directory has unreasonable size.";
+ else if( dosflds[DOS_SECT].value != 512 )
+ err = "Drive sector size isn't 512 bytes sorry no-go.";
+ else if( dosflds[DOS_HEADS].value != 2 )
+ err = "Drive doesn't have two heads, this is required.";
+ else if( numclust > 0xFF0 )
+ err = "Filesystem has a 16 bit fat, only 12bits allowed.";
+ else if( dosflds[DOS_RESV].value + dosflds[DOS_FATLEN].value >
+ dosflds[DOS_SPT].value )
+ err = "The bootblock needs all of fat1 on the first track.";
+ else
+ return;
+
+ fprintf(stderr, "ERROR: %s\n\n", err);
+ print_super(buffer);
+ exit(2);
}
+/**************************************************************************/
diff --git a/bootblocks/mbr.s b/bootblocks/mbr.s
index e190be2..dd4cb27 100644
--- a/bootblocks/mbr.s
+++ b/bootblocks/mbr.s
@@ -14,8 +14,8 @@ preboot=1 ! Include the pre-boot loader ?
org ORGADDR
include sysboot.s
-org ORGADDR+$7
-.ascii "ELKS MBR Copyright 1996, Robert de Bath"
+org ORGADDR+$3
+.ascii "ELKS MBR Copyright 1996, Robert de Bath"
! Start after dos fsstat data, not strictly required.
org codestart
diff --git a/bootblocks/monitor.c b/bootblocks/monitor.c
index 6c1d9eb..b9cc751 100644
--- a/bootblocks/monitor.c
+++ b/bootblocks/monitor.c
@@ -1,13 +1,17 @@
-#define VERSION "0.0.0-ALPHA"
-#define NOT_ANSICOLOUR
-#define VT52COLOUR
+#define VERSION "0.1.1-ALPHA"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
-#include <i86_funcs.h>
#include <dos.h>
+#include "i86_funcs.h"
+#include "readfs.h"
+
+#ifdef __STANDALONE__
+#define VT52COLOUR
+#define NOT_ANSICOLOUR
+#endif
char command_buf[256];
@@ -37,41 +41,29 @@ static char minibuf[2] = " ";
char *cmd, *args, *ptr;
struct t_cmd_list * cptr;
+#ifdef __STANDALONE__
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__
+#else
if( argc > 1 && strcmp(argv[1], "-t") == 0 ) x86_test=0; else x86_test=1;
#endif
init_prog();
+
+#if 0
#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);
- }
+ reg_line();
#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");
+ colour_line();
+#endif
#endif
- printf("Type ^C to exit\n");
+ display_help(0);
+
+ if(1) /* ( x86 > 2 && !x86_emu ) /* Check some basics */
+ cmd_bzimage((void*)0);
+ else
+ printf("System appears incompatible use '=' <return> to try anyway\n");
for (;;)
{
@@ -88,7 +80,7 @@ static char minibuf[2] = " ";
command_buf[ch] = '\0';
if( ch == 1 && command_buf[0] != '\n' )
{
- sprintf(command_buf, "func 0x%02x\n", command_buf[0]&0xFF);
+ sprintf(command_buf, "?$%02x\n", command_buf[0]&0xFF);
printf("%s", command_buf);
}
if( command_buf[ch-1] == '\n' ) command_buf[ch-1] = 0;
@@ -127,6 +119,7 @@ static char minibuf[2] = " ";
#ifdef VT52COLOUR
printf("\033S \033Sa\033Rg");
#endif
+ fflush(stdout);
if( cptr->command )
(void) (*cptr->func)(args);
else
@@ -138,6 +131,14 @@ static char minibuf[2] = " ";
void init_prog()
{
+#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);
+
cpu_check();
mem_check();
@@ -162,16 +163,41 @@ void init_prog()
printf("There is %dk of boot memory", boot_mem_top/64);
if( main_mem_top )
{
- printf(" %ld.%ldM of main memory",
+ printf(" %ld.%ldM %sof main memory",
main_mem_top/1024,
- (10*main_mem_top)/1024%10
+ (10*main_mem_top)/1024%10,
+ main_mem_top >= 0xFC00L ?"(perhaps more) ":""
);
}
printf("\n");
+}
- if( main_mem_top >= 0xFC00L )
- printf("There may be more main memory available but the BIOS don't say\n");
+#ifdef __STANDALONE__
+reg_line()
+{
+ 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
+colour_line()
+{
+ printf("Colours: \033S ");
+ printf("\033R_UNL\033S ");
+ printf("\033R*BLK\033S ");
+ printf("\033R+BLD\033S ");
+ printf("\033R!REV\033S ");
+ 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");
+
+ printf("\033S \033Sa\033Rg");
+}
+#endif
/****************************************************************************/
@@ -320,29 +346,84 @@ char * ptr;
printf("to 0x%04x\n", __get_cs());
}
+int cmd_dir(ptr)
+char * ptr;
+{
+ open_file(".");
+ return 0;
+}
+
+int cmd_type(ptr)
+char * ptr;
+{
+ char * fname;
+ char buffer[1024];
+ long len;
+
+ while(*ptr == ' ') ptr++;
+ if( (fname=ptr) == 0 ) return 0;
+ while(*ptr & *ptr != ' ') ptr++;
+
+ if( open_file(fname) >= 0 ) for(len=file_length(); len>0; len-=1024)
+ {
+ if( read_block(buffer) < 0 ) break;
+ if( len > 1024 )
+ write(1, buffer, 1024);
+ else
+ write(1, buffer, len);
+ }
+ else
+ printf("Cannout open file '%s'\n", fname);
+ close_file();
+ return 0;
+}
+
+/****************************************************************************/
+
+/* Others */
+extern int cmd_bzimage();
+extern int cmd_help();
+
/****************************************************************************/
struct t_cmd_list cmd_list[] =
{
{"exit", cmd_quit}, {"quit", cmd_quit}, {"q", cmd_quit},
- {"memdump",cmd_memdump}, {"m", cmd_memdump},
+ {"#", cmd_nop},
+ {"help", cmd_help}, /* Display from help.txt */
+ {"?", cmd_help}, /* Display from help.txt */
+ {"bzimage",cmd_bzimage}, /* Load and run 386 bzimage file */
+ {"=", cmd_bzimage}, /* Load and run 386 bzimage file */
+ {"dir", cmd_dir}, /* Display directory */
+ {"type", cmd_type}, /* Cat/Type a file to the screen */
+ {"cat", cmd_type}, /* Cat/Type a file to the screen */
+
+ /* Debugger/monitor commands */
+ {"memdump",cmd_memdump}, {"mem",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},
+
+#ifdef VT52COLOUR
+ {"colour", colour_line},
+#endif
+ {"init", init_prog},
+#ifdef __STANDALONE__
+ {"reg", reg_line},
+ {"r", reg_line},
+#endif
+
/*
{"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
+ {"zimage", cmd_zimage}, Load and run 386 zimage file
+ {"image", cmd_image}, Load and run 8086 image file
{"read", cmd_read}, Read sector
{"write", cmd_write}, Write sector
diff --git a/bootblocks/msdos.s b/bootblocks/msdos.s
index 1e71f31..fdded78 100644
--- a/bootblocks/msdos.s
+++ b/bootblocks/msdos.s
@@ -2,21 +2,31 @@
! This is a bootblock to load an execute a standalone program from an
! MSDOS filesystem on a floppy disk.
!
-! The program is divided into two parts, the first 512 bytes contains a
-! loader to fetch one block from a file called 'BOOTFILE.SYS' from the
-! root directory of the disk. The second 512, which is stored in this file,
-! loads the executable using functions supplied by the first.
+! The file loaded is called 'BOOTFILE.SYS' it can be changed at install time
+! by following the label boot_name.
!
-! The 2nd part is loaded as if it's a floppy boot block and can be used to
-! store, for instance, a LILO boot block to let LILO boot from an MSDOS
-! floppy.
+! The file is loaded at address $7C00, this means it can be the image of a
+! boot block (eg LILO). It's also checked for the magic number associated
+! with a Linux-8086 standalone executable and this is used if found.
!
-! The second part is NOT yet complete!
+! There are a number of assumptions made by the code concerning the layout
+! of the msdos files system:
+!
+! 1) All of the first FAT must be on the first track.
+! 2) The FAT must be 12 bit
+! 3) The value of the hidden sectors field must be zero
+! 4) There must be two heads on the disk.
+!
+! All these are true for mtools created floppies on normal PC drives.
!
ORGADDR=$0500
use16
+! Some configuration values
+LOADSEG= $7C0
+
+!-------------------------------------------------------------------------
! Absolute position macro, fails if code before it is too big.
macro locn
if *-start>?1
@@ -25,6 +35,8 @@ macro locn
.blkb ?1 + start-*
mend
+heads=2 ! This can be 1 or 2 ONLY. (1 is untested)
+
org ORGADDR
start:
include sysboot.s
@@ -74,13 +86,13 @@ cont:
mov [bp],di
mov 2[bp],ax
- mov al,[dos_spt]
+ mov al,[dos_spt] ! Finally, correct spt.
mov 4[di],al
! For each sector in root dir
! For each dir entry
! If entry name is == boot_name
-! then load and call sector
+! then load and run
! First dir = dos_fatlen*dos_nfat+dos_resv
mov ax,[dos_fatlen]
@@ -88,6 +100,7 @@ cont:
xor dh,dh
mul dx
add ax,[dos_resv]
+ ! Assume: dos_hidden == 0
mov di,ax
! DI is sector number of first root dir sector.
@@ -109,6 +122,8 @@ nextsect:
mov si,bx
nextentry:
+ ! Test attributes for !dir !label here ?
+
! test entry name
push si
push di
@@ -118,61 +133,53 @@ nextentry:
cmpsb
pop di
pop si
- je got_entry
+ jne bad_entry
- add si,#32
+ mov ax,[si+26] ! Cluster number of start of file
+ test ax,ax ! Make sure we have a block.
+ jnz load_system
+
+bad_entry:
+ add si,#32 ! skip to next entry
cmp si,#512
jnz nextentry
- inc di
+ inc di ! Load next sector
sub [root_count],#16
jp nextsect
jmp no_system
-got_entry:
- mov ax,[si+26] ! Cluster number of start of file
- test ax,ax
- jz no_system ! Make sure we have a block.
-
- mov di,ax ! Save the cluster number we are loading.
- call linclust
-
- mov ax,#$0201
- int $13
- jc floppy_error
-
- mov bx,#7
- mov ax,#$0E3E
- int $10
-
- jmpi $7C00,0 ! No magics, just go.
-
-! Convert a cluster number into a CHS in CX:DX
+! Convert a cluster number in AX into a CHS in CX:DX
linclust:
sub ax,#2
mov dl,[dos_clust]
xor dh,dh
mul dx
- add ax,bp
- mov di,ax
- ! JMP linsect ...
+ add ax,bp ! Add sector number of first data sector.
+ jmp linsect2
!
! This function converts a linear sector number in DI
! into a CHS representation in CX:DX
!
linsect:
- xor dx,dx
mov ax,di
+linsect2:
+ xor dx,dx
div [dos_spt]
inc dx
mov cl,dl ! Sector num
xor dx,dx ! Drive 0
+ if heads =2
shr ax,#1 ! Assume dos_heads == 2
adc dh,#0 ! Head num
+ endif
mov ch,al ! Cylinder
ret
+error_msg:
+ .asciz "\r\nError during initial boot\r\nPress a key:"
+
no_system:
floppy_error:
@@ -191,31 +198,15 @@ EOS:
int $19 ! This should be OK as we haven't touched anything.
jmpi $0,$FFFF ! Wam! Try or die!
-error_msg:
- .asciz "\r\nError during initial boot\r\nPress a key:"
-
-export boot_name
-boot_name:
- .ascii "BOOTFILESYS"
-name_end:
-! NNNNNNNNEEE
!
-!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+! This loads the boot program 1 sector at a time, funny thing is it actually
+! loads at exactly the same speed as loading a track at a time, at least on
+! my slow old 286/8Mhz. Oh well, we need the space so if you're worried just
+! tell superformat to give you an interleave of 2 (-i 2).
!
-! Part 2, loaded like a boot block by part 1
-! ... Here we will allow some assumptions (cause we've set them)
-fat_table = ORGADDR+$400 ! Where to load the fat
-locn(512)
-part2_addr:
- push di
- mov cx,#$100 ! Move 256 words
- mov si,#$7C00 ! From default BB
- mov di,#part2_addr ! To the correct address.
- rep
- movsw
- jmpi cont2,#0 ! Set CS:IP correct.
-cont2:
+load_system:
+ push ax ! Save cluster we're loading
! 1) Load FAT
! This assumes all of FAT1 is on the first track, this is normal
@@ -226,28 +217,109 @@ cont2:
inc cx
xor dx,dx ! Head zero
int $13
- !jc floppy_error
+ jc floppy_error
- mov bx,#$7C00
+ mov ax,#LOADSEG
+ mov es,ax
pop di ! Cluster to start load.
! load whole cluster
next_cluster:
+ mov si,[dos_clust] ! How big is a cluster
+ and si,#255
+
+ mov ax,di ! Find it's physical address
+ call linclust
+
+next:
+ mov ax,#$0201
+ xor bx,bx
+ int $13 ! Load 1 sector at a time
+ jc floppy_error
+
+ mov ax,es
+ add ax,#512/16
+ mov es,ax
+
+ cmp cl,[dos_spt] ! Does cluster straddle tracks ?
+ jnz sectok
+ mov cl,#0
+ if heads=2
+ inc dh
+ cmp dh,#2 ! Does cluster straddle cylinders ?
+ jnz sectok
+ xor dh,dh
+ endif
+ inc ch
+sectok:
+ inc cl
+ dec si
+ jnz next
call next_fat
- cmp di,#0
- jnz next_cluster
- br maincode
+ jc next_cluster
+ jmp maincode
next_fat:
- !mov ax,di
- !mov bx,ax
- !shr ax,#1
- !add bx,ax
-
+ mov ax,di
+ shr ax,#1
+ pushf ! Save if odd number
+ add di,ax
+ mov di,fat_table[di]
+ popf
+ jnc noshift ! Odd in high nibbles.
+ mov cl,#4
+ shr di,cl
+noshift:
+ and di,#$FFF
+ cmp di,#$FF0 ! FFF is EOF, clear carry flag.
+ ! FF0+ are badblocks etc.
+ ret
-! The end ... place a marker.
-locn(1023)
- .byte $FF
maincode:
+ mov bx,#7
+ mov ax,#$0E3E
+ int $10 ! Marker printed to say bootblock succeeded.
+
+ xor dx,dx ! DX=0 => floppy drive
+ push dx ! CX=0 => partition offset = 0
+
+ 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
+bad_magic:
+ jmpi $7C00,0 ! No magics, just go.
+
+export boot_name
+boot_name:
+ .ascii "BOOTFILESYS"
+name_end:
+! NNNNNNNNEEE
+
+locn(512)
+fat_table: ! This is the location that the fat table is loaded.
+ ! Note: The fat must be entirely on track zero.
diff --git a/bootblocks/nofs.c b/bootblocks/nofs.c
new file mode 100644
index 0000000..e671a69
--- /dev/null
+++ b/bootblocks/nofs.c
@@ -0,0 +1,55 @@
+
+#ifndef __STANDALONE__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "readfs.h"
+
+static int fd = -1;
+
+open_file(fname)
+char * fname;
+{
+ if( fd >= 0 ) close(fd);
+ fd = open(fname, 0);
+ if( fd >= 0 ) return 0;
+ return -1;
+}
+
+rewind_file()
+{
+ if( fd == -1 ) return -1;
+ lseek(fd, 0L, 0);
+ return 0;
+}
+
+close_file()
+{
+ if( fd >= 0 ) close(fd);
+ fd = -1;
+}
+
+long
+file_length()
+{
+ struct stat st;
+ if( fd == -1 ) return -1;
+ if( fstat(fd, &st) < 0 ) return -1;
+
+ return st.st_size;
+}
+
+read_block(buffer)
+char * buffer;
+{
+ int rv;
+ if( fd == -1 ) return -1;
+
+ rv = read(fd, buffer, 1024);
+ if( rv <= 0 ) return -1;
+ if( rv < 1024 )
+ memset(buffer+rv, '\0', 1024-rv);
+ return 0;
+}
+
+#endif
diff --git a/bootblocks/relocate.c b/bootblocks/relocate.c
index 37396a1..6101296 100644
--- a/bootblocks/relocate.c
+++ b/bootblocks/relocate.c
@@ -50,11 +50,10 @@ unsigned newseg;
moved += lump;
}
- /* re-link int 0x80
- __set_es(0);
- __doke_es(0x80*4+2, newseg);
- __set_es(es);
- */
+ /* re-link int 0x80, this one is only an example (used by 'standalone.c') */
+ /*
+ __set_es(0); __doke_es(0x80*4+2, newseg); __set_es(es);
+ */
/* The actual jump ... */
memseg = newseg;
diff --git a/bootblocks/skip.s b/bootblocks/skip.s
index 8de5ada..3e55cd9 100644
--- a/bootblocks/skip.s
+++ b/bootblocks/skip.s
@@ -33,6 +33,7 @@ cont:
mov di,#5
hcode:
+ mov bx,#$7C00 ! Pointer to start of BB.
mov ax,#$0201 ! Read 1 sector
mov cx,#$0001 ! From sector 1
mov dx,#BOOTDISK ! Of the hard drive head zero
diff --git a/bootblocks/sysboot.s b/bootblocks/sysboot.s
index 622488f..54b0fb2 100644
--- a/bootblocks/sysboot.s
+++ b/bootblocks/sysboot.s
@@ -15,31 +15,33 @@
sysboot_start:
j codestart
+nop ! DOS appears to _require_ this to identify an MSDOS disk!!
.blkb sysboot_start+3-*
public dosfs_stat
+dos_sysid: .ascii "LINUX" ! System ID
+ .byte 0,0,0
dosfs_stat:
-dos_sysid: .blkb 8 ! System ID
-dos_sect: .word 0 ! Sector size
-dos_clust: .byte 0 ! Cluster size
-dos_resv: .word 0 ! Res-sector
-dos_nfat: .byte 0 ! FAT count
-dos_nroot: .word 0 ! Root dir entries
-dos_maxsect: .word 0 ! Sector count (=0 if large FS)
-dos_media: .byte 0 ! Media code
-dos_fatlen: .word 0 ! FAT length
-dos_spt: .word 0 ! Sect/Track
-dos_heads: .word 0 ! Heads
-dos_hidden: .long 0 ! Hidden sectors
+dos_sect: .blkw 1 ! Sector size
+dos_clust: .blkb 1 ! Cluster size
+dos_resv: .blkw 1 ! Res-sector
+dos_nfat: .blkb 1 ! FAT count
+dos_nroot: .blkw 1 ! Root dir entries
+dos_maxsect: .blkw 1 ! Sector count (=0 if large FS)
+dos_media: .blkb 1 ! Media code
+dos_fatlen: .blkw 1 ! FAT length
+dos_spt: .blkw 1 ! Sect/Track
+dos_heads: .blkw 1 ! Heads
+dos_hidden: .blkw 2 ! Hidden sectors
! Here down is DOS 4+ and probably not needed for floppy boots.
floppy_temp:
-dos4_maxsect: .long 0 ! Large FS sector count
-dos4_phy_drive: .byte 0 ! Phys drive
-.byte 0 ! Reserved
-.byte 0 ! DOS 4
-dos4_serial: .long 0 ! Serial number
+dos4_maxsect: .blkw 2 ! Large FS sector count
+dos4_phy_drive: .blkb 1 ! Phys drive
+.blkb 1 ! Reserved
+.blkb 1 ! DOS 4
+dos4_serial: .blkw 2 ! Serial number
dos4_label: .blkb 11 ! Disk Label (DOS 4+)
dos4_fattype: .blkb 8 ! FAT type
@@ -57,24 +59,28 @@ public bootblock_magic
.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
+.byte 0 ! IN
+.blkb 7 ! SH,SS,ST,OS,EH,ES,ET
+.blkw 2 ! Linear position (0 based)
+.blkw 2 ! 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
+.byte 0 ! IN
+.blkb 7 ! SH,SS,ST,OS,EH,ES,ET
+.blkw 2 ! Linear position (0 based)
+.blkw 2 ! 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
+.byte 0 ! IN
+.blkb 7 ! SH,SS,ST,OS,EH,ES,ET
+.blkw 2 ! Linear position (0 based)
+.blkw 2 ! 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
+.byte 0 ! IN
+.blkb 7 ! SH,SS,ST,OS,EH,ES,ET
+.blkw 2 ! Linear position (0 based)
+.blkw 2 ! Linear length
bootblock_magic:
.blkb sysboot_start+0x1FE-*