OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/initial/orpmon/services
    from Rev 811 to Rev 1765
    Reverse comparison

Rev 811 → Rev 1765

/.Makefile.swp
0,0 → 1,10
 
 
+Ï — ƒ € a ` O N # ú ù í ì Ó » º p o O ' &   Ê +#########################################################################sinclude .depend $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@.depend: Makefile $(OBJS:.o=.c)######################################################################### $(LD) -r -o $@ $(OBJS)$(LIB): $(START) $(OBJS)all: $(LIB)OBJS = net.o tftp.o bootp.o rarp.o arp.o# OBJS = net.o tftp.o bootp.o rarp.o arp.oLIB = services.o# CFLAGS += -DET_DEBUG -DDEBUG## MA 02111-1307 USA# Foundation, Inc., 59 Temple Place, Suite 330, Boston,# along with this program; if not, write to the Free Software# You should have received a copy of the GNU General Public License## GNU General Public License for more details.# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# but WITHOUT ANY WARRANTY; without even the implied warranty of# This program is distributed in the hope that it will be useful,## the License, or (at your option) any later version.# published by the Free Software Foundation; either version 2 of# modify it under the terms of the GNU General Public License as# This program is free software; you can redistribute it and/or## project.# See file CREDITS for list of people who contributed to this## Wolfgang Denk, DENX Software Engineering, wd@denx.de.# (C) Copyright 2000## (C) Marko Mlinar, based on ppcboot \ No newline at end of file
/arp.c
0,0 → 1,110
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
 
#include "common.h"
#include "support.h"
#include "net.h"
#include "bootp.h"
#include "tftp.h"
#include "arp.h"
 
 
#define TIMEOUT 5 /* Seconds before trying ARP again */
#define TIMEOUT_COUNT 1 /* # of timeouts before giving up */
 
static void ArpHandler(unsigned char *pkt, unsigned dest, unsigned src, unsigned len);
static void ArpTimeout(void);
 
int ArpTry = 0;
 
/*
* Handle a ARP received packet.
*/
static void
ArpHandler(unsigned char *pkt, unsigned dest, unsigned src, unsigned len)
{
/* Check if the frame is really an ARP reply */
if (memcmp (NetServerEther, NetBcastAddr, 6) != 0) {
#ifdef DEBUG
printf("Got good ARP - start TFTP\n");
#endif
TftpStart ();
}
}
 
 
/*
* Timeout on ARP request.
*/
static void
ArpTimeout(void)
{
if (ArpTry >= TIMEOUT_COUNT) {
printf("\nRetry count exceeded; starting again\n");
NetStartAgain ();
} else {
NetSetTimeout (TIMEOUT * IN_CLK, ArpTimeout);
ArpRequest ();
}
}
 
 
void
ArpRequest (void)
{
int i;
volatile unsigned char *pkt;
ARP_t * arp;
 
printf("ARP broadcast %d\n", ++ArpTry);
pkt = NetTxPacket;
 
NetSetEther(pkt, NetBcastAddr, PROT_ARP);
pkt += ETHER_HDR_SIZE;
 
arp = (ARP_t *)pkt;
 
arp->ar_hrd = ARP_ETHER;
arp->ar_pro = PROT_IP;
arp->ar_hln = 6;
arp->ar_pln = 4;
arp->ar_op = ARPOP_REQUEST;
NetCopyEther(&arp->ar_data[0], NetOurEther); /* source ET addr */
*(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP; /* source IP addr */
for (i=10; i<16; ++i) {
arp->ar_data[i] = 0; /* dest ET addr = 0 */
}
 
if((NetServerIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) {
*(IPaddr_t *)(&arp->ar_data[16]) = NetOurGatewayIP;
} else {
*(IPaddr_t *)(&arp->ar_data[16]) = NetServerIP;
}
 
 
NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
 
NetSetTimeout(TIMEOUT * IN_CLK, ArpTimeout);
NetSetHandler(ArpHandler);
}
 
/tftp.h
0,0 → 1,21
/*
* LiMon - BOOTP/TFTP.
*
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
*/
 
#ifndef __TFTP_H__
#define __TFTP_H__
 
/**********************************************************************/
/*
* Global functions and variables.
*/
 
/* tftp.c */
extern void TftpStart (void); /* Begin TFTP get */
 
/**********************************************************************/
 
#endif /* __TFTP_H__ */
/bootp.c
0,0 → 1,863
/*
* Based on LiMon - BOOTP.
*
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
* Copyright 2000 Roland Borde
* Copyright 2000 Paolo Scaffardi
*/
 
#if 0
#define DEBUG 1 /* general debug */
#define DEBUG_BOOTP_EXT 1 /* Debug received vendor fields */
#endif
 
#ifdef DEBUG_BOOTP_EXT
#define debug_ext(fmt,args...) printf (fmt ,##args)
#else
#define debug_ext(fmt,args...)
#endif
 
#include "common.h"
#include "net.h"
#include "bootp.h"
#include "tftp.h"
#include "arp.h"
 
#define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
 
#if (CONFIG_COMMANDS & CFG_CMD_NET)
 
#define TIMEOUT 5 /* Seconds before trying BOOTP again */
#define TIMEOUT_COUNT 1 /* # of timeouts before giving up */
 
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
 
#ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
#define CONFIG_DHCP_MIN_EXT_LEN 64
#endif
 
ulong BootpID;
int BootpTry;
#ifdef CONFIG_BOOTP_RANDOM_DELAY
ulong seed1, seed2;
#endif
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
dhcp_state_t dhcp_state = INIT;
unsigned int dhcp_leasetime = 0;
static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
 
/* For Debug */
char *dhcpmsg2str(int type)
{
switch (type) {
case 1: return "DHCPDISCOVER"; break;
case 2: return "DHCPOFFER"; break;
case 3: return "DHCPREQUEST"; break;
case 4: return "DHCPDECLINE"; break;
case 5: return "DHCPACK"; break;
case 6: return "DHCPNACK"; break;
case 7: return "DHCPRELEASE"; break;
default: return "UNKNOWN/INVALID MSG TYPE"; break;
}
}
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL */
#endif
 
#endif /* CFG_CMD_DHCP */
 
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
{
Bootp_t *bp = (Bootp_t *) pkt;
int retval = 0;
 
if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
retval = -1;
if (len < sizeof (Bootp_t) - OPT_SIZE)
retval = -2;
if (bp->bp_op != OP_BOOTREQUEST &&
bp->bp_op != OP_BOOTREPLY &&
bp->bp_op != DHCP_OFFER &&
bp->bp_op != DHCP_ACK &&
bp->bp_op != DHCP_NAK ) {
retval = -3;
}
if (bp->bp_htype != HWT_ETHER)
retval = -4;
if (bp->bp_hlen != HWL_ETHER)
retval = -5;
if (bp->bp_id != BootpID)
retval = -6;
 
debug ("Filtering pkt = %d\n", retval);
 
return retval;
}
 
/*
* Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
*/
void BootpCopyNetParams(Bootp_t *bp)
{
NetOurIP = bp->bp_yiaddr;
NetServerIP = bp->bp_siaddr;
NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
 
debug ("Bootfile: %s\n", BootFile);
 
/* Propagate to environment:
* don't delete exising entry when BOOTP / DHCP reply does
* not contain a new value
*/
if (*BootFile) {
setenv ("bootfile", BootFile);
}
}
 
static int truncate_sz (const char *name, int maxlen, int curlen)
{
if (curlen >= maxlen) {
printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
name, curlen, maxlen);
curlen = maxlen - 1;
}
return (curlen);
}
 
#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
 
static void BootpVendorFieldProcess(u8 *ext)
{
int size = *(ext+1) ;
 
debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
 
NetBootFileSize = 0;
 
switch (*ext) {
/* Fixed length fields */
case 1: /* Subnet mask */
if (NetOurSubnetMask == 0)
memcpy(&NetOurSubnetMask, ext+2, 4);
break;
case 2: /* Time offset - Not yet supported */
break;
/* Variable length fields */
case 3: /* Gateways list */
if (NetOurGatewayIP == 0) {
memcpy(&NetOurGatewayIP, ext+2, 4);
}
break;
case 4: /* Time server - Not yet supported */
break;
case 5: /* IEN-116 name server - Not yet supported */
break;
case 6:
if (NetOurDNSIP == 0) {
memcpy(&NetOurDNSIP, ext+2, 4);
}
break;
case 7: /* Log server - Not yet supported */
break;
case 8: /* Cookie/Quote server - Not yet supported */
break;
case 9: /* LPR server - Not yet supported */
break;
case 10: /* Impress server - Not yet supported */
break;
case 11: /* RPL server - Not yet supported */
break;
case 12: /* Host name */
if (NetOurHostName[0] == 0) {
size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
memcpy(&NetOurHostName, ext+2, size);
NetOurHostName[size] = 0 ;
}
break;
case 13: /* Boot file size */
memcpy(&NetBootFileSize, ext+2, size);
break;
case 14: /* Merit dump file - Not yet supported */
break;
case 15: /* Domain name - Not yet supported */
break;
case 16: /* Swap server - Not yet supported */
break;
case 17: /* Root path */
if (NetOurRootPath[0] == 0) {
size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
memcpy(&NetOurRootPath, ext+2, size);
NetOurRootPath[size] = 0 ;
}
break;
case 18: /* Extension path - Not yet supported */
/*
* This can be used to send the informations of the
* vendor area in another file that the client can
* access via TFTP.
*/
break;
/* IP host layer fields */
case 40: /* NIS Domain name */
if (NetOurNISDomain[0] == 0) {
size = truncate_sz ("NIS Domain Name",
sizeof(NetOurNISDomain),
size);
memcpy(&NetOurNISDomain, ext+2, size);
NetOurNISDomain[size] = 0 ;
}
break;
/* Application layer fields */
case 43: /* Vendor specific info - Not yet supported */
/*
* Binary informations to exchange specific
* product information.
*/
break;
/* Reserved (custom) fields (128..254) */
}
}
 
static void BootpVendorProcess(u8 *ext, int size)
{
u8 *end = ext + size ;
 
debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
 
while ((ext < end) && (*ext != 0xff)) {
if (*ext == 0) {
ext ++ ;
} else {
u8 *opt = ext ;
ext += ext[1] + 2 ;
if (ext <= end)
BootpVendorFieldProcess (opt) ;
}
}
 
#ifdef DEBUG_BOOTP_EXT
printf("[BOOTP] Received fields: \n");
if (NetOurSubnetMask) {
puts ("NetOurSubnetMask : ");
print_IPaddr (NetOurSubnetMask);
putc('\n');
}
 
if (NetOurGatewayIP) {
puts ("NetOurGatewayIP : ");
print_IPaddr (NetOurGatewayIP);
putc('\n');
}
 
if (NetBootFileSize) {
printf("NetBootFileSize : %d\n", NetBootFileSize);
}
 
if (NetOurHostName[0]) {
printf("NetOurHostName : %s\n", NetOurHostName);
}
 
if (NetOurRootPath[0]) {
printf("NetOurRootPath : %s\n", NetOurRootPath);
}
 
if (NetOurNISDomain[0]) {
printf("NetOurNISDomain : %s\n", NetOurNISDomain);
}
#endif /* DEBUG_BOOTP_EXT */
}
 
/*
* Handle a BOOTP received packet.
*/
static void
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
Bootp_t *bp;
char *s;
 
debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
src, dest, len, sizeof (Bootp_t));
 
bp = (Bootp_t *)pkt;
 
if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
return;
 
/*
* Got a good BOOTP reply. Copy the data into our variables.
*/
#ifdef CONFIG_STATUS_LED
status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
#endif
 
BootpCopyNetParams(bp); /* Store net parameters from reply */
 
/* Retrieve extended informations (we must parse the vendor area) */
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
BootpVendorProcess(&bp->bp_vend[4], len);
 
NetSetTimeout(0, (thand_f *)0);
 
debug ("Got good BOOTP\n");
 
if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
/*
* Just use BOOTP to configure system;
* Do not use TFTP to load the bootfile.
*/
NetState = NETLOOP_SUCCESS;
return;
}
 
/* Send ARP request to get TFTP server ethernet address.
* This automagically starts TFTP, too.
*/
ArpRequest();
}
#endif /* !CFG_CMD_DHCP */
 
/*
* Timeout on BOOTP/DHCP request.
*/
static void
BootpTimeout(void)
{
if (BootpTry >= TIMEOUT_COUNT) {
puts ("\nRetry count exceeded; starting again\n");
NetStartAgain ();
} else {
NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
BootpRequest ();
}
}
 
/*
* Initialize BOOTP extension fields in the request.
*/
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
{
u8 *start = e ;
u8 *cnt;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
u8 *x;
#endif
 
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
*e++ = 83;
*e++ = 99;
 
*e++ = 53; /* DHCP Message Type */
*e++ = 1;
*e++ = message_type;
 
*e++ = 57; /* Maximum DHCP Message Size */
*e++ = 2;
*e++ = (576-312+OPT_SIZE) >> 8;
*e++ = (576-312+OPT_SIZE) & 0xff;
 
if ( ServerID ) {
*e++ = 54; /* ServerID */
*e++ = 4;
*e++ = ServerID >> 24;
*e++ = ServerID >> 16;
*e++ = ServerID >> 8;
*e++ = ServerID & 0xff;
}
 
if ( RequestedIP ) {
*e++ = 50; /* Requested IP */
*e++ = 4;
*e++ = RequestedIP >> 24;
*e++ = RequestedIP >> 16;
*e++ = RequestedIP >> 8;
*e++ = RequestedIP & 0xff;
}
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
if ((x = dhcp_vendorex_prep (e)))
return x - start ;
#endif
 
*e++ = 55; /* Parameter Request List */
cnt = e++; /* Pointer to count of requested items */
*cnt = 0;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
*e++ = 1; /* Subnet Mask */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
*e++ = 3; /* Router Option */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
*e++ = 6; /* DNS Server(s) */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
*e++ = 12; /* Hostname */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
*e++ = 13; /* Boot File Size */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
*e++ = 17; /* Boot path */
*cnt += 1;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
*e++ = 40; /* NIS Domain name request */
*cnt += 1;
#endif
*e++ = 255; /* End of the list */
 
/* Pad to minimal length */
#ifdef CONFIG_DHCP_MIN_EXT_LEN
while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
*e++ = 0;
#endif
 
return e - start ;
}
 
#else /* CFG_CMD_DHCP */
/*
* Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
*/
static int BootpExtended (u8 *e)
{
u8 *start = e ;
 
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
*e++ = 83;
*e++ = 99;
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
*e++ = 53; /* DHCP Message Type */
*e++ = 1;
*e++ = DHCP_DISCOVER;
 
*e++ = 57; /* Maximum DHCP Message Size */
*e++ = 2;
*e++ = (576-312+OPT_SIZE) >> 16;
*e++ = (576-312+OPT_SIZE) & 0xff;
#endif /* CFG_CMD_DHCP */
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
*e++ = 1; /* Subnet mask request */
*e++ = 4;
e += 4;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
*e++ = 3; /* Default gateway request */
*e++ = 4;
e += 4;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
*e++ = 6; /* Domain Name Server */
*e++ = 4;
e += 4;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
*e++ = 12; /* Host name request */
*e++ = 32;
e += 32;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
*e++ = 13; /* Boot file size */
*e++ = 2;
e += 2;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
*e++ = 17; /* Boot path */
*e++ = 32;
e += 32;
#endif
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
*e++ = 40; /* NIS Domain name request */
*e++ = 32;
e += 32;
#endif
 
*e++ = 255; /* End of the list */
 
return e - start ;
}
#endif /* CFG_CMD_DHCP */
 
void
BootpRequest (void)
{
volatile uchar *pkt, *iphdr;
Bootp_t *bp;
int ext_len, pktlen, iplen;
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
dhcp_state = INIT;
#endif
 
#ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */
unsigned char bi_enetaddr[6];
int reg;
char *e,*s;
uchar tmp[64];
ulong tst1, tst2, sum, m_mask, m_value = 0;
 
if (BootpTry ==0) {
/* get our mac */
reg = getenv_r ("ethaddr", tmp, sizeof(tmp));
s = (reg > 0) ? tmp : NULL;
 
for (reg=0; reg<6; ++reg) {
bi_enetaddr[reg] = s ? simple_strtoul(s, &e, 16) : 0;
if (s) {
s = (*e) ? e+1 : e;
}
}
#ifdef DEBUG
printf("BootpRequest => Our Mac: ");
for (reg=0; reg<6; reg++) {
printf ("%x%c",
bi_enetaddr[reg],
reg==5 ? '\n' : ':');
}
#endif /* DEBUG */
 
/* Mac-Manipulation 2 get seed1 */
tst1=0;
tst2=0;
for (reg=2; reg<6; reg++) {
tst1 = tst1 << 8;
tst1 = tst1 | bi_enetaddr[reg];
}
for (reg=0; reg<2; reg++) {
tst2 = tst2 | bi_enetaddr[reg];
tst2 = tst2 << 8;
}
 
seed1 = tst1^tst2;
 
/* Mirror seed1*/
m_mask=0x1;
for (reg=1;reg<=32;reg++) {
m_value |= (m_mask & seed1);
seed1 = seed1 >> 1;
m_value = m_value << 1;
}
seed1 = m_value;
seed2 = 0xB78D0945;
}
 
/* Random Number Generator */
 
for (reg=0;reg<=0;reg++) {
sum = seed1 + seed2;
if (sum < seed1 || sum < seed2)
sum++;
seed2 = seed1;
seed1 = sum;
 
if (BootpTry<=2) { /* Start with max 1024 * 1ms */
sum = sum >> (22-BootpTry);
} else { /*After 3rd BOOTP request max 8192 * 1ms */
sum = sum >> 19;
}
}
 
printf ("Random delay: %ld ms...\n", sum);
for (reg=0; reg <sum; reg++) {
udelay(1000); /*Wait 1ms*/
}
#endif /* CONFIG_BOOTP_RANDOM_DELAY */
 
printf("BOOTP broadcast %d\n", ++BootpTry);
pkt = NetTxPacket;
memset ((void*)pkt, 0, PKTSIZE);
 
NetSetEther(pkt, NetBcastAddr, PROT_IP);
pkt += ETHER_HDR_SIZE;
 
/*
* Next line results in incorrect packet size being transmitted, resulting
* in errors in some DHCP servers, reporting missing bytes. Size must be
* set in packet header after extension length has been determined.
* C. Hallinan, DS4.COM, Inc.
*/
/* NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
iphdr = pkt; /* We need this later for NetSetIP() */
pkt += IP_HDR_SIZE;
 
bp = (Bootp_t *)pkt;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
bp->bp_ciaddr = 0;
bp->bp_yiaddr = 0;
bp->bp_siaddr = 0;
bp->bp_giaddr = 0;
NetCopyEther(bp->bp_chaddr, NetOurEther);
copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file));
 
/* Request additional information from the BOOTP/DHCP server */
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
ext_len = DhcpExtended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
#else
ext_len = BootpExtended(bp->bp_vend);
#endif /* CFG_CMD_DHCP */
 
/*
* Bootp ID is the lower 4 bytes of our ethernet address
* plus the current time in HZ.
*/
BootpID = ((ulong)NetOurEther[2] << 24)
| ((ulong)NetOurEther[3] << 16)
| ((ulong)NetOurEther[4] << 8)
| (ulong)NetOurEther[5];
BootpID += get_timer(0);
bp->bp_id = BootpID;
 
/*
* Calculate proper packet lengths taking into account the
* variable size of the options field
*/
pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
dhcp_state = SELECTING;
NetSetHandler(DhcpHandler);
#else
NetSetHandler(BootpHandler);
#endif /* CFG_CMD_DHCP */
NetSendPacket(NetTxPacket, pktlen);
}
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
void DhcpOptionsProcess(char *popt)
{
char *end = popt + BOOTP_HDR_SIZE;
int oplen, size;
 
while ( popt < end && *popt != 0xff ) {
oplen = *(popt + 1);
switch(*popt) {
case 1:
NetOurSubnetMask = *(IPaddr_t *)(popt + 2);
break;
case 3:
NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
break;
case 6:
NetOurDNSIP = *(IPaddr_t *)(popt +2);
break;
case 12:
size = truncate_sz ("Host Name",
sizeof(NetOurHostName),
oplen);
memcpy(&NetOurHostName, popt+2, size);
NetOurHostName[size] = 0 ;
break;
case 15: /* Ignore Domain Name Option */
break;
case 17:
size = truncate_sz ("Root Path",
sizeof(NetOurRootPath),
oplen);
memcpy(&NetOurRootPath, popt+2, size);
NetOurRootPath[size] = 0 ;
break;
case 51:
dhcp_leasetime = *(unsigned int *)(popt + 2);
break;
case 53: /* Ignore Message Type Option */
break;
case 54:
NetServerIP = *(IPaddr_t *)(popt+2);
break;
case 58: /* Ignore Renewal Time Option */
break;
case 59: /* Ignore Rebinding Time Option */
break;
default:
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
if (dhcp_vendorex_proc(popt))
break;
#endif
printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
*popt);
break;
}
popt += oplen + 2; /* Process next option */
}
}
 
static int DhcpMessageType(unsigned char *popt)
{
if ((*(uint *)popt) != BOOTP_VENDOR_MAGIC)
return -1;
 
popt += 4;
while ( *popt != 0xff ) {
if ( *popt == 53 ) /* DHCP Message Type */
return *(popt + 2);
popt += *(popt + 1) + 2; /* Scan through all options */
}
return -1;
}
 
void DhcpSendRequestPkt(Bootp_t *bp_offer)
{
volatile uchar *pkt, *iphdr;
Bootp_t *bp;
int pktlen, iplen, extlen;
 
debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
pkt = NetTxPacket;
memset ((void*)pkt, 0, PKTSIZE);
 
NetSetEther(pkt, NetBcastAddr, PROT_IP);
pkt += ETHER_HDR_SIZE;
 
iphdr = pkt; /* We'll need this later to set proper pkt size */
pkt += IP_HDR_SIZE;
 
bp = (Bootp_t *)pkt;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
bp->bp_ciaddr = bp_offer->bp_ciaddr;
bp->bp_yiaddr = bp_offer->bp_yiaddr;
bp->bp_siaddr = bp_offer->bp_siaddr;
bp->bp_giaddr = bp_offer->bp_giaddr;
NetCopyEther(bp->bp_chaddr, NetOurEther);
 
/*
* ID is the id of the OFFER packet
*/
 
bp->bp_id = bp_offer->bp_id;
 
/*
* Copy options from OFFER packet if present
*/
extlen = DhcpExtended(bp->bp_vend, DHCP_REQUEST, NetServerIP, bp->bp_yiaddr);
 
pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
NetSendPacket(NetTxPacket, pktlen);
}
 
/*
* Handle DHCP received packets.
*/
static void
DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
Bootp_t *bp = (Bootp_t *)pkt;
 
debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
src, dest, len, dhcp_state);
 
if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
return;
 
debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
src, dest, len, dhcp_state);
 
switch (dhcp_state) {
case SELECTING:
/*
* Wait an appropriate time for any potential DHCPOFFER packets
* to arrive. Then select one, and generate DHCPREQUEST response.
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
#ifdef CFG_BOOTFILE_PREFIX
if (strncmp(bp->bp_file,
CFG_BOOTFILE_PREFIX,
strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
#endif /* CFG_BOOTFILE_PREFIX */
 
debug ("TRANSITIONING TO REQUESTING STATE\n");
dhcp_state = REQUESTING;
#if 0
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
DhcpOptionsProcess(&bp->bp_vend[4]);
 
#endif
BootpCopyNetParams(bp); /* Store net params from reply */
 
NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
DhcpSendRequestPkt(bp);
#ifdef CFG_BOOTFILE_PREFIX
}
#endif /* CFG_BOOTFILE_PREFIX */
 
return;
break;
case REQUESTING:
debug ("DHCP State: REQUESTING\n");
 
if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
char *s;
 
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
DhcpOptionsProcess(&bp->bp_vend[4]);
BootpCopyNetParams(bp); /* Store net params from reply */
dhcp_state = BOUND;
printf("DHCP client bound to address ");
print_IPaddr(NetOurIP);
printf("\n");
 
/* Obey the 'autoload' setting */
if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
NetState = NETLOOP_SUCCESS;
return;
}
/* Send ARP request to get TFTP server ethernet address.
* This automagically starts TFTP, too.
*/
ArpRequest();
return;
}
break;
default:
printf("DHCP: INVALID STATE\n");
break;
}
 
}
 
void DhcpRequest(void)
{
BootpRequest();
}
#endif /* CFG_CMD_DHCP */
 
#endif /* CFG_CMD_NET */
/rarp.c
0,0 → 1,101
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
 
#include "common.h"
#include "net.h"
#include "bootp.h"
#include "rarp.h"
#include "tftp.h"
 
#if (CONFIG_COMMANDS & CFG_CMD_NET)
 
#define TIMEOUT 5 /* Seconds before trying BOOTP again */
#define TIMEOUT_COUNT 1 /* # of timeouts before giving up */
 
 
int RarpTry;
 
/*
* Handle a RARP received packet.
*/
static void
RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3)
{
#ifdef DEBUG
printf("Got good RARP\n");
#endif
TftpStart ();
}
 
 
/*
* Timeout on BOOTP request.
*/
static void
RarpTimeout(void)
{
if (RarpTry >= TIMEOUT_COUNT) {
puts ("\nRetry count exceeded; starting again\n");
NetStartAgain ();
} else {
NetSetTimeout (TIMEOUT * CFG_HZ, RarpTimeout);
RarpRequest ();
}
}
 
 
void
RarpRequest (void)
{
int i;
volatile uchar *pkt;
ARP_t * rarp;
 
printf("RARP broadcast %d\n", ++RarpTry);
pkt = NetTxPacket;
 
NetSetEther(pkt, NetBcastAddr, PROT_RARP);
pkt += ETHER_HDR_SIZE;
 
rarp = (ARP_t *)pkt;
 
rarp->ar_hrd = ARP_ETHER;
rarp->ar_pro = PROT_IP;
rarp->ar_hln = 6;
rarp->ar_pln = 4;
rarp->ar_op = RARPOP_REQUEST;
NetCopyEther(&rarp->ar_data[0], NetOurEther); /* source ET addr */
*(IPaddr_t *)(&rarp->ar_data[6]) = NetOurIP; /* source IP addr */
NetCopyEther(&rarp->ar_data[10], NetOurEther); /* dest ET addr = source ET addr ??*/
/* dest. IP addr set to broadcast */
for (i = 0; i <= 3; i++) {
rarp->ar_data[16 + i] = 0xff;
}
 
NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
 
NetSetTimeout(TIMEOUT * CFG_HZ, RarpTimeout);
NetSetHandler(RarpHandler);
}
 
#endif /* CFG_CMD_NET */
/net.c
0,0 → 1,644
/*
* Copied from Linux Monitor (LiMon) - Networking.
*
* Copyright 1994 - 2000 Neil Russell.
* (See License)
* Copyright 2000 Roland Borde
* Copyright 2000 Paolo Scaffardi
* Copyright 2000, 2001 Wolfgang Denk
*/
 
/*
* General Desription:
*
* The user interface supports commands for BOOTP, RARP, and TFTP.
* Also, we support ARP internally. Depending on available data,
* these interact as follows:
*
* BOOTP:
*
* Prerequisites: - own ethernet address
* We want: - own IP address
* - TFTP server IP address
* - name of bootfile
* Next step: ARP
*
* RARP:
*
* Prerequisites: - own ethernet address
* We want: - own IP address
* - TFTP server IP address
* Next step: ARP
*
* ARP:
*
* Prerequisites: - own ethernet address
* - own IP address
* - TFTP server IP address
* We want: - TFTP server ethernet address
* Next step: TFTP
*
* DHCP:
*
* Prerequisites: - own ethernet address
* We want: - IP, Netmask, ServerIP, Gateway IP
* - bootfilename, lease time
* Next step: - TFTP
*
* TFTP:
*
* Prerequisites: - own ethernet address
* - own IP address
* - TFTP server IP address
* - TFTP server ethernet address
* - name of bootfile (if unknown, we use a default name
* derived from our own IP address)
* We want: - load the boot file
* Next step: none
*/
 
 
#include "common.h"
#include "support.h"
#include "net.h"
#include "bootp.h"
#include "tftp.h"
#include "rarp.h"
#include "arp.h"
#include "eth.h"
 
#if 0
#define ET_DEBUG
#endif
 
/** BOOTP EXTENTIONS **/
 
IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */
char NetOurNISDomain[32]={0,}; /* Our NIS domain */
char NetOurHostName[32]={0,}; /* Our hostname */
char NetOurRootPath[64]={0,}; /* Our bootpath */
unsigned short NetBootFileSize=0; /* Our bootfile size in blocks */
 
/** END OF BOOTP EXTENTIONS **/
 
unsigned long NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
unsigned char NetOurEther[6]; /* Our ethernet address */
unsigned char NetServerEther[6] = /* Boot server enet address */
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */
volatile unsigned char *NetRxPkt; /* Current receive packet */
int NetRxPktLen; /* Current rx packet length */
unsigned NetIPID; /* IP packet ID */
unsigned char NetBcastAddr[6] = /* Ethernet bcast address */
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int NetState; /* Network loop state */
 
char BootFile[128]; /* Boot File name */
 
volatile unsigned char PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
 
volatile unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
 
static rxhand_f *packetHandler; /* Current RX packet handler */
static thand_f *timeHandler; /* Current timeout handler */
static unsigned long timeValue; /* Current timeout value */
volatile unsigned char *NetTxPacket = 0; /* THE transmit packet */
 
static int net_check_prereq (proto_t protocol);
 
/**********************************************************************/
/*
* Main network processing loop.
*/
int
NetLoop(proto_t protocol)
{
#if 1
if (!NetTxPacket) {
int i;
 
/*
* Setup packet buffers, aligned correctly.
*/
NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
NetTxPacket -= (unsigned long)NetTxPacket % PKTALIGN;
for (i = 0; i < PKTBUFSRX; i++) {
NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
}
}
 
eth_halt();
eth_init(NetReceive);
 
restart:
NetCopyEther(NetOurEther, global.eth_add);
 
NetState = NETLOOP_CONTINUE;
 
/*
* Start the ball rolling with the given start function. From
* here on, this code is a state machine driven by received
* packets and timer events.
*/
 
if (protocol == TFTP) { /* TFTP */
NetOurIP = global.ip;
NetServerIP = global.srv_ip;
NetOurGatewayIP = global.gw_ip;
NetOurSubnetMask= global.mask;
 
if (net_check_prereq (protocol) != 0) {
return 0;
}
 
/* always use ARP to get server ethernet address */
ArpTry = 0;
ArpRequest ();
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
} else if (protocol == DHCP) {
if (net_check_prereq (protocol) != 0) {
return 0;
}
 
/* Start with a clean slate... */
NetOurIP = 0;
NetServerIP = 0;
DhcpRequest(); /* Basically same as BOOTP */
 
#endif /* CFG_CMD_DHCP */
 
} else { /* BOOTP or RARP */
 
/*
* initialize our IP addr to 0 in order to accept ANY
* IP addr assigned to us by the BOOTP / RARP server
*/
NetOurIP = 0;
NetServerIP = 0;
 
if (net_check_prereq (protocol) != 0) {
return 0;
}
#ifdef BOOTP
if (protocol == BOOTP) {
BootpTry = 0;
BootpRequest ();
}
#endif
#ifdef RARP
if {
RarpTry = 0;
RarpRequest ();
}
#endif
}
 
NetBootFileXferSize = 0;
 
/*
* Main packet reception loop. Loop receiving packets until
* someone sets `NetQuit'.
*/
for (;;) {
// WATCHDOG_RESET();
/*
* Check the ethernet for a new packet. The ethernet
* receive routine will process it.
*/
eth_rx();
 
/*
* Abort if ctrl-c was pressed.
*/
if (ctrlc()) {
eth_halt();
printf("\nAbort\n");
return 0;
}
 
 
/*
* Check for a timeout, and run the timeout handler
* if we have one.
*/
if (timeHandler && (get_timer(0) > timeValue)) {
thand_f *x;
 
x = timeHandler;
timeHandler = (thand_f *)0;
(*x)();
}
 
 
switch (NetState) {
 
case NETLOOP_RESTART:
goto restart;
 
case NETLOOP_SUCCESS:
if (NetBootFileXferSize > 0) {
printf("Bytes transferred = %ld (%lx hex)\n",
NetBootFileXferSize,
NetBootFileXferSize);
}
eth_halt();
return NetBootFileXferSize;
 
case NETLOOP_FAIL:
return 0;
}
}
#endif
}
 
/**********************************************************************/
 
 
#if 1
void
NetStartAgain(void)
{
NetState = NETLOOP_RESTART;
}
 
/**********************************************************************/
/*
* Miscelaneous bits.
*/
 
void
NetSetHandler(rxhand_f * f)
{
packetHandler = f;
}
 
 
void
NetSetTimeout(int iv, thand_f * f)
{
if (iv == 0) {
timeHandler = (thand_f *)0;
} else {
timeHandler = f;
timeValue = get_timer(0) + iv;
}
}
 
 
void
NetSendPacket(volatile unsigned char * pkt, int len)
{
unsigned char *p;
 
p = eth_get_tx_buf();
memcpy(p, (void *)pkt, len);
eth_send(p, len);
}
 
 
 
void
NetReceive(volatile unsigned char * pkt, int len)
{
Ethernet_t *et;
IP_t *ip;
ARP_t *arp;
int x;
 
 
NetRxPkt = pkt;
NetRxPktLen = len;
et = (Ethernet_t *)pkt;
 
x = SWAP16(et->et_protlen);
 
if (x < 1514) {
/*
* Got a 802 packet. Check the other protocol field.
*/
x = SWAP16(et->et_prot);
ip = (IP_t *)(pkt + E802_HDR_SIZE);
len -= E802_HDR_SIZE;
} else {
ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
len -= ETHER_HDR_SIZE;
}
 
#ifdef ET_DEBUG
printf("Receive from protocol 0x%x\n", x);
#endif
 
switch (x) {
 
case PROT_ARP:
/*
* We have to deal with two types of ARP packets:
* - REQUEST packets will be answered by sending our
* IP address - if we know it.
* - REPLY packates are expected only after we asked
* for the TFTP server's or the gateway's ethernet
* address; so if we receive such a packet, we set
* the server ethernet address
*/
#ifdef ET_DEBUG
printf("Got ARP\n");
#endif
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE) {
printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
return;
}
if (SWAP16(arp->ar_hrd) != ARP_ETHER) {
return;
}
if (SWAP16(arp->ar_pro) != PROT_IP) {
return;
}
if (arp->ar_hln != 6) {
return;
}
if (arp->ar_pln != 4) {
return;
}
 
if (NetOurIP == 0 ||
*((IPaddr_t *)&arp->ar_data[16]) != NetOurIP) {
return;
}
 
switch (SWAP16(arp->ar_op)) {
case ARPOP_REQUEST: /* reply with our IP address */
#ifdef ET_DEBUG
printf("Got ARP REQUEST, return our IP\n");
#endif
NetSetEther((unsigned char *)et, et->et_src, PROT_ARP);
arp->ar_op = SWAP16(ARPOP_REPLY);
NetCopyEther(&arp->ar_data[10], &arp->ar_data[0]);
NetCopyEther(&arp->ar_data[0], NetOurEther);
*(IPaddr_t *)(&arp->ar_data[16]) =
*(IPaddr_t *)(&arp->ar_data[6]);
*(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP;
NetSendPacket((unsigned char *)et,((unsigned char *)arp-pkt)+ARP_HDR_SIZE);
return;
case ARPOP_REPLY: /* set TFTP server eth addr */
#ifdef ET_DEBUG
printf("Got ARP REPLY, set server/gtwy eth addr\n");
#endif
NetCopyEther(NetServerEther, &arp->ar_data[0]);
(*packetHandler)(0,0,0,0); /* start TFTP */
return;
default:
#ifdef ET_DEBUG
printf("Unexpected ARP opcode 0x%x\n", SWAP16(arp->ar_op));
#endif
return;
}
 
case PROT_RARP:
#ifdef ET_DEBUG
printf("Got RARP\n");
#endif
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE) {
printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
return;
}
 
if ((SWAP16(arp->ar_op) != RARPOP_REPLY) ||
(SWAP16(arp->ar_hrd) != ARP_ETHER) ||
(SWAP16(arp->ar_pro) != PROT_IP) ||
(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
 
printf("invalid RARP header\n");
} else {
NetOurIP = *((IPaddr_t *)&arp->ar_data[16]);
NetServerIP = *((IPaddr_t *)&arp->ar_data[6]);
NetCopyEther(NetServerEther, &arp->ar_data[0]);
 
(*packetHandler)(0,0,0,0);
}
break;
 
case PROT_IP:
#ifdef ET_DEBUG
printf("Got IP\n");
#endif
if (len < IP_HDR_SIZE) {
debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
return;
}
if (len < SWAP16(ip->ip_len)) {
printf("len bad %d < %d\n", len, SWAP16(ip->ip_len));
return;
}
len = SWAP16(ip->ip_len);
#ifdef ET_DEBUG
printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
#endif
if ((ip->ip_hl_v & 0xf0) != 0x40) {
return;
}
if (ip->ip_off & SWAP16c(0x1fff)) { /* Can't deal w/ fragments */
return;
}
if (!NetCksumOk((unsigned char *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
printf("checksum bad\n");
return;
}
if (NetOurIP &&
ip->ip_dst != NetOurIP &&
ip->ip_dst != 0xFFFFFFFF) {
return;
}
/*
* watch for ICMP host redirects
*
* There is no real handler code (yet). We just watch
* for ICMP host redirect messages. In case anybody
* sees these messages: please contact me
* (wd@denx.de), or - even better - send me the
* necessary fixes :-)
*
* Note: in all cases where I have seen this so far
* it was a problem with the router configuration,
* for instance when a router was configured in the
* BOOTP reply, but the TFTP server was on the same
* subnet. So this is probably a warning that your
* configuration might be wrong. But I'm not really
* sure if there aren't any other situations.
*/
if (ip->ip_p == IPPROTO_ICMP) {
ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
 
if (icmph->type != ICMP_REDIRECT)
return;
if (icmph->code != ICMP_REDIR_HOST)
return;
printf (" ICMP Host Redirect to ");
print_IPaddr(icmph->un.gateway);
putc(' ');
} else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
return;
}
 
/*
* IP header OK. Pass the packet to the current handler.
*/
(*packetHandler)((unsigned char *)ip +IP_HDR_SIZE,
SWAP16(ip->udp_dst),
SWAP16(ip->udp_src),
SWAP16(ip->udp_len) - 8);
 
break;
}
}
 
 
/**********************************************************************/
 
static int net_check_prereq (proto_t protocol)
{
switch (protocol) {
case ARP: /* nothing to do */
break;
 
case TFTP:
if (NetServerIP == 0) {
printf ("*** ERROR: `serverip' not set\n");
return (1);
}
 
if (NetOurIP == 0) {
printf ("*** ERROR: `ipaddr' not set\n");
return (1);
}
/* Fall through */
 
case DHCP:
case RARP:
case BOOTP:
if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
printf ("*** ERROR: `ethaddr' not set\n");
return (1);
}
/* Fall through */
}
return (0); /* OK */
}
/**********************************************************************/
 
int
NetCksumOk(unsigned char * ptr, int len)
{
return !((NetCksum(ptr, len) + 1) & 0xfffe);
}
 
 
unsigned
NetCksum(unsigned char * ptr, int len)
{
unsigned long xsum;
 
xsum = 0;
while (len-- > 0)
xsum += *((unsigned short *)ptr)++;
xsum = (xsum & 0xffff) + (xsum >> 16);
xsum = (xsum & 0xffff) + (xsum >> 16);
return (xsum & 0xffff);
}
 
 
void
NetCopyEther(volatile unsigned char * to, unsigned char * from)
{
int i;
 
for (i = 0; i < 6; i++)
*to++ = *from++;
}
 
 
void
NetSetEther(volatile unsigned char * xet, unsigned char * addr, unsigned long prot)
{
volatile Ethernet_t *et = (Ethernet_t *)xet;
 
NetCopyEther(et->et_dest, addr);
NetCopyEther(et->et_src, NetOurEther);
et->et_protlen = SWAP16(prot);
}
 
 
void
NetSetIP(volatile unsigned char * xip, IPaddr_t dest, int dport, int sport, int len)
{
volatile IP_t *ip = (IP_t *)xip;
 
/*
* If the data is an odd number of bytes, zero the
* byte after the last byte so that the checksum
* will work.
*/
if (len & 1)
xip[IP_HDR_SIZE + len] = 0;
 
/*
* Construct an IP and UDP header.
(need to set no fragment bit - XXX)
*/
ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
ip->ip_tos = 0;
ip->ip_len = SWAP16(IP_HDR_SIZE + len);
ip->ip_id = SWAP16(NetIPID++);
ip->ip_off = SWAP16c(0x4000); /* No fragmentation */
ip->ip_ttl = 255;
ip->ip_p = 17; /* UDP */
ip->ip_sum = 0;
ip->ip_src = NetOurIP;
ip->ip_dst = dest;
ip->udp_src = SWAP16(sport);
ip->udp_dst = SWAP16(dport);
ip->udp_len = SWAP16(8 + len);
ip->udp_xsum = 0;
ip->ip_sum = ~NetCksum((unsigned char *)ip, IP_HDR_SIZE_NO_UDP / 2);
}
 
void copy_filename (unsigned char *dst, unsigned char *src, int size)
{
if (*src && (*src == '"')) {
++src;
--size;
}
 
while ((--size > 0) && *src && (*src != '"')) {
*dst++ = *src++;
}
*dst = '\0';
}
 
void ip_to_string (IPaddr_t x, char *s)
{
char num[] = "0123456789ABCDEF";
int i;
 
x = SWAP32(x);
for(i = 28; i >= 0; i -= 4)
*s++ = num[((x >> i) & 0x0f)];
*s = 0;
}
 
void print_IPaddr (IPaddr_t x)
{
char tmp[12];
 
ip_to_string(x, tmp);
 
printf(tmp);
}
 
#endif
/arp.h
0,0 → 1,40
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
 
 
#ifndef __ARP_H__
#define __ARP_H__
 
/**********************************************************************/
/*
* Global functions and variables.
*/
 
extern int ArpTry;
 
extern void ArpRequest (void); /* Send a ARP request */
 
/**********************************************************************/
 
#endif /* __ARP_H__ */
 
/bootp.h
0,0 → 1,95
/*
* Copied from LiMon - BOOTP.
*
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
* Copyright 2000 Paolo Scaffardi
*/
 
#ifndef __BOOTP_H__
#define __BOOTP_H__
 
#ifndef __NET_H__
#include "net.h"
#endif /* __NET_H__ */
 
/**********************************************************************/
 
/*
* BOOTP header.
*/
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */
#else
#define OPT_SIZE 64
#endif
 
typedef struct
{
unsigned char bp_op; /* Operation */
# define OP_BOOTREQUEST 1
# define OP_BOOTREPLY 2
unsigned char bp_htype; /* Hardware type */
# define HWT_ETHER 1
unsigned char bp_hlen; /* Hardware address length */
# define HWL_ETHER 6
unsigned char bp_hops; /* Hop count (gateway thing) */
unsigned long bp_id; /* Transaction ID */
unsigned short bp_secs; /* Seconds since boot */
unsigned short bp_spare1; /* Alignment */
IPaddr_t bp_ciaddr; /* Client IP address */
IPaddr_t bp_yiaddr; /* Your (client) IP address */
IPaddr_t bp_siaddr; /* Server IP address */
IPaddr_t bp_giaddr; /* Gateway IP address */
unsigned char bp_chaddr[16]; /* Client hardware address */
char bp_sname[64]; /* Server host name */
char bp_file[128]; /* Boot file name */
char bp_vend[OPT_SIZE]; /* Vendor information */
} Bootp_t;
 
#define BOOTP_HDR_SIZE sizeof (Bootp_t)
#define BOOTP_SIZE (ETHER_HDR_SIZE + IP_HDR_SIZE + BOOTP_HDR_SIZE)
 
/**********************************************************************/
/*
* Global functions and variables.
*/
 
/* bootp.c */
extern unsigned long BootpID; /* ID of cur BOOTP request */
extern char BootFile[128]; /* Boot file name */
extern int BootpTry;
#ifdef CONFIG_BOOTP_RANDOM_DELAY
unsigned long seed1, seed2; /* seed for random BOOTP delay */
#endif
 
 
/* Send a BOOTP request */
extern void BootpRequest (void);
 
/****************** DHCP Support *********************/
extern void DhcpRequest(void);
 
/* DHCP States */
typedef enum { INIT,
INIT_REBOOT,
REBOOTING,
SELECTING,
REQUESTING,
REBINDING,
BOUND,
RENEWING } dhcp_state_t;
 
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
#define DHCP_REQUEST 3
#define DHCP_DECLINE 4
#define DHCP_ACK 5
#define DHCP_NAK 6
#define DHCP_RELEASE 7
 
#define SELECT_TIMEOUT 3 /* Seconds to wait for offers */
 
/**********************************************************************/
 
#endif /* __BOOTP_H__ */
/rarp.h
0,0 → 1,44
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
 
 
#ifndef __RARP_H__
#define __RARP_H__
 
#ifndef __NET_H__
#include "net.h"
#endif /* __NET_H__ */
 
 
/**********************************************************************/
/*
* Global functions and variables.
*/
 
extern int RarpTry;
 
extern void RarpRequest (void); /* Send a RARP request */
 
/**********************************************************************/
 
#endif /* __RARP_H__ */
/Makefile
0,0 → 1,44
# (C) Marko Mlinar, based on ppcboot
#
# (C) Copyright 2000
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# 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., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
 
# CFLAGS += -DET_DEBUG -DDEBUG
 
LIB = services.o
 
# OBJS = net.o tftp.o bootp.o rarp.o arp.o
OBJS = net.o tftp.o bootp.o rarp.o arp.o
 
all: $(LIB)
 
$(LIB): $(START) $(OBJS)
$(LD) -r -o $@ $(OBJS)
 
#########################################################################
 
.depend: Makefile $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
 
sinclude .depend
 
#########################################################################
/tftp.c
0,0 → 1,326
/*
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
* Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
*/
 
#include "common.h"
#include "support.h"
#include "net.h"
#include "tftp.h"
#include "bootp.h"
 
#undef ET_DEBUG
 
#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
#define TIMEOUT 2 /* Seconds to timeout for a lost pkt */
#define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
/* (for checking the image size) */
#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
 
/*
* TFTP operations.
*/
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
 
 
extern unsigned long load_addr;
 
static int TftpServerPort; /* The UDP port at their end */
static int TftpOurPort; /* The UDP port at our end */
static int TftpTimeoutCount;
static unsigned TftpBlock;
static unsigned TftpLastBlock;
static int TftpState;
#define STATE_RRQ 1
#define STATE_DATA 2
#define STATE_TOO_LARGE 3
#define STATE_BAD_MAGIC 4
 
#define DEFAULT_NAME_LEN (8 + 4 + 1)
static char default_filename[DEFAULT_NAME_LEN] = "tftpboot.img";
static char *tftp_filename;
 
#ifdef CFG_DIRECT_FLASH_TFTP
extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
#endif
 
static __inline__ void
store_block (unsigned block, unsigned char * src, unsigned len)
{
unsigned long offset = block * 512, newsize = offset + len;
#ifdef CFG_DIRECT_FLASH_TFTP
int i, rc = 0;
 
for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {
/* start address in flash? */
if (load_addr + offset >= flash_info[i].start[0]) {
rc = 1;
break;
}
}
 
if (rc) { /* Flash is destination for this packet */
rc = flash_write ((unsigned char *)src, (unsigned long)(load_addr+offset), len);
switch (rc) {
case 0: /* OK */
break;
case 1: printf ("Timeout writing to Flash\n");
break;
case 2: printf ("Flash not Erased\n");
break;
case 4: printf ("Can't write to protected Flash sectors\n");
break;
case 8: printf ("Outside available Flash\n");
break;
case 16:printf ("Size must be aligned (multiple of 8?)\n");
break;
default:
printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
break;
}
if (rc) {
NetState = NETLOOP_FAIL;
return;
}
}
else
#endif /* CFG_DIRECT_FLASH_TFTP */
(void)memcpy((void *)(load_addr + offset), src, len);
 
if (NetBootFileXferSize < newsize)
NetBootFileXferSize = newsize;
}
 
static void TftpSend (void);
static void TftpTimeout (void);
 
/**********************************************************************/
 
static void
TftpSend (void)
{
volatile unsigned char * pkt;
volatile unsigned char * xp;
int len = 0;
 
/*
* We will always be sending some sort of packet, so
* cobble together the packet headers now.
*/
pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
 
switch (TftpState) {
 
case STATE_RRQ:
xp = pkt;
*((unsigned short *)pkt)++ = SWAP16c(TFTP_RRQ);
strcpy ((char *)pkt, tftp_filename);
pkt += strlen(tftp_filename) + 1;
strcpy ((char *)pkt, "octet");
pkt += 5 /*strlen("octet")*/ + 1;
len = pkt - xp;
break;
 
case STATE_DATA:
xp = pkt;
*((unsigned short *)pkt)++ = SWAP16c(TFTP_ACK);
*((unsigned short *)pkt)++ = SWAP16(TftpBlock);
len = pkt - xp;
break;
 
case STATE_TOO_LARGE:
xp = pkt;
*((unsigned short *)pkt)++ = SWAP16c(TFTP_ERROR);
*((unsigned short *)pkt)++ = SWAP16(3);
strcpy ((char *)pkt, "File too large");
pkt += 14 /*strlen("File too large")*/ + 1;
len = pkt - xp;
break;
 
case STATE_BAD_MAGIC:
xp = pkt;
*((unsigned short *)pkt)++ = SWAP16c(TFTP_ERROR);
*((unsigned short *)pkt)++ = SWAP16(2);
strcpy ((char *)pkt, "File has bad magic");
pkt += 18 /*strlen("File has bad magic")*/ + 1;
len = pkt - xp;
break;
}
 
NetSetEther (NetTxPacket, NetServerEther, PROT_IP);
NetSetIP (NetTxPacket + ETHER_HDR_SIZE, NetServerIP,
TftpServerPort, TftpOurPort, len);
NetSendPacket (NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
}
 
 
static void
TftpHandler (unsigned char * pkt, unsigned dest, unsigned src, unsigned len)
{
if (dest != TftpOurPort) {
return;
}
if (TftpState != STATE_RRQ && src != TftpServerPort) {
return;
}
 
if (len < 2) {
return;
}
len -= 2;
switch (SWAP16(*((unsigned short *)pkt)++)) {
 
case TFTP_RRQ:
case TFTP_WRQ:
case TFTP_ACK:
break;
default:
break;
 
case TFTP_DATA:
if (len < 2)
return;
len -= 2;
TftpBlock = SWAP16(*(unsigned short *)pkt);
if (((TftpBlock - 1) % 10) == 0) {
putc ('#');
} else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
printf ("\n\t ");
}
 
if (TftpState == STATE_RRQ) {
TftpState = STATE_DATA;
TftpServerPort = src;
TftpLastBlock = 0;
 
if (TftpBlock != 1) { /* Assertion */
printf ("\nTFTP error: "
"First block is not block 1 (%d)\n"
"Starting again\n\n",
TftpBlock);
NetStartAgain ();
break;
}
}
 
if (TftpBlock == TftpLastBlock) {
/*
* Same block again; ignore it.
*/
break;
}
 
TftpLastBlock = TftpBlock;
NetSetTimeout (TIMEOUT * IN_CLK, TftpTimeout);
 
store_block (TftpBlock - 1, pkt + 2, len);
 
/*
* Acknoledge the block just received, which will prompt
* the server for the next one.
*/
TftpSend ();
 
if (len < 512) {
/*
* We received the whole thing. Try to
* run it.
*/
printf ("\ndone\n");
NetState = NETLOOP_SUCCESS;
}
break;
 
case TFTP_ERROR:
printf ("\nTFTP error: '%s' (%d)\n",
pkt + 2, SWAP16(*(unsigned short *)pkt));
printf ("Starting again\n\n");
NetStartAgain ();
break;
}
}
 
 
static void
TftpTimeout (void)
{
if (++TftpTimeoutCount >= TIMEOUT_COUNT) {
printf ("\nRetry count exceeded; starting again\n");
NetStartAgain ();
} else {
printf ("T ");
NetSetTimeout (TIMEOUT * IN_CLK, TftpTimeout);
TftpSend ();
}
}
 
 
void
TftpStart (void)
{
#ifdef ET_DEBUG
printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
NetServerEther[0],
NetServerEther[1],
NetServerEther[2],
NetServerEther[3],
NetServerEther[4],
NetServerEther[5]
);
#endif /* DEBUG */
 
if (BootFile[0] == '\0') {
tftp_filename = default_filename;
 
printf ("*** Warning: no boot file name; using '%s'\n",
tftp_filename);
} else {
tftp_filename = BootFile;
}
 
printf ("TFTP from server "); print_IPaddr (NetServerIP);
printf ("; our IP address is "); print_IPaddr (NetOurIP);
 
// Check if we need to send across this subnet
if (NetOurGatewayIP && NetOurSubnetMask) {
IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
 
if (OurNet != ServerNet) {
printf ("; sending through gateway ");
print_IPaddr (NetOurGatewayIP) ;
}
}
putc ('\n');
 
printf ("Filename '%s'.", tftp_filename);
 
if (NetBootFileSize) {
printf (" Size is %d%s kB => %x Bytes",
NetBootFileSize/2,
(NetBootFileSize%2) ? ".5" : "",
NetBootFileSize<<9);
}
 
putc ('\n');
 
printf ("Load address: 0x%lx\n", load_addr);
 
printf ("Loading: *\b");
 
NetSetTimeout (TIMEOUT * IN_CLK, TftpTimeout);
NetSetHandler (TftpHandler);
 
TftpServerPort = WELL_KNOWN_PORT;
TftpTimeoutCount = 0;
TftpState = STATE_RRQ;
TftpOurPort = 1024 + (get_timer(0) % 3072);
 
TftpSend ();
}
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.