From e7f0852dbd8d12a4abe47cb7659acfaefe09ecaa Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Sat, 31 Jan 2004 15:01:40 +0000 Subject: [PATCH] correct sectors/track, head and hidden sector values if the boot sector disagrees with the default bpb (unless the default bpb says that the number of hidden sectors is zero (usual for floppies)). introduce generic_block_ioctl() function to handle all 0x440d ioctls (inclusive locking) git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@763 6ac86273-5f31-0410-b378-82cca8765d1b --- sys/sys.c | 95 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/sys/sys.c b/sys/sys.c index 317b1ac..af59665 100644 --- a/sys/sys.c +++ b/sys/sys.c @@ -29,7 +29,7 @@ #define DEBUG /* #define DDEBUG */ -#define SYS_VERSION "v3.0" +#define SYS_VERSION "v3.1" #include #include @@ -471,28 +471,20 @@ void reset_drive(int DosDrive); parm [dx] \ modify [ax bx]; -void lock_drive(int DosDrive); -#pragma aux lock_drive = \ - "mov ax,0x440d" \ - "mov cx,0x84a" \ - "xor dx,dx" \ - "inc bx" \ - "int 0x21" \ - parm [bx]; - -void unlock_drive(int DosDrive); -#pragma aux unlock_drive = \ - "mov ax,0x440d" \ - "mov cx,0x86a" \ - "inc bx" \ - "int 0x21" \ - parm [bx]; - void truename(char far *dest, const char *src); #pragma aux truename = \ "mov ah,0x60" \ "int 0x21" \ parm [es di] [si]; + +int generic_block_ioctl(unsigned char drive, unsigned cx, unsigned char *par); +#pragma aux generic_block_ioctl = \ + "mov ax, 0x440d" \ + "int 0x21" \ + "sbb ax, ax" \ + value [ax] \ + parm [bl] [cx] [dx]; + #else #ifndef __TURBOC__ @@ -543,26 +535,17 @@ void reset_drive(int DosDrive) intdos(®s, ®s); } /* reset_drive */ -void lock_drive(int DosDrive) +int generic_block_ioctl(unsigned char drive, unsigned cx, unsigned char *par) { union REGS regs; regs.x.ax = 0x440d; - regs.x.cx = 0x84a; - regs.x.dx = 0; - regs.h.bl = DosDrive + 1; + regs.x.cx = cx; + regs.x.dx = (unsigned)par; + regs.h.bl = drive + 1; intdos(®s, ®s); -} /* lock_drive */ - -void unlock_drive(int DosDrive) -{ - union REGS regs; - - regs.x.ax = 0x440d; - regs.x.cx = 0x86a; - regs.h.bl = DosDrive + 1; - intdos(®s, ®s); -} /* unlock_drive */ + return regs.x.cflag; +} /* generic_block_ioctl */ void truename(char *dest, const char *src) { @@ -669,6 +652,26 @@ BOOL haveLBA(void) } #endif +void correct_bpb(struct bootsectortype *default_bpb, + struct bootsectortype *oldboot) +{ + /* don't touch partitions (floppies most likely) that don't have hidden + sectors */ + if (default_bpb->bsHiddenSecs == 0) + return; +#ifdef DEBUG + printf("Old boot sector values: sectors/track: %u, heads: %u, hidden: %lu\n", + oldboot->bsSecPerTrack, oldboot->bsHeads, oldboot->bsHiddenSecs); + printf("Default and new boot sector values: sectors/track: %u, heads: %u, " + "hidden: %lu\n", default_bpb->bsSecPerTrack, default_bpb->bsHeads, + default_bpb->bsHiddenSecs); +#endif + + oldboot->bsSecPerTrack = default_bpb->bsSecPerTrack; + oldboot->bsHeads = default_bpb->bsHeads; + oldboot->bsHiddenSecs = default_bpb->bsHiddenSecs; +} + void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both) { #ifdef WITHFAT32 @@ -676,12 +679,15 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both #endif struct bootsectortype *bs; static unsigned char oldboot[SEC_SIZE], newboot[SEC_SIZE]; + static unsigned char default_bpb[0x5c]; #ifdef DEBUG printf("Reading old bootsector from drive %c:\n", drive + 'A'); #endif - lock_drive(drive); + /* lock drive */ + generic_block_ioctl((unsigned char)drive + 1, 0x84a, NULL); + reset_drive(drive); /* suggestion: allow reading from a boot sector or image file here */ if (MyAbsReadWrite(drive, 1, 0, oldboot, 0) != 0) @@ -727,10 +733,22 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both bs->bsBytesPerSec); exit(1); /* Japan?! */ } - + + /* bit 0 set if function to use current BPB, clear if Device + BIOS Parameter Block field contains new default BPB + bit 1 set if function to use track layout fields only + must be clear if CL=60h + bit 2 set if all sectors in track same size (should be set) (RBIL) */ + default_bpb[0] = 4; + if (fs == FAT32) { printf("FAT type: FAT32\n"); + /* get default bpb (but not for floppies) */ + if (drive >= 2 && + generic_block_ioctl((unsigned char)drive + 1, 0x4860, default_bpb) == 0) + correct_bpb((struct bootsectortype *)(default_bpb + 7 - 11), bs); + #ifdef WITHFAT32 /* copy one of the FAT32 boot sectors */ memcpy(newboot, haveLBA() ? fat32lba : fat32chs, SEC_SIZE); #else @@ -742,6 +760,9 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both else { /* copy the FAT12/16 CHS+LBA boot sector */ printf("FAT type: FAT1%c\n", fs + '0' - 10); + if (drive >= 2 && + generic_block_ioctl((unsigned char)drive + 1, 0x860, default_bpb) == 0) + correct_bpb((struct bootsectortype *)(default_bpb + 7 - 11), bs); memcpy(newboot, fs == FAT16 ? fat16com : fat12com, SEC_SIZE); } @@ -864,7 +885,9 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both close(fd); } /* if write boot sector file */ reset_drive(drive); - unlock_drive(drive); + + /* unlock_drive */ + generic_block_ioctl((unsigned char)drive + 1, 0x86a, NULL); } /* put_boot */