home *** CD-ROM | disk | FTP | other *** search
- /* Program to load an image into the SPARClite monitor board via Ethernet
- Copyright 1993 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Call with:
-
- eload PROG HOSTNAME
-
- (HOSTNAME is the name (or IP address) of your eval board)
-
- ie: eload hello sparky
-
- */
-
- #include <stdio.h>
- #include <stdarg.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <unistd.h>
- #define min(A, B) (((A) < (B)) ? (A) : (B))
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <bfd.h>
- #include <fcntl.h>
- #include <sys/time.h>
-
- /* Where the code goes by default. */
-
- #ifndef LOAD_ADDRESS
- #define LOAD_ADDRESS 0x40000000
- #endif
-
- extern void *malloc();
-
- static void
- usage()
- {
- fprintf(stderr, "usage: eload executable-file network-name\n");
- exit(1);
- }
-
- static void
- sys_error(const char *msg, ...)
- {
- int e = errno;
- va_list args;
-
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
-
- fprintf(stderr, ": %s\n", strerror(e));
- exit(1);
- }
-
- static void
- error(const char *msg, ...)
- {
- va_list args;
-
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
-
- fputc('\n', stderr);
- exit(1);
- }
-
- int netfd;
-
- static void
- sendex(outtxt, outlen, intxt, inlen, id)
- unsigned char *outtxt;
- int outlen;
- unsigned char *intxt;
- int inlen;
- char *id;
- {
- char buf[100];
- int cc;
-
- #if 0
- if (outlen > 0)
- {
- cc = write(fileno(ttyf), outtxt, outlen);
- if (cc != outlen)
- sys_error("Write %s failed", id);
- }
-
- if (inlen > 0)
- {
- cc = read(fileno(ttyf), buf, inlen); /* Get reply */
- if (cc != inlen)
- sys_error("Read %s reply failed", id);
- if (bcmp(buf, intxt, inlen) != 0)
- error("Bad reply to %s", id);
- }
- #endif
- }
-
- static int
- recv_buf (fd, buf, len, timeout)
- int fd, len;
- unsigned char *buf;
- int timeout;
- {
- int cc;
- fd_set readfds;
-
- FD_ZERO (&readfds);
- FD_SET (fd, &readfds);
-
- if (timeout >= 0)
- {
- struct timeval timebuf;
-
- timebuf.tv_sec = timeout;
- timebuf.tv_usec = 0;
- cc = select (fd + 1, &readfds, 0, 0, &timebuf);
- }
- else
- cc = select (fd + 1, &readfds, 0, 0, 0);
-
- if (cc == 0)
- return 0;
-
- if (cc != 1)
- sys_error ("recv_buf: Bad return value from select:");
-
- cc = recv (fd, buf, len, 0);
-
- if (cc < 0)
- sys_error ("Got an error from recv: ");
- }
-
- static int
- send_buf (fd, buf, len)
- int fd, len;
- unsigned char *buf;
- {
- int cc;
-
- cc = send (fd, buf, len, 0);
-
- if (cc == len)
- return;
-
- if (cc < 0)
- sys_error ("Got an error from send: ");
-
- printf ("Short count in send: tried %d, sent %d\n", len, cc);
- }
-
- static unsigned short
- calc_checksum (buffer, count)
- unsigned char *buffer;
- int count;
- {
- unsigned short checksum;
- unsigned short *s;
-
- s = (unsigned short *)buffer;
-
- checksum = 0;
- for (; count > 0; count -= 2)
- checksum += *s++;
-
- if (count != 0)
- checksum += (*s & 0xff00);
-
- return checksum;
- }
-
- static void
- send_data (buffer, fd, addr, count)
- unsigned char *buffer;
- int fd;
- unsigned long addr;
- int count;
- {
- static int pkt_num = 0;
- unsigned char snd_buf[2000];
- unsigned short checksum;
- int cc;
- int i;
- static unsigned long old_addr = -1;
-
- while (1)
- {
-
- if (addr != old_addr)
- {
- snd_buf[0] = 0x1; /* Load command */
- snd_buf[1] = 0x1; /* Loading address */
- snd_buf[2] = addr >> 24;
- snd_buf[3] = addr >> 16;
- snd_buf[4] = addr >> 8;
- snd_buf[5] = addr;
-
- checksum = 0;
- for (i = 0; i < 6; i++)
- checksum += snd_buf[i];
- checksum &= 0xff;
-
- send_buf (fd, snd_buf, 6);
- cc = recv_buf (fd, snd_buf, sizeof snd_buf, -1);
-
- if (cc < 1)
- {
- fprintf (stderr, "Got back short checksum for load addr\n");
- exit (1);
- }
-
- if (checksum != snd_buf[0])
- {
- fprintf (stderr, "Got back bad checksum for load addr\n");
- exit (1);
- }
- pkt_num = 0; /* Load addr resets packet seq # */
- old_addr = addr;
- }
-
- memcpy (snd_buf + 6, buffer, count);
-
- checksum = calc_checksum (buffer, count);
-
- snd_buf[0] = 0x1; /* Load command */
- snd_buf[1] = 0x2; /* Loading data */
- snd_buf[2] = pkt_num >> 8;
- snd_buf[3] = pkt_num;
- snd_buf[4] = checksum >> 8;
- snd_buf[5] = checksum;
-
- send_buf (fd, snd_buf, count + 6);
- cc = recv_buf (fd, snd_buf, sizeof snd_buf, 3);
-
- if (cc == 0)
- {
- fprintf (stderr, "send_data: timeout sending %d bytes to address 0x%x retrying\n", count, addr);
- continue;
- }
-
- if (cc < 1)
- {
- fprintf (stderr, "Got back short response for load data\n");
- exit (1);
- }
-
- if (snd_buf[0] != 0xff)
- {
- fprintf (stderr, "Got back bad response for load data\n");
- exit (1);
- }
-
- old_addr += count;
- pkt_num++;
-
- return;
- }
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- struct termios termios;
- int cc, progsize, i;
- unsigned char buf[10];
- asection *section;
- bfd *pbfd;
- unsigned long entry;
- struct hostent *he;
- struct sockaddr_in sockaddr;
-
- extern int optind;
- int c;
-
- while ((c = getopt(argc, argv, "")) != EOF)
- {
- switch (c)
- {
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 2)
- usage();
-
- pbfd = bfd_openr(argv[1], 0);
-
- if (!pbfd)
- sys_error("Open of PROG failed");
-
- /* Setup the socket. Must be raw UDP. */
-
- he = gethostbyname (argv[2]);
-
- if (!he)
- sys_error ("No such host");
-
- netfd = socket (PF_INET, SOCK_DGRAM, 0);
-
- sockaddr.sin_family = PF_INET;
- sockaddr.sin_port = htons(7000);
- memcpy (&sockaddr.sin_addr.s_addr, he->h_addr, sizeof (struct in_addr));
-
- if (connect (netfd, &sockaddr, sizeof(sockaddr)))
- sys_error ("Connect failed");
-
- buf[0] = 0x5;
- buf[1] = 0;
-
- send_buf (netfd, buf, 2); /* Request version */
- cc = recv_buf (netfd, buf, sizeof(buf), -1); /* Get response */
-
- if (cc < 3)
- {
- fprintf(stderr, "SPARClite appears to be ill\n");
- exit (1);
- }
-
- printf("[SPARClite appears to be alive]\n");
-
- if (!bfd_check_format (pbfd, bfd_object))
- error ("It doesn't seem to be an object file");
-
- for (section = pbfd->sections; section; section = section->next)
- {
- if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
- {
- bfd_vma section_address;
- unsigned long section_size;
- const char *section_name;
-
- section_name = bfd_get_section_name (pbfd, section);
-
- section_address = bfd_get_section_vma (pbfd, section);
- /* Adjust sections from a.out files, since they don't
- carry their addresses with. */
- if (bfd_get_flavour (pbfd) == bfd_target_aout_flavour)
- section_address += LOAD_ADDRESS;
- section_size = bfd_section_size (pbfd, section);
-
- printf("[Loading section %s at %x (%d bytes)]\n",
- section_name,
- section_address,
- section_size);
-
- if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
- {
- file_ptr fptr;
-
- fptr = 0;
-
- while (section_size > 0)
- {
- char buffer[1024];
- int count, i;
- unsigned char checksum;
- static char inds[] = "|/-\\";
- static int k = 0;
-
- count = min (section_size, 1024);
-
- bfd_get_section_contents (pbfd, section, buffer, fptr,
- count);
-
- #if 0
- checksum = 0;
- for (i=0; i < count; i++)
- checksum += buffer[i];
- #endif
-
- printf("\r%c", inds[k++ % 4]);
- fflush(stdout);
-
- send_data (buffer, netfd, section_address, count);
- #if 0
- sendex("\001", 1, "\x5a", 1, "load command");
- sendex(§ion_address, 4, NULL, 0, "load address");
- sendex(&count, 4, NULL, 0, "program size");
- sendex(buffer, count, &checksum, 1, "program");
- #endif
-
- section_address += count;
- fptr += count;
- section_size -= count;
- }
- }
- else /* BSS */
- printf ("Not loading BSS \n");
- }
- }
-
- entry = bfd_get_start_address (pbfd);
-
- printf("[Starting %s at 0x%x]\n", argv[1], entry);
-
- #if 0
- sendex("\003", 1, NULL, 0, "exec command");
- sendex(&entry, 4, "\x55", 1, "program start");
- #endif
-
- buf[0] = 0x3;
- buf[1] = 0;
- buf[2] = entry >> 24;
- buf[3] = entry >> 16;
- buf[4] = entry >> 8;
- buf[5] = entry;
-
- send_buf (netfd, buf, 6); /* Send start addr */
- cc = recv_buf (netfd, buf, sizeof(buf), -1); /* Get response */
-
- if (cc < 1 || buf[0] != 0x55)
- {
- fprintf(stderr, "Failed to take start address\n");
- exit (1);
- }
- }
-