home *** CD-ROM | disk | FTP | other *** search
- #include "part.h"
- #include <bios.h>
- #include <dos.h>
- #include <malloc.h>
- #include <errno.h>
-
- BOOT *master_boot_rec, /* master boot record of currently selected disk */
- *part_boot_rec[4]; /* boot record of each (active) logical partition */
-
- static word start_mode, start_page;
- byte changed_parms; /* if this byte is set, save_tbl (below) has
- * a ptr to the original (BIOS or whatever)
- * disk table, and must be reset.
- */
- DISK_TABLE far *fd_tbl,
- far *save_tbl;
-
- byte num_disks,
- fixed_disk,
- _numsecs;
- word _shprod;
- extern word sector_size;
- PARTDATA part_data[4];
- extern int dotrans(dword relsect,word startsec,void *buf,word numsec,word op);
-
- void
- init() /* initialize tables from a given physical disk */
- {
- static byte _init = 0;
- static word old_sector_size = 0;
- struct diskinfo_t diskinfo;
- int i;
-
- /* if first time through, fill num_disks */
- if(! _init) {
- _init = 1;
- diskinfo.drive = fixed_disk;
- _bios_disk(8,&diskinfo);
- if((num_disks = diskinfo.drive) == 0) {
- fprintf(stderr,"No fixed disks attached.\n");
- exit(1);
- /* NOTREACHED */
- }
- if(num_disks==1 && fixed_disk==DISK1) {
- fprintf(stderr,"Only one disk attached.\n");
- exit(2);
- /* NOTREACHED */
- }
- start_page = scr_gapage();
- scr_sapage(0);
- start_mode = scr_gmode();
- switch(start_mode) {
- case 0:
- case 5:
- case 6:
- scr_smode(2);
- break;
- case 1:
- case 4:
- scr_smode(3);
- break;
- }
- master_boot_rec = (BOOT *)malloc(sector_size);
- for(i=0;i<4;i++)
- part_boot_rec[i] = (BOOT *)malloc(sector_size);
- }
- else {
- if(old_sector_size != sector_size) {
- master_boot_rec = (BOOT *)realloc(master_boot_rec,sector_size);
- for(i=0; i<4; i++)
- part_boot_rec[i] = (BOOT *)realloc(part_boot_rec[i],sector_size);
- }
- if(changed_parms) {
- /* we cast the table vector as a pointer to a far interrupt handler
- * function returning void, since that is what _dos_setvect expects.
- */
- _dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
- (void (interrupt far *)()) save_tbl
- );
- diskinfo.drive = changed_parms;
- _bios_disk(0x09, &diskinfo); /* reset drive pair vector */
- diskinfo.drive = changed_parms;
- _bios_disk(0, &diskinfo); /* reset drive */
- changed_parms = 0;
- }
- }
-
- old_sector_size = sector_size;
- fd_tbl = (DISK_TABLE far *) _dos_getvect(fixed_disk==DISK1 ? 0x46 : 0x41);
- _numsecs = fd_tbl->fd_sec_per_track;
- _shprod = _numsecs * fd_tbl->fd_heads;
- boot_transfer(READ,0);
- for(i=0; i<4; i++) {
- if((part_data[i].sys_ind = master_boot_rec->ptable[i].sys_ind) != 0) {
- part_data[i].s_cylinder=get_cyl(master_boot_rec->ptable[i].s_sec_cyl);
- part_data[i].e_cylinder=get_cyl(master_boot_rec->ptable[i].e_sec_cyl);
- boot_transfer(READ,i+1);
- }
- }
- }
-
- void
- clean_quit()
- {
- struct diskinfo_t diskinfo;
-
- if(changed_parms) {
- _dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
- (void (interrupt far *)()) save_tbl
- );
- diskinfo.drive = changed_parms;
- _bios_disk(0x09, &diskinfo); /* reset drive pair vector */
- diskinfo.drive = changed_parms;
- _bios_disk(0, &diskinfo); /* reset drive */
- changed_parms = 0;
- }
- scr_sapage(start_page);
- scr_smode(start_mode);
- exit(0);
- /* NOTREACHED */
- }
-
- int
- make_fat(partno, fat_size, secs_in_rdir) /* make FAT (two copies) */
- int partno,
- fat_size;
- word secs_in_rdir;
- {
- int i;
- word *fatbuf, numsecs, offset, data_offset, secs_per_clus, secs_in_part;
- byte *fatbuf2, *scratch;
- BPB *bptr = &part_boot_rec[partno]->bpb;
- dword relsec = master_boot_rec->ptable[partno].rel_sect;
- extern word lineno;
-
- numsecs = bptr->secs_in_fat;
- data_offset = numsecs*2 + secs_in_rdir + bptr->res_sectors;
- secs_in_part = bptr->nsectors;
- secs_per_clus = (word) bptr->secs_per_au;
- scratch = malloc(sector_size*secs_per_clus);
- #ifdef DEBUG
- printf("numsecs %d, offset %d, part_size %d\n",numsecs,data_offset,secs_in_part);
- fflush(stdout);
- #endif
- if(!(fatbuf = (word *)calloc(numsecs,sector_size))) {
- errno = ENOMEM;
- return(0);
- /* NOTREACHED */
- }
- fatbuf2 = (byte *)fatbuf;
- if(fat_size == 12) {
- fatbuf[0] = 0xfff8;
- fatbuf[1] = 0x00ff;
- }
- else {
- fatbuf[0] = 0xfff8;
- fatbuf[1] = 0xffff;
- }
- /* get a list of sectors that can't be read -- presumably result of lo
- * level formatting. Mark off appropriate cluster as bad.
- */
- #ifndef DEBUG
- scr_pos(lineno,42);
- printf("Sector:");
- for(offset=data_offset; offset <= secs_in_part; offset += secs_per_clus) {
- word i;
-
- i = (offset+secs_per_clus <= secs_in_part) ? secs_per_clus :
- (secs_in_part-offset+1);
- scr_pos(lineno,50);
- printf("%u",offset-data_offset);
- fflush(stdout);
- if(dotrans(relsec,offset,scratch, i, READ)) {
- /* got a bad sector */
- word cnum = (offset - data_offset)/secs_per_clus + 2;
-
- if(fat_size == 12) {
- /* byte offset into cluster array is cnum*3/2 */
- word *cptr = (word *)(fatbuf2 + ((cnum*3) >> 1));
-
- *cptr |= (cnum & 1) ? 0xff70 : 0xff7;
- }
- else
- fatbuf[cnum] = 0xfff7;
- }
- }
- #endif
- for(i=0; i<2; i++)
- #ifndef DEBUG
- if(dotrans(relsec,(i*numsecs)+1,fatbuf,numsecs,WRITE) < 0) {
- errno = EINVAL;
- return(0);
- /* NOTREACHED */
- }
- #else
- printf("Writing FAT, relsec 0x%lxL, whither 0x%x, count %d\n",
- relsec,(i*numsecs)+1,numsecs);
- fflush(stdout); (void) getch();
- #endif
- free(scratch);
- free(fatbuf);
- return(numsecs);
- }
-
- int
- make_rdir(partno) /* make the root directory */
- int partno;
- {
- int numsecs, offset;
- word *buf, csize, temp;
- BPB *bptr = &part_boot_rec[partno]->bpb;
- dword relsec = master_boot_rec->ptable[partno].rel_sect;
-
- offset = (bptr->secs_in_fat << 1) + 1;
- numsecs = (bptr->nroot_ents+15)/16;
- csize = (word) bptr->secs_per_au;
- if((temp = numsecs % csize) != 0)
- numsecs += csize-temp;
- if((buf = (word *)calloc(numsecs,sector_size)) == NULL) {
- errno = ENOMEM;
- return(0);
- /* NOTREACHED */
- }
- #ifndef DEBUG
- if(dotrans(relsec,offset,buf,numsecs, WRITE) < 0) {
- errno = EINVAL;
- return(0);
- /* NOTREACHED */
- }
- #else
- printf("Writing directory, relsec (long) 0x%lx, whither 0x%x, count %d\n", relsec,offset,numsecs);
- fflush(stdout); getch();
- #endif
- free(buf);
- return(numsecs);
- }
-
- #ifdef BT_IN_C
- void
- boot_transfer(op, idx)
- word op, /* either READ or WRITE */
- idx; /* 0=master boot record, 1-5=partition */
- {
- union REGS fregs;
- struct SREGS segreg;
-
- if(idx) {
- PARTITION *pptr;
-
- pptr = & master_boot_rec->ptable[--idx];
- fregs.x.bx = (unsigned) part_boot_rec[idx];
- segreg.es = FP_SEG(part_boot_rec[idx]);
- fregs.x.cx = pptr->s_sec_cyl; /* cylinder 0, sector 1 */
- fregs.h.dh = pptr->s_head; /* head 0 */
- }
- else {
- fregs.x.bx = (unsigned) master_boot_rec;
- segreg.es = FP_SEG(master_boot_rec);
- fregs.x.cx = 0x0001; /* cylinder 0, sector 1 */
- fregs.h.dh = 0; /* head 0 */
- }
- fregs.h.ah = op; /* what to do */
- fregs.h.al = 1; /* do 1 sector */
- fregs.h.dl = fixed_disk;
- int86x(0x13,&fregs,&fregs,&segreg);
- }
- #endif
-