You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.6 KiB
244 lines
6.6 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rom.c
|
|
|
|
Abstract:
|
|
|
|
Boot loader ROM routines.
|
|
|
|
Author:
|
|
|
|
Chuck Lenzmeier (chuckl) December 27, 1996
|
|
|
|
Revision History:
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <udp_api.h>
|
|
#include <tftp_api.h>
|
|
#include "bldr.h"
|
|
#include "efi.h"
|
|
#include "efip.h"
|
|
#include "bldria64.h"
|
|
#include "extern.h"
|
|
|
|
|
|
//
|
|
// We'll use this to keep track of which port we're communicating through.
|
|
//
|
|
EFI_PXE_BASE_CODE_UDP_PORT MachineLocalPort = 2000;
|
|
|
|
|
|
#define UDP_STALL_TIME (40000)
|
|
#define UDP_RETRY_COUNT (10)
|
|
|
|
extern VOID
|
|
FwStallExecution(
|
|
IN ULONG Microseconds
|
|
);
|
|
|
|
|
|
|
|
|
|
VOID
|
|
RomSetReceiveStatus (
|
|
IN USHORT UnicastUdpDestinationPort
|
|
#if 0
|
|
,
|
|
IN USHORT MulticastUdpDestinationPort,
|
|
IN ULONG MulticastUdpDestinationAddress,
|
|
IN USHORT MulticastUdpSourcePort,
|
|
IN ULONG MulticastUdpSourceAddress
|
|
#endif
|
|
)
|
|
{
|
|
return;
|
|
|
|
} // RomSetReceiveStatus
|
|
|
|
|
|
ULONG
|
|
RomSendUdpPacket (
|
|
IN PVOID Buffer,
|
|
IN ULONG Length,
|
|
IN ULONG RemoteHost,
|
|
IN USHORT pServerPort
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus = EFI_SUCCESS;
|
|
EFI_IP_ADDRESS DestinationIpAddress;
|
|
INTN Count = 0;
|
|
EFI_PXE_BASE_CODE_UDP_PORT ServerPort = pServerPort;
|
|
UINTN BufferLength = Length;
|
|
PVOID MyBuffer = NULL;
|
|
|
|
|
|
//
|
|
// Get the server's EFI_IP_ADDRESS from the handle to the PXE base code.
|
|
//
|
|
for( Count = 0; Count < 4; Count++ ) {
|
|
DestinationIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
|
|
}
|
|
|
|
FlipToPhysical();
|
|
|
|
//
|
|
// Make sure the address is a physical address, then do the UdpWrite.
|
|
//
|
|
MyBuffer = (PVOID)((ULONG_PTR)Buffer & ~KSEG0_BASE);
|
|
Count = UDP_RETRY_COUNT;
|
|
do {
|
|
EfiStatus = PXEClient->UdpWrite( PXEClient,
|
|
0,
|
|
&DestinationIpAddress,
|
|
&ServerPort,
|
|
NULL,
|
|
NULL,
|
|
&MachineLocalPort,
|
|
NULL,
|
|
NULL,
|
|
&BufferLength,
|
|
MyBuffer );
|
|
|
|
//
|
|
// This is really gross, but on retail builds with no debugger, EFI will go
|
|
// off in the weeds unless we slow down transactions over the network. So
|
|
// after Udp operations, take a short nap.
|
|
//
|
|
if( EfiStatus == EFI_TIMEOUT ) {
|
|
FwStallExecution( UDP_STALL_TIME );
|
|
}
|
|
Count--;
|
|
} while( (EfiStatus == EFI_TIMEOUT) && (Count > 0) );
|
|
|
|
FlipToVirtual();
|
|
|
|
|
|
if( EfiStatus != EFI_SUCCESS ) {
|
|
|
|
if( BdDebuggerEnabled ) {
|
|
DbgPrint( "RomSendUdpPacket: UdpWrite failed. MachineLocalPort: %d ServerPort: %d (%d)\r\n", MachineLocalPort, ServerPort, EfiStatus );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return (ULONG)BufferLength;
|
|
|
|
|
|
} // RomSendUdpPacket
|
|
|
|
|
|
ULONG
|
|
RomReceiveUdpPacket (
|
|
IN PVOID Buffer,
|
|
IN ULONG Length,
|
|
IN ULONG Timeout,
|
|
IN OUT PULONG RemoteHost,
|
|
IN OUT PUSHORT LocalPort
|
|
)
|
|
{
|
|
EFI_STATUS EfiStatus = EFI_SUCCESS;
|
|
UINTN BufferLength = Length;
|
|
EFI_IP_ADDRESS ServerIpAddress;
|
|
EFI_IP_ADDRESS MyIpAddress;
|
|
INTN Count = 0;
|
|
EFI_PXE_BASE_CODE_UDP_PORT ServerPort = (EFI_PXE_BASE_CODE_UDP_PORT)(0xFAB); // hardcode to 4011
|
|
PVOID MyBuffer = NULL;
|
|
ULONG startTime;
|
|
|
|
//
|
|
// Get The server's EFI_IP_ADDRESS from the handle to the PXE base code.
|
|
//
|
|
for( Count = 0; Count < 4; Count++ ) {
|
|
ServerIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
|
|
}
|
|
|
|
|
|
//
|
|
// Get our EFI_IP_ADDRESS from the handle to the PXE base code.
|
|
//
|
|
for( Count = 0; Count < 4; Count++ ) {
|
|
MyIpAddress.v4.Addr[Count] = PXEClient->Mode->StationIp.v4.Addr[Count];
|
|
}
|
|
|
|
|
|
startTime = SysGetRelativeTime();
|
|
if ( Timeout < 2 ) Timeout = 2;
|
|
|
|
//
|
|
// Make sure the address is a physical address, then do the UdpReceive.
|
|
//
|
|
MyBuffer = (PVOID)((ULONG_PTR)Buffer & ~KSEG0_BASE);
|
|
|
|
while ( (SysGetRelativeTime() - startTime) < Timeout ) {
|
|
|
|
FlipToPhysical();
|
|
|
|
//
|
|
// By setting flags to 0, we are setting a receive filter
|
|
// which says we'll only receive a packet from the specified
|
|
// IP address and port, sent to the specified IP address and
|
|
// port.
|
|
//
|
|
EfiStatus = PXEClient->UdpRead( PXEClient,
|
|
0,
|
|
&MyIpAddress,
|
|
&MachineLocalPort,
|
|
&ServerIpAddress,
|
|
&ServerPort,
|
|
NULL, // &HeaderLength
|
|
NULL, // HeaderBuffer
|
|
&BufferLength,
|
|
MyBuffer );
|
|
|
|
//
|
|
// This is really gross, but on retail builds with no debugger, EFI will go
|
|
// off in the weeds unless we slow down transactions over the network. So
|
|
// after Udp operations, take a short nap. We must be in physical mode
|
|
// when we call this API.
|
|
//
|
|
if( EfiStatus == EFI_TIMEOUT ) {
|
|
FwStallExecution( UDP_STALL_TIME );
|
|
}
|
|
|
|
//
|
|
// back into virtual mode -- we're either going to break out or do another
|
|
// loop, and the SysGetRelativeTime call wants us in physical mode.
|
|
//
|
|
FlipToVirtual();
|
|
if (EfiStatus == EFI_SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if( EfiStatus != EFI_SUCCESS ) {
|
|
|
|
if( BdDebuggerEnabled ) {
|
|
DbgPrint( "RomReceiveUdpPacket: UdpRead failed. MachineLocalPort: %d ServerPort: %d (%d)\r\n", MachineLocalPort, ServerPort, EfiStatus );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
return (ULONG)BufferLength;
|
|
|
|
} // RomReceiveUdpPacket
|
|
|
|
|
|
ULONG
|
|
RomGetNicType (
|
|
OUT t_PXENV_UNDI_GET_NIC_TYPE *NicType
|
|
)
|
|
{
|
|
return 0;
|
|
}
|