URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [insight/] [utils/] [sparclite/] [eload.c] - Rev 1778
Go to most recent revision | Compare with Previous | Blame | View Log
/* 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 "ansidecl.h" #ifdef ANSI_PROTOTYPES #include <stdarg.h> #else #include <varargs.h> #endif #include "libiberty.h" #include "bfd.h" #include <errno.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <sys/time.h> #define min(A, B) (((A) < (B)) ? (A) : (B)) /* Where the code goes by default. */ #ifndef LOAD_ADDRESS #define LOAD_ADDRESS 0x40000000 #endif static void usage() { fprintf (stderr, "usage: eload executable-file network-name\n"); exit (1); } static void #ifdef ANSI_PROTOTYPES sys_error (char *msg, ...) #else sys_error (va_alist) va_dcl #endif { int e = errno; va_list args; #ifdef ANSI_PROTOTYPES va_start (args, msg); #else va_start (args); #endif #ifdef ANSI_PROTOTYPES vfprintf (stderr, msg, args); #else { char *msg1; msg1 = va_arg (args, char *); vfprintf (stderr, msg1, args); } #endif va_end (args); fprintf (stderr, ": %s\n", strerror(e)); exit (1); } static void #ifdef ANSI_PROTOTYPES error (char *msg, ...) #else error (va_alist) va_dcl #endif { va_list args; #ifdef ANSI_PROTOTYPES va_start (args, msg); #else va_start (args); #endif #ifdef ANSI_PROTOTYPES vfprintf (stderr, msg, args); #else { char *msg1; msg1 = va_arg (args, char *); vfprintf (stderr, msg1, args); } #endif va_end (args); fputc ('\n', stderr); exit (1); } int netfd; 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: "); return cc; } static void 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; { int cc, i; static int pkt_num = 0; unsigned char snd_buf[2000]; unsigned short checksum; 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 addr 0x%lx, 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; } } extern int optind; int main (argc, argv) int argc; char **argv; { int cc, c; unsigned char buf[10]; asection *section; bfd *pbfd; unsigned long entry; struct hostent *he; struct sockaddr_in sockaddr; 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 == NULL) 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 %lx (%ld bytes)]\n", section_name, section_address, section_size); /* Text, data or lit */ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) { file_ptr fptr; fptr = 0; while (section_size > 0) { char buffer[1024]; int count; static char inds[] = "|/-\\"; static int k = 0; count = min (section_size, 1024); bfd_get_section_contents (pbfd, section, buffer, fptr, count); #if 0 { int i; unsigned char checksum; 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); 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%lx]\n", argv[1], entry); 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); } exit (0); }
Go to most recent revision | Compare with Previous | Blame | View Log