home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / disk / bbinstall / bbinstall.c next >
Encoding:
C/C++ Source or Header  |  1997-09-01  |  8.2 KB  |  365 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/ports.h>
  4. #include <exec/io.h>
  5. #include <devices/trackdisk.h>
  6. #include <dos/rdargs.h>
  7. #include <dos/doshunks.h>
  8. #include <clib/exec_protos.h>
  9. #include <clib/dos_protos.h>
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13.  
  14. const STRPTR PROG_Name = "BBInstall";
  15. const STRPTR PROG_Ver  = "1";
  16. const STRPTR PROG_Rev  = "7";
  17. const STRPTR PROG_Date = "1st September 1997";
  18.  
  19. /* Information for C:Version */
  20. const STRPTR VerStr = "$VER: BBInstall 1.7 (1st September 1997)";
  21.  
  22.  
  23. const STRPTR BA_Template = "DRIVE/A,LOAD/K,SAVE/K,DOSTYPE/N,CODE/S,MOVESYS/S";
  24.  
  25. struct BBIArgs {
  26.   STRPTR DRIVE;
  27.   STRPTR LOAD;
  28.   STRPTR SAVE;
  29.   ULONG *DOSTYPE;
  30.   ULONG  CODE;
  31.   ULONG  MOVESYS;
  32. };
  33.  
  34. struct RDArgs *rdargs;
  35. struct MsgPort *diskport;
  36. struct IOExtTD *diskreq;
  37. BYTE td_open;
  38. ULONG *bb_buffer;
  39. FILE *bbfile;
  40.  
  41.  
  42. /* Initialize global data */
  43. void clear_globals(void)
  44. {
  45.   rdargs = NULL;
  46.   diskport = NULL;
  47.   diskreq = NULL;
  48.   td_open = NULL;
  49.   bb_buffer = NULL;
  50.   bbfile = NULL;
  51. }
  52.  
  53. /* Exit cleanly */
  54. void clean_exit(ULONG rc)
  55. {
  56.   /* Close BootBlock FILE */
  57.   if (bbfile) fclose(bbfile);
  58.   
  59.   /* Free Allocated Memory */
  60.   if (bb_buffer) FreeMem(bb_buffer,1024);
  61.   
  62.   /* Close TrackDisk Unit */
  63.   if (td_open)
  64.   {
  65.     /* Flush any buffers */
  66.     diskreq->iotd_Req.io_Command = CMD_UPDATE;
  67.     DoIO((struct IORequest *)diskreq);
  68.     
  69.     /* Turn off the motor */
  70.     diskreq->iotd_Req.io_Command = TD_MOTOR;
  71.     diskreq->iotd_Req.io_Length = 0;
  72.     DoIO((struct IORequest *)diskreq);
  73.     
  74.     /* Close trackdisk.device */
  75.     CloseDevice((struct IORequest *)diskreq);
  76.   }
  77.   
  78.   /* Delete IO Request */
  79.   if (diskreq) DeleteIORequest(diskreq);
  80.   
  81.   /* Delete Message Port */
  82.   if (diskport) DeleteMsgPort(diskport);
  83.   
  84.   /* Free arguments */
  85.   if (rdargs) FreeArgs(rdargs);
  86.   
  87.   exit(rc);
  88. }
  89.  
  90.  
  91. void LoadCode(ULONG *buf, FILE *infile, STRPTR infilename, ULONG moveSysBase)
  92. {
  93.   ULONG read_value;
  94.   ULONG code_size;
  95.   int i;
  96.  
  97.   /* Find a HUNK_CODE within input file */
  98.   do {
  99.     fread(&read_value,4,1,infile);
  100.   } while ((read_value != HUNK_CODE) && (!feof(infile)));
  101.   
  102.   if (read_value != HUNK_CODE)
  103.   {
  104.     fprintf(stderr,"%s has no code hunk.\n",infilename);
  105.     clean_exit(10);
  106.   }
  107.   
  108.   /* Get size of code */
  109.   fread(&code_size,4,1,infile);
  110.   if (moveSysBase)
  111.   {
  112.     fread(&read_value,4,1,infile);
  113.     
  114.     if (read_value == 0x2C780004)
  115.       code_size--;
  116.     else
  117.       fseek(infile,-4,SEEK_CUR);
  118.   }
  119.   if (code_size > 253)
  120.   {
  121.     fprintf(stderr,"%s is too large to fit into a boot block.\n",infilename);
  122.     clean_exit(10);
  123.   }
  124.   
  125.   /* read code into bootblock array and clear leftover space */
  126.   fread(buf+3,4,code_size,infile);
  127.   for (i=code_size+3; i<256; i++)
  128.     buf[i] = 0;
  129. }
  130.  
  131. void LoadData(ULONG *buf, FILE *infile)
  132. {
  133.   int i;
  134.   ULONG read_value;
  135.   
  136.   /* Clear buffer */
  137.   for (i=0; i<256; i++)
  138.     buf[i] = 0;
  139.   
  140.   fread(&read_value,4,1,infile);
  141.   
  142.   if ((read_value & 0xFFFFFF00) == 0x444F5300)
  143.   {
  144.     buf[0] = read_value;
  145.     fread(buf+1,4,255,infile);
  146.   }
  147.   else
  148.   {
  149.     buf[3] = read_value;
  150.     fread(buf+4,4,252,infile);
  151.   }
  152. }
  153.  
  154. void SaveCode(ULONG *buf, FILE *outfile, ULONG moveSysBase)
  155. {
  156.   ULONG exe_head[8] = {HUNK_HEADER,0,1,0,0,253,
  157.                        HUNK_CODE,253};
  158.   ULONG exe_foot[1] = {HUNK_END};
  159.   ULONG exe_sysbase[1] = {0x2C780004};    /* MOVEA.L 4.W,A6 */
  160.   
  161.   if (moveSysBase)
  162.   {
  163.     exe_head[5]++;
  164.     exe_head[7]++;
  165.   }
  166.     
  167.   fwrite(exe_head,4,8,outfile);
  168.   
  169.   if (moveSysBase)
  170.     fwrite(exe_sysbase,4,1,outfile);
  171.  
  172.   fwrite(buf+3,4,253,outfile);
  173.   fwrite(exe_foot,4,1,outfile);
  174. }
  175.  
  176. void SaveData(ULONG *buf, FILE *outfile)
  177. {
  178.   fwrite(buf,4,256,outfile);
  179. }
  180.  
  181. ULONG calcsum(ULONG *buf)
  182. {
  183.   ULONG sum,prevsum;
  184.   int i;
  185.   
  186.   sum = buf[0];
  187.   prevsum = 0;
  188.   if (sum < 0)
  189.     sum++;
  190.   
  191.   for (i=2; i<256; i++)
  192.   {
  193.     prevsum = sum;
  194.     sum += buf[i];
  195.     if (prevsum > sum)
  196.       sum++;
  197.   }
  198.   
  199.   return -(sum+1);
  200. }
  201.  
  202. void OutputBanner(void)
  203. {
  204.   printf("\033[1m%s v%s.%s © %s Karl J. Ots\033[0m\n\n",PROG_Name,
  205.                                                         PROG_Ver,
  206.                                                         PROG_Rev,
  207.                                                         PROG_Date);
  208. }
  209.  
  210. void OutputUsage(void)
  211. {
  212.   fprintf(stderr,"Usage: BBInstall %s\n",BA_Template);
  213.   clean_exit(5);
  214. }
  215.  
  216. int main(int argc, char *argv[])
  217. {
  218.   struct BBIArgs BBIArgs = {NULL, NULL, NULL, NULL, FALSE, FALSE};
  219.   int unit;
  220.   ULONG old_dostype;
  221.   
  222.   clear_globals();
  223.   OutputBanner();
  224.   
  225.   /* Collect and analyse arguments */
  226.   rdargs = ReadArgs(BA_Template,(ULONG *)&BBIArgs,NULL);
  227.   if (!rdargs)
  228.     OutputUsage();
  229.   
  230.   if ((BBIArgs.LOAD && BBIArgs.SAVE) ||
  231.       (!BBIArgs.LOAD && !BBIArgs.SAVE))
  232.     OutputUsage();
  233.  
  234.  
  235.   /* Determine if DRIVE is valid */
  236.   if (((BBIArgs.DRIVE[0] != 'D') && (BBIArgs.DRIVE[0] != 'd')) ||
  237.       ((BBIArgs.DRIVE[1] != 'F') && (BBIArgs.DRIVE[1] != 'f')) ||
  238.        (BBIArgs.DRIVE[2] >= '4') ||
  239.        (BBIArgs.DRIVE[3] != ':'))
  240.   {
  241.     fprintf(stderr,"Invalid Drive %s\n",BBIArgs.DRIVE);
  242.     clean_exit(5);
  243.   }
  244.   unit = BBIArgs.DRIVE[2] - '0';
  245.   
  246.  
  247.   /* Open TrackDisk Unit */
  248.   diskport = CreateMsgPort();
  249.   if (!diskport)
  250.   {
  251.     fputs("Error: Couldn't create a Message Port (Out of Memory?)\n",stderr);
  252.     clean_exit(20);
  253.   }
  254.   
  255.   diskreq = (struct IOExtTD *)
  256.             CreateIORequest(diskport,sizeof(struct IOExtTD));
  257.   if (!diskreq)
  258.   {
  259.     fputs("Error: Couldn't create an IO request (Out of Memory?)\n",stderr);
  260.     clean_exit(20);
  261.   }
  262.   
  263.   td_open = !OpenDevice(TD_NAME,unit,(struct IORequest *)diskreq,NULL);
  264.   if (!td_open)
  265.   {
  266.     fprintf(stderr,"Can't open trackdisk.device unit %d (DF%d:)!\n",unit,
  267.                                                                     unit);
  268.     clean_exit(20);
  269.   }
  270.   
  271.   
  272.   /* Allocate some memory */
  273.   bb_buffer = (ULONG *)AllocMem(1024,MEMF_CLEAR|MEMF_CHIP);
  274.   if (!bb_buffer)
  275.   {
  276.     fputs("Error: Out of memory.\n",stderr);
  277.     clean_exit(10);
  278.   }
  279.   
  280.   /* Read TrackDisk Unit */
  281.   diskreq->iotd_Req.io_Length = 1024;
  282.   diskreq->iotd_Req.io_Data = bb_buffer;
  283.   diskreq->iotd_Req.io_Command = CMD_READ;
  284.   diskreq->iotd_Req.io_Offset = 0;
  285.   if (DoIO((struct IORequest *)diskreq))
  286.   {
  287.     fputs("An error occured\n",stderr);
  288.     clean_exit(20);
  289.   }
  290.   
  291.   old_dostype = bb_buffer[0];
  292.     
  293.   if (BBIArgs.LOAD)
  294.   {
  295.     bbfile = fopen(BBIArgs.LOAD,"rb");
  296.     if (!bbfile)
  297.     {
  298.       fprintf(stderr,"Couldn't open \"%s\" for reading\n",BBIArgs.LOAD);
  299.       clean_exit(10);
  300.     }
  301.     printf("Loading \"%s\" as %s to DF%d: ... \n",BBIArgs.LOAD,
  302.                                             (BBIArgs.CODE ? "code" : "data"),
  303.                                                   unit);
  304.     
  305.     /* Setup bootblock header (without checksum) */
  306.     /* bb_buffer[0] = bb_buffer[0] */ /* Obviously... */
  307.     bb_buffer[1] = 0;
  308.     bb_buffer[2] = 0x00000370;
  309.     
  310.     if (BBIArgs.CODE)
  311.       LoadCode(bb_buffer,bbfile,BBIArgs.LOAD,BBIArgs.MOVESYS);
  312.     else
  313.       LoadData(bb_buffer,bbfile);
  314.     
  315.     if (BBIArgs.DOSTYPE)
  316.       bb_buffer[0] = (bb_buffer[0] & 0xFFFFFF00) |
  317.                      (BBIArgs.DOSTYPE[0] & 0xFF);
  318.     printf("  Dostype = 0x%02X ... ",(bb_buffer[0] & 0xFF));
  319.     fflush(stdout);
  320.     
  321.     /* Calculate checksum and insert it into bootblock */
  322.     bb_buffer[1] = calcsum(bb_buffer);
  323.     printf("Checksum = 0x%08X ... ",bb_buffer[1]);
  324.     fflush(stdout);
  325.     
  326.     /* bb_buffer in now ready to be inserted into bootblock */
  327.     /* Write TD Unit */
  328.     diskreq->iotd_Req.io_Length = 1024;
  329.     diskreq->iotd_Req.io_Data = bb_buffer;
  330.     diskreq->iotd_Req.io_Command = CMD_WRITE;
  331.     diskreq->iotd_Req.io_Offset = 0;
  332.     if (DoIO((struct IORequest *)diskreq))
  333.     {
  334.       fputs("Another error occured\n",stderr);
  335.       clean_exit(20);
  336.     }
  337.   
  338.     puts("Done.\n");
  339.   }
  340.   else  /* if (BBIArgs.SAVE) */ /* <-- We know this is set if LOAD isn't */
  341.   {
  342.     bbfile = fopen(BBIArgs.SAVE,"wb");
  343.     if (!bbfile)
  344.     {
  345.       fprintf(stderr,"Couldn't open \"%s\" for writing.\n",BBIArgs.SAVE);
  346.       clean_exit(10);
  347.     }
  348.     printf("Saving old BootBlock from DF%d: to \"%s\" as %s ... ",unit,
  349.                                                              BBIArgs.SAVE,
  350.                                            (BBIArgs.CODE ? "code" : "data"));
  351.     fflush(stdout);
  352.         
  353.     if (BBIArgs.CODE)
  354.       SaveCode(bb_buffer,bbfile,BBIArgs.MOVESYS);
  355.     else
  356.       SaveData(bb_buffer,bbfile);
  357.     
  358.     puts("Done.\n");
  359.   }
  360.   
  361.   clean_exit(0);
  362.   
  363.   return 0;    /* Keep compiler happy */
  364. }
  365.