diff options
author | Robert de Bath <rdebath@poboxes.com> | 2000-10-07 15:35:09 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:46:41 +0200 |
commit | dfab97edd018b8904568bce77536037dd76b7507 (patch) | |
tree | fb45be914dda1e47c3d28eab6a4fc23a14c7b587 /bootblocks | |
parent | 65da95772de1633acd1bfcc7f579067bac3249af (diff) | |
download | dev86-dfab97edd018b8904568bce77536037dd76b7507.tar.gz |
Import Dev86src-0.15.3.tar.gzv0.15.3
Diffstat (limited to 'bootblocks')
-rw-r--r-- | bootblocks/makeboot.c | 366 | ||||
-rw-r--r-- | bootblocks/mbr.s | 358 | ||||
-rw-r--r-- | bootblocks/msdos.s | 29 | ||||
-rw-r--r-- | bootblocks/sysboot.s | 3 |
4 files changed, 591 insertions, 165 deletions
diff --git a/bootblocks/makeboot.c b/bootblocks/makeboot.c index e45fa4a..77403c3 100644 --- a/bootblocks/makeboot.c +++ b/bootblocks/makeboot.c @@ -17,11 +17,11 @@ unsigned char buffer[1024]; #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_DOS 1 /* Bootsector needs 'normal' DOS FS */ +#define FS_ADOS 2 /* Bootsector likes any DOS FS */ #define FS_TAR 3 /* Bootsector needs GNU-tar volume label */ -#define FS_STAT 4 /* DOS bootsector is checked */ -#define FS_ZERO 5 /* Boot sector must be Zapped */ +#define FS_STAT 4 /* Any bootsector is checked */ +#define FS_ZERO 5 /* Boot sector must be already Zapped */ #define FS_MBR 6 /* Boot sector is an MBR */ #ifndef __MSDOS__ @@ -40,29 +40,35 @@ struct bblist { } bblocks[] = { { "tar", "Bootable GNU tar volume lable", tarboot_data, tarboot_size, 0, 0, FS_TAR}, -{ "dosfs","Boot file BOOTFILE.SYS from dos floppy", +{ "dos12","Boot file BOOTFILE.SYS from dos floppy", msdos_data, msdos_size, 1, msdos_boot_name-msdos_start, FS_DOS, 12}, -{ "dos16","Boot file BOOTFILE.SYS from 16 bit dos filesystem", +{ "dos16","Boot file BOOTFILE.SYS from FAT16 hard disk or floppy", msdos16_data, msdos16_size, 1, msdos16_boot_name-msdos16_start, FS_DOS, 16}, -{ "none", "No OS bootblock, just message", +{ "none", "No OS bootblock, just display message", noboot_data, noboot_size, - 2, noboot_boot_message-noboot_start, FS_DOS}, + 2, noboot_boot_message-noboot_start, FS_ADOS}, { "skip", "Bypasses floppy boot with message", skip_data, skip_size, - 2, skip_mesg-skip_start, FS_DOS}, + 2, skip_mesg-skip_start, FS_ADOS}, { "minix","Minix floppy FS booter", minix_data, minix_size, 2, minix_bootfile-minix_start, FS_ZERO}, { "hdmin","Minix Hard disk FS booter", minixhd_data, minixhd_size, 2, minixhd_bootfile-minixhd_start, FS_ZERO}, +#ifdef mbr_Banner +{ "mbr", "Master boot record for HD (with optional message)", + mbr_data,mbr_size, + 2, mbr_Banner-mbr_start, FS_MBR}, +#else { "mbr", "Master boot record for HD", mbr_data,mbr_size, 0, 0, FS_MBR}, +#endif { "stat", "Display dosfs superblock", 0, 0, 0, 0, FS_STAT}, -{ "copy", "Copy boot block to makeboot.sav", +{ "copy", "Copy boot block to makeboot.sav or named file", 0, 0, 0, 0, FS_STAT}, { "Zap", "Clear boot block to NULs", 0, 1024, 0, 0, FS_NONE}, @@ -121,9 +127,10 @@ char ** argv; switch(ptr->fstype) { case FS_NONE: /* override */ - break; - case FS_DOS: case FS_STAT: + case FS_ADOS: + break; + case FS_DOS: check_msdos(); if(ptr->fsmod) check_simpledos(ptr->fsmod); break; @@ -145,12 +152,14 @@ char ** argv; switch(ptr->fstype) { case FS_STAT: - print_super(buffer); if( strcmp(ptr->name, "copy") == 0 ) save_super(buffer); + else + print_super(buffer); close_disk(); exit(0); case FS_DOS: + case FS_ADOS: for(i=0; i<sysboot_dosfs_stat; i++) buffer[i] = ptr->data[i]; for(i=sysboot_codestart; i<512; i++) @@ -186,7 +195,7 @@ char ** argv; set_asciz(ptr->boot_name); break; default: - fprintf(stderr, "Cannot specify boot file for this block\n"); + fprintf(stderr, "Cannot specify boot name for this block\n"); exit(1); } @@ -212,11 +221,12 @@ Usage() progname = "makeboot"; #ifdef __MSDOS__ - fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] a:\n", progname); + fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] a:\n\n", progname); + fprintf(stderr, "The 'a:' can be any drive or file or @: for the MBR.\n"); #else - fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] /dev/fd0\n", progname); + fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] /dev/fd0\n\n", progname); #endif - fprintf(stderr, "\nThe bootname is a filename to use with the block,\n"); + fprintf(stderr, "The bootname is a filename or message to use with the block,\n"); fprintf(stderr, "the blocks are:\n"); for(;ptr->name; ptr++) fprintf(stderr, "\t%s\t%s\n", ptr->name, ptr->desc); @@ -233,14 +243,22 @@ char * diskname; /* Freedos fix */ if( diskname[2] == '\r' ) diskname[2] = 0; - 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; } + if( diskname[2] == 0 && diskname[1] == ':' ) + { + if (isalpha(diskname[0])) { + disktype = toupper(diskname[0])-'A'+1; + return 0; + } + if (diskname[0] =='@') { + disktype = 129; + return 0; + } + } #endif disktype = 0; - diskfd = fopen(diskname, "r+"); - if( diskfd == 0 ) diskfd = fopen(diskname, "r"); + diskfd = fopen(diskname, "r+b"); + if( diskfd == 0 ) diskfd = fopen(diskname, "rb"); + if( diskfd == 0 && force ) diskfd = fopen(diskname, "w+b"); if( diskfd == 0 ) { fprintf(stderr, "Cannot open '%s'\n", diskname); @@ -262,7 +280,7 @@ int sectno; char * loadaddr; { #ifdef __MSDOS__ - if( disktype == 1 || disktype == 2 ) + if( disktype == 1 || disktype == 2 || disktype == 129 ) { int tries, rv; int s,h,c; @@ -271,11 +289,29 @@ char * loadaddr; c = sectno/disk_sect/disk_head; for(tries=0; tries<6; tries++) - if( (rv = dos_sect_write(disktype-1, c, h, s, loadaddr)) == 0 ) + if( (rv = bios_sect_write(disktype-1, c, h, s, loadaddr)) == 0 ) + break; + if( rv ) + { + if (rv/256 == 3) + fprintf(stderr, "Write protect error writing sector %d\n", sectno); + else + fprintf(stderr, "Error writing sector %d, (%d)\n", sectno, rv/256); + return -1; + } + return 0; + } + if( disktype ) + { + int tries, rv; + + for(tries=0; tries<6; tries++) + if( (rv = dos_sect_write(disktype-1, sectno, loadaddr)) == 0 ) break; if( rv ) { - fprintf(stderr, "Error writing sector %d, (%d)\n", sectno, rv/256); + fprintf(stderr, "Error writing sector %d, (0x%04d)\n", sectno, rv); + memset(loadaddr, '\0', 512); return -1; } return 0; @@ -303,7 +339,7 @@ char * loadaddr; { int cc; #ifdef __MSDOS__ - if( disktype == 1 || disktype == 2 ) + if( disktype == 1 || disktype == 2 || disktype == 129 ) { int tries, rv; int s,h,c; @@ -312,7 +348,7 @@ char * loadaddr; c = sectno/disk_sect/disk_head; for(tries=0; tries<6; tries++) - if( (rv = dos_sect_read(disktype-1, c, h, s, loadaddr)) == 0 ) + if( (rv = bios_sect_read(disktype-1, c, h, s, loadaddr)) == 0 ) break; if( rv ) { @@ -322,6 +358,21 @@ char * loadaddr; } return 0; } + if( disktype ) + { + int tries, rv; + + for(tries=0; tries<6; tries++) + if( (rv = dos_sect_read(disktype-1, sectno, loadaddr)) == 0 ) + break; + if( rv ) + { + fprintf(stderr, "Error reading sector %d, (0x%04d)\n", sectno, rv); + memset(loadaddr, '\0', 512); + return -1; + } + return 0; + } #endif if( disktype ) { @@ -337,10 +388,11 @@ char * loadaddr; } return 0; } + /**************************************************************************/ #ifdef __MSDOS__ -dos_sect_read(drv, track, head, sector, loadaddr) +bios_sect_read(drv, track, head, sector, loadaddr) { #asm push bp @@ -349,26 +401,24 @@ dos_sect_read(drv, track, head, sector, loadaddr) push ds pop es - 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] + mov dh,[bp+2+_bios_sect_read.head] + mov dl,[bp+2+_bios_sect_read.drv] + mov cl,[bp+2+_bios_sect_read.sector] + mov ch,[bp+2+_bios_sect_read.track] - mov bx,[bp+2+_dos_sect_read.loadaddr] + mov bx,[bp+2+_bios_sect_read.loadaddr] mov ax,#$0201 int $13 - jc read_err + jc bios_read_err mov ax,#0 -read_err: +bios_read_err: pop bp #endasm } -#endif -#ifdef __MSDOS__ -dos_sect_write(drv, track, head, sector, loadaddr) +bios_sect_write(drv, track, head, sector, loadaddr) { #asm push bp @@ -377,18 +427,18 @@ dos_sect_write(drv, track, head, sector, loadaddr) 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 dh,[bp+2+_bios_sect_write.head] + mov dl,[bp+2+_bios_sect_write.drv] + mov cl,[bp+2+_bios_sect_write.sector] + mov ch,[bp+2+_bios_sect_write.track] - mov bx,[bp+2+_dos_sect_write.loadaddr] + mov bx,[bp+2+_bios_sect_write.loadaddr] mov ax,#$0301 int $13 - jc write_err + jc bios_write_err mov ax,#0 -write_err: +bios_write_err: pop bp #endasm @@ -397,6 +447,112 @@ write_err: /**************************************************************************/ +#ifdef __MSDOS__ + +/* All this mess just to read one sector!! */ + +struct disk_packet { + long sector; + int count; + long addr; +} disk_packet; + +dos_sect_read(drv, sector, loadaddr) +{ +#asm + push bp + mov bp,sp + + mov al,[bp+2+_dos_sect_read.drv] + mov cx,#1 + mov dx,[bp+2+_dos_sect_read.sector] + mov bx,[bp+2+_dos_sect_read.loadaddr] + + int $25 + pop bx + jnc dos_read_ok + + mov bp,sp + + ! Fill the disk packet + mov ax,[bp+2+_dos_sect_read.sector] + mov [_disk_packet],ax + xor ax,ax + mov [_disk_packet+2],ax + inc ax + mov [_disk_packet+4],ax + mov ax,[bp+2+_dos_sect_read.loadaddr] + mov [_disk_packet+6],ax + mov ax,ds + mov [_disk_packet+8],ax + + mov dl,[bp+2+_dos_sect_read.drv] + inc dl + mov bx,#_disk_packet + mov cx,#0xFFFF + mov si,#0 + mov ax,#0x7305 + + int $21 + + jc dos_read_err +dos_read_ok: + mov ax,#0 +dos_read_err: + + pop bp +#endasm +} + +dos_sect_write(drv, sector, loadaddr) +{ +#asm + push bp + mov bp,sp + + mov al,[bp+2+_dos_sect_write.drv] + mov cx,#1 + mov dx,[bp+2+_dos_sect_write.sector] + mov bx,[bp+2+_dos_sect_write.loadaddr] + + int $26 + pop bx + jnc dos_write_ok + + mov bp,sp + + ! Fill the disk packet + mov ax,[bp+2+_dos_sect_write.sector] + mov [_disk_packet],ax + xor ax,ax + mov [_disk_packet+2],ax + inc ax + mov [_disk_packet+4],ax + mov ax,[bp+2+_dos_sect_write.loadaddr] + mov [_disk_packet+6],ax + mov ax,ds + mov [_disk_packet+8],ax + + mov dl,[bp+2+_dos_sect_write.drv] + inc dl + mov bx,#_disk_packet + mov cx,#0xFFFF + mov si,#1 + mov ax,#0x7305 + + int $21 + + jc dos_write_err +dos_write_ok: + mov ax,#0 +dos_write_err: + + pop bp +#endasm +} +#endif +/**************************************************************************/ + check_zapped() { int i; @@ -551,12 +707,21 @@ copy_tarblock() #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 +#define DOS7_MAXSECT 17 +#define DOS7_FAT32LEN 18 +#define DOS7_FLAGS 19 +#define DOS7_VERSION 20 +#define DOS7_ROOT_CLUST 21 +#define DOS7_INFO_SECT 22 +#define DOS7_BOOT2 23 + struct bootfields { int offset; int length; @@ -577,11 +742,21 @@ struct bootfields { { 0x18, 2, 0}, { 0x1A, 2, 0}, { 0x1C, 4, 0}, - { 0x20, 4, 0}, + + { 0x20, 4, 0}, /* DOS4+ */ { 0x24, 1, 0}, { 0x27, 4, 0}, { 0x2B, 11, 0}, { 0x36, 8, 0}, + + { 0x20, 4, 0}, /* DOS7 FAT32 */ + { 0x24, 4, 0}, + { 0x28, 2, 0}, + { 0x2A, 2, 0}, + { 0x2C, 4, 0}, + { 0x30, 2, 0}, + { 0x32, 2, 0}, + { -1,0,0} }; @@ -595,24 +770,39 @@ static char * fieldnames[] = { "Reserved sectors", "FAT count", "Root dir entries", - "Sector count (=0 if large FS)", + "Sector count", "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", + + "FAT32 FS sector count", + "FAT32 FAT length", + "FAT32 Flags", + "FAT32 version", + "FAT32 Root Cluster", + "FAT32 Info Sector", + "FAT32 Backup Boot", + 0 }; int i; + long numclust = 0xFFFF; + int fatbits = 0; + int fat_len = -1; for(i=0; dosflds[i].offset >= 0; i++) { - printf("%-35s", fieldnames[i]); + if( i>= DOS4_MAXSECT && (fat_len==0) != (i>=DOS7_MAXSECT) ) + continue; + if( dosflds[i].length <= 4 ) { long v = 0; int j; @@ -620,11 +810,23 @@ static char * fieldnames[] = { { v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] )); } - printf("%ld\n", v); + + if( i==DOS_FATLEN ) + fat_len = v; + + if (v==0 && + (i==DOS_FATLEN || i==DOS_MAXSECT || i==DOS4_MAXSECT || i==DOS_NROOT)) + continue; + + printf("%-35s%ld\n", fieldnames[i], v); + + if (i==DOS_SECT && v!=512 && v!=1024 && v!=2048) + break; } else { int ch, j; + printf("%-35s", fieldnames[i]); for(j=0; j<dosflds[i].length; j++) { ch = bootsect[dosflds[i].offset+j]; @@ -643,6 +845,13 @@ char * bootsect; for(i=0; dosflds[i].offset >= 0; i++) { + if( i>= DOS4_MAXSECT && + (dosflds[DOS_FATLEN].value==0) != (i>=DOS7_MAXSECT) ) + { + dosflds[i].lvalue = dosflds[i].value = 0; + continue; + } + if( dosflds[i].length <= 4 ) { long v = 0; int j; @@ -654,7 +863,7 @@ char * bootsect; dosflds[i].lvalue = v; } else - dosflds[i].value = 0; + dosflds[i].lvalue = dosflds[i].value = 0; } } @@ -680,7 +889,10 @@ check_msdos() dosflds[DOS_CLUST].value = 1; if( dosflds[DOS_MEDIA].value < 0xF0 ) - fprintf(stderr, "Dos media descriptor is invalid\n"); + { + if (!force) + 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"); @@ -728,7 +940,7 @@ check_msdos() check_simpledos(bb_fatbits) int bb_fatbits; { - unsigned numclust = 0xFFFF; + long numclust = 0xFFFF; char * err = 0; int fatbits = 0; @@ -739,19 +951,24 @@ int bb_fatbits; - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value - ((dosflds[DOS_NROOT].value+15)/16) ) / dosflds[DOS_CLUST].value + 2; - else + else if( dosflds[DOS4_MAXSECT].value > 0 ) numclust = ( dosflds[DOS4_MAXSECT].lvalue - dosflds[DOS_RESV].value - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value - ((dosflds[DOS_NROOT].value+15)/16) ) / dosflds[DOS_CLUST].value + 2; + else + numclust = ( dosflds[DOS7_MAXSECT].lvalue + - dosflds[DOS_RESV].value + - dosflds[DOS_NFAT].value * dosflds[DOS7_FAT32LEN].value + ) / dosflds[DOS_CLUST].value; if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT12", 5) == 0 ) fatbits=12; else if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT16", 5) == 0 ) fatbits=16; else - fatbits=12+4*(numclust > 0xFF0); + fatbits=12+4*(numclust > 0xFF0) + 16*(numclust > 0xFFF0L); if( dosflds[DOS_NFAT].value > 2 ) err = "Too many fat copies on disk"; @@ -759,15 +976,19 @@ int bb_fatbits; 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( fatbits == 16 && numclust < 0xFF0 ) + err = "Weirdness, FAT16 but less than $FF0 clusters"; else if( fatbits != bb_fatbits ) err = "Filesystem has the wrong fat type for this bootblock."; else if( numclust * dosflds[DOS_CLUST].lvalue / dosflds[DOS_SPT].value > 65535 ) - err = "Maximum of 65535 tracks allowed, sorry"; + err = "Boot sector untested with more than 65535 tracks"; if( !err && bb_fatbits == 12 ) { - if( (0x7C00-msdos_start-512)/512 < dosflds[DOS_FATLEN].value ) + if( dosflds[DOS4_PHY_DRIVE].value != 0 ) + err = "This boot sector is only for floppies"; + else if( (0x7C00-msdos_start-512)/512 < dosflds[DOS_FATLEN].value ) err = "The FAT is too large to load in the available space."; else if( dosflds[DOS_RESV].value + dosflds[DOS_FATLEN].value > dosflds[DOS_SPT].value ) @@ -819,7 +1040,7 @@ int boot_name; if( strlen(boot_id) > i ) { - fprintf(stderr, "Filename '%s' is too long for bootblock\n"); + fprintf(stderr, "Name '%s' is too long for bootblock\n"); exit(1); } else @@ -840,6 +1061,10 @@ int boot_name; default: buffer[j++] = boot_id[i]; break; } } +#ifdef __MSDOS__ + else if(boot_id[i] == '_') buffer[j++] = ' '; + else if(boot_id[i] == '^') { buffer[j++] = '\r'; buffer[j++] = '\n'; } +#endif else buffer[j++] = boot_id[i]; } buffer[j] = 0; @@ -857,28 +1082,37 @@ check_mbr() if( buffer[i] ) break; + /* Check for Disk Manager partition tables */ + if( buffer[252] == 0xAA && buffer[253] == 0x55 ) + { + if( (unsigned char)mbr_data[252] != 0xAA || mbr_data[253] != 0x55 ) + i = 252; + } + if( i != 512 ) { if(force) - fprintf(stderr, "That doesn't look like an MBR zapping\n"); + fprintf(stderr, "That doesn't look like a compatible MBR but ...\n"); else { - fprintf(stderr, "That doesn't look like an MBR, -f will zap\n"); + fprintf(stderr, "That doesn't look like a compatible MBR\n"); exit(1); } - - memset(buffer, '\0', 512); } } copy_mbr(mbr_data) char * mbr_data; { - if( buffer[252] != 0xAA || buffer[253] != 0x55 ) + if( buffer[252] != 0xAA || buffer[253] != 0x55 || + (unsigned char)mbr_data[252] != 0xAA || mbr_data[253] != 0x55 ) memcpy(buffer, mbr_data, 446); else memcpy(buffer, mbr_data, 254); - memcpy(buffer+510, mbr_data+510, 2); + + buffer[510] = 0x55; + buffer[511] = 0xAA; + write_zero = 1; } /**************************************************************************/ @@ -1142,7 +1376,7 @@ do_2m_write() #ifdef HAS_2M20 else if( disk_trck != 82 || disk_sect != 22 ) { - fprintf(stderr, "To be bootable a 2M disk must be 22 sectors 82 tracks or formatted with 2m20.\n"); + fprintf(stderr, "To be bootable a 2M disk must be 22 sectors 82 tracks or formatted with DOS 2m.\n"); if( !force ) exit(1); fprintf(stderr, "But I'll try it\n"); } @@ -1166,7 +1400,7 @@ do_2m_write() write_sector(bs_offset+i/512+1, program_2m_vsn_20+i); } #else - fprintf(stderr, "To be bootable a 2M disk must be formatted with the 2m20 device driver.\n"); + fprintf(stderr, "To be bootable a 2M disk must be formatted with the DOS 2m driver.\n"); exit(1); #endif } diff --git a/bootblocks/mbr.s b/bootblocks/mbr.s index 3a22984..113bb51 100644 --- a/bootblocks/mbr.s +++ b/bootblocks/mbr.s @@ -3,37 +3,38 @@ ! This BB successfully boots MSDOS or Linux. ! ! In addition it has the facility to load and execute a small program -! (of 8 extents) before the boot blocks are checked. +! before the boot blocks are checked. ! ! Or ! -! Space for 12 extra partitions in a form that Linux _does_ understand. +! Space for 12 extra partitions in the 'DiskManager' form that Linux +! _does_ understand. ! +! NB: This needs Dev86 0.15.2 or later ! Lowest available is $0500, MSDOS appears to use $0600 ... I wonder why? ORGADDR=$0500 preboot=0 ! Include the pre-boot loader. -diskman=1 ! Disk manager partitions, allows 16 partitions but +mbrkey=0 ! Option to choose the boot record base on keystroke +message=0 ! Display boot message +diskman=0 ! Disk manager partitions, allows 16 partitions but ! don't overwrite this with a LILO BB. -! Include standard layout -org ORGADDR -include sysboot.s - -public partition_1 -public partition_2 -public partition_3 -public partition_4 +linear=0 ! Use the linear addresses not the CHS ones - if diskman=0 -org ORGADDR+$3 -.ascii "ELKS MBR Copyright 1996, Robert de Bath" +partition_start=ORGADDR+0x1BE +partition_size=0x10 +partition_end=ORGADDR+0x1FE -! Start after dos fsstat data, not strictly required. -org codestart + if diskman + ! Partition table start ... + table_start=ORGADDR+0xFC + low_partition=table_start+2 else -org ORGADDR + table_start=partition_start endif + +org ORGADDR cli ! Assume _nothing_! cld mov bx,#$7C00 ! Pointer to start of BB. @@ -51,52 +52,38 @@ org ORGADDR cont: sti ! Let the interrupts back in. -! -! Next check for a pre-boot load. - +! Next check for a pre-boot load or a keypress + if message + call disp_message + endif if preboot - push bx - mov si,#pre_boot_table - lodsw - mov di,ax ! First word is execute address -more_boot: - lodsw - test ax,ax - jz load_done - mov bx,ax ! word 1 address - lodsw - mov cx,ax ! word 2 CX, head/sector - lodsw - mov dx,ax ! word 3 DX, drive, cylinder - lodsw ! word 4 AX, $02, sector count - int $13 - jnc more_boot ! This doesn't retry, with a HD it shouldn't be bad. - jc disk_error -load_done: - call di -exec_done: - pop bx + call preboot_code + endif + if mbrkey + call key_wait endif ! Now check the partition table, must use SI as pointer cause that's what the ! partition boot blocks expect. - mov si,#partition_1 + mov si,#partition_start check_active: cmp byte [si],#$80 ! Flag for activated partition jz found_active + if mbrkey=0 bad_boot: - add si,#partition_2-partition_1 - cmp si,#bootblock_magic + endif + add si,#partition_size + cmp si,#partition_end jnz check_active - ! Check for Disk manager partitions (12 more!) + ! Check for Disk manager partitions in the order that Linux numbers them. if diskman cmp word ptr diskman_magic,#$55AA jnz no_diskman - mov si,#partition_1 + mov si,#partition_start check_next: - sub si,#partition_2-partition_1 + sub si,#partition_size cmp byte [si],#$80 ! Flag for activated partition jz found_active cmp si,#low_partition @@ -109,10 +96,14 @@ no_diskman: jmp no_boot found_active: + if linear + call linearise + else mov di,#6 ! Max retries, int list says 3 ... double it mov dx,[si] ! dh = Drive head, dl = $80 ie HD drive 0 mov cx,[si+2] ! cx = Sector & head encoded for int $13 - ! bx is correct + ! bx is correct at $7C00 + endif retry: movb [$7DFE],#0 ! Clear magic for dosemu mov ax,#$0201 ! Read 1 sector @@ -126,9 +117,8 @@ retry: dec di jnz retry ! Try again -disk_error: mov si,#disk_read_error - jmp no_boot ! Sorry it ain't gonna work. + jmp no_boot ! Sorry it ain't gonna work. sector_loaded: mov di,#$7DFE ! End of sector loaded @@ -139,6 +129,19 @@ sector_loaded: jmpi #$7C00,#0 ! Go! ! Fatal errors ........... + if mbrkey +bad_boot: + mov si,#no_bootpart +no_boot: ! SI now has pointer to error message + call puts + mov si,#crlf + call puts +tick: + call key_wait + j tick + + else + no_boot: ! SI now has pointer to error message lodsb cmp al,#0 @@ -156,65 +159,242 @@ EOS: keyboot: ! Wait for a key then reboot xor ax,ax int $16 - int $19 ! This should be OK as we haven't touched anything. +! int $19 ! This rarely does anything useful... jmpi $0,$FFFF ! Wam! Try or die! -no_bootpart: - .asciz "No bootable partition" -disk_read_error: - .asciz "Error loading system" press_key: - .asciz "\r\nPress a key to reboot" + .asciz "\r\nPress return:" press_end: + endif + +no_bootpart: + .asciz "No active partition" +disk_read_error: + .asciz "Disk read error" + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! Instead of loading using the CHS data in the ptbl use the linear addr +! + if linear +linearise: + mov di,#6 ! Max retries, int list says 3 ... double it + mov dx,[si] ! dh = Drive head, dl = $80 ie HD drive 0 + mov cx,[si+2] ! cx = Sector & head encoded for int $13 + ! bx is correct at $7C00 + + fail! Todo ... + ret + endif + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! Choose the partition based on a pressed key ... + + if mbrkey +key_wait: + mov si,#Prompt + call puts + mov di,#19 ! Wait for 18-19 ticks + +next_loop: + mov ah,#1 + int $16 + jnz Got_key + mov ah,#0 + int $1A ! Get current tick + cmp dx,si ! If changed DEC our counter. + jz next_loop + mov si,dx + dec di + jnz next_loop + + mov si,#Unprompt ! Nothing has happened, return. + call puts + +bad_key: + ret + +Got_key: + cmp al,#$20 + jnz not_space + mov si,#Pause + j showit +not_space: + mov Showkey,al + mov si,#Showkey +showit: + call puts + + mov ah,#0 ! Clean the kbd buffer. + int $16 + + ! ... Now we use our key ... + ! 0 => Floppy + ! 1 .. 4 => Hard disk partition. + + mov di,#-1 + cmp al,#$20 + jz next_loop + and ax,#0xF + + jnz not_floppy + mov si,#floppy_part + br found_active + +not_floppy: + dec ax + test ax,#0xC + jnz bad_key + + mov cl,#4 + shl ax,cl + add ax,#partition_start + mov si,ax + +! Set active flag for disk interrupt. + or byte [si],#$80 + + br found_active + +puts: + lodsb + cmp al,#0 + jz EOS + push bx + mov bx,#7 + mov ah,#$E ! Can't use $13 cause that's AT+ only! + int $10 + pop bx + jmp puts +EOS: + ret + +Prompt: + .asciz "MBR: " +Unprompt: + .asciz "\b\b\b\b\b \b\b\b\b\b" +Pause: + .asciz "\b\b> " +Showkey: + .ascii " " +crlf: + .asciz "\r\n" +floppy_part: + .word 0,1 + + endif + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! + if message +disp_message: + mov si,#Banner + + if mbrkey + br puts + else + +puts: + lodsb + cmp al,#0 + jz .EOS + push bx + mov bx,#7 + mov ah,#$E ! Can't use $13 cause that's AT+ only! + int $10 + pop bx + jmp puts +.EOS: + ret + endif +export Banner +Banner: + .asciz "" + endif +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! This is the pre-boot loader it uses CHS but that's ok for track 0 +! if preboot +public preboot_code +preboot_code: + push bx + mov si,#pre_boot_table + lodsw + mov di,ax ! First word is execute address +more_boot: + lodsw + test ah,ah + jz load_done + mov bx,ax ! word 1 address + lodsw + mov cx,ax ! word 2 CX, head/sector + lodsw + mov dx,ax ! word 3 DX, drive, cylinder + lodsw ! word 4 AX, $02, sector count + int $13 + jnc more_boot ! This doesn't retry, with a HD it shouldn't be bad. + + mov si,#disk_read_error + br no_boot ! Sorry it ain't gonna work. +load_done: + call di +exec_done: + pop bx + return: ret export pre_boot_table pre_boot_table: + ! Example: Do nothing. + .word return,0 + + ! Labels + ! .word <execute address> + ! Then repeat .. + ! .word <BX>, <CX>, <DX>, <AX> + ! Finally + ! .word 0 + ! Example: Load rest of H0,C0 into mem at $7C00 (8k). - ! .word $7C00, $7C00,$0002,$0000,$0210, $0000 - .word return - .word 0 + ! .word $7C00, $7C00,$0002,$8000,$0210, $0000 + + ! Example: Use single LBA call + ! .word <execute address> + ! .word 0,0,$8000,$4200, $0010 + ! .word <number of blocks> + ! .long <transfer buffer> + ! .long <start block number> + ! .long <start block number high 4 bytes> endif - if diskman +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! Now make sure this isn't too big! + if *>table_start + fail! Partition table overlaps + endif +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! The diskman magic number and empty DM partitions. + if diskman org ORGADDR+0xFC public diskman_magic diskman_magic: .word 0xAA55 -low_partition: -public partition_16 -partition_16 = low_partition+0x00 -public partition_15 -partition_15 = low_partition+0x10 -public partition_14 -partition_14 = low_partition+0x20 -public partition_13 -partition_13 = low_partition+0x30 -public partition_12 -partition_12 = low_partition+0x40 -public partition_11 -partition_11 = low_partition+0x50 -public partition_10 -partition_10 = low_partition+0x60 -public partition_9 -partition_9 = low_partition+0x70 -public partition_8 -partition_8 = low_partition+0x80 -public partition_7 -partition_7 = low_partition+0x90 -public partition_6 -partition_6 = low_partition+0xA0 -public partition_5 -partition_5 = low_partition+0xB0 + .blkb 12*partition_size-1 + .byte 0 + endif + +!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +! And finally a copyright message if there's room. + if *<ORGADDR+0x180 + org ORGADDR+0x180 +.asciz "ELKS MBR " +.asciz "Robert de Bath," +.asciz "Copyright 1996-2000." + org partition_start-1 + .byte 0xFF endif -! Now make sure this isn't to big! - if *>partition_1 - fail! Partition overlap - endif !THE END diff --git a/bootblocks/msdos.s b/bootblocks/msdos.s index f291b6b..b9f02a9 100644 --- a/bootblocks/msdos.s +++ b/bootblocks/msdos.s @@ -19,10 +19,9 @@ ! ! All these are true for mtools created floppies on normal PC drives. ! -! In addition this now has a compile time option for 16 bit FAT floppies -! TODO: Hard partition (dos_hidden != 0) -! Zip disks (floppy with dos_hidden != 0) -! Auto detect disk type +! In addition this now has a compile time option for FAT16 partitions. +! TODO: Auto detect disk type +! FAT32 ! !--------------------------------------------------------------------------- ORGADDR=$0500 @@ -37,6 +36,13 @@ fatbits=12 ! Set to 12 or 16 (16 for LS-120 disks) export heads heads=0 ! This can be 0,1 or 2. 0 is dynamic. +export harddisk + if fatbits=12 +harddisk=0 + else +harddisk=1 ! Allow for hard disks, but will only work with + endif ! disks formatted >= MSDOS 4.0 + !--------------------------------------------------------------------------- ! Absolute position macro, fails if code before it is too big. macro locn @@ -185,6 +191,9 @@ linsect2: and al,#$C0 or cl,al endif + if harddisk + mov dl,[dos4_phy_drive] + endif ret !--------------------------------------------------------------------------- @@ -332,13 +341,18 @@ got_fsect: !--------------------------------------------------------------------------- ! File is now loaded, execute it. maincode: + if harddisk=0 mov bx,#7 mov ax,#$0E3E int $10 ! Marker printed to say bootblock succeeded. + endif xor dx,dx ! DX=0 => floppy drive + if harddisk + mov dl,[dos4_phy_drive] + endif push dx ! CX=0 => partition offset = 0 - mov si,[dos_spt] ! SI=Sectors pet track + mov si,[dos_spt] ! SI=Sectors per track mov bx,#LOADSEG mov ds,bx ! DS = loadaddress @@ -390,12 +404,9 @@ boot_name: name_end: ! NNNNNNNNEEE -if fatbits =16 locn(510) - .word 0 ! This is a floppy so it should not need the magic _but_ + .word $AA55 ! This is a floppy so it should not need the magic _but_ ! the debian MBR requires the magic even on floppies - ! so only clear on a superfloppy (LS-120). -endif fat_table: ! This is the location that the fat table is loaded. ! Note: The fat must be entirely on track zero if 12 bit. diff --git a/bootblocks/sysboot.s b/bootblocks/sysboot.s index 558d02e..baac806 100644 --- a/bootblocks/sysboot.s +++ b/bootblocks/sysboot.s @@ -35,12 +35,13 @@ 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: .blkw 2 ! Large FS sector count dos4_phy_drive: .blkb 1 ! Phys drive .blkb 1 ! Reserved .blkb 1 ! DOS 4 + +floppy_temp: dos4_serial: .blkw 2 ! Serial number dos4_label: .blkb 11 ! Disk Label (DOS 4+) dos4_fattype: .blkb 8 ! FAT type |