📄 sys.c
字号:
{ union REGS regs; regs.x.ax = 0x7305; regs.h.dl = DosDrive; regs.x.bx = (short)diskReadPacket; regs.x.cx = 0xffff; regs.x.si = intno; intdos(®s, ®s); return regs.x.cflag;} /* fat32readwrite */void reset_drive(int DosDrive){ union REGS regs; regs.h.ah = 0xd; intdos(®s, ®s); regs.h.ah = 0x32; regs.h.dl = DosDrive + 1; intdos(®s, ®s);} /* reset_drive */int generic_block_ioctl(unsigned char drive, unsigned cx, unsigned char *par){ union REGS regs; regs.x.ax = 0x440d; regs.x.cx = cx; regs.x.dx = (unsigned)par; regs.h.bl = drive + 1; intdos(®s, ®s); return regs.x.cflag;} /* generic_block_ioctl */void truename(char *dest, const char *src){ union REGS regs; struct SREGS sregs; regs.h.ah = 0x60; sregs.es = FP_SEG(dest); regs.x.di = FP_OFF(dest); sregs.ds = FP_SEG(src); regs.x.si = FP_OFF(src); intdosx(®s, ®s, &sregs);} /* truename */#endifint MyAbsReadWrite(int DosDrive, int count, ULONG sector, void *buffer, int write){ struct { unsigned long sectorNumber; unsigned short count; void far *address; } diskReadPacket; diskReadPacket.sectorNumber = sector; diskReadPacket.count = count; diskReadPacket.address = buffer; if ((!write && absread(DosDrive, -1, -1, &diskReadPacket) == -1) || (write && abswrite(DosDrive, -1, -1, &diskReadPacket) == -1)) {#ifdef WITHFAT32 return fat32readwrite(DosDrive + 1, &diskReadPacket, write);#else return 0xff;#endif } return 0;} /* MyAbsReadWrite */#ifdef __WATCOMC__unsigned getextdrivespace(void far *drivename, void *buf, unsigned buf_size);#pragma aux getextdrivespace = \ "mov ax, 0x7303" \ "stc" \ "int 0x21" \ "sbb ax, ax" \ parm [es dx] [di] [cx] \ value [ax];#else /* !defined __WATCOMC__ */unsigned getextdrivespace(void *drivename, void *buf, unsigned buf_size){ union REGS regs; struct SREGS sregs; regs.x.ax = 0x7303; /* get extended drive free space */ sregs.es = FP_SEG(buf); regs.x.di = FP_OFF(buf); sregs.ds = FP_SEG(drivename); regs.x.dx = FP_OFF(drivename); regs.x.cx = buf_size; intdosx(®s, ®s, &sregs); return regs.x.ax == 0x7300 || regs.x.cflag;} /* getextdrivespace */#endif /* defined __WATCOMC__ */#ifdef __WATCOMC__/* * If BIOS has got LBA extensions, after the Int 13h call BX will be 0xAA55. * If extended disk access functions are supported, bit 0 of CX will be set. */BOOL haveLBA(void); /* return TRUE if we have LBA BIOS, FALSE otherwise */#pragma aux haveLBA = \ "mov ax, 0x4100" /* IBM/MS Int 13h Extensions - installation check */ \ "mov bx, 0x55AA" \ "mov dl, 0x80" \ "int 0x13" \ "xor ax, ax" \ "cmp bx, 0xAA55" \ "jne quit" \ "and cx, 1" \ "xchg cx, ax" \"quit:" \ modify [bx cx] \ value [ax];#elseBOOL haveLBA(void){ union REGS r; r.x.ax = 0x4100; r.x.bx = 0x55AA; r.h.dl = 0x80; int86(0x13, &r, &r); return r.x.bx == 0xAA55 && r.x.cx & 1;}#endifvoid 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 struct bootsectortype32 *bs32;#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 */ 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) { printf("can't read old boot sector for drive %c:\n", drive + 'A'); exit(1); }#ifdef DDEBUG printf("Old Boot Sector:\n"); dump_sector(oldboot);#endif bs = (struct bootsectortype *)&oldboot; if (bs->bsBytesPerSec != SEC_SIZE) { printf("Sector size is not 512 but %d bytes - not currently supported!\n", bs->bsBytesPerSec); exit(1); /* Japan?! */ } { /* see "FAT: General Overview of On-Disk Format" v1.02, 5.V.1999 * (http://www.nondot.org/sabre/os/files/FileSystems/FatFormat.pdf) */ ULONG fatSize, totalSectors, dataSectors, clusters; UCOUNT rootDirSectors; bs32 = (struct bootsectortype32 *)&oldboot; rootDirSectors = (bs->bsRootDirEnts * DIRENT_SIZE /* 32 */ + bs32->bsBytesPerSec - 1) / bs32->bsBytesPerSec; fatSize = bs32->bsFATsecs ? bs32->bsFATsecs : bs32->bsBigFatSize; totalSectors = bs32->bsSectors ? bs32->bsSectors : bs32->bsHugeSectors; dataSectors = totalSectors - bs32->bsResSectors - (bs32->bsFATs * fatSize) - rootDirSectors; clusters = dataSectors / bs32->bsSecPerClust; if (clusters < FAT_MAGIC) /* < 4085 */ fs = FAT12; else if (clusters < FAT_MAGIC16) /* < 65525 */ fs = FAT16; else fs = FAT32; } /* 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 printf("SYS hasn't been compiled with FAT32 support.\n" "Consider using -DWITHFAT32 option.\n"); exit(1);#endif } 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); } /* Copy disk parameter from old sector to new sector */#ifdef WITHFAT32 if (fs == FAT32) memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE32); else#endif memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE); bs = (struct bootsectortype *)&newboot; memcpy(bs->OemName, "FreeDOS ", 8);#ifdef WITHFAT32 if (fs == FAT32) { bs32 = (struct bootsectortype32 *)&newboot; /* put 0 for A: or B: (force booting from A:), otherwise use DL */ bs32->bsDriveNumber = drive < 2 ? 0 : 0xff; /* the location of the "0060" segment portion of the far pointer in the boot sector is just before cont: in boot*.asm. This happens to be offset 0x78 (=0x3c * 2) for FAT32 and offset 0x5c (=0x2e * 2) for FAT16 */ /* i.e. BE CAREFUL WHEN YOU CHANGE THE BOOT SECTORS !!! */ ((int *)newboot)[0x3C] = load_seg;#ifdef DEBUG printf(" FAT starts at sector %lx + %x\n", bs32->bsHiddenSecs, bs32->bsResSectors);#endif } else#endif { /* put 0 for A: or B: (force booting from A:), otherwise use DL */ bs->bsDriveNumber = drive < 2 ? 0 : 0xff; ((int *)newboot)[0x2E] = load_seg; }#ifdef DEBUG /* add an option to display this on user request? */ printf("Root dir entries = %u\n", bs->bsRootDirEnts); printf("FAT starts at sector (%lu + %u)\n", bs->bsHiddenSecs, bs->bsResSectors); printf("Root directory starts at sector (PREVIOUS + %u * %u)\n", bs->bsFATsecs, bs->bsFATs);#endif { int i = 0; memset(&newboot[0x1f1], ' ', 11); while (kernel_name[i] && kernel_name[i] != '.') { if (i < 8) newboot[0x1f1+i] = toupper(kernel_name[i]); i++; } if (kernel_name[i] == '.') { /* copy extension */ int j = 0; i++; while (kernel_name[i+j] && j < 3) { newboot[0x1f9+j] = toupper(kernel_name[i+j]); j++; } } }#ifdef DEBUG /* there's a zero past the kernel name in all boot sectors */ printf("Boot sector kernel name set to %s\n", &newboot[0x1f1]); printf("Boot sector load segment set to %Xh\n", load_seg);#endif#ifdef DDEBUG printf("\nNew Boot Sector:\n"); dump_sector(newboot);#endif if ((bsFile == NULL) || both) {#ifdef DEBUG printf("writing new bootsector to drive %c:\n", drive + 'A');#endif /* write newboot to a drive */ if (MyAbsReadWrite(drive, 1, 0, newboot, 1) != 0) { printf("Can't write new boot sector to drive %c:\n", drive + 'A'); exit(1); } } /* if write boot sector */ if (bsFile != NULL) { int fd;#ifdef DEBUG printf("writing new bootsector to file %s\n", bsFile);#endif /* write newboot to bsFile */ if ((fd = /* suggestion: do not trunc - allows to write to images */ open(bsFile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, S_IREAD | S_IWRITE)) < 0) { printf(" %s: can't create\"%s\"\nDOS errnum %d", pgm, bsFile, errno); exit(1); } if (write(fd, newboot, SEC_SIZE) != SEC_SIZE) { printf("Can't write %u bytes to %s\n", SEC_SIZE, bsFile); close(fd); unlink(bsFile); exit(1); } close(fd); } /* if write boot sector file */ reset_drive(drive); /* unlock_drive */ generic_block_ioctl((unsigned char)drive + 1, 0x86a, NULL);} /* put_boot *//* * Returns TRUE if `drive` has at least `bytes` free space, FALSE otherwise. * put_sector() must have been already called to determine file system type. */BOOL check_space(COUNT drive, ULONG bytes){#ifdef WITHFAT32 if (fs == FAT32) { char *drivename = "A:\\"; drivename[0] = 'A' + drive; getextdrivespace(drivename, &x, sizeof(x)); return x.xfs_freeclusters > (bytes / (x.xfs_clussize * x.xfs_secsize)); } else#endif {#ifdef __TURBOC__ struct dfree df; getdfree(drive + 1, &df); return (ULONG)df.df_avail * df.df_sclus * df.df_bsec >= bytes;#else struct _diskfree_t df; _dos_getdiskfree(drive + 1, &df); return (ULONG)df.avail_clusters * df.sectors_per_cluster * df.bytes_per_sector >= bytes;#endif }} /* check_space */BYTE copybuffer[COPY_SIZE];BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file){ static BYTE dest[SYS_MAXPATH], source[SYS_MAXPATH]; unsigned ret; int fdin, fdout; ULONG copied = 0; struct stat fstatbuf; strcpy(source, srcPath); if (rootPath != NULL) /* trick for comspec */ strcat(source, file); if (stat(source, &fstatbuf)) { printf("%s: \"%s\" not found\n", pgm, source); if ((rootPath != NULL) && (*rootPath) /* && (errno == ENOENT) */ ) { sprintf(source, "%s%s", rootPath, file); printf("%s: Trying \"%s\"\n", pgm, source); if (stat(source, &fstatbuf)) { printf("%s: \"%s\" not found\n", pgm, source); return FALSE; } } else return FALSE; } truename(dest, source); strcpy(source, dest); sprintf(dest, "%c:\\%s", 'A' + drive, file); if (stricmp(source, dest) == 0) { printf("%s: source and destination are identical: skipping \"%s\"\n", pgm, source); return TRUE; } if ((fdin = open(source, O_RDONLY | O_BINARY)) < 0) { printf("%s: failed to open \"%s\"\n", pgm, source); return FALSE; } if (!check_space(drive, filelength(fdin))) { printf("%s: Not enough space to transfer %s\n", pgm, file); close(fdin); exit(1); } if ((fdout = open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, S_IREAD | S_IWRITE)) < 0) { printf(" %s: can't create\"%s\"\nDOS errnum %d", pgm, dest, errno); close(fdin); return FALSE; } while ((ret = read(fdin, copybuffer, COPY_SIZE)) > 0) { if (write(fdout, copybuffer, ret) != ret) { printf("Can't write %u bytes to %s\n", ret, dest); close(fdout); unlink(dest); break; } copied += ret; } {#if defined __WATCOMC__ || defined _MSC_VER /* || defined __BORLANDC__ */ unsigned short date, time; _dos_getftime(fdin, &date, &time); _dos_setftime(fdout, date, time);#elif defined __TURBOC__ struct ftime ftime; getftime(fdin, &ftime); setftime(fdout, &ftime);#endif } close(fdin); close(fdout);#ifdef __SOME_OTHER_COMPILER__ {#include <utime.h> struct utimbuf utimb; utimb.actime = /* access time */ utimb.modtime = fstatbuf.st_mtime; /* modification time */ utime(dest, &utimb); };#endif printf("%lu Bytes transferred", copied); return TRUE;} /* copy */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -