home *** CD-ROM | disk | FTP | other *** search
/ Micro R&D 1 / MicroRD-CD-ROM-Vol1-1994.iso / disktools / moni / bb20.lzh / BB / BB.c < prev    next >
C/C++ Source or Header  |  1992-01-18  |  10KB  |  545 lines

  1. /*
  2.  * BB.c - bootblock management: reads, installs and fix checksums.
  3.  *
  4.  * Bruno Costa - 5 Dec 89 - 22 Jul 91
  5.  *
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/io.h>
  10. #include <devices/bootblock.h>
  11. #include <devices/trackdisk.h>
  12. #include <exec/memory.h>
  13. #include <proto/exec.h>
  14. #include <proto/dos.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17.  
  18. typedef unsigned char byte;
  19.  
  20. #if 0
  21. #include "bootblock.h"
  22. #else
  23. byte bootblock[] = {        /* standard AmigaDOS bootblock */
  24.  'D', 'O', 'S', 0,
  25.  0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
  26.  0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
  27.  0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
  28.  0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  29.  0x00, 0x00
  30. };
  31. #endif
  32.  
  33. byte doPAL[] = {
  34.  0x33, 0xfc, 0x00, 0x20, 0x00, 0xdf, 0xf1, 0xdc   /* move.W  #$20,$dff1dc */
  35. };
  36.  
  37.  
  38. #define BBSIZE    1024
  39. #define MAXNAME 100
  40.  
  41. #define FIX    1
  42. #define SHOW    2
  43. #define INSTALL    3
  44. #define PAL    4
  45. #define READ    5
  46.  
  47.  
  48. void print (char *msg);
  49. void newline (void);
  50. void xprint (unsigned long n);
  51. void copyright (void);
  52. void help (void);
  53. void notify (char *msg);
  54. void bbdump (byte *buffer);
  55. unsigned long checksum (byte *buffer);
  56. int bbinstall (struct IOStdReq *disk, byte *buffer);
  57. int bbread (struct IOStdReq *disk, byte *buffer);
  58. int fileread (char *name, byte *buf);
  59. int filewrite (char *name, byte *buf);
  60. void waitenter (void);
  61.  
  62.  
  63. #define abort(x) {errnum = x; goto cleanup;}
  64.  
  65.  
  66. void main (int argc, char *argv[])
  67. {
  68.  byte *buf = NULL;            /* disk buffer for bootblocks */
  69.  struct Port *diskport = NULL;        /* trackdisk's message port   */
  70.  struct IOStdReq *diskreq = NULL;    /* trackdisk's IO request     */
  71.  int errnum = 0;
  72.  int unit = -1;
  73.  int batch = TRUE, action = SHOW;
  74.  char bbname[MAXNAME], data[MAXNAME];
  75.  long error;
  76.  int c;
  77.  
  78.  /*
  79.   *  Command line processing
  80.   */
  81.  
  82.  if (argc == 1)
  83.  {
  84.    copyright ();
  85.    help ();
  86.    abort (5);
  87.  }
  88.  
  89.  while (c = getoption (argc, argv, "ir", "acshpd", data))
  90.    if (c < 0)
  91.    {
  92.      notify ("unknown option");
  93.      help ();
  94.      abort (10);
  95.    }
  96.    else if (c == 1)
  97.    {
  98.      if (isdigit (data[0]))
  99.        unit = data[0] - '0';
  100.      else if (tolower (data[0]) == 'd'  &&  tolower (data[1]) == 'f'  &&
  101.               isdigit (data[2]))
  102.        unit = data[2] - '0';
  103.      else
  104.      {
  105.        help ();
  106.        abort (10);
  107.      }
  108.    }
  109.    else
  110.      switch (c)
  111.      {
  112.        case 'i':
  113.          action = INSTALL;
  114.          strcpy (bbname, data);
  115.          break;
  116.  
  117.        case 'd':
  118.          action = INSTALL;
  119.          bbname[0] = '\0';
  120.          break;
  121.  
  122.        case 'r':
  123.          action = READ;
  124.          strcpy (bbname, data);
  125.          break;
  126.  
  127.        case 'a':
  128.          batch = FALSE;
  129.          break;
  130.  
  131.        case 'c':
  132.          action = FIX;
  133.          break;
  134.  
  135.        case 's':
  136.          action = SHOW;
  137.          break;
  138.  
  139.        case 'p':
  140.          action = PAL;
  141.          break;
  142.  
  143.        case 'h':
  144.          help ();
  145.          abort (10);
  146.          break;
  147.      }
  148.  
  149.  if (unit < 0  ||  unit > 3)
  150.  {
  151.    notify ("Bad drive number");
  152.    abort (10);
  153.  }
  154.  
  155.  
  156.  /*
  157.   *  Trackdisk I/O setup
  158.   */
  159.  
  160.  buf = AllocMem (BBSIZE, MEMF_CHIP | MEMF_CLEAR);
  161.  diskport = CreatePort (0, 0);
  162.  diskreq = CreateStdIO (diskport);
  163.  if (!buf  ||  !diskport  ||  !diskreq)
  164.  {
  165.    notify ("memory");
  166.    abort (30);
  167.  }
  168.  
  169.  error = OpenDevice ("trackdisk.device", (long)unit, diskreq, 0);
  170.  if (error > 0)
  171.  {
  172.    notify ("trackdisk");
  173.    abort (20);
  174.  }
  175.  
  176.  if (!batch)    /*           1         2          */
  177.  {              /* 012345678901234567890123456789 */
  178.    char tmp[60] = "Please insert disk in DF9: and press ENTER ...";
  179.  
  180.    tmp[24] = unit + '0';
  181.    print (tmp);
  182.  
  183.    waitenter ();
  184.  }
  185.  
  186.  
  187.  /*
  188.   *  Action processing
  189.   */
  190.  switch (action)
  191.  {
  192.    case FIX:
  193.      if (!bbread (diskreq, buf))
  194.        abort (20);
  195.  
  196.      print ("Old checksum = 0x");
  197.      xprint (((unsigned long *)buf)[1]);
  198.      newline ();
  199.  
  200.      checksum (buf);
  201.  
  202.      print ("New checksum = 0x");
  203.      xprint (((unsigned long *)buf)[1]);
  204.      newline ();
  205.  
  206.      if (!bbinstall (diskreq, buf))
  207.        abort (20);
  208.      break;
  209.  
  210.    case PAL:
  211.      print ("warning: this may make your bootblock unusable!\n");
  212.      print ("         remove disk or press ENTER to continue:");
  213.      waitenter ();
  214.  
  215.      if (!bbread (diskreq, buf))
  216.        abort (20);
  217.  
  218.      memmove (buf + 12 + sizeof (doPAL), buf + 12, BBSIZE - 12 - sizeof (doPAL));
  219.      memcpy (buf + 12, doPAL, sizeof (doPAL));
  220.  
  221.      checksum (buf);
  222.      if (!bbinstall (diskreq, buf))
  223.        abort (20);
  224.      break;
  225.  
  226.    case INSTALL:
  227.      if (bbname[0] == '\0')
  228.        CopyMem (bootblock, buf, sizeof(bootblock));    /* my bootblock */
  229.      else
  230.        if (!fileread (bbname, buf))
  231.          abort (20);
  232.  
  233.      checksum (buf);            /* be sure that checksum is correct */
  234.      if (!bbinstall (diskreq, buf))
  235.        abort (20);
  236.      break;
  237.  
  238.    case READ:
  239.      if (bbname[0] == '\0')
  240.        notify ("no filename given");
  241.      else
  242.        if (!bbread (diskreq, buf)  ||  !filewrite (bbname, buf))
  243.          abort (20);
  244.      break;
  245.  
  246.    case SHOW:
  247.      if (!bbread (diskreq, buf))
  248.        abort (20);
  249.      bbdump (buf);
  250.      break;
  251.  }
  252.  
  253.  
  254. cleanup:
  255.  
  256.  if (diskreq)
  257.  {
  258.    if (diskreq->io_Device)
  259.      CloseDevice (diskreq);
  260.    DeleteStdIO (diskreq);
  261.  }
  262.  if (diskport)
  263.    DeletePort (diskport);
  264.  if (buf)
  265.    FreeMem (buf, BBSIZE);
  266. }
  267.  
  268.  
  269. int fileread (char *name, byte *buf)
  270. {
  271.  BPTR f;
  272.  long error;
  273.  
  274.  f = Open (name, MODE_OLDFILE);
  275.  if (f)
  276.  {
  277.    error = Read (f, buf, BBSIZE);
  278.    Close (f);
  279.  }
  280.  
  281.  if (!f  ||  error == 0  ||  error == -1)
  282.  {
  283.    notify ("could not read custom bootblock file");
  284.    return FALSE;
  285.  }
  286.  else
  287.    return TRUE;
  288. }
  289.  
  290.  
  291. int filewrite (char *name, byte *buf)
  292. {
  293.  BPTR f;
  294.  long error;
  295.  
  296.  f = Open (name, MODE_NEWFILE);
  297.  if (f)
  298.  {
  299.    error = Write (f, buf, BBSIZE);
  300.    Close (f);
  301.  }
  302.  
  303.  if (!f  ||  error != BBSIZE)
  304.  {
  305.    notify ("could not write custom bootblock file");
  306.    return FALSE;
  307.  }
  308.  else
  309.    return TRUE;
  310. }
  311.  
  312.  
  313. /*
  314.  * waits for the ENTER key to be pressed
  315.  */
  316. void waitenter (void)
  317. {
  318.  char dummy[2];
  319.  
  320.  (void)Read (Input(), dummy, 2);
  321. }
  322.  
  323.  
  324. /*
  325.  * prints any message
  326.  */
  327. void print (char *msg)
  328. {
  329.  Write (Output(), msg, strlen (msg));
  330. }
  331.  
  332.  
  333. /*
  334.  * prints a newline
  335.  */
  336. void newline (void)
  337. {
  338.  Write (Output(), "\n", 1);
  339. }
  340.  
  341.  
  342. /*
  343.  * prints a copyright message
  344.  */
  345. void copyright (void)
  346. {
  347.  print ("\x1b[33mBB v2.0\x1b[31m - \xa9 1989 by Bruno Costa\n");
  348. }
  349.  
  350.  
  351. /*
  352.  * prints a help message
  353.  */
  354. void help (void)
  355. {
  356.  print ("usage: BB [-acshpd] [-i<filename>] [-r<filename>] <drivename>\n");
  357.  print ("\tr = read bootblock\n");
  358.  print ("\ti = install new bootblock\n");
  359.  print ("\td = install a DOS bootblock\n");
  360.  print ("\tc = fix bootblock checksum\n");
  361.  print ("\ts = show bootblock (default)\n");
  362.  print ("\tp = adds PAL booter to bootblock\n");
  363.  print ("\ta = asks for disk insertion before actions\n");
  364.  print ("\th = prints this help message\n");
  365. }
  366.  
  367.  
  368. /*
  369.  * notifies an error
  370.  */
  371. void notify (char *msg)
  372. {
  373.  print ("BB: ");
  374.  print (msg);
  375.  newline ();
  376. }
  377.  
  378.  
  379. /*
  380.  * prints an hexadecimal number
  381.  */
  382. void xprint (unsigned long n)
  383. {
  384.  int i;
  385.  char tmp[10];
  386.  static char xdigit[17] = "0123456789ABCDEF";
  387.  
  388.  for (i = 7; i >= 0; i--)
  389.  {
  390.    tmp[i] = xdigit[n & 0x0000000f];
  391.    n = n >> 4;
  392.  }
  393.  tmp[8] = '\0';
  394.  print (tmp);
  395. }
  396.  
  397.  
  398. /*
  399.  * dumps the given bootblock in a readable form
  400.  */
  401. void bbdump (byte *buffer)
  402. {
  403.  register int i, j;
  404.  char c, line[80];
  405.  unsigned long cksum;
  406.  
  407.  cksum = ((unsigned long *)buffer)[1];
  408.  
  409.  print ("  Current checksum = 0x");
  410.  xprint (cksum);
  411.  print ("      Correct checksum = 0x");
  412.  xprint (checksum (buffer));
  413.  
  414.  ((unsigned long *)buffer)[1] = cksum;        /* restore old checksum */
  415.  
  416.  newline ();
  417.  newline ();
  418.  
  419.  for (i = 0; i < 16; i++)
  420.  {
  421.    for (j = 0; j < 64; j++)
  422.    {
  423.      c = buffer[i * 64 + j];
  424.      if (isprint (c))
  425.        line[j] = c;
  426.      else
  427.        line[j] = '.';
  428.    }
  429.    line[j] = '\0';
  430.    print ("  ");
  431.    print (line);
  432.    newline ();
  433.  }
  434. }
  435.  
  436.  
  437. /*
  438.  * updates bootblock checksum in given buffer
  439.  */
  440. unsigned long checksum (byte *buffer)
  441. {
  442.  register long sum, lastsum;
  443.  register int a;
  444.  unsigned long *ptr;
  445.  
  446.  ptr = (long *)buffer;
  447.  
  448.  if (ptr[0] != ID_DOS_DISK)    /* not a DOS0 disk ? */
  449.    return 0;
  450.  
  451.  ptr[1] = 0;        /* clear buffer checksum */
  452.  
  453.  sum = 0;
  454.  for (a = 0; a < 256; a++)
  455.  {
  456.    lastsum = sum;
  457.    sum = sum + ptr[a];
  458.    if (lastsum > sum)
  459.      sum++;
  460.  }
  461.  
  462.  if (lastsum > 0)
  463.    ptr[1] = - sum - 1;
  464.  else
  465.    ptr[1] = - sum;    /* sum + checksum must be 0 */
  466.  
  467.  return ptr[1];
  468. }
  469.  
  470.  
  471. /*
  472.  * install bootblock in buffer into given disk
  473.  */
  474. int bbinstall (struct IOStdReq *disk, byte *buffer)
  475. {
  476.  int error;
  477.  
  478.  disk->io_Command = TD_PROTSTATUS;        /* check write protection */
  479.  DoIO (disk);
  480.  
  481.  if (disk->io_Actual != 0)
  482.  {
  483.    notify ("disk is write-protected");
  484.    return (FALSE);
  485.  };
  486.  
  487.  error = 0;
  488.  disk->io_Length  = BBSIZE;
  489.  disk->io_Data    = (APTR)buffer;
  490.  disk->io_Command = CMD_WRITE;
  491.  disk->io_Offset  = 0;
  492.  DoIO (disk);
  493.  
  494.  error = disk->io_Error;
  495.  
  496.  if (error < 19)
  497.  {
  498.    disk->io_Command = CMD_UPDATE;    /* flush buffer to disk */
  499.    DoIO (disk);
  500.    error = disk->io_Error;
  501.  };
  502.  
  503.  if (error < 19)
  504.  {
  505.    disk->io_Length  = 0;
  506.    disk->io_Command = ETD_MOTOR;    /* turn motor off */
  507.    DoIO (disk);
  508.    error = disk->io_Error;
  509.  };
  510.  
  511.  if (error < 19)
  512.    return (TRUE);
  513.  else
  514.  {
  515.    notify ("could not install bootblock");
  516.    return (FALSE);
  517.  }
  518. }
  519.  
  520.  
  521. /*
  522.  *  reads a bootblock (from given disk IO request) into buffer
  523.  */
  524. int bbread (struct IOStdReq *disk, byte *buffer)
  525. {
  526.  disk->io_Command = CMD_READ;
  527.  disk->io_Data    = (APTR)buffer;
  528.  disk->io_Length  = BBSIZE;
  529.  disk->io_Offset  = 0;
  530.  DoIO (disk);
  531.  
  532.  if (disk->io_Error > 0)
  533.  {
  534.    notify ("could not read bootblock");
  535.    return (FALSE);
  536.  }
  537.  else
  538.  {
  539.    disk->io_Length  = 0;
  540.    disk->io_Command = TD_MOTOR;
  541.    DoIO (disk);
  542.    return (TRUE);
  543.  }
  544. }
  545.