summaryrefslogtreecommitdiff
path: root/bootblocks
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>2000-10-07 15:35:09 +0200
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:46:41 +0200
commitdfab97edd018b8904568bce77536037dd76b7507 (patch)
treefb45be914dda1e47c3d28eab6a4fc23a14c7b587 /bootblocks
parent65da95772de1633acd1bfcc7f579067bac3249af (diff)
downloaddev86-dfab97edd018b8904568bce77536037dd76b7507.tar.gz
Import Dev86src-0.15.3.tar.gzv0.15.3
Diffstat (limited to 'bootblocks')
-rw-r--r--bootblocks/makeboot.c366
-rw-r--r--bootblocks/mbr.s358
-rw-r--r--bootblocks/msdos.s29
-rw-r--r--bootblocks/sysboot.s3
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