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.o LIB = 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 (); |
} |
|