📄 ether.c
字号:
//
// Copyright(C) Renesas Technology Corp. 2005. All rights reserved.
//
// Ethernet Boot Loader for ITS-DS7
//
// FILE : ether.c
// CREATED : 2005.08.01
// MODIFIED :
// AUTHOR : Renesas Technology Corp.
// HARDWARE : RENESAS ITS-DS7
// HISTORY :
// 2005.08.01
// - Created release code.
// (based on EBOOT for ASPEN for WCE5.0)
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Module: ether.c
//
// This module provides the interface to the ethernet transport.
//
//------------------------------------------------------------------------------
// Include Files
#include "boot.h"
#include <ethdbg.h>
#include <pehdr.h>
#include <romldr.h>
#include <oemfw.h>
#include "shx.h"
#include "platform.h"
#include "drv_glob.h"
#include "loader.h"
#include "rev.h"
// External Functions
extern BOOL ReadEEPROMData ( DWORD *pdwIP, DWORD *pdwSubnetMask);
extern BOOL UpdateEEPROMData( DWORD dwIP, DWORD dwSubnetMask);
extern void JumpToOS ( DWORD dwLaunchAddr );
extern BOOL AskUser ( EDBG_ADDR *pMyAddr, LPDWORD pdwSubnetMask );
extern void SpinForever ( VOID );
// External Variables
extern BOOL gbStoreSDRAMImageToFlash;
extern BOOL gbJumpToFlash;
extern BOOL gbGotIP;
// Global Variables
// Defines
#define pDriverGlobals ((PDRIVER_GLOBALS) DRIVER_GLOBALS_PHYSICAL_MEMORY_START)
#define EDBG_CPUID EDBG_CPU_SH4 // CPU Id for Eshell
#define LAST_LAUNCH_ADDR_VALID (0xBADBEEF6)
#if 1
#define MACADDR0 0x0000
#define MACADDR1 0x0000
#define MACADDR2 0x0000
#else
/* 00:00:E1:0C:50:FF */
#define MACADDR0 0x0000
#define MACADDR1 0xe10c
#define MACADDR2 0x50ff
#endif
// Types
// Local Variables
// Local Functions
// function to ask user for IP/subnetMask
static EDBG_ADDR MyAddr; // IP address
static DWORD dwSubnetMask; // subnet mask
static BOOL fNoWait; // wait for desktop?
//------------------------------------------------------------------------------
// Function: EthInit
//
// Initialize ethernet interface.
//
BOOL EthInit( void )
{
EdbgOutputDebugString( "+EthInit\r\n" );
EdbgOutputDebugString( "INFO: SMC base : 0x%X\r\n", PF_ETHER_BASE);
if( !SMCInit( (BYTE *) PF_ETHER_BASE, 1, MyAddr.wMAC) )
{
EdbgOutputDebugString("ERROR: SMC Ethernet init failed, attempting parallel download...\n");
pDriverGlobals->eth.etherFlags|=EDBG_FL_CLEANBOOT;
pDriverGlobals->eth.EbootMagicNum = ~EBOOT_MAGIC_NUM;
return( FALSE );
}
#if (MACADDR0 || MACADDR1 || MACADDR2)
/* Serial EEPROM emulation */
{
EdbgOutputDebugString("Set Ethernet Address\r\n");
MyAddr.wMAC[0] = ((MACADDR0 << 8) & 0xFF00) | ((MACADDR0 >> 8) & 0x00FF);
MyAddr.wMAC[1] = ((MACADDR1 << 8) & 0xFF00) | ((MACADDR1 >> 8) & 0x00FF);
MyAddr.wMAC[2] = ((MACADDR2 << 8) & 0xFF00) | ((MACADDR2 >> 8) & 0x00FF);
WRITE_REGISTER_USHORT(PF_ETHER_BASE + (0x0E * 1),0x3301);
WRITE_REGISTER_USHORT(PF_ETHER_BASE + (0x04 * 1),MyAddr.wMAC[0]);
WRITE_REGISTER_USHORT(PF_ETHER_BASE + (0x06 * 1),MyAddr.wMAC[1]);
WRITE_REGISTER_USHORT(PF_ETHER_BASE + (0x08 * 1),MyAddr.wMAC[2]);
MyAddr.wMAC[0] = READ_REGISTER_USHORT(PF_ETHER_BASE + (0x04 * 1));
MyAddr.wMAC[1] = READ_REGISTER_USHORT(PF_ETHER_BASE + (0x06 * 1));
MyAddr.wMAC[2] = READ_REGISTER_USHORT(PF_ETHER_BASE + (0x08 * 1));
EdbgOutputDebugString("SMC Ethernet Address: %B:%B:%B:%B:%B:%B\r\n",
MyAddr.wMAC[0] & 0x00FF, MyAddr.wMAC[0] >> 8,
MyAddr.wMAC[1] & 0x00FF, MyAddr.wMAC[1] >> 8,
MyAddr.wMAC[2] & 0x00FF, MyAddr.wMAC[2] >> 8);
}
#endif
// Make sure MAC address has been programmed
if( !MyAddr.wMAC[0] && !MyAddr.wMAC[1] && !MyAddr.wMAC[2] )
{
EdbgOutputDebugString( "ERROR: Invalid MAC address.\r\n" );
return( FALSE );
}
// Read IP info in EEPROMs
EdbgOutputDebugString( "INFO: ReadEEPROMData...\r\n");
if( !ReadEEPROMData( &MyAddr.dwIP, &dwSubnetMask ) )
{
EdbgOutputDebugString(" ERROR: EthInit: ReadEEPROMData failed\r\n" );
return( FALSE );
}
EdbgOutputDebugString("INFO: EEPROM IpAddr %s ", inet_ntoa( MyAddr.dwIP ) );
EdbgOutputDebugString("netmask %s\r\n", inet_ntoa( dwSubnetMask) );
// Save our address in driver globals
memcpy(&pDriverGlobals->eth.PlatformAddr,&MyAddr,sizeof(MyAddr));
pDriverGlobals->eth.SubnetMask = dwSubnetMask;
// Indicate status
EdbgOutputDebugString( "-EthInit(rc=1)\r\n" );
return( TRUE );
}
//------------------------------------------------------------------------------
// Function: EthPreDownload
//
//
//
DWORD EthPreDownload( void )
{
BOOL fGotJumpImg = FALSE;
DWORD DHCPLeaseTime = 0;
DWORD *pDHCPLeaseTime = &DHCPLeaseTime;
EdbgOutputDebugString( "+EthPreDownload\r\n" );
// Polarity is reversed, so this is actually testing the "Off" position
if( gbJumpToFlash )
{
EdbgOutputDebugString( "INFO: Switch 1 on, jumping to flash image...\r\n");
fNoWait = TRUE;
return BL_JUMP;
}
EdbgOutputDebugString("Using device name: %s%d\n", BSP_DEVICE_PREFIX, ((MyAddr.wMAC[2] & 0x00FF) << 8) | MyAddr.wMAC[2] >> 8);
// If DIP switch SW2-2 is ON, use already IP address.
if (gbGotIP) { // ON
if (dwSubnetMask) {
EdbgOutputDebugString("Switch SW2-2 is ON, use existing IP address.\r\n");
//bGotIP = TRUE;
} else {
EdbgOutputDebugString("Switch SW2-2 is ON, but NOT exist IP address. Enter new IP address.\r\n");
gbGotIP = FALSE;
}
}
if(gbGotIP){
// already read EEPROM from static IP(EthInit)
pDHCPLeaseTime = NULL; // pDHCPLeaseTime is overloaded - NULL indicates static IP
pDriverGlobals->eth.EdbgFlags = EDBG_FLAGS_STATIC_IP;
}
else{
// Ask user if static IP is desired
if( AskUser( &MyAddr, &dwSubnetMask) )
{
pDHCPLeaseTime = NULL; // pDHCPLeaseTime is overloaded - NULL indicates static IP
pDriverGlobals->eth.EdbgFlags = EDBG_FLAGS_STATIC_IP;
}
}
// Initialize TFTP transport
if( !EbootInitEtherTransport( &MyAddr,
&dwSubnetMask,
&fGotJumpImg,
pDHCPLeaseTime,
EBOOT_VERSION_MAJOR,
EBOOT_VERSION_MINOR,
BSP_DEVICE_PREFIX,
NULL,
EDBG_CPUID,
0) )
{
return( BL_ERROR );
}
// update DHCP lease time
pDriverGlobals->eth.DHCPLeaseTime = DHCPLeaseTime;
return( fGotJumpImg? BL_JUMP : BL_DOWNLOAD );
}
//------------------------------------------------------------------------------
// Function: EthLaunch
//
//
//
void EthLaunch( DWORD dwImageStart,
DWORD dwImageLength,
DWORD dwLaunchAddr,
const ROMHDR *pRomHdr )
{
EDBG_OS_CONFIG_DATA *pCfgData = NULL;
EDBG_ADDR EshellHostAddr;
EdbgOutputDebugString("+EthLaunch( 0x%x, 0x%x, 0x%x, 0x%x )\r\n",
dwImageStart, dwImageLength, dwLaunchAddr, pRomHdr );
// Wait for the jump command from PB unless user specify jump directly
if( !fNoWait )
{
EdbgOutputDebugString ("Download successful! Jumping to image at %Xh...\r\n", dwLaunchAddr);
if( !(pCfgData = EbootWaitForHostConnect( &MyAddr, &EshellHostAddr )) )
{
EdbgOutputDebugString ("ERROR: EthLaunch: EbootWaitForHostConenct failed\r\n");
SpinForever();
// Should never get here. Also cleans up a prefast error...
return;
}
// Update service information
if( pCfgData->Flags & EDBG_FL_DBGMSG )
{
EdbgOutputDebugString("Enabling debug messages over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->DbgMsgIPAddr),ntohs(pCfgData->DbgMsgPort));
memcpy(&pDriverGlobals->eth.DbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pDriverGlobals->eth.DbgHostAddr.dwIP = pCfgData->DbgMsgIPAddr;
pDriverGlobals->eth.DbgHostAddr.wPort = pCfgData->DbgMsgPort;
}
if( pCfgData->Flags & EDBG_FL_PPSH )
{
EdbgOutputDebugString("Enabling CESH over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->PpshIPAddr),ntohs(pCfgData->PpshPort));
memcpy(&pDriverGlobals->eth.PpshHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pDriverGlobals->eth.PpshHostAddr.dwIP = pCfgData->PpshIPAddr;
pDriverGlobals->eth.PpshHostAddr.wPort = pCfgData->PpshPort;
}
if( pCfgData->Flags & EDBG_FL_KDBG )
{
EdbgOutputDebugString("Enabling KDBG over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->KdbgIPAddr),ntohs(pCfgData->KdbgPort));
memcpy(&pDriverGlobals->eth.KdbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pDriverGlobals->eth.KdbgHostAddr.dwIP = pCfgData->KdbgIPAddr;
pDriverGlobals->eth.KdbgHostAddr.wPort = pCfgData->KdbgPort;
}
pDriverGlobals->eth.etherFlags = pCfgData->Flags;
memcpy( &pDriverGlobals->eth.DownloadHostAddr,&EshellHostAddr,sizeof(EDBG_ADDR) );
}
// Update address info, in driver globals, and in EEPROM if necessary
pDriverGlobals->eth.EbootMagicNum = EBOOT_MAGIC_NUM;
if(pCfgData) pDriverGlobals->eth.KitlTransport = pCfgData->KitlTransport;
memcpy( &pDriverGlobals->eth.PlatformAddr, &MyAddr, sizeof(MyAddr) );
pDriverGlobals->eth.SubnetMask = dwSubnetMask;
// Update EEPROM IP/subnet information
UpdateEEPROMData( MyAddr.dwIP, dwSubnetMask );
if( dwLaunchAddr == 0 )
{
if( pDriverGlobals->dwLastLaunchAddrValid == LAST_LAUNCH_ADDR_VALID )
{
EdbgOutputDebugString("Using previous launch address\n");
dwLaunchAddr = pDriverGlobals->dwLastLaunchAddr;
}
else
{
if( pRomHdr && pRomHdr->physfirst != -1 )
{
dwLaunchAddr= pRomHdr->physfirst;
}
else
{
dwLaunchAddr = FLASH_IMAGE_START_CACHED; // Default launch address
}
}
}
else
{
pDriverGlobals->dwLastLaunchAddrValid = LAST_LAUNCH_ADDR_VALID;
pDriverGlobals->dwLastLaunchAddr=dwLaunchAddr;
}
EdbgOutputDebugString("\r\nJumping to existing image at %Xh...\r\n",dwLaunchAddr);
// Launch the OS - never returns
JumpToOS( dwLaunchAddr );
SpinForever();
}
//------------------------------------------------------------------------------
// Function: OEMEthGetFrame
//
// Receives a buffer from NIC driver. Returns TRUE if frame
// has been received, FALSE if not.
//
BOOL OEMEthGetFrame( BYTE *pData, UINT16 *pwLength )
{
return( SMCGetFrame(pData, pwLength) );
}
//------------------------------------------------------------------------------
// Function: OEMEthSendFrame
//
// Send Ethernet frame. Returns TRUE if frame successfully
// sent, FALSE otherwise.
//
BOOL OEMEthSendFrame( BYTE *pData, DWORD dwLength )
{
int retries = 0;
// Let's be persistant here
while( retries++ < 4 )
{
if( !SMCSendFrame(pData, dwLength) )
{
return TRUE;
}
else
{
EdbgOutputDebugString("ERROR: OEMEthSendFrame: Failed - retries %u\n",retries);
}
}
return FALSE;
}
//------------------------------------------------------------------------------
// Function: OEMEthGetSecs
//
// Return a count of seconds from some arbitrary time (the absolute value
// is not important, so long as it increments appropriately).
//
DWORD OEMEthGetSecs( void )
{
SYSTEMTIME st;
OEMGetRealTime( &st );
return((60UL * (60UL * (24UL * (31UL * st.wMonth + st.wDay) + st.wHour) + st.wMinute)) + st.wSecond);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -