diff options
author | Robert de Bath <rdebath@poboxes.com> | 1997-07-20 12:16:17 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:39:55 +0200 |
commit | 9d97bc3cb3aecd3416fb7c4be3ca2f436665b696 (patch) | |
tree | b1e5b67ef9e065efb6a4c9977ecfac8dedbad39b /bootblocks | |
parent | e63c244cb22bf48ca1d2695784a072269d19ea96 (diff) | |
download | dev86-9d97bc3cb3aecd3416fb7c4be3ca2f436665b696.tar.gz |
Import Dev86src-0.12.4.tar.gzv0.12.4
Diffstat (limited to 'bootblocks')
-rw-r--r-- | bootblocks/Makefile | 41 | ||||
-rw-r--r-- | bootblocks/bzimage.c | 2 | ||||
-rw-r--r-- | bootblocks/dosfs.c | 6 | ||||
-rw-r--r-- | bootblocks/elf_info.c | 189 | ||||
-rw-r--r-- | bootblocks/elf_info.h | 282 | ||||
-rw-r--r-- | bootblocks/i86_funcs.h | 21 | ||||
-rw-r--r-- | bootblocks/li86.s | 46 | ||||
-rw-r--r-- | bootblocks/makeboot.c | 43 | ||||
-rw-r--r-- | bootblocks/minix.c | 349 | ||||
-rw-r--r-- | bootblocks/minix.h | 103 | ||||
-rw-r--r-- | bootblocks/monitor.c | 11 | ||||
-rw-r--r-- | bootblocks/noboot.s | 32 | ||||
-rw-r--r-- | bootblocks/readfs.h | 17 | ||||
-rw-r--r-- | bootblocks/standalone.c | 309 | ||||
-rw-r--r-- | bootblocks/sysboot.s | 29 | ||||
-rw-r--r-- | bootblocks/tarboot.s | 12 |
16 files changed, 1242 insertions, 250 deletions
diff --git a/bootblocks/Makefile b/bootblocks/Makefile index 707179f..7569500 100644 --- a/bootblocks/Makefile +++ b/bootblocks/Makefile @@ -7,26 +7,34 @@ CC=$(BCC) CFLAGS=-ansi -Ms -H0x10000 -s ASFLAGS=-0 # LST=-l $*.lst +# CLST=-A-l -A$*.lst default: makeboot makeboot.com monitor.out 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 +SSRC=sysboot.s \ + tarboot.s skip.s com_bcc.s tich.s \ + bootlist.s mbr.s msdos.s noboot.s encap: $(SSRC:s=v) $(CSRC:c=v) minixhd.v bin: $(SSRC:s=bin) $(CSRC:c=bin) minixhd.bin 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 +MINC=i86_funcs.h readfs.h + +EXTRAS=minix.h elf_info.c elf_info.h standalone.c li86.s install: monitor.out: $(MOBJ) $(CC) $(CFLAGS) $(MOBJ) -o monitor.out -monitor: $(MSRC) +$(MOBJ): $(MINC) version.h + +monitor: $(MSRC) $(MINC) @rm -f $(MOBJ) make 'CFLAGS=-ansi' monitor.out mv monitor.out monitor @@ -38,35 +46,42 @@ minix.s: minix.c minixhd.s: minix.c $(BCC) -Mc -DHARDDISK -S minix.c -o minixhd.s -makeboot: makeboot.c sysboot.v skip.v msdos.v tarboot.v +makeboot: makeboot.c sysboot.v noboot.v skip.v msdos.v tarboot.v $(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c -makeboot.com: makeboot.c sysboot.v skip.v msdos.v tarboot.v +makeboot.com: makeboot.c sysboot.v noboot.v skip.v msdos.v tarboot.v $(BCC) -Md -o makeboot.com makeboot.c +version.h: + head -1 ../Libc_version | \ + sed 's/\(.*\)/#define VERSION "\1"/' > version.h + clean realclean: rm -f monitor makeboot bootblocks.tar.gz - rm -f minix.s *.com *.o *.bin *.out *.lst *.sym *.v + rm -f minix.s minixhd.s version.h + rm -f *.com *.o *.bin *.out *.lst *.sym *.v *.tmp tgz: minix.bin monitor.out makeboot.com makeboot tar cfV bootblocks.tar ENIAC monitor.out \ README Makefile \ - $(MSRC) makeboot.c \ - $(CSRC) $(SSRC) \ - makeboot.com minix.bin + $(MSRC) \ + $(MINC) \ + makeboot.c $(CSRC) \ + $(SSRC) \ + makeboot.com minix.bin \ + $(EXTRAS) makeboot tar bootblocks.tar gzip -f9 bootblocks.tar distribution: - tar czf /tmp/bootblocks.tar.gz README Makefile \ - $(MSRC) makeboot.c \ - $(CSRC) $(SSRC) + tar czf /tmp/bootblocks.tar.gz \ + README Makefile $(MSRC) $(MINC) makeboot.c $(CSRC) $(SSRC) $(EXTRAS) .SUFFIXES: .bin .v .s.bin: - $(BCC) -c $*.s -A-u- -A-b -A/tmp/$*.bin -A-s -A$*.sym -A-l -A$*.lst - -@mv /tmp/$*.bin $*.bin + $(BCC) -c $*.s -A-u- -A-b -A$*.tmp -A-s -A$*.sym $(CLST) + mv $*.tmp $*.bin -@rm $*.o .s.v: diff --git a/bootblocks/bzimage.c b/bootblocks/bzimage.c index 8d38753..2e7c835 100644 --- a/bootblocks/bzimage.c +++ b/bootblocks/bzimage.c @@ -227,6 +227,8 @@ static unsigned int last_address = 0; for(i=0; i<512; i++) __poke_es(i, buffer[i]); } + else + printf("In EMU can't write to 0x%x\n", address); return 0; } #endif diff --git a/bootblocks/dosfs.c b/bootblocks/dosfs.c index 9dba0af..b9a2c04 100644 --- a/bootblocks/dosfs.c +++ b/bootblocks/dosfs.c @@ -298,14 +298,12 @@ static int pend_s, pend_h, pend_c, pend_len = 0; 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--; + if( rv ) printf("Error in phy_read(%d,%d,%d,%d,%d,%d);\n", + drive, pend_c, pend_h, pend_s+1, pend_len, buf_start); } while(rv && tries > 0); diff --git a/bootblocks/elf_info.c b/bootblocks/elf_info.c new file mode 100644 index 0000000..86fa392 --- /dev/null +++ b/bootblocks/elf_info.c @@ -0,0 +1,189 @@ + +#include <stdio.h> +#include "elf_info.h" + +Elf32_Ehdr elf_head; +Elf32_Phdr *elf_prog; + +#ifdef TEST +FILE *ifd; + +main(argc, argv) +int argc; +char **argv; +{ + ifd = fopen(argv[1], "r"); + if (ifd == 0) + exit(1); + + read_elfprog(); + write_ram("", -1L, 0); + + fclose(ifd); +} + +read_file(buf, offset, len) +void *buf; +long offset; +int len; +{ + fseek(ifd, offset, 0); + return fread(buf, 1, len, ifd); +} + +write_ram(buf, linear, len) +char *buf; +long linear; +int len; +{ +static long llen = 0; +static long lastlin= -1; + + if( llen > 0 && lastlin + llen != linear ) + { + printf("for %8ld bytes\n", llen); + lastlin= -1; + } + if( lastlin == -1 ) + { + lastlin = linear; + llen = 0; + + if( linear != -1 ) + printf("Write %08lx ", linear); + } + llen += len; + return len; +} + +error(str) +char *str; +{ + printf("Error: %s\n", str); + return -1; +} +#endif + +info_elf() +{ + int i; + + printf("ELF-386 executable, entry = 0x%08lx\n", elf_head.e_entry); + printf("\t\toffset paddr vaddr filesz memsz align\n"); + for (i = 0; i < elf_head.e_phnum; i++) + { + printf(" %d: ", i); + switch ((int) elf_prog[i].p_type) + { + case PT_NULL: + printf("PT_NULL"); + break; + case PT_LOAD: + printf("PT_LOAD"); + break; + case PT_DYNAMIC: + printf("PT_DYNAMIC"); + break; + case PT_INTERP: + printf("PT_INTERP"); + break; + case PT_NOTE: + printf("PT_NOTE"); + break; + case PT_SHLIB: + printf("PT_SHLIB"); + break; + case PT_PHDR: + printf("PT_PHDR"); + break; + default: + printf("PT_(%d)", elf_prog[i].p_type); + break; + } + printf("\t%08lx %08lx %08lx %08lx %08lx %08lx", + elf_prog[i].p_offset, + elf_prog[i].p_paddr, + elf_prog[i].p_vaddr, + elf_prog[i].p_filesz, + elf_prog[i].p_memsz, + elf_prog[i].p_align + ); + printf("\n"); + } +} + +read_elfprog() +{ + static unsigned char elf_ok[] = + {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, EV_CURRENT}; + + int i; + char page_buf[4096]; + + if (read_file(&elf_head, 0L, sizeof(elf_head)) != sizeof(elf_head)) + return error("Can't read ELF header"); + + if (memcmp(elf_head.e_ident, elf_ok, 7) != 0 || + elf_head.e_type != ET_EXEC || + elf_head.e_machine != EM_386 || + elf_head.e_phnum <= 0 || + elf_head.e_phentsize != sizeof(Elf32_Phdr) + ) + return error("Not a 386 executable ELF program"); + + elf_prog = malloc(i = sizeof(Elf32_Phdr) * elf_head.e_phnum); + if (elf_prog == 0) + return error("Out of memory"); + + if (read_file(elf_prog, elf_head.e_phoff, i) != i) + return error("Can't read ELF program header"); + + info_elf(); + + for (i = 0; i < elf_head.e_phnum; i++) + { + long from, to, length, copied; + int chunk; + + switch ((int) elf_prog[i].p_type) + { + case PT_NULL: + case PT_NOTE: + continue; + default: + return error("ELF: Unusable program segment (Must be static)"); + case PT_LOAD: + break; + } + from=elf_prog[i].p_offset; + to=elf_prog[i].p_vaddr; + length=elf_prog[i].p_filesz; + + for(copied=0; copied<length; ) + { + if(length>copied+sizeof(page_buf)) chunk=sizeof(page_buf); + else chunk=length-copied; + + if( (chunk=read_file(page_buf, from, chunk)) <= 0 ) + return error("ELF Cannot read executable"); + if( write_ram(page_buf, to, chunk) < 0 ) + return error("Memory save failed"); + copied+=chunk; from+=chunk; to+=chunk; + } + length=elf_prog[i].p_memsz; + if( length > copied ) + { + write_ram("", -1L, 0); + memset(page_buf, '\0', sizeof(page_buf)); + for(; copied<length; ) + { + if(length>copied+sizeof(page_buf)) chunk=sizeof(page_buf); + else chunk=length-copied; + + if( write_ram(page_buf, to, chunk) < 0 ) + return error("Memory zap failed"); + copied+=chunk; to+=chunk; + } + } + } +} diff --git a/bootblocks/elf_info.h b/bootblocks/elf_info.h new file mode 100644 index 0000000..a011d97 --- /dev/null +++ b/bootblocks/elf_info.h @@ -0,0 +1,282 @@ + +/* ELF layout information */ + +/* NOTE: I'm copying the file format information here because the _format_ + * is standard, but the Linux header files are not and may depend on + * headers not available when compiling Linux-86 code. + */ + +#ifndef _LINUX_ELF_H +#define _LINUX_ELF_H + +typedef unsigned long Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned long Elf32_Off; +typedef long Elf32_Sword; +typedef unsigned long Elf32_Word; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000L +#define PT_HIPROC 0x7fffffffL + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 5 +#define ET_HIPROC 6 + +/* These constants define the various ELF target machines */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000L +#define DT_HIPROC 0x7fffffffL + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 + +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) + +/* Symbolic values for the entries in the auxiliary table + put on the initial stack */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ + + +typedef struct dynamic{ + Elf32_Sword d_tag; + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +extern Elf32_Dyn _DYNAMIC []; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf32_sym{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + + +#define EI_NIDENT 16 + +typedef struct elfhdr{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000L +#define SHT_HIPROC 0x7fffffffL +#define SHT_LOUSER 0x80000000L +#define SHT_HIUSER 0xffffffffL + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000L + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00L +#define SHN_LOPROC 0xff00L +#define SHN_HIPROC 0xff1fL +#define SHN_ABS 0xfff1L +#define SHN_COMMON 0xfff2L +#define SHN_HIRESERVE 0xffffL + +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 + +/* Note header in a PT_NOTE section */ +typedef struct elf_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +#endif /* _LINUX_ELF_H */ diff --git a/bootblocks/i86_funcs.h b/bootblocks/i86_funcs.h new file mode 100644 index 0000000..9eb1b05 --- /dev/null +++ b/bootblocks/i86_funcs.h @@ -0,0 +1,21 @@ +/* + * These are bios and hardware functions for the 8086 IBM PC + */ + +extern int x86; /* CPU major number (0-3) */ +extern char *x86_name; /* and it's name */ +extern int x86_emu; /* Is this a PC emulator ? */ +extern int x86_a20_closed; /* Is the A20 gate closed ? */ +extern int x86_test; /* In test mode */ +extern int x86_fpu; + +extern unsigned boot_mem_top; /* Top of RAM below 1M */ +extern long main_mem_top; /* Top of RAM above 1M */ + +int a20_closed(); +void open_a20(); +void bios_open_a20(); +void cpu_check(); +void mem_check(); +int ext_put(); +int ext_get(); diff --git a/bootblocks/li86.s b/bootblocks/li86.s new file mode 100644 index 0000000..0c391ff --- /dev/null +++ b/bootblocks/li86.s @@ -0,0 +1,46 @@ +!---------------------------------------------------------------------------- +! +! This is a skeleton for creating an impure Linux-8086 executable without +! using the linker. The .text and .data areas are correctly positioned. +! +! This file needs to be compiled using the 3 pass mode (-j) +! +!---------------------------------------------------------------------------- +.text +org -32 +.word 0x0301 ! Magic +.word 0x0410 ! Btype +.long 0x20 ! header length +.long _etext ! a_text +.long _edata-_etext ! a_data +.long 0 ! a_bss +.long 0 ! a_entry +.long STACK_SIZE ! a_total +.long 0 ! a_syms +.data +.blkb _etext +.even +.text +!---------------------------------------------------------------------------- + +STACK_SIZE = 0x10000 + +.data +var: +.word $1234 + +.text + int $20 + mov ax,var + mov bx,_edata + push ax + ret + +!---------------------------------------------------------------------------- +! This trailer must be at the end of the file. +.text +_etext: +.data +_edata: +END + diff --git a/bootblocks/makeboot.c b/bootblocks/makeboot.c index 0f07735..4a036a6 100644 --- a/bootblocks/makeboot.c +++ b/bootblocks/makeboot.c @@ -4,17 +4,18 @@ #include <time.h> #include "sysboot.v" +#include "noboot.v" #include "msdos.v" #include "skip.v" #include "tarboot.v" char buffer[1024]; -#define FS_NONE 0 -#define FS_ADOS 1 -#define FS_DOS 2 -#define FS_TAR 3 -#define FS_STAT 4 +#define FS_NONE 0 /* Bootsector is complete */ +#define FS_ADOS 1 /* Bootsector needs 'normal' DOS FS */ +#define FS_DOS 2 /* Bootsector needs any DOS FS */ +#define FS_TAR 3 /* Bootsector needs GNU-tar volume label */ +#define FS_STAT 4 /* DOS bootsector is checked */ struct bblist { char * name; @@ -24,7 +25,7 @@ struct bblist { } bblocks[] = { { "tar", tarboot_data, FS_TAR, "Bootable GNU tar volume lable" }, { "dosfs", msdos_data, FS_ADOS, "Boots file BOOTFILE.SYS from dosfs" }, - { "none", sysboot_data, FS_DOS, "No OS bookblock, just message" }, + { "none", noboot_data, FS_DOS, "No OS bookblock, just message" }, { "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" }, @@ -41,6 +42,8 @@ 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 */ +int force = 0; + main(argc, argv) int argc; char ** argv; @@ -51,6 +54,10 @@ char ** argv; progname = argv[0]; + if( argc == 4 && strcmp(argv[1], "-f") == 0 ) + { + argv++; argc--; force++; + } if( argc != 3 ) Usage(); if( (i=strlen(argv[1])) < 2 ) Usage(); @@ -355,12 +362,12 @@ not_zapped: if( csum != osum ) { fprintf(stderr, "TAR file checksum failed, this isn't a tar file.\n"); - exit(9); + if(!force) exit(9); } if( buff_tar.linkflag != 'V' ) { fprintf(stderr, "Tar file doesn't start with a volume label\n"); - exit(8); + if(!force) exit(8); } strcpy(vbuf, boot_tar.name); strcat(vbuf, " Volume 1"); @@ -568,24 +575,26 @@ check_msdos() { disk_sect = dosflds[DOS_SPT].value; disk_head = dosflds[DOS_HEADS].value; - disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect; + if( disk_sect > 0 && disk_head > 0 ) + disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect; return; } - exit(2); + if(!force) exit(2); } check_simpledos() { - int numclust; + int numclust = 0xFFFF; 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_MAXSECT].value + 2 > 2 ) + 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"; @@ -607,7 +616,7 @@ check_simpledos() fprintf(stderr, "ERROR: %s\n\n", err); print_super(buffer); - exit(2); + if(!force) exit(2); } /**************************************************************************/ diff --git a/bootblocks/minix.c b/bootblocks/minix.c index 8242707..cfcfb38 100644 --- a/bootblocks/minix.c +++ b/bootblocks/minix.c @@ -7,6 +7,7 @@ */ #include <a.out.h> +#include "minix.h" #undef DOTS /* define to have dots printed */ #define zone_shift 0 /* for any < 32M (non-zero not supported yet) */ @@ -16,10 +17,20 @@ #define BOOTSEG (0x07c0) #define LOADSEG (0x1000) +#define TRY_FLOPPY + #ifdef HARDDISK #define get_now() #endif +#ifdef zone_shift +#if zone_shift == 0 +#define load_zone load_block +#endif +#else +static short zone_shift; +#endif + #asm ! BOOTSEG = 0x07c0 ! LOADSEG = 0x1000 ! This must be sector aligned @@ -57,11 +68,13 @@ org dos_sysid mov sp,ax #ifndef HARDDISK +loopy: mov ax,#$0204 ! Read 4 sectors, code + superblock. mov bx,#start ! Where this _should_ be mov cx,#$0001 ! From sector 1 xor dx,dx ! Of the floppy drive head zero int $13 + jc loopy #else mov cx,#$100 ! Move 256 words @@ -88,117 +101,7 @@ org dos_sysid #endasm /****************************************************************************/ -/* Super block table. The root file system and every mounted file system - * has an entry here. The entry holds information about the sizes of the bit - * maps and inodes. The s_ninodes field gives the number of inodes available - * for files and directories, including the root directory. Inode 0 is - * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be - * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4 - * for files and directories. The disk layout is: - * - * Item # blocks - * boot block 1 - * super block 1 - * inode map s_imap_blocks - * zone map s_zmap_blocks - * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK - * unused whatever is needed to fill out the current zone - * data zones (s_nzones - s_firstdatazone) << s_log_zone_size - * - * A super_block slot is free if s_dev == NO_DEV. - */ - -#define BLOCK_SIZE 1024 /* # bytes in a disk block */ - -/* Flag bits for i_mode in the inode. */ -#define I_TYPE 0170000 /* this field gives inode type */ -#define I_REGULAR 0100000 /* regular file, not dir or special */ -#define I_BLOCK_SPECIAL 0060000 /* block special file */ -#define I_DIRECTORY 0040000 /* file is a directory */ -#define I_CHAR_SPECIAL 0020000 /* character special file */ -#define I_SET_UID_BIT 0004000 /* set effective uid on exec */ -#define I_SET_GID_BIT 0002000 /* set effective gid on exec */ -#define ALL_MODES 0006777 /* all bits for user, group and others */ -#define RWX_MODES 0000777 /* mode bits for RWX only */ -#define R_BIT 0000004 /* Rwx protection bit */ -#define W_BIT 0000002 /* rWx protection bit */ -#define X_BIT 0000001 /* rwX protection bit */ -#define I_NOT_ALLOC 0000000 /* this inode is free */ - -/* Type definitions */ -typedef unsigned short unshort; /* must be 16-bit unsigned */ -typedef unshort block_nr; /* block number */ -typedef unshort inode_nr; /* inode number */ -typedef unshort zone_nr; /* zone number */ -typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort, - then also unshort, else long */ - -typedef unshort sect_nr; - -typedef long zone_type; /* zone size */ -typedef unshort mask_bits; /* mode bits */ -typedef unshort dev_nr; /* major | minor device number */ -typedef char links; /* number of links to an inode */ -typedef long real_time; /* real time in seconds since Jan 1, 1970 */ -typedef long file_pos; /* position in, or length of, a file */ -typedef short uid; /* user id */ -typedef char gid; /* group id */ - -/* Tables sizes */ -#define NR_ZONE_NUMS 9 /* # zone numbers in an inode */ -#define NAME_SIZE 14 /* # bytes in a directory component */ - -/* Miscellaneous constants */ -#define SUPER_MAGIC 0x137F /* magic number contained in super-block */ - -#define BOOT_BLOCK (block_nr)0 /* block number of boot block */ -#define SUPER_BLOCK (block_nr)1 /* block number of super block */ -#define ROOT_INODE (inode_nr)1 /* inode number for root directory */ - -/* Derived sizes */ -#define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */ -#define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */ -#define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */ -#define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */ - -struct super_block { - inode_nr s_ninodes; /* # usable inodes on the minor device */ - zone_nr s_nzones; /* total device size, including bit maps etc */ - unshort s_imap_blocks; /* # of blocks used by inode bit map */ - unshort s_zmap_blocks; /* # of blocks used by zone bit map */ - zone_nr s_firstdatazone; /* number of first data zone */ - short s_log_zone_size; /* log2 of blocks/zone */ - file_pos s_max_size; /* maximum file size on this device */ - short s_magic; /* magic number to recognize super-blocks */ - -} ; - -/* Type definitions local to the File System. */ -typedef struct { /* directory entry */ - inode_nr d_inum; /* inode number */ - char d_name[NAME_SIZE]; /* character string */ -} dir_struct; - -/* Declaration of the disk inode used in rw_inode(). */ -typedef struct { /* disk inode. Memory inode is in "inotab.h" */ - mask_bits i_mode; /* file type, protection, etc. */ - uid i_uid; /* user id of the file's owner */ - file_pos i_size; /* current file size in bytes */ - real_time i_modtime; /* when was file data last changed */ - gid i_gid; /* group number */ - links i_nlinks; /* how many links to this file */ - zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */ -} d_inode; - -/****************************************************************************/ - -#ifdef zone_shift -#if zone_shift == 0 -#define load_zone load_block -#endif -#else -static short zone_shift; -#endif +/* /* */ /* The name of the file and inode to start */ extern char bootfile[]; @@ -222,8 +125,10 @@ extern unsigned ldaddr; extern dir_struct * dirptr; extern unsigned flength; +#ifndef HARDDISK /* The 'shape' of the floppy - intuit from superblock */ extern unsigned n_sectors; +#endif /* * #define b_super (*(struct super_block *) 1024) @@ -237,16 +142,19 @@ extern zone_nr b_zone[NR_INDIRECTS]; extern dir_struct directory[]; /****************************************************************************/ +/* /* */ #asm ! A few variables we need to know the positions of for patching, so export ! them and as86_encaps will make some variables. .text -export _inode ! Inode to search +export inode ! Inode to search +inode: _inode: .word 1 ! ROOT_INODE -export _bootfile ! File to boot, make this whatever you like, -_bootfile: ! 'boot' is good too. +export bootfile ! File to boot, make this whatever you like, +bootfile: ! 'boot' is good too. +_bootfile: .ascii "linux" .byte 0,0,0,0,0,0,0,0,0 @@ -266,6 +174,9 @@ code: #endasm +/************************************/ +/* Hard disk device driver */ +/************************************/ #ifdef HARDDISK #asm @@ -319,7 +230,7 @@ real_block: ! ! Load AL sectors from linear sector DX:CX into location ES:BX -! Linear sector zero is a [bootpart] +! Linear sector zero is at [bootpart] ! This loads one sector at a time, but that's OK cause even in the _very_ ! worst case it'll take no more that 5 seconds to load a 16 bit executable. ! @@ -384,10 +295,20 @@ onesect: pop bx ! ES:BX for int 1302 pop es + mov di,#5 ! Lots of retries for a hd +retry: mov ax,#$0201 int $13 - jc _nogood + jnc got_hd_sect + + xor ax,ax ! Reset between each try. + int $13 + dec di + jnz retry + jmp _nogood + +got_hd_sect: pop dx pop cx pop si @@ -402,62 +323,9 @@ onesect: #endasm #else -#asm -_set_bpb: -bios_tabl=dosfs_stat ! Temp space. -bios_disk=dosfs_stat+4 ! - -#ifndef __CALLER_SAVES__ - push si - push di -#endif - - mov di,#bios_disk - mov bx,#0x78 -! 0:bx is parameter table address - - push ds - push di - - mov si,[bx] - mov ax,[bx+2] - mov [bios_tabl],si - mov [bios_tabl+2],ax - push ax - - pop ds -! ds:si is source - -! copy 12 bytes - mov cl,#6 - cld - rep - movsw - - pop di - pop ds - mov ax,[_n_sectors] - movb 4[di],al ! patch sector count - - mov [bx],di - mov 2[bx],es - -#ifndef __CALLER_SAVES__ - pop si - pop di -#endif - ret - -_unset_bpb: -! 0:0x78 is parameter table address - - mov ax,[bios_tabl] - mov [0x78],ax - mov ax,[bios_tabl+2] - mov [0x78+2],ax - ret - -#endasm +/************************************/ +/* Floppy disk device driver */ +/************************************/ static load_block(address, blkno) @@ -505,6 +373,8 @@ static get_now() { #asm + mov si,#5 +retry_get: xor dx,dx mov cx,[_firstsect] shr ch,#1 @@ -515,8 +385,13 @@ get_now() test ax,ax jz no_load mov ah,#2 + int $13 ! Try fetch + jnc no_load + xor ax,ax ! Bad, retry. int $13 - jc nogood + dec si + jnz retry_get + jmp nogood no_load: xor ax,ax mov [_loadcount],ax @@ -548,7 +423,47 @@ zero_block(address) #endasm } -#endif /* !HARDDISK */ +#ifdef TRY_FLOPPY +#asm +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! +! These are the number of sectors per track that will be scanned for. +! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on +! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. + +disksizes: .byte 36,21,18,15,9 + +! It seems that there is no BIOS call to get the number of sectors. Guess +! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, +! 15 if sector 15 can be read. Otherwise guess 9. + +_probe_sectors: + mov si,#disksizes ! table of sizes to try + +probe_loop: + lodsb + cbw ! extend to word + mov _n_sectors, ax + cmp al,#9 + je got_sectors ! if all else fails, try 9 + xchg ax, cx ! cx = track and sector + xor dx, dx ! drive 0, head 0 + mov bx,#probe_buf ! address after setup (es = cs) + mov ax,#0x0201 ! service 2, 1 sector + int 0x13 + jc probe_loop ! try next value +got_sectors: + + ret +#endasm +#else +probe_sectors() +{ + n_sectors = b_super.s_nzones / 80; + if( n_sectors < 5 ) n_sectors = b_super.s_nzones / 40; +} +#endif +#endif #ifdef DOTS static @@ -566,10 +481,10 @@ bios_putc(c) } #endif +#if defined(HARDDISK) && !defined(SKIPBOOT) static nogood() { -#ifdef HARDDISK #asm mov si,#fail_fs min_nextc: @@ -589,7 +504,13 @@ min_eos: ! Wait for a key then reboot fail_fs: .asciz "Inital boot failed, press return to reboot\r\n" #endasm +} + #else + +static +nogood() +{ /* This didn't work, chain the boot sector of the HD */ #asm push cs @@ -603,8 +524,8 @@ hcode: jc hcode ! Keep trying forever! jmpi BOOTADDR,0 #endasm -#endif } +#endif /****************************************************************************/ #asm @@ -616,6 +537,8 @@ end_of_part1: #endasm /****************************************************************************/ +/* Part two, code to load directories then a file into memory from the device + */ static loadprog() @@ -624,10 +547,9 @@ loadprog() bios_putc('+'); #endif if( b_super.s_magic != SUPER_MAGIC ) nogood(); - n_sectors = b_super.s_nzones / 80; - if( n_sectors < 5 ) n_sectors = b_super.s_nzones / 40; - #ifndef HARDDISK + probe_sectors(); + set_bpb(); #endif @@ -723,20 +645,80 @@ register char * p = dirptr->d_name; #endif } +#ifndef HARDDISK +#asm +_set_bpb: +bios_tabl=dosfs_stat ! Temp space. +bios_disk=dosfs_stat+4 ! + +#ifndef __CALLER_SAVES__ + push si + push di +#endif + + mov di,#bios_disk + mov bx,#0x78 +! 0:bx is parameter table address + + push ds + push di + + mov si,[bx] + mov ax,[bx+2] + mov [bios_tabl],si + mov [bios_tabl+2],ax + push ax + + pop ds +! ds:si is source + +! copy 12 bytes + mov cl,#6 + cld + rep + movsw + + pop di + pop ds + mov ax,[_n_sectors] + movb 4[di],al ! patch sector count + + mov [bx],di + mov 2[bx],es + +#ifndef __CALLER_SAVES__ + pop si + pop di +#endif + ret + +_unset_bpb: +! 0:0x78 is parameter table address + + mov ax,[bios_tabl] + mov [0x78],ax + mov ax,[bios_tabl+2] + mov [0x78+2],ax + ret + +#endasm +#endif + static runprog() { -/* This did work, run the loaded executable */ +/* It all worked, run the loaded executable */ #asm #ifdef HARDDISK mov dx,[bootpart+2] xchg dh,dl ! DX => hard drive push [bootpart] ! CX => partition offset + xor si,si #else xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 -#endif mov si,[_n_sectors] ! Save for monitor.out +#endif mov bx,#LOADSEG mov ds,bx ! DS = loadaddress @@ -787,7 +769,9 @@ islu: libend: vars: +#ifndef HARDDISK _n_sectors: .word 0 +#endif _next_zone: .word 0 _end_zone: .word 0 _indirect: .word 0 @@ -798,7 +782,7 @@ varend: end_of_prog: if *>start+0x400 - fail + fail! Part 2 too large! endif .blkb 0x3FF+start-* @@ -807,6 +791,7 @@ end_of_prog: _b_super: .blkb 1024 _b_inode: .blkb 1024 _b_zone: .blkb 1024 +probe_buf: _directory: .blkb 32768 #endasm diff --git a/bootblocks/minix.h b/bootblocks/minix.h new file mode 100644 index 0000000..984a6bc --- /dev/null +++ b/bootblocks/minix.h @@ -0,0 +1,103 @@ +/****************************************************************************/ +/* Super block table. The root file system and every mounted file system + * has an entry here. The entry holds information about the sizes of the bit + * maps and inodes. The s_ninodes field gives the number of inodes available + * for files and directories, including the root directory. Inode 0 is + * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be + * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4 + * for files and directories. The disk layout is: + * + * Item # blocks + * boot block 1 + * super block 1 + * inode map s_imap_blocks + * zone map s_zmap_blocks + * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK + * unused whatever is needed to fill out the current zone + * data zones (s_nzones - s_firstdatazone) << s_log_zone_size + * + * A super_block slot is free if s_dev == NO_DEV. + */ + +#define BLOCK_SIZE 1024 /* # bytes in a disk block */ + +/* Flag bits for i_mode in the inode. */ +#define I_TYPE 0170000 /* this field gives inode type */ +#define I_REGULAR 0100000 /* regular file, not dir or special */ +#define I_BLOCK_SPECIAL 0060000 /* block special file */ +#define I_DIRECTORY 0040000 /* file is a directory */ +#define I_CHAR_SPECIAL 0020000 /* character special file */ +#define I_SET_UID_BIT 0004000 /* set effective uid on exec */ +#define I_SET_GID_BIT 0002000 /* set effective gid on exec */ +#define ALL_MODES 0006777 /* all bits for user, group and others */ +#define RWX_MODES 0000777 /* mode bits for RWX only */ +#define R_BIT 0000004 /* Rwx protection bit */ +#define W_BIT 0000002 /* rWx protection bit */ +#define X_BIT 0000001 /* rwX protection bit */ +#define I_NOT_ALLOC 0000000 /* this inode is free */ + +/* Type definitions */ +typedef unsigned short unshort; /* must be 16-bit unsigned */ +typedef unshort block_nr; /* block number */ +typedef unshort inode_nr; /* inode number */ +typedef unshort zone_nr; /* zone number */ +typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort, + then also unshort, else long */ + +typedef unshort sect_nr; + +typedef long zone_type; /* zone size */ +typedef unshort mask_bits; /* mode bits */ +typedef unshort dev_nr; /* major | minor device number */ +typedef char links; /* number of links to an inode */ +typedef long real_time; /* real time in seconds since Jan 1, 1970 */ +typedef long file_pos; /* position in, or length of, a file */ +typedef short uid; /* user id */ +typedef char gid; /* group id */ + +/* Tables sizes */ +#define NR_ZONE_NUMS 9 /* # zone numbers in an inode */ +#define NAME_SIZE 14 /* # bytes in a directory component */ + +/* Miscellaneous constants */ +#define SUPER_MAGIC 0x137F /* magic number contained in super-block */ + +#define BOOT_BLOCK (block_nr)0 /* block number of boot block */ +#define SUPER_BLOCK (block_nr)1 /* block number of super block */ +#define ROOT_INODE (inode_nr)1 /* inode number for root directory */ + +/* Derived sizes */ +#define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */ +#define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */ +#define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */ +#define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */ + +struct super_block { + inode_nr s_ninodes; /* # usable inodes on the minor device */ + zone_nr s_nzones; /* total device size, including bit maps etc */ + unshort s_imap_blocks; /* # of blocks used by inode bit map */ + unshort s_zmap_blocks; /* # of blocks used by zone bit map */ + zone_nr s_firstdatazone; /* number of first data zone */ + short s_log_zone_size; /* log2 of blocks/zone */ + file_pos s_max_size; /* maximum file size on this device */ + short s_magic; /* magic number to recognize super-blocks */ + +} ; + +/* Type definitions local to the File System. */ +typedef struct { /* directory entry */ + inode_nr d_inum; /* inode number */ + char d_name[NAME_SIZE]; /* character string */ +} dir_struct; + +/* Declaration of the disk inode used in rw_inode(). */ +typedef struct { /* disk inode. Memory inode is in "inotab.h" */ + mask_bits i_mode; /* file type, protection, etc. */ + uid i_uid; /* user id of the file's owner */ + file_pos i_size; /* current file size in bytes */ + real_time i_modtime; /* when was file data last changed */ + gid i_gid; /* group number */ + links i_nlinks; /* how many links to this file */ + zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */ +} d_inode; + diff --git a/bootblocks/monitor.c b/bootblocks/monitor.c index dbf2d64..5c78aaf 100644 --- a/bootblocks/monitor.c +++ b/bootblocks/monitor.c @@ -1,12 +1,11 @@ -#define VERSION "0.1.1-ALPHA" - #include <stdio.h> #include <errno.h> #include <ctype.h> #include <dos.h> #include "i86_funcs.h" #include "readfs.h" +#include "version.h" #ifdef __STANDALONE__ #define NOT_VT52COLOUR @@ -60,7 +59,7 @@ static char minibuf[2] = " "; if( x86 > 2 && !x86_emu ) /* Check some basics */ cmd_bzimage((void*)0); else - printf("System is not a 386+ in real mode, load aborted.\nUse 'bzimage' command toattempt load.\n"); + printf("System is not an 80386 compatible in real mode, load aborted.\nUse 'bzimage' command to attempt load.\n"); } for (;;) @@ -135,7 +134,11 @@ void init_prog() #ifdef VT52COLOUR printf("\033E\033Rg\033Sa\033J"); #endif - printf("Linux x86 boot monitor Version %s\n", VERSION); +#ifdef VERSION + printf("Linux x86 boot monitor, Version %s.\n", VERSION); +#else + printf("Linux x86 boot monitor.\n"); +#endif cpu_check(); mem_check(); diff --git a/bootblocks/noboot.s b/bootblocks/noboot.s new file mode 100644 index 0000000..7ab9f4e --- /dev/null +++ b/bootblocks/noboot.s @@ -0,0 +1,32 @@ + +org $7c00 + +include sysboot.s + +org dos_sysid + .ascii "PANIC" ! System ID + +org codestart + xor ax,ax + mov ds,ax + mov ss,ax + mov sp,ax + jmpi code,#0 + +no_os: + .asciz "PANIC! NO OS Found!\r\n" + +code: ! SI = pointer to error message + mov si,#no_os +nextc: + lodsb + cmp al,#0 + jz eos + mov bx,#7 + mov ah,#$E ! Can't use $13 cause that's AT+ only! + int $10 + jmp nextc +eos: ! Wait for a key then reboot + xor ax,ax + int $16 + jmpi $0,$FFFF ! Wam! Try or die! diff --git a/bootblocks/readfs.h b/bootblocks/readfs.h new file mode 100644 index 0000000..aa6b87c --- /dev/null +++ b/bootblocks/readfs.h @@ -0,0 +1,17 @@ + +/* Functions for reading from one file at a time in the root directory + * of a raw filesystem. + */ + +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +int open_file P((char * fname)); +int rewind_file P((void)); +int close_file P((void)); +long file_length P((void)); +int read_block P((char * buffer)); + diff --git a/bootblocks/standalone.c b/bootblocks/standalone.c new file mode 100644 index 0000000..57634d4 --- /dev/null +++ b/bootblocks/standalone.c @@ -0,0 +1,309 @@ + +#include <errno.h> +#asm +entry _int_80 ! Tell ld86 we really do need this file. + ! then call the init stuff before main. + + loc 1 ! Make sure the pointer is in the correct segment +auto_func: ! Label for bcc -M to work. + .word _pre_main ! Pointer to the autorun function + .word no_op ! Space filler cause segs are padded to 4 bytes. + .text ! So the function after is also in the correct seg. +#endasm + +void int_80(); + +static void pre_main() +{ + /* Set the int 0x80 pointer to here */ + __set_es(0); + __doke_es(0x80*4+0, int_80); + __doke_es(0x80*4+2, __get_cs()); + bios_coninit(); +} + +void int_80() +{ +#asm +SYS_EXIT=1 +SYS_FORK=2 +SYS_READ=3 +SYS_WRITE=4 +SYS_OPEN=5 +SYS_CLOSE=6 +SYS_CHDIR=12 +SYS_LSEEK=19 +ENOSYS=38 + + push es + push si + push di + push dx + push cx + push bx + cmp ax,#SYS_READ + jne L1 + call _func_read + jmp L0 +L1: + cmp ax,#SYS_WRITE + jne L2 + call _func_write + jmp L0 +L2: + cmp ax,#SYS_LSEEK + jne L3 + call _func_lseek + jmp L0 +L3: + cmp ax,#SYS_EXIT + jne L4 + call _func_exit + jmp L0 +L4: + mov ax,#-ENOSYS +L0: + pop bx + pop cx + pop dx + pop di + pop si + pop es + iret +#endasm +} + +func_lseek() { return -38; } + +func_write(bx,cx,dx,di,si,es) +int bx,dx; +char * cx; +{ + register int v, c; + if(bx == 1 || bx == 2) + { + for(v=dx; v>0; v--) + { + c= *cx++; + if( c == '\n') bios_putc('\r'); + bios_putc(c); + } + return dx; + } + return -EBADF; +} + +func_read(bx,cx,dx,di,si,es) +int bx,dx; +char * cx; +{ + if(bx == 0) return read_line(cx, dx); + return -EBADF; +} + +read_line(buf, len) +char * buf; +int len; +{ + int ch; + int pos=0; + + if( len == 1 ) + { + buf[0]=((ch=bios_getc())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80)); + return 1; + } + + for(ch=0;;) + { + if(ch != '\003') + { + ch = bios_getc(); + if( pos == 0 && (ch&0xFF) == 0 ) + { + buf[0] = ((ch>>8)|0x80); + return 1; + } + ch &= 0x7F; + } + if( ch == '\r' ) + { + bios_putc('\r'); bios_putc('\n'); + buf[pos++] = '\n'; + return pos; + } + if( ch >= ' ' && ch != 0x7F && pos < len-1) + bios_putc(buf[pos++] = ch); + else if( (ch == '\003' || ch == '\b') && pos > 0 ) + { + bios_putc('\b'); bios_putc(' '); bios_putc('\b'); + pos--; + } + else if( ch == '\003' ) + return 0; + else + bios_putc('\007'); + } +} + +#define CTRL(x) ((x)&0x1F) +static int last_attr = 0x07; +static int con_mode; +static int con_size = 0x184F; +static int con_colour = 0; + +bios_coninit() +{ +#asm + mov ax,#$0F00 + int $10 + mov _con_mode,ax +#endasm + if( (con_mode &0xFF) > 39 ) con_size = (con_size&0xFF00) + (con_mode&0xFF); + if( (con_mode&0xFF00) != 0x700) + con_colour = 1; +} + +bios_putc(c) +int c; +{ +static char tbuf[3]; +static int tcnt=0; + if(tcnt) + { + tbuf[tcnt++] = c; + if( tcnt < 3 && (tbuf[0] != CTRL(']') || tbuf[1] < '`' || tbuf[1] > 'p')) + return; + if( tbuf[0] == CTRL('P') ) + { + if( tbuf[1] >= 32 && tbuf[1] <= 56 + && tbuf[2] >= 32 && tbuf[2] <= 111 ) + asm_cpos((tbuf[1]-32), (tbuf[2]-32)); + } + else + { + if( tbuf[1] >= '`' ) + last_attr = ( (tbuf[1]&0xF) | (last_attr&0xF0)); + else + last_attr = ( (tbuf[2]&0xF) | ((tbuf[1]&0xF)<<4)); + + if( !con_colour ) + last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70); + } + tcnt=0; + return; + } + if( c & 0xE0 ) { asm_colour(last_attr) ; asm_putc(c); } + else switch(c) + { + case CTRL('L'): + asm_cpos(0,0); + asm_cls(); + break; + case CTRL('P'): + case CTRL(']'): + tbuf[tcnt++] = c; + break; + default: + asm_putc(c); + break; + } + return; +} + +static asm_putc(c) +{ +#asm +#if !__FIRST_ARG_IN_AX__ + mov bx,sp + mov ax,[bx+2] +#endif + mov ah,#$0E + mov bx,#7 + int $10 +#endasm +} + +static asm_colour(c) +{ +#asm +#if __FIRST_ARG_IN_AX__ + mov bx,ax +#else + mov bx,sp + mov bx,[bx+2] +#endif + mov ah,#$08 + int $10 + mov ah,#$09 + mov cx,#1 + int $10 +#endasm +} + +static asm_cls() +{ +#asm + push bp ! Bug in some old BIOS's + !mov ax,#$0500 + !int $10 + mov ax,#$0600 + mov bh,_last_attr + mov cx,#$0000 + mov dx,_con_size + int $10 + pop bp +#endasm +} + +static asm_cpos(r,c) +{ +#asm +#if __FIRST_ARG_IN_AX__ + mov bx,sp + mov dh,al + mov ax,[bx+2] + mov dl,al +#else + mov bx,sp + mov ax,[bx+2] + mov dh,al + mov ax,[bx+4] + mov dl,al +#endif + mov ah,#$02 + mov bx,#7 + int $10 +#endasm +} + +bios_getc() +{ +#asm + xor ax,ax + int $16 +#endasm +} + +static void be_safe() +{ +#asm + iret +#endasm +} + +func_exit(bx,cx,dx,di,si,es) /* AKA reboot! */ +{ + __set_es(0); + __doke_es(0xE6*4+2,__get_cs()); + __doke_es(0xE6*4+0,be_safe); +#asm + mov ax,#$FFFF + int $E6 ! Try to exit DOSEMU + mov ax,#$0040 ! If we get here we're not in dosemu. + mov es,ax + seg es + mov [$72],#$1234 ! Warm reboot. + jmpi $0000,$FFFF +#endasm +} diff --git a/bootblocks/sysboot.s b/bootblocks/sysboot.s index 3bc7c57..ee62e69 100644 --- a/bootblocks/sysboot.s +++ b/bootblocks/sysboot.s @@ -46,36 +46,11 @@ dos4_label: .blkb 11 ! Disk Label (DOS 4+) dos4_fattype: .blkb 8 ! FAT type ! -! This is where the code will be overlaid, the default is an 'oops' +! This is where the code will be overlaid, the default is a hang .blkb sysboot_start+0x3E-* public codestart codestart: - xor ax,ax - mov ds,ax - mov es,ax - mov ss,ax - mov sp,ax - jmpi sys_code+$7C00-sysboot_start,#0 - -sys_code: ! SI now has pointer to error message - mov si,#sys_no_os+$7C00-sysboot_start -sys_nextc: - lodsb - cmp al,#0 - jz sys_eos - mov bx,#7 - mov ah,#$E ! Can't use $13 cause that's AT+ only! - int $10 - jmp sys_nextc -sys_eos: ! Wait for a key then reboot - xor ax,ax - int $16 - !int $19 ! This should be OK as we haven't touched anything. - jmpi $0,$FFFF ! Wam! Try or die! - -sys_no_os: - .asciz "PANIC! NO OS Found!\r\n" - + j codestart ! Partition table public partition_1 diff --git a/bootblocks/tarboot.s b/bootblocks/tarboot.s index 0fb85d3..be68ecd 100644 --- a/bootblocks/tarboot.s +++ b/bootblocks/tarboot.s @@ -137,7 +137,11 @@ blk_uid: .blkb 8 blk_gid: .blkb 8 blk_size: .blkb 12 blk_mtime: .asciz "6141567743 " -blk_chksum: .asciz " 131141" +if DEBUG +blk_chksum: .asciz " 142273" +else +blk_chksum: .asciz " 127270" +endif blk_link: .byte 'V ! Sneaks here, overlay zero init vars on tar data. @@ -476,14 +480,16 @@ endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -if DEBUG = 0 - locn(510) ! This isn't a hard disk boot sector so don't give it an HD magic +! locn(510) ! .word 0xAA55 +if DEBUG = 0 +locn(510) .word 0 endif ! From here down is where we load stuff. +locn(512) blk_load: ! Address of block load tar_name: .blkb 100 |