diff options
author | Robert de Bath <rdebath@poboxes.com> | 1997-02-25 20:42:19 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:38:07 +0200 |
commit | 4c36e9a0c125ccfff37aa440dab2cf58c4152fff (patch) | |
tree | a5d9c84ba2661029ddb2223dacd50529a361c3d5 /bootblocks | |
parent | f8de35da65c5d93bb733073cf40da154bc1c0748 (diff) | |
parent | 9696d7b0e1f3a1b0f5fd4a0428eb75afe8ad4ed6 (diff) | |
download | dev86-4c36e9a0c125ccfff37aa440dab2cf58c4152fff.tar.gz |
Import Dev86src-0.0.11.tar.gzv0.0.11
Diffstat (limited to 'bootblocks')
-rw-r--r-- | bootblocks/Makefile | 42 | ||||
-rw-r--r-- | bootblocks/README | 80 | ||||
-rw-r--r-- | bootblocks/bzimage.c | 555 | ||||
-rw-r--r-- | bootblocks/dosboot.c | 72 | ||||
-rw-r--r-- | bootblocks/dosfs.c | 419 | ||||
-rw-r--r-- | bootblocks/help.c | 93 | ||||
-rw-r--r-- | bootblocks/i86_funcs.c | 28 | ||||
-rw-r--r-- | bootblocks/makeboot.c | 634 | ||||
-rw-r--r-- | bootblocks/mbr.s | 4 | ||||
-rw-r--r-- | bootblocks/monitor.c | 161 | ||||
-rw-r--r-- | bootblocks/msdos.s | 214 | ||||
-rw-r--r-- | bootblocks/nofs.c | 55 | ||||
-rw-r--r-- | bootblocks/relocate.c | 9 | ||||
-rw-r--r-- | bootblocks/skip.s | 1 | ||||
-rw-r--r-- | bootblocks/sysboot.s | 64 |
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-* |