Initial import.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
bbahnsen
2006-04-21 22:54:32 +00:00
commit 878ddf1fc3
2651 changed files with 624620 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MbdHeader>
<BaseName>BC</BaseName>
<Guid>A3f436EA-A127-4EF8-957C-8048606FF670</Guid>
<Version>0</Version>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Created>2006-03-12 17:09</Created>
<Modified>2006-03-19 15:19</Modified>
</MbdHeader>
<Libraries>
<Library>UefiBootServicesTableLib</Library>
<Library>UefiMemoryLib</Library>
<Library>UefiLib</Library>
<Library>UefiDriverEntryPoint</Library>
<Library>UefiDriverModelLib</Library>
<Library>DxeReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>EdkDxePrintLib</Library>
<Library>BaseLib</Library>
<Library>DxeMemoryAllocationLib</Library>
</Libraries>
</ModuleBuildDescription>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MsaHeader>
<BaseName>BC</BaseName>
<ModuleType>UEFI_DRIVER</ModuleType>
<ComponentType>BS_DRIVER</ComponentType>
<Guid>A3f436EA-A127-4EF8-957C-8048606FF670</Guid>
<Version>0</Version>
<Abstract>Component description file for DiskIo module.</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Specification>0</Specification>
<Created>2006-03-12 17:09</Created>
<Updated>2006-03-19 15:19</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">PrintLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>bc.c</Filename>
<Filename>pxe_bc_arp.c</Filename>
<Filename>pxe_bc_dhcp.c</Filename>
<Filename>pxe_bc_igmp.c</Filename>
<Filename>pxe_bc_ip.c</Filename>
<Filename>pxe_bc_mtftp.c</Filename>
<Filename>pxe_bc_udp.c</Filename>
<Filename>pxe_loadfile.c</Filename>
<Filename>dhcp.h</Filename>
<Filename>bc.h</Filename>
<Filename>ip.h</Filename>
<Filename>ComponentName.c</Filename>
<Filename>Print.c</Filename>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="TO_START">Bis</Protocol>
<Protocol Usage="BY_START">LoadFile</Protocol>
<Protocol Usage="SOMETIMES_PRODUCED">PxeBaseCodeCallBack</Protocol>
<Protocol Usage="TO_START">SimpleNetwork</Protocol>
<Protocol Usage="TO_START">DevicePath</Protocol>
<Protocol Usage="SOMETIMES_CONSUMED">NetworkInterfaceIdentifier</Protocol>
<Protocol Usage="SOMETIMES_CONSUMED">NetworkInterfaceIdentifier2</Protocol>
<Protocol Usage="BY_START">PxeBaseCode</Protocol>
</Protocols>
<SystemTables>
<SystemTable Usage="SOMETIMES_CONSUMED">
<Entry>gEfiSmbiosTableGuid</Entry>
</SystemTable>
</SystemTables>
<Guids>
<GuidEntry Usage="ALWAYS_CONSUMED">
<C_Name>SmbiosTable</C_Name>
</GuidEntry>
</Guids>
<Externs>
<Extern>
<ModuleEntryPoint>InitializeBCDriver</ModuleEntryPoint>
<ModuleUnloadImage></ModuleUnloadImage>
</Extern>
<Extern>
<DriverBinding>gPxeBcDriverBinding</DriverBinding>
<ComponentName>gPxeBcComponentName</ComponentName>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,160 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
--*/
#include "Bc.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
PxeBcComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
PxeBcComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
EFI_COMPONENT_NAME_PROTOCOL gPxeBcComponentName = {
PxeBcComponentNameGetDriverName,
PxeBcComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mPxeBcDriverNameTable[] = {
{
"eng",
(CHAR16 *) L"PXE Base Code Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
PxeBcComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gPxeBcComponentName.SupportedLanguages,
mPxeBcDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
PxeBcComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,81 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Print.c
Abstract:
--*/
#include <Bc.h>
UINTN
EFIAPI
AsciiPrint (
IN CONST CHAR8 *Format,
...
)
/*++
Routine Description:
Print function for a maximum of PXE_MAX_PRINT_BUFFER ascii
characters.
Arguments:
Format - Ascii format string see file header for more details.
... - Vararg list consumed by processing Format.
Returns:
Number of characters printed.
--*/
{
UINTN Return;
VA_LIST Marker;
UINTN Index;
UINTN MaxIndex;
CHAR16 Buffer[PXE_MAX_PRINT_BUFFER];
CHAR16 UnicodeFormat[PXE_MAX_PRINT_BUFFER];
MaxIndex = AsciiStrLen ((CHAR8 *) Format);
if (MaxIndex > PXE_MAX_PRINT_BUFFER) {
//
// Format string was too long for use to process.
//
return 0;
}
for (Index = 0; Index < PXE_MAX_PRINT_BUFFER; Index++) {
UnicodeFormat[Index] = (CHAR16) Format[Index];
}
VA_START (Marker, Format);
Return = UnicodeVSPrint (Buffer, sizeof (Buffer), UnicodeFormat, Marker);
VA_END (Marker);
//
// Need to convert to Unicode to do an OutputString
//
if (gST->ConOut != NULL) {
//
// To be extra safe make sure ConOut has been initialized
//
gST->ConOut->OutputString (gST->ConOut, Buffer);
}
return Return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,499 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
bc.h
Abstract:
--*/
#ifndef _BC_H
#define _BC_H
#ifndef EFI_MIN
#define EFI_MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
#define CALLBACK_INTERVAL 100 // ten times a second
#define FILTER_BITS (EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP | \
EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST | \
EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS | \
EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST \
)
#define WAIT_TX_TIMEOUT 1000
#define SUPPORT_IPV6 0
#define PXE_BASECODE_DEVICE_SIGNATURE EFI_SIGNATURE_32('p','x','e','d')
//
// Determine the classes of IPv4 address
//
#define IS_CLASSA_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0x80) == 0x00)
#define IS_CLASSB_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0xc0) == 0x80)
#define IS_CLASSC_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0xe0) == 0xc0)
#define IS_INADDR_UNICAST(x) ((IS_CLASSA_IPADDR(x) || IS_CLASSB_IPADDR(x) || IS_CLASSC_IPADDR(x)) && (((EFI_IP_ADDRESS*)x)->Addr[0] != 0) )
//
// Definitions for internet group management protocol version 2 message
// structure
// Per RFC 2236, November 1997
//
#pragma pack(1)
typedef struct {
UINT8 Type;
UINT8 MaxRespTime; // in tenths of a second
UINT16 Checksum; // ones complement of ones complement sum of
// 16 bit words of message
UINT32 GroupAddress; // for general query, all systems group,
// for group specific, the group
} IGMPV2_MESSAGE;
#define IGMP_TYPE_QUERY 0x11
#define IGMP_TYPE_REPORT 0x16
#define IGMP_TYPE_V1REPORT 0x12
#define IGMP_TYPE_LEAVE_GROUP 0x17
#define IGMP_DEFAULT_MAX_RESPONSE_TIME 10 // 10 second default
#pragma pack()
#define MAX_MCAST_GROUPS 8 // most we allow ourselves to join at once
#define MAX_OFFERS 16
typedef struct {
UINTN Signature;
EFI_LOCK Lock;
BOOLEAN ShowErrorMessages;
EFI_PXE_BASE_CODE_PROTOCOL EfiBc;
EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *CallbackProtocolPtr;
EFI_HANDLE Handle;
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiPtr;
EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
UINT8 *TransmitBufferPtr;
UINT8 *ReceiveBufferPtr;
EFI_PXE_BASE_CODE_FUNCTION Function;
UINTN OldestArpEntry;
UINTN MCastGroupCount;
EFI_EVENT Igmpv1TimeoutEvent;
BOOLEAN UseIgmpv1Reporting;
EFI_EVENT IgmpGroupEvent[MAX_MCAST_GROUPS];
UINT16 RandomPort;
#if SUPPORT_IPV6
//
// TBD
//
#else
UINT32 MCastGroup[MAX_MCAST_GROUPS];
#endif
BOOLEAN GoodStationIp;
BOOLEAN DidTransmit;
UINTN IpLength;
VOID *DhcpPacketBuffer;
UINTN FileSize;
VOID *BootServerReceiveBuffer;
EFI_IP_ADDRESS ServerIp;
//
// work area
// for dhcp
//
VOID *ReceiveBuffers;
VOID *TransmitBuffer;
UINTN NumOffersReceived;
UINT16 TotalSeconds;
//
// arrays for different types of offers
//
UINT8 ServerCount[4];
UINT8 OfferCount[4][MAX_OFFERS];
UINT8 GotBootp;
UINT8 GotProxy[4];
UINT8 BinlProxies[MAX_OFFERS];
UINT8 *ArpBuffer;
UINT8 *TftpAckBuffer;
UINT8 *TftpErrorBuffer;
IGMPV2_MESSAGE IgmpMessage;
BOOLEAN BigBlkNumFlag;
UINT8 Timeout;
UINT16 RandomSeed;
} PXE_BASECODE_DEVICE;
//
// type index
//
#define DHCP_ONLY_IX 0
#define PXE10_IX 1
#define WfM11a_IX 2
#define BINL_IX 3
#define PXE_RND_PORT_LOW 2070
#define PXE_MAX_PRINT_BUFFER 128
//
//
//
#define LOADFILE_DEVICE_SIGNATURE EFI_SIGNATURE_32('p','x','e','l')
typedef struct {
UINTN Signature;
EFI_LOCK Lock;
EFI_LOAD_FILE_PROTOCOL LoadFile;
PXE_BASECODE_DEVICE *Private;
} LOADFILE_DEVICE;
#define EFI_BASE_CODE_DEV_FROM_THIS(a) CR (a, PXE_BASECODE_DEVICE, efi_bc, PXE_BASECODE_DEVICE_SIGNATURE);
#define EFI_LOAD_FILE_DEV_FROM_THIS(a) CR (a, LOADFILE_DEVICE, LoadFile, LOADFILE_DEVICE_SIGNATURE)
EFI_BIS_PROTOCOL *
PxebcBisStart (
PXE_BASECODE_DEVICE *Private,
BIS_APPLICATION_HANDLE *BisAppHandle,
EFI_BIS_DATA **BisDataSigInfo
)
;
VOID
PxebcBisStop (
EFI_BIS_PROTOCOL *Bis,
BIS_APPLICATION_HANDLE BisAppHandle,
EFI_BIS_DATA *BisDataSigInfo
)
;
BOOLEAN
PxebcBisVerify (
PXE_BASECODE_DEVICE *Private,
VOID *FileBuffer,
UINTN FileBufferLength,
VOID *CredentialBuffer,
UINTN CredentialBufferLength
)
;
BOOLEAN
PxebcBisDetect (
PXE_BASECODE_DEVICE *Private
)
;
//
// Global Variables
//
extern EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gPxeBcComponentName;
//
// //////////////////////////////////////////////////////////
//
// prototypes
//
EFI_STATUS
EFIAPI
InitializeBCDriver (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
;
EFI_STATUS
EFIAPI
BcStart (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN BOOLEAN UseIpv6
)
;
EFI_STATUS
EFIAPI
BcStop (
IN EFI_PXE_BASE_CODE_PROTOCOL *This
)
;
EFI_STATUS
EFIAPI
BcDhcp (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN BOOLEAN SortOffers
)
;
EFI_STATUS
EFIAPI
BcDiscover (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN UINT16 Type,
IN UINT16 *Layer,
IN BOOLEAN UseBis,
IN EFI_PXE_BASE_CODE_DISCOVER_INFO * Info OPTIONAL
)
;
EFI_STATUS
EFIAPI
BcMtftp (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation,
IN OUT VOID *BufferPtr,
IN BOOLEAN Overwrite,
IN OUT UINT64 *BufferSize,
IN UINTN *BlockSize OPTIONAL,
IN EFI_IP_ADDRESS * ServerIp,
IN UINT8 *Filename,
IN EFI_PXE_BASE_CODE_MTFTP_INFO * Info OPTIONAL,
IN BOOLEAN DontUseBuffer
)
;
EFI_STATUS
EFIAPI
BcUdpWrite (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN UINT16 OpFlags,
IN EFI_IP_ADDRESS *DestIp,
IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL
IN EFI_IP_ADDRESS *SrcIp, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL
IN UINTN *HeaderSize, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN UINTN *BufferSize,
IN VOID *BufferPtr
)
;
EFI_STATUS
EFIAPI
BcUdpRead (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN UINT16 OpFlags,
IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL
IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL
IN UINTN *HeaderSize, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN OUT UINTN *BufferSize,
IN VOID *BufferPtr
)
;
EFI_STATUS
EFIAPI
BcArp (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN EFI_IP_ADDRESS * IpAddr,
IN EFI_MAC_ADDRESS * MacAddr OPTIONAL
)
;
EFI_STATUS
EFIAPI
BcIpFilter (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter
)
;
EFI_STATUS
EFIAPI
BcSetParameters (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN BOOLEAN *NewAutoArp, OPTIONAL
IN BOOLEAN *NewSendGUID, OPTIONAL
IN UINT8 *NewTTL, OPTIONAL
IN UINT8 *NewToS, OPTIONAL
IN BOOLEAN *NewMakeCallback OPTIONAL
)
;
EFI_STATUS
EFIAPI
BcSetStationIP (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN EFI_IP_ADDRESS * NewStationIp, OPTIONAL
IN EFI_IP_ADDRESS * NewSubnetMask OPTIONAL
)
;
EFI_STATUS
EFIAPI
BcSetPackets (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
BOOLEAN *NewDhcpDiscoverValid, OPTIONAL
BOOLEAN *NewDhcpAckReceived, OPTIONAL
BOOLEAN *NewProxyOfferReceived, OPTIONAL
BOOLEAN *NewPxeDiscoverValid, OPTIONAL
BOOLEAN *NewPxeReplyReceived, OPTIONAL
BOOLEAN *NewPxeBisReplyReceived, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL
IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL
)
;
EFI_STATUS
EFIAPI
LoadFile (
IN EFI_LOAD_FILE_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN BOOLEAN BootPolicy,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
;
EFI_STATUS
PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
IN EFI_GUID *SystemGuid,
OUT CHAR8 **SystemSerialNumber
)
;
UINTN
EFIAPI
AsciiPrint (
IN CONST CHAR8 *Format,
...
)
;
//
// Define SMBIOS tables.
//
#pragma pack(1)
typedef struct {
UINT8 AnchorString[4];
UINT8 EntryPointStructureChecksum;
UINT8 EntryPointLength;
UINT8 MajorVersion;
UINT8 MinorVersion;
UINT16 MaxStructureSize;
UINT8 EntryPointRevision;
UINT8 FormattedArea[5];
UINT8 IntermediateAnchorString[5];
UINT8 IntermediateChecksum;
UINT16 TableLength;
UINT32 TableAddress;
UINT16 NumberOfSmbiosStructures;
UINT8 SmbiosBcdRevision;
} SMBIOS_STRUCTURE_TABLE;
//
// Please note that SMBIOS structures can be odd byte aligned since the
// unformated section of each record is a set of arbitrary size strings.
//
typedef struct {
UINT8 Type;
UINT8 Length;
UINT8 Handle[2];
} SMBIOS_HEADER;
typedef UINT8 SMBIOS_STRING;
typedef struct {
SMBIOS_HEADER Hdr;
SMBIOS_STRING Vendor;
SMBIOS_STRING BiosVersion;
UINT8 BiosSegment[2];
SMBIOS_STRING BiosReleaseDate;
UINT8 BiosSize;
UINT8 BiosCharacteristics[8];
} SMBIOS_TYPE0;
typedef struct {
SMBIOS_HEADER Hdr;
SMBIOS_STRING Manufacturer;
SMBIOS_STRING ProductName;
SMBIOS_STRING Version;
SMBIOS_STRING SerialNumber;
//
// always byte copy this data to prevent alignment faults!
//
EFI_GUID Uuid;
UINT8 WakeUpType;
} SMBIOS_TYPE1;
typedef struct {
SMBIOS_HEADER Hdr;
SMBIOS_STRING Manufacturer;
SMBIOS_STRING ProductName;
SMBIOS_STRING Version;
SMBIOS_STRING SerialNumber;
} SMBIOS_TYPE2;
typedef struct {
SMBIOS_HEADER Hdr;
SMBIOS_STRING Manufacturer;
UINT8 Type;
SMBIOS_STRING Version;
SMBIOS_STRING SerialNumber;
SMBIOS_STRING AssetTag;
UINT8 BootupState;
UINT8 PowerSupplyState;
UINT8 ThermalState;
UINT8 SecurityStatus;
UINT8 OemDefined[4];
} SMBIOS_TYPE3;
typedef struct {
SMBIOS_HEADER Hdr;
UINT8 Socket;
UINT8 ProcessorType;
UINT8 ProcessorFamily;
SMBIOS_STRING ProcessorManufacture;
UINT8 ProcessorId[8];
SMBIOS_STRING ProcessorVersion;
UINT8 Voltage;
UINT8 ExternalClock[2];
UINT8 MaxSpeed[2];
UINT8 CurrentSpeed[2];
UINT8 Status;
UINT8 ProcessorUpgrade;
UINT8 L1CacheHandle[2];
UINT8 L2CacheHandle[2];
UINT8 L3CacheHandle[2];
} SMBIOS_TYPE4;
typedef union {
SMBIOS_HEADER *Hdr;
SMBIOS_TYPE0 *Type0;
SMBIOS_TYPE1 *Type1;
SMBIOS_TYPE2 *Type2;
SMBIOS_TYPE3 *Type3;
SMBIOS_TYPE4 *Type4;
UINT8 *Raw;
} SMBIOS_STRUCTURE_POINTER;
#pragma pack()
#include "ip.h"
#include "dhcp.h"
#include "tftp.h"
#endif /* _BC_H */
/* EOF - bc.h */

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
<project basedir="." default="BC"><!--Apply external ANT tasks-->
<taskdef resource="GenBuild.tasks"/>
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<property environment="env"/>
<property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
<import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
<property name="MODULE_RELATIVE_PATH" value="Universal\Network\PxeBc\Dxe"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="BC">
<GenBuild baseName="BC" mbdFilename="${MODULE_DIR}\BC.mbd" msaFilename="${MODULE_DIR}\BC.msa"/>
</target>
<target depends="BC_clean" name="clean"/>
<target depends="BC_cleanall" name="cleanall"/>
<target name="BC_clean">
<OutputDirSetup baseName="BC" mbdFilename="${MODULE_DIR}\BC.mbd" msaFilename="${MODULE_DIR}\BC.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\BC_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\BC_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="BC_cleanall">
<OutputDirSetup baseName="BC" mbdFilename="${MODULE_DIR}\BC.mbd" msaFilename="${MODULE_DIR}\BC.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\BC_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\BC_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**BC*"/>
</delete>
</target>
</project>

View File

@@ -0,0 +1,627 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
--*/
#ifndef _DHCP_H
#define _DHCP_H
//
// Definitions for DHCP version 4 UDP packet.
// The field names in this structure are defined and described in RFC 2131.
//
#pragma pack(1)
typedef struct {
UINT8 op;
#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2
UINT8 htype;
UINT8 hlen;
UINT8 hops;
UINT32 xid;
UINT16 secs;
UINT16 flags;
#define DHCP_BROADCAST_FLAG 0x8000
UINT32 ciaddr;
UINT32 yiaddr;
UINT32 siaddr;
UINT32 giaddr;
UINT8 chaddr[16];
UINT8 sname[64];
UINT8 file[128];
UINT8 options[312];
#define OP_PAD 0
#define OP_END 255
#define OP_SUBNET_MASK 1
#define OP_TIME_OFFSET 2
#define OP_ROUTER_LIST 3
#define OP_TIME_SERVERS 4
#define OP_NAME_SERVERS 5
#define OP_DNS_SERVERS 6
#define OP_LOG_SERVERS 7
#define OP_COOKIE_SERVERS 8
#define OP_LPR_SREVERS 9
#define OP_IMPRESS_SERVERS 10
#define OP_RES_LOC_SERVERS 11
#define OP_HOST_NAME 12
#define OP_BOOT_FILE_SZ 13
#define OP_DUMP_FILE 14
#define OP_DOMAIN_NAME 15
#define OP_SWAP_SERVER 16
#define OP_ROOT_PATH 17
#define OP_EXTENSION_PATH 18
#define OP_IP_FORWARDING 19
#define OP_NON_LOCAL_SRC_RTE 20
#define OP_POLICY_FILTER 21
#define OP_MAX_DATAGRAM_SZ 22
#define OP_DEFAULT_TTL 23
#define OP_MTU_AGING_TIMEOUT 24
#define OP_MTU_SIZES 25
#define OP_MTU_TO_USE 26
#define OP_ALL_SUBNETS_LOCAL 27
#define OP_BROADCAST_ADD 28
#define OP_PERFORM_MASK_DISCOVERY 29
#define OP_RESPOND_TO_MASK_REQ 30
#define OP_PERFORM_ROUTER_DISCOVERY 31
#define OP_ROUTER_SOLICIT_ADDRESS 32
#define OP_STATIC_ROUTER_LIST 33
#define OP_USE_ARP_TRAILERS 34
#define OP_ARP_CACHE_TIMEOUT 35
#define OP_ETHERNET_ENCAPSULATION 36
#define OP_TCP_DEFAULT_TTL 37
#define OP_TCP_KEEP_ALIVE_INT 38
#define OP_KEEP_ALIVE_GARBAGE 39
#define OP_NIS_DOMAIN_NAME 40
#define OP_NIS_SERVERS 41
#define OP_NTP_SERVERS 42
#define OP_VENDOR_SPECIFIC 43
#define VEND_PXE_MTFTP_IP 1
#define VEND_PXE_MTFTP_CPORT 2
#define VEND_PXE_MTFTP_SPORT 3
#define VEND_PXE_MTFTP_TMOUT 4
#define VEND_PXE_MTFTP_DELAY 5
#define VEND_PXE_DISCOVERY_CONTROL 6
#define VEND_PXE_DISCOVERY_MCAST_ADDR 7
#define VEND_PXE_BOOT_SERVERS 8
#define VEND_PXE_BOOT_MENU 9
#define VEND_PXE_BOOT_PROMPT 10
#define VEND_PXE_MCAST_ADDRS_ALLOC 11
#define VEND_PXE_CREDENTIAL_TYPES 12
#define VEND_PXE_BOOT_ITEM 71
#define OP_NBNS_SERVERS 44
#define OP_NBDD_SERVERS 45
#define OP_NETBIOS_NODE_TYPE 46
#define OP_NETBIOS_SCOPE 47
#define OP_XWINDOW_SYSTEM_FONT_SERVERS 48
#define OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49
#define OP_DHCP_REQ_IP_ADD 50
#define OP_DHCP_LEASE_TIME 51
#define OP_DHCP_OPTION_OVERLOAD 52
#define OVLD_FILE 1
#define OVLD_SRVR_NAME 2
#define OP_DHCP_MESSAGE_TYPE 53
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8
#define OP_DHCP_SERVER_IP 54
#define OP_DHCP_PARM_REQ_LIST 55
#define OP_DHCP_ERROR_MESSAGE 56
#define OP_DHCP_MAX_MESSAGE_SZ 57
#define OP_DHCP_RENEWAL_TIME 58
#define OP_DHCP_REBINDING_TIME 59
#define OP_DHCP_CLASS_IDENTIFIER 60
#define OP_DHCP_CLIENT_IDENTIFIER 61
#define OP_NISPLUS_DOMAIN_NAME 64
#define OP_NISPLUS_SERVERS 65
#define OP_DHCP_TFTP_SERVER_NAME 66
#define OP_DHCP_BOOTFILE 67
#define OP_MOBILE_IP_HOME_AGENTS 68
#define OP_SMPT_SERVERS 69
#define OP_POP3_SERVERS 70
#define OP_NNTP_SERVERS 71
#define OP_WWW_SERVERS 72
#define OP_FINGER_SERVERS 73
#define OP_IRC_SERVERS 74
#define OP_STREET_TALK_SERVERS 75
#define OP_STREET_TALK_DIR_ASSIST_SERVERS 76
#define OP_NDS_SERVERS 85
#define OP_NDS_TREE_NAME 86
#define OP_NDS_CONTEXT 87
#define OP_DHCP_SYSTEM_ARCH 93
#define OP_DHCP_NETWORK_ARCH 94
#define OP_DHCP_PLATFORM_ID 97
} DHCPV4_STRUCT;
//
// DHCPv4 option header
//
typedef struct {
UINT8 OpCode;
UINT8 Length;
//
// followed by Data[]
//
} DHCPV4_OP_HEADER;
//
// Generic DHCPv4 option (header followed by data)
//
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Data[1];
} DHCPV4_OP_STRUCT;
//
// Maximum DHCP packet size on ethernet
//
#define MAX_DHCP_MSG_SZ (MAX_ENET_DATA_SIZE - sizeof (IPV4_HEADER) - sizeof (UDPV4_HEADER))
//
// Macros used in pxe_bc_dhcp.c and pxe_loadfile.c
//
#define DHCPV4_TRANSMIT_BUFFER (*(DHCPV4_STRUCT *) (Private->TransmitBuffer))
#define DHCPV4_OPTIONS_BUFFER (*(struct optionsstr *) DHCPV4_TRANSMIT_BUFFER.options)
#define DHCPV4_ACK_INDEX 0
#define PXE_BINL_INDEX 1
#define PXE_OFFER_INDEX 1
#define PXE_ACK_INDEX 2
#define PXE_BIS_INDEX 3
#define DHCPV4_ACK_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[DHCPV4_ACK_INDEX]
#define PXE_BINL_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_BINL_INDEX]
#define PXE_OFFER_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_OFFER_INDEX]
#define PXE_ACK_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_ACK_INDEX]
#define PXE_BIS_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_BIS_INDEX]
#define DHCPV4_ACK_PACKET DHCPV4_ACK_BUFFER.u.Dhcpv4
#define PXE_BINL_PACKET PXE_BINL_BUFFER.u.Dhcpv4
#define PXE_OFFER_PACKET PXE_OFFER_BUFFER.u.Dhcpv4
#define PXE_ACK_PACKET PXE_ACK_BUFFER.u.Dhcpv4
#define PXE_BIS_PACKET PXE_BIS_BUFFER.u.Dhcpv4
//
// network structure definitions
//
//
// some option definitions
//
#define DHCPV4_OPTION_LENGTH(type) (sizeof (type) - sizeof (DHCPV4_OP_HEADER))
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Type;
} DHCPV4_OP_MESSAGE_TYPE;
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Overload;
} DHCPV4_OP_OVERLOAD;
//
// boot server list structure
// one or more contained in a pxe boot servers structure
//
typedef struct {
UINT8 IpCount;
EFI_IPv4_ADDRESS IpList[1]; // IP count of IPs
} PXEV4_SERVER_LIST;
typedef struct {
UINT8 IpCount;
EFI_IPv6_ADDRESS IpList[1]; // IP count of IPs
} PXEV6_SERVER_LIST;
typedef union {
PXEV4_SERVER_LIST Ipv4List;
PXEV6_SERVER_LIST Ipv6List;
} PXE_SERVER_LISTS;
typedef struct {
UINT16 Type;
PXE_SERVER_LISTS u;
} PXE_SERVER_LIST;
//
// pxe boot servers structure
//
typedef struct {
DHCPV4_OP_HEADER Header;
PXE_SERVER_LIST ServerList[1]; // one or more
} PXE_OP_SERVER_LIST;
//
// pxe boot item structure
//
typedef struct {
DHCPV4_OP_HEADER Header;
UINT16 Type;
UINT16 Layer;
} PXE_OP_BOOT_ITEM;
//
// pxe boot menu item structure
//
typedef struct {
UINT16 Type;
UINT8 DataLen;
UINT8 Data[1];
} PXE_BOOT_MENU_ENTRY;
//
// pxe boot menu structure
//
typedef struct {
DHCPV4_OP_HEADER Header;
PXE_BOOT_MENU_ENTRY MenuItem[1];
} PXE_OP_BOOT_MENU;
//
// pxe boot prompt structure
//
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Timeout;
UINT8 Prompt[1];
} PXE_OP_BOOT_PROMPT;
#define PXE_BOOT_PROMPT_AUTO_SELECT 0
#define PXE_BOOT_PROMPT_NO_TIMEOUT 255
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Class[1];
} DHCPV4_OP_CLASS;
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 File[1];
} DHCPV4_OP_BOOTFILE;
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 VendorOptions[1];
} DHCPV4_OP_VENDOR_OPTIONS;
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 MaxSize[2];
} DHCPV4_OP_MAX_MESSAGE_SIZE;
typedef struct {
UINT8 _OP_SUBNET_MASK; /* 1 */
UINT8 _OP_TIME_OFFSET; /* 2 */
UINT8 _OP_ROUTER_LIST; /* 3 */
UINT8 _OP_TIME_SERVERS; /* 4 */
UINT8 _OP_NAME_SERVERS; /* 5 */
UINT8 _OP_DNS_SERVERS; /* 6 */
UINT8 _OP_HOST_NAME; /* 12 */
UINT8 _OP_BOOT_FILE_SZ; /* 13 */
UINT8 _OP_DOMAIN_NAME; /* 15 */
UINT8 _OP_ROOT_PATH; /* 17 */
UINT8 _OP_EXTENSION_PATH; /* 18 */
UINT8 _OP_MAX_DATAGRAM_SZ; /* 22 */
UINT8 _OP_DEFAULT_TTL; /* 23 */
UINT8 _OP_BROADCAST_ADD; /* 28 */
UINT8 _OP_NIS_DOMAIN_NAME; /* 40 */
UINT8 _OP_NIS_SERVERS; /* 41 */
UINT8 _OP_NTP_SERVERS; /* 42 */
UINT8 _OP_VENDOR_SPECIFIC; /* 43 */
UINT8 _OP_DHCP_REQ_IP_ADD; /* 50 */
UINT8 _OP_DHCP_LEASE_TIME; /* 51 */
UINT8 _OP_DHCP_SERVER_IP; /* 54 */
UINT8 _OP_DHCP_RENEWAL_TIME; /* 58 */
UINT8 _OP_DHCP_REBINDING_TIME; /* 59 */
UINT8 _OP_DHCP_CLASS_IDENTIFIER; /* 60 */
UINT8 _OP_DHCP_TFTP_SERVER_NAME; /* 66 */
UINT8 _OP_DHCP_BOOTFILE; /* 67 */
UINT8 _OP_DHCP_PLATFORM_ID; /* 97 */
UINT8 VendorOption128; // vendor option 128
UINT8 VendorOption129; // vendor option 129
UINT8 VendorOption130; // vendor option 130
UINT8 VendorOption131; // vendor option 131
UINT8 VendorOption132; // vendor option 132
UINT8 VendorOption133; // vendor option 133
UINT8 VendorOption134; // vendor option 134
UINT8 VendorOption135; // vendor option 135
} DHCPV4_REQUESTED_OPTIONS_DATA;
typedef struct {
DHCPV4_OP_HEADER Header;
DHCPV4_REQUESTED_OPTIONS_DATA Data;
} DHCPV4_OP_REQUESTED_OPTIONS;
typedef struct opipstr {
DHCPV4_OP_HEADER Header;
EFI_IPv4_ADDRESS Ip;
} DHCPV4_OP_IP_ADDRESS;
//
// ip list structure - e.g. router list
//
typedef struct {
DHCPV4_OP_HEADER Header;
EFI_IPv4_ADDRESS IpList[1];
} DHCPV4_OP_IP_LIST;
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Type;
UINT8 Guid[sizeof (EFI_GUID)];
} DHCPV4_OP_CLIENT_ID;
//
// special options start - someday obsolete ???
//
#define DHCPV4_OP_PLATFORM_ID DHCPV4_OP_CLIENT_ID
typedef struct {
DHCPV4_OP_HEADER Header;
UINT8 Type; // SNP = 2
UINT8 MajorVersion;
UINT8 MinorVersion;
} DHCPV4_OP_NETWORK_INTERFACE;
#define UNDI_TYPE 1
#define SNP_TYPE 2
typedef struct {
DHCPV4_OP_HEADER Header;
UINT16 Type;
} DHCPV4_OP_ARCHITECTURE_TYPE;
//
// special options end - someday obsolete ???
//
typedef struct {
UINT8 ClassIdentifier[10]; // PXEClient:
UINT8 Lit2[5]; // Arch:
UINT8 ArchitectureType[5]; // 00000 - 65536
UINT8 Lit3[1]; // :
UINT8 InterfaceName[4]; // e.g. UNDI
UINT8 Lit4[1]; // :
UINT8 UndiMajor[3]; // 000 - 255
UINT8 UndiMinor[3]; // 000 - 255
} DHCPV4_CLASS_ID_DATA;
typedef struct {
DHCPV4_OP_HEADER Header;
DHCPV4_CLASS_ID_DATA Data;
} DHCPV4_OP_CLASS_ID;
typedef struct {
DHCPV4_OP_HEADER Header;
EFI_IPv4_ADDRESS Ip;
} DHCPV4_OP_REQUESTED_IP;
typedef struct {
DHCPV4_OP_HEADER Header;
EFI_IPv4_ADDRESS Ip;
} DHCPV4_OP_SERVER_IP;
typedef struct {
DHCPV4_OP_HEADER Header;
EFI_IPv4_ADDRESS Ip;
} DHCPV4_OP_SUBNET_MASK;
typedef struct { // oppxedisctlstr {
DHCPV4_OP_HEADER Header;
UINT8 ControlBits;
} PXE_OP_DISCOVERY_CONTROL;
#define DISABLE_BCAST (1 << 0)
#define DISABLE_MCAST (1 << 1)
#define USE_ACCEPT_LIST (1 << 2)
#define USE_BOOTFILE (1 << 3)
#pragma pack()
//
// definitions of indices to populate option interest array
//
#define VEND_PXE_MTFTP_IP_IX 1 // multicast IP address of bootfile for MTFTP listen
#define VEND_PXE_MTFTP_CPORT_IX 2 // UDP Port to monitor for MTFTP responses - Intel order
#define VEND_PXE_MTFTP_SPORT_IX 3 // Server UDP Port for MTFTP open - Intel order
#define VEND_PXE_MTFTP_TMOUT_IX 4 // Listen timeout - secs
#define VEND_PXE_MTFTP_DELAY_IX 5 // Transmission timeout - secs
#define VEND_PXE_DISCOVERY_CONTROL_IX 6 // bit field
#define VEND_PXE_DISCOVERY_MCAST_ADDR_IX 7 // boot server discovery multicast address
#define VEND_PXE_BOOT_SERVERS_IX 8 // list of boot servers of form tp(2) cnt(1) ips[cnt]
#define VEND_PXE_BOOT_MENU_IX 9
#define VEND_PXE_BOOT_PROMPT_IX 10
#define VEND_PXE_MCAST_ADDRS_ALLOC_IX 0 // not used by PXE client
#define VEND_PXE_CREDENTIAL_TYPES_IX 11
#define VEND_13_IX 0 // not used by PXE client
#define VEND_14_IX 0 // not used by PXE client
#define VEND_15_IX 0 // not used by PXE client
#define VEND_16_IX 0 // not used by PXE client
#define VEND_17_IX 0 // not used by PXE client
#define VEND_18_IX 0 // not used by PXE client
#define VEND_19_IX 0 // not used by PXE client
#define VEND_20_IX 0 // not used by PXE client
#define VEND_21_IX 0 // not used by PXE client
#define VEND_22_IX 0 // not used by PXE client
#define VEND_23_IX 0 // not used by PXE client
#define VEND_24_IX 0 // not used by PXE client
#define VEND_25_IX 0 // not used by PXE client
#define VEND_26_IX 0 // not used by PXE client
#define VEND_27_IX 0 // not used by PXE client
#define VEND_28_IX 0 // not used by PXE client
#define VEND_29_IX 0 // not used by PXE client
#define VEND_30_IX 0 // not used by PXE client
#define VEND_31_IX 0 // not used by PXE client
#define VEND_32_IX 0 // not used by PXE client
#define VEND_33_IX 0 // not used by PXE client
#define VEND_34_IX 0 // not used by PXE client
#define VEND_35_IX 0 // not used by PXE client
#define VEND_36_IX 0 // not used by PXE client
#define VEND_37_IX 0 // not used by PXE client
#define VEND_38_IX 0 // not used by PXE client
#define VEND_39_IX 0 // not used by PXE client
#define VEND_40_IX 0 // not used by PXE client
#define VEND_41_IX 0 // not used by PXE client
#define VEND_42_IX 0 // not used by PXE client
#define VEND_43_IX 0 // not used by PXE client
#define VEND_44_IX 0 // not used by PXE client
#define VEND_45_IX 0 // not used by PXE client
#define VEND_46_IX 0 // not used by PXE client
#define VEND_47_IX 0 // not used by PXE client
#define VEND_48_IX 0 // not used by PXE client
#define VEND_49_IX 0 // not used by PXE client
#define VEND_50_IX 0 // not used by PXE client
#define VEND_51_IX 0 // not used by PXE client
#define VEND_52_IX 0 // not used by PXE client
#define VEND_53_IX 0 // not used by PXE client
#define VEND_54_IX 0 // not used by PXE client
#define VEND_55_IX 0 // not used by PXE client
#define VEND_56_IX 0 // not used by PXE client
#define VEND_57_IX 0 // not used by PXE client
#define VEND_58_IX 0 // not used by PXE client
#define VEND_59_IX 0 // not used by PXE client
#define VEND_60_IX 0 // not used by PXE client
#define VEND_61_IX 0 // not used by PXE client
#define VEND_62_IX 0 // not used by PXE client
#define VEND_63_IX 0 // not used by PXE client
#define VEND_64_IX 0 // not used by PXE client
#define VEND_65_IX 0 // not used by PXE client
#define VEND_66_IX 0 // not used by PXE client
#define VEND_67_IX 0 // not used by PXE client
#define VEND_68_IX 0 // not used by PXE client
#define VEND_69_IX 0 // not used by PXE client
#define VEND_70_IX 0 // not used by PXE client
#define VEND_PXE_BOOT_ITEM_IX 12
#define MAX_OUR_PXE_OPT VEND_PXE_BOOT_ITEM // largest PXE option in which we are interested
#define MAX_OUR_PXE_IX VEND_PXE_BOOT_ITEM_IX // largest PXE option index
//
// define various types by options that are sent
//
#define WfM11a_OPTS ((1<<VEND_PXE_MTFTP_IP_IX) | \
(1<<VEND_PXE_MTFTP_CPORT_IX) | \
(1<<VEND_PXE_MTFTP_SPORT_IX) | \
(1<<VEND_PXE_MTFTP_TMOUT_IX) | \
(1<<VEND_PXE_MTFTP_DELAY_IX))
#define DISCOVER_OPTS ((1<<VEND_PXE_DISCOVERY_CONTROL_IX) | \
(1<<VEND_PXE_DISCOVERY_MCAST_ADDR_IX) | \
(1<<VEND_PXE_BOOT_SERVERS_IX) | \
(1<<VEND_PXE_BOOT_MENU_IX) | \
(1<<VEND_PXE_BOOT_PROMPT_IX) | \
(1<<VEND_PXE_BOOT_ITEM_IX))
#define CREDENTIALS_OPT (1 << VEND_PXE_CREDENTIAL_TYPES_IX)
//
// definitions of indices to populate option interest array
//
#define OP_SUBNET_MASK_IX 1
#define OP_TIME_OFFSET_IX 0 // not used by PXE client
#define OP_ROUTER_LIST_IX 2
#define OP_TIME_SERVERS_IX 0 // not used by PXE client
#define OP_NAME_SERVERS_IX 0 // not used by PXE client
#define OP_DNS_SERVERS_IX 0 // not used by PXE client
#define OP_LOG_SERVERS_IX 0 // not used by PXE client
#define OP_COOKIE_SERVERS_IX 0 // not used by PXE client
#define OP_LPR_SREVERS_IX 0 // not used by PXE client
#define OP_IMPRESS_SERVERS_IX 0 // not used by PXE client
#define OP_RES_LOC_SERVERS_IX 0 // not used by PXE client
#define OP_HOST_NAME_IX 0 // not used by PXE client
#define OP_BOOT_FILE_SZ_IX 9
#define OP_DUMP_FILE_IX 0 // not used by PXE client
#define OP_DOMAIN_NAME_IX 0 // not used by PXE client
#define OP_SWAP_SERVER_IX 0 // not used by PXE client
#define OP_ROOT_PATH_IX 0 // not used by PXE client
#define OP_EXTENSION_PATH_IX 0 // not used by PXE client
#define OP_IP_FORWARDING_IX 0 // not used by PXE client
#define OP_NON_LOCAL_SRC_RTE_IX 0 // not used by PXE client
#define OP_POLICY_FILTER_IX 0 // not used by PXE client
#define OP_MAX_DATAGRAM_SZ_IX 0 // not used by PXE client
#define OP_DEFAULT_TTL_IX 0 // not used by PXE client
#define OP_MTU_AGING_TIMEOUT_IX 0 // not used by PXE client
#define OP_MTU_SIZES_IX 0 // not used by PXE client
#define OP_MTU_TO_USE_IX 0 // not used by PXE client
#define OP_ALL_SUBNETS_LOCAL_IX 0 // not used by PXE client
#define OP_BROADCAST_ADD_IX 0 // not used by PXE client
#define OP_PERFORM_MASK_DISCOVERY_IX 0 // not used by PXE client
#define OP_RESPOND_TO_MASK_REQ_IX 0 // not used by PXE client
#define OP_PERFORM_ROUTER_DISCOVERY_IX 0 // not used by PXE client
#define OP_ROUTER_SOLICIT_ADDRESS_IX 0 // not used by PXE client
#define OP_STATIC_ROUTER_LIST_IX 0 // not used by PXE client
#define OP_USE_ARP_TRAILERS_IX 0 // not used by PXE client
#define OP_ARP_CACHE_TIMEOUT_IX 0 // not used by PXE client
#define OP_ETHERNET_ENCAPSULATION_IX 0 // not used by PXE client
#define OP_TCP_DEFAULT_TTL_IX 0 // not used by PXE client
#define OP_TCP_KEEP_ALIVE_INT_IX 0 // not used by PXE client
#define OP_KEEP_ALIVE_GARBAGE_IX 0 // not used by PXE client
#define OP_NIS_DOMAIN_NAME_IX 0 // not used by PXE client
#define OP_NIS_SERVERS_IX 0 // not used by PXE client
#define OP_NTP_SERVERS_IX 0 // not used by PXE client
#define OP_VENDOR_SPECIFIC_IX 3
#define OP_NBNS_SERVERS_IX 0 // not used by PXE client
#define OP_NBDD_SERVERS_IX 0 // not used by PXE client
#define OP_NETBIOS_NODE_TYPE_IX 0 // not used by PXE client
#define OP_NETBIOS_SCOPE_IX 0 // not used by PXE client
#define OP_XWINDOW_SYSTEM_FONT_SERVERS_IX 0 // not used by PXE client
#define OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS_IX 0 // not used by PXE client
// DHCP option indices
//
#define OP_DHCP_REQ_IP_ADD_IX 0 // not used by PXE client
#define OP_DHCP_LEASE_TIME_IX 0 // not used by PXE client
#define OP_DHCP_OPTION_OVERLOAD_IX 4
#define OP_DHCP_MESSAGE_TYPE_IX 5
#define OP_DHCP_SERVER_IP_IX 6
#define OP_DHCP_PARM_REQ_LIST_IX 0 // not used by PXE client
#define OP_DHCP_ERROR_MESSAGE_IX 0 // not used by PXE client
#define OP_DHCP_MAX_MESSAGE_SZ_IX 0 // not used by PXE client
#define OP_DHCP_RENEWAL_TIME_IX 0 // not used by PXE client
#define OP_DHCP_REBINDING_TIME_IX 0 // not used by PXE client
#define OP_DHCP_CLASS_IDENTIFIER_IX 7
#define OP_DHCP_CLIENT_IDENTIFIER_IX 0 // not used by PXE client
#define OP_RESERVED62_IX 0 // not used by PXE client
#define OP_RESERVED63_IX 0 // not used by PXE client
#define OP_NISPLUS_DOMAIN_NAME_IX 0 // not used by PXE client
#define OP_NISPLUS_SERVERS_IX 0 // not used by PXE client
#define OP_DHCP_TFTP_SERVER_NAME_IX 0 // not used by PXE client
#define OP_DHCP_BOOTFILE_IX 8
#define MAX_OUR_OPT OP_DHCP_BOOTFILE // largest option in which we are interested
#define MAX_OUR_IX OP_BOOT_FILE_SZ_IX
typedef struct {
DHCPV4_OP_STRUCT *PktOptAdds[MAX_OUR_IX];
DHCPV4_OP_STRUCT *PxeOptAdds[MAX_OUR_PXE_IX];
UINT8 Status;
} OPTION_POINTERS;
typedef struct DhcpReceiveBufferStruct {
union {
UINT8 ReceiveBuffer[MAX_DHCP_MSG_SZ];
DHCPV4_STRUCT Dhcpv4;
} u;
OPTION_POINTERS OpAdds;
} DHCP_RECEIVE_BUFFER;
#define PXE_TYPE (1 << 0)
#define WfM11a_TYPE (1 << 1)
#define DISCOVER_TYPE (1 << 2)
#define CREDENTIALS_TYPE (1 << 3)
#define USE_THREE_BYTE (1 << 4)
#endif // _DHCP_H
/* EOF - dhcp.h */

View File

@@ -0,0 +1,42 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
hton.h
Abstract:
Byte swapping macros.
--*/
#ifndef _HTON_H_
#define _HTON_H_
//
// Only Intel order functions are defined at this time.
//
#define HTONS(v) (UINT16) ((((v) << 8) & 0xff00) + (((v) >> 8) & 0x00ff))
#define HTONL(v) \
(UINT32) ((((v) << 24) & 0xff000000) + (((v) << 8) & 0x00ff0000) + (((v) >> 8) & 0x0000ff00) + (((v) >> 24) & 0x000000ff))
#define HTONLL(v) swap64 (v)
#define U8PTR(na) ((UINT8 *) &(na))
#define NTOHS(ns) ((UINT16) (((*U8PTR (ns)) << 8) +*(U8PTR (ns) + 1)))
#define NTOHL(ns) \
((UINT32) (((*U8PTR (ns)) << 24) + ((*(U8PTR (ns) + 1)) << 16) + ((*(U8PTR (ns) + 2)) << 8) +*(U8PTR (ns) + 3)))
#endif /* _HTON_H_ */
/* EOF - hton.h */

View File

@@ -0,0 +1,741 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
--*/
#ifndef _IP_H_
#define _IP_H_
#include "hton.h"
//
// Client architecture types
//
#define IA64 2
#define SYS_ARCH_EFI32 6
//
// portability macros
//
#define UDP_FILTER_MASK (EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | \
EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT | \
EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | \
EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT | \
EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER \
)
#define PXE_BOOT_LAYER_MASK 0x7FFF
#define PXE_BOOT_LAYER_INITIAL 0x0000
#define PXE_BOOT_LAYER_CREDENTIAL_FLAG 0x8000
#define MAX_BOOT_SERVERS 32
//
// macro to evaluate IP address as TRUE if it is a multicast IP address
//
#define IS_MULTICAST(ptr) ((*((UINT8 *) ptr) & 0xf0) == 0xe0)
//
// length macros
//
#define IP_ADDRESS_LENGTH(qp) (((qp)->UsingIpv6) ? sizeof (EFI_IPv6_ADDRESS) : sizeof (EFI_IPv4_ADDRESS))
#define MAX_FRAME_DATA_SIZE 1488
#define ALLOCATE_SIZE(X) (((X) + 7) & 0xfff8)
#define MODE_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_MODE))
#define BUFFER_ALLOCATE_SIZE (8192 + 512)
#define ROUTER_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY) * PXE_ROUTER_TABLE_SIZE))
#define ARP_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_PXE_BASE_CODE_ARP_ENTRY) * PXE_ARP_CACHE_SIZE))
#define FILTER_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_IP_ADDRESS) * PXE_IP_FILTER_SIZE))
#define PXE_ARP_CACHE_SIZE 8
#define PXE_ROUTER_TABLE_SIZE 8
#define PXE_IP_FILTER_SIZE 8
#define ICMP_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR))
#define TFTP_ERR_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR))
//
// DHCP discover/request packets are sent to this UDP port. ProxyDHCP
// servers listen on this port for DHCP discover packets that have a
// class identifier (option 60) with 'PXEClient' in the first 9 bytes.
// Bootservers also listen on this port for PXE broadcast discover
// requests from PXE clients.
//
#define DHCP_SERVER_PORT 67
//
// When DHCP, proxyDHCP and Bootservers respond to DHCP and PXE broadcast
// discover requests by broadcasting the reply packet, the packet is
// broadcast to this port.
//
#define DHCP_CLIENT_PORT 68
//
// TFTP servers listen for TFTP open requests on this port.
//
#define TFTP_OPEN_PORT 69
//
// proxyDHCP and Bootservers listen on this port for a PXE unicast and/or
// multicast discover requests from PXE clients. A PXE discover request
// looks like a DHCP discover or DHCP request packet.
//
#define PXE_DISCOVERY_PORT 4011
//
// This port is used by the PXE client/server protocol tests.
//
#define PXE_PORT_PXETEST_PORT 0x8080
//
// Definitions for Ethertype protocol numbers and interface types
// Per RFC 1700,
//
#define PXE_PROTOCOL_ETHERNET_IP 0x0800
#define PXE_PROTOCOL_ETHERNET_ARP 0x0806
#define PXE_PROTOCOL_ETHERNET_RARP 0x8035
#define PXE_IFTYPE_ETHERNET 0x01
#define PXE_IFTYPE_TOKENRING 0x04
#define PXE_IFTYPE_FIBRE_CHANNEL 0x12
//
// Definitions for internet protocol version 4 header
// Per RFC 791, September 1981.
//
#define IPVER4 4
#pragma pack(1) // make network structures packed byte alignment
typedef union {
UINT8 B[4];
UINT32 L;
} IPV4_ADDR;
#define IPV4_HEADER_LENGTH(IpHeaderPtr) (((IpHeaderPtr)->VersionIhl & 0xf) << 2)
#define SET_IPV4_VER_HDL(IpHeaderPtr, IpHeaderLen) { \
(IpHeaderPtr)->VersionIhl = (UINT8) ((IPVER4 << 4) | ((IpHeaderLen) >> 2)); \
}
typedef struct {
UINT8 VersionIhl;
UINT8 TypeOfService;
UINT16 TotalLength;
UINT16 Id;
UINT16 FragmentFields;
UINT8 TimeToLive;
UINT8 Protocol;
UINT16 HeaderChecksum;
IPV4_ADDR SrcAddr;
IPV4_ADDR DestAddr;
//
// options are not implemented
//
} IPV4_HEADER;
#define IP_FRAG_RSVD 0x8000 // reserved bit - must be zero
#define IP_NO_FRAG 0x4000 // do not fragment bit
#define IP_MORE_FRAG 0x2000 // not last fragment
#define IP_FRAG_OFF_MSK 0x1fff // fragment offset in 8 byte chunks
#define DEFAULT_RFC_TTL 64
#define PROT_ICMP 1
#define PROT_IGMP 2
#define PROT_TCP 6
#define PROT_UDP 17
/*
* Definitions for internet control message protocol version 4 message
* structure. Per RFC 792, September 1981.
*/
//
// icmp header for all icmp messages
//
typedef struct {
UINT8 Type; // message type
UINT8 Code; // type specific - 0 for types we implement
UINT16 Checksum; // ones complement of ones complement sum of 16 bit words of message
} ICMPV4_HEADER;
#define ICMP_DEST_UNREACHABLE 3
#define ICMP_SOURCE_QUENCH 4
#define ICMP_REDIRECT 5
#define ICMP_ECHO 8
#define ICMP_ECHO_REPLY 0
#define ICMP_ROUTER_ADV 9
#define ICMP_ROUTER_SOLICIT 10
#define ICMP_TIME_EXCEEDED 11
#define ICMP_PARAMETER_PROBLEM 12
#define ICMP_TIMESTAMP 13
#define ICMP_TIMESTAMP_REPLY 14
#define ICMP_INFO_REQ 15
#define ICMP_INFO_REQ_REPLY 16
#define ICMP_SUBNET_MASK_REQ 17
#define ICMP_SUBNET_MASK_REPLY 18
//
// other ICMP message types ignored in this implementation
//
// icmp general messages
//
typedef struct {
ICMPV4_HEADER Header;
//
// generally unused except byte [0] for
// parameter problem message
//
UINT8 GenerallyUnused[4];
//
// original message ip header of plus 64
// bits of data
//
IPV4_HEADER IpHeader;
} ICMPV4_GENERAL_MESSAGE;
//
// icmp req/rply message header
//
typedef struct {
ICMPV4_HEADER Header;
UINT16 Id;
UINT16 SequenceNumber;
} ICMPV4_REQUEST_REPLY_HEADER;
//
// icmp echo message
//
typedef struct {
ICMPV4_REQUEST_REPLY_HEADER Header;
UINT8 EchoData[1]; // variable length data to be echoed
} ICMPV4_ECHO_MESSAGE;
//
// icmp timestamp message - times are milliseconds since midnight UT -
// if non std, set high order bit
//
typedef struct {
ICMPV4_REQUEST_REPLY_HEADER Header;
UINT32 OriginalTime; // originating timestamp
UINT32 ReceiveTime; // receiving timestamp
UINT32 TransmitTime; // transmitting timestamp
} ICMPV4_TIMESTAMP_MESSAGE;
//
// icmp info request structure - fill in source and dest net ip address on reply
//
typedef struct {
ICMPV4_REQUEST_REPLY_HEADER Header;
} ICMPV4_INFO_MESSAGE;
//
// Definitions for internet control message protocol version 4 message structure
// Router discovery
// Per RFC 1256, September 1991.
//
//
// icmp router advertisement message
//
typedef struct {
ICMPV4_HEADER Header;
UINT8 NumberEntries; // number of address entries
UINT8 EntrySize; // number of 32 bit words per address entry
UINT16 Lifetime; // seconds to consider info valid
UINT32 RouterIp;
UINT32 Preferance;
} ICMPV4_ROUTER_ADVERTISE_MESSAGE;
//
// icmp router solicitation message
//
typedef struct {
ICMPV4_HEADER Header;
UINT32 Reserved;
} ICMPV4_ROUTER_SOLICIT_MESSAGE;
#define MAX_SOLICITATION_DELAY 1 // 1 second
#define SOLICITATION_INTERVAL 3 // 3 seconds
#define MAX_SOLICITATIONS 3 // 3 transmissions
#define V1ROUTER_PRESENT_TIMEOUT 400 // 400 second timeout until v2 reports can be sent
#define UNSOLICITED_REPORT_INTERVAL 10 // 10 seconds between unsolicited reports
#define BROADCAST_IPv4 0xffffffff
//
// Definitions for address resolution protocol message structure
// Per RFC 826, November 1982
//
typedef struct {
UINT16 HwType; // hardware type - e.g. ethernet (1)
UINT16 ProtType; // protocol type - for ethernet, 0x800 for IP
UINT8 HwAddLen; // byte length of a hardware address (e.g. 6 for ethernet)
UINT8 ProtAddLen; // byte length of a protocol address (e.g. 4 for ipv4)
UINT16 OpCode;
//
// source and dest hw and prot addresses follow - see example below
//
} ARP_HEADER;
#define ETHERNET_ADD_SPC 1
#define ETHER_TYPE_IP 0x800
#define ARP_REQUEST 1
#define ARP_REPLY 2
//
// generic ARP packet
//
typedef struct {
ARP_HEADER ArpHeader;
EFI_MAC_ADDRESS SrcHardwareAddr;
EFI_IP_ADDRESS SrcProtocolAddr;
EFI_MAC_ADDRESS DestHardwareAddr;
EFI_IP_ADDRESS DestProtocolAddr;
} ARP_PACKET;
#define ENET_HWADDLEN 6
#define IPV4_PROTADDLEN 4
//
// Definitions for user datagram protocol version 4 pseudo header & header
// Per RFC 768, 28 August 1980
//
typedef struct {
IPV4_ADDR SrcAddr; // source ip address
IPV4_ADDR DestAddr; // dest ip address
UINT8 Zero; // 0
UINT8 Protocol; // protocol
UINT16 TotalLength; // UDP length - sizeof udpv4hdr + data length
} UDPV4_PSEUDO_HEADER;
typedef struct {
UINT16 SrcPort; // source port identifier
UINT16 DestPort; // destination port identifier
UINT16 TotalLength; // total length header plus data
//
// ones complement of ones complement sum of 16 bit
// words of pseudo header, UDP header, and data
// zero checksum is transmitted as -0 (ones comp)
// zero transmitted means checksum not computed
// data follows
//
UINT16 Checksum;
} UDPV4_HEADER;
typedef struct {
UDPV4_PSEUDO_HEADER Udpv4PseudoHeader;
UDPV4_HEADER Udpv4Header;
} UDPV4_HEADERS;
//
// Definitions for transmission control protocol header
// Per RFC 793, September, 1981
//
typedef struct {
IPV4_ADDR SrcAddr; // source ip address
IPV4_ADDR DestAddr; // dest ip address
UINT8 Zero; // 0
UINT8 Protocol; // protocol
UINT16 TotalLength; // TCP length - TCP header length + data length
} TCPV4_PSEUDO_HEADER;
typedef struct {
UINT16 SrcPort; // source port identifier
UINT16 DestPort; // destination port identifier
UINT32 SeqNumber; // Sequence number
UINT32 AckNumber; // Acknowledgement Number
//
// Nibble of HLEN (length of header in 32-bit multiples)
// 6bits of RESERVED
// Nibble of Code Bits
//
UINT16 HlenResCode;
UINT16 Window; // Software buffer size (sliding window size) in network-standard byte order
//
// ones complement of ones complement sum of 16 bit words of
// pseudo header, TCP header, and data
// zero checksum is transmitted as -0 (ones comp)
// zero transmitted means checksum not computed
//
UINT16 Checksum;
UINT16 UrgentPointer; // pointer to urgent data (allows sender to specify urgent data)
} TCPV4_HEADER;
typedef struct {
TCPV4_PSEUDO_HEADER Tcpv4PseudoHeader;
TCPV4_HEADER Tcpv4Header;
} TCPV4_HEADERS;
typedef struct {
UINT8 Kind; // one of the following:
UINT8 Length; // total option length including Kind and Lth
UINT8 Data[1]; // length = Lth - 2
} TCPV4_OPTION;
#define TCP_OP_END 0 // only used to pad to end of TCP header
#define TCP_NOP 1 // optional - may be used to pad between options to get alignment
#define TCP_MAX_SEG 2 // maximum receive segment size - only send at initial connection request
#define MAX_MEDIA_HDR_SIZE 64
#define MIN_ENET_DATA_SIZE 64
#define MAX_ENET_DATA_SIZE 1500 // temp def - make a network based var
#define MAX_IPV4_PKT_SIZE 65535 // maximum IP packet size
#define MAX_IPV4_DATA_SIZE (MAX_IPV4_PKT_SIZE - sizeof (IPV4_HEADER))
#define MAX_IPV4_FRAME_DATA_SIZE (MAX_FRAME_DATA_SIZE - sizeof (IPV4_HEADER))
#define REAS_IPV4_PKT_SIZE 576 // minimum IP packet size all IP host can handle
#define REAS_IPV4_DATA_SIZE (REAS_IPV4_PKT_SIZE - sizeof (IPV4_HEADER))
//
//
//
typedef union {
UINT8 Data[MAX_ENET_DATA_SIZE];
ICMPV4_HEADER IcmpHeader;
IGMPV2_MESSAGE IgmpMessage;
struct {
UDPV4_HEADER UdpHeader;
UINT8 Data[1];
} Udp;
struct {
TCPV4_HEADER TcpHeader;
UINT8 Data[1];
} Tcp;
} PROTOCOL_UNION;
//
// out buffer structure
//
typedef struct {
UINT8 MediaHeader[MAX_MEDIA_HDR_SIZE];
IPV4_HEADER IpHeader;
//
// following union placement only valid if no option IP header
//
PROTOCOL_UNION u;
} IPV4_BUFFER;
typedef struct {
IPV4_HEADER IpHeader;
//
// following union placement only valid if no option IP header
//
PROTOCOL_UNION u;
} IPV4_STRUCT;
#pragma pack() // reset to default
////////////////////////////////////////////////////////////
//
// BC IP Filter Routine
//
EFI_STATUS
IpFilter (
PXE_BASECODE_DEVICE *Private,
IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
)
;
//
// //////////////////////////////////////////////////////////////////////
//
// Udp Write Routine - called by base code - e.g. TFTP - already locked
//
EFI_STATUS
UdpWrite (
IN PXE_BASECODE_DEVICE *Private,
IN UINT16 OpFlags,
IN EFI_IP_ADDRESS *DestIpPtr,
IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortptr,
IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL
IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL
IN UINTN *HeaderSizePtr, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN UINTN *BufferSizePtr,
IN VOID *BufferPtr
)
;
//
// /////////////////////////////////////////////////////////////////////
//
// Udp Read Routine - called by base code - e.g. TFTP - already locked
//
EFI_STATUS
UdpRead (
IN PXE_BASECODE_DEVICE *Private,
IN UINT16 OpFlags,
IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPorPtrt, OPTIONAL
IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL
IN UINTN *HeaderSizePtr, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN OUT UINTN *BufferSizePtr,
IN VOID *BufferPtr,
IN EFI_EVENT TimeoutEvent
)
;
VOID
IgmpLeaveGroup (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *
)
;
VOID
IgmpJoinGroup (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *
)
;
//
// convert number to zero filled ascii value of length lth
//
VOID
CvtNum (
UINTN Number,
UINT8 *BufferPtr,
INTN BufferLen
)
;
//
// convert number to ascii string at ptr
//
VOID
UtoA10 (
UINTN Number,
UINT8 *BufferPtr
)
;
//
// convert ascii numeric string to UINTN
//
UINTN
AtoU (
UINT8 *BufferPtr
)
;
UINT64
AtoU64 (
UINT8 *BufferPtr
)
;
//
// calculate the internet checksum (RFC 1071)
// return 16 bit ones complement of ones complement sum of 16 bit words
//
UINT16
IpChecksum (
UINT16 *MessagePtr,
UINTN ByteLength
)
;
//
// do checksum on non contiguous header and data
//
UINT16
IpChecksum2 (
UINT16 *Header,
UINTN HeaderLength,
UINT16 *Message,
UINTN MessageLength
)
;
//
// update checksum when only a single word changes
//
UINT16
UpdateChecksum (
UINT16 OldChecksum,
UINT16 OldWord,
UINT16 NewWord
)
;
VOID
SeedRandom (
IN PXE_BASECODE_DEVICE *Private,
IN UINT16 InitialSeed
)
;
UINT16
Random (
IN PXE_BASECODE_DEVICE *Private
)
;
EFI_STATUS
SendPacket (
PXE_BASECODE_DEVICE *Private,
VOID *HeaderPtr,
VOID *PacketPtr,
INTN PacketLength,
VOID *HardwareAddress,
UINT16 MediaProtocol,
IN EFI_PXE_BASE_CODE_FUNCTION Function
)
;
VOID
HandleArpReceive (
PXE_BASECODE_DEVICE *Private,
ARP_PACKET *ArpPacketPtr,
VOID *HeaderPtr
)
;
VOID
HandleIgmp (
PXE_BASECODE_DEVICE *Private,
IGMPV2_MESSAGE *IgmpMessageptr,
UINTN IgmpMessageLen
)
;
VOID
IgmpCheckTimers (
PXE_BASECODE_DEVICE *Private
)
; // poll when doing a receive
// return hw add of IP and TRUE if available, otherwise FALSE
//
BOOLEAN
GetHwAddr (
IN PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *ProtocolAddressPtr,
EFI_MAC_ADDRESS *HardwareAddressPtr
)
;
EFI_STATUS
DoArp (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_IP_ADDRESS *ProtocolAddressPtr,
OUT EFI_MAC_ADDRESS *HardwareAddressptr
)
;
BOOLEAN
OnSameSubnet (
UINTN IpAddressLen,
EFI_IP_ADDRESS *Ip1,
EFI_IP_ADDRESS *Ip2,
EFI_IP_ADDRESS *SubnetMask
)
;
VOID
IpAddRouter (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *RouterIp
)
;
#define Ip4AddRouter(Private, Ipv4Ptr) IpAddRouter (Private, (EFI_IP_ADDRESS *) Ipv4Ptr)
//
// routine to send ipv4 packet
// ipv4 + upper protocol header for length TotHdrLth in xmtbuf, ipv4 header length IpHdrLth
// routine fills in ipv4hdr Ver_Hdl, TotLth, and Checksum, moves in Data, and gets dest MAC address
//
EFI_STATUS
Ipv4Xmt (
PXE_BASECODE_DEVICE *Private,
UINT32 GatewayIP,
UINTN IpHeaderLen,
UINTN TotalHeaderLen,
VOID *Data,
UINTN DataLen,
EFI_PXE_BASE_CODE_FUNCTION Function
)
;
//
// send ipv4 packet with ipv4 option
//
EFI_STATUS
Ipv4SendWOp (
PXE_BASECODE_DEVICE *Private,
UINT32 GatewayIP,
UINT8 *MessagePtr,
UINTN MessageLth,
UINT8 Protocol,
UINT8 *Option,
UINTN OptionLen,
UINT32 DestIp,
EFI_PXE_BASE_CODE_FUNCTION Function
)
;
//
// send MsgLth message at MsgPtr - higher level protocol header already in xmtbuf, length HdrSize
//
EFI_STATUS
Ip4Send (
IN PXE_BASECODE_DEVICE *Private, // pointer to instance data
IN UINTN MayFragment, //
IN UINT8 Protocol, // protocol
IN UINT32 SrcIp, // Source IP address
IN UINT32 DestIp, // Destination IP address
IN UINT32 GatewayIp, // used if not NULL and needed
IN UINTN HeaderSize, // protocol header byte length
IN UINT8 *MsgPtr, // pointer to data
IN UINTN MsgLength
)
; // data byte length
// receive up to MsgLth message into MsgPtr for protocol Prot
// return message length, src/dest ips if select any, and pointer to protocol header
//
EFI_STATUS
IpReceive (
IN PXE_BASECODE_DEVICE *Private, // pointer to instance data
UINT16 OpFlags, // Flags to determine if filtering on IP addresses
EFI_IP_ADDRESS *SrcIpPtr, // if filtering, O if accept any
EFI_IP_ADDRESS *DstIpPtr, // if filtering, O if accept any
UINT8 Protocol, // protocol
VOID *HeaderPtr, // address of where to put protocol header
UINTN HeaderSize, // protocol header byte length
UINT8 *MsgPtr, // pointer to data buffer
UINTN *MsgLenPtr, // pointer to data buffer length/ O - returned data length
IN EFI_EVENT TimeoutEvent
)
;
#if 0
VOID
WaitForTxComplete (
IN PXE_BASECODE_DEVICE *Private
)
;
#endif
//
// routine to cycle waiting for a receive or timeout
//
EFI_STATUS
WaitForReceive (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_PXE_BASE_CODE_FUNCTION Function,
IN EFI_EVENT TimeoutEvent,
IN OUT UINTN *HeaderSizePtr,
IN OUT UINTN *BufferSizePtr,
IN OUT UINT16 *ProtocolPtr
)
;
#endif /* _IP_H_ */
/* EOF - ip.h */

View File

@@ -0,0 +1,617 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
pxe_bc_arp.c
Abstract:
--*/
#include "bc.h"
//
// Definitions for ARP
// Per RFC 826
//
STATIC ARP_HEADER ArpHeader;
#pragma pack(1)
STATIC struct {
UINT8 MediaHeader[14];
ARP_HEADER ArpHeader;
UINT8 ArpData[64];
} ArpReplyPacket;
#pragma pack()
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
InitArpHeader (
VOID
)
/*++
Routine description:
Initialize ARP packet header.
Parameters:
none
Returns:
none
--*/
{
ArpHeader.HwType = HTONS (ETHERNET_ADD_SPC);
ArpHeader.ProtType = HTONS (ETHER_TYPE_IP);
ArpHeader.HwAddLen = ENET_HWADDLEN;
ArpHeader.ProtAddLen = IPV4_PROTADDLEN;
ArpHeader.OpCode = HTONS (ARP_REQUEST);
CopyMem (&ArpReplyPacket.ArpHeader, &ArpHeader, sizeof (ARP_HEADER));
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
HandleArpReceive (
IN PXE_BASECODE_DEVICE *Private,
IN ARP_PACKET *ArpPacketPtr,
IN VOID *MediaHeader
)
/*++
Routine description:
Process ARP packet.
Parameters:
Private := Pointer to PxeBc interface
ArpPacketPtr := Pointer to ARP packet
MediaHeader := Pointer to media header.
Returns:
--*/
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
EFI_SIMPLE_NETWORK_MODE *SnpMode;
EFI_MAC_ADDRESS TmpMacAddr;
UINTN Index;
UINT8 *SrcHwAddr;
UINT8 *SrcPrAddr;
UINT8 *DstHwAddr;
UINT8 *DstPrAddr;
UINT8 *TmpPtr;
//
//
//
PxeBcMode = Private->EfiBc.Mode;
SnpMode = Private->SimpleNetwork->Mode;
//
// For now only ethernet addresses are supported.
// This will need to be updated when other media
// layers are supported by PxeBc, Snp and UNDI.
//
if (ArpPacketPtr->ArpHeader.HwType != HTONS (ETHERNET_ADD_SPC)) {
return ;
}
//
// For now only IP protocol addresses are supported.
// This will need to be updated when other protocol
// types are supported by PxeBc, Snp and UNDI.
//
if (ArpPacketPtr->ArpHeader.ProtType != HTONS (ETHER_TYPE_IP)) {
return ;
}
//
// For now only SNP hardware address sizes are supported.
//
if (ArpPacketPtr->ArpHeader.HwAddLen != SnpMode->HwAddressSize) {
return ;
}
//
// For now only PxeBc protocol address sizes are supported.
//
if (ArpPacketPtr->ArpHeader.ProtAddLen != Private->IpLength) {
return ;
}
//
// Ignore out of range opcodes
//
switch (ArpPacketPtr->ArpHeader.OpCode) {
case HTONS (ARP_REPLY):
case HTONS (ARP_REQUEST):
break;
default:
return ;
}
//
// update entry in our ARP cache if we have it
//
SrcHwAddr = (UINT8 *) &ArpPacketPtr->SrcHardwareAddr;
SrcPrAddr = SrcHwAddr + SnpMode->HwAddressSize;
for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) {
if (CompareMem (
&PxeBcMode->ArpCache[Index].IpAddr,
SrcPrAddr,
Private->IpLength
)) {
continue;
}
CopyMem (
&PxeBcMode->ArpCache[Index].MacAddr,
SrcHwAddr,
SnpMode->HwAddressSize
);
break;
}
//
// Done if ARP packet was not for us.
//
DstHwAddr = SrcPrAddr + Private->IpLength;
DstPrAddr = DstHwAddr + SnpMode->HwAddressSize;
if (CompareMem (DstPrAddr, &PxeBcMode->StationIp, Private->IpLength)) {
return ;
//
// not for us
//
}
//
// for us - if we did not update entry, add it
//
if (Index == PxeBcMode->ArpCacheEntries) {
//
// if we have a full table, get rid of oldest
//
if (Index == PXE_ARP_CACHE_SIZE) {
Index = Private->OldestArpEntry;
if (++Private->OldestArpEntry == PXE_ARP_CACHE_SIZE) {
Private->OldestArpEntry = 0;
}
} else {
++PxeBcMode->ArpCacheEntries;
}
CopyMem (
&PxeBcMode->ArpCache[Index].MacAddr,
SrcHwAddr,
SnpMode->HwAddressSize
);
CopyMem (
&PxeBcMode->ArpCache[Index].IpAddr,
SrcPrAddr,
Private->IpLength
);
}
//
// if this is not a request or we don't yet have an IP, finished
//
if (ArpPacketPtr->ArpHeader.OpCode != HTONS (ARP_REQUEST) || !Private->GoodStationIp) {
return ;
}
//
// Assemble ARP reply.
//
//
// Create media header. [ dest mac | src mac | prot ]
//
CopyMem (
&ArpReplyPacket.MediaHeader[0],
SrcHwAddr,
SnpMode->HwAddressSize
);
CopyMem (
&ArpReplyPacket.MediaHeader[SnpMode->HwAddressSize],
&SnpMode->CurrentAddress,
SnpMode->HwAddressSize
);
CopyMem (
&ArpReplyPacket.MediaHeader[2 * SnpMode->HwAddressSize],
&((UINT8 *) MediaHeader)[2 * SnpMode->HwAddressSize],
sizeof (UINT16)
);
//
// ARP reply header is almost filled in,
// just insert the correct opcode.
//
ArpReplyPacket.ArpHeader.OpCode = HTONS (ARP_REPLY);
//
// Now fill in ARP data. [ src mac | src prot | dest mac | dest prot ]
//
TmpPtr = ArpReplyPacket.ArpData;
CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
TmpPtr += SnpMode->HwAddressSize;
CopyMem (TmpPtr, &PxeBcMode->StationIp, Private->IpLength);
TmpPtr += Private->IpLength;
CopyMem (TmpPtr, SrcHwAddr, SnpMode->HwAddressSize);
TmpPtr += SnpMode->HwAddressSize;
CopyMem (TmpPtr, SrcPrAddr, Private->IpLength);
//
// Now send out the ARP reply.
//
CopyMem (&TmpMacAddr, SrcHwAddr, sizeof (EFI_MAC_ADDRESS));
SendPacket (
Private,
&ArpReplyPacket.MediaHeader,
&ArpReplyPacket.ArpHeader,
sizeof (ARP_HEADER) + 2 * (Private->IpLength + SnpMode->HwAddressSize),
&TmpMacAddr,
PXE_PROTOCOL_ETHERNET_ARP,
EFI_PXE_BASE_CODE_FUNCTION_ARP
);
//
// Give time (100 microseconds) for ARP reply to get onto wire.
//
gBS->Stall (1000);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
BOOLEAN
GetHwAddr (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
OUT EFI_MAC_ADDRESS *HardwareAddrPtr
)
/*++
Routine description:
Locate IP address in ARP cache and return MAC address.
Parameters:
Private := Pointer to PxeBc interface
ProtocolAddrPtr := Pointer to IP address
HardwareAddrPtr := Pointer to MAC address storage
Returns:
TRUE := If IP address was found and MAC address was stored
FALSE := If IP address was not found
--*/
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
UINTN HardwareAddrLength;
UINTN Index;
PxeBcMode = Private->EfiBc.Mode;
HardwareAddrLength = Private->SimpleNetwork->Mode->HwAddressSize;
for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) {
if (!CompareMem (
ProtocolAddrPtr,
&PxeBcMode->ArpCache[Index].IpAddr,
Private->IpLength
)) {
CopyMem (
HardwareAddrPtr,
&PxeBcMode->ArpCache[Index].MacAddr,
HardwareAddrLength
);
return TRUE;
}
}
return FALSE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
EFI_STATUS
SendRequest (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
IN EFI_MAC_ADDRESS *HardwareAddrPtr
)
/*++
Routine description:
Transmit ARP request packet
Parameters:
Private := Pointer to PxeBc interface
ProtocolAddrPtr := Pointer IP address to find
HardwareAddrPtr := Pointer to MAC address to find
Returns:
EFI_SUCCESS := ARP request sent
other := ARP request could not be sent
--*/
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
EFI_SIMPLE_NETWORK_MODE *SnpMode;
ARP_PACKET *ArpPacket;
EFI_STATUS Status;
UINTN HardwareAddrLength;
UINT8 *SrcProtocolAddrPtr;
UINT8 *DestHardwareAddrptr;
UINT8 *DestProtocolAddrPtr;
//
//
//
PxeBcMode = Private->EfiBc.Mode;
SnpMode = Private->SimpleNetwork->Mode;
HardwareAddrLength = SnpMode->HwAddressSize;
//
// Allocate ARP buffer
//
if (Private->ArpBuffer == NULL) {
Status = gBS->AllocatePool (
EfiBootServicesData,
SnpMode->MediaHeaderSize + sizeof (ARP_PACKET),
(VOID **) &Private->ArpBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
}
ArpPacket = (VOID *) (Private->ArpBuffer + SnpMode->MediaHeaderSize);
//
// for now, only handle one kind of hw and pr address
//
ArpPacket->ArpHeader = ArpHeader;
ArpPacket->ArpHeader.HwAddLen = (UINT8) HardwareAddrLength;
ArpPacket->ArpHeader.ProtAddLen = (UINT8) Private->IpLength;
//
// rest more generic
//
SrcProtocolAddrPtr = (UINT8 *) (&ArpPacket->SrcHardwareAddr) + HardwareAddrLength;
DestHardwareAddrptr = SrcProtocolAddrPtr + Private->IpLength;
DestProtocolAddrPtr = DestHardwareAddrptr + HardwareAddrLength;
CopyMem (DestProtocolAddrPtr, ProtocolAddrPtr, Private->IpLength);
CopyMem (DestHardwareAddrptr, HardwareAddrPtr, HardwareAddrLength);
CopyMem (SrcProtocolAddrPtr, &PxeBcMode->StationIp, Private->IpLength);
CopyMem (
&ArpPacket->SrcHardwareAddr,
&SnpMode->CurrentAddress,
HardwareAddrLength
);
return SendPacket (
Private,
Private->ArpBuffer,
ArpPacket,
sizeof (ARP_HEADER) + ((Private->IpLength + HardwareAddrLength) << 1),
&SnpMode->BroadcastAddress,
PXE_PROTOCOL_ETHERNET_ARP,
EFI_PXE_BASE_CODE_FUNCTION_ARP
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// check for address - if not there, send ARP request, wait and check again
// not how it would be done in a full system
//
#define ARP_REQUEST_TIMEOUT_MS 500 // try for half a second
////////////////////////////////////////////////////////////
//
// BC Arp Routine
//
EFI_STATUS
EFIAPI
BcArp (
IN EFI_PXE_BASE_CODE_PROTOCOL * This,
IN EFI_IP_ADDRESS * ProtocolAddrPtr,
OUT EFI_MAC_ADDRESS * HardwareAddrPtr OPTIONAL
)
/*++
Routine description:
PxeBc ARP API.
Parameters:
This := Pointer to PxeBc interface
ProtocolAddrPtr := Pointer to IP address to find
HardwareAddrPtr := Pointer to MAC address found.
Returns:
--*/
{
EFI_MAC_ADDRESS Mac;
EFI_STATUS StatCode;
PXE_BASECODE_DEVICE *Private;
//
// Lock the instance data and make sure started
//
StatCode = EFI_SUCCESS;
if (This == NULL) {
DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
return EFI_INVALID_PARAMETER;
}
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
if (Private == NULL) {
DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
return EFI_INVALID_PARAMETER;
}
EfiAcquireLock (&Private->Lock);
if (This->Mode == NULL || !This->Mode->Started) {
DEBUG ((EFI_D_ERROR, "BC was not started."));
EfiReleaseLock (&Private->Lock);
return EFI_NOT_STARTED;
}
DEBUG ((EFI_D_INFO, "\nBcArp()"));
//
// Issue BC command
//
if (ProtocolAddrPtr == NULL) {
DEBUG (
(EFI_D_INFO,
"\nBcArp() Exit #1 %Xh (%r)",
EFI_INVALID_PARAMETER,
EFI_INVALID_PARAMETER)
);
EfiReleaseLock (&Private->Lock);
return EFI_INVALID_PARAMETER;
}
if (HardwareAddrPtr == NULL) {
HardwareAddrPtr = &Mac;
}
ZeroMem (HardwareAddrPtr, Private->SimpleNetwork->Mode->HwAddressSize);
if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {
DEBUG (
(EFI_D_INFO,
"\nBcArp() Exit #2 %Xh (%r)",
EFI_SUCCESS,
EFI_SUCCESS)
);
EfiReleaseLock (&Private->Lock);
return EFI_SUCCESS;
}
StatCode = DoArp (Private, ProtocolAddrPtr, HardwareAddrPtr);
DEBUG ((EFI_D_INFO, "\nBcArp() Exit #3 %Xh (%r)", StatCode, StatCode));
EfiReleaseLock (&Private->Lock);
return StatCode;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
DoArp (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
OUT EFI_MAC_ADDRESS *HardwareAddrPtr
)
/*++
Routine description:
Internal ARP implementation.
Parameters:
Private := Pointer to PxeBc interface
ProtocolAddrPtr := Pointer to IP address to find
HardwareAddrPtr := Pointer to MAC address found
Returns:
EFI_SUCCESS := MAC address found
other := MAC address could not be found
--*/
{
EFI_STATUS StatCode;
EFI_EVENT TimeoutEvent;
UINTN HeaderSize;
UINTN BufferSize;
UINT16 Protocol;
DEBUG ((EFI_D_INFO, "\nDoArp()"));
//
//
//
StatCode = SendRequest (Private, ProtocolAddrPtr, HardwareAddrPtr);
if (EFI_ERROR (StatCode)) {
DEBUG ((EFI_D_INFO, "\nDoArp() Exit #1 %Xh (%r)", StatCode, StatCode));
return StatCode;
}
//
//
//
StatCode = gBS->CreateEvent (
EFI_EVENT_TIMER,
EFI_TPL_CALLBACK,
NULL,
NULL,
&TimeoutEvent
);
if (EFI_ERROR (StatCode)) {
return StatCode;
}
StatCode = gBS->SetTimer (
TimeoutEvent,
TimerRelative,
ARP_REQUEST_TIMEOUT_MS * 10000
);
if (EFI_ERROR (StatCode)) {
gBS->CloseEvent (TimeoutEvent);
return StatCode;
}
//
//
//
for (;;) {
StatCode = WaitForReceive (
Private,
EFI_PXE_BASE_CODE_FUNCTION_ARP,
TimeoutEvent,
&HeaderSize,
&BufferSize,
&Protocol
);
if (EFI_ERROR (StatCode)) {
break;
}
if (Protocol != PXE_PROTOCOL_ETHERNET_ARP) {
continue;
}
HandleArpReceive (
Private,
(ARP_PACKET *) (Private->ReceiveBufferPtr + HeaderSize),
Private->ReceiveBufferPtr
);
if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {
break;
}
}
DEBUG (
(EFI_D_INFO,
"\nDoArp() Exit #2 %Xh, (%r)",
StatCode,
StatCode)
);
gBS->CloseEvent (TimeoutEvent);
return StatCode;
}
/* eof - pxe_bc_arp.c */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,476 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
--*/
#define RAND_MAX 0x10000
#include "bc.h"
//
// Definitions for internet group management protocol version 2 message
// structure Per RFC 2236, November 1997
//
STATIC UINT8 RouterAlertOption[4] = { 0x80 | 20, 4, 0, 0 };
STATIC IPV4_ADDR AllRoutersGroup = { { 224, 0, 0, 2 } };
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
ClearGroupTimer (
PXE_BASECODE_DEVICE *Private,
UINTN TimerId
)
{
if (Private == NULL) {
return ;
}
if (TimerId >= Private->MCastGroupCount) {
return ;
}
if (Private->IgmpGroupEvent[TimerId] == NULL) {
return ;
}
gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]);
Private->IgmpGroupEvent[TimerId] = NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
SetGroupTimer (
PXE_BASECODE_DEVICE *Private,
UINTN TimerId,
UINTN MaxRespTime
)
/*++
Routine description:
Set IGMP response timeout value.
Parameters:
Private := Pointer to PxeBc interface
TimerId := Timer ID#
MaxRespTime := Base response timeout value in tenths of seconds
Returns:
--*/
{
EFI_STATUS EfiStatus;
if (Private == NULL) {
return ;
}
if (TimerId >= Private->MCastGroupCount) {
return ;
}
if (Private->IgmpGroupEvent[TimerId] != NULL) {
gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]);
}
EfiStatus = gBS->CreateEvent (
EFI_EVENT_TIMER,
EFI_TPL_CALLBACK,
NULL,
NULL,
&Private->IgmpGroupEvent[TimerId]
);
if (EFI_ERROR (EfiStatus)) {
Private->IgmpGroupEvent[TimerId] = NULL;
return ;
}
EfiStatus = gBS->SetTimer (
Private->IgmpGroupEvent[TimerId],
TimerRelative,
MaxRespTime * 1000000 + Random (Private) % RAND_MAX
);
if (EFI_ERROR (EfiStatus)) {
gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]);
Private->IgmpGroupEvent[TimerId] = NULL;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
SendIgmpMessage (
PXE_BASECODE_DEVICE *Private,
UINT8 Type,
INTN GroupId
)
/*++
Routine description:
Send an IGMP message
Parameters:
Private := Pointer to PxeBc interface
Type := Message type opcode
GroupId := Group ID#
Returns:
--*/
{
Private->IgmpMessage.Type = Type;
Private->IgmpMessage.MaxRespTime = 0;
Private->IgmpMessage.Checksum = 0;
Private->IgmpMessage.GroupAddress = Private->MCastGroup[GroupId];
Private->IgmpMessage.Checksum = IpChecksum (
(UINT16 *) &Private->IgmpMessage,
sizeof Private->IgmpMessage
);
Ipv4SendWOp (
Private,
0,
(UINT8 *) &Private->IgmpMessage,
sizeof Private->IgmpMessage,
PROT_IGMP,
RouterAlertOption,
sizeof RouterAlertOption,
((Type == IGMP_TYPE_LEAVE_GROUP) ? AllRoutersGroup.L : Private->IgmpMessage.GroupAddress),
EFI_PXE_BASE_CODE_FUNCTION_IGMP
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
ReportIgmp (
PXE_BASECODE_DEVICE *Private,
INTN GroupId
)
/*++
Routine description:
Send an IGMP report message.
Parameters:
Private := Pointer to PxeBc interface
GroupId := Group ID#
Returns:
--*/
{
//
// if version 1 querier, send v1 report
//
UINT8 Type;
if (Private->Igmpv1TimeoutEvent != NULL) {
if (!EFI_ERROR (gBS->CheckEvent (Private->Igmpv1TimeoutEvent))) {
gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
Private->Igmpv1TimeoutEvent = NULL;
Private->UseIgmpv1Reporting = TRUE;
}
}
Type = (UINT8) (Private->UseIgmpv1Reporting ? IGMP_TYPE_V1REPORT : IGMP_TYPE_REPORT);
SendIgmpMessage (Private, Type, GroupId);
ClearGroupTimer (Private, GroupId);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
IgmpCheckTimers (
PXE_BASECODE_DEVICE *Private
)
/*++
Routine description:
Check IGMP timers and send reports for all groups that have expired.
Parameters:
Private := Pointer to PxeBc interface
Returns:
--*/
{
UINTN GroupId;
if (Private == NULL) {
return ;
}
for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) {
if (Private->IgmpGroupEvent[GroupId] == NULL) {
continue;
}
if (!EFI_ERROR (gBS->CheckEvent (Private->IgmpGroupEvent[GroupId]))) {
//
// send a report
//
ReportIgmp (Private, GroupId);
}
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
INTN
FindMulticastGroup (
PXE_BASECODE_DEVICE *Private,
UINT32 GroupAddress
)
/*++
Routine description:
Fund group ID# (index).
Parameters:
Private := Pointer to PxeBc interface
GroupAddress := Group multicast address
Returns:
0 := Group not found
other := Group ID#
--*/
{
UINTN GroupId;
for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) {
if (Private->MCastGroup[GroupId] == GroupAddress) {
return GroupId + 1;
}
}
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
IgmpJoinGroup (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *GroupPtr
)
/*++
Routine description:
Join multicast group.
Parameters:
Private := Pointer to PxeBc interface
GroupPtr := Pointer to group mutlicast IP address.
Returns:
--*/
{
UINT32 Grp;
Grp = *(UINT32 *) GroupPtr;
#if SUPPORT_IPV6
if (Private->EfiBc.Mode->UsingIpv6) {
//
// TBD
//
}
#endif
//
// see if we already have it or if we can't take anymore
//
if (FindMulticastGroup (Private, Grp) || Private->MCastGroupCount == MAX_MCAST_GROUPS) {
return ;
}
//
// add the group
//
Private->MCastGroup[Private->MCastGroupCount] = Grp;
ReportIgmp (Private, Private->MCastGroupCount);
//
// send a report
// so it will get sent again per RFC 2236
//
SetGroupTimer (
Private,
Private->MCastGroupCount++,
UNSOLICITED_REPORT_INTERVAL * 10
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
IgmpLeaveGroup (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *GroupPtr
)
/*++
Routine description:
Leave multicast group.
Parameters:
Private := Pointer to PxeBc interface
GroupPtr := Mutlicast group IP address.
Returns:
--*/
{
UINT32 Grp;
UINTN GroupId;
Grp = *(UINT32 *) GroupPtr;
#if SUPPORT_IPV6
if (Private->EfiBc.Mode->UsingIpv6) {
//
// TBD
//
}
#endif
//
// if not in group, ignore
//
GroupId = FindMulticastGroup (Private, Grp);
if (GroupId == 0) {
return ;
}
//
// if not v1 querrier, send leave group IGMP message
//
if (Private->Igmpv1TimeoutEvent != NULL) {
if (!EFI_ERROR (gBS->CheckEvent (Private->Igmpv1TimeoutEvent))) {
gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
Private->Igmpv1TimeoutEvent = NULL;
Private->UseIgmpv1Reporting = TRUE;
} else {
SendIgmpMessage (Private, IGMP_TYPE_LEAVE_GROUP, GroupId - 1);
}
}
while (GroupId < Private->MCastGroupCount) {
Private->MCastGroup[GroupId - 1] = Private->MCastGroup[GroupId];
Private->IgmpGroupEvent[GroupId - 1] = Private->IgmpGroupEvent[GroupId];
++GroupId;
}
--Private->MCastGroupCount;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
HandleIgmp (
PXE_BASECODE_DEVICE *Private,
IGMPV2_MESSAGE *IgmpMessagePtr,
UINTN IgmpLength
)
/*++
Routine description:
Handle received IGMP packet
Parameters:
Private := Pointer to PxeBc interface
IgmpMessagePtr := Pointer to IGMP packet
IgmpLength := packet length in bytes
Returns:
--*/
{
EFI_STATUS EfiStatus;
UINTN GroupId;
INTN MaxRespTime;
if (Private == NULL) {
return ;
}
if (Private->MCastGroupCount == 0) {
//
// if we don't belong to any multicast groups, ignore
//
return ;
}
//
// verify checksum
//
if (IpChecksum ((UINT16 *) IgmpMessagePtr, IgmpLength)) {
//
// bad checksum - ignore packet
//
return ;
}
switch (IgmpMessagePtr->Type) {
case IGMP_TYPE_QUERY:
//
// if a version 1 querier, note the fact and set max resp time
//
MaxRespTime = IgmpMessagePtr->MaxRespTime;
if (MaxRespTime == 0) {
Private->UseIgmpv1Reporting = TRUE;
if (Private->Igmpv1TimeoutEvent != NULL) {
gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
}
EfiStatus = gBS->CreateEvent (
EFI_EVENT_TIMER,
EFI_TPL_CALLBACK,
NULL,
NULL,
&Private->Igmpv1TimeoutEvent
);
if (EFI_ERROR (EfiStatus)) {
Private->Igmpv1TimeoutEvent = NULL;
} else {
EfiStatus = gBS->SetTimer (
Private->Igmpv1TimeoutEvent,
TimerRelative,
(UINT64) V1ROUTER_PRESENT_TIMEOUT * 10000000
);
}
MaxRespTime = IGMP_DEFAULT_MAX_RESPONSE_TIME * 10;
}
//
// if a general query (!GroupAddress), set all our group timers
//
if (!IgmpMessagePtr->GroupAddress) {
for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) {
SetGroupTimer (Private, GroupId, MaxRespTime);
}
} else {
//
// specific query - set only specific group
//
GroupId = FindMulticastGroup (Private, IgmpMessagePtr->GroupAddress);
if (GroupId != 0) {
SetGroupTimer (Private, GroupId - 1, MaxRespTime);
}
}
break;
//
// if we have a timer running for this group, clear it
//
case IGMP_TYPE_V1REPORT:
case IGMP_TYPE_REPORT:
GroupId = FindMulticastGroup (Private, IgmpMessagePtr->GroupAddress);
if (GroupId != 0) {
ClearGroupTimer (Private, GroupId - 1);
}
break;
}
}
/* EOF - pxe_bc_igmp.c */

View File

@@ -0,0 +1,861 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
pxe_bc_ip.c
Abstract:
--*/
#include "bc.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
BOOLEAN
OnSameSubnet (
IN UINTN IpLength,
IN EFI_IP_ADDRESS *Ip1,
IN EFI_IP_ADDRESS *Ip2,
IN EFI_IP_ADDRESS *SubnetMask
)
/*++
Routine Description:
Check if two IP addresses are on the same subnet.
Arguments:
IpLength - Length of IP address in bytes.
Ip1 - IP address to check.
Ip2 - IP address to check.
SubnetMask - Subnet mask to check with.
Returns:
TRUE - IP addresses are on the same subnet.
FALSE - IP addresses are on different subnets.
--*/
{
if (IpLength == 0 || Ip1 == NULL || Ip2 == NULL || SubnetMask == NULL) {
return FALSE;
}
while (IpLength-- != 0) {
if ((Ip1->v6.Addr[IpLength] ^ Ip2->v6.Addr[IpLength]) & SubnetMask->v6.Addr[IpLength]) {
return FALSE;
}
}
return TRUE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
IpAddRouter (
IN PXE_BASECODE_DEVICE *Private,
IN EFI_IP_ADDRESS *RouterIpPtr
)
/*++
Routine Description:
Add router to router table.
Arguments:
Private - Pointer PxeBc instance data.
RouterIpPtr - Pointer to router IP address.
Returns:
Nothing
--*/
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
UINTN Index;
if (Private == NULL || RouterIpPtr == NULL) {
return ;
}
PxeBcMode = Private->EfiBc.Mode;
//
// if we are filled up or this is not on the same subnet, forget it
//
if ((PxeBcMode->RouteTableEntries == PXE_ROUTER_TABLE_SIZE) ||
!OnSameSubnet(Private->IpLength, &PxeBcMode->StationIp, RouterIpPtr, &PxeBcMode->SubnetMask)) {
return ;
}
//
// make sure we don't already have it
//
for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
if (!CompareMem (
&PxeBcMode->RouteTable[Index].GwAddr,
RouterIpPtr,
Private->IpLength
)) {
return ;
}
}
//
// keep it
//
ZeroMem (
&PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries],
sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY)
);
CopyMem (
&PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries++].GwAddr,
RouterIpPtr,
Private->IpLength
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// return router ip to use for DestIp (0 if none)
//
STATIC
EFI_IP_ADDRESS *
GetRouterIp (
PXE_BASECODE_DEVICE *Private,
EFI_IP_ADDRESS *DestIpPtr
)
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
UINTN Index;
if (Private == NULL || DestIpPtr == NULL) {
return NULL;
}
PxeBcMode = Private->EfiBc.Mode;
for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
if (OnSameSubnet (
Private->IpLength,
&PxeBcMode->RouteTable[Index].IpAddr,
DestIpPtr,
&PxeBcMode->RouteTable[Index].SubnetMask
)) {
return &PxeBcMode->RouteTable[Index].GwAddr;
}
}
return NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// routine to send ipv4 packet
// ipv4 header of length HdrLth in TransmitBufferPtr
// routine fills in ipv4hdr Ver_Hdl, TotalLength, and Checksum, moves in Data
// and gets dest MAC address
//
#define IP_TX_BUFFER ((IPV4_BUFFER *) Private->TransmitBufferPtr)
#define IP_TX_HEADER IP_TX_BUFFER->IpHeader
EFI_STATUS
Ipv4Xmt (
PXE_BASECODE_DEVICE *Private,
UINT32 GatewayIp,
UINTN IpHeaderLength,
UINTN TotalHeaderLength,
VOID *Data,
UINTN DataLength,
EFI_PXE_BASE_CODE_FUNCTION Function
)
{
EFI_MAC_ADDRESS DestMac;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
EFI_STATUS StatCode;
UINTN PacketLength;
Snp = Private->SimpleNetwork;
PxeBcMode = Private->EfiBc.Mode;
StatCode = EFI_SUCCESS;
PacketLength = TotalHeaderLength + DataLength;
//
// get dest MAC address
// multicast - convert to hw equiv
// unicast on same net, use arp
// on different net, arp for router
//
if (IP_TX_HEADER.DestAddr.L == BROADCAST_IPv4) {
CopyMem (&DestMac, &Snp->Mode->BroadcastAddress, sizeof (DestMac));
} else if (IS_MULTICAST (&IP_TX_HEADER.DestAddr)) {
StatCode = (*Snp->MCastIpToMac) (Snp, PxeBcMode->UsingIpv6, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr, &DestMac);
} else {
UINT32 Ip;
if (OnSameSubnet (
Private->IpLength,
&PxeBcMode->StationIp,
(EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr,
&PxeBcMode->SubnetMask
)) {
Ip = IP_TX_HEADER.DestAddr.L;
} else if (GatewayIp != 0) {
Ip = GatewayIp;
} else {
EFI_IP_ADDRESS *TmpIp;
TmpIp = GetRouterIp (Private, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr);
if (TmpIp == NULL) {
DEBUG (
(EFI_D_WARN,
"\nIpv4Xmit() Exit #1 %xh (%r)",
EFI_NO_RESPONSE,
EFI_NO_RESPONSE)
);
return EFI_NO_RESPONSE;
//
// no router
//
}
Ip = TmpIp->Addr[0];
}
if (!GetHwAddr (
Private,
(EFI_IP_ADDRESS *) &Ip,
(EFI_MAC_ADDRESS *) &DestMac
)) {
if (!PxeBcMode->AutoArp) {
DEBUG (
(EFI_D_WARN,
"\nIpv4Xmit() Exit #2 %xh (%r)",
EFI_DEVICE_ERROR,
EFI_DEVICE_ERROR)
);
return EFI_DEVICE_ERROR;
} else {
StatCode = DoArp (
Private,
(EFI_IP_ADDRESS *) &Ip,
(EFI_MAC_ADDRESS *) &DestMac
);
}
}
}
if (EFI_ERROR (StatCode)) {
DEBUG ((EFI_D_WARN, "\nIpv4Xmit() Exit #3 %xh (%r)", StatCode, StatCode));
return StatCode;
}
//
// fill in packet info
//
SET_IPV4_VER_HDL (&IP_TX_HEADER, IpHeaderLength);
IP_TX_HEADER.TotalLength = HTONS (PacketLength);
IP_TX_HEADER.HeaderChecksum = IpChecksum ((UINT16 *) &IP_TX_HEADER, IpHeaderLength);
CopyMem (((UINT8 *) &IP_TX_HEADER) + TotalHeaderLength, Data, DataLength);
//
// send it
//
return SendPacket (
Private,
(UINT8 *) &IP_TX_HEADER - Snp->Mode->MediaHeaderSize,
&IP_TX_HEADER,
PacketLength,
&DestMac,
PXE_PROTOCOL_ETHERNET_IP,
Function
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// send ipv4 packet with option
//
EFI_STATUS
Ipv4SendWOp (
PXE_BASECODE_DEVICE *Private,
UINT32 GatewayIp,
UINT8 *Msg,
UINTN MessageLength,
UINT8 Prot,
UINT8 *Option,
UINTN OptionLength,
UINT32 DestIp,
EFI_PXE_BASE_CODE_FUNCTION Function
)
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
UINTN HdrLth;
PxeBcMode = Private->EfiBc.Mode;
HdrLth = sizeof (IPV4_HEADER) + OptionLength;
ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
IP_TX_HEADER.TimeToLive = PxeBcMode->TTL;
IP_TX_HEADER.TypeOfService = PxeBcMode->ToS;
IP_TX_HEADER.Protocol = Prot;
IP_TX_HEADER.SrcAddr.L = *(UINT32 *) &PxeBcMode->StationIp;
IP_TX_HEADER.DestAddr.L = DestIp;
IP_TX_HEADER.Id = Random (Private);
CopyMem (IP_TX_BUFFER->u.Data, Option, OptionLength);
return Ipv4Xmt (
Private,
GatewayIp,
HdrLth,
HdrLth,
Msg,
MessageLength,
Function
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// send MessageLength message at MessagePtr - higher level protocol header already in TransmitBufferPtr, length HdrSize
//
EFI_STATUS
Ip4Send (
PXE_BASECODE_DEVICE *Private, // pointer to instance data
UINTN MayFrag, //
UINT8 Prot, // protocol
UINT32 SrcIp, // Source IP address
UINT32 DestIp, // Destination IP address
UINT32 GatewayIp, // used if not NULL and needed
UINTN HdrSize, // protocol header byte length
UINT8 *MessagePtr, // pointer to data
UINTN MessageLength // data byte length
)
{
EFI_STATUS StatCode;
UINTN TotDataLength;
TotDataLength = HdrSize + MessageLength;
if (TotDataLength > MAX_IPV4_DATA_SIZE) {
DEBUG (
(EFI_D_WARN,
"\nIp4Send() Exit #1 %xh (%r)",
EFI_BAD_BUFFER_SIZE,
EFI_BAD_BUFFER_SIZE)
);
return EFI_BAD_BUFFER_SIZE;
}
ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
IP_TX_HEADER.TimeToLive = DEFAULT_TTL;
IP_TX_HEADER.Protocol = Prot;
IP_TX_HEADER.SrcAddr.L = SrcIp;
IP_TX_HEADER.DestAddr.L = DestIp;
IP_TX_HEADER.Id = Random (Private);
if (!MayFrag) {
*(UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_NO_FRAG >> 8;
}
//
// check for need to fragment
//
if (TotDataLength > MAX_IPV4_FRAME_DATA_SIZE) {
UINTN DataLengthSent;
UINT16 FragmentOffset;
FragmentOffset = IP_MORE_FRAG;
//
// frag offset field
//
if (!MayFrag) {
DEBUG (
(EFI_D_WARN,
"\nIp4Send() Exit #2 %xh (%r)",
EFI_BAD_BUFFER_SIZE,
EFI_BAD_BUFFER_SIZE)
);
return EFI_BAD_BUFFER_SIZE;
}
//
// send out in fragments - first includes upper level header
// all are max and include more frag bit except last
//
* (UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_MORE_FRAG >> 8;
#define IPV4_FRAG_SIZE (MAX_IPV4_FRAME_DATA_SIZE & 0xfff8)
#define IPV4_FRAG_OFF_INC (IPV4_FRAG_SIZE >> 3)
DataLengthSent = IPV4_FRAG_SIZE - HdrSize;
StatCode = Ipv4Xmt (
Private,
GatewayIp,
sizeof (IPV4_HEADER),
sizeof (IPV4_HEADER) + HdrSize,
MessagePtr,
DataLengthSent,
Private->Function
);
if (EFI_ERROR (StatCode)) {
DEBUG (
(EFI_D_WARN,
"\nIp4Send() Exit #3 %xh (%r)",
StatCode,
StatCode)
);
return StatCode;
}
MessagePtr += DataLengthSent;
MessageLength -= DataLengthSent;
FragmentOffset += IPV4_FRAG_OFF_INC;
IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
while (MessageLength > IPV4_FRAG_SIZE) {
StatCode = Ipv4Xmt (
Private,
GatewayIp,
sizeof (IPV4_HEADER),
sizeof (IPV4_HEADER),
MessagePtr,
IPV4_FRAG_SIZE,
Private->Function
);
if (EFI_ERROR (StatCode)) {
DEBUG (
(EFI_D_WARN,
"\nIp4Send() Exit #3 %xh (%r)",
StatCode,
StatCode)
);
return StatCode;
}
MessagePtr += IPV4_FRAG_SIZE;
MessageLength -= IPV4_FRAG_SIZE;
FragmentOffset += IPV4_FRAG_OFF_INC;
IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
}
* (UINT8 *) (&IP_TX_HEADER.FragmentFields) &= ~(IP_MORE_FRAG >> 8);
HdrSize = 0;
}
//
// transmit
//
return Ipv4Xmt (
Private,
GatewayIp,
sizeof (IPV4_HEADER),
sizeof (IPV4_HEADER) + HdrSize,
MessagePtr,
MessageLength,
Private->Function
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// return true if dst IP in receive header matched with what's enabled
//
STATIC
BOOLEAN
IPgood (
PXE_BASECODE_DEVICE *Private,
IPV4_HEADER *IpHeader
)
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
UINTN Index;
PxeBcMode = Private->EfiBc.Mode;
if (PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
return TRUE;
}
if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) &&
IS_MULTICAST (&IpHeader->DestAddr)
) {
return TRUE;
}
if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) &&
PxeBcMode->StationIp.Addr[0] == IpHeader->DestAddr.L
) {
return TRUE;
}
if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) && IpHeader->DestAddr.L == BROADCAST_IPv4) {
return TRUE;
}
for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; ++Index) {
if (IpHeader->DestAddr.L == PxeBcMode->IpFilter.IpList[Index].Addr[0]) {
return TRUE;
}
}
return FALSE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// receive up to MessageLength message into MessagePtr for protocol Prot
// return message length, src/dest ips if select any, and pointer to protocol
// header routine will filter based on source and/or dest ip if OpFlags set.
//
EFI_STATUS
IpReceive (
PXE_BASECODE_DEVICE *Private,
PXE_OPFLAGS OpFlags,
EFI_IP_ADDRESS *SrcIpPtr,
EFI_IP_ADDRESS *DestIpPtr,
UINT8 Prot,
VOID *HeaderPtr,
UINTN HdrSize,
UINT8 *MessagePtr,
UINTN *MessageLengthPtr,
EFI_EVENT TimeoutEvent
)
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
EFI_STATUS StatCode;
UINTN ByteCount;
UINTN FragmentCount;
UINTN ExpectedPacketLength;
UINTN Id;
BOOLEAN GotFirstFragment;
BOOLEAN GotLastFragment;
DEBUG (
(EFI_D_NET,
"\nIpReceive() Hdr=%Xh HdrSz=%d Data=%Xh DataSz=%d",
HeaderPtr,
HdrSize,
MessagePtr,
*MessageLengthPtr)
);
PxeBcMode = Private->EfiBc.Mode;
PxeBcMode->IcmpErrorReceived = FALSE;
ExpectedPacketLength = 0;
GotFirstFragment = FALSE;
GotLastFragment = FALSE;
FragmentCount = 0;
ByteCount = 0;
Id = 0;
for (;;) {
IPV4_HEADER IpHdr;
UINTN FFlds;
UINTN TotalLength;
UINTN FragmentOffset;
UINTN HeaderSize;
UINTN BufferSize;
UINTN IpHeaderLength;
UINTN DataLength;
UINT16 Protocol;
UINT8 *NextHdrPtr;
UINT8 *PacketPtr;
StatCode = WaitForReceive (
Private,
Private->Function,
TimeoutEvent,
&HeaderSize,
&BufferSize,
&Protocol
);
if (EFI_ERROR (StatCode)) {
return StatCode;
}
PacketPtr = Private->ReceiveBufferPtr + HeaderSize;
if (Protocol == PXE_PROTOCOL_ETHERNET_ARP) {
HandleArpReceive (
Private,
(ARP_PACKET *) PacketPtr,
Private->ReceiveBufferPtr
);
continue;
}
if (Protocol != PXE_PROTOCOL_ETHERNET_IP) {
continue;
}
#if SUPPORT_IPV6
if (PxeBcMode->UsingIpv6) {
//
// TBD
//
}
#endif
#define IpRxHeader ((IPV4_HEADER *) PacketPtr)
//
// filter for version & check sum
//
IpHeaderLength = IPV4_HEADER_LENGTH (IpRxHeader);
if ((IpRxHeader->VersionIhl >> 4) != IPVER4) {
continue;
}
if (IpChecksum ((UINT16 *) IpRxHeader, IpHeaderLength)) {
continue;
}
CopyMem (&IpHdr, IpRxHeader, sizeof (IpHdr));
//IpHdr = *IpRxHeader;
TotalLength = NTOHS (IpHdr.TotalLength);
if (IpHdr.Protocol == PROT_TCP) {
//
// The NextHdrPtr is used to seed the header buffer we are passing back.
// That being the case, we want to see everything in pPkt which contains
// everything but the ethernet (or whatever) frame. IP + TCP in this case.
//
DataLength = TotalLength;
NextHdrPtr = PacketPtr;
} else {
DataLength = TotalLength - IpHeaderLength;
NextHdrPtr = PacketPtr + IpHeaderLength;
}
//
// If this is an ICMP, it might not be for us.
// Double check the state of the IP stack and the
// packet fields before assuming it is an ICMP
// error. ICMP requests are not supported by the
// PxeBc IP stack and should be ignored.
//
if (IpHdr.Protocol == PROT_ICMP) {
ICMPV4_HEADER *Icmpv4;
Icmpv4 = (ICMPV4_HEADER *) NextHdrPtr;
//
// For now only obvious ICMP error replies will be accepted by
// this stack. This still makes us vulnerable to DoS attacks.
// But at least we will not be killed by DHCP daemons.
//
switch (Icmpv4->Type) {
case ICMP_REDIRECT:
case ICMP_ECHO:
case ICMP_ROUTER_ADV:
case ICMP_ROUTER_SOLICIT:
case ICMP_TIMESTAMP:
case ICMP_TIMESTAMP_REPLY:
case ICMP_INFO_REQ:
case ICMP_INFO_REQ_REPLY:
case ICMP_SUBNET_MASK_REQ:
case ICMP_SUBNET_MASK_REPLY:
default:
continue;
//
// %%TBD - This should be implemented.
//
case ICMP_ECHO_REPLY:
continue;
case ICMP_DEST_UNREACHABLE:
case ICMP_TIME_EXCEEDED:
case ICMP_PARAMETER_PROBLEM:
case ICMP_SOURCE_QUENCH:
PxeBcMode->IcmpErrorReceived = TRUE;
CopyMem (
&PxeBcMode->IcmpError,
NextHdrPtr,
sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
);
DEBUG (
(EFI_D_NET,
"\nIpReceive() Exit #1 %Xh (%r)",
EFI_ICMP_ERROR,
EFI_ICMP_ERROR)
);
}
return EFI_ICMP_ERROR;
}
if (IpHdr.Protocol == PROT_IGMP) {
HandleIgmp (Private, (IGMPV2_MESSAGE *) NextHdrPtr, DataLength);
DEBUG ((EFI_D_NET, "\n IGMP"));
continue;
}
//
// check for protocol
//
if (IpHdr.Protocol != Prot) {
continue;
}
//
// do filtering
//
if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr && SrcIpPtr->Addr[0] != IpHdr.SrcAddr.L) {
DEBUG ((EFI_D_NET, "\n Not expected source IP address."));
continue;
}
if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) {
if (!IPgood (Private, &IpHdr)) {
continue;
}
} else if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP)) {
if (DestIpPtr == NULL) {
if (PxeBcMode->StationIp.Addr[0] != IpHdr.DestAddr.L) {
continue;
}
} else if (DestIpPtr->Addr[0] != IpHdr.DestAddr.L) {
continue;
}
}
//
// get some data we need
//
FFlds = NTOHS (IpHdr.FragmentFields);
FragmentOffset = ((FFlds & IP_FRAG_OFF_MSK) << 3);
/* Keep count of fragments that belong to this session.
* If we get packets with a different IP ID number,
* ignore them. Ignored packets should be handled
* by the upper level protocol.
*/
if (FragmentCount == 0) {
Id = IpHdr.Id;
if (DestIpPtr != NULL) {
DestIpPtr->Addr[0] = IpHdr.DestAddr.L;
}
if (SrcIpPtr != NULL) {
SrcIpPtr->Addr[0] = IpHdr.SrcAddr.L;
}
} else {
if (IpHdr.Id != Id) {
continue;
}
}
++FragmentCount;
/* Fragment management.
*/
if (FragmentOffset == 0) {
/* This is the first fragment (may also be the
* only fragment).
*/
GotFirstFragment = TRUE;
/* If there is a separate protocol header buffer,
* copy the header, adjust the data pointer and
* the data length.
*/
if (HdrSize != 0) {
CopyMem (HeaderPtr, NextHdrPtr, HdrSize);
NextHdrPtr += HdrSize;
DataLength -= HdrSize;
}
} else {
/* If there is a separate protocol header buffer,
* adjust the fragment offset.
*/
FragmentOffset -= HdrSize;
}
/* See if this is the last fragment.
*/
if (!(FFlds & IP_MORE_FRAG)) {
//
// This is the last fragment (may also be the only fragment).
//
GotLastFragment = TRUE;
/* Compute the expected length of the assembled
* packet. This will be used to decide if we
* have gotten all of the fragments.
*/
ExpectedPacketLength = FragmentOffset + DataLength;
}
DEBUG (
(EFI_D_NET,
"\n ID = %Xh Off = %d Len = %d",
Id,
FragmentOffset,
DataLength)
);
/* Check for receive buffer overflow.
*/
if (FragmentOffset + DataLength > *MessageLengthPtr) {
/* There is not enough space in the receive
* buffer for the fragment.
*/
DEBUG (
(EFI_D_NET,
"\nIpReceive() Exit #3 %Xh (%r)",
EFI_BUFFER_TOO_SMALL,
EFI_BUFFER_TOO_SMALL)
);
return EFI_BUFFER_TOO_SMALL;
}
/* Copy data into receive buffer.
*/
if (DataLength != 0) {
DEBUG ((EFI_D_NET, " To = %Xh", MessagePtr + FragmentOffset));
CopyMem (MessagePtr + FragmentOffset, NextHdrPtr, DataLength);
ByteCount += DataLength;
}
/* If we have seen the first and last fragments and
* the receive byte count is at least as large as the
* expected byte count, return SUCCESS.
*
* We could be tricked by receiving a fragment twice
* but the upper level protocol should figure this
* out.
*/
if (GotFirstFragment && GotLastFragment && ByteCount >= ExpectedPacketLength) {
*MessageLengthPtr = ExpectedPacketLength;
return EFI_SUCCESS;
}
}
}
/* eof - pxe_bc_ip.c */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,577 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
pxe_bc_udp.c
Abstract:
--*/
#include "bc.h"
//
// //////////////////////////////////////////////////////////////////////
//
// Udp Write Routine - called by base code - e.g. TFTP - already locked
//
EFI_STATUS
UdpWrite (
IN PXE_BASECODE_DEVICE *Private,
IN UINT16 OpFlags,
IN EFI_IP_ADDRESS *DestIpPtr,
IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,
IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL
IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL
IN UINTN *HeaderSizePtr, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN UINTN *BufferSizeptr,
IN VOID *BufferPtr
)
/*++
Routine description:
UDP write packet.
Parameters:
Private := Pointer to PxeBc interface
OpFlags :=
DestIpPtr :=
DestPortPtr :=
GatewayIpPtr :=
SrcIpPtr :=
SrcPortPtr :=
HeaderSizePtr :=
HeaderPtr :=
BufferSizeptr :=
BufferPtr :=
Returns:
EFI_SUCCESS :=
EFI_INVALID_PARAMETER :=
other :=
--*/
{
UINTN TotalLength;
UINTN HeaderSize;
EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort;
//
//
//
HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;
DefaultSrcPort = 0;
//
// check parameters
//
if (BufferSizeptr == NULL ||
BufferPtr == NULL ||
DestIpPtr == NULL ||
DestPortPtr == NULL ||
(HeaderSizePtr != NULL && *HeaderSizePtr == 0) ||
(HeaderSize != 0 && HeaderPtr == NULL) ||
(GatewayIpPtr != NULL && !IS_INADDR_UNICAST(GatewayIpPtr)) ||
(OpFlags &~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT))
) {
DEBUG (
(EFI_D_WARN,
"\nUdpWrite() Exit #1 %xh (%r)",
EFI_INVALID_PARAMETER,
EFI_INVALID_PARAMETER)
);
return EFI_INVALID_PARAMETER;
}
TotalLength = *BufferSizeptr + HeaderSize + sizeof (UDPV4_HEADER);
if (TotalLength > 0x0000ffff) {
DEBUG (
(EFI_D_WARN,
"\nUdpWrite() Exit #2 %xh (%r)",
EFI_BAD_BUFFER_SIZE,
EFI_BAD_BUFFER_SIZE)
);
return EFI_BAD_BUFFER_SIZE;
}
if (SrcIpPtr == NULL) {
SrcIpPtr = &Private->EfiBc.Mode->StationIp;
}
if (SrcPortPtr == NULL) {
SrcPortPtr = &DefaultSrcPort;
OpFlags |= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT;
}
if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) {
*SrcPortPtr = Private->RandomPort;
if (++Private->RandomPort == 0) {
Private->RandomPort = PXE_RND_PORT_LOW;
}
}
#define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr)
//
// build pseudo header and udp header in transmit buffer
//
#define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER)))
Udpv4Base->Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];
Udpv4Base->Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];
Udpv4Base->Udpv4PseudoHeader.Zero = 0;
Udpv4Base->Udpv4PseudoHeader.Protocol = PROT_UDP;
Udpv4Base->Udpv4PseudoHeader.TotalLength = HTONS (TotalLength);
Udpv4Base->Udpv4Header.SrcPort = HTONS (*SrcPortPtr);
Udpv4Base->Udpv4Header.DestPort = HTONS (*DestPortPtr);
Udpv4Base->Udpv4Header.TotalLength = Udpv4Base->Udpv4PseudoHeader.TotalLength;
Udpv4Base->Udpv4Header.Checksum = 0;
if (HeaderSize != 0) {
CopyMem (IpTxBuffer->u.Udp.Data, HeaderPtr, HeaderSize);
}
HeaderSize += sizeof (UDPV4_HEADER);
Udpv4Base->Udpv4Header.Checksum = IpChecksum2 (
(UINT16 *) Udpv4Base,
HeaderSize + sizeof (UDPV4_PSEUDO_HEADER),
(UINT16 *) BufferPtr,
(UINT16) *BufferSizeptr
);
if (Udpv4Base->Udpv4Header.Checksum == 0) {
Udpv4Base->Udpv4Header.Checksum = 0xffff;
//
// transmit zero checksum as ones complement
//
}
return Ip4Send (
Private,
OpFlags,
PROT_UDP,
Udpv4Base->Udpv4PseudoHeader.SrcAddr.L,
Udpv4Base->Udpv4PseudoHeader.DestAddr.L,
(GatewayIpPtr) ? GatewayIpPtr->Addr[0] : 0,
HeaderSize,
BufferPtr,
*BufferSizeptr
);
}
//
// //////////////////////////////////////////////////////////
//
// BC Udp Write Routine
//
EFI_STATUS
EFIAPI
BcUdpWrite (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN UINT16 OpFlags,
IN EFI_IP_ADDRESS *DestIpPtr,
IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,
IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL
IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL
IN UINTN *HeaderSizePtr, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN UINTN *BufferSizeptr,
IN VOID *BufferPtr
)
/*++
Routine description:
UDP write API entry point.
Parameters:
This := Pointer to PxeBc interface.
OpFlags :=
DestIpPtr :=
DestPortPtr :=
GatewayIpPtr :=
SrcIpPtr :=
SrcPortPtr :=
HeaderSizePtr :=
HeaderPtr :=
BufferSizeptr :=
BufferPtr :=
Returns:
EFI_SUCCESS :=
other :=
--*/
{
EFI_STATUS StatCode;
PXE_BASECODE_DEVICE *Private;
//
// Lock the instance data and make sure started
//
StatCode = EFI_SUCCESS;
if (This == NULL) {
DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
return EFI_INVALID_PARAMETER;
}
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
if (Private == NULL) {
DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
return EFI_INVALID_PARAMETER;
}
EfiAcquireLock (&Private->Lock);
if (This->Mode == NULL || !This->Mode->Started) {
DEBUG ((EFI_D_ERROR, "BC was not started."));
EfiReleaseLock (&Private->Lock);
return EFI_NOT_STARTED;
}
Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE;
//
// Issue BC command
//
StatCode = UdpWrite (
Private,
OpFlags,
DestIpPtr,
DestPortPtr,
GatewayIpPtr,
SrcIpPtr,
SrcPortPtr,
HeaderSizePtr,
HeaderPtr,
BufferSizeptr,
BufferPtr
);
//
// Unlock the instance data
//
EfiReleaseLock (&Private->Lock);
return StatCode;
}
//
// /////////////////////////////////////////////////////////////////////
//
// Udp Read Routine - called by base code - e.g. TFTP - already locked
//
EFI_STATUS
UdpRead (
IN PXE_BASECODE_DEVICE *Private,
IN UINT16 OpFlags,
IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, OPTIONAL
IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL
IN UINTN *HeaderSizePtr, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN OUT UINTN *BufferSizeptr,
IN VOID *BufferPtr,
EFI_EVENT TimeoutEvent
)
/*++
Routine description:
UDP read packet.
Parameters:
Private := Pointer to PxeBc interface
OpFlags :=
DestIpPtr :=
DestPortPtr :=
SrcIpPtr :=
SrcPortPtr :=
HeaderSizePtr :=
HeaderPtr :=
BufferSizeptr :=
BufferPtr :=
TimeoutEvent :=
Returns:
EFI_SUCCESS :=
EFI_INVALID_PARAMETER :=
other :=
--*/
{
EFI_STATUS StatCode;
EFI_IP_ADDRESS TmpSrcIp;
EFI_IP_ADDRESS TmpDestIp;
UINTN BufferSize;
UINTN HeaderSize;
//
// combination structure of pseudo header/udp header
//
#pragma pack (1)
struct {
UDPV4_PSEUDO_HEADER Udpv4PseudoHeader;
UDPV4_HEADER Udpv4Header;
UINT8 ProtHdr[64];
} Hdrs;
#pragma pack ()
HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;
//
// read [with filtering]
// check parameters
//
if (BufferSizeptr == NULL ||
BufferPtr == NULL ||
(HeaderSize != 0 && HeaderPtr == NULL) ||
(OpFlags &~UDP_FILTER_MASK)
//
// if filtering on a particular IP/Port, need it
//
||
(!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr == NULL) ||
(!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && SrcPortPtr == NULL) ||
(!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && DestPortPtr == NULL)
) {
DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #1 Invalid Parameter"));
return EFI_INVALID_PARAMETER;
}
//
// in case we loop
//
BufferSize = *BufferSizeptr;
//
// we need source and dest IPs for pseudo header
//
if (SrcIpPtr == NULL) {
SrcIpPtr = &TmpSrcIp;
}
if (DestIpPtr == NULL) {
DestIpPtr = &TmpDestIp;
CopyMem (&TmpDestIp, &Private->EfiBc.Mode->StationIp, sizeof (TmpDestIp));
}
#if SUPPORT_IPV6
if (Private->EfiBc.Mode->UsingIpv6) {
//
// %%TBD
//
}
#endif
for (;;) {
*BufferSizeptr = BufferSize;
StatCode = IpReceive (
Private,
OpFlags,
SrcIpPtr,
DestIpPtr,
PROT_UDP,
&Hdrs.Udpv4Header,
HeaderSize + sizeof Hdrs.Udpv4Header,
BufferPtr,
BufferSizeptr,
TimeoutEvent
);
if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {
UINT16 SPort;
UINT16 DPort;
SPort = NTOHS (Hdrs.Udpv4Header.SrcPort);
DPort = NTOHS (Hdrs.Udpv4Header.DestPort);
//
// do filtering
//
if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && *SrcPortPtr != SPort) {
continue;
}
if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && *DestPortPtr != DPort) {
continue;
}
//
// check checksum
//
if (StatCode == EFI_SUCCESS && Hdrs.Udpv4Header.Checksum) {
Hdrs.Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];
Hdrs.Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];
Hdrs.Udpv4PseudoHeader.Zero = 0;
Hdrs.Udpv4PseudoHeader.Protocol = PROT_UDP;
Hdrs.Udpv4PseudoHeader.TotalLength = Hdrs.Udpv4Header.TotalLength;
if (Hdrs.Udpv4Header.Checksum == 0xffff) {
Hdrs.Udpv4Header.Checksum = 0;
}
if (IpChecksum2 (
(UINT16 *) &Hdrs.Udpv4PseudoHeader,
HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader) + sizeof (Hdrs.Udpv4Header),
(UINT16 *) BufferPtr,
*BufferSizeptr
)) {
DEBUG (
(EFI_D_INFO,
"\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",
&Hdrs.Udpv4PseudoHeader)
);
DEBUG (
(EFI_D_INFO,
"\nUdpRead() Header size == %d",
HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader))
);
DEBUG (
(EFI_D_INFO,
"\nUdpRead() BufferPtr == %Xh",
BufferPtr)
);
DEBUG (
(EFI_D_INFO,
"\nUdpRead() Buffer size == %d",
*BufferSizeptr)
);
DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #2 Device Error"));
return EFI_DEVICE_ERROR;
}
}
//
// all passed
//
if (SrcPortPtr != NULL) {
*SrcPortPtr = SPort;
}
if (DestPortPtr != NULL) {
*DestPortPtr = DPort;
}
if (HeaderSize != 0) {
CopyMem (HeaderPtr, Hdrs.ProtHdr, HeaderSize);
}
}
switch (StatCode) {
case EFI_SUCCESS:
case EFI_TIMEOUT:
break;
default:
DEBUG (
(EFI_D_INFO,
"\nUdpRead() Exit #3 %Xh %r",
StatCode,
StatCode)
);
}
return StatCode;
}
}
//
// //////////////////////////////////////////////////////////
//
// BC Udp Read Routine
//
EFI_STATUS
EFIAPI
BcUdpRead (
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
IN UINT16 OpFlags,
IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL
IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL
IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL
IN UINTN *HeaderSize, OPTIONAL
IN VOID *HeaderPtr, OPTIONAL
IN OUT UINTN *BufferSize,
IN VOID *BufferPtr
)
/*++
Routine description:
UDP read API entry point.
Parameters:
This := Pointer to PxeBc interface.
OpFlags :=
DestIpPtr :=
DestPortPtr :=
SrcIpPtr :=
SrcPortPtr :=
HeaderSizePtr :=
HeaderPtr :=
BufferSizeptr :=
BufferPtr :=
Returns:
EFI_SUCCESS :=
other :=
--*/
{
EFI_STATUS StatCode;
PXE_BASECODE_DEVICE *Private;
//
// Lock the instance data and make sure started
//
StatCode = EFI_SUCCESS;
if (This == NULL) {
DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
return EFI_INVALID_PARAMETER;
}
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
if (Private == NULL) {
DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
return EFI_INVALID_PARAMETER;
}
EfiAcquireLock (&Private->Lock);
if (This->Mode == NULL || !This->Mode->Started) {
DEBUG ((EFI_D_ERROR, "BC was not started."));
EfiReleaseLock (&Private->Lock);
return EFI_NOT_STARTED;
}
Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_READ;
//
// Issue BC command
//
StatCode = UdpRead (
Private,
OpFlags,
DestIp,
DestPort,
SrcIp,
SrcPort,
HeaderSize,
HeaderPtr,
BufferSize,
BufferPtr,
0
);
//
// Unlock the instance data and return
//
EfiReleaseLock (&Private->Lock);
return StatCode;
}
/* eof - pxe_bc_udp.c */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
tftp.h
Abstract:
--*/
#ifndef __TFTP_H__
#define __TFTP_H__
//
// Definitions for trivial file transfer protocol functionality with IP v4
// Per RFC 1350, July 1992 and RFC 2347, 8, and 9, May 1998
//
#pragma pack(1)
//
// max and min packet sizes
// (all data packets in transmission except last)
//
#define MAX_TFTP_PKT_SIZE (BUFFER_ALLOCATE_SIZE - 512)
#define MIN_TFTP_PKT_SIZE 512
//
// TFTPv4 OpCodes
//
#define TFTP_RRQ 1 // read request
#define TFTP_WRQ 2 // write request
#define TFTP_DATA 3 // data
#define TFTP_ACK 4 // acknowledgement
#define TFTP_ERROR 5 // error packet
#define TFTP_OACK 6 // option acknowledge
#define TFTP_DIR 7 // read directory request
#define TFTP_DATA8 8
#define TFTP_ACK8 9
//
// request packet (read or write)
// Fields shown (except file name) are not to be referenced directly,
// since their placement is variable within a request packet.
// All are null terminated case insensitive ascii strings.
//
struct Tftpv4Req {
UINT16 OpCode; // TFTP Op code
UINT8 FileName[2]; // file name
UINT8 Mode[2]; // "netascii" or "octet"
struct { // optionally, one or more option requests
UINT8 Option[2]; // option name
UINT8 Value[2]; // value requested
} OpReq[1];
};
//
// modes
//
#define MODE_ASCII "netascii"
#define MODE_BINARY "octet"
//
// option strings
//
#define OP_BLKSIZE "blksize" // block size option
#define OP_TIMEOUT "timeout" // time to wait before retransmitting
#define OP_TFRSIZE "tsize" // total transfer size option
#define OP_OVERWRITE "overwrite" // overwrite file option
#define OP_BIGBLKNUM "bigblk#" // big block number
// See RFC 2347, 8, and 9 for more information on TFTP options
// option acknowledge packet (optional)
// options not acknowledged are rejected
//
struct Tftpv4Oack {
UINT16 OpCode; // TFTP Op code
struct { // optionally, one or more option acknowledgements
UINT8 Option[2]; // option name (of those requested)
UINT8 Value[2]; // value acknowledged
} OpAck[1];
};
//
// acknowledge packet
//
struct Tftpv4Ack {
UINT16 OpCode; // TFTP Op code
UINT16 BlockNum;
};
//
// data packet
//
struct Tftpv4Data {
struct Tftpv4Ack Header;
UINT8 Data[512];
};
//
// big block number ack packet
//
struct Tftpv4Ack8 {
UINT16 OpCode;
UINT64 BlockNum;
};
//
// big block number data packet
//
struct Tftpv4Data8 {
struct Tftpv4Ack8 Header;
UINT8 Data[506];
};
//
// error packet
//
struct Tftpv4Error {
UINT16 OpCode; // TFTP Op code
UINT16 ErrCode; // error code
UINT8 ErrMsg[1]; // error message (nul terminated)
};
#pragma pack()
//
// error codes
//
#define TFTP_ERR_UNDEF 0 // Not defined, see error message (if any).
#define TFTP_ERR_NOT_FOUND 1 // File not found.
#define TFTP_ERR_ACCESS 2 // Access violation.
#define TFTP_ERR_FULL 3 // Disk full or allocation exceeded.
#define TFTP_ERR_ILLEGAL 4 // Illegal TFTP operation.
#define TFTP_ERR_BAD_ID 5 // Unknown transfer ID.
#define TFTP_ERR_EXISTS 6 // File already exists.
#define TFTP_ERR_NO_USER 7 // No such user.
#define TFTP_ERR_OPTION 8 // Option negotiation termination
//
// some defines
//
#define REQ_RESP_TIMEOUT 5 // Wait five seconds for request response.
#define ACK_TIMEOUT 4 // Wait four seconds for ack response.
#define NUM_ACK_RETRIES 3
#define NUM_MTFTP_OPEN_RETRIES 3
#endif /* __TFTP_H__ */
/* EOF - tftp.h */

View File

@@ -0,0 +1,169 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
PxeDhcp4 component name protocol declarations
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
PxeDhcp4ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
PxeDhcp4ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// EFI Component Name Protocol
//
EFI_COMPONENT_NAME_PROTOCOL gPxeDhcp4ComponentName = {
PxeDhcp4ComponentNameGetDriverName,
PxeDhcp4ComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mPxeDhcp4DriverNameTable[] = {
{
"eng",
(CHAR16 *) L"PXE DHCPv4 Driver"
},
{
NULL,
NULL
}
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4ComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gPxeDhcp4ComponentName.SupportedLanguages,
mPxeDhcp4DriverNameTable,
DriverName
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4ComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}
/* EOF - ComponentName.c */

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MbdHeader>
<BaseName>Dhcp4</BaseName>
<Guid>a46c3330-be36-4977-9d24-a7cf92eef0fe</Guid>
<Version>0</Version>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Created>2006-03-12 17:09</Created>
<Modified>2006-03-19 15:19</Modified>
</MbdHeader>
<Libraries>
<Library>UefiBootServicesTableLib</Library>
<Library>UefiMemoryLib</Library>
<Library>UefiLib</Library>
<Library>UefiDriverEntryPoint</Library>
<Library>UefiDriverModelLib</Library>
<Library>DxeReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>BaseLib</Library>
<Library>DxeMemoryAllocationLib</Library>
</Libraries>
</ModuleBuildDescription>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MsaHeader>
<BaseName>Dhcp4</BaseName>
<ModuleType>UEFI_DRIVER</ModuleType>
<ComponentType>BS_DRIVER</ComponentType>
<Guid>a46c3330-be36-4977-9d24-a7cf92eef0fe</Guid>
<Version>0</Version>
<Abstract>Component description file for DiskIo module.</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Specification>0</Specification>
<Created>2006-03-12 17:09</Created>
<Updated>2006-03-19 15:19</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>ComponentName.c</Filename>
<Filename>PxeDhcp4.c</Filename>
<Filename>PxeDhcp4.h</Filename>
<Filename>PxeDhcp4InitSelect.c</Filename>
<Filename>PxeDhcp4Release.c</Filename>
<Filename>PxeDhcp4RenewRebind.c</Filename>
<Filename>PxeDhcp4Run.c</Filename>
<Filename>PxeDhcp4Setup.c</Filename>
<Filename>support.c</Filename>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">PxeDhcp4Callback</Protocol>
<Protocol Usage="BY_START">PxeDhcp4</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">SimpleNetwork</Protocol>
<Protocol Usage="TO_START">PxeBaseCode</Protocol>
</Protocols>
<Externs>
<Extern>
<ModuleEntryPoint></ModuleEntryPoint>
<ModuleUnloadImage></ModuleUnloadImage>
</Extern>
<Extern>
<DriverBinding>gPxeDhcp4DriverBinding</DriverBinding>
<ComponentName>gPxeDhcp4ComponentName</ComponentName>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,342 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4.c
Abstract:
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// Prototypes
// Driver model protocol interface
//
EFI_STATUS
EFIAPI
PxeDhcp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// PXE DHCP Protocol Interface
//
EFI_DRIVER_BINDING_PROTOCOL gPxeDhcp4DriverBinding = {
PxeDhcp4DriverBindingSupported,
PxeDhcp4DriverBindingStart,
PxeDhcp4DriverBindingStop,
0x10,
NULL,
NULL
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
/*++
Routine Description:
Test to see if this driver supports ControllerHandle. Any
ControllerHandle that contains a PxeBaseCode protocol can be
supported.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to test.
RemainingDevicePath - Not used.
Returns:
EFI_SUCCESS - This driver supports this device.
EFI_ALREADY_STARTED - This driver is already running on this
device.
other - This driver does not support this device.
--*/
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
//
// Open the IO Abstraction(s) needed to perform the supported test.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPxeBaseCodeProtocolGuid,
(VOID **) &PxeBc,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Close the I/O Abstraction(s) used to perform the supported test.
//
return gBS->CloseProtocol (
ControllerHandle,
&gEfiPxeBaseCodeProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
/*++
Routine Description:
Start this driver on ControllerHandle by opening a PxeBaseCode
protocol and installing a PxeDhcp4 protocol on ControllerHandle.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to bind driver to.
RemainingDevicePath - Not used, always produce all possible
children.
Returns:
EFI_SUCCESS - This driver is added to ControllerHandle.
EFI_ALREADY_STARTED - This driver is already running on
ControllerHandle.
other - This driver does not support this device.
--*/
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
PXE_DHCP4_PRIVATE_DATA *Private;
//
// Connect to the PxeBaseCode interface on ControllerHandle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPxeBaseCodeProtocolGuid,
(VOID **) &PxeBc,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// BaseCode has already grabbed the SimpleNetwork interface
// so just do a HandleProtocol() to get it.
//
Status = gBS->HandleProtocol (
ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
(VOID **) &Snp
);
if (EFI_ERROR (Status)) {
goto error_exit;
}
ASSERT (Snp);
//
// Initialize the PXE DHCP device instance.
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (PXE_DHCP4_PRIVATE_DATA),
(VOID **) &Private
);
if (EFI_ERROR (Status)) {
goto error_exit;
}
//
//
//
ZeroMem (Private, sizeof (PXE_DHCP4_PRIVATE_DATA));
Private->Signature = PXE_DHCP4_PRIVATE_DATA_SIGNATURE;
Private->PxeBc = PxeBc;
Private->Snp = Snp;
Private->Handle = ControllerHandle;
Private->PxeDhcp4.Revision = EFI_PXE_DHCP4_PROTOCOL_REVISION;
Private->PxeDhcp4.Run = PxeDhcp4Run;
Private->PxeDhcp4.Setup = PxeDhcp4Setup;
Private->PxeDhcp4.Init = PxeDhcp4Init;
Private->PxeDhcp4.Select = PxeDhcp4Select;
Private->PxeDhcp4.Renew = PxeDhcp4Renew;
Private->PxeDhcp4.Rebind = PxeDhcp4Rebind;
Private->PxeDhcp4.Release = PxeDhcp4Release;
Private->PxeDhcp4.Data = NULL;
//
// Install protocol interfaces for the PXE DHCP device.
//
Status = gBS->InstallProtocolInterface (
&ControllerHandle,
&gEfiPxeDhcp4ProtocolGuid,
EFI_NATIVE_INTERFACE,
&Private->PxeDhcp4
);
if (!EFI_ERROR (Status)) {
return Status;
}
error_exit: ;
gBS->CloseProtocol (
ControllerHandle,
&gEfiPxeBaseCodeProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return Status;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop this driver on ControllerHandle by removing PXE DHCP
protocol and closing the PXE Base Code protocol on
ControllerHandle.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to stop driver on.
NumberOfChildren - Not used.
ChildHandleBuffer - Not used.
Returns:
EFI_SUCCESS - This driver is removed ControllerHandle.
other - This driver was not removed from this
device.
--*/
{
EFI_STATUS Status;
EFI_PXE_DHCP4_PROTOCOL *PxeDhcp4;
PXE_DHCP4_PRIVATE_DATA *Private;
//
// Get our context back.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPxeDhcp4ProtocolGuid,
(VOID **) &PxeDhcp4,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (PxeDhcp4);
//
// Release allocated resources
//
if (Private->PxeDhcp4.Data) {
gBS->FreePool (Private->PxeDhcp4.Data);
Private->PxeDhcp4.Data = NULL;
}
//
// Uninstall our protocol
//
Status = gBS->UninstallProtocolInterface (
ControllerHandle,
&gEfiPxeDhcp4ProtocolGuid,
&Private->PxeDhcp4
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Close any consumed protocols
//
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiPxeBaseCodeProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Release our private data
//
gBS->FreePool (Private);
return Status;
}
/* EOF - PxeDhcp4.c */

View File

@@ -0,0 +1,307 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4.h
Abstract:
Common header for PxeDhcp4 protocol driver
--*/
#ifndef _PXEDHCP4_H
#define _PXEDHCP4_H
//
// PxeDhcp4 protocol instance data
//
typedef struct {
//
// Signature field used to locate beginning of containment record.
//
UINTN Signature;
#define PXE_DHCP4_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('p', 'x', 'D', '4')
//
// Device handle the protocol is bound to.
//
EFI_HANDLE Handle;
//
// Public PxeDhcp4 protocol interface.
//
EFI_PXE_DHCP4_PROTOCOL PxeDhcp4;
//
// Consumed PxeBc, Snp and PxeDhcp4Callback protocol interfaces.
//
EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_PXE_DHCP4_CALLBACK_PROTOCOL *callback;
//
// PxeDhcp4 called function for PxeDhcp4Callback.
//
EFI_PXE_DHCP4_FUNCTION function;
//
// Timeout event and flag for PxeDhcp4Callback.
//
EFI_EVENT TimeoutEvent;
BOOLEAN TimeoutOccurred;
//
// Periodic event and flag for PxeDhcp4Callback.
//
EFI_EVENT PeriodicEvent;
BOOLEAN PeriodicOccurred;
//
// DHCP server IP address.
//
UINT32 ServerIp;
//
// DHCP renewal and rebinding times, in seconds.
//
UINT32 RenewTime;
UINT32 RebindTime;
UINT32 LeaseTime;
//
// Number of offers received & allocated offer list.
//
UINTN offers;
DHCP4_PACKET *offer_list;
//
//
//
BOOLEAN StopPxeBc;
} PXE_DHCP4_PRIVATE_DATA;
#define PXE_DHCP4_PRIVATE_DATA_FROM_THIS(a) CR (a, PXE_DHCP4_PRIVATE_DATA, PxeDhcp4, PXE_DHCP4_PRIVATE_DATA_SIGNATURE)
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// Protocol function prototypes.
//
extern
EFI_STATUS
EFIAPI
PxeDhcp4Run (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN OPTIONAL UINTN OpLen,
IN OPTIONAL VOID *OpList
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Setup (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN EFI_PXE_DHCP4_DATA *Data
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Init (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
OUT UINTN *offer_list_entries,
OUT DHCP4_PACKET **offer_list
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Select (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
IN DHCP4_PACKET *offer_list
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Renew (
IN EFI_PXE_DHCP4_PROTOCOL *This,
UINTN seconds_timeout
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Rebind (
IN EFI_PXE_DHCP4_PROTOCOL *This,
UINTN seconds_timeout
)
;
extern
EFI_STATUS
EFIAPI
PxeDhcp4Release (
IN EFI_PXE_DHCP4_PROTOCOL *This
)
;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// Support function prototypes.
//
extern
UINT16
htons (
UINTN n
)
;
extern
UINT32
htonl (
UINTN n
)
;
extern
VOID
EFIAPI
timeout_notify (
IN EFI_EVENT Event,
IN VOID *Context
)
;
extern
VOID
EFIAPI
periodic_notify (
IN EFI_EVENT Event,
IN VOID *Context
)
;
extern
EFI_STATUS
find_opt (
IN DHCP4_PACKET *Packet,
IN UINT8 OpCode,
IN UINTN Skip,
OUT DHCP4_OP **OpPtr
)
;
extern
EFI_STATUS
add_opt (
IN DHCP4_PACKET *Packet,
IN DHCP4_OP *OpPtr
)
;
extern
EFI_STATUS
start_udp (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN OPTIONAL EFI_IP_ADDRESS *station_ip,
IN OPTIONAL EFI_IP_ADDRESS *subnet_mask
)
;
extern
VOID
stop_udp (
IN PXE_DHCP4_PRIVATE_DATA *Private
)
;
extern
EFI_STATUS
start_receive_events (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN UINTN seconds_timeout
)
;
extern
VOID
stop_receive_events (
IN PXE_DHCP4_PRIVATE_DATA *Private
)
;
extern
EFI_STATUS
tx_udp (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN EFI_IP_ADDRESS *dest_ip,
IN OPTIONAL EFI_IP_ADDRESS *gateway_ip,
IN EFI_IP_ADDRESS *src_ip,
IN VOID *buffer,
IN UINTN BufferSize
)
;
extern
EFI_STATUS
rx_udp (
IN PXE_DHCP4_PRIVATE_DATA *Private,
OUT VOID *buffer,
OUT UINTN *BufferSize,
IN OUT EFI_IP_ADDRESS *dest_ip,
IN OUT EFI_IP_ADDRESS *src_ip,
IN UINT16 op_flags
)
;
extern
EFI_STATUS
tx_rx_udp (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN OUT EFI_IP_ADDRESS *ServerIp,
IN OPTIONAL EFI_IP_ADDRESS *gateway_ip,
IN OPTIONAL EFI_IP_ADDRESS *client_ip,
IN OPTIONAL EFI_IP_ADDRESS *subnet_mask,
IN DHCP4_PACKET *tx_pkt,
OUT DHCP4_PACKET *rx_pkt,
IN INTN
(
*rx_vfy)
(
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN DHCP4_PACKET *tx_pkt,
IN DHCP4_PACKET *rx_pkt,
IN UINTN rx_pkt_size
),
IN UINTN seconds_timeout
)
;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// Global variable definitions.
//
extern EFI_DRIVER_BINDING_PROTOCOL gPxeDhcp4DriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gPxeDhcp4ComponentName;
#endif /* _PXEDHCP4_H */
/* EOF - PxeDhcp4.h */

View File

@@ -0,0 +1,786 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4InitSelect.c
Abstract:
--*/
#include "PxeDhcp4.h"
#define DebugPrint(x)
//
// #define DebugPrint(x) Aprint x
//
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
INTN
offer_verify (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN DHCP4_PACKET *tx_pkt,
IN DHCP4_PACKET *rx_pkt,
IN UINTN rx_pkt_size
)
/*++
-2 = ignore, stop waiting
-1 = ignore, keep waiting
0 = accept, keep waiting
1 = accept, stop waiting
--*/
{
EFI_STATUS EfiStatus;
DHCP4_PACKET *tmp;
DHCP4_OP *msg_type_op;
DHCP4_OP *srvid_op;
UINT32 magik;
//
// Verify parameters. Touch unused parameters to keep
// compiler happy.
//
ASSERT (Private);
ASSERT (rx_pkt);
if (Private == NULL || rx_pkt == NULL) {
return -2;
}
tx_pkt = tx_pkt;
rx_pkt_size = rx_pkt_size;
//
// This may be a BOOTP Reply or DHCP Offer packet.
// If there is no DHCP magik number, assume that
// this is a BOOTP Reply packet.
//
magik = htonl (DHCP4_MAGIK_NUMBER);
while (!CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {
//
// If there is no DHCP message type option, assume
// this is a BOOTP reply packet and cache it.
//
EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);
if (EFI_ERROR (EfiStatus)) {
break;
}
//
// If there is a DHCP message type option, it must be a
// DHCP offer packet
//
if (msg_type_op->len != 1) {
return -1;
}
if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {
return -1;
}
//
// There must be a server identifier option.
//
EfiStatus = find_opt (
rx_pkt,
DHCP4_SERVER_IDENTIFIER,
0,
&srvid_op
);
if (EFI_ERROR (EfiStatus)) {
return -1;
}
if (srvid_op->len != 4) {
return -1;
}
//
// Good DHCP offer packet.
//
break;
}
//
// Good DHCP (or BOOTP) packet. Cache it!
//
EfiStatus = gBS->AllocatePool (
EfiBootServicesData,
(Private->offers + 1) * sizeof (DHCP4_PACKET),
(VOID **) &tmp
);
if (EFI_ERROR (EfiStatus)) {
return -2;
}
ASSERT (tmp);
if (Private->offers != 0) {
CopyMem (
tmp,
Private->offer_list,
Private->offers * sizeof (DHCP4_PACKET)
);
gBS->FreePool (Private->offer_list);
}
CopyMem (&tmp[Private->offers++], rx_pkt, sizeof (DHCP4_PACKET));
Private->offer_list = tmp;
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
INTN
acknak_verify (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN DHCP4_PACKET *tx_pkt,
IN DHCP4_PACKET *rx_pkt,
IN UINTN rx_pkt_size
)
/*++
-2 = ignore, stop waiting
-1 = ignore, keep waiting
0 = accept, keep waiting
1 = accept, stop waiting
--*/
{
EFI_STATUS EfiStatus;
DHCP4_OP *msg_type_op;
DHCP4_OP *srvid_op;
DHCP4_OP *renew_op;
DHCP4_OP *rebind_op;
DHCP4_OP *lease_time_op;
UINT32 magik;
//
// Verify parameters. Touch unused parameters to
// keep compiler happy.
//
ASSERT (Private);
ASSERT (rx_pkt);
if (Private == NULL || rx_pkt == NULL) {
return -2;
}
tx_pkt = tx_pkt;
rx_pkt_size = rx_pkt_size;
//
// This must be a DHCP Ack message.
//
magik = htonl (DHCP4_MAGIK_NUMBER);
if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {
return -1;
}
EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);
if (EFI_ERROR (EfiStatus)) {
return -1;
}
if (msg_type_op->len != 1) {
return -1;
}
if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) {
return -1;
}
//
// There must be a server identifier.
//
EfiStatus = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op);
if (EFI_ERROR (EfiStatus)) {
return -1;
}
if (srvid_op->len != 4) {
return -1;
}
//
// There should be a renewal time.
// If there is not, we will default to the 7/8 of the rebinding time.
//
EfiStatus = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op);
if (EFI_ERROR (EfiStatus)) {
renew_op = NULL;
} else if (renew_op->len != 4) {
renew_op = NULL;
}
//
// There should be a rebinding time.
// If there is not, we will default to 7/8 of the lease time.
//
EfiStatus = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op);
if (EFI_ERROR (EfiStatus)) {
rebind_op = NULL;
} else if (rebind_op->len != 4) {
rebind_op = NULL;
}
//
// There should be a lease time.
// If there is not, we will default to one week.
//
EfiStatus = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op);
if (EFI_ERROR (EfiStatus)) {
lease_time_op = NULL;
} else if (lease_time_op->len != 4) {
lease_time_op = NULL;
}
//
// Packet looks good. Double check the renew, rebind and lease times.
//
CopyMem (&Private->ServerIp, srvid_op->data, 4);
if (renew_op != NULL) {
CopyMem (&Private->RenewTime, renew_op->data, 4);
Private->RenewTime = htonl (Private->RenewTime);
} else {
Private->RenewTime = 0;
}
if (rebind_op != NULL) {
CopyMem (&Private->RebindTime, rebind_op->data, 4);
Private->RebindTime = htonl (Private->RebindTime);
} else {
Private->RebindTime = 0;
}
if (lease_time_op != NULL) {
CopyMem (&Private->LeaseTime, lease_time_op->data, 4);
Private->LeaseTime = htonl (Private->LeaseTime);
} else {
Private->LeaseTime = 0;
}
if (Private->LeaseTime < 60) {
Private->LeaseTime = 7 * 86400;
}
if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) {
Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8;
}
if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) {
Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8;
}
return 1;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Init (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
OUT UINTN *Offers,
OUT DHCP4_PACKET **OfferList
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
DHCP4_PACKET offer;
EFI_IP_ADDRESS bcast_ip;
EFI_STATUS EfiStatus;
//
// Verify parameters and protocol state.
//
if (This == NULL ||
seconds_timeout < DHCP4_MIN_SECONDS ||
seconds_timeout > DHCP4_MAX_SECONDS ||
Offers == NULL ||
OfferList == NULL
) {
//
// Return parameters are not initialized when
// parameters are invalid!
//
return EFI_INVALID_PARAMETER;
}
*Offers = 0;
*OfferList = NULL;
//
// Check protocol state.
//
if (This->Data == NULL) {
return EFI_NOT_STARTED;
}
if (!This->Data->SetupCompleted) {
return EFI_NOT_READY;
}
#if 0
if (!is_good_discover (&This->Data->Discover)) {
//
// %%TBD - check discover packet fields
//
}
#endif
//
// Get pointer to our instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Setup variables...
//
Private->offers = 0;
Private->offer_list = NULL;
EfiStatus = gBS->HandleProtocol (
Private->Handle,
&gEfiPxeDhcp4CallbackProtocolGuid,
(VOID *) &Private->callback
);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
}
Private->function = EFI_PXE_DHCP4_FUNCTION_INIT;
//
// Increment the transaction ID.
//
{
UINT32 xid;
CopyMem (&xid, &This->Data->Discover.dhcp4.xid, sizeof (UINT32));
xid = htonl (htonl (xid) + 1);
CopyMem (&This->Data->Discover.dhcp4.xid, &xid, sizeof (UINT32));
}
//
// Transmit discover and wait for offers...
//
SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
EfiStatus = tx_rx_udp (
Private,
&bcast_ip,
NULL,
NULL,
NULL,
&This->Data->Discover,
&offer,
&offer_verify,
seconds_timeout
);
if (EFI_ERROR (EfiStatus)) {
if (Private->offer_list) {
gBS->FreePool (Private->offer_list);
}
Private->offers = 0;
Private->offer_list = NULL;
Private->callback = NULL;
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
return EfiStatus;
}
*Offers = Private->offers;
*OfferList = Private->offer_list;
Private->offers = 0;
Private->offer_list = NULL;
Private->callback = NULL;
This->Data->InitCompleted = TRUE;
This->Data->SelectCompleted = FALSE;
This->Data->IsBootp = FALSE;
This->Data->IsAck = FALSE;
return EFI_SUCCESS;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Select (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
IN DHCP4_PACKET *Offer
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
EFI_STATUS EfiStatus;
DHCP4_PACKET request;
DHCP4_PACKET acknak;
EFI_IP_ADDRESS bcast_ip;
EFI_IP_ADDRESS zero_ip;
EFI_IP_ADDRESS local_ip;
DHCP4_OP *srvid;
DHCP4_OP *op;
UINT32 dhcp4_magik;
UINT8 buf[16];
BOOLEAN is_bootp;
//
// Verify parameters.
//
if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS || Offer == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check protocol state.
//
if (This->Data == NULL) {
return EFI_NOT_STARTED;
}
if (!This->Data->SetupCompleted) {
return EFI_NOT_READY;
}
//
// Get pointer to instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
#if 0
if (!is_good_discover (&This->Data->Discover)) {
//
// %%TBD - check discover packet fields
//
}
#endif
//
// Setup useful variables...
//
SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));
ZeroMem (&local_ip, sizeof (EFI_IP_ADDRESS));
local_ip.v4.Addr[0] = 127;
local_ip.v4.Addr[3] = 1;
This->Data->SelectCompleted = FALSE;
This->Data->IsBootp = FALSE;
This->Data->IsAck = FALSE;
EfiStatus = gBS->HandleProtocol (
Private->Handle,
&gEfiPxeDhcp4CallbackProtocolGuid,
(VOID *) &Private->callback
);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
}
Private->function = EFI_PXE_DHCP4_FUNCTION_SELECT;
//
// Verify offer packet fields.
//
if (Offer->dhcp4.op != BOOTP_REPLY) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (Offer->dhcp4.htype != This->Data->Discover.dhcp4.htype) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (Offer->dhcp4.hlen != This->Data->Discover.dhcp4.hlen) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (CompareMem (&Offer->dhcp4.xid, &This->Data->Discover.dhcp4.xid, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!CompareMem (&Offer->dhcp4.yiaddr, &bcast_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!CompareMem (&Offer->dhcp4.yiaddr, &zero_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!CompareMem (&Offer->dhcp4.yiaddr, &local_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (CompareMem (
&Offer->dhcp4.chaddr,
&This->Data->Discover.dhcp4.chaddr,
16
)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
//
// DHCP option checks
//
dhcp4_magik = htonl (DHCP4_MAGIK_NUMBER);
is_bootp = TRUE;
if (!CompareMem (&Offer->dhcp4.magik, &dhcp4_magik, 4)) {
//
// If present, DHCP message type must be offer.
//
EfiStatus = find_opt (Offer, DHCP4_MESSAGE_TYPE, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 1 || op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
is_bootp = FALSE;
}
//
// If present, DHCP max message size must be valid.
//
EfiStatus = find_opt (Offer, DHCP4_MAX_MESSAGE_SIZE, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 2 || ((op->data[0] << 8) | op->data[1]) < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
//
// If present, DHCP server identifier must be valid.
//
EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 4 || !CompareMem (op->data, &bcast_ip, 4) || !CompareMem (op->data, &zero_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
//
// If present, DHCP subnet mask must be valid.
//
EfiStatus = find_opt (
Offer,
DHCP4_SUBNET_MASK,
0,
&op
);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 4) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
}
//
// Early out for BOOTP.
//
This->Data->IsBootp = is_bootp;
if (is_bootp) {
//
// Copy offer packet to instance data.
//
CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));
//
// Copy discover to request and offer to acknak.
//
CopyMem (
&This->Data->Request,
&This->Data->Discover,
sizeof (DHCP4_PACKET)
);
CopyMem (
&This->Data->AckNak,
&This->Data->Offer,
sizeof (DHCP4_PACKET)
);
//
// Set state flags.
//
This->Data->SelectCompleted = TRUE;
This->Data->IsAck = TRUE;
Private->callback = NULL;
return EFI_SUCCESS;
}
//
// Copy discover packet contents to request packet.
//
CopyMem (&request, &This->Data->Discover, sizeof (DHCP4_PACKET));
This->Data->IsAck = FALSE;
//
// Change DHCP message type from discover to request.
//
EfiStatus = find_opt (&request, DHCP4_MESSAGE_TYPE, 0, &op);
if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (EfiStatus == EFI_NOT_FOUND) {
EfiStatus = find_opt (&request, DHCP4_END, 0, &op);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
op->op = DHCP4_MESSAGE_TYPE;
op->len = 1;
op->data[1] = DHCP4_END;
}
op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;
//
// Copy server identifier option from offer to request.
//
EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &srvid);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (srvid->len != 4) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
EfiStatus = add_opt (&request, srvid);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Add requested IP address option to request packet.
//
op = (DHCP4_OP *) buf;
op->op = DHCP4_REQUESTED_IP_ADDRESS;
op->len = 4;
CopyMem (op->data, &Offer->dhcp4.yiaddr, 4);
EfiStatus = add_opt (&request, op);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Transimit DHCP request and wait for DHCP ack...
//
SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
EfiStatus = tx_rx_udp (
Private,
&bcast_ip,
NULL,
NULL,
NULL,
&request,
&acknak,
&acknak_verify,
seconds_timeout
);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Set Data->IsAck and return.
//
EfiStatus = find_opt (&acknak, DHCP4_MESSAGE_TYPE, 0, &op);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
if (op->len != 1) {
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
switch (op->data[0]) {
case DHCP4_MESSAGE_TYPE_ACK:
This->Data->IsAck = TRUE;
break;
case DHCP4_MESSAGE_TYPE_NAK:
This->Data->IsAck = FALSE;
break;
default:
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
//
// Copy packets into instance data...
//
CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));
CopyMem (&This->Data->Request, &request, sizeof (DHCP4_PACKET));
CopyMem (&This->Data->AckNak, &acknak, sizeof (DHCP4_PACKET));
This->Data->SelectCompleted = TRUE;
Private->callback = NULL;
return EFI_SUCCESS;
}
/* eof - PxeDhcp4InitSelect.c */

View File

@@ -0,0 +1,246 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4Release.c
Abstract:
Transmit release packet, free allocations and shutdown PxeDhcp4.
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Release (
IN EFI_PXE_DHCP4_PROTOCOL *This
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
EFI_IP_ADDRESS ServerIp;
EFI_IP_ADDRESS client_ip;
EFI_IP_ADDRESS gateway_ip;
EFI_IP_ADDRESS subnet_mask;
EFI_STATUS efi_status;
DHCP4_OP *op;
UINT8 op_list[20];
//
// Check for invalid parameters.
//
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Release does nothing if the protocol has never been setup.
//
if (This->Data == NULL) {
return EFI_NOT_STARTED;
}
//
// Fail if we do not have valid instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
//
// If this is a BOOTP session and there is not a DHCP Ack
// packet, just release storage and return.
//
if (This->Data->IsBootp || !This->Data->IsAck) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
//
// Build option list for DHCP Release packet.
// If any errors occur, just release storage and return.
//
//
// Message type is first.
//
op_list[0] = DHCP4_MESSAGE_TYPE;
op_list[1] = 1;
op_list[2] = DHCP4_MESSAGE_TYPE_RELEASE;
//
// Followed by server identifier.
//
efi_status = find_opt (
&This->Data->Request,
DHCP4_SERVER_IDENTIFIER,
0,
&op
);
if (EFI_ERROR (efi_status)) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
if (op->len != 4) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
CopyMem (&ServerIp, op->data, 4);
op_list[3] = DHCP4_SERVER_IDENTIFIER;
op_list[4] = 4;
CopyMem (&op_list[5], &ServerIp, 4);
//
// Followed by end.
//
op_list[9] = DHCP4_END;
//
// We need a subnet mask for IP stack operation.
//
efi_status = find_opt (
&This->Data->AckNak,
DHCP4_SUBNET_MASK,
0,
&op
);
if (EFI_ERROR (efi_status)) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
if (op->len != 4) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));
CopyMem (&subnet_mask, op->data, 4);
//
// Gateway IP address may be needed.
//
ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));
CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);
//
// Client IP address needed for IP stack operation.
//
ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));
CopyMem (&client_ip, &This->Data->AckNak.dhcp4.yiaddr, 4);
//
// Enable UDP...
//
efi_status = start_udp (Private, &client_ip, &subnet_mask);
if (EFI_ERROR (efi_status)) {
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return efi_status;
}
//
// Gather information out of DHCP request packet needed for
// DHCP release packet.
//
//
// Setup DHCP Release packet.
//
CopyMem (&This->Data->Request.dhcp4.ciaddr, &client_ip, 4);
ZeroMem (&This->Data->Request.dhcp4.yiaddr, 12);
ZeroMem (&This->Data->Request.dhcp4.sname, 64 + 128);
This->Data->Request.dhcp4.hops = 0;
This->Data->Request.dhcp4.secs = 0;
This->Data->Request.dhcp4.flags = 0;
ZeroMem (
&This->Data->Request.dhcp4.options,
sizeof This->Data->Request.dhcp4.options
);
CopyMem (&This->Data->Request.dhcp4.options, op_list, 10);
//
// Transmit DHCP Release packet.
//
tx_udp (
Private,
&ServerIp,
&gateway_ip,
&client_ip,
&This->Data->Request,
DHCP4_MAX_PACKET_SIZE - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE)
);
gBS->Stall (1000000); /* 1/10th second */
//
// Shutdown PXE BaseCode and release local storage.
//
stop_udp (Private);
gBS->FreePool (This->Data);
This->Data = NULL;
if (Private->StopPxeBc) {
Private->PxeBc->Stop (Private->PxeBc);
}
return EFI_SUCCESS;
}
/* eof - PxeDhcp4Release.c */

View File

@@ -0,0 +1,408 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4RenewRebind.c
Abstract:
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
INTN
acknak_verify (
IN PXE_DHCP4_PRIVATE_DATA *Private,
IN DHCP4_PACKET *tx_pkt,
IN DHCP4_PACKET *rx_pkt,
IN UINTN rx_pkt_size
)
/*++
Routine Description:
Parameters:
Returns:
-2 = ignore, stop waiting
-1 = ignore, keep waiting
0 = accept, keep waiting
1 = accept, stop waiting
--*/
{
EFI_STATUS efi_status;
DHCP4_OP *msg_type_op;
DHCP4_OP *srvid_op;
DHCP4_OP *renew_op;
DHCP4_OP *rebind_op;
DHCP4_OP *lease_time_op;
UINT32 magik;
//
// Verify parameters. Unused parameters are also touched
// to make the compiler happy.
//
ASSERT (Private);
ASSERT (rx_pkt);
if (Private == NULL || rx_pkt == NULL) {
return -2;
}
tx_pkt = tx_pkt;
rx_pkt_size = rx_pkt_size;
//
// This must be a DHCP Ack message.
//
magik = htonl (DHCP4_MAGIK_NUMBER);
if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {
return -1;
}
efi_status = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);
if (EFI_ERROR (efi_status)) {
return -1;
}
if (msg_type_op->len != 1) {
return -1;
}
if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) {
return -1;
}
//
// There must be a server identifier.
//
efi_status = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op);
if (EFI_ERROR (efi_status)) {
return -1;
}
if (srvid_op->len != 4) {
return -1;
}
//
// There should be a renewal time.
// If there is not, we will default to the 7/8 of the rebinding time.
//
efi_status = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op);
if (EFI_ERROR (efi_status)) {
renew_op = NULL;
} else if (renew_op->len != 4) {
renew_op = NULL;
}
//
// There should be a rebinding time.
// If there is not, we will default to 7/8 of the lease time.
//
efi_status = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op);
if (EFI_ERROR (efi_status)) {
rebind_op = NULL;
} else if (rebind_op->len != 4) {
rebind_op = NULL;
}
//
// There should be a lease time.
// If there is not, we will default to one week.
//
efi_status = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op);
if (EFI_ERROR (efi_status)) {
lease_time_op = NULL;
} else if (lease_time_op->len != 4) {
lease_time_op = NULL;
}
//
// Packet looks good. Double check the renew, rebind and lease times.
//
CopyMem (&Private->ServerIp, srvid_op->data, 4);
if (renew_op != NULL) {
CopyMem (&Private->RenewTime, renew_op->data, 4);
Private->RenewTime = htonl (Private->RenewTime);
} else {
Private->RenewTime = 0;
}
if (rebind_op != NULL) {
CopyMem (&Private->RebindTime, rebind_op->data, 4);
Private->RebindTime = htonl (Private->RebindTime);
} else {
Private->RebindTime = 0;
}
if (lease_time_op != NULL) {
CopyMem (&Private->LeaseTime, lease_time_op->data, 4);
Private->LeaseTime = htonl (Private->LeaseTime);
} else {
Private->LeaseTime = 0;
}
if (Private->LeaseTime < 60) {
Private->LeaseTime = 7 * 86400;
}
if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) {
Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8;
}
if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) {
Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8;
}
return 1;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
EFI_STATUS
EFIAPI
renew_rebind (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
IN BOOLEAN renew
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
EFI_IP_ADDRESS ServerIp;
EFI_IP_ADDRESS client_ip;
EFI_IP_ADDRESS subnet_mask;
EFI_IP_ADDRESS gateway_ip;
DHCP4_PACKET Request;
DHCP4_PACKET AckNak;
DHCP4_OP *op;
EFI_STATUS efi_status;
//
// Check for invalid parameters.
//
if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS) {
return EFI_INVALID_PARAMETER;
}
//
// Check for proper protocol state.
//
if (This->Data == NULL) {
return EFI_NOT_STARTED;
}
if (!This->Data->SelectCompleted) {
return EFI_NOT_READY;
}
if (This->Data->IsBootp) {
return EFI_SUCCESS;
}
if (!This->Data->IsAck) {
return EFI_INVALID_PARAMETER;
}
//
// Get pointer to instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Copy Discover packet to temporary request packet
// to be used for Renew/Rebind operation.
//
CopyMem (&Request, &This->Data->Discover, sizeof (DHCP4_PACKET));
CopyMem (&Request.dhcp4.ciaddr, &This->Data->AckNak.dhcp4.yiaddr, 4);
Request.dhcp4.flags = 0; /* Reply does not need to be broadcast. */
//
// Change message type from discover to request.
//
efi_status = find_opt (&Request, DHCP4_MESSAGE_TYPE, 0, &op);
if (EFI_ERROR (efi_status)) {
return EFI_INVALID_PARAMETER;
}
if (op->len != 1) {
return EFI_INVALID_PARAMETER;
}
op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;
//
// Need a subnet mask.
//
efi_status = find_opt (
&This->Data->AckNak,
DHCP4_SUBNET_MASK,
0,
&op
);
if (EFI_ERROR (efi_status)) {
return EFI_INVALID_PARAMETER;
}
if (op->len != 4) {
return EFI_INVALID_PARAMETER;
}
ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));
CopyMem (&subnet_mask, op->data, 4);
//
// Need a server IP address (renew) or a broadcast
// IP address (rebind).
//
ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));
if (renew) {
efi_status = find_opt (
&This->Data->AckNak,
DHCP4_SERVER_IDENTIFIER,
0,
&op
);
if (EFI_ERROR (efi_status)) {
return EFI_INVALID_PARAMETER;
}
if (op->len != 4) {
return EFI_INVALID_PARAMETER;
}
ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS));
CopyMem (&ServerIp, op->data, 4);
//
//
//
if (CompareMem (&This->Data->AckNak.dhcp4.giaddr, &gateway_ip, 4)) {
CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);
}
} else {
SetMem (&ServerIp, sizeof (EFI_IP_ADDRESS), 0xFF);
}
//
// Need a client IP address.
//
ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));
CopyMem (&client_ip, &Request.dhcp4.ciaddr, 4);
//
//
//
efi_status = gBS->HandleProtocol (
Private->Handle,
&gEfiPxeDhcp4CallbackProtocolGuid,
(VOID *) &Private->callback
);
if (EFI_ERROR (efi_status)) {
Private->callback = NULL;
}
Private->function = renew ? EFI_PXE_DHCP4_FUNCTION_RENEW : EFI_PXE_DHCP4_FUNCTION_REBIND;
//
// Transimit DHCP request and wait for DHCP ack...
//
efi_status = tx_rx_udp (
Private,
&ServerIp,
&gateway_ip,
&client_ip,
&subnet_mask,
&Request,
&AckNak,
&acknak_verify,
seconds_timeout
);
if (EFI_ERROR (efi_status)) {
Private->callback = NULL;
return efi_status;
}
//
// Copy server identifier, renewal time and rebinding time
// from temporary ack/nak packet into cached ack/nak packet.
//
efi_status = find_opt (
&This->Data->AckNak,
DHCP4_SERVER_IDENTIFIER,
0,
&op
);
if (!EFI_ERROR (efi_status)) {
if (op->len == 4) {
CopyMem (op->data, &Private->ServerIp, 4);
}
}
efi_status = find_opt (&This->Data->AckNak, DHCP4_RENEWAL_TIME, 0, &op);
if (!EFI_ERROR (efi_status)) {
if (op->len == 4) {
CopyMem (op->data, &Private->RenewTime, 4);
}
}
efi_status = find_opt (&This->Data->AckNak, DHCP4_REBINDING_TIME, 0, &op);
if (!EFI_ERROR (efi_status)) {
if (op->len == 4) {
CopyMem (op->data, &Private->RebindTime, 4);
}
}
Private->callback = NULL;
return efi_status;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Renew (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout
)
{
return renew_rebind (This, seconds_timeout, TRUE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Rebind (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout
)
{
return renew_rebind (This, seconds_timeout, FALSE);
}
/* eof - PxeDhcp4RenewRebind.c */

View File

@@ -0,0 +1,196 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4Run.c
Abstract:
Simplified entry point for starting basic PxeDhcp4 client operation.
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Run (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN OPTIONAL UINTN OpLen,
IN OPTIONAL VOID *OpList
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
DHCP4_PACKET *offer_list;
EFI_STATUS efi_status;
EFI_IP_ADDRESS zero_ip;
UINTN offers;
UINTN timeout;
UINTN n;
UINT16 seconds;
//
// Validate parameters.
//
if (This == NULL || (OpLen != 0 && OpList == NULL) || (OpLen == 0 && OpList != NULL)) {
return EFI_INVALID_PARAMETER;
}
for (n = 0; n < OpLen;) {
switch (((UINT8 *) OpList)[n]) {
case DHCP4_PAD:
++n;
continue;
case DHCP4_END:
++n;
break;
default:
n += 2 + ((UINT8 *) OpList)[n + 1];
continue;
}
break;
}
if (n != OpLen) {
return EFI_INVALID_PARAMETER;
}
//
// Get pointer to instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Initialize DHCP discover packet.
//
efi_status = PxeDhcp4Setup (This, NULL);
if (EFI_ERROR (efi_status)) {
return efi_status;
}
for (n = 0; n < OpLen;) {
switch (((UINT8 *) OpList)[n]) {
case DHCP4_PAD:
++n;
continue;
case DHCP4_END:
++n;
break;
default:
efi_status = add_opt (
&This->Data->Discover,
(DHCP4_OP *) &(((UINT8 *) OpList)[n])
);
if (EFI_ERROR (efi_status)) {
return efi_status;
}
n += 2 + ((UINT8 *) OpList)[n + 1];
continue;
}
break;
}
//
// Basic DHCP D.O.R.A.
// 1, 2, 4, 8, 16 & 32 second timeouts.
// Callback routine can be used to break out earlier.
//
ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));
for (timeout = 1;;) {
//
// Broadcast DHCP discover and wait for DHCP offers.
//
efi_status = PxeDhcp4Init (This, timeout, &offers, &offer_list);
switch (efi_status) {
case EFI_NO_RESPONSE:
case EFI_TIMEOUT:
case EFI_SUCCESS:
break;
case EFI_ABORTED:
default:
return efi_status;
}
//
// Try to select from each DHCP or BOOTP offer.
//
for (n = 0; n < offers; ++n) {
//
// Ignore proxyDHCP offers.
//
if (!CompareMem (&offer_list[n].dhcp4.yiaddr, &zero_ip, 4)) {
continue;
}
//
// Issue DHCP Request and wait for DHCP Ack/Nak.
//
efi_status = PxeDhcp4Select (
This,
timeout,
&offer_list[n]
);
if (EFI_ERROR (efi_status)) {
continue;
}
//
// Exit when we have got our DHCP Ack.
//
if (This->Data->IsAck) {
return EFI_SUCCESS;
}
}
//
// No DHCP Acks. Release DHCP Offer list storage.
//
if (offer_list != NULL) {
gBS->FreePool (offer_list);
offer_list = NULL;
}
//
// Try again until we have used up >= DHCP4_MAX_SECONDS.
//
if ((timeout <<= 1) > DHCP4_MAX_SECONDS) {
if (!EFI_ERROR (efi_status)) {
efi_status = EFI_TIMEOUT;
}
return efi_status;
}
//
// Next timeout value.
//
CopyMem (&seconds, &This->Data->Discover.dhcp4.secs, 2);
seconds = htons (htons (seconds) + timeout);
CopyMem (&This->Data->Discover.dhcp4.secs, &seconds, 2);
}
}
/* eof - PxeDhcp4Run.c */

View File

@@ -0,0 +1,268 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PxeDhcp4Setup.c
Abstract:
--*/
#include "PxeDhcp4.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Setup (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN EFI_PXE_DHCP4_DATA *Data
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
DHCP4_HEADER *Packet;
EFI_STATUS EfiStatus;
UINT8 *OpLen;
UINT8 *OpPtr;
//
// Return error if parameters are invalid.
//
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (This->Data != NULL) {
return EFI_ALREADY_STARTED;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Check contents of provided Data structure.
//
if (Data != NULL) {
//
// Do protocol state checks first.
//
if (Data->SelectCompleted) {
if (!Data->InitCompleted || !Data->SetupCompleted) {
return EFI_INVALID_PARAMETER;
}
if (Data->IsBootp && !Data->IsAck) {
return EFI_INVALID_PARAMETER;
}
} else if (Data->InitCompleted) {
if (!Data->SetupCompleted || Data->IsBootp || Data->IsAck) {
return EFI_INVALID_PARAMETER;
}
} else if (Data->SetupCompleted) {
if (Data->IsBootp || Data->IsAck) {
return EFI_INVALID_PARAMETER;
}
}
//
// Do packet content checks.
//
if (Data->SetupCompleted) {
//
// %%TBD - check discover packet
//
}
if (Data->SelectCompleted) {
if (Data->IsBootp) {
//
// %%TBD - check offer packet
//
if (CompareMem (
&Data->Discover,
&Data->Request,
sizeof (DHCP4_PACKET)
)) {
return EFI_INVALID_PARAMETER;
}
if (CompareMem (
&Data->Offer,
&Data->AckNak,
sizeof (DHCP4_PACKET)
)) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// %%TBD - check offer, request & acknak packets
//
}
}
}
//
// Allocate data structure. Return error
// if there is not enough available memory.
//
EfiStatus = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_PXE_DHCP4_DATA),
(VOID **) &This->Data
);
if (EFI_ERROR (EfiStatus)) {
This->Data = NULL;
return EfiStatus;
}
if (This->Data == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Start PxeBc because we want to use its UdpWrite, UdpRead and
// SetFilter calls.
//
EfiStatus = Private->PxeBc->Start (Private->PxeBc, FALSE);
if (EFI_ERROR (EfiStatus)) {
if (EfiStatus != EFI_ALREADY_STARTED) {
gBS->FreePool (This->Data);
This->Data = NULL;
Private->PxeBc->Stop (Private->PxeBc);
return EfiStatus;
}
Private->StopPxeBc = FALSE;
} else {
Private->StopPxeBc = TRUE;
}
//
// Use new data.
//
if (Data != NULL) {
CopyMem (This->Data, Data, sizeof (EFI_PXE_DHCP4_DATA));
return EFI_SUCCESS;
}
//
// Initialize new public data structure.
//
ZeroMem (This->Data, sizeof (EFI_PXE_DHCP4_DATA));
//
// Fill in default DHCP discover packet.
// Check for MAC addresses of strange lengths, just in case.
//
Packet = &This->Data->Discover.dhcp4;
Packet->op = BOOTP_REQUEST;
Packet->htype = Private->Snp->Mode->IfType;
if (Private->Snp->Mode->HwAddressSize > 16) {
Packet->hlen = 16;
} else {
Packet->hlen = (UINT8) Private->Snp->Mode->HwAddressSize;
}
Packet->hops = 0; /* Set to zero per RFC 2131. */
if (Packet->hlen < sizeof Packet->xid) {
if (Packet->hlen != 0) {
CopyMem (
&Packet->xid,
&Private->Snp->Mode->CurrentAddress,
Packet->hlen
);
}
} else {
CopyMem (
&Packet->xid,
&Private->Snp->Mode->CurrentAddress.Addr[Packet->hlen - sizeof Packet->xid],
sizeof Packet->xid
);
}
//
// %%TBD - xid should be randomized
//
Packet->secs = htons (DHCP4_INITIAL_SECONDS);
Packet->flags = htons (DHCP4_BROADCAST_FLAG);
if (Packet->hlen != 0) {
CopyMem (Packet->chaddr, &Private->Snp->Mode->CurrentAddress, Packet->hlen);
}
Packet->magik = htonl (DHCP4_MAGIK_NUMBER);
OpPtr = Packet->options;
*OpPtr++ = DHCP4_MESSAGE_TYPE;
*OpPtr++ = 1;
*OpPtr++ = DHCP4_MESSAGE_TYPE_DISCOVER;
*OpPtr++ = DHCP4_MAX_MESSAGE_SIZE;
*OpPtr++ = 2;
*OpPtr++ = (UINT8) ((DHCP4_DEFAULT_MAX_MESSAGE_SIZE >> 8) & 0xFF);
*OpPtr++ = (UINT8) (DHCP4_DEFAULT_MAX_MESSAGE_SIZE & 0xFF);
*OpPtr++ = DHCP4_PARAMETER_REQUEST_LIST;
OpLen = OpPtr;
*OpPtr++ = 0;
*OpPtr++ = DHCP4_SUBNET_MASK;
*OpPtr++ = DHCP4_TIME_OFFSET;
*OpPtr++ = DHCP4_ROUTER_LIST;
*OpPtr++ = DHCP4_TIME_SERVERS;
*OpPtr++ = DHCP4_NAME_SERVERS;
*OpPtr++ = DHCP4_DNS_SERVERS;
*OpPtr++ = DHCP4_HOST_NAME;
*OpPtr++ = DHCP4_BOOT_FILE_SIZE;
*OpPtr++ = DHCP4_MESSAGE_TYPE;
*OpPtr++ = DHCP4_DOMAIN_NAME;
*OpPtr++ = DHCP4_ROOT_PATH;
*OpPtr++ = DHCP4_EXTENSION_PATH;
*OpPtr++ = DHCP4_MAX_DATAGRAM_SIZE;
*OpPtr++ = DHCP4_DEFAULT_TTL;
*OpPtr++ = DHCP4_BROADCAST_ADDRESS;
*OpPtr++ = DHCP4_NIS_DOMAIN_NAME;
*OpPtr++ = DHCP4_NIS_SERVERS;
*OpPtr++ = DHCP4_NTP_SERVERS;
*OpPtr++ = DHCP4_VENDOR_SPECIFIC;
*OpPtr++ = DHCP4_REQUESTED_IP_ADDRESS;
*OpPtr++ = DHCP4_LEASE_TIME;
*OpPtr++ = DHCP4_SERVER_IDENTIFIER;
*OpPtr++ = DHCP4_RENEWAL_TIME;
*OpPtr++ = DHCP4_REBINDING_TIME;
*OpPtr++ = DHCP4_CLASS_IDENTIFIER;
*OpPtr++ = DHCP4_TFTP_SERVER_NAME;
*OpPtr++ = DHCP4_BOOTFILE;
*OpPtr++ = 128;
*OpPtr++ = 129;
*OpPtr++ = 130;
*OpPtr++ = 131;
*OpPtr++ = 132;
*OpPtr++ = 133;
*OpPtr++ = 134;
*OpPtr++ = 135;
*OpLen = (UINT8) ((OpPtr - OpLen) - 1);
*OpPtr++ = DHCP4_END;
This->Data->SetupCompleted = TRUE;
return EFI_SUCCESS;
}
/* eof - PxeDhcp4Setup.c */

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
<project basedir="." default="Dhcp4"><!--Apply external ANT tasks-->
<taskdef resource="GenBuild.tasks"/>
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<property environment="env"/>
<property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
<import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
<property name="MODULE_RELATIVE_PATH" value="Universal\Network\PxeDhcp4\Dxe"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="Dhcp4">
<GenBuild baseName="Dhcp4" mbdFilename="${MODULE_DIR}\Dhcp4.mbd" msaFilename="${MODULE_DIR}\Dhcp4.msa"/>
</target>
<target depends="Dhcp4_clean" name="clean"/>
<target depends="Dhcp4_cleanall" name="cleanall"/>
<target name="Dhcp4_clean">
<OutputDirSetup baseName="Dhcp4" mbdFilename="${MODULE_DIR}\Dhcp4.mbd" msaFilename="${MODULE_DIR}\Dhcp4.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\Dhcp4_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\Dhcp4_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="Dhcp4_cleanall">
<OutputDirSetup baseName="Dhcp4" mbdFilename="${MODULE_DIR}\Dhcp4.mbd" msaFilename="${MODULE_DIR}\Dhcp4.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\Dhcp4_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\Dhcp4_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**Dhcp4*"/>
</delete>
</target>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,160 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
--*/
#include "Snp.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName = {
SimpleNetworkComponentNameGetDriverName,
SimpleNetworkComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mSimpleNetworkDriverNameTable[] = {
{
"eng",
(CHAR16 *) L"Simple Network Protocol Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gSimpleNetworkComponentName.SupportedLanguages,
mSimpleNetworkDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MbdHeader>
<BaseName>SNP</BaseName>
<Guid>A2f436EA-A127-4EF8-957C-8048606FF670</Guid>
<Version>0</Version>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Created>2006-03-12 17:09</Created>
<Modified>2006-03-19 15:19</Modified>
</MbdHeader>
<Libraries>
<Library>UefiBootServicesTableLib</Library>
<Library>BaseMemoryLib</Library>
<Library>UefiLib</Library>
<Library>UefiDriverEntryPoint</Library>
<Library>UefiDriverModelLib</Library>
<Library>DxeReportStatusCodeLib</Library>
<Library>BaseDebugLibReportStatusCode</Library>
<Library>BaseLib</Library>
<Library>DxeMemoryAllocationLib</Library>
</Libraries>
</ModuleBuildDescription>

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-->
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
<MsaHeader>
<BaseName>SNP</BaseName>
<ModuleType>UEFI_DRIVER</ModuleType>
<ComponentType>BS_DRIVER</ComponentType>
<Guid>A2f436EA-A127-4EF8-957C-8048606FF670</Guid>
<Version>0</Version>
<Abstract>Component description file for DiskIo module.</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
<License>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
</License>
<Specification>0</Specification>
<Created>2006-03-12 17:09</Created>
<Updated>2006-03-19 15:19</Updated>
</MsaHeader>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>callback.c</Filename>
<Filename>get_status.c</Filename>
<Filename>initialize.c</Filename>
<Filename>mcast_ip_to_mac.c</Filename>
<Filename>nvdata.c</Filename>
<Filename>receive.c</Filename>
<Filename>receive_filters.c</Filename>
<Filename>reset.c</Filename>
<Filename>shutdown.c</Filename>
<Filename>snp.c</Filename>
<Filename>snp.h</Filename>
<Filename>start.c</Filename>
<Filename>station_address.c</Filename>
<Filename>statistics.c</Filename>
<Filename>stop.c</Filename>
<Filename>transmit.c</Filename>
<Filename>WaitForPacket.c</Filename>
<Filename>ComponentName.c</Filename>
</SourceFiles>
<Includes>
<PackageName>MdePkg</PackageName>
<PackageName>EdkModulePkg</PackageName>
</Includes>
<Protocols>
<Protocol Usage="BY_START">SimpleNetwork</Protocol>
<Protocol Usage="TO_START">PciIo</Protocol>
<Protocol Usage="TO_START">DevicePath</Protocol>
<Protocol Usage="SOMETIMES_CONSUMED">NetworkInterfaceIdentifier</Protocol>
<Protocol Usage="TO_START">NetworkInterfaceIdentifier2</Protocol>
</Protocols>
<Externs>
<Extern>
<ModuleEntryPoint></ModuleEntryPoint>
<ModuleUnloadImage></ModuleUnloadImage>
</Extern>
<Extern>
<DriverBinding>mSimpleNetworkDriverBinding</DriverBinding>
<ComponentName>gSimpleNetworkComponentName</ComponentName>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,100 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
WaitForPacket.c
Abstract:
Event handler to check for available packet.
--*/
#include "snp.h"
VOID
EFIAPI
SnpWaitForPacketNotify (
EFI_EVENT Event,
VOID *SnpPtr
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
PXE_DB_GET_STATUS PxeDbGetStatus;
//
// Do nothing if either parameter is a NULL pointer.
//
if (Event == NULL || SnpPtr == NULL) {
return ;
}
//
// Do nothing if the SNP interface is not initialized.
//
switch (((SNP_DRIVER *) SnpPtr)->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
case EfiSimpleNetworkStarted:
default:
return ;
}
//
// Fill in CDB for UNDI GetStatus().
//
((SNP_DRIVER *) SnpPtr)->cdb.OpCode = PXE_OPCODE_GET_STATUS;
((SNP_DRIVER *) SnpPtr)->cdb.OpFlags = 0;
((SNP_DRIVER *) SnpPtr)->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
((SNP_DRIVER *) SnpPtr)->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
((SNP_DRIVER *) SnpPtr)->cdb.DBsize = sizeof (UINT32) * 2;
((SNP_DRIVER *) SnpPtr)->cdb.DBaddr = (UINT64) (UINTN) (((SNP_DRIVER *) SnpPtr)->db);
((SNP_DRIVER *) SnpPtr)->cdb.StatCode = PXE_STATCODE_INITIALIZE;
((SNP_DRIVER *) SnpPtr)->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
((SNP_DRIVER *) SnpPtr)->cdb.IFnum = ((SNP_DRIVER *) SnpPtr)->if_num;
((SNP_DRIVER *) SnpPtr)->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Clear contents of DB buffer.
//
ZeroMem (((SNP_DRIVER *) SnpPtr)->db, sizeof (UINT32) * 2);
//
// Issue UNDI command and check result.
//
(*((SNP_DRIVER *) SnpPtr)->issue_undi32_command) ((UINT64) (UINTN) &((SNP_DRIVER *) SnpPtr)->cdb);
if (((SNP_DRIVER *) SnpPtr)->cdb.StatCode != EFI_SUCCESS) {
return ;
}
//
// We might have a packet. Check the receive length and signal
// the event if the length is not zero.
//
CopyMem (
&PxeDbGetStatus,
((SNP_DRIVER *) SnpPtr)->db,
sizeof (UINT32) * 2
);
if (PxeDbGetStatus.RxFrameLen != 0) {
gBS->SignalEvent (Event);
}
}
/* eof - WaitForPacket.c */

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
<project basedir="." default="SNP"><!--Apply external ANT tasks-->
<taskdef resource="GenBuild.tasks"/>
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<property environment="env"/>
<property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
<import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
<property name="MODULE_RELATIVE_PATH" value="Universal\Network\Snp32_64\Dxe"/>
<property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
<property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
<target name="SNP">
<GenBuild baseName="SNP" mbdFilename="${MODULE_DIR}\SNP.mbd" msaFilename="${MODULE_DIR}\SNP.msa"/>
</target>
<target depends="SNP_clean" name="clean"/>
<target depends="SNP_cleanall" name="cleanall"/>
<target name="SNP_clean">
<OutputDirSetup baseName="SNP" mbdFilename="${MODULE_DIR}\SNP.mbd" msaFilename="${MODULE_DIR}\SNP.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\SNP_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\SNP_build.xml" target="clean"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
</target>
<target name="SNP_cleanall">
<OutputDirSetup baseName="SNP" mbdFilename="${MODULE_DIR}\SNP.mbd" msaFilename="${MODULE_DIR}\SNP.msa"/>
<if>
<available file="${DEST_DIR_OUTPUT}\SNP_build.xml"/>
<then>
<ant antfile="${DEST_DIR_OUTPUT}\SNP_build.xml" target="cleanall"/>
</then>
</if>
<delete dir="${DEST_DIR_OUTPUT}"/>
<delete dir="${DEST_DIR_DEBUG}"/>
<delete>
<fileset dir="${BIN_DIR}" includes="**SNP*"/>
</delete>
</target>
</project>

View File

@@ -0,0 +1,613 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
callback.c
Abstract:
This file contains two sets of callback routines for undi3.0 and undi3.1.
the callback routines for Undi3.1 have an extra parameter UniqueId which
stores the interface context for the NIC that snp is trying to talk..
--*/
#include "snp.h"
//
// Global variables
// these 2 global variables are used only for 3.0 undi. we could not place
// them in the snp structure because we will not know which snp structure
// in the callback context!
//
STATIC BOOLEAN mInitializeLock = TRUE;
STATIC EFI_LOCK mLock;
//
// End Global variables
//
extern EFI_PCI_IO_PROTOCOL *mPciIoFncs;
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with a virtual or CPU address that SNP provided
to convert it to a physical or device address. Since EFI uses the identical
mapping, this routine returns the physical address same as the virtual address
for most of the addresses. an address above 4GB cannot generally be used as a
device address, it needs to be mapped to a lower physical address. This routine
does not call the map routine itself, but it assumes that the mapping was done
at the time of providing the address to UNDI. This routine just looks up the
address in a map table (which is the v2p structure chain)
Arguments:
CpuAddr - virtual address of a buffer
DeviceAddrPtr - pointer to the physical address
Returns:
void - The DeviceAddrPtr will contain 0 in case of any error
--*/
{
struct s_v2p *v2p;
//
// Do nothing if virtual address is zero or physical pointer is NULL.
// No need to map if the virtual address is within 4GB limit since
// EFI uses identical mapping
//
if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) {
DEBUG ((EFI_D_ERROR, "\nv2p: Null virtual address or physical pointer.\n"));
return ;
}
if (CpuAddr < FOUR_GIGABYTES) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
return ;
}
//
// SNP creates a vaddr tp paddr mapping at the time of calling undi with any
// big address, this callback routine just looks up in the v2p list and
// returns the physical address for any given virtual address.
//
if (find_v2p (&v2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
} else {
*(UINT64 *) (UINTN) DeviceAddrPtr = v2p->paddr;
}
}
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
//
// tcpip was calling snp at tpl_notify and if we acquire a lock that was
// created at a lower level (TPL_CALLBACK) it gives an assert!
//
if (mInitializeLock) {
EfiInitializeLock (&mLock, EFI_TPL_NOTIFY);
mInitializeLock = FALSE;
}
if (Enable != 0) {
EfiAcquireLock (&mLock);
} else {
EfiReleaseLock (&mLock);
}
}
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 Address,
IN OUT UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI. This is not currently being used by UNDI3.0
because Undi3.0 uses io/mem offsets relative to the beginning of the device
io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
start of the device's io/mem addresses. Since SNP cannot retrive the context
of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
that NIC and uses one global IO functions structure, this does not work.
This however works fine for EFI1.0 Undis because they use absolute addresses
for io/mem access.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
EFI_PCI_IO_PROTOCOL_WIDTH Width;
switch (NumBytes) {
case 2:
Width = 1;
break;
case 4:
Width = 2;
break;
case 8:
Width = 3;
break;
default:
Width = 0;
}
switch (ReadOrWrite) {
case PXE_IO_READ:
mPciIoFncs->Io.Read (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
mPciIoFncs->Io.Write (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
mPciIoFncs->Mem.Read (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
mPciIoFncs->Mem.Write (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
//
// New callbacks for 3.1:
// there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses
// the MemMap call to map the required address by itself!
//
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI3.1 at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
SNP_DRIVER *snp;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
//
// tcpip was calling snp at tpl_notify and when we acquire a lock that was
// created at a lower level (TPL_CALLBACK) it gives an assert!
//
if (Enable != 0) {
EfiAcquireLock (&snp->lock);
} else {
EfiReleaseLock (&snp->lock);
}
}
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
/*
* IO routine for UNDI start CPB.
*/
VOID
snp_undi32_callback_memio (
UINT64 UniqueId,
UINT8 ReadOrWrite,
UINT8 NumBytes,
UINT64 Address,
UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI3.1.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
SNP_DRIVER *snp;
EFI_PCI_IO_PROTOCOL_WIDTH Width;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
Width = 0;
switch (NumBytes) {
case 2:
Width = 1;
break;
case 4:
Width = 2;
break;
case 8:
Width = 3;
break;
}
switch (ReadOrWrite) {
case PXE_IO_READ:
snp->IoFncs->Io.Read (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
snp->IoFncs->Io.Write (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
snp->IoFncs->Mem.Read (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
snp->IoFncs->Mem.Write (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it has to map a CPU address to a device
address.
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address to be mapped!
NumBytes - size of memory to be mapped
Direction - direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddrPtr - pointer to return the mapped device address
Returns:
None
--*/
{
EFI_PHYSICAL_ADDRESS *DevAddrPtr;
EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;
UINTN BuffSize;
SNP_DRIVER *snp;
UINTN Index;
EFI_STATUS Status;
BuffSize = (UINTN) NumBytes;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;
if (CpuAddr == 0) {
*DevAddrPtr = 0;
return ;
}
switch (Direction) {
case TO_AND_FROM_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;
break;
case FROM_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterWrite;
break;
case TO_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterRead;
break;
default:
*DevAddrPtr = 0;
//
// any non zero indicates error!
//
return ;
}
//
// find an unused map_list entry
//
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
if (snp->map_list[Index].virt == 0) {
break;
}
}
if (Index >= MAX_MAP_LENGTH) {
SNP_PRINT (L"SNP maplist is FULL\n");
*DevAddrPtr = 0;
return ;
}
snp->map_list[Index].virt = (EFI_PHYSICAL_ADDRESS) CpuAddr;
Status = snp->IoFncs->Map (
snp->IoFncs,
DirectionFlag,
(VOID *) (UINTN) CpuAddr,
&BuffSize,
DevAddrPtr,
&(snp->map_list[Index].map_cookie)
);
if (Status != EFI_SUCCESS) {
*DevAddrPtr = 0;
snp->map_list[Index].virt = 0;
}
return ;
}
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to unmap an address that was previously
mapped using map callback
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
SNP_DRIVER *snp;
UINT16 Index;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
if (snp->map_list[Index].virt == CpuAddr) {
break;
}
}
if (Index >= MAX_MAP_LENGTH)
{
#if SNP_DEBUG
Print (L"SNP could not find a mapping, failed to unmap.\n");
#endif
return ;
}
snp->IoFncs->Unmap (snp->IoFncs, snp->map_list[Index].map_cookie);
snp->map_list[Index].virt = 0;
snp->map_list[Index].map_cookie = NULL;
return ;
}
VOID
snp_undi32_callback_sync (
UINT64 UniqueId,
UINT64 CpuAddr,
UINT32 NumBytes,
UINT32 Direction,
UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants synchronize the virtual buffer contents
with the mapped buffer contents. The virtual and mapped buffers need not
correspond to the same physical memory (especially if the virtual address is
> 4GB). Depending on the direction for which the buffer is mapped, undi will
need to synchronize their contents whenever it writes to/reads from the buffer
using either the cpu address or the device address.
EFI does not provide a sync call, since virt=physical, we sould just do
the synchronization ourself here!
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {
return ;
}
switch (Direction) {
case FROM_DEVICE:
CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);
break;
case TO_DEVICE:
CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);
break;
}
return ;
}

View File

@@ -0,0 +1,193 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
get_status.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_getstatus (
SNP_DRIVER *snp,
UINT32 *InterruptStatusPtr,
VOID **TransmitBufferListPtr
)
/*++
Routine Description:
this routine calls undi to get the status of the interrupts, get the list of
transmit buffers that completed transmitting!
Arguments:
snp - pointer to snp driver structure
InterruptStatusPtr - a non null pointer gets the interrupt status
TransmitBufferListPtrs - a non null ointer gets the list of pointers of previously
transmitted buffers whose transmission was completed
asynchrnously.
Returns:
--*/
{
PXE_DB_GET_STATUS *db;
UINT16 InterruptFlags;
UINT64 TempData;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_GET_STATUS;
snp->cdb.OpFlags = 0;
if (TransmitBufferListPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;
}
if (InterruptStatusPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;
}
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
//
// size DB for return of one buffer
//
snp->cdb.DBsize = (UINT16) (((UINT16) (sizeof (PXE_DB_GET_STATUS)) - (UINT16) (sizeof db->TxBuffer)) + (UINT16) (sizeof db->TxBuffer[0]));
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.get_status() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
DEBUG (
(EFI_D_NET,
"\nsnp->undi.get_status() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// report the values back..
//
if (InterruptStatusPtr != NULL) {
InterruptFlags = (UINT16) (snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK);
*InterruptStatusPtr = 0;
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
}
if (TransmitBufferListPtr != NULL) {
*TransmitBufferListPtr =
(
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) ||
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY)
) ? 0 : (VOID *) (UINTN) db->TxBuffer[0];
TempData = (UINT64) (UINTN) (*TransmitBufferListPtr);
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
del_v2p ((VOID *) (UINTN) (db->TxBuffer[0]));
}
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *InterruptStatusPtr OPTIONAL,
OUT VOID **TransmitBufferListPtr OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for getting the status
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_getstatus routine to actually get the undi status
Arguments:
this - context pointer
InterruptStatusPtr - a non null pointer gets the interrupt status
TransmitBufferListPtrs - a non null ointer gets the list of pointers of previously
transmitted buffers whose transmission was completed
asynchrnously.
Returns:
--*/
{
SNP_DRIVER *snp;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
if (InterruptStatusPtr == NULL && TransmitBufferListPtr == NULL) {
return EFI_INVALID_PARAMETER;
}
return pxe_getstatus (snp, InterruptStatusPtr, TransmitBufferListPtr);
}

View File

@@ -0,0 +1,244 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
initialize.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
--*/
#include "snp.h"
VOID
EFIAPI
SnpWaitForPacketNotify (
IN EFI_EVENT Event,
IN VOID *SnpPtr
);
EFI_STATUS
pxe_init (
SNP_DRIVER *snp,
UINT16 CableDetectFlag
)
/*++
Routine Description:
this routine calls undi to initialize the interface.
Arguments:
snp - pointer to snp driver structure
CableDetectFlag - Do/don't detect the cable (depending on what undi supports)
Returns:
--*/
{
PXE_CPB_INITIALIZE *cpb;
VOID *addr;
EFI_STATUS Status;
cpb = snp->cpb;
if (snp->tx_rx_bufsize != 0) {
Status = snp->IoFncs->AllocateBuffer (
snp->IoFncs,
AllocateAnyPages,
EfiBootServicesData,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
&addr,
0
);
if (Status != EFI_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->pxe_init() AllocateBuffer %xh (%r)\n",
Status,
Status)
);
return Status;
}
ASSERT (addr);
snp->tx_rx_buffer = addr;
}
cpb->MemoryAddr = (UINT64) (UINTN) snp->tx_rx_buffer;
cpb->MemoryLength = snp->tx_rx_bufsize;
//
// let UNDI decide/detect these values
//
cpb->LinkSpeed = 0;
cpb->TxBufCnt = 0;
cpb->TxBufSize = 0;
cpb->RxBufCnt = 0;
cpb->RxBufSize = 0;
cpb->DuplexMode = PXE_DUPLEX_DEFAULT;
cpb->LoopBackMode = LOOPBACK_NORMAL;
snp->cdb.OpCode = PXE_OPCODE_INITIALIZE;
snp->cdb.OpFlags = CableDetectFlag;
snp->cdb.CPBsize = sizeof (PXE_CPB_INITIALIZE);
snp->cdb.DBsize = sizeof (PXE_DB_INITIALIZE);
snp->cdb.CPBaddr = (UINT64) (UINTN) snp->cpb;
snp->cdb.DBaddr = (UINT64) (UINTN) snp->db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.initialize() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode == PXE_STATCODE_SUCCESS) {
snp->mode.State = EfiSimpleNetworkInitialized;
Status = EFI_SUCCESS;
} else {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi.initialize() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
if (snp->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
Status = EFI_DEVICE_ERROR;
}
return Status;
}
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for initializing the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_initialize routine to actually do the undi initialization
Arguments:
this - context pointer
extra_rx_buffer_size - optional parameter, indicates extra space for rx_buffers
extra_tx_buffer_size - optional parameter, indicates extra space for tx_buffers
Returns:
--*/
{
EFI_STATUS EfiStatus;
SNP_DRIVER *snp;
//
//
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_INVALID_PARAMETER;
}
//
//
//
switch (snp->mode.State) {
case EfiSimpleNetworkStarted:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkInitialized:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
//
//
EfiStatus = gBS->CreateEvent (
EFI_EVENT_NOTIFY_WAIT,
EFI_TPL_NOTIFY,
&SnpWaitForPacketNotify,
snp,
&snp->snp.WaitForPacket
);
if (EFI_ERROR (EfiStatus)) {
snp->snp.WaitForPacket = NULL;
return EFI_DEVICE_ERROR;
}
//
//
//
snp->mode.MCastFilterCount = 0;
snp->mode.ReceiveFilterSetting = 0;
ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter);
CopyMem (
&snp->mode.CurrentAddress,
&snp->mode.PermanentAddress,
sizeof (EFI_MAC_ADDRESS)
);
//
// Compute tx/rx buffer sizes based on UNDI init info and parameters.
//
snp->tx_rx_bufsize = (UINT32) (snp->init_info.MemoryRequired + extra_rx_buffer_size + extra_tx_buffer_size);
if (snp->mode.MediaPresentSupported) {
if (pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {
snp->mode.MediaPresent = TRUE;
return EFI_SUCCESS;
}
}
snp->mode.MediaPresent = FALSE;
EfiStatus = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
if (EFI_ERROR (EfiStatus)) {
gBS->CloseEvent (snp->snp.WaitForPacket);
}
return EfiStatus;
}

View File

@@ -0,0 +1,167 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
mcast_ip_to_mac.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_ip2mac (
IN SNP_DRIVER *snp,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
IN OUT EFI_MAC_ADDRESS *MAC
)
/*++
Routine Description:
this routine calls undi to convert an multicast IP address to a MAC address
Arguments:
snp - pointer to snp driver structure
IPv6 - flag to indicate if this is an ipv6 address
IP - multicast IP address
MAC - pointer to hold the return MAC address
Returns:
--*/
{
PXE_CPB_MCAST_IP_TO_MAC *cpb;
PXE_DB_MCAST_IP_TO_MAC *db;
cpb = snp->cpb;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_MCAST_IP_TO_MAC;
snp->cdb.OpFlags = (UINT16) (IPv6 ? PXE_OPFLAGS_MCAST_IPV6_TO_MAC : PXE_OPFLAGS_MCAST_IPV4_TO_MAC);
snp->cdb.CPBsize = sizeof (PXE_CPB_MCAST_IP_TO_MAC);
snp->cdb.DBsize = sizeof (PXE_DB_MCAST_IP_TO_MAC);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
CopyMem (&cpb->IP, IP, sizeof (PXE_IP_ADDR));
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.mcast_ip_to_mac() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_INVALID_CPB:
return EFI_INVALID_PARAMETER;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_UNSUPPORTED;
default:
//
// UNDI command failed. Return EFI_DEVICE_ERROR
// to caller.
//
DEBUG (
(EFI_D_NET,
"\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
CopyMem (MAC, &db->MAC, sizeof (PXE_MAC_ADDR));
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
OUT EFI_MAC_ADDRESS *MAC
)
/*++
Routine Description:
This is the SNP interface routine for converting a multicast IP address to
a MAC address.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ip2mac routine to actually do the conversion
Arguments:
this - context pointer
IPv6 - flag to indicate if this is an ipv6 address
IP - multicast IP address
MAC - pointer to hold the return MAC address
Returns:
--*/
{
SNP_DRIVER *snp;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
if (IP == NULL || MAC == NULL) {
return EFI_INVALID_PARAMETER;
}
return pxe_ip2mac (snp, IPv6, IP, MAC);
}

View File

@@ -0,0 +1,183 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
nvdata.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_nvdata_read (
IN SNP_DRIVER *snp,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
/*++
Routine Description:
This routine calls Undi to read the desired number of eeprom bytes.
Arguments:
snp - pointer to the snp driver structure
RegOffset - eeprom register value relative to the base address
NumBytes - number of bytes to read
BufferPtr - pointer where to read into
Returns:
--*/
{
PXE_DB_NVDATA *db;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_NVDATA;
snp->cdb.OpFlags = PXE_OPFLAGS_NVDATA_READ;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBsize = sizeof (PXE_DB_NVDATA);
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.nvdata () "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.nvdata() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_UNSUPPORTED;
default:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.nvdata() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
CopyMem (BufferPtr, db->Data.Byte + RegOffset, NumBytes);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ReadOrWrite,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
/*++
Routine Description:
This is an interface call provided by SNP.
It does the basic checking on the input parameters and retrieves snp structure
and then calls the read_nvdata() call which does the actual reading
Arguments:
this - context pointer
ReadOrWrite - true for reading and false for writing
RegOffset - eeprom register relative to the base
NumBytes - how many bytes to read
BufferPtr - address of memory to read into
Returns:
--*/
{
SNP_DRIVER *snp;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
// Return error if non-volatile memory variables are not valid.
//
if (snp->mode.NvRamSize == 0 || snp->mode.NvRamAccessSize == 0) {
return EFI_UNSUPPORTED;
}
//
// Check for invalid parameter combinations.
//
if ((NumBytes == 0) ||
(BufferPtr == NULL) ||
(RegOffset >= snp->mode.NvRamSize) ||
(RegOffset + NumBytes > snp->mode.NvRamSize) ||
(NumBytes % snp->mode.NvRamAccessSize != 0) ||
(RegOffset % snp->mode.NvRamAccessSize != 0)
) {
return EFI_INVALID_PARAMETER;
}
//
// check the implementation flags of undi if we can write the nvdata!
//
if (!ReadOrWrite) {
return EFI_UNSUPPORTED;
} else {
return pxe_nvdata_read (snp, RegOffset, NumBytes, BufferPtr);
}
}

View File

@@ -0,0 +1,255 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
receive.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_receive (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN *BuffSizePtr,
UINTN *HeaderSizePtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
EFI_MAC_ADDRESS *DestinationAddrPtr,
UINT16 *ProtocolPtr
)
/*++
Routine Description:
this routine calls undi to receive a packet and fills in the data in the
input pointers!
Arguments:
snp - pointer to snp driver structure
BufferPtr - pointer to the memory for the received data
BuffSizePtr - is a pointer to the length of the buffer on entry and contains
the length of the received data on return
HeaderSizePtr - pointer to the header portion of the data received.
SourceAddrPtr - optional parameter, is a pointer to contain the source
ethernet address on return
DestinationAddrPtr - optional parameter, is a pointer to contain the destination
ethernet address on return
ProtocolPtr - optional parameter, is a pointer to contain the protocol type
from the ethernet header on return
Returns:
--*/
{
PXE_CPB_RECEIVE *cpb;
PXE_DB_RECEIVE *db;
UINTN buf_size;
UINT64 TempData;
cpb = snp->cpb;
db = snp->db;
buf_size = *BuffSizePtr;
//
// IMPORTANT NOTE:
// In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
// DO NOT call the map function on the given buffer, instead use
// a global buffer. The reason is that UNDI3.0 has some unnecessary check of
// making sure that all the addresses (whether or not they will be given
// to the NIC ) supplied to it are below 4GB. It may or may not use
// the mapped address after all (like in case of CPB and DB)!
// Instead of using the global buffer whose address is allocated within the
// 2GB limit if I start mapping the given buffer we lose the data, here is
// why!!!
// if our address is > 4GB, the map call creates another buffer below 2GB and
// copies data to/from the original buffer to the mapped buffer either at
// map time or unmap time depending on the map direction.
// UNDI will not complain since we already mapped the buffer to be
// within the 2GB limit but will not use (I know undi) the mapped address
// since it does not give the user buffers to the NIC's receive unit,
// It just copies the received packet into the user buffer using the virtual
// (CPU) address rather than the mapped (device or physical) address.
// When the UNDI call returns, if we then unmap the buffer, we will lose
// the contents because unmap copies the contents of the mapped buffer into
// the original buffer (since the direction is FROM_DEVICE) !!!
//
// this is not a problem in Undi 3.1 because this undi uses it's map callback
// routine to map a cpu address to device address and it does it only if
// it is giving the address to the device and unmaps it before using the cpu
// address!
//
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
cpb->BufferAddr = (UINT64) (UINTN) snp->receive_buf;
cpb->BufferLen = (UINT32) (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
} else {
cpb->BufferAddr = (UINT64) (UINTN) BufferPtr;
cpb->BufferLen = (UINT32) *BuffSizePtr;
}
cpb->reserved = 0;
snp->cdb.OpCode = PXE_OPCODE_RECEIVE;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = sizeof (PXE_CPB_RECEIVE);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
snp->cdb.DBsize = sizeof (PXE_DB_RECEIVE);
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_INFO, "\nsnp->undi.receive () "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_NO_DATA:
DEBUG (
(EFI_D_INFO,
"\nsnp->undi.receive () %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_NOT_READY;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
*BuffSizePtr = db->FrameLen;
if (HeaderSizePtr != NULL) {
*HeaderSizePtr = db->MediaHeaderLen;
}
if (SourceAddrPtr != NULL) {
CopyMem (SourceAddrPtr, &db->SrcAddr, snp->mode.HwAddressSize);
}
if (DestinationAddrPtr != NULL) {
CopyMem (DestinationAddrPtr, &db->DestAddr, snp->mode.HwAddressSize);
}
if (ProtocolPtr != NULL) {
*ProtocolPtr = (UINT16) PXE_SWAP_UINT16 (db->Protocol); /* we need to do the byte swapping */
}
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
CopyMem (BufferPtr, snp->receive_buf, snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
}
return (*BuffSizePtr <= buf_size) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
}
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *HeaderSizePtr OPTIONAL,
IN OUT UINTN *BuffSizePtr,
OUT VOID *BufferPtr,
OUT EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
OUT EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
OUT UINT16 *ProtocolPtr OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for receiving network data.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_receive routine to actually do the receive!
Arguments:
this - context pointer
HeaderSizePtr - optional parameter and is a pointer to the header portion of
the data received.
BuffSizePtr - is a pointer to the length of the buffer on entry and contains
the length of the received data on return
BufferPtr - pointer to the memory for the received data
SourceAddrPtr - optional parameter, is a pointer to contain the source
ethernet address on return
DestinationAddrPtr - optional parameter, is a pointer to contain the destination
ethernet address on return
ProtocolPtr - optional parameter, is a pointer to contain the protocol type
from the ethernet header on return
Returns:
--*/
{
SNP_DRIVER *snp;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
if ((BuffSizePtr == NULL) || (BufferPtr == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (!snp->mode.ReceiveFilterSetting) {
return EFI_DEVICE_ERROR;
}
return pxe_receive (
snp,
BufferPtr,
BuffSizePtr,
HeaderSizePtr,
SourceAddrPtr,
DestinationAddrPtr,
ProtocolPtr
);
}

View File

@@ -0,0 +1,411 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
receive_filters.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_rcvfilter_enable (
SNP_DRIVER *snp,
UINT32 EnableFlags,
UINTN MCastAddressCount,
EFI_MAC_ADDRESS *MCastAddressList
)
/*++
Routine Description:
this routine calls undi to enable the receive filters.
Arguments:
snp - pointer to snp driver structure
EnableFlags - bit mask for enabling the receive filters
MCastAddressCount - multicast address count for a new multicast address list
MCastAddressList - list of new multicast addresses
Returns:
--*/
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
}
if (MCastAddressCount != 0) {
snp->cdb.CPBsize = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS));
snp->cdb.CPBaddr = (UINT64) (UINTN) snp->cpb;
CopyMem (snp->cpb, MCastAddressList, snp->cdb.CPBsize);
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_INVALID_CDB:
case PXE_STATCODE_INVALID_CPB:
case PXE_STATCODE_INVALID_PARAMETER:
return EFI_INVALID_PARAMETER;
case PXE_STATCODE_UNSUPPORTED:
return EFI_UNSUPPORTED;
}
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
pxe_rcvfilter_disable (
SNP_DRIVER *snp,
UINT32 DisableFlags,
BOOLEAN ResetMCastList
)
/*++
Routine Description:
this routine calls undi to disable the receive filters.
Arguments:
snp - pointer to snp driver structure
DisableFlags - bit mask for disabling the receive filters
ResetMCastList - boolean flag to reset/delete the multicast filter list
Returns:
--*/
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
snp->cdb.OpFlags = (UINT16) (DisableFlags ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED);
if (ResetMCastList) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
pxe_rcvfilter_read (
SNP_DRIVER *snp
)
/*++
Routine Description:
this routine calls undi to read the receive filters.
Arguments:
snp - pointer to snp driver structure
Returns:
--*/
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_READ;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = (UINT16) (snp->mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS));
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
if (snp->cdb.DBsize == 0) {
snp->cdb.DBaddr = (UINT64) NULL;
} else {
snp->cdb.DBaddr = (UINT64) (UINTN) snp->db;
ZeroMem (snp->db, snp->cdb.DBsize);
}
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
//
// Convert UNDI32 StatFlags to EFI SNP filter flags.
//
snp->mode.ReceiveFilterSetting = 0;
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
}
CopyMem (snp->mode.MCastFilter, snp->db, snp->cdb.DBsize);
//
// Count number of active entries in multicast filter list.
//
{
EFI_MAC_ADDRESS ZeroMacAddr;
SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0);
for (snp->mode.MCastFilterCount = 0;
snp->mode.MCastFilterCount < snp->mode.MaxMCastFilterCount;
snp->mode.MCastFilterCount++
) {
if (CompareMem (
&snp->mode.MCastFilter[snp->mode.MCastFilterCount],
&ZeroMacAddr,
sizeof ZeroMacAddr
) == 0) {
break;
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 EnableFlags,
IN UINT32 DisableFlags,
IN BOOLEAN ResetMCastList,
IN UINTN MCastAddressCount OPTIONAL,
IN EFI_MAC_ADDRESS * MCastAddressList OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for reading/enabling/disabling the
receive filters.
This routine basically retrieves snp structure, checks the SNP state and
checks the parameter validity, calls one of the above routines to actually
do the work
Arguments:
this - context pointer
EnableFlags - bit mask for enabling the receive filters
DisableFlags - bit mask for disabling the receive filters
ResetMCastList - boolean flag to reset/delete the multicast filter list
MCastAddressCount - multicast address count for a new multicast address list
MCastAddressList - list of new multicast addresses
Returns:
--*/
{
SNP_DRIVER *snp;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
// check if we are asked to enable or disable something that the UNDI
// does not even support!
//
if ((EnableFlags &~snp->mode.ReceiveFilterMask) != 0) {
return EFI_INVALID_PARAMETER;
}
if ((DisableFlags &~snp->mode.ReceiveFilterMask) != 0) {
return EFI_INVALID_PARAMETER;
}
if (ResetMCastList) {
DisableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & snp->mode.ReceiveFilterMask;
MCastAddressCount = 0;
MCastAddressList = NULL;
} else {
if (MCastAddressCount != 0) {
if (MCastAddressCount > snp->mode.MaxMCastFilterCount) {
return EFI_INVALID_PARAMETER;
}
if (MCastAddressList == NULL) {
return EFI_INVALID_PARAMETER;
}
}
}
if (EnableFlags == 0 && DisableFlags == 0 && !ResetMCastList && MCastAddressCount == 0) {
return EFI_SUCCESS;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastAddressCount == 0) {
return EFI_INVALID_PARAMETER;
}
if ((EnableFlags != 0) || (MCastAddressCount != 0)) {
Status = pxe_rcvfilter_enable (
snp,
EnableFlags,
MCastAddressCount,
MCastAddressList
);
if (Status != EFI_SUCCESS) {
return Status;
}
}
if ((DisableFlags != 0) || ResetMCastList) {
Status = pxe_rcvfilter_disable (snp, DisableFlags, ResetMCastList);
if (Status != EFI_SUCCESS) {
return Status;
}
}
return pxe_rcvfilter_read (snp);
}

View File

@@ -0,0 +1,129 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
reset.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_reset (
SNP_DRIVER *snp
)
/*++
Routine Description:
This routine calls undi to reset the nic.
Arguments:
snp - pointer to the snp driver structure
Returns:
EFI_SUCCESSFUL for a successful completion
other for failed calls
--*/
{
snp->cdb.OpCode = PXE_OPCODE_RESET;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.reset() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi32.reset() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
//
// UNDI could not be reset. Return UNDI error.
//
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_reset (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ExtendedVerification
)
/*++
Routine Description:
This is the SNP interface routine for resetting the NIC
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_reset routine to actually do the reset!
Arguments:
this - context pointer
ExtendedVerification - not implemented
Returns:
--*/
{
SNP_DRIVER *snp;
//
// Resolve Warning 4 unreferenced parameter problem
//
ExtendedVerification = 0;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
return pxe_reset (snp);
}

View File

@@ -0,0 +1,152 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
shutdown.c
Abstract:
Revision history:
2000-Feb-14 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_shutdown (
IN SNP_DRIVER *snp
)
/*++
Routine Description:
this routine calls undi to shut down the interface.
Arguments:
snp - pointer to snp driver structure
Returns:
--*/
{
snp->cdb.OpCode = PXE_OPCODE_SHUTDOWN;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.shutdown() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
//
// UNDI could not be shutdown. Return UNDI error.
//
DEBUG ((EFI_D_WARN, "\nsnp->undi.shutdown() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
return EFI_DEVICE_ERROR;
}
//
// Free allocated memory.
//
if (snp->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
snp->tx_rx_bufsize = 0;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
/*++
Routine Description:
This is the SNP interface routine for shutting down the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_shutdown routine to actually do the undi shutdown
Arguments:
this - context pointer
Returns:
--*/
{
SNP_DRIVER *snp;
EFI_STATUS status;
//
//
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
//
//
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
//
//
status = pxe_shutdown (snp);
snp->mode.State = EfiSimpleNetworkStarted;
snp->mode.ReceiveFilterSetting = 0;
snp->mode.MCastFilterCount = 0;
snp->mode.ReceiveFilterSetting = 0;
ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter);
CopyMem (
&snp->mode.CurrentAddress,
&snp->mode.PermanentAddress,
sizeof (EFI_MAC_ADDRESS)
);
gBS->CloseEvent (snp->snp.WaitForPacket);
return status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
snp.h
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
--*/
#ifndef _SNP_H
#define _SNP_H
#include "IndustryStandard/pci22.h"
#define SNP_DEBUG 0
#define FOUR_GIGABYTES (UINT64) 0x100000000ULL
#if SNP_DEBUG
#undef D_NET
#define D_NET D_WARN
#define SNP_PRINT(DebugInfo) Print (DebugInfo)
#else
#define SNP_PRINT(DebugInfo)
#endif
#define SNP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('s', 'n', 'd', 's')
#define MAX_MAP_LENGTH 100
#define PCI_BAR_IO_MASK 0x00000003
#define PCI_BAR_IO_MODE 0x00000001
#define PCI_BAR_MEM_MASK 0x0000000F
#define PCI_BAR_MEM_MODE 0x00000000
#define PCI_BAR_MEM_64BIT 0x00000004
typedef struct {
UINT32 Signature;
EFI_LOCK lock;
EFI_SIMPLE_NETWORK_PROTOCOL snp;
EFI_SIMPLE_NETWORK_MODE mode;
EFI_HANDLE device_handle;
EFI_DEVICE_PATH_PROTOCOL *device_path;
//
// Local instance data needed by SNP driver
//
// Pointer to S/W UNDI API entry point
// This will be NULL for H/W UNDI
//
EFI_STATUS (*issue_undi32_command) (UINT64 cdb);
BOOLEAN is_swundi;
//
// undi interface number, if one undi manages more nics
//
PXE_IFNUM if_num;
//
// Allocated tx/rx buffer that was passed to UNDI Initialize.
//
UINT32 tx_rx_bufsize;
VOID *tx_rx_buffer;
//
// mappable buffers for receive and fill header for undi3.0
// these will be used if the user buffers are above 4GB limit (instead of
// mapping the user buffers)
//
UINT8 *receive_buf;
VOID *ReceiveBufUnmap;
UINT8 *fill_hdr_buf;
VOID *FillHdrBufUnmap;
EFI_PCI_IO_PROTOCOL *IoFncs;
UINT8 IoBarIndex;
UINT8 MemoryBarIndex;
BOOLEAN IsOldUndi; // true for EFI1.0 UNDI (3.0) drivers
//
// Buffers for command descriptor block, command parameter block
// and data block.
//
PXE_CDB cdb;
VOID *cpb;
VOID *CpbUnmap;
VOID *db;
//
// UNDI structure, we need to remember the init info for a long time!
//
PXE_DB_GET_INIT_INFO init_info;
VOID *SnpDriverUnmap;
//
// when ever we map an address, we must remember it's address and the un-map
// cookie so that we can unmap later
//
struct s_map_list {
EFI_PHYSICAL_ADDRESS virt;
VOID *map_cookie;
} map_list[MAX_MAP_LENGTH];
}
SNP_DRIVER;
#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, snp, SNP_DRIVER_SIGNATURE)
//
// Global Variables
//
extern EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName;
extern EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding;
//
// Virtual to physical mapping for all UNDI 3.0s.
//
extern struct s_v2p {
struct s_v2p *next;
VOID *vaddr;
UINTN bsize;
EFI_PHYSICAL_ADDRESS paddr;
VOID *unmap;
}
*_v2p;
EFI_STATUS
add_v2p (
struct s_v2p **v2p,
EFI_PCI_IO_PROTOCOL_OPERATION type,
VOID *vaddr,
UINTN bsize
)
;
EFI_STATUS
find_v2p (
struct s_v2p **v2p,
VOID *vaddr
)
;
EFI_STATUS
del_v2p (
VOID *vaddr
)
;
extern
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddress,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio (
IN UINT64 UniqueId,
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddr,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
VOID
snp_undi32_callback_sync (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_start (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_stop (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_reset (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ExtendedVerification
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 enable,
IN UINT32 disable,
IN BOOLEAN reset_mcast_filter,
IN UINTN mcast_filter_count OPTIONAL,
IN EFI_MAC_ADDRESS * mcast_filter OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN EFI_MAC_ADDRESS *new OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN OUT UINTN *statistics_size OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * statistics_table OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
OUT EFI_MAC_ADDRESS *MAC
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN read_write,
IN UINTN offset,
IN UINTN buffer_size,
IN OUT VOID *buffer
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *interrupt_status OPTIONAL,
OUT VOID **tx_buffer OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN header_size,
IN UINTN buffer_size,
IN VOID *buffer,
IN EFI_MAC_ADDRESS * src_addr OPTIONAL,
IN EFI_MAC_ADDRESS * dest_addr OPTIONAL,
IN UINT16 *protocol OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *header_size OPTIONAL,
IN OUT UINTN *buffer_size,
OUT VOID *buffer,
OUT EFI_MAC_ADDRESS * src_addr OPTIONAL,
OUT EFI_MAC_ADDRESS * dest_addr OPTIONAL,
OUT UINT16 *protocol OPTIONAL
)
;
typedef
EFI_STATUS
(*issue_undi32_command) (
UINT64 cdb
);
typedef
VOID
(*ptr) (
VOID
);
#define SNP_MEM_PAGES(x) (((x) - 1) / 4096 + 1)
#if SNP_DEBUG
extern
VOID
snp_wait_for_key (
VOID
)
;
#endif
#endif /* _SNP_H */

View File

@@ -0,0 +1,191 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
start.c
Abstract:
Revision history:
2000-Feb-07 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_start (
SNP_DRIVER *snp
)
/*++
Routine Description:
this routine calls undi to start the interface and changes the snp state!
Arguments:
snp - pointer to snp driver structure
Returns:
--*/
{
PXE_CPB_START_30 *cpb;
PXE_CPB_START_31 *cpb_31;
cpb = snp->cpb;
cpb_31 = snp->cpb;
//
// Initialize UNDI Start CDB for H/W UNDI
//
snp->cdb.OpCode = PXE_OPCODE_START;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Make changes to H/W UNDI Start CDB if this is
// a S/W UNDI.
//
if (snp->is_swundi) {
if (snp->IsOldUndi) {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_30);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
cpb->Delay = (UINT64) &snp_undi32_callback_delay_30;
cpb->Block = (UINT64) &snp_undi32_callback_block_30;
//
// Virtual == Physical. This can be set to zero.
//
cpb->Virt2Phys = (UINT64) &snp_undi32_callback_v2p_30;
cpb->Mem_IO = (UINT64) &snp_undi32_callback_memio_30;
} else {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_31);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb_31;
cpb_31->Delay = (UINT64) &snp_undi32_callback_delay;
cpb_31->Block = (UINT64) &snp_undi32_callback_block;
//
// Virtual == Physical. This can be set to zero.
//
cpb_31->Virt2Phys = (UINT64) 0;
cpb_31->Mem_IO = (UINT64) &snp_undi32_callback_memio;
cpb_31->Map_Mem = (UINT64) &snp_undi32_callback_map;
cpb_31->UnMap_Mem = (UINT64) &snp_undi32_callback_unmap;
cpb_31->Sync_Mem = (UINT64) &snp_undi32_callback_sync;
cpb_31->Unique_ID = (UINT64) (UINTN) snp;
}
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.start() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
//
// UNDI could not be started. Return UNDI error.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.start() %xh:%xh\n",
snp->cdb.StatCode,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// Set simple network state to Started and return success.
//
snp->mode.State = EfiSimpleNetworkStarted;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_start (
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
)
/*++
Routine Description:
This is the SNP interface routine for starting the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_start routine to actually do start undi interface
Arguments:
This - context pointer
Returns:
EFI_INVALID_PARAMETER - "This" is Null
- No SNP driver can be extracted from "This"
EFI_ALREADY_STARTED - The state of SNP is EfiSimpleNetworkStarted
or EfiSimpleNetworkInitialized
EFI_DEVICE_ERROR - The state of SNP is other than EfiSimpleNetworkStarted,
EfiSimpleNetworkInitialized, and EfiSimpleNetworkStopped
EFI_SUCCESS - UNDI interface is succesfully started
Other - Error occurs while calling pxe_start function.
--*/
{
SNP_DRIVER *Snp;
EFI_STATUS Status;
UINTN Index;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
if (Snp == NULL) {
return EFI_INVALID_PARAMETER;
}
switch (Snp->mode.State) {
case EfiSimpleNetworkStopped:
break;
case EfiSimpleNetworkStarted:
case EfiSimpleNetworkInitialized:
return EFI_ALREADY_STARTED;
default:
return EFI_DEVICE_ERROR;
}
Status = pxe_start (Snp);
if (Status != EFI_SUCCESS) {
return Status;
}
//
// clear the map_list in SNP structure
//
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
Snp->map_list[Index].virt = 0;
Snp->map_list[Index].map_cookie = 0;
}
Snp->mode.MCastFilterCount = 0;
return Status;
}

View File

@@ -0,0 +1,248 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
station_address.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_get_stn_addr (
SNP_DRIVER *snp
)
/*++
Routine Description:
this routine calls undi to read the MAC address of the NIC and updates the
mode structure with the address.
Arguments:
snp - pointer to snp driver structure
Returns:
--*/
{
PXE_DB_STATION_ADDRESS *db;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS);
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.station_addr() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
//
// Set new station address in SNP->Mode structure and return success.
//
CopyMem (
&(snp->mode.CurrentAddress),
&db->StationAddr,
snp->mode.HwAddressSize
);
CopyMem (
&snp->mode.BroadcastAddress,
&db->BroadcastAddr,
snp->mode.HwAddressSize
);
CopyMem (
&snp->mode.PermanentAddress,
&db->PermanentAddr,
snp->mode.HwAddressSize
);
return EFI_SUCCESS;
}
EFI_STATUS
pxe_set_stn_addr (
SNP_DRIVER *snp,
EFI_MAC_ADDRESS *NewMacAddr
)
/*++
Routine Description:
this routine calls undi to set a new MAC address for the NIC,
Arguments:
snp - pointer to snp driver structure
NewMacAddr - pointer to a mac address to be set for the nic, if this is NULL
then this routine resets the mac address to the NIC's original
address.
Returns:
--*/
{
PXE_CPB_STATION_ADDRESS *cpb;
PXE_DB_STATION_ADDRESS *db;
cpb = snp->cpb;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
if (NewMacAddr == NULL) {
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_RESET;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
} else {
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
//
// even though the OPFLAGS are set to READ, supplying a new address
// in the CPB will make undi change the mac address to the new one.
//
CopyMem (&cpb->StationAddr, NewMacAddr, snp->mode.HwAddressSize);
snp->cdb.CPBsize = sizeof (PXE_CPB_STATION_ADDRESS);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
}
snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS);
snp->cdb.DBaddr = (UINT64) (UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.station_addr() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
//
// UNDI command failed. Return UNDI status to caller.
//
return EFI_DEVICE_ERROR;
}
//
// read the changed address and save it in SNP->Mode structure
//
pxe_get_stn_addr (snp);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN EFI_MAC_ADDRESS * NewMacAddr OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for changing the NIC's mac address.
This routine basically retrieves snp structure, checks the SNP state and
calls the above routines to actually do the work
Arguments:
this - context pointer
NewMacAddr - pointer to a mac address to be set for the nic, if this is NULL
then this routine resets the mac address to the NIC's original
address.
ResetFlag - If true, the mac address will change to NIC's original address
Returns:
--*/
{
SNP_DRIVER *snp;
EFI_STATUS Status;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
// Check for invalid parameter combinations.
//
if (!ResetFlag && NewMacAddr == NULL) {
return EFI_INVALID_PARAMETER;
}
if (ResetFlag) {
Status = pxe_set_stn_addr (snp, NULL);
} else {
Status = pxe_set_stn_addr (snp, NewMacAddr);
}
return Status;
}

View File

@@ -0,0 +1,193 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
statistics.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
--*/
#include "Snp.h"
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN OUT UINTN *StatTableSizePtr OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * StatTablePtr OPTIONAL
)
/*++
Routine Description:
This is the SNP interface routine for getting the NIC's statistics.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ routine to actually do the
Arguments:
this - context pointer
ResetFlag - true to reset the NIC's statistics counters to zero.
StatTableSizePtr - pointer to the statistics table size
StatTablePtr - pointer to the statistics table
Returns:
--*/
{
SNP_DRIVER *snp;
PXE_DB_STATISTICS *db;
UINT64 *stp;
UINT64 mask;
UINTN size;
UINTN n;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
//
// if we are not resetting the counters, we have to have a valid stat table
// with >0 size. if no reset, no table and no size, return success.
//
if (!ResetFlag && StatTableSizePtr == NULL) {
return StatTablePtr ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
}
//
// Initialize UNDI Statistics CDB
//
snp->cdb.OpCode = PXE_OPCODE_STATISTICS;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
if (ResetFlag) {
snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_RESET;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
db = snp->db;
} else {
snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_READ;
snp->cdb.DBsize = sizeof (PXE_DB_STATISTICS);
snp->cdb.DBaddr = (UINT64) (UINTN) (db = snp->db);
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.statistics() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.statistics() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_UNSUPPORTED;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.statistics() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
if (ResetFlag) {
return EFI_SUCCESS;
}
if (StatTablePtr == NULL) {
*StatTableSizePtr = sizeof (EFI_NETWORK_STATISTICS);
return EFI_BUFFER_TOO_SMALL;
}
//
// Convert the UNDI statistics information to SNP statistics
// information.
//
ZeroMem (StatTablePtr, *StatTableSizePtr);
stp = (UINT64 *) StatTablePtr;
size = 0;
for (n = 0, mask = 1; n < 64; n++, mask = LShiftU64 (mask, 1), stp++) {
//
// There must be room for a full UINT64. Partial
// numbers will not be stored.
//
if ((n + 1) * sizeof (UINT64) > *StatTableSizePtr) {
break;
}
if (db->Supported & mask) {
*stp = db->Data[n];
size = n + 1;
} else {
SetMem (stp, sizeof (UINT64), 0xFF);
}
}
//
// Compute size up to last supported statistic.
//
while (++n < 64) {
if (db->Supported & (mask = LShiftU64 (mask, 1))) {
size = n;
}
}
size *= sizeof (UINT64);
if (*StatTableSizePtr >= size) {
*StatTableSizePtr = size;
return EFI_SUCCESS;
} else {
*StatTableSizePtr = size;
return EFI_BUFFER_TOO_SMALL;
}
}

View File

@@ -0,0 +1,120 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
stop.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_stop (
SNP_DRIVER *snp
)
/*++
Routine Description:
this routine calls undi to stop the interface and changes the snp state
Arguments:
snp - pointer to snp driver structure
Returns:
--*/
{
snp->cdb.OpCode = PXE_OPCODE_STOP;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command
//
DEBUG ((EFI_D_NET, "\nsnp->undi.stop() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi.stop() %xh:%xh\n",
snp->cdb.StatCode,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// Set simple network state to Started and return success.
//
snp->mode.State = EfiSimpleNetworkStopped;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
snp_undi32_stop (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
/*++
Routine Description:
This is the SNP interface routine for stopping the interface.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_stop routine to actually stop the undi interface
Arguments:
this - context pointer
Returns:
--*/
{
SNP_DRIVER *snp;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkStarted:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkInitialized:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
return pxe_stop (snp);
}

View File

@@ -0,0 +1,396 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
transmit.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
--*/
#include "snp.h"
EFI_STATUS
pxe_fillheader (
SNP_DRIVER *snp,
VOID *MacHeaderPtr,
UINTN MacHeaderSize,
VOID *BufferPtr,
UINTN BufferLength,
EFI_MAC_ADDRESS *DestinationAddrPtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
UINT16 *ProtocolPtr
)
/*++
Routine Description:
This routine calls undi to create the meadia header for the given data buffer.
Arguments:
snp - pointer to SNP driver structure
MacHeaderPtr - address where the media header will be filled in.
MacHeaderSize - size of the memory at MacHeaderPtr
BufferPtr - data buffer pointer
BufferLength - Size of data in the BufferPtr
DestinationAddrPtr - address of the destination mac address buffer
SourceAddrPtr - address of the source mac address buffer
ProtocolPtr - address of the protocol type
Returns:
EFI_SUCCESS - if successfully completed the undi call
Other - error return from undi call.
--*/
{
PXE_CPB_FILL_HEADER_FRAGMENTED *cpb;
EFI_STATUS Status;
struct s_v2p *pkt_v2p;
UINT64 TempData;
cpb = snp->cpb;
if (SourceAddrPtr) {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) SourceAddrPtr,
snp->mode.HwAddressSize
);
} else {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) &(snp->mode.CurrentAddress),
snp->mode.HwAddressSize
);
}
CopyMem (
(VOID *) cpb->DestAddr,
(VOID *) DestinationAddrPtr,
snp->mode.HwAddressSize
);
//
// we need to do the byte swapping
//
cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);
cpb->PacketLen = (UINT32) (BufferLength);
cpb->MediaHeaderLen = (UINT16) MacHeaderSize;
cpb->FragCnt = 2;
cpb->reserved = 0;
cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) MacHeaderPtr;
cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize;
cpb->FragDesc[1].FragAddr = (UINT64) (UINTN) BufferPtr;
cpb->FragDesc[1].FragLen = (UINT32) BufferLength;
cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0;
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) snp->fill_hdr_buf;
cpb->FragDesc[0].FragLen = (UINT32) snp->init_info.MediaHeaderLen;
}
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
//
// Let the device just read this buffer
//
Status = add_v2p (
&pkt_v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
//
// give the virtual address to UNDI and it will call back on Virt2Phys
// to get the mapped address, if it needs it
//
cpb->FragDesc[1].FragLen = (UINT32) pkt_v2p->bsize;
}
}
snp->cdb.OpCode = PXE_OPCODE_FILL_HEADER;
snp->cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.CPBsize = sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
del_v2p (BufferPtr);
}
//
// if we used the global buffer for header, copy the contents
//
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
CopyMem (
MacHeaderPtr,
snp->fill_hdr_buf,
snp->init_info.MediaHeaderLen
);
}
}
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
return EFI_SUCCESS;
case PXE_STATCODE_INVALID_PARAMETER:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.fill_header() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_INVALID_PARAMETER;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.fill_header() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
}
EFI_STATUS
pxe_transmit (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN BufferLength
)
/*++
Routine Description:
This routine calls undi to transmit the given data buffer
Arguments:
snp - pointer to SNP driver structure
BufferPtr - data buffer pointer
BufferLength - Size of data in the BufferPtr
Returns:
EFI_SUCCESS - if successfully completed the undi call
Other - error return from undi call.
--*/
{
PXE_CPB_TRANSMIT *cpb;
EFI_STATUS Status;
struct s_v2p *v2p;
UINT64 TempData;
cpb = snp->cpb;
cpb->FrameAddr = (UINT64) (UINTN) BufferPtr;
cpb->DataLen = (UINT32) BufferLength;
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
//
// we need to create a mapping now and give it to the undi when it calls
// the Virt2Phys on this address.
// this is a transmit, just map it for the device to READ
//
Status = add_v2p (
&v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
cpb->DataLen = (UINT32) v2p->bsize;
}
cpb->MediaheaderLen = 0;
cpb->reserved = 0;
snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;
snp->cdb.CPBsize = sizeof (PXE_CPB_TRANSMIT);
snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;
snp->cdb.OpCode = PXE_OPCODE_TRANSMIT;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.transmit() "));
DEBUG ((EFI_D_NET, "\nsnp->cdb.OpCode == %x", snp->cdb.OpCode));
DEBUG ((EFI_D_NET, "\nsnp->cdb.CPBaddr == %X", snp->cdb.CPBaddr));
DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr));
DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() "));
DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode));
//
// we will unmap the buffers in get_status call, not here
//
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
return EFI_SUCCESS;
case PXE_STATCODE_QUEUE_FULL:
case PXE_STATCODE_BUSY:
Status = EFI_NOT_READY;
break;
default:
Status = EFI_DEVICE_ERROR;
}
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.transmit() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return Status;
}
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN MacHeaderSize,
IN UINTN BufferLength,
IN VOID *BufferPtr,
IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
IN UINT16 *ProtocolPtr OPTIONAL
)
/*++
Routine Description:
This is the snp interface routine for transmitting a packet. this routine
basically retrieves the snp structure, checks the snp state and calls
pxe_fill_header and pxe_transmit calls to complete the transmission.
Arguments:
this - pointer to SNP driver context
MacHeaderSize - size of the memory at MacHeaderPtr
BufferLength - Size of data in the BufferPtr
BufferPtr - data buffer pointer
SourceAddrPtr - address of the source mac address buffer
DestinationAddrPtr - address of the destination mac address buffer
ProtocolPtr - address of the protocol type
Returns:
EFI_SUCCESS - if successfully completed the undi call
Other - error return from undi call.
--*/
{
SNP_DRIVER *snp;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
return EFI_NOT_STARTED;
case EfiSimpleNetworkStarted:
return EFI_DEVICE_ERROR;
default:
return EFI_DEVICE_ERROR;
}
if (BufferPtr == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferLength < snp->mode.MediaHeaderSize) {
return EFI_BUFFER_TOO_SMALL;
}
//
// if the MacHeaderSize is non-zero, we need to fill up the header and for that
// we need the destination address and the protocol
//
if (MacHeaderSize != 0) {
if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) {
return EFI_INVALID_PARAMETER;
}
Status = pxe_fillheader (
snp,
BufferPtr,
MacHeaderSize,
(UINT8 *) BufferPtr + MacHeaderSize,
BufferLength - MacHeaderSize,
DestinationAddrPtr,
SourceAddrPtr,
ProtocolPtr
);
if (Status != EFI_SUCCESS) {
return Status;
}
}
return pxe_transmit (snp, BufferPtr, BufferLength);
}