I build a bootloader, it can send bootme well and the PB5.0 can
reply to it too. But here is a stange problem, bootloader can accept
destination 59.77.17.255 UDP packet but can't accept destination
59.77.17.100
UDP packet, which is its IP. Anytime the program comes to
EbootTFtpReceiver,
the packet must be 59.77.17.255 destination, so can't go on. It seems
to me that, if
IP is 59.77.17.255 every thing works as normal, but if it's
59.77.17.100,
bootloader works as if there is no frame arrived. Anyone can help me? I
have
debugged it for ond day.
The code below is cut from my sourcecode. I add a lot
of EdbgOutputDebugString which is used for debug, don't care about it.
UINT16
LAN91CGetFrame(UINT8 *pBuffer, UINT16 *pLength){ UINT8 *pos =3D
pBuffer;
UINT16 code, pointer; UINT32 length, count; EdbgOutputDebugString
("+
LAN91CGetFrame"); // Make sure that bank 2 is actual OUTPORT16(&
g_pLAN91C->BANKSEL, 2); length =3D 0; while
((INPORT16(&g_pLAN91C->INTR)
& INTR_RX) !=3D 0) { EdbgOutputDebugString ("+LAN91CGetFrame while\r\n")
; // Setup pointer address register pointer =3D PTR_RCV |
PTR_READ
; // Read status OUTPORT16(&g_pLAN91C->PTR, pointer);
code =3D INPORT16(&g_pLAN91C->DATA); pointer +=3D sizeof(UINT16);
if ((code & (STAT_ALGNERR|STAT_BADCRC|STAT_LONG|STAT_SHORT)) =3D=3D 0)
{ // Get packet size OUTPORT16(&g_pLAN91C->PTR,
pointer)
; length =3D (INPORT16(&g_pLAN91C->DATA) & 0x07FF) - 6;
pointer +=3D sizeof(UINT16); // Copy packet count =3D
length
; while (count > 1) {
OUTPORT16(&g_pLAN91C->PTR,
pointer); *(UINT16*)pos =3D INPORT16(&g_pLAN91C->DATA)
; pointer +=3D sizeof(UINT16); pos +=3D
sizeof(
UINT16); count -=3D sizeof(UINT16); }
//
Get control word (which can contain last byte)
OUTPORT16(&g_pLAN91C
->PTR, pointer); code =3D INPORT16(&g_pLAN91C->DATA);
pointer +=3D sizeof(UINT16); if ((code & CTRL_ODD) !=3D 0)
{ length++; *pos =3D (UINT8)code;
} } // Release the memory for the received frame
switch (
GET_CHIP_ID(g_chipRevision)) { case CHIP_ID_LAN91C111:
OUTPORT16(&g_pLAN91C->MMUCR, MMUCR_111_REM_REL_RX); break;
default: OUTPORT16(&g_pLAN91C->MMUCR,
MMUCR_REM_REL_TOP
); } while ((INPORT16(&g_pLAN91C->MMUCR) & MMUCR_BUSY) !=3D
0)
; // If length is non zero we get a packet if (length >
0) break
; } EdbgOutputDebugString ("hahahaha\r\n"); *pLength =3D
(UINT16)
length; return (*pLength);}pfnEDbgGetFrame =3D
(PFN_EDBG_GET_FRAME)
LAN91CGetFrame; BOOL OEMEthGetFrame(BYTE *pData, // OUT -
Receives
frame data UINT16 *pwLength) // IN - Length of Rx
buffer
{ EdbgOutputDebugString ("+OEMEthGetFrame\r\n"); return
(pfnEDbgGetFrame(
pData, pwLength));}BOOL EbootSendBootmeAndWaitForTftp (EDBG_ADDR
*pEdbgAddr,
UCHAR VersionMajor, UCHAR VersionMinor,
char *
szPlatformString, char *szDeviceName,
UCHAR CPUId
, DWORD dwBootFlags){ DWORD dwCurSec =3D OEMEthGetSecs () -
BOOTME_INTERVAL
; USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData; int
nRetries =3D 0; EdbgOutputDebugString
("+EbootSendBootmeAndWaitForTftp\r\n")
; while (!fTftpLinked) { EdbgOutputDebugString ("+while (!
fTftpLinked)\r\n"); if ((nRetries < MAX_BOOTME_CNT) && (OEMEthGetSecs
() -
dwCurSec >=3D BOOTME_INTERVAL)) { nRetries ++;
dwCurSec
+=3D BOOTME_INTERVAL; // send a bootme message
EbootSendBootme (pEdbgAddr, VersionMajor, VersionMinor,
szPlatformString,
szDeviceName, CPUId, dwBootFlags); } // get another frame
and
pass it to TFTP handler wLen =3D sizeof (gFrameBuffer); if
(
OEMEthGetFrame (gFrameBuffer, &wLen)) { // frame available?
switch (FRAMETYPE (gFrameBuffer)) { case 0x0800: // IP
packet EdbgOutputDebugString ("+FRAMETYPE IP\r\n"); if
(!
EbootCheckUDP(pEdbgAddr, gFrameBuffer, &wDestPort, &wSrcPort,
&pwUDPData, &
wUDPDataLen)) { // UDP? // EDBG command? (should
only
occur if eshell asked us to jump to existing image)
if (!
EbootProcessEDBG (pEdbgAddr, &gHostAddr, gFrameBuffer, pwUDPData,
wUDPDataLen
, &fTftpLinked, &gpCfgData)) { // no, pass it to
TFTP EbootTFtpReceiver (pEdbgAddr, gFrameBuffer,
wDestPort, wSrcPort, pwUDPData, wUDPDataLen);
} } break; case 0x0806: //
ARP
packet EdbgOutputDebugString ("+FRAMETYPE
ARP\r\n"); if (
EbootProcessARP (pEdbgAddr, gFrameBuffer) =3D=3D PROCESS_ARP_RESPONSE)
{ EdbgOutputDebugString( "Some other station has IP
Address
: %s !!! Aborting.\r\n", inet_ntoa(pEdbgAddr->dwIP));
return FALSE; } break; default
: break; } } }
EdbgOutputDebugString (
"-EbootSendBootmeAndWaitForTftp\r\n"); return TRUE;}// This routine
handles the multiplexing of all active TFTP links. It returns 0 if
there was
no valid link formed,// or 1 of there was.WORD EbootTFtpReceiver(
EDBG_ADDR *
pMyAddr, BYTE *pFrameBuffer, UINT16 wDestPort, UINT16 wSrcPort, UINT16
*
pwUDPData, UINT16 cwUDPDataLength ) { int i; UINT16 iLinkSlot =3D
MAX_TFTP_LINKS;EdbgOutputDebugString ("+EbootTFtpReceiver\r\n"); //
Check to
see if this is for a link that is currently in use for( i =3D 0; i <
MAX_TFTP_LINKS; i++ ) { // Here I don't compare the destination (Odo)
port,
only the source (host) because // this could be a repeat open packet,
which
we don't want to cause a second link. // This could happen if a second
open
packet comes because we will have changed the // destination port with
the
acknowledge. if (TFtpLinks[i].State !=3D TFTP_STATE_IDLE && wSrcPort =3D=
=3D
TFtpLinks[i].DestAddr.wPort && wDestPort =3D=3D
TFtpLinks[i].SrcAddr.wPort) {
iLinkSlot =3D i; break; } else if (TFtpLinks[i].State =3D=3D
TFTP_STATE_IDLE)
iLinkSlot =3D i; } // If we broke out of the loop early, then the packet
is for
a link that is already open if (i < MAX_TFTP_LINKS) { // iLinkSlot is
the
index of the link this packet belongs too TFtpStateMachine( wSrcPort,
iLinkSlot, pwUDPData, cwUDPDataLength ); } // Check to see if someone
is
trying to start a new connection, // If so, guarantee that there are
always
TFTP_TX_LINKS link(s) available to transmit information else if
(wDestPort =3D=3D
wOdoWellKnownServerPort && MAX_TFTP_LINKS - nNumTFtpLinksInUse >
TFTP_TX_LINKS
) { // iLinkSlot is the index of a link that is in the IDLE state,
giving
the number of a free link // slot that can be used, the wDestTID and
the
TFTP Message TFtpdFormNewLink( pMyAddr, pFrameBuffer, iLinkSlot,
pwUDPData )
; return 1; } else { for( i =3D 0; i < MAX_TFTP_LINKS; i++ )
{ EdbgOutputDebugString("TFTP link[%u]: State:%u,
DestAddr.wPort: %
u, SrcAddr.wPort: %u\n",
i,TFtpLinks[i].State,
ntohs(TFtpLinks[i].DestAddr.wPort),
ntohs(
TFtpLinks[i].SrcAddr.wPort)); } EdbgOutputDebugString("
TftpReceiver, port: 0x%X, wkp:
0x%X\n\r",wDestPort,wOdoWellKnownServerPort)
; } return 0;} //
TFtpReceiver()//---------------------------------------
---------------------------------------//// Function Name:
EbootCheckUD(...)
// Description..: This routine will check a UDP frame that has been
received
. // It will make sure that it was for our IP address
and
that // the checksums are right and that it's a UDP
packet.
If // something is wrong, the packet will be discarded
and
the // routine will return non-zero. If everything is
right
, // then all the port and IP information will be
filled out
and // the routine will return 0. Note that if we are
doing
the // DHCP process, the DHCP server will send the
OFFER
packet to // the IP address that it would like to give
us.
We have to // be able to accept a packet for any IP
address
in that // case. This condition is signaled to the
routine
by // fPromiscuousIP =3D=3D 1, which is set using
SetPromiscuousIP()//// Inputs.......: EDBG_ADDR * pntr to
address
// BYTE * pntr to frame//
UINT16 * pntr to dst addr// UINT16 *
pntr to src addr// UINT16 ** pntr to pntr to
data
// UINT16 * pntr to data length// Outputs
.=2E....: 0 on success, non zero on
failure////-------------------------------
-----------------------------------------------UINT16 EbootCheckUDP(
EDBG_ADDR *pMyAddr, BYTE *pFrameBuffer
, UINT16 *wDestPort,
UINT16
*wSrcPort, UINT16 **pwData,
UINT16 *cwLength ) { IPHeaderFormat *pIPHeader;
UDPPseudoHeaderFormat UDPPseudoHeader; UDPHeaderFormat *
pUDPHeader; // Note that I don't do any checking that depends on a
length
field // in the packet until after the CRC is verified for that
data
. // This prevents the code from running past the end of buffers,
etc
. // when a bad packet is received.EdbgOutputDebugString
("+EbootCheckUDP\
r\n"); pIPHeader =3D (IPHeaderFormat *)(pFrameBuffer + sizeof(
EthernetFrameHeader)); // Make sure that it was for our IP address,
unless
we're // doing DHCP (indicated by fPromiscuousIP =3D=3D 1) if( !
fPromiscuousIP && pIPHeader->dwDestIP !=3D pMyAddr->dwIP ) {//
EdbgOutputDebugString( // "!CheckUDP: Not our IP
(0x%X)\n",pIPHeader->
dwDestIP);EdbgOutputDebugString ("zjwzjwzjw return 1\r\n");
EdbgOutputDebugString("%s\r\n", inet_ntoa(pIPHeader->dwDestIP));
EdbgOutputDebugString("%s\r\n",
inet_ntoa(pMyAddr->dwIP));if(fPromiscuousIP)
{ EdbgOutputDebugString ("DHCP is ON ! WRONG!!!\r\n");} return(
1 )
; } // Make sure that it is a UDP packet if(
pIPHeader->bProtocol !=3D
17 ) { EdbgOutputDebugString( "!CheckUDP: Not UDP (proto =3D
0x%X)\n"
, pIPHeader->bProtocol ); return( 2 ); } //
Check the
IP header checksum if( CRC( (UINT16 *)pIPHeader,
sizeof(IPHeaderFormat),
NULL, 0 ) !=3D 0 ) { EdbgOutputDebugString( "!CheckUDP: IP
header
checksum failure\n" ); return( 3 ); } // Build the UDP
Pseudo
Header UDPPseudoHeader.dwSrcIP =3D pIPHeader->dwSrcIP;
UDPPseudoHeader.
dwDestIP =3D pIPHeader->dwDestIP; UDPPseudoHeader.bZero =3D 0;
UDPPseudoHeader.bProtocol =3D 17; // UDP Proto is 17
UDPPseudoHeader.
cwTotalUDPLength =3D htons( htons(pIPHeader->cwTotalLength) -
sizeof(
IPHeaderFormat )); // Check the UDP checksum, I'm using the
cwTotalUDPLength // calculated from the IP header info because we
know
that // it's not corrupted and won't give an outrageous length for
the
packet pUDPHeader =3D (UDPHeaderFormat *)((BYTE *)pIPHeader+sizeof(
IPHeaderFormat)); if( pUDPHeader->wCRC !=3D 0 && CRC( (UINT16
*)&
UDPPseudoHeader, sizeof(UDPPseudoHeader), (UINT16
*)pUDPHeader
, ntohs(UDPPseudoHeader.cwTotalUDPLength) ) !=3D 0 ) {
EdbgOutputDebugString( "!CheckUDP: UDP header checksum failure\n" );
return( 4 ); } // Now we know we have a good packet, fill out the
fields *wDestPort =3D pUDPHeader->wDestPort; *wSrcPort =3D
pUDPHeader->
wSrcPort; *pwData =3D (UINT16 *)((BYTE *)pUDPHeader +
sizeof(UDPHeaderFormat)
); *cwLength =3D htons(pUDPHeader->cwTotalUDPLength) -
sizeof(UDPHeaderFormat
); // Indicate success return( 0 );}