📄 sys.c
字号:
/*************************************************************** sys.c DOS-C sys utility for DOS-C Copyright (c) 1991 Pasquale J. Villani All Rights Reserved This file is part of DOS-C. DOS-C is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. DOS-C is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DOS-C; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************/#define DEBUG/* #define DDEBUG */#define SYS_VERSION "v3.2"#include <stdlib.h>#include <dos.h>#include <ctype.h>#include <fcntl.h>#include <sys/stat.h>#ifdef __TURBOC__#include <mem.h>#else#include <memory.h>#endif#include <string.h>#ifdef __TURBOC__#include <dir.h>#endif#define SYS_MAXPATH 260#include "portab.h"#include "algnbyte.h"#include "device.h"#include "dcb.h"#include "xstructs.h"#include "date.h"#include "../hdr/time.h"#include "fat.h"/* These definitions deliberately put here instead of * #including <stdio.h> to make executable MUCH smaller * using [s]printf from prf.c! */extern int VA_CDECL printf(const char * fmt, ...);extern int VA_CDECL sprintf(char * buff, const char * fmt, ...);#include "fat12com.h"#include "fat16com.h"#ifdef WITHFAT32#include "fat32chs.h"#include "fat32lba.h"#endif#ifndef __WATCOMC__#include <io.h>#elselong filelength(int __handle);#pragma aux filelength = \ "mov ax, 0x4202" \ "xor cx, cx" \ "xor dx, dx" \ "int 0x21" \ "push ax" \ "push dx" \ "mov ax, 0x4200" \ "xor cx, cx" \ "xor dx, dx" \ "int 0x21" \ "pop dx" \ "pop ax" \ parm [bx] \ modify [cx] \ value [dx ax];extern int unlink(const char *pathname);/* some non-conforming functions to make the executable smaller */int open(const char *pathname, int flags, ...){ int handle; int result = (flags & O_CREAT ? _dos_creat(pathname, _A_NORMAL, &handle) : _dos_open(pathname, flags & (O_RDONLY | O_WRONLY | O_RDWR), &handle)); return (result == 0 ? handle : -1);}int read(int fd, void *buf, unsigned count){ unsigned bytes; int result = _dos_read(fd, buf, count, &bytes); return (result == 0 ? bytes : -1);}int write(int fd, const void *buf, unsigned count){ unsigned bytes; int result = _dos_write(fd, buf, count, &bytes); return (result == 0 ? bytes : -1);}#define close _dos_closeint stat(const char *file_name, struct stat *buf){ struct find_t find_tbuf; UNREFERENCED_PARAMETER(buf); return _dos_findfirst(file_name, _A_NORMAL | _A_HIDDEN | _A_SYSTEM, &find_tbuf);}/* WATCOM's getenv is case-insensitive which wastes a lot of space for our purposes. So here's a simple case-sensitive one */char *getenv(const char *name){ char **envp, *ep; const char *np; char ec, nc; for (envp = environ; (ep = *envp) != NULL; envp++) { np = name; do { ec = *ep++; nc = *np++; if (nc == 0) { if (ec == '=') return ep; break; } } while (ec == nc); } return NULL;}#endifBYTE pgm[] = "SYS";void put_boot(int, char *, char *, int, int);BOOL check_space(COUNT, ULONG);BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file);#define SEC_SIZE 512#define COPY_SIZE 0x7e00struct bootsectortype { UBYTE bsJump[3]; char OemName[8]; UWORD bsBytesPerSec; UBYTE bsSecPerClust; UWORD bsResSectors; UBYTE bsFATs; UWORD bsRootDirEnts; UWORD bsSectors; UBYTE bsMedia; UWORD bsFATsecs; UWORD bsSecPerTrack; UWORD bsHeads; ULONG bsHiddenSecs; ULONG bsHugeSectors; UBYTE bsDriveNumber; UBYTE bsReserved1; UBYTE bsBootSignature; ULONG bsVolumeID; char bsVolumeLabel[11]; char bsFileSysType[8];};struct bootsectortype32 { UBYTE bsJump[3]; char OemName[8]; UWORD bsBytesPerSec; UBYTE bsSecPerClust; UWORD bsResSectors; UBYTE bsFATs; UWORD bsRootDirEnts; UWORD bsSectors; UBYTE bsMedia; UWORD bsFATsecs; UWORD bsSecPerTrack; UWORD bsHeads; ULONG bsHiddenSecs; ULONG bsHugeSectors; ULONG bsBigFatSize; UBYTE bsFlags; UBYTE bsMajorVersion; UWORD bsMinorVersion; ULONG bsRootCluster; UWORD bsFSInfoSector; UWORD bsBackupBoot; ULONG bsReserved2[3]; UBYTE bsDriveNumber; UBYTE bsReserved3; UBYTE bsExtendedSignature; ULONG bsSerialNumber; char bsVolumeLabel[11]; char bsFileSystemID[8];};/* * globals needed by put_boot & check_space */enum {FAT12 = 12, FAT16 = 16, FAT32 = 32} fs; /* file system type *//* static */ struct xfreespace x; /* we make this static to be 0 by default - this avoids FAT misdetections */#define SBOFFSET 11#define SBSIZE (sizeof(struct bootsectortype) - SBOFFSET)#define SBSIZE32 (sizeof(struct bootsectortype32) - SBOFFSET)/* essentially - verify alignment on byte boundaries at compile time */struct VerifyBootSectorSize { char failure1[sizeof(struct bootsectortype) == 62 ? 1 : -1]; char failure2[sizeof(struct bootsectortype) == 62 ? 1 : 0];/* (Watcom has a nice warning for this, by the way) */};int FDKrnConfigMain(int argc, char **argv);int main(int argc, char **argv){ COUNT drive; /* destination drive */ COUNT drivearg = 0; /* drive argument position */ COUNT srcarg = 0; /* source argument position */ BYTE *bsFile = NULL; /* user specified destination boot sector */ unsigned srcDrive; /* source drive */ BYTE srcPath[SYS_MAXPATH]; /* user specified source drive and/or path */ BYTE rootPath[4]; /* alternate source path to try if not '\0' */ WORD slen; int argno = 0; int bootonly = 0; int both = 0; char *kernel_name = "KERNEL.SYS"; int load_segment = 0x60; printf("FreeDOS System Installer " SYS_VERSION ", " __DATE__ "\n\n"); if (argc > 1 && memicmp(argv[1], "CONFIG", 6) == 0) { exit(FDKrnConfigMain(argc, argv)); } for(argno = 1; argno < argc; argno++) { char *argp = argv[argno]; if (argp[1] == ':' && argp[2] == '\0' && drivearg <= srcarg) drivearg = argno; if (srcarg == 0) { srcarg = argno; } else if (argp[0] == '/' && toupper(argp[1]) == 'K' && argno + 1 < argc) { argno++; kernel_name = argv[argno]; } else if (argp[0] == '/' && toupper(argp[1]) == 'L' && argno + 1 < argc) { argno++; load_segment = (int)strtol(argv[argno], NULL, 16); } else if (memicmp(argp, "BOOTONLY", 8) == 0 && !bootonly) { bootonly = 1; } else if (memicmp(argp, "BOTH", 4) == 0 && !both) { both = 1; } else if (drivearg != argno) { if (bsFile == NULL) { bsFile = argp; } else { drivearg = 0; break; } } } if (drivearg == 0) { printf( "Usage: %s [source] drive: [bootsect [BOTH]] [BOOTONLY] [/K name] [/L segm]\n" " source = A:,B:,C:\\KERNEL\\BIN\\,etc., or current directory if not given\n" " drive = A,B,etc.\n" " bootsect = name of 512-byte boot sector file image for drive:\n" " to write to *instead* of real boot sector\n" " BOTH : write to *both* the real boot sector and the image file\n" " BOOTONLY : do *not* copy kernel / shell, only update boot sector or image\n" " /K name : name of kernel to use instead of KERNEL.SYS\n" " /L segm : hex load segment to use instead of 60\n" "%s CONFIG /help\n", pgm, pgm); exit(1); } drive = toupper(argv[drivearg][0]) - 'A'; if (drive < 0 || drive >= 26) { printf("%s: drive %c must be A:..Z:\n", pgm, *argv[(argc == 3 ? 2 : 1)]); exit(1); } srcPath[0] = '\0'; if (drivearg > srcarg && srcarg) { strncpy(srcPath, argv[srcarg], SYS_MAXPATH - 12); /* leave room for COMMAND.COM\0 */ srcPath[SYS_MAXPATH - 13] = '\0'; /* make sure srcPath + "file" is a valid path */ slen = strlen(srcPath); if ((srcPath[slen - 1] != ':') && ((srcPath[slen - 1] != '\\') || (srcPath[slen - 1] != '/'))) { srcPath[slen] = '\\'; slen++; srcPath[slen] = '\0'; } } /* Get source drive */ if ((strlen(srcPath) > 1) && (srcPath[1] == ':')) /* src specifies drive */ srcDrive = toupper(*srcPath) - 'A'; else /* src doesn't specify drive, so assume current drive */ {#ifdef __TURBOC__ srcDrive = (unsigned) getdisk();#else _dos_getdrive(&srcDrive); srcDrive--;#endif } /* Don't try root if src==dst drive or source path given */ if ((drive == srcDrive) || (*srcPath && ((srcPath[1] != ':') || ((srcPath[1] == ':') && srcPath[2])))) *rootPath = '\0'; else sprintf(rootPath, "%c:\\", 'A' + srcDrive); printf("Processing boot sector...\n"); put_boot(drive, bsFile, kernel_name, load_segment, both); if (!bootonly) { printf("\nCopying %s...\n", kernel_name); if (!copy(drive, srcPath, rootPath, kernel_name)) { printf("\n%s: cannot copy \"%s\"\n", pgm, kernel_name); exit(1); } /* copy kernel */ printf("\nCopying COMMAND.COM...\n"); if (!copy(drive, srcPath, rootPath, "COMMAND.COM")) { char *comspec = getenv("COMSPEC"); if (comspec != NULL) { printf("%s: Trying \"%s\"\n", pgm, comspec); if (!copy(drive, comspec, NULL, "COMMAND.COM")) comspec = NULL; } if (comspec == NULL) { printf("\n%s: cannot copy \"COMMAND.COM\"\n", pgm); exit(1); } } /* copy shell */ } printf("\nSystem transferred.\n"); return 0;}#ifdef DDEBUGVOID dump_sector(unsigned char far * sec){ COUNT x, y; char c; for (x = 0; x < 32; x++) { printf("%03X ", x * 16); for (y = 0; y < 16; y++) { printf("%02X ", sec[x * 16 + y]); } for (y = 0; y < 16; y++) { c = sec[x * 16 + y]; if (isprint(c)) printf("%c", c); else printf("."); } printf("\n"); } printf("\n");}#endif#ifdef __WATCOMC__int absread(int DosDrive, int nsects, int foo, void *diskReadPacket);#pragma aux absread = \ "push bp" \ "int 0x25" \ "sbb ax, ax" \ "popf" \ "pop bp" \ parm [ax] [cx] [dx] [bx] \ modify [si di] \ value [ax];int abswrite(int DosDrive, int nsects, int foo, void *diskReadPacket);#pragma aux abswrite = \ "push bp" \ "int 0x26" \ "sbb ax, ax" \ "popf" \ "pop bp" \ parm [ax] [cx] [dx] [bx] \ modify [si di] \ value [ax];int fat32readwrite(int DosDrive, void *diskReadPacket, unsigned intno);#pragma aux fat32readwrite = \ "mov ax, 0x7305" \ "mov cx, 0xffff" \ "int 0x21" \ "sbb ax, ax" \ parm [dx] [bx] [si] \ modify [cx dx si] \ value [ax];void reset_drive(int DosDrive);#pragma aux reset_drive = \ "push ds" \ "inc dx" \ "mov ah, 0xd" \ "int 0x21" \ "mov ah,0x32" \ "int 0x21" \ "pop ds" \ parm [dx] \ modify [ax 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__int2526readwrite(int DosDrive, void *diskReadPacket, unsigned intno){ union REGS regs; regs.h.al = (BYTE) DosDrive; regs.x.bx = (short)diskReadPacket; regs.x.cx = 0xffff; int86(intno, ®s, ®s); return regs.x.cflag;}#define absread(DosDrive, foo, cx, diskReadPacket) \int2526readwrite(DosDrive, diskReadPacket, 0x25)#define abswrite(DosDrive, foo, cx, diskReadPacket) \int2526readwrite(DosDrive, diskReadPacket, 0x26)#endiffat32readwrite(int DosDrive, void *diskReadPacket, unsigned intno)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -