home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / sparclite / eload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-09  |  8.8 KB  |  441 lines

  1. /* Program to load an image into the SPARClite monitor board via Ethernet
  2.    Copyright 1993 Free Software Foundation, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Call with:
  19.  
  20.    eload PROG HOSTNAME
  21.  
  22. (HOSTNAME is the name (or IP address) of your eval board)
  23.  
  24. ie: eload hello sparky
  25.  
  26. */
  27.  
  28. #include <stdio.h>
  29. #include <stdarg.h>
  30. #include <errno.h>
  31. #include <fcntl.h>
  32. #include <termios.h>
  33. #include <unistd.h>
  34. #define min(A, B) (((A) < (B)) ? (A) : (B))
  35.  
  36. #include <sys/types.h>
  37. #include <sys/socket.h>
  38. #include <netdb.h>
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <bfd.h>
  42. #include <fcntl.h>
  43. #include <sys/time.h>
  44.  
  45. /* Where the code goes by default. */
  46.  
  47. #ifndef LOAD_ADDRESS
  48. #define LOAD_ADDRESS 0x40000000
  49. #endif
  50.  
  51. extern void *malloc();
  52.  
  53. static void
  54. usage()
  55. {
  56.   fprintf(stderr, "usage: eload executable-file network-name\n");
  57.   exit(1);
  58. }
  59.  
  60. static void
  61. sys_error(const char *msg, ...)
  62. {
  63.   int e = errno;
  64.   va_list args;
  65.  
  66.   va_start(args, msg);
  67.   vfprintf(stderr, msg, args);
  68.   va_end(args);
  69.  
  70.   fprintf(stderr, ": %s\n", strerror(e));
  71.   exit(1);
  72. }
  73.  
  74. static void
  75. error(const char *msg, ...)
  76. {
  77.   va_list args;
  78.  
  79.   va_start(args, msg);
  80.   vfprintf(stderr, msg, args);
  81.   va_end(args);
  82.  
  83.   fputc('\n', stderr);
  84.   exit(1);
  85. }
  86.  
  87. int netfd;
  88.  
  89. static void
  90. sendex(outtxt, outlen, intxt, inlen, id)
  91.      unsigned char *outtxt;
  92.      int outlen;
  93.      unsigned char *intxt;
  94.      int inlen;
  95.      char *id;
  96. {
  97.   char buf[100];
  98.   int cc;
  99.  
  100. #if 0
  101.   if (outlen > 0)
  102.     {
  103.       cc = write(fileno(ttyf), outtxt, outlen);
  104.       if (cc != outlen)
  105.     sys_error("Write %s failed", id);
  106.     }
  107.  
  108.   if (inlen > 0)
  109.     {
  110.       cc = read(fileno(ttyf), buf, inlen);    /* Get reply */
  111.       if (cc != inlen)
  112.     sys_error("Read %s reply failed", id);
  113.       if (bcmp(buf, intxt, inlen) != 0)
  114.     error("Bad reply to %s", id);
  115.     }
  116. #endif
  117. }
  118.  
  119. static int
  120. recv_buf (fd, buf, len, timeout)
  121.      int fd, len;
  122.      unsigned char *buf;
  123.      int timeout;
  124. {
  125.   int cc;
  126.   fd_set readfds;
  127.  
  128.   FD_ZERO (&readfds);
  129.   FD_SET (fd, &readfds);
  130.  
  131.   if (timeout >= 0)
  132.     {
  133.       struct timeval timebuf;
  134.  
  135.       timebuf.tv_sec = timeout;
  136.       timebuf.tv_usec = 0;
  137.       cc = select (fd + 1, &readfds, 0, 0, &timebuf);
  138.     }
  139.   else
  140.     cc = select (fd + 1, &readfds, 0, 0, 0);
  141.  
  142.   if (cc == 0)
  143.     return 0;
  144.  
  145.   if (cc != 1)
  146.     sys_error ("recv_buf: Bad return value from select:");
  147.  
  148.   cc = recv (fd, buf, len, 0);
  149.  
  150.   if (cc < 0)
  151.     sys_error ("Got an error from recv: ");
  152. }
  153.  
  154. static int
  155. send_buf (fd, buf, len)
  156.      int fd, len;
  157.      unsigned char *buf;
  158. {
  159.   int cc;
  160.  
  161.   cc = send (fd, buf, len, 0);
  162.  
  163.   if (cc == len)
  164.     return;
  165.  
  166.   if (cc < 0)
  167.     sys_error ("Got an error from send: ");
  168.  
  169.   printf ("Short count in send: tried %d, sent %d\n", len, cc);
  170. }
  171.  
  172. static unsigned short
  173. calc_checksum (buffer, count)
  174.      unsigned char *buffer;
  175.      int count;
  176. {
  177.   unsigned short checksum;
  178.   unsigned short *s;
  179.  
  180.   s = (unsigned short *)buffer;
  181.  
  182.   checksum = 0;
  183.   for (; count > 0; count -= 2)
  184.     checksum += *s++;
  185.  
  186.   if (count != 0)
  187.     checksum += (*s & 0xff00);
  188.  
  189.   return checksum;
  190. }
  191.  
  192. static void
  193. send_data (buffer, fd, addr, count)
  194.      unsigned char *buffer;
  195.      int fd;
  196.      unsigned long addr;
  197.      int count;
  198. {
  199.   static int pkt_num = 0;
  200.   unsigned char snd_buf[2000];
  201.   unsigned short checksum;
  202.   int cc;
  203.   int i;
  204.   static unsigned long old_addr = -1;
  205.  
  206.   while (1)
  207.     {
  208.  
  209.       if (addr != old_addr)
  210.     {
  211.       snd_buf[0] = 0x1;    /* Load command */
  212.       snd_buf[1] = 0x1;    /* Loading address */
  213.       snd_buf[2] = addr >> 24;
  214.       snd_buf[3] = addr >> 16;
  215.       snd_buf[4] = addr >> 8;
  216.       snd_buf[5] = addr;
  217.  
  218.       checksum = 0;
  219.       for (i = 0; i < 6; i++)
  220.         checksum += snd_buf[i];
  221.       checksum &= 0xff;
  222.  
  223.       send_buf (fd, snd_buf, 6);
  224.       cc = recv_buf (fd, snd_buf, sizeof snd_buf, -1);
  225.  
  226.       if (cc < 1)
  227.         {
  228.           fprintf (stderr, "Got back short checksum for load addr\n");
  229.           exit (1);
  230.         }
  231.  
  232.       if (checksum != snd_buf[0])
  233.         {
  234.           fprintf (stderr, "Got back bad checksum for load addr\n");
  235.           exit (1);
  236.         }
  237.       pkt_num = 0;        /* Load addr resets packet seq # */
  238.       old_addr = addr;
  239.     }
  240.  
  241.       memcpy (snd_buf + 6, buffer, count);
  242.  
  243.       checksum = calc_checksum (buffer, count);
  244.  
  245.       snd_buf[0] = 0x1;        /* Load command */
  246.       snd_buf[1] = 0x2;        /* Loading data */
  247.       snd_buf[2] = pkt_num >> 8;
  248.       snd_buf[3] = pkt_num;
  249.       snd_buf[4] = checksum >> 8;
  250.       snd_buf[5] = checksum;
  251.  
  252.       send_buf (fd, snd_buf, count + 6);
  253.       cc = recv_buf (fd, snd_buf, sizeof snd_buf, 3);
  254.  
  255.       if (cc == 0)
  256.     {
  257.       fprintf (stderr, "send_data: timeout sending %d bytes to address 0x%x retrying\n", count, addr);
  258.       continue;
  259.     }
  260.  
  261.       if (cc < 1)
  262.     {
  263.       fprintf (stderr, "Got back short response for load data\n");
  264.       exit (1);
  265.     }
  266.  
  267.       if (snd_buf[0] != 0xff)
  268.     {
  269.       fprintf (stderr, "Got back bad response for load data\n");
  270.       exit (1);
  271.     }
  272.  
  273.       old_addr += count;
  274.       pkt_num++;
  275.  
  276.       return;
  277.     }
  278. }
  279.  
  280. main(argc, argv)
  281.      int argc;
  282.      char **argv;
  283. {
  284.   struct termios termios;
  285.   int cc, progsize, i;
  286.   unsigned char buf[10];
  287.   asection *section;
  288.   bfd *pbfd;
  289.   unsigned long entry;
  290.   struct hostent *he;
  291.   struct sockaddr_in sockaddr;
  292.  
  293.   extern int optind;
  294.   int c;
  295.  
  296.   while ((c = getopt(argc, argv, "")) != EOF)
  297.     {
  298.       switch (c)
  299.     {
  300.     default:
  301.       usage();
  302.     }
  303.     }
  304.   argc -= optind;
  305.   argv += optind;
  306.  
  307.   if (argc != 2) 
  308.       usage();
  309.  
  310.   pbfd = bfd_openr(argv[1], 0);
  311.  
  312.   if (!pbfd)
  313.     sys_error("Open of PROG failed");
  314.  
  315. /* Setup the socket.  Must be raw UDP. */
  316.  
  317.   he = gethostbyname (argv[2]);
  318.  
  319.   if (!he)
  320.     sys_error ("No such host");
  321.  
  322.   netfd = socket (PF_INET, SOCK_DGRAM, 0);
  323.  
  324.   sockaddr.sin_family = PF_INET;
  325.   sockaddr.sin_port = htons(7000);
  326.   memcpy (&sockaddr.sin_addr.s_addr, he->h_addr, sizeof (struct in_addr));
  327.  
  328.   if (connect (netfd, &sockaddr, sizeof(sockaddr)))
  329.     sys_error ("Connect failed");
  330.  
  331.   buf[0] = 0x5;
  332.   buf[1] = 0;
  333.  
  334.   send_buf (netfd, buf, 2);    /* Request version */
  335.   cc = recv_buf (netfd, buf, sizeof(buf), -1); /* Get response */
  336.  
  337.   if (cc < 3)
  338.     {
  339.       fprintf(stderr, "SPARClite appears to be ill\n");
  340.       exit (1);
  341.     }
  342.  
  343.   printf("[SPARClite appears to be alive]\n");
  344.  
  345.   if (!bfd_check_format (pbfd, bfd_object)) 
  346.     error ("It doesn't seem to be an object file");
  347.  
  348.   for (section = pbfd->sections; section; section = section->next) 
  349.     {
  350.       if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
  351.     {
  352.       bfd_vma section_address;
  353.       unsigned long section_size;
  354.       const char *section_name;
  355.  
  356.       section_name = bfd_get_section_name (pbfd, section);
  357.  
  358.       section_address = bfd_get_section_vma (pbfd, section);
  359.       /* Adjust sections from a.out files, since they don't
  360.          carry their addresses with.  */
  361.       if (bfd_get_flavour (pbfd) == bfd_target_aout_flavour)
  362.         section_address += LOAD_ADDRESS;
  363.       section_size = bfd_section_size (pbfd, section);
  364.  
  365.       printf("[Loading section %s at %x (%d bytes)]\n",
  366.          section_name,
  367.          section_address,
  368.          section_size);
  369.  
  370.       if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
  371.         {
  372.           file_ptr fptr;
  373.  
  374.           fptr = 0;
  375.  
  376.           while (section_size > 0)
  377.         {
  378.           char buffer[1024];
  379.           int count, i;
  380.           unsigned char checksum;
  381.           static char inds[] = "|/-\\";
  382.           static int k = 0;
  383.  
  384.           count = min (section_size, 1024);
  385.  
  386.           bfd_get_section_contents (pbfd, section, buffer, fptr,
  387.                         count);
  388.  
  389. #if 0
  390.           checksum = 0;
  391.           for (i=0; i < count; i++)
  392.             checksum += buffer[i];
  393. #endif
  394.  
  395.           printf("\r%c", inds[k++ % 4]);
  396.           fflush(stdout);
  397.  
  398.           send_data (buffer, netfd, section_address, count);
  399. #if 0
  400.           sendex("\001", 1, "\x5a", 1, "load command");
  401.           sendex(§ion_address, 4, NULL, 0, "load address");
  402.           sendex(&count, 4, NULL, 0, "program size");
  403.           sendex(buffer, count, &checksum, 1, "program");
  404. #endif
  405.  
  406.           section_address += count;
  407.           fptr += count;
  408.           section_size -= count;
  409.         }
  410.         }
  411.       else            /* BSS */
  412.         printf ("Not loading BSS \n");
  413.     }
  414.     }
  415.  
  416.   entry = bfd_get_start_address (pbfd);
  417.   
  418.   printf("[Starting %s at 0x%x]\n", argv[1], entry);
  419.  
  420. #if 0
  421.   sendex("\003", 1, NULL, 0, "exec command");
  422.   sendex(&entry, 4, "\x55", 1, "program start");
  423. #endif
  424.  
  425.   buf[0] = 0x3;
  426.   buf[1] = 0;
  427.   buf[2] = entry >> 24;
  428.   buf[3] = entry >> 16;
  429.   buf[4] = entry >> 8;
  430.   buf[5] = entry;
  431.  
  432.   send_buf (netfd, buf, 6);    /* Send start addr */
  433.   cc = recv_buf (netfd, buf, sizeof(buf), -1); /* Get response */
  434.  
  435.   if (cc < 1 || buf[0] != 0x55)
  436.     {
  437.       fprintf(stderr, "Failed to take start address\n");
  438.       exit (1);
  439.     }
  440. }
  441.