/* * diskload.c * * This program reads an MPX load module and stores it into the * sumulated diskfile. The SMD entry is changed to reflect the * new file entry. * input - filename * - simulated diskfile * output - modified diskfile with SMD entry modified * 08/11/2018 */ #include #include #include #define BLKSIZE 768 /* MPX file sector size */ unsigned char os[BLKSIZE * 100]; /* O/S code */ /* read program file and output to simulated mpx1.x diskfile using filemgr format */ /* dload file diskfile */ int main(argc, argv) int argc; char *argv[]; { FILE *fp, *dp, *fopen(); unsigned char si[BUFSIZ]; char *p; int i, j; #define DOLIST 1 #define DOADD 2 unsigned int option = DOLIST; /* what to do */ unsigned char *fnp; /* file name pointer */ unsigned int size; /* size in 768 byte sectors */ unsigned int word,tmp; /* just a temp word variable */ unsigned char name[9]; /* LM name */ unsigned int lmname[2], passwd[2]; unsigned int smds; /* size of smd */ unsigned int smdd[2]; /* SMD space definition */ unsigned char *smd; unsigned int hash1; /* SMD hash value for name */ unsigned int udtp; /* UDT pointer */ unsigned int *mptr; /* word ptr for SMD entries */ unsigned int boff; unsigned int rem; unsigned int blk; unsigned int lmblk; /* sector addess of load module on disk */ unsigned int smdudt; /* smd udt index */ unsigned int spau; /* sectors per allocation unit */ unsigned int fileau; /* file size in allocation units */ unsigned int auptr; /* pointer to allocation unit on disk */ unsigned int lsblk; /* lowest block address of SMD entries */ if (argc <= 1) { /* see if correct # args */ // fprintf(stderr, "Error: incorrect number of parameters\n"); fprintf(stderr, "Usage: %s -la program diskfile\n", *argv); exit(1); } if (--argc > 0) { p = *++argv; // printf("argv %s\n", p); if (*p++ == '-') { while (*p != '\0') { switch (*p++) { case 'l': case 'L': option |= DOLIST; break; case 'A': case 'a': option |= DOADD; break; default: // fprintf(stderr, "Error: incorrect option %c specified\n", *--p); fprintf(stderr, "Usage: %s -la program diskfile\n", *--argv); exit(1); break; } } if (*--p == '-') { fprintf(stderr, "Error: no option specified\n"); fprintf(stderr, "Usage: %s -la program diskfile\n", *--argv); exit(1); } } else { argc++; argv--; } if (--argc > 0) { p = *++argv; // printf("argv2 %s\n", p); if ((fp = fopen(*argv, "r")) == NULL) { fprintf(stderr, "error: can't open load module %s\n", *argv); exit(1); } fnp = *argv; /* get file name pointer */ fseek(fp, 0, SEEK_END); /* seek to end */ word = ftell(fp); /* get filesize in bytes */ fseek(fp, 0, SEEK_SET); /* rewind file */ } } if (--argc <= 0) { fprintf(stderr, "Error: incorrect number of parameters\n"); fprintf(stderr, "Usage: %s -la program diskfile\n", *argv); exit(1); } /* open diskfile */ if ((dp = fopen(*++argv, "r+")) == NULL) { fprintf(stderr, "error: can't open disk file %s\n", *argv); exit(1); } /* determine size of file */ size = word/BLKSIZE; /* get sector count */ if ((word % BLKSIZE) != 0) size++; /* add in 1 for partial sector */ /* size now has load module size in sectors */ /* we need the file name and password for entry */ for (i=0; i<8; i++) name[i] = 0x20; /* pre blank name */ name[8] = '\0'; /* NULL terminate */ for (i=0; (i<8) && (fnp[i] != 0); i++) name[i] = toupper(fnp[i]); /* upper case name */ // fprintf(stderr, "file %s is size %d sectors\n", name, size); lmname[0] = (name[0] << 24) | (name[1] << 16) | (name[2] << 8) | (name[3]); lmname[1] = (name[4] << 24) | (name[5] << 16) | (name[6] << 8) | (name[7]); passwd[0] = passwd[1] = 0; /* no password */ /* the disk data has the O/S starting at 0x780 in the file */ /* add 0x780 to any O/S location you want to load */ /* C.SMDS (#smd entries) is at 0xb00 + 0x780 = 0x1280 */ /* read the O/S diskfile into buffer, 7680 bytes */ // fprintf(stderr, "reading 100*BLKSIZE bytes from disk\n", 100*BLKSIZE); if (fread(os, 1, BLKSIZE*100, dp) <= 0) return (0); /* this means bad read */ smds = (os[0x780+0xb00] << 24) | (os[0x780+0xb01] << 16) | (os[0x780+0xb02] << 8) | (os[0x780+0xb03]); /* get udt index for SMD location */ smdudt = (os[0x780+0xc2c] << 8) | (os[0x780+0xc2d]); /* udt size id 0x40, C.UDTA is at 0xb40 */ word = (os[0x780+0xb40] << 24) | (os[0x780+0xb41] << 16) | (os[0x780+0xb42] << 8) | (os[0x780+0xb43]); udtp = (smdudt * 0x40 + word); /* get udt address */ /* spau is in byte 0x0f of udt */ spau = os[0x780+udtp+0x0f] & 0xff; /* get word with spau */ /* get file size in au's */ fileau = size / spau; /* get number of au's required for file */ if ((size % spau) != 0) fileau++; /* round up to next au of overflow */ fprintf(stderr, "file %s is size %d sectors (%d au) requiring %d sectors on disk\n", name, size, fileau, fileau*spau); // fprintf(stderr, "UDTP 0x%x SPAU 0x%x\n", udtp, spau); /* display udtp & spau */ fprintf(stderr, "C.SMDS(0xB00) - SMD size is 0x%x %d entries C.SMDUDT is %x\n", smds, smds, smdudt); /* get SMD space definition */ smdd[0] = (os[0x780+0x840] << 24) | (os[0x780+0x841] << 16) | (os[0x780+0x842] << 8) | (os[0x780+0x843]); smdd[1] = (os[0x780+0x844] << 24) | (os[0x780+0x845] << 16) | (os[0x780+0x846] << 8) | (os[0x780+0x847]); fprintf(stderr, "C.SMDD(0x840) - SMD space definition wd0 0x%x wd1 0x%x wd0 %d wd1 %d entries %d\n", smdd[0], smdd[1], smdd[0] ,smdd[1], smdd[1] * 24); fprintf(stderr, "SMD space def: blk 0x%x seek 0x%x size 0x%x (%d)\n", smdd[0], smdd[0]*BLKSIZE, smdd[1], smdd[1]); /* rewind the disk */ fseek(dp, 0, 0); /* seek home */ /* seek to the smd */ fseek(dp, smdd[0]*BLKSIZE, 0); /* seek smd */ if ((smd = (unsigned char *)malloc(smdd[1] * BLKSIZE)) < 0) return (0); /* this means bad read */ /* read the SMD into memory */ if (fread(smd, 1, smdd[1]*BLKSIZE, dp) <= 0) return (0); /* this means bad read */ /* use lowest space definition from SMD entries */ lsblk = smdd[0]; /* set lowest to start of SMD */ /* loop through the SMD looking for a match to the load module name */ for (i=0; i<(smds*32); i+=32) { unsigned int sblk, len, udt, pw; int yep = 0; for (j=0; j<8; j++) { if (smd[i+j] != 0) { fprintf(stderr, "%c", smd[i+j]); yep = 1; } } if (yep) { int bit; unsigned int lmn[2]; /* load module name */ sblk = (smd[i+8] << 24) | (smd[i+9] << 16) | (smd[i+10] << 8) | (smd[i+11]); if ((sblk & 0xffffff) < lsblk) lsblk = sblk & 0xffffff;/* save the new lowest address */ len = (smd[i+12] << 24) | (smd[i+13] << 16) | (smd[i+14] << 8) | (smd[i+15]); pw = (smd[i+24] << 8) | (smd[i+25]); udt = (smd[i+26] << 8) | (smd[i+27]); /* hash the name to see if pointer is to current SMD entry */ mptr = (unsigned int *)smd; /* get word pointer for SMD data */ j = i/32; /* offset in SMD file (entry #) */ lmn[0] = mptr[j*8]; /* get filename first 4 chars to R5 and shift right circular by 1 */ word = ((lmn[0] & 0xff) << 24) | ((lmn[0] & 0xff00) << 8) | ((lmn[0] & 0xff0000) >> 8) | ((lmn[0] & 0xff000000) >> 24); bit = word & 1; /* save bit 31 */ word = word >> 1; /* shift right 1 */ if (bit) word |= 0x80000000; /* copy old bit 31 to bit 0 */ lmn[1] = mptr[j*8+1]; /* get 2nd 4 chars of filename */ rem = ((lmn[1] & 0xff) << 24) | ((lmn[1] & 0xff00) << 8) | ((lmn[1] & 0xff0000) >> 8) | ((lmn[1] & 0xff000000) >> 24); word = word ^ rem; /* EOR with 2nd half of load module name */ rem = word % smds; /* get remainder as relative entry number */ fprintf(stderr, " entry %d (calc %d) off 0x%x typ 0x%x blk 0x%x len 0x%x, pw 0x%x udt 0x%x\n", j, rem, (sblk & 0xffffff)*BLKSIZE, sblk>>24, sblk, len, pw, udt); // fprintf(stderr, "offset index %d calc %d\n", i/32, rem); /* display entry # */ } } /* see if user want list only */ if ((option & DOLIST) && !(option & DOADD)) goto doexit; // getout #if 0 /* get file size in au's */ fileau = size / spau; /* get number of au's required for file */ if ((size % spau) != 0) fileau++; /* round up to next au of overflow */ #endif /* lsblk has the lowest space definition from SMD entries */ lmblk = lsblk - fileau * spau; /* get sector address of where to store lm */ fprintf(stderr, "lmblk 0x%x lsblk 0x%x fileau 0x%x spau 0x%x\n", lmblk, lsblk, fileau, spau); /* hash filename into SMD entry number */ fprintf(stderr, "1 hashing lmname[0] %x lmname[1] %x\n", lmname[0], lmname[1]); word = lmname[0]; /* get filename first 4 chars to R5 and shift right circular by 1 */ i = word & 1; /* save bit 31 */ word = word >> 1; /* shift right 1 */ if (i) word |= 0x80000000; /* copy old bit 31 to bit 0 */ word = word ^ lmname[1]; /* EOR with 2nd half of load module name */ hash1 = word / smds; /* calc SMD hash number and save */ rem = word % smds; /* get remainder as relative entry number */ /* get relative 192W block in SMD */ blk = rem/24; /* divide entry # by # entries/block */ boff = (rem%24) * 32; /* get byte offset in block of entry */ tmp = (blk * 24 + (boff/32)); /* make word offset in smd array */ fprintf(stderr, "hash1 %x rem %x blk 0x%x %d boff %x index %d\n", hash1, rem, blk, blk, boff, tmp); /* populate the 32 byte SMD entry */ /* smd has entire SMD in memory */ tmp = (blk * BLKSIZE + boff) >> 2; /* make word offset in smd array */ mptr = (unsigned int *)smd; /* get word pointer for smd data */ /* word 1 and 2 has filename */ blk = lmname[0]; /* 1st 4 char of lmname */ word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); mptr[tmp] = word; /* set 1st 4 char of name */ blk = lmname[1]; /* set 2nd 4 char of name */ word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); mptr[tmp+1] = word; /* set 2nd 4 char of name */ // blk = 0xca000000 | lmblk; /* type ca and blk address */ blk = 0xee000000 | lmblk; /* type ca and blk address */ word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); mptr[tmp+2] = word; /* set type and blk addr */ /* size now has load module size in sectors */ blk = 0x80000000 | size; /* file flags and size */ word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); mptr[tmp+3] = word; /* set flags and size */ mptr[tmp+4] = 0; /* no username */ mptr[tmp+5] = 0; /* no username */ blk = 0x00000000 | smdudt; /* no password and smd udt */ word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); mptr[tmp+6] = word; /* set password and udt index */ mptr[tmp+7] = 0; /* not used */ /* loop through the SMD looking for a match to the load module name */ for (i=0; i<(smds*32); i+=32) { unsigned int sblk, len, udt, pw; int yep = 0; for (j=0; j<8; j++) { if (smd[i+j] != 0) { fprintf(stderr, "%c", smd[i+j]); yep = 1; } } if (yep) { int bit; unsigned int lmn[2]; /* load module name */ sblk = (smd[i+8] << 24) | (smd[i+9] << 16) | (smd[i+10] << 8) | (smd[i+11]); len = (smd[i+12] << 24) | (smd[i+13] << 16) | (smd[i+14] << 8) | (smd[i+15]); pw = (smd[i+24] << 8) | (smd[i+25]); udt = (smd[i+26] << 8) | (smd[i+27]); #if 0 fprintf(stderr, " entry %d blk # 0x%x off 0x%x len 0x%x, pw 0x%x udt 0x%x\n", i/32, sblk, (sblk & 0xffffff) * BLKSIZE, len, pw, udt); /* udt size id 0x40, C.UDTA is at 0xb40 */ word = (os[0x780+0xb40] << 24) | (os[0x780+0xb41] << 16) | (os[0x780+0xb42] << 8) | (os[0x780+0xb43]); udtp = (udt * 0x40 + word); /* get udt address */ fprintf(stderr, "UDTP 0x%x\n", udtp); /* display word */ /* spau is in byte 0x0f */ spau = os[0x780+udtp+0x0f] & 0xff; /* get word with spau */ fprintf(stderr, "SPAU 0x%x\n", spau); /* display spau */ #endif /* hash the name to see if pointer is to current SMD entry */ mptr = (unsigned int *)smd; /* get word pointer for SMD data */ j = i/32; /* offset in SMD file (entry #) */ lmn[0] = mptr[j*8]; /* get filename first 4 chars to R5 and shift right circular by 1 */ word = ((lmn[0] & 0xff) << 24) | ((lmn[0] & 0xff00) << 8) | ((lmn[0] & 0xff0000) >> 8) | ((lmn[0] & 0xff000000) >> 24); bit = word & 1; /* save bit 31 */ word = word >> 1; /* shift right 1 */ if (bit) word |= 0x80000000; /* copy old bit 31 to bit 0 */ lmn[1] = mptr[j*8+1]; /* get 2nd 4 chars of filename */ rem = ((lmn[1] & 0xff) << 24) | ((lmn[1] & 0xff00) << 8) | ((lmn[1] & 0xff0000) >> 8) | ((lmn[1] & 0xff000000) >> 24); word = word ^ rem; /* EOR with 2nd half of load module name */ rem = word % smds; /* get remainder as relative entry number */ fprintf(stderr, " entry %d (calc %d) off 0x%x typ 0x%x blk 0x%x len 0x%x, pw 0x%x udt 0x%x\n", j, rem, (sblk & 0xffffff)*BLKSIZE, sblk>>24, sblk, len, pw, udt); // fprintf(stderr, "offset index %d calc %d\n", i/32, rem); /* display entry # */ } } fprintf(stderr, "file space def: blk 0x%x seek 0x%x size 0x%x %d\n", lmblk, lmblk*BLKSIZE, size, size); if (option & DOADD) { /* see if user wants file written to disk */ /* write the load module to disk */ /* rewind the disk */ fseek(dp, 0, 0); /* seek home */ /* seek to where the load module is to be stored */ fseek(dp, lmblk*BLKSIZE, 0); /* seek sector for saving load module */ /* rewind the load module */ fseek(fp, 0, 0); /* seek home */ /* copy all of the sectors */ for (i=0; i