home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol135 / reloc.cq / RELOC.C
Encoding:
C/C++ Source or Header  |  1985-02-10  |  8.6 KB  |  262 lines

  1. /*-----------------------------------------------------------------------------
  2.  
  3.                 R E L O C . C
  4.                 =============
  5.  
  6.     Part of a system for generating self-relocating programs.
  7.  
  8.     (See RELOC.DOC for full details of method and application)
  9.  
  10.     COPYRIGHT NOTICE    (C) 1982   John Hastwell-Batten
  11.  
  12. These programs have been submitted to the public domain via Bill Bolton's RCPM 
  13. system and comprise a system for simply generating self-relocating programs by 
  14. a  method which relies on a linker to generate two object code files which are 
  15. then  processed to yield an object program consisting of  a  relocator,  user-
  16. supplied  object  code  and  a relocation  bitmap.   These  programs  and  the 
  17. accompanying  documentation may be freely distributed in original or  modified 
  18. form subject to the following conditions:
  19.  
  20. 1.   Although  there is no restriction on the sale of self-relocating programs 
  21.      generated  by  the method described herein,  these programs  or  variants 
  22.      thereof  may not be sold as part of any program package  without  written 
  23.      permission  from the author.   Neither may any program or program package 
  24.      which  is dependent for its operation on the use of this method  be  sold 
  25.      without such permission.
  26.  
  27. 2.   The  author's  name  must  be retained in all source  code  (original  or 
  28.      modified)  and  as an acknowlegement in any message  displayed  by  these 
  29.      programs or variant(s) thereof.  An acknowledgement giving credit for the 
  30.      method  shall contain the author's name or the words "H-B method" or  the 
  31.      words "Ashby method".
  32.  
  33. 3.   This copyright notice must be included in and retained in all source code 
  34.      and documentation pertaining to this system.
  35.  
  36.                              John Hastwell-Batten
  37.                                38 Silvia Street
  38.                                Hornsby NSW 2077
  39.                                   AUSTRALIA
  40.                                 (02) 477 4225
  41.  
  42.                               1st November, 1982
  43.  
  44. Acknowledgement
  45.  
  46. In  testing those relocations which overlay specified portions of CP/M I  have 
  47. made  use of John Woolner's CCP protection scheme obtained via  Bill  Bolton's 
  48. RCPM  system.   Without  the CCP protection the verification of the  relocator 
  49. module  would have been exceedingly difficult as the standard program  testing 
  50. tools  all  overlay  the CCP which,  in the case of  the  CP/M  overlays,  the 
  51. relocator expects to be intact.
  52.  
  53. -----------------------------------------------------------------------------*/
  54.  
  55. #include bdscio.h
  56.  
  57. #define    COPY        TRUE
  58. #define DISCARD        FALSE
  59.  
  60. #define CCPOFFSET    -8        /*  8 pages below BDOS */
  61. #define BDOSOFFSET     0
  62. #define BIOSOFFSET    14        /* 14 pages above BDOS */
  63. #define IMPLICIT    0x100
  64. #define PAGEMASK    0xFF
  65.  
  66. char
  67.     b100[BUFSIZ], b200[BUFSIZ], b300[BUFSIZ];
  68. char
  69.     bitmap[8192];
  70. int
  71.     c, c3;
  72. unsigned
  73.     codelen, i, relparam, relword();
  74.  
  75. main(argc,argv)
  76.   int  argc;
  77.   char *argv[];
  78. {
  79.   puts("Self-relocating-program generator - version 2.1 (27/11/82)\n");
  80.   puts("\n(C)1982: John Hastwell-Batten,\n\t 38 Silvia Street,\n");
  81.   puts("\t Hornsby NSW 2077.\n\t (02) 477 4225\n");
  82.  
  83. /* Open the 2 input files and the output code file */
  84.  
  85.   if (argc < 2) {
  86.       puts("\nNo output file name specified\n");
  87.       usage();
  88.       exit();  }
  89.  
  90.   if (fopen("ORG200.COM",b200) < 0) {
  91.       puts("\nORG200 linked code file is missing\n");
  92.       exit();  }
  93.   else if (fopen("ORG300.COM",b300) < 0) {
  94.       puts("\nORG300 linked code file is missing\n");
  95.       exit();  }
  96.   else if (fcreat(argv[1],b100) < 0) {
  97.       printf("\nCannot open output %s file",argv[1]);
  98.       exit();  }
  99.  
  100. /* First establish the relocation parameter for the relocator module.
  101.  
  102.    The relocator starts with a jump to base+5 to skip over the parameter.
  103.    (For most processors on which this program will be run, the jump is
  104.    a 3-byte instruction.)  The relocation parameter is in the next two
  105.    bytes.
  106.  
  107.    It would be most convenient to write the object code for the jump
  108.    from this module but to do so is slightly less general in that this
  109.    module must assume knowledge of the processor's instruction set.
  110.  
  111.    Instead, we copy the first three bytes from the relocator module,
  112.    replace the next two bytes with the relocation parameter, and then
  113.    copy the rest of the relocator.  It is just a little bit messy.    */
  114.  
  115.    for (i=0; i<3; i++)
  116.      relmod(COPY);        /* Copy first 3 bytes */
  117.  
  118.    for (; i<5; i++)
  119.      relmod(DISCARD);        /* Discard next 2 bytes */
  120.  
  121.    if (argc > 2)        /* i.e. if relocation parameter specified */
  122.      relparam = relword(argv[2],argv[1]);
  123.    else {
  124.      relparam = 0;
  125.      printf("\n%s will load below the BDOS\n",argv[1]);
  126.     }
  127.  
  128.    putw(relparam,b100);        /* Stuff in the relocation parameter */
  129.    printf("Relocation parameter is %x\n",relparam);
  130.  
  131. /* Now copy the remainder of the first 0xFE bytes (relocator module)
  132.    from ORG200 to the output code file */
  133.  
  134.   for (i=5; i<0xFE; i++)
  135.     relmod(COPY);
  136.  
  137. /* Now get the code length and write it to the output file */
  138.  
  139.   codelen = getw(b200);
  140.   putw(codelen,b100);
  141.   codelen -= 0x200;
  142.   printf("Relocatable code is %xh long\n",codelen);
  143.  
  144. /* Skip over all the leading junk in ORG300 */
  145.  
  146.   for (i=0; i<0x1FE; i++) {
  147.     if (getc(b300) == EOF) {
  148.       puts("\nRelocatable program missing from ORG300\n");
  149.       exit(); } }
  150.  
  151. /* Check to see that the ORG200 & ORG300 code is at least the same length */
  152.  
  153.   if (getw(b300)-0x300 != codelen) {
  154.     puts("\nLength of relocatable code in ORG200 and ORG300 is different\n");
  155.     exit(); }
  156.  
  157. /* If we get this far then we are ready to build the bit map */
  158.  
  159.   setmem(&bitmap[0],8192,0);
  160.  
  161.   for (i=0; i<codelen; i++) {
  162.     if (((c=getc(b200))==EOF) | ((c3=getc(b300))==EOF)) {
  163.       puts("\nPremature EOF reading relocatable code\n");
  164.       exit(); }
  165.     putc(c,b100);    /* Copy ORG200 to output */
  166.     if (c != c3)
  167.       setbit(i); }
  168.  
  169. /* Input ORG200 file now copied to output. Close input files and append
  170.    bitmap to the output file */
  171.  
  172.   fclose(b200);
  173.   fclose(b300);
  174.  
  175. /* Bitmap is (codelen+7) div 8 bytes long */
  176.  
  177.   codelen = (codelen+7) >> 3;
  178.   for (i=0; i<codelen; i++)
  179.     putc(bitmap[i],b100);
  180.  
  181. /* Wrap up */
  182.  
  183.   fflush(b100);
  184.   fclose(b100);        }
  185.         
  186. /****************************************************************************/
  187.  
  188. relmod(copy)
  189.     int   copy;
  190. {
  191.     int   c;
  192.  
  193.     if ((c=getc(b200)) == EOF) {
  194.       puts("\nPremature EOF copying relocator program\n");
  195.       exit();              }
  196.  
  197.     if (copy)
  198.       putc(c,b100);
  199. }
  200.  
  201. /****************************************************************************/
  202.  
  203. setbit(bitno)        /* sets a bit in the bitmap */
  204.   unsigned bitno; {
  205. /*printf("Setting bit %xh, changing from %xh",bitno,bitmap[(bitno>>3)]);*/
  206.   bitmap[(bitno / 8)] |= (1 << (7-(bitno % 8)));
  207. /*printf(" to %xh\n",bitmap[(bitno>>3)]);*/
  208. }
  209.  
  210. /****************************************************************************/
  211.  
  212. usage() {    /* Display a quick summary of how to invoke RELOC */
  213.  
  214.       puts("\nUsage: RELOC <.COM file name> [option]\n\n");
  215.       puts("Option can be any of:-\n");
  216.       puts("\t<empty>\t    => relocate below BDOS\n");
  217.       puts("\t-\t    => relocate below CCP\n");
  218.       puts("\tBIOS\t    => overlay BIOS\n");
  219.       puts("\tBDOS\t    => overlay BDOS\n");
  220.       puts("\tCCP\t    => overlay CCP\n");
  221.       puts("\thex number  => relocate to specific address\n");    }
  222.  
  223. /***************************************************************************/
  224.  
  225. relword(where,what)
  226.     char  where[], what[];
  227. {
  228.   unsigned   addr;
  229.   char       *x;
  230.  
  231.   for (x=where;*x++;)
  232.     *x = toupper(*x);
  233.  
  234.   if (!(strcmp(where,"-"))) {
  235.     printf("\n%s will load below the CCP\n",what);
  236.     return(CCPOFFSET & PAGEMASK);
  237.                 }
  238.   if (!(strcmp(where,"BIOS"))) {
  239.     printf("\n%s will overlay the BIOS\n",what);
  240.     return(BIOSOFFSET & PAGEMASK | IMPLICIT);
  241.                    }
  242.   if (!(strcmp(where,"BDOS"))) {
  243.     printf("\n%s will overlay the BDOS\n",what);
  244.     return(BDOSOFFSET & PAGEMASK | IMPLICIT);
  245.                    }
  246.   if (!(strcmp(where,"CCP"))) {
  247.     printf("\n%s will overlay the CCP\n",what);
  248.     return(CCPOFFSET & PAGEMASK | IMPLICIT);
  249.                   }
  250.   sscanf(where,"%x",&addr);
  251.   if (addr % 0x100) {
  252.     puts("\nCode destination must be on a 100h boundary\n");
  253.     exit();        }
  254.   if (addr < 0x200) { 
  255.     puts("\nCode cannot be relocated to an address below 200h\n");
  256.     exit();        }
  257.   printf("\n%s will load at %xh\n",what,addr);
  258.   return(addr);
  259. }
  260.  
  261. /****************************************************************************/
  262.