#include #include #include #include #include #include /* Eliminate unnecessary code in the EXE image... */ char **__crt0_glob_function(char *arg) { return 0; } void __crt0_load_environment_file(char *progname) {} #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define SECTOR_SIZE 512 typedef int BOOL ; typedef unsigned char BYTE8 ; typedef unsigned short WORD16 ; typedef unsigned long DWORD32 ; #define PCK __attribute__((packed)) typedef struct PARAMS { WORD16 bytes_per_sctr PCK ; /* Bytes per sector */ BYTE8 sctrs_per_clust PCK ; /* Sectors per cluster */ WORD16 rsvd_sectors PCK ; /* rsvd sectors (boot sector) */ BYTE8 number_fats PCK ; /* Number of FATs */ WORD16 dir_entries PCK ; /* # root-directory entries */ WORD16 total_sctrs PCK ; /* # sectors in logical volume */ BYTE8 media_desc PCK ; /* Media descriptor byte */ WORD16 sctrs_per_fat PCK ; /* Sectors per FAT */ /* Additional information (MS/DOS 3.0) ... */ WORD16 sctrs_per_track PCK ; /* Sectors per track */ WORD16 number_heads PCK ; /* Number of heads */ DWORD32 hidden_sctrs PCK ; /* Number of hidden sectors */ /* Additional information (MS/DOS 4.0) ... */ DWORD32 ttl_sctrs_vol PCK ; /* ttl log sctrs in log volume */ BYTE8 phys_drive PCK ; /* physical drive number */ BYTE8 reserved1 PCK ; /* reserved */ BYTE8 ext_boot_sig PCK ; /* extended boot signature */ DWORD32 volume_id PCK ; /* 32-bit binary volume ID */ BYTE8 volume_label[11] PCK ; /* volume label */ BYTE8 reserved2[8] PCK ; /* reserved */ /* Additional information written by COPYBOOT.EXE ... */ WORD16 fat_nibbles PCK ; /* 4-bit Nibbles per FAT entry */ WORD16 bytes_per_clust PCK ; /* Bytes per cluster */ WORD16 dir_sector0 PCK ; /* log sctr # of 1st dir sctr */ WORD16 data_sector0 PCK ; /* log sctr # of 1st data sctr */ WORD16 dir_sectors PCK ; /* # directory sectors */ WORD16 para_per_clust PCK ; /* paragraphs per cluster */ WORD16 kb_needed PCK ; /* total memory space required */ WORD16 end_of_chain PCK ; /* end marker for FAT chain */ } PARAMS ; void Abort(char *fmt, ...) ; BOOL FAT12(int drive) ; BOOL FAT16(int drive) ; BYTE8 * GetFAT(int drive) ; BOOL Read_Sector(int drive, int sector, void *buffer) ; BOOL RW_Sector(int command, int drive, int sector, void *buffer) ; void Summary(PARAMS *p) ; void Usage(void) ; BOOL Write_Sector(int drive, int sector, void *buffer) ; BOOL summary = FALSE ; int main(int argc, char *argv[]) { static char filename[] = "BOOTLOAD.BIN" ; int target_drive, sctr_buffers, bytes_needed ; static char old[SECTOR_SIZE] ; static char new[SECTOR_SIZE] ; BOOL fat12, fat16 ; char *diskname ; PARAMS *p ; FILE *fp ; if (argc != 2) Usage() ; strupr(diskname = argv[1]) ; if (strcmp(diskname, "A") && strcmp(diskname, "A:") && strcmp(diskname, "B") && strcmp(diskname, "B:")) { Usage() ; } target_drive = diskname[0] - 'A' ; fat12 = FAT12(target_drive) ; fat16 = FAT16(target_drive) ; if (!fat12 && !fat16) { Abort("Target diskette is NOT formatted FAT12 or FAT16!\n") ; } fp = fopen(filename, "rb") ; if (!fp) Abort("Can't open file: %s\n", filename) ; if (fread(new, sizeof(new), 1, fp) != 1) { Abort("Can't read file: %s\n", filename) ; } fclose(fp) ; if (!Read_Sector(target_drive, 0, old)) { Abort("Can't read boot sector of drive %c.\n", diskname[0]) ; } memcpy(p = (PARAMS *) &new[11], &old[11], sizeof(PARAMS)) ; p->ext_boot_sig = 0x29 ; if (fat12) p->fat_nibbles = 3 ; if (fat16) p->fat_nibbles = 4 ; p->bytes_per_clust = p->bytes_per_sctr * p->sctrs_per_clust ; p->dir_sector0 = 1 + p->number_fats * p->sctrs_per_fat ; p->data_sector0 = p->dir_sector0 + (32 * p->dir_entries) / p->bytes_per_sctr ; p->dir_sectors = (32 * p->dir_entries) / p->bytes_per_sctr ; p->para_per_clust = p->bytes_per_clust / 16 ; sctr_buffers = p->dir_sectors ; if (p->sctrs_per_fat > sctr_buffers) sctr_buffers = p->sctrs_per_fat ; bytes_needed = p->bytes_per_sctr * (1 + sctr_buffers) ; p->kb_needed = (bytes_needed + 1023) / 1024 ; p->end_of_chain = fat16 ? 0xFFF0 : 0x0FF0 ; Summary(p) ; if (!Write_Sector(target_drive, 0, new)) { Abort("Can't write boot sector of drive %c.\n", diskname[0]) ; } printf("Boot loader transferred to boot sector of drive '%c'.\n", diskname[0]) ; return 0 ; } void Summary(PARAMS *p) { char label[12] ; if (!summary) return ; printf("\n") ; printf("%11d Bytes per sector\n", p->bytes_per_sctr) ; printf("%11d Sectors per cluster\n", p->sctrs_per_clust) ; printf("%11d rsvd sectors (boot sector)\n", p->rsvd_sectors) ; printf("%11d Number of FATs\n", p->number_fats) ; printf("%11d root-directory entries\n", p->dir_entries) ; printf("%11d sectors in logical volume\n", p->total_sctrs) ; printf("%11X Media descriptor byte\n", p->media_desc) ; printf("%11d Sectors per FAT\n", p->sctrs_per_fat) ; /* Additional information (MS/DOS 3.0) ... */ printf("%11d Sectors per track\n", p->sctrs_per_track) ; printf("%11d Number of heads\n", p->number_heads) ; printf("%11ld Number of hidden sectors\n", p->hidden_sctrs) ; /* Additional information (MS/DOS 4.0) ... */ printf("%11ld ttl log sctrs in log volume\n", p->ttl_sctrs_vol) ; printf("%11d physical drive number\n", p->phys_drive) ; printf("%11X reserved\n", p->reserved1) ; printf("%11X extended boot signature\n", p->ext_boot_sig) ; printf("%11lX 32-bit binary volume ID\n", p->volume_id) ; memcpy(label, p->volume_label, 11) ; label[11] = '\0' ; printf("%s volume label\n", label) ; /* Additional information written by COPYBOOT.EXE ... */ printf("%11d 4-bit Nibbles per FAT entry\n", p->fat_nibbles) ; printf("%11d Bytes per cluster\n", p->bytes_per_clust) ; printf("%11d log sctr # of 1st dir sctr\n", p->dir_sector0) ; printf("%11d log sctr # of 1st data sctr\n", p->data_sector0) ; printf("%11d directory sectors\n", p->dir_sectors) ; printf("%11d paragraphs per cluster\n", p->para_per_clust) ; printf("%11d total KB memory space required\n", p->kb_needed) ; printf("%11X end marker for FAT chain\n", p->end_of_chain) ; printf("\n") ; } BYTE8 *GetFAT(int drive) { static BYTE8 fat[SECTOR_SIZE] ; static int previous = -1 ; if (drive != previous) { if (!Read_Sector(drive, 1, fat)) { Abort("Can't read 1st sector of 1st FAT!") ; } previous = drive ; } return fat ; } BOOL FAT12(int drive) { BYTE8 *fat = GetFAT(drive) ; return fat[1] == 0xFF && fat[2] == 0xFF && fat[3] != 0xFF ; } BOOL FAT16(int drive) { BYTE8 *fat = GetFAT(drive) ; return fat[1] == 0xFF && fat[2] == 0xFF && fat[3] == 0xFF && fat[4] != 0xFF ; } BOOL RW_Sector(int command, int drive, int sector, void *buffer) { int attempt ; sector++ ; for (attempt = 0; attempt < 3; attempt++) { if (!biosdisk(command, drive, 0, 0, sector, 1, buffer)) { return TRUE ; } biosdisk(0, drive, 0, 0, 0, 0, NULL) ; } return FALSE ; } BOOL Read_Sector(int drive, int sector, void *buffer) { return RW_Sector(2, drive, sector, buffer) ; } BOOL Write_Sector(int drive, int sector, void *buffer) { return RW_Sector(3, drive, sector, buffer) ; } void Abort(char *fmt, ...) { va_list args ; va_start(args, fmt) ; vfprintf(stderr, fmt, args) ; va_end(args) ; exit(255) ; } void Usage(void) { Abort("Usage: COPYBOOT A:\n") ; }