Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3492 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -73,11 +73,6 @@ typedef struct _ICMP_ERROR_INFO {
|
||||
BOOLEAN Notify;
|
||||
} ICMP_ERROR_INFO;
|
||||
|
||||
//
|
||||
// Driver Consumed Protocol Prototypes
|
||||
//
|
||||
//@MT:#include EFI_PROTOCOL_CONSUMER (Ip4)
|
||||
//@MT:#include EFI_PROTOCOL_CONSUMER (Udp4)
|
||||
|
||||
#define EFI_IP4_HEADER_LEN(HdrPtr) ((HdrPtr)->HeaderLength << 2)
|
||||
|
||||
|
@ -188,7 +188,7 @@ typedef struct {
|
||||
//
|
||||
#define EFI_IP4(EfiIpAddr) (*(IP4_ADDR *) ((EfiIpAddr).Addr))
|
||||
#define EFI_NTOHL(EfiIp) (NTOHL (EFI_IP4 ((EfiIp))))
|
||||
#define EFI_IP_EQUAL(Ip1, Ip2) (EFI_IP4 (Ip1) == EFI_IP4 (Ip2))
|
||||
#define EFI_IP4_EQUAL(Ip1, Ip2) (NetCompareMem (&(Ip1), &(Ip2), sizeof (EFI_IPv4_ADDRESS)) == 0)
|
||||
|
||||
INTN
|
||||
NetGetMaskLength (
|
||||
@ -208,10 +208,10 @@ Ip4IsUnicast (
|
||||
|
||||
extern IP4_ADDR mIp4AllMasks [IP4_MASK_NUM];
|
||||
|
||||
//@MT:#include EFI_PROTOCOL_CONSUMER (LoadedImage)
|
||||
//@MT:#include EFI_PROTOCOL_CONSUMER (ServiceBinding)
|
||||
//@MT:#include EFI_PROTOCOL_CONSUMER (SimpleNetwork)
|
||||
|
||||
extern EFI_IPv4_ADDRESS mZeroIp4Addr;
|
||||
|
||||
#define NET_IS_DIGIT(Ch) (('0' <= (Ch)) && ((Ch) <= '9'))
|
||||
//
|
||||
// Wrap functions to ease the impact of EFI library changes.
|
||||
//
|
||||
|
350
MdeModulePkg/Include/Protocol/PxeDhcp4.h
Normal file
350
MdeModulePkg/Include/Protocol/PxeDhcp4.h
Normal file
@ -0,0 +1,350 @@
|
||||
/*++
|
||||
|
||||
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:
|
||||
EFI PXE DHCPv4 protocol definition
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _PXEDHCP4_H_
|
||||
#define _PXEDHCP4_H_
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// PXE DHCPv4 GUID definition
|
||||
//
|
||||
|
||||
#define EFI_PXE_DHCP4_PROTOCOL_GUID \
|
||||
{ 0x03c4e624, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d } }
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// Interface definition
|
||||
//
|
||||
|
||||
typedef struct _EFI_PXE_DHCP4_PROTOCOL EFI_PXE_DHCP4_PROTOCOL;
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// Descriptions of the DHCP version 4 header and options can be found
|
||||
// in RFC-2131 and RFC-2132 at www.ietf.org
|
||||
//
|
||||
|
||||
#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;
|
||||
#define DHCP4_INITIAL_SECONDS 4
|
||||
|
||||
UINT16 flags;
|
||||
#define DHCP4_BROADCAST_FLAG 0x8000
|
||||
|
||||
UINT32 ciaddr;
|
||||
|
||||
UINT32 yiaddr;
|
||||
|
||||
UINT32 siaddr;
|
||||
|
||||
UINT32 giaddr;
|
||||
|
||||
UINT8 chaddr[16];
|
||||
|
||||
UINT8 sname[64];
|
||||
|
||||
UINT8 fname[128];
|
||||
|
||||
//
|
||||
// This is the minimum option length as specified in RFC-2131.
|
||||
// The packet must be padded out this far with DHCP4_PAD.
|
||||
// DHCPv4 packets are usually 576 bytes in length. This length
|
||||
// includes the IPv4 and UDPv4 headers but not the media header.
|
||||
// Note: Not all DHCP relay agents will forward DHCPv4 packets
|
||||
// if they are less than 384 bytes or exceed 576 bytes. Even if
|
||||
// the underlying hardware can handle smaller and larger packets,
|
||||
// many older relay agents will not accept them.
|
||||
//
|
||||
UINT32 magik;
|
||||
#define DHCP4_MAGIK_NUMBER 0x63825363
|
||||
|
||||
UINT8 options[308];
|
||||
|
||||
} DHCP4_HEADER;
|
||||
#pragma pack()
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// DHCPv4 packet definition. Room for 576 bytes including IP and
|
||||
// UDP header.
|
||||
//
|
||||
|
||||
#define DHCP4_MAX_PACKET_SIZE 576
|
||||
#define DHCP4_UDP_HEADER_SIZE 8
|
||||
#define DHCP4_IP_HEADER_SIZE 20
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union _DHCP4_PACKET {
|
||||
UINT32 _force_data_alignment;
|
||||
|
||||
UINT8 raw[1500];
|
||||
|
||||
DHCP4_HEADER dhcp4;
|
||||
} DHCP4_PACKET;
|
||||
#pragma pack()
|
||||
|
||||
#define DHCP4_SERVER_PORT 67
|
||||
#define DHCP4_CLIENT_PORT 68
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// DHCPv4 and PXE option numbers.
|
||||
//
|
||||
|
||||
#define DHCP4_PAD 0
|
||||
#define DHCP4_END 255
|
||||
#define DHCP4_SUBNET_MASK 1
|
||||
#define DHCP4_TIME_OFFSET 2
|
||||
#define DHCP4_ROUTER_LIST 3
|
||||
#define DHCP4_TIME_SERVERS 4
|
||||
#define DHCP4_NAME_SERVERS 5
|
||||
#define DHCP4_DNS_SERVERS 6
|
||||
#define DHCP4_LOG_SERVERS 7
|
||||
#define DHCP4_COOKIE_SERVERS 8
|
||||
#define DHCP4_LPR_SREVERS 9
|
||||
#define DHCP4_IMPRESS_SERVERS 10
|
||||
#define DHCP4_RESOURCE_LOCATION_SERVERS 11
|
||||
#define DHCP4_HOST_NAME 12
|
||||
#define DHCP4_BOOT_FILE_SIZE 13
|
||||
#define DHCP4_DUMP_FILE 14
|
||||
#define DHCP4_DOMAIN_NAME 15
|
||||
#define DHCP4_SWAP_SERVER 16
|
||||
#define DHCP4_ROOT_PATH 17
|
||||
#define DHCP4_EXTENSION_PATH 18
|
||||
#define DHCP4_IP_FORWARDING 19
|
||||
#define DHCP4_NON_LOCAL_SOURCE_ROUTE 20
|
||||
#define DHCP4_POLICY_FILTER 21
|
||||
#define DHCP4_MAX_DATAGRAM_SIZE 22
|
||||
#define DHCP4_DEFAULT_TTL 23
|
||||
#define DHCP4_MTU_AGING_TIMEOUT 24
|
||||
#define DHCP4_MTU_SIZES 25
|
||||
#define DHCP4_MTU_TO_USE 26
|
||||
#define DHCP4_ALL_SUBNETS_LOCAL 27
|
||||
#define DHCP4_BROADCAST_ADDRESS 28
|
||||
#define DHCP4_PERFORM_MASK_DISCOVERY 29
|
||||
#define DHCP4_RESPOND_TO_MASK_REQ 30
|
||||
#define DHCP4_PERFORM_ROUTER_DISCOVERY 31
|
||||
#define DHCP4_ROUTER_SOLICIT_ADDRESS 32
|
||||
#define DHCP4_STATIC_ROUTER_LIST 33
|
||||
#define DHCP4_USE_ARP_TRAILERS 34
|
||||
#define DHCP4_ARP_CACHE_TIMEOUT 35
|
||||
#define DHCP4_ETHERNET_ENCAPSULATION 36
|
||||
#define DHCP4_TCP_DEFAULT_TTL 37
|
||||
#define DHCP4_TCP_KEEP_ALIVE_INT 38
|
||||
#define DHCP4_KEEP_ALIVE_GARBAGE 39
|
||||
#define DHCP4_NIS_DOMAIN_NAME 40
|
||||
#define DHCP4_NIS_SERVERS 41
|
||||
#define DHCP4_NTP_SERVERS 42
|
||||
#define DHCP4_VENDOR_SPECIFIC 43
|
||||
# define PXE_MTFTP_IP 1
|
||||
# define PXE_MTFTP_CPORT 2
|
||||
# define PXE_MTFTP_SPORT 3
|
||||
# define PXE_MTFTP_TMOUT 4
|
||||
# define PXE_MTFTP_DELAY 5
|
||||
# define PXE_DISCOVERY_CONTROL 6
|
||||
# define PXE_DISABLE_BROADCAST_DISCOVERY 0x01
|
||||
# define PXE_DISABLE_MULTICAST_DISCOVERY 0x02
|
||||
# define PXE_ACCEPT_ONLY_PXE_BOOT_SERVERS 0x04
|
||||
# define PXE_DO_NOT_PROMPT 0x08
|
||||
# define PXE_DISCOVERY_MCAST_ADDR 7
|
||||
# define PXE_BOOT_SERVERS 8
|
||||
# define PXE_BOOT_MENU 9
|
||||
# define PXE_BOOT_PROMPT 10
|
||||
# define PXE_MCAST_ADDRS_ALLOC 11
|
||||
# define PXE_CREDENTIAL_TYPES 12
|
||||
# define PXE_BOOT_ITEM 71
|
||||
#define DHCP4_NBNS_SERVERS 44
|
||||
#define DHCP4_NBDD_SERVERS 45
|
||||
#define DHCP4_NETBIOS_NODE_TYPE 46
|
||||
#define DHCP4_NETBIOS_SCOPE 47
|
||||
#define DHCP4_XWINDOW_SYSTEM_FONT_SERVERS 48
|
||||
#define DHCP4_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49
|
||||
#define DHCP4_REQUESTED_IP_ADDRESS 50
|
||||
#define DHCP4_LEASE_TIME 51
|
||||
#define DHCP4_OPTION_OVERLOAD 52
|
||||
# define DHCP4_OVERLOAD_FNAME 1
|
||||
# define DHCP4_OVERLOAD_SNAME 2
|
||||
# define DHCP4_OVERLOAD_FNAME_AND_SNAME 3
|
||||
#define DHCP4_MESSAGE_TYPE 53
|
||||
# define DHCP4_MESSAGE_TYPE_DISCOVER 1
|
||||
# define DHCP4_MESSAGE_TYPE_OFFER 2
|
||||
# define DHCP4_MESSAGE_TYPE_REQUEST 3
|
||||
# define DHCP4_MESSAGE_TYPE_DECLINE 4
|
||||
# define DHCP4_MESSAGE_TYPE_ACK 5
|
||||
# define DHCP4_MESSAGE_TYPE_NAK 6
|
||||
# define DHCP4_MESSAGE_TYPE_RELEASE 7
|
||||
# define DHCP4_MESSAGE_TYPE_INFORM 8
|
||||
#define DHCP4_SERVER_IDENTIFIER 54
|
||||
#define DHCP4_PARAMETER_REQUEST_LIST 55
|
||||
#define DHCP4_ERROR_MESSAGE 56
|
||||
#define DHCP4_MAX_MESSAGE_SIZE 57
|
||||
# define DHCP4_DEFAULT_MAX_MESSAGE_SIZE 576
|
||||
#define DHCP4_RENEWAL_TIME 58
|
||||
#define DHCP4_REBINDING_TIME 59
|
||||
#define DHCP4_CLASS_IDENTIFIER 60
|
||||
#define DHCP4_CLIENT_IDENTIFIER 61
|
||||
#define DHCP4_NISPLUS_DOMAIN_NAME 64
|
||||
#define DHCP4_NISPLUS_SERVERS 65
|
||||
#define DHCP4_TFTP_SERVER_NAME 66
|
||||
#define DHCP4_BOOTFILE 67
|
||||
#define DHCP4_MOBILE_IP_HOME_AGENTS 68
|
||||
#define DHCP4_SMPT_SERVERS 69
|
||||
#define DHCP4_POP3_SERVERS 70
|
||||
#define DHCP4_NNTP_SERVERS 71
|
||||
#define DHCP4_WWW_SERVERS 72
|
||||
#define DHCP4_FINGER_SERVERS 73
|
||||
#define DHCP4_IRC_SERVERS 74
|
||||
#define DHCP4_STREET_TALK_SERVERS 75
|
||||
#define DHCP4_STREET_TALK_DIR_ASSIST_SERVERS 76
|
||||
#define DHCP4_NDS_SERVERS 85
|
||||
#define DHCP4_NDS_TREE_NAME 86
|
||||
#define DHCP4_NDS_CONTEXT 87
|
||||
#define DHCP4_SYSTEM_ARCHITECTURE 93
|
||||
#define DHCP4_NETWORK_ARCHITECTURE 94
|
||||
#define DHCP4_PLATFORM_ID 97
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
//
|
||||
// DHCP4 option format.
|
||||
//
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 op;
|
||||
UINT8 len;
|
||||
UINT8 data[1];
|
||||
} DHCP4_OP;
|
||||
#pragma pack()
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
typedef struct {
|
||||
DHCP4_PACKET Discover;
|
||||
DHCP4_PACKET Offer;
|
||||
DHCP4_PACKET Request;
|
||||
DHCP4_PACKET AckNak;
|
||||
BOOLEAN SetupCompleted;
|
||||
BOOLEAN InitCompleted;
|
||||
BOOLEAN SelectCompleted;
|
||||
BOOLEAN IsBootp;
|
||||
BOOLEAN IsAck;
|
||||
} EFI_PXE_DHCP4_DATA;
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_RUN) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
IN OPTIONAL UINTN OpLen,
|
||||
IN OPTIONAL VOID *OpList
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_SETUP) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
IN OPTIONAL EFI_PXE_DHCP4_DATA * NewData
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_INIT) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
IN UINTN SecondsTimeout,
|
||||
OUT UINTN *Offers,
|
||||
OUT DHCP4_PACKET **OfferList
|
||||
);
|
||||
|
||||
#define DHCP4_MIN_SECONDS 1
|
||||
#define DHCP4_MAX_SECONDS 60
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_SELECT) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
IN UINTN SecondsTimeout,
|
||||
IN DHCP4_PACKET * offer
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_RENEW) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
UINTN seconds_timeout
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_REBIND) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
UINTN seconds_timeout
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_RELEASE) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL * This
|
||||
);
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#define EFI_PXE_DHCP4_PROTOCOL_REVISION 0x00010000
|
||||
|
||||
struct _EFI_PXE_DHCP4_PROTOCOL {
|
||||
UINT64 Revision;
|
||||
EFI_PXE_DHCP4_RUN Run;
|
||||
EFI_PXE_DHCP4_SETUP Setup;
|
||||
EFI_PXE_DHCP4_INIT Init;
|
||||
EFI_PXE_DHCP4_SELECT Select;
|
||||
EFI_PXE_DHCP4_RENEW Renew;
|
||||
EFI_PXE_DHCP4_REBIND Rebind;
|
||||
EFI_PXE_DHCP4_RELEASE Release;
|
||||
EFI_PXE_DHCP4_DATA *Data;
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
extern EFI_GUID gEfiPxeDhcp4ProtocolGuid;
|
||||
|
||||
#endif /* _PXEDHCP4_H_ */
|
||||
/* EOF - PxeDhcp4.h */
|
85
MdeModulePkg/Include/Protocol/PxeDhcp4CallBack.h
Normal file
85
MdeModulePkg/Include/Protocol/PxeDhcp4CallBack.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*++
|
||||
|
||||
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:
|
||||
PxeDhcp4Callback.h
|
||||
|
||||
Abstract:
|
||||
EFI PXE DHCP4 Callback protocol definition.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _PXE_DHCP4CALLBACK_H
|
||||
#define _PXE_DHCP4CALLBACK_H
|
||||
|
||||
#include <Protocol/PxeDhcp4.h>
|
||||
//
|
||||
// GUID definition
|
||||
//
|
||||
|
||||
#define EFI_PXE_DHCP4_CALLBACK_PROTOCOL_GUID \
|
||||
{ 0xc1544c01, 0x92a4, 0x4198, {0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 } }
|
||||
|
||||
|
||||
//
|
||||
// Revision number
|
||||
//
|
||||
|
||||
#define EFI_PXE_DHCP4_CALLBACK_INTERFACE_REVISION 0x00010000
|
||||
|
||||
//
|
||||
// Interface definition
|
||||
//
|
||||
|
||||
typedef struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL EFI_PXE_DHCP4_CALLBACK_PROTOCOL;
|
||||
|
||||
typedef enum {
|
||||
EFI_PXE_DHCP4_FUNCTION_FIRST,
|
||||
EFI_PXE_DHCP4_FUNCTION_INIT,
|
||||
EFI_PXE_DHCP4_FUNCTION_SELECT,
|
||||
EFI_PXE_DHCP4_FUNCTION_RENEW,
|
||||
EFI_PXE_DHCP4_FUNCTION_REBIND,
|
||||
EFI_PXE_DHCP4_FUNCTION_LAST
|
||||
} EFI_PXE_DHCP4_FUNCTION;
|
||||
|
||||
typedef enum {
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_FIRST,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE,
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS_LAST
|
||||
} EFI_PXE_DHCP4_CALLBACK_STATUS;
|
||||
|
||||
typedef
|
||||
EFI_PXE_DHCP4_CALLBACK_STATUS
|
||||
(EFIAPI *EFI_PXE_DHCP4_CALLBACK) (
|
||||
IN EFI_PXE_DHCP4_PROTOCOL *This,
|
||||
IN EFI_PXE_DHCP4_FUNCTION Function,
|
||||
IN UINT32 PacketLen,
|
||||
IN DHCP4_PACKET *Packet OPTIONAL
|
||||
);
|
||||
|
||||
struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL {
|
||||
UINT64 Revision;
|
||||
EFI_PXE_DHCP4_CALLBACK Callback;
|
||||
};
|
||||
|
||||
//
|
||||
// GUID declaration
|
||||
//
|
||||
|
||||
extern EFI_GUID gEfiPxeDhcp4CallbackProtocolGuid;
|
||||
|
||||
#endif /* _PXE_DHCP4CALLBACK_H */
|
||||
/* EOF - PxeDhcp4Callback.h */
|
108
MdeModulePkg/Include/Protocol/Tcp.h
Normal file
108
MdeModulePkg/Include/Protocol/Tcp.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2004, 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:
|
||||
|
||||
tcp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI Transmission Control Protocol
|
||||
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _EFITCP_H
|
||||
#define _EFITCP_H
|
||||
|
||||
|
||||
#include <Protocol/PxeBaseCode.h>
|
||||
|
||||
//
|
||||
// PXE Base Code protocol
|
||||
//
|
||||
|
||||
#define EFI_TCP_PROTOCOL_GUID \
|
||||
{ 0x02b3d5f2, 0xac28, 0x11d3, { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }}
|
||||
|
||||
|
||||
typedef UINT16 EFI_PXE_BASE_CODE_TCP_PORT;
|
||||
|
||||
//
|
||||
// Port Receive Filter definitions
|
||||
//
|
||||
#define EFI_PXE_BASE_CODE_MAX_PORTCNT 8
|
||||
typedef struct {
|
||||
UINT8 Filters;
|
||||
UINT8 IpCnt;
|
||||
UINT16 reserved;
|
||||
EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_PORTCNT];
|
||||
} EFI_TCP_PORT_FILTER;
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TCP_WRITE) (
|
||||
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
|
||||
IN UINT16 OpFlags,
|
||||
IN UINT16 *UrgentPointer,
|
||||
IN UINT32 *SequenceNumber,
|
||||
IN UINT32 *AckNumber,
|
||||
IN UINT16 *HlenResCode,
|
||||
IN UINT16 *Window,
|
||||
IN EFI_IP_ADDRESS *DestIp,
|
||||
IN UINT16 *DestPort,
|
||||
IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL
|
||||
IN EFI_IP_ADDRESS *SrcIp, OPTIONAL
|
||||
IN UINT16 *SrcPort, OPTIONAL
|
||||
IN UINTN *HeaderSize, OPTIONAL
|
||||
IN VOID *HeaderPtr, OPTIONAL
|
||||
IN UINTN *BufferSize,
|
||||
IN VOID *BufferPtr
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TCP_READ) (
|
||||
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
|
||||
IN UINT16 OpFlags,
|
||||
IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL
|
||||
IN OUT UINT16 *DestPort, OPTIONAL
|
||||
IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL
|
||||
IN OUT UINT16 *SrcPort, OPTIONAL
|
||||
IN UINTN *HeaderSize, OPTIONAL
|
||||
IN VOID *HeaderPtr, OPTIONAL
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *BufferPtr
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_TCP_SET_PORT_FILTER) (
|
||||
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
|
||||
IN EFI_TCP_PORT_FILTER *NewFilter
|
||||
);
|
||||
|
||||
//
|
||||
// TCP Protocol structure
|
||||
//
|
||||
typedef struct _EFI_TCP_PROTOCOL {
|
||||
EFI_TCP_WRITE TcpWrite;
|
||||
EFI_TCP_READ TcpRead;
|
||||
EFI_TCP_SET_PORT_FILTER SetPortFilter;
|
||||
} EFI_TCP_PROTOCOL;
|
||||
|
||||
extern EFI_GUID gEfiTcpProtocolGuid;
|
||||
|
||||
#endif /* _EFITCP_H */
|
@ -77,6 +77,7 @@ IP4_ADDR mIp4AllMasks[IP4_MASK_NUM] = {
|
||||
0xFFFFFFFF,
|
||||
};
|
||||
|
||||
EFI_IPv4_ADDRESS mZeroIp4Addr = {0, 0, 0, 0};
|
||||
|
||||
/**
|
||||
Converts the low nibble of a byte to hex unicode character.
|
||||
|
@ -80,6 +80,10 @@
|
||||
gEfiNicIp4ConfigProtocolGuid = {0xdca3d4d, 0x12da, 0x4728, { 0xbf, 0x7e, 0x86, 0xce, 0xb9, 0x28, 0xd0, 0x67 }}
|
||||
gEfiNicIp4ConfigVariableGuid = {0xd8944553, 0xc4dd, 0x41f4, { 0x9b, 0x30, 0xe1, 0x39, 0x7c, 0xfb, 0x26, 0x7b }}
|
||||
|
||||
gEfiTcpProtocolGuid = { 0x02b3d5f2, 0xac28, 0x11d3, { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }}
|
||||
gEfiPxeDhcp4CallbackProtocolGuid = { 0xc1544c01, 0x92a4, 0x4198, {0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 } }
|
||||
gEfiPxeDhcp4ProtocolGuid = { 0x03c4e624, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d } }
|
||||
|
||||
[Ppis.common]
|
||||
gPeiBaseMemoryTestPpiGuid = { 0xB6EC423C, 0x21D2, 0x490D, { 0x85, 0xC6, 0xDD, 0x58, 0x64, 0xEA, 0xA6, 0x74 }}
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
||||
[LibraryClasses.IPF]
|
||||
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
|
||||
|
||||
[LibraryClasses.EBC.DXE_RUNTIME_DRIVER]
|
||||
[LibraryClasses.EBC]
|
||||
IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf
|
||||
|
||||
[LibraryClasses.common.PEI_CORE]
|
||||
@ -112,6 +112,7 @@
|
||||
UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
|
||||
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
|
||||
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
|
||||
UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
|
||||
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
||||
@ -368,8 +369,13 @@
|
||||
MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
|
||||
MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
|
||||
|
||||
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
|
||||
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
|
||||
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
|
||||
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
|
||||
MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf
|
||||
MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.inf
|
||||
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.inf
|
||||
MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
|
||||
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
|
||||
MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
|
||||
|
30
MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h
Normal file
30
MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h
Normal file
@ -0,0 +1,30 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
ArpDebug.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARP_DEBUG_H_
|
||||
#define _ARP_DEBUG_H_
|
||||
|
||||
|
||||
#define ARP_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Arp", PrintArg)
|
||||
#define ARP_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Arp", PrintArg)
|
||||
#define ARP_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Arp", PrintArg)
|
||||
|
||||
#endif
|
||||
|
763
MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
Normal file
763
MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
Normal file
@ -0,0 +1,763 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
ArpDriver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "ArpDriver.h"
|
||||
#include "ArpImpl.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
|
||||
ArpDriverBindingSupported,
|
||||
ArpDriverBindingStart,
|
||||
ArpDriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Create and initialize the arp service context data.
|
||||
|
||||
@param ImageHandle The image handle representing the loaded driver
|
||||
image.
|
||||
@param ControllerHandle The controller handle the driver binds to.
|
||||
@param ArpService Pointer to the buffer containing the arp service
|
||||
context data.
|
||||
|
||||
@retval EFI_SUCCESS The arp service context is initialized.
|
||||
@retval other Failed to initialize the arp service context.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ArpCreateService (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN ARP_SERVICE_DATA *ArpService
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (ArpService != NULL);
|
||||
|
||||
ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
|
||||
|
||||
//
|
||||
// Init the servicebinding protocol members.
|
||||
//
|
||||
ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
|
||||
ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
|
||||
|
||||
//
|
||||
// Save the handles.
|
||||
//
|
||||
ArpService->ImageHandle = ImageHandle;
|
||||
ArpService->ControllerHandle = ControllerHandle;
|
||||
|
||||
//
|
||||
// Create a MNP child instance.
|
||||
//
|
||||
Status = NetLibCreateServiceChild (
|
||||
ControllerHandle,
|
||||
ImageHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
&ArpService->MnpChildHandle
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the MNP protocol.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ArpService->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **)&ArpService->Mnp,
|
||||
ImageHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the underlayer Snp mode data.
|
||||
//
|
||||
Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
|
||||
if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
|
||||
//
|
||||
// Only support the ethernet.
|
||||
//
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the Mnp config parameters.
|
||||
//
|
||||
ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
|
||||
ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
|
||||
ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
|
||||
ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
|
||||
ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
|
||||
ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
|
||||
ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
|
||||
ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
|
||||
ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
|
||||
ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
|
||||
|
||||
//
|
||||
// Configure the Mnp child.
|
||||
//
|
||||
Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the event used in the RxToken.
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
NET_TPL_EVENT,
|
||||
ArpOnFrameRcvd,
|
||||
ArpService,
|
||||
&ArpService->RxToken.Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the Arp heartbeat timer.
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
NET_TPL_TIMER,
|
||||
ArpTimerHandler,
|
||||
ArpService,
|
||||
&ArpService->PeriodicTimer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Start the heartbeat timer.
|
||||
//
|
||||
Status = gBS->SetTimer (
|
||||
ArpService->PeriodicTimer,
|
||||
TimerPeriodic,
|
||||
ARP_PERIODIC_TIMER_INTERVAL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the lock.
|
||||
//
|
||||
NET_LOCK_INIT (&ArpService->Lock);
|
||||
|
||||
//
|
||||
// Init the lists.
|
||||
//
|
||||
NetListInit (&ArpService->ChildrenList);
|
||||
NetListInit (&ArpService->PendingRequestTable);
|
||||
NetListInit (&ArpService->DeniedCacheTable);
|
||||
NetListInit (&ArpService->ResolvedCacheTable);
|
||||
|
||||
ERROR_EXIT:
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean the arp service context data.
|
||||
|
||||
@param ArpService Pointer to the buffer containing the arp service
|
||||
context data.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
ArpCleanService (
|
||||
IN ARP_SERVICE_DATA *ArpService
|
||||
)
|
||||
{
|
||||
NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
|
||||
|
||||
if (ArpService->PeriodicTimer != NULL) {
|
||||
//
|
||||
// Cancle and close the PeriodicTimer.
|
||||
//
|
||||
gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
|
||||
gBS->CloseEvent (ArpService->PeriodicTimer);
|
||||
}
|
||||
|
||||
if (ArpService->RxToken.Event != NULL) {
|
||||
//
|
||||
// Cancle the RxToken and close the event in the RxToken.
|
||||
//
|
||||
ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
|
||||
gBS->CloseEvent (ArpService->RxToken.Event);
|
||||
}
|
||||
|
||||
if (ArpService->Mnp != NULL) {
|
||||
//
|
||||
// Reset the Mnp child and close the Mnp protocol.
|
||||
//
|
||||
ArpService->Mnp->Configure (ArpService->Mnp, NULL);
|
||||
gBS->CloseProtocol (
|
||||
ArpService->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
ArpService->ImageHandle,
|
||||
ArpService->ControllerHandle
|
||||
);
|
||||
}
|
||||
|
||||
if (ArpService->MnpChildHandle != NULL) {
|
||||
//
|
||||
// Destroy the mnp child.
|
||||
//
|
||||
NetLibDestroyServiceChild(
|
||||
ArpService->ControllerHandle,
|
||||
ArpService->ImageHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
ArpService->MnpChildHandle
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test.
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver supports this device
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device.
|
||||
@retval other This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test to see if Arp SB is already installed.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Test to see if MNP SB is installed.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver is added to ControllerHandle
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
|
||||
//
|
||||
// Allocate a zero pool for ArpService.
|
||||
//
|
||||
ArpService = NetAllocateZeroPool (sizeof(ARP_SERVICE_DATA));
|
||||
if (ArpService == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the arp service context data.
|
||||
//
|
||||
Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the ARP service binding protocol.
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
&ArpService->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// OK, start to receive arp packets from Mnp.
|
||||
//
|
||||
Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
ERROR:
|
||||
|
||||
//
|
||||
// On error, clean the arp service context data, and free the memory allocated.
|
||||
//
|
||||
ArpCleanService (ArpService);
|
||||
NetFreePool (ArpService);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCES This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
|
||||
//
|
||||
// Get the NicHandle which the arp servicebinding is installed on.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to get the arp servicebinding protocol on the NicHandle.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
(VOID **)&ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ARP_DEBUG_ERROR (("ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
|
||||
|
||||
while (!NetListIsEmpty (&ArpService->ChildrenList)) {
|
||||
//
|
||||
// Iterate all the instances.
|
||||
//
|
||||
Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);
|
||||
|
||||
//
|
||||
// Destroy this arp child.
|
||||
//
|
||||
ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
|
||||
}
|
||||
|
||||
ASSERT (NetListIsEmpty (&ArpService->PendingRequestTable));
|
||||
ASSERT (NetListIsEmpty (&ArpService->DeniedCacheTable));
|
||||
ASSERT (NetListIsEmpty (&ArpService->ResolvedCacheTable));
|
||||
|
||||
//
|
||||
// Uninstall the ARP ServiceBinding protocol.
|
||||
//
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
NicHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
&ArpService->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ARP_DEBUG_ERROR (("ArpDriverBindingStop: Failed to uninstall ArpSb, %r.\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Clean the arp servicebinding context data and free the memory allocated.
|
||||
//
|
||||
ArpCleanService (ArpService);
|
||||
NetFreePool (ArpService);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it is
|
||||
not NULL, then the I/O services are added to the
|
||||
existing child handle.
|
||||
|
||||
@retval EFI_SUCCES The child handle was created with the I/O
|
||||
services.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
|
||||
the child.
|
||||
@retval other The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
VOID *Mnp;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Allocate memory for the instance context data.
|
||||
//
|
||||
Instance = NetAllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
|
||||
if (Instance == NULL) {
|
||||
ARP_DEBUG_ERROR (("ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
|
||||
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the instance context data.
|
||||
//
|
||||
ArpInitInstance (ArpService, Instance);
|
||||
|
||||
//
|
||||
// Install the ARP protocol onto the ChildHandle.
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiArpProtocolGuid,
|
||||
(VOID *)&Instance->ArpProto,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ARP_DEBUG_ERROR (("ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
|
||||
|
||||
NetFreePool (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Save the ChildHandle.
|
||||
//
|
||||
Instance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Managed Network protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ArpService->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **) &Mnp,
|
||||
gArpDriverBinding.DriverBindingHandle,
|
||||
Instance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the instance into children list managed by the arp service context data.
|
||||
//
|
||||
NetListInsertTail (&ArpService->ChildrenList, &Instance->List);
|
||||
ArpService->ChildrenNumber++;
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
ERROR:
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
gBS->CloseProtocol (
|
||||
ArpService->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
gArpDriverBinding.DriverBindingHandle,
|
||||
Instance->Handle
|
||||
);
|
||||
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiArpProtocolGuid,
|
||||
&Instance->ArpProto,
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
// Free the allocated memory.
|
||||
//
|
||||
NetFreePool (Instance);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The I/O services were removed from the child
|
||||
handle.
|
||||
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
|
||||
that are being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
|
||||
its I/O services are being used.
|
||||
@retval other The child handle was not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
EFI_ARP_PROTOCOL *Arp;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Get the arp protocol.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiArpProtocolGuid,
|
||||
(VOID **)&Arp,
|
||||
ArpService->ImageHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
|
||||
|
||||
if (Instance->Destroyed) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Use the Destroyed as a flag to avoid re-entrance.
|
||||
//
|
||||
Instance->Destroyed = TRUE;
|
||||
|
||||
//
|
||||
// Close the Managed Network protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
ArpService->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
gArpDriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the ARP protocol.
|
||||
//
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiArpProtocolGuid,
|
||||
&Instance->ArpProto,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ARP_DEBUG_ERROR (("ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
|
||||
Status));
|
||||
|
||||
Instance->Destroyed = FALSE;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
Instance->Destroyed = FALSE;
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (Instance->Configured) {
|
||||
//
|
||||
// Delete the related cache entry.
|
||||
//
|
||||
ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
|
||||
|
||||
//
|
||||
// Reset the instance configuration.
|
||||
//
|
||||
ArpConfigureInstance (Instance, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove this instance from the ChildrenList.
|
||||
//
|
||||
NetListRemoveEntry (&Instance->List);
|
||||
ArpService->ChildrenNumber--;
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
NetFreePool (Instance);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (ArpDriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The entry point for Arp driver which installs the driver binding and component name
|
||||
protocol on its ImageHandle.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The image handle of the driver.
|
||||
SystemTable - The system table.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - if the driver binding and component name protocols are successfully
|
||||
installed, otherwise if failed.
|
||||
|
||||
--*/
|
||||
{
|
||||
return NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gArpDriverBinding,
|
||||
ImageHandle,
|
||||
&gArpComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
84
MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h
Normal file
84
MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h
Normal file
@ -0,0 +1,84 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
ArpDriver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARP_DRIVER_H_
|
||||
#define _ARP_DRIVER_H_
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/Arp.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include "ArpDebug.h"
|
||||
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gArpComponentName;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
||||
|
59
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
Normal file
59
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
Normal file
@ -0,0 +1,59 @@
|
||||
#/** @file
|
||||
# Component description file for ARP module
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArpDxe
|
||||
FILE_GUID = 529D3F93-E8E9-4e73-B1E1-BDF6A9D50113
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = ArpDriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
ArpMain.c
|
||||
ArpDriver.h
|
||||
ComponentName.c
|
||||
ArpImpl.h
|
||||
ArpImpl.c
|
||||
ArpDebug.h
|
||||
ArpDriver.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
NetLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
72
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa
Normal file
72
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa
Normal file
@ -0,0 +1,72 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Arp</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>529D3F93-E8E9-4e73-B1E1-BDF6A9D50113</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Arp</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Arp</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>ArpDriver.c</Filename>
|
||||
<Filename>ArpDebug.h</Filename>
|
||||
<Filename>ArpImpl.c</Filename>
|
||||
<Filename>ArpImpl.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>ArpDriver.h</Filename>
|
||||
<Filename>ArpMain.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>ArpDriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
1628
MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
Normal file
1628
MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
Normal file
File diff suppressed because it is too large
Load Diff
341
MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h
Normal file
341
MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h
Normal file
@ -0,0 +1,341 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
ArpImpl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _ARP_IMPL_H_
|
||||
#define _ARP_IMPL_H_
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/Arp.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include "ArpDebug.h"
|
||||
|
||||
#define ARP_ETHER_PROTO_TYPE 0x0806
|
||||
#define IPv4_ETHER_PROTO_TYPE 0x0800
|
||||
#define IPv6_ETHER_PROTO_TYPE 0x86DD
|
||||
|
||||
#define ARP_OPCODE_REQUEST 0x0001
|
||||
#define ARP_OPCODE_REPLY 0x0002
|
||||
|
||||
#define ARP_DEFAULT_TIMEOUT_VALUE (400 * TICKS_PER_SECOND)
|
||||
#define ARP_DEFAULT_RETRY_COUNT 2
|
||||
#define ARP_DEFAULT_RETRY_INTERVAL (5 * TICKS_PER_MS)
|
||||
#define ARP_PERIODIC_TIMER_INTERVAL (500 * TICKS_PER_MS)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _ARP_HEAD {
|
||||
UINT16 HwType;
|
||||
UINT16 ProtoType;
|
||||
UINT8 HwAddrLen;
|
||||
UINT8 ProtoAddrLen;
|
||||
UINT16 OpCode;
|
||||
} ARP_HEAD;
|
||||
#pragma pack()
|
||||
|
||||
typedef struct _ARP_ADDRESS {
|
||||
UINT8 *SenderHwAddr;
|
||||
UINT8 *SenderProtoAddr;
|
||||
UINT8 *TargetHwAddr;
|
||||
UINT8 *TargetProtoAddr;
|
||||
} ARP_ADDRESS;
|
||||
|
||||
#define MATCH_SW_ADDRESS 0x1
|
||||
#define MATCH_HW_ADDRESS 0x2
|
||||
|
||||
typedef enum {
|
||||
ByNone = 0,
|
||||
ByProtoAddress = MATCH_SW_ADDRESS,
|
||||
ByHwAddress = MATCH_HW_ADDRESS,
|
||||
ByBoth = MATCH_SW_ADDRESS | MATCH_HW_ADDRESS
|
||||
} FIND_OPTYPE;
|
||||
|
||||
#define ARP_INSTANCE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'I')
|
||||
|
||||
#define ARP_INSTANCE_DATA_FROM_THIS(a) \
|
||||
CR ( \
|
||||
(a), \
|
||||
ARP_INSTANCE_DATA, \
|
||||
ArpProto, \
|
||||
ARP_INSTANCE_DATA_SIGNATURE \
|
||||
)
|
||||
|
||||
typedef struct _ARP_SERVICE_DATA ARP_SERVICE_DATA;
|
||||
|
||||
typedef struct _ARP_INSTANCE_DATA {
|
||||
UINT32 Signature;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_ARP_PROTOCOL ArpProto;
|
||||
NET_LIST_ENTRY List;
|
||||
EFI_ARP_CONFIG_DATA ConfigData;
|
||||
BOOLEAN Configured;
|
||||
BOOLEAN Destroyed;
|
||||
} ARP_INSTANCE_DATA;
|
||||
|
||||
#define ARP_SERVICE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'S')
|
||||
|
||||
#define ARP_SERVICE_DATA_FROM_THIS(a) \
|
||||
CR ( \
|
||||
(a), \
|
||||
ARP_SERVICE_DATA, \
|
||||
ServiceBinding, \
|
||||
ARP_SERVICE_DATA_SIGNATURE \
|
||||
)
|
||||
|
||||
struct _ARP_SERVICE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
|
||||
EFI_HANDLE MnpChildHandle;
|
||||
EFI_HANDLE ImageHandle;
|
||||
EFI_HANDLE ControllerHandle;
|
||||
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN RxToken;
|
||||
|
||||
EFI_SIMPLE_NETWORK_MODE SnpMode;
|
||||
|
||||
NET_LOCK Lock;
|
||||
|
||||
UINTN ChildrenNumber;
|
||||
NET_LIST_ENTRY ChildrenList;
|
||||
|
||||
NET_LIST_ENTRY PendingRequestTable;
|
||||
NET_LIST_ENTRY DeniedCacheTable;
|
||||
NET_LIST_ENTRY ResolvedCacheTable;
|
||||
|
||||
EFI_EVENT PeriodicTimer;
|
||||
};
|
||||
|
||||
typedef struct _USER_REQUEST_CONTEXT {
|
||||
NET_LIST_ENTRY List;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
EFI_EVENT UserRequestEvent;
|
||||
VOID *UserHwAddrBuffer;
|
||||
} USER_REQUEST_CONTEXT;
|
||||
|
||||
#define ARP_MAX_PROTOCOL_ADDRESS_LEN sizeof(EFI_IP_ADDRESS)
|
||||
#define ARP_MAX_HARDWARE_ADDRESS_LEN sizeof(EFI_MAC_ADDRESS)
|
||||
|
||||
typedef struct _NET_ARP_ADDRESS {
|
||||
UINT16 Type;
|
||||
UINT8 Length;
|
||||
UINT8 *AddressPtr;
|
||||
union {
|
||||
UINT8 ProtoAddress[ARP_MAX_PROTOCOL_ADDRESS_LEN];
|
||||
UINT8 HwAddress[ARP_MAX_HARDWARE_ADDRESS_LEN];
|
||||
} Buffer;
|
||||
} NET_ARP_ADDRESS;
|
||||
|
||||
typedef enum {
|
||||
Hardware,
|
||||
Protocol
|
||||
} ARP_ADDRESS_TYPE;
|
||||
|
||||
typedef struct _ARP_CACHE_ENTRY {
|
||||
NET_LIST_ENTRY List;
|
||||
|
||||
UINT32 RetryCount;
|
||||
UINT32 DefaultDecayTime;
|
||||
UINT32 DecayTime;
|
||||
UINT32 NextRetryTime;
|
||||
|
||||
NET_ARP_ADDRESS Addresses[2];
|
||||
|
||||
NET_LIST_ENTRY UserRequestList;
|
||||
} ARP_CACHE_ENTRY;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpConfigure (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpAdd (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN DenyFlag,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN VOID *TargetHwAddress OPTIONAL,
|
||||
IN UINT32 TimeoutValue,
|
||||
IN BOOLEAN Overwrite
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpFind (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN VOID *AddressBuffer OPTIONAL,
|
||||
OUT UINT32 *EntryLength OPTIONAL,
|
||||
OUT UINT32 *EntryCount OPTIONAL,
|
||||
OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
|
||||
IN BOOLEAN Refresh
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDelete (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN VOID *AddressBuffer OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpFlush (
|
||||
IN EFI_ARP_PROTOCOL *This
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpRequest (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN EFI_EVENT ResolvedEvent OPTIONAL,
|
||||
OUT VOID *TargetHwAddress
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpCancel (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN EFI_EVENT ResolvedEvent OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArpConfigureInstance (
|
||||
IN ARP_INSTANCE_DATA *Instance,
|
||||
IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
|
||||
);
|
||||
|
||||
ARP_CACHE_ENTRY *
|
||||
ArpFindDeniedCacheEntry (
|
||||
IN ARP_SERVICE_DATA *ArpService,
|
||||
IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
|
||||
IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
|
||||
);
|
||||
|
||||
ARP_CACHE_ENTRY *
|
||||
ArpFindNextCacheEntryInTable (
|
||||
IN NET_LIST_ENTRY *CacheTable,
|
||||
IN NET_LIST_ENTRY *StartEntry,
|
||||
IN FIND_OPTYPE FindOpType,
|
||||
IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
|
||||
IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
|
||||
);
|
||||
|
||||
ARP_CACHE_ENTRY *
|
||||
ArpAllocCacheEntry (
|
||||
IN ARP_INSTANCE_DATA *Instance
|
||||
);
|
||||
|
||||
VOID
|
||||
ArpFillAddressInCacheEntry (
|
||||
IN ARP_CACHE_ENTRY *CacheEntry,
|
||||
IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
|
||||
IN NET_ARP_ADDRESS *SwAddr OPTIONAL
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArpAddressResolved (
|
||||
IN ARP_CACHE_ENTRY *CacheEntry,
|
||||
IN ARP_INSTANCE_DATA *Instance OPTIONAL,
|
||||
IN EFI_EVENT UserEvent OPTIONAL
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArpDeleteCacheEntry (
|
||||
IN ARP_INSTANCE_DATA *Instance,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN UINT8 *AddressBuffer OPTIONAL,
|
||||
IN BOOLEAN Force
|
||||
);
|
||||
|
||||
VOID
|
||||
ArpSendFrame (
|
||||
IN ARP_INSTANCE_DATA *Instance,
|
||||
IN ARP_CACHE_ENTRY *CacheEntry,
|
||||
IN UINT16 ArpOpCode
|
||||
);
|
||||
|
||||
VOID
|
||||
ArpInitInstance (
|
||||
IN ARP_SERVICE_DATA *ArpService,
|
||||
IN ARP_INSTANCE_DATA *Instance
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArpOnFrameRcvd (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArpOnFrameSent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArpTimerHandler (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArpCancelRequest (
|
||||
IN ARP_INSTANCE_DATA *Instance,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN EFI_EVENT UserEvent OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArpFindCacheEntry (
|
||||
IN ARP_INSTANCE_DATA *Instance,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN VOID *AddressBuffer OPTIONAL,
|
||||
OUT UINT32 *EntryLength OPTIONAL,
|
||||
OUT UINT32 *EntryCount OPTIONAL,
|
||||
OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
|
||||
IN BOOLEAN Refresh
|
||||
);
|
||||
|
||||
#endif
|
||||
|
727
MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c
Normal file
727
MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c
Normal file
@ -0,0 +1,727 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
ArpMain.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "ArpImpl.h"
|
||||
|
||||
|
||||
/**
|
||||
This function is used to assign a station address to the ARP cache for this instance
|
||||
of the ARP driver. A call to this function with the ConfigData field set to NULL
|
||||
will reset this ARP instance.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param ConfigData Pointer to the EFI_ARP_CONFIG_DATA structure.
|
||||
|
||||
@retval EFI_SUCCESS The new station address was successfully
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
This is NULL. SwAddressLength is zero when
|
||||
ConfigData is not NULL. StationAddress is NULL
|
||||
when ConfigData is not NULL.
|
||||
@retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or
|
||||
StationAddress is different from the one that is
|
||||
already registered.
|
||||
@retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be
|
||||
allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpConfigure (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((ConfigData != NULL) &&
|
||||
((ConfigData->SwAddressLength == 0) ||
|
||||
(ConfigData->StationAddress == NULL) ||
|
||||
(ConfigData->SwAddressType <= 1500))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&Instance->ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure this instance, the ConfigData has already passed the basic checks.
|
||||
//
|
||||
Status = ArpConfigureInstance (Instance, ConfigData);
|
||||
|
||||
NET_UNLOCK (&Instance->ArpService->Lock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function is used to insert entries into the ARP cache.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param DenyFlag Set to TRUE if this entry is a deny entry. Set to
|
||||
FALSE if this entry is a normal entry.
|
||||
@param TargetSwAddress Pointer to a protocol address to add (or deny).
|
||||
May be set to NULL if DenyFlag is TRUE.
|
||||
@param TargetHwAddress Pointer to a hardware address to add (or deny).
|
||||
May be set to NULL if DenyFlag is TRUE.
|
||||
@param TimeoutValue Time in 100-ns units that this entry will remain
|
||||
in the ARP cache. A value of zero means that the
|
||||
entry is permanent. A nonzero value will override
|
||||
the one given by Configure() if the entry to be
|
||||
added is a dynamic entry.
|
||||
@param Overwrite If TRUE, the matching cache entry will be
|
||||
overwritten with the supplied parameters. If
|
||||
FALSE, EFI_ACCESS_DENIED is returned if the
|
||||
corresponding cache entry already exists.
|
||||
|
||||
@retval EFI_SUCCESS The entry has been added or updated.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
This is NULL. DenyFlag is FALSE and
|
||||
TargetHwAddress is NULL. DenyFlag is FALSE and
|
||||
TargetSwAddress is NULL. TargetHwAddress is NULL
|
||||
and TargetSwAddress is NULL. Both TargetSwAddress
|
||||
and TargetHwAddress are not NULL when DenyFlag is
|
||||
TRUE.
|
||||
@retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated.
|
||||
@retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite
|
||||
is not true.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpAdd (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN DenyFlag,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN VOID *TargetHwAddress OPTIONAL,
|
||||
IN UINT32 TimeoutValue,
|
||||
IN BOOLEAN Overwrite
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
ARP_CACHE_ENTRY *CacheEntry;
|
||||
EFI_SIMPLE_NETWORK_MODE *SnpMode;
|
||||
NET_ARP_ADDRESS MatchAddress[2];
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (((!DenyFlag) && ((TargetHwAddress == NULL) || (TargetSwAddress == NULL))) ||
|
||||
(DenyFlag && (TargetHwAddress != NULL) && (TargetSwAddress != NULL)) ||
|
||||
((TargetHwAddress == NULL) && (TargetSwAddress == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
ArpService = Instance->ArpService;
|
||||
SnpMode = &Instance->ArpService->SnpMode;
|
||||
|
||||
//
|
||||
// Fill the hardware address part in the MatchAddress.
|
||||
//
|
||||
MatchAddress[Hardware].Type = SnpMode->IfType;
|
||||
MatchAddress[Hardware].Length = (UINT8) SnpMode->HwAddressSize;
|
||||
MatchAddress[Hardware].AddressPtr = TargetHwAddress;
|
||||
|
||||
//
|
||||
// Fill the software address part in the MatchAddress.
|
||||
//
|
||||
MatchAddress[Protocol].Type = Instance->ConfigData.SwAddressType;
|
||||
MatchAddress[Protocol].Length = Instance->ConfigData.SwAddressLength;
|
||||
MatchAddress[Protocol].AddressPtr = TargetSwAddress;
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// See whether the entry to add exists. Check the DeinedCacheTable first.
|
||||
//
|
||||
CacheEntry = ArpFindDeniedCacheEntry (
|
||||
ArpService,
|
||||
&MatchAddress[Protocol],
|
||||
&MatchAddress[Hardware]
|
||||
);
|
||||
|
||||
if (CacheEntry == NULL) {
|
||||
//
|
||||
// Check the ResolvedCacheTable
|
||||
//
|
||||
CacheEntry = ArpFindNextCacheEntryInTable (
|
||||
&ArpService->ResolvedCacheTable,
|
||||
NULL,
|
||||
ByBoth,
|
||||
&MatchAddress[Protocol],
|
||||
&MatchAddress[Hardware]
|
||||
);
|
||||
}
|
||||
|
||||
if ((CacheEntry != NULL) && !Overwrite) {
|
||||
//
|
||||
// The entry to add exists, if not Overwirte, deny this add request.
|
||||
//
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
if ((CacheEntry == NULL) && (TargetSwAddress != NULL)) {
|
||||
//
|
||||
// Check whether there are pending requests matching the entry to be added.
|
||||
//
|
||||
CacheEntry = ArpFindNextCacheEntryInTable (
|
||||
&ArpService->PendingRequestTable,
|
||||
NULL,
|
||||
ByProtoAddress,
|
||||
&MatchAddress[Protocol],
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
if (CacheEntry != NULL) {
|
||||
//
|
||||
// Remove it from the Table.
|
||||
//
|
||||
NetListRemoveEntry (&CacheEntry->List);
|
||||
} else {
|
||||
//
|
||||
// It's a new entry, allocate memory for the entry.
|
||||
//
|
||||
CacheEntry = ArpAllocCacheEntry (Instance);
|
||||
|
||||
if (CacheEntry == NULL) {
|
||||
ARP_DEBUG_ERROR (("ArpAdd: Failed to allocate pool for CacheEntry.\n"));
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Overwrite these parameters.
|
||||
//
|
||||
CacheEntry->DefaultDecayTime = TimeoutValue;
|
||||
CacheEntry->DecayTime = TimeoutValue;
|
||||
|
||||
//
|
||||
// Fill in the addresses.
|
||||
//
|
||||
ArpFillAddressInCacheEntry (
|
||||
CacheEntry,
|
||||
&MatchAddress[Hardware],
|
||||
&MatchAddress[Protocol]
|
||||
);
|
||||
|
||||
//
|
||||
// Inform the user if there is any.
|
||||
//
|
||||
ArpAddressResolved (CacheEntry, NULL, NULL);
|
||||
|
||||
//
|
||||
// Add this CacheEntry to the corresponding CacheTable.
|
||||
//
|
||||
if (DenyFlag) {
|
||||
NetListInsertHead (&ArpService->DeniedCacheTable, &CacheEntry->List);
|
||||
} else {
|
||||
NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);
|
||||
}
|
||||
|
||||
UNLOCK_EXIT:
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function searches the ARP cache for matching entries and allocates a buffer into
|
||||
which those entries are copied.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param BySwAddress Set to TRUE to look for matching software protocol
|
||||
addresses. Set to FALSE to look for matching
|
||||
hardware protocol addresses.
|
||||
@param AddressBuffer Pointer to address buffer. Set to NULL to match
|
||||
all addresses.
|
||||
@param EntryLength The size of an entry in the entries buffer.
|
||||
@param EntryCount The number of ARP cache entries that are found by
|
||||
the specified criteria.
|
||||
@param Entries Pointer to the buffer that will receive the ARP
|
||||
cache entries.
|
||||
@param Refresh Set to TRUE to refresh the timeout value of the
|
||||
matching ARP cache entry.
|
||||
|
||||
@retval EFI_SUCCESS The requested ARP cache entries were copied into
|
||||
the buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
This is NULL. Both EntryCount and EntryLength are
|
||||
NULL, when Refresh is FALSE.
|
||||
@retval EFI_NOT_FOUND No matching entries were found.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpFind (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN VOID *AddressBuffer OPTIONAL,
|
||||
OUT UINT32 *EntryLength OPTIONAL,
|
||||
OUT UINT32 *EntryCount OPTIONAL,
|
||||
OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
|
||||
IN BOOLEAN Refresh
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
|
||||
if ((This == NULL) ||
|
||||
(!Refresh && (EntryCount == NULL) && (EntryLength == NULL)) ||
|
||||
((Entries != NULL) && ((EntryLength == NULL) || (EntryCount == NULL)))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
ArpService = Instance->ArpService;
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// All the check passed, find the cache entries now.
|
||||
//
|
||||
Status = ArpFindCacheEntry (
|
||||
Instance,
|
||||
BySwAddress,
|
||||
AddressBuffer,
|
||||
EntryLength,
|
||||
EntryCount,
|
||||
Entries,
|
||||
Refresh
|
||||
);
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function removes specified ARP cache entries.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param BySwAddress Set to TRUE to delete matching protocol addresses.
|
||||
Set to FALSE to delete matching hardware
|
||||
addresses.
|
||||
@param AddressBuffer Pointer to the address buffer that is used as a
|
||||
key to look for the cache entry. Set to NULL to
|
||||
delete all entries.
|
||||
|
||||
@retval EFI_SUCCESS The entry was removed from the ARP cache.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_NOT_FOUND The specified deletion key was not found.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpDelete (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN BOOLEAN BySwAddress,
|
||||
IN VOID *AddressBuffer OPTIONAL
|
||||
)
|
||||
{
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
UINTN Count;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
ArpService = Instance->ArpService;
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete the specified cache entries.
|
||||
//
|
||||
Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function delete all dynamic entries from the ARP cache that match the specified
|
||||
software protocol type.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The cache has been flushed.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_NOT_FOUND There are no matching dynamic cache entries.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpFlush (
|
||||
IN EFI_ARP_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
UINTN Count;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
ArpService = Instance->ArpService;
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete the dynamic entries from the cache table.
|
||||
//
|
||||
Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function tries to resolve the TargetSwAddress and optionally returns a
|
||||
TargetHwAddress if it already exists in the ARP cache.
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param TargetSwAddress Pointer to the protocol address to resolve.
|
||||
@param ResolvedEvent Pointer to the event that will be signaled when
|
||||
the address is resolved or some error occurs.
|
||||
@param TargetHwAddress Pointer to the buffer for the resolved hardware
|
||||
address in network byte order.
|
||||
|
||||
@retval EFI_SUCCESS The data is copied from the ARP cache into the
|
||||
TargetHwAddress buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
This is NULL. TargetHwAddress is NULL.
|
||||
@retval EFI_ACCESS_DENIED The requested address is not present in the normal
|
||||
ARP cache but is present in the deny address list.
|
||||
Outgoing traffic to that address is forbidden.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
@retval EFI_NOT_READY The request has been started and is not finished.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpRequest (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN EFI_EVENT ResolvedEvent OPTIONAL,
|
||||
OUT VOID *TargetHwAddress
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
EFI_SIMPLE_NETWORK_MODE *SnpMode;
|
||||
ARP_CACHE_ENTRY *CacheEntry;
|
||||
NET_ARP_ADDRESS HardwareAddress;
|
||||
NET_ARP_ADDRESS ProtocolAddress;
|
||||
USER_REQUEST_CONTEXT *RequestContext;
|
||||
|
||||
if ((This == NULL) || (TargetHwAddress == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
ArpService = Instance->ArpService;
|
||||
SnpMode = &ArpService->SnpMode;
|
||||
|
||||
if ((TargetSwAddress == NULL) ||
|
||||
((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&
|
||||
IP4_IS_LOCAL_BROADCAST (*((UINT32 *)TargetSwAddress)))) {
|
||||
//
|
||||
// Return the hardware broadcast address.
|
||||
//
|
||||
NetCopyMem (TargetHwAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
|
||||
|
||||
goto SIGNAL_USER;
|
||||
}
|
||||
|
||||
if ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&
|
||||
IP4_IS_MULTICAST (NTOHL (*((UINT32 *)TargetSwAddress)))) {
|
||||
//
|
||||
// If the software address is an IPv4 multicast address, invoke Mnp to
|
||||
// resolve the address.
|
||||
//
|
||||
Status = ArpService->Mnp->McastIpToMac (
|
||||
ArpService->Mnp,
|
||||
FALSE,
|
||||
TargetSwAddress,
|
||||
TargetHwAddress
|
||||
);
|
||||
goto SIGNAL_USER;
|
||||
}
|
||||
|
||||
HardwareAddress.Type = SnpMode->IfType;
|
||||
HardwareAddress.Length = (UINT8)SnpMode->HwAddressSize;
|
||||
HardwareAddress.AddressPtr = NULL;
|
||||
|
||||
ProtocolAddress.Type = Instance->ConfigData.SwAddressType;
|
||||
ProtocolAddress.Length = Instance->ConfigData.SwAddressLength;
|
||||
ProtocolAddress.AddressPtr = TargetSwAddress;
|
||||
|
||||
//
|
||||
// Initialize the TargetHwAddrss to a zero address.
|
||||
//
|
||||
NetZeroMem (TargetHwAddress, SnpMode->HwAddressSize);
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether the software address is in the denied table.
|
||||
//
|
||||
CacheEntry = ArpFindDeniedCacheEntry (ArpService, &ProtocolAddress, NULL);
|
||||
if (CacheEntry != NULL) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether the software address is already resolved.
|
||||
//
|
||||
CacheEntry = ArpFindNextCacheEntryInTable (
|
||||
&ArpService->ResolvedCacheTable,
|
||||
NULL,
|
||||
ByProtoAddress,
|
||||
&ProtocolAddress,
|
||||
NULL
|
||||
);
|
||||
if (CacheEntry != NULL) {
|
||||
//
|
||||
// Resolved, copy the address into the user buffer.
|
||||
//
|
||||
NetCopyMem (
|
||||
TargetHwAddress,
|
||||
CacheEntry->Addresses[Hardware].AddressPtr,
|
||||
CacheEntry->Addresses[Hardware].Length
|
||||
);
|
||||
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
if (ResolvedEvent == NULL) {
|
||||
Status = EFI_NOT_READY;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a request context for this arp request.
|
||||
//
|
||||
RequestContext = NetAllocatePool (sizeof(USER_REQUEST_CONTEXT));
|
||||
if (RequestContext == NULL) {
|
||||
ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for RequestContext failed.\n"));
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
RequestContext->Instance = Instance;
|
||||
RequestContext->UserRequestEvent = ResolvedEvent;
|
||||
RequestContext->UserHwAddrBuffer = TargetHwAddress;
|
||||
NetListInit (&RequestContext->List);
|
||||
|
||||
//
|
||||
// Check whether there is a same request.
|
||||
//
|
||||
CacheEntry = ArpFindNextCacheEntryInTable (
|
||||
&ArpService->PendingRequestTable,
|
||||
NULL,
|
||||
ByProtoAddress,
|
||||
&ProtocolAddress,
|
||||
NULL
|
||||
);
|
||||
if (CacheEntry != NULL) {
|
||||
|
||||
CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
|
||||
CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
|
||||
} else {
|
||||
//
|
||||
// Allocate a cache entry for this request.
|
||||
//
|
||||
CacheEntry = ArpAllocCacheEntry (Instance);
|
||||
if (CacheEntry == NULL) {
|
||||
ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for CacheEntry failed.\n"));
|
||||
NetFreePool (RequestContext);
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto UNLOCK_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill the software address.
|
||||
//
|
||||
ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);
|
||||
|
||||
//
|
||||
// Add this entry into the PendingRequestTable.
|
||||
//
|
||||
NetListInsertTail (&ArpService->PendingRequestTable, &CacheEntry->List);
|
||||
}
|
||||
|
||||
//
|
||||
// Link this request context into the cache entry.
|
||||
//
|
||||
NetListInsertHead (&CacheEntry->UserRequestList, &RequestContext->List);
|
||||
|
||||
//
|
||||
// Send out the ARP Request frame.
|
||||
//
|
||||
ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);
|
||||
Status = EFI_NOT_READY;
|
||||
|
||||
UNLOCK_EXIT:
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
SIGNAL_USER:
|
||||
|
||||
if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {
|
||||
gBS->SignalEvent (ResolvedEvent);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function aborts the previous ARP request (identified by This, TargetSwAddress
|
||||
and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().
|
||||
|
||||
@param This Pointer to the EFI_ARP_PROTOCOL instance.
|
||||
@param TargetSwAddress Pointer to the protocol address in previous
|
||||
request session.
|
||||
@param ResolvedEvent Pointer to the event that is used as the
|
||||
notification event in previous request session.
|
||||
|
||||
@retval EFI_SUCCESS The pending request session(s) is/are aborted and
|
||||
corresponding event(s) is/are signaled.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
This is NULL. TargetSwAddress is not NULL and
|
||||
ResolvedEvent is NULL. TargetSwAddress is NULL and
|
||||
ResolvedEvent is not NULL.
|
||||
@retval EFI_NOT_STARTED The ARP driver instance has not been configured.
|
||||
@retval EFI_NOT_FOUND The request is not issued by
|
||||
EFI_ARP_PROTOCOL.Request().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpCancel (
|
||||
IN EFI_ARP_PROTOCOL *This,
|
||||
IN VOID *TargetSwAddress OPTIONAL,
|
||||
IN EFI_EVENT ResolvedEvent OPTIONAL
|
||||
)
|
||||
{
|
||||
ARP_INSTANCE_DATA *Instance;
|
||||
ARP_SERVICE_DATA *ArpService;
|
||||
UINTN Count;
|
||||
|
||||
if ((This == NULL) ||
|
||||
((TargetSwAddress != NULL) && (ResolvedEvent == NULL)) ||
|
||||
((TargetSwAddress == NULL) && (ResolvedEvent != NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
|
||||
|
||||
if (!Instance->Configured) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
ArpService = Instance->ArpService;
|
||||
|
||||
if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Cancel the specified request.
|
||||
//
|
||||
Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);
|
||||
|
||||
NET_UNLOCK (&ArpService->Lock);
|
||||
|
||||
return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
|
||||
}
|
156
MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c
Normal file
156
MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c
Normal file
@ -0,0 +1,156 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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 "ArpDriver.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpComponentNameGetControllerName (
|
||||
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 gArpComponentName = {
|
||||
ArpComponentNameGetDriverName,
|
||||
ArpComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
STATIC EFI_UNICODE_STRING_TABLE mArpDriverNameTable[] = {
|
||||
{ "eng", L"ARP Network Service Driver" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpComponentNameGetDriverName (
|
||||
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_SUCCES - 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,
|
||||
gArpComponentName.SupportedLanguages,
|
||||
mArpDriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArpComponentNameGetControllerName (
|
||||
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;
|
||||
}
|
||||
|
162
MdeModulePkg/Universal/Network/Dhcp4Dxe/ComponentName.c
Normal file
162
MdeModulePkg/Universal/Network/Dhcp4Dxe/ComponentName.c
Normal file
@ -0,0 +1,162 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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 "Dhcp4Impl.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetControllerName (
|
||||
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 gDhcp4ComponentName = {
|
||||
DhcpComponentNameGetDriverName,
|
||||
DhcpComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
static EFI_UNICODE_STRING_TABLE mDhcpDriverNameTable[] = {
|
||||
{
|
||||
"eng",
|
||||
L"DHCP Protocol Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetDriverName (
|
||||
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_SUCCES - 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,
|
||||
gDhcp4ComponentName.SupportedLanguages,
|
||||
mDhcpDriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DhcpComponentNameGetControllerName (
|
||||
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 isn't NULL and isn't 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;
|
||||
}
|
665
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c
Normal file
665
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c
Normal file
@ -0,0 +1,665 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Dhcp4Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
#include "Dhcp4Driver.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {
|
||||
Dhcp4DriverBindingSupported,
|
||||
Dhcp4DriverBindingStart,
|
||||
Dhcp4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete = {
|
||||
Dhcp4ServiceBindingCreateChild,
|
||||
Dhcp4ServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Dhcp4DriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Entry point of the DHCP driver to install various protocols.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The driver's image handle
|
||||
SystemTable - The system table
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - All the related protocols are installed.
|
||||
Others - Failed to install the protocols.
|
||||
|
||||
--*/
|
||||
{
|
||||
return NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gDhcp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gDhcp4ComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if DHCP driver supports the ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver supports this device
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiUdp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Configure the default UDP child to receive all the DHCP traffics
|
||||
on this network interface.
|
||||
|
||||
@param UdpIo The UDP IO port to configure
|
||||
@param Context The context to the function
|
||||
|
||||
@retval EFI_SUCCESS The UDP IO port is successfully configured.
|
||||
@retval Others Failed to configure the UDP child.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpConfigUdpIo (
|
||||
IN UDP_IO_PORT *UdpIo,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_UDP4_CONFIG_DATA UdpConfigData;
|
||||
|
||||
UdpConfigData.AcceptBroadcast = TRUE;
|
||||
UdpConfigData.AcceptPromiscuous = FALSE;
|
||||
UdpConfigData.AcceptAnyPort = FALSE;
|
||||
UdpConfigData.AllowDuplicatePort = TRUE;
|
||||
UdpConfigData.TypeOfService = 0;
|
||||
UdpConfigData.TimeToLive = 64;
|
||||
UdpConfigData.DoNotFragment = FALSE;
|
||||
UdpConfigData.ReceiveTimeout = 0;
|
||||
UdpConfigData.TransmitTimeout = 0;
|
||||
|
||||
UdpConfigData.UseDefaultAddress = FALSE;
|
||||
UdpConfigData.StationPort = DHCP_CLIENT_PORT;
|
||||
UdpConfigData.RemotePort = DHCP_SERVER_PORT;
|
||||
|
||||
NetZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Destory the DHCP service. The Dhcp4 service may be partly initialized,
|
||||
or partly destoried. If a resource is destoried, it is marked as so in
|
||||
case the destory failed and being called again later.
|
||||
|
||||
@param DhcpSb The DHCP service instance to destory.
|
||||
|
||||
@retval EFI_SUCCESS The DHCP service is successfully closed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Dhcp4CloseService (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
)
|
||||
{
|
||||
DhcpCleanLease (DhcpSb);
|
||||
|
||||
if (DhcpSb->UdpIo != NULL) {
|
||||
UdpIoFreePort (DhcpSb->UdpIo);
|
||||
DhcpSb->UdpIo = NULL;
|
||||
}
|
||||
|
||||
if (DhcpSb->Timer != NULL) {
|
||||
gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);
|
||||
gBS->CloseEvent (DhcpSb->Timer);
|
||||
|
||||
DhcpSb->Timer = NULL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Create a new DHCP service binding instance for the controller.
|
||||
|
||||
@param Controller The controller to install DHCP service binding
|
||||
protocol onto
|
||||
@param ImageHandle The driver's image handle
|
||||
@param Service The variable to receive the created DHCP service
|
||||
instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource .
|
||||
@retval EFI_SUCCESS The DHCP service instance is created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Dhcp4CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT DHCP_SERVICE **Service
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
*Service = NULL;
|
||||
DhcpSb = NetAllocateZeroPool (sizeof (DHCP_SERVICE));
|
||||
|
||||
if (DhcpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;
|
||||
DhcpSb->ServiceBinding = mDhcp4ServiceBindingTemplete;
|
||||
DhcpSb->ServiceState = DHCP_UNCONFIGED;
|
||||
DhcpSb->InDestory = FALSE;
|
||||
DhcpSb->Controller = Controller;
|
||||
DhcpSb->Image = ImageHandle;
|
||||
NetListInit (&DhcpSb->Children);
|
||||
DhcpSb->DhcpState = Dhcp4Stopped;
|
||||
DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
|
||||
|
||||
//
|
||||
// Create various resources, UdpIo, Timer, and get Mac address
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
DhcpOnTimerTick,
|
||||
DhcpSb,
|
||||
&DhcpSb->Timer
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL);
|
||||
|
||||
if (DhcpSb->UdpIo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize;
|
||||
DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;
|
||||
CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));
|
||||
|
||||
*Service = DhcpSb;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
NetFreePool (DhcpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver is added to ControllerHandle
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// First: test for the DHCP4 Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Dhcp4ServiceBinding Protocol onto ControlerHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
&DhcpSb->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
ON_ERROR:
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
NetFreePool (DhcpSb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCES This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// DHCP driver opens UDP child, So, the ControllerHandle is the
|
||||
// UDP child handle. locate the Nic handle first.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);
|
||||
|
||||
if (DhcpSb->InDestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb->InDestory = TRUE;
|
||||
|
||||
//
|
||||
// Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild
|
||||
// may cause other child to be deleted.
|
||||
//
|
||||
while (!NetListIsEmpty (&DhcpSb->Children)) {
|
||||
Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);
|
||||
Dhcp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
|
||||
}
|
||||
|
||||
if (DhcpSb->NumChildren != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->ServiceState = DHCP_DESTORY;
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiDhcp4ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Dhcp4CloseService (DhcpSb);
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
NetFreePool (DhcpSb);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
DhcpSb->InDestory = FALSE;
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize a new DHCP child
|
||||
|
||||
@param DhcpSb The dhcp service instance
|
||||
@param Instance The dhcp instance to initialize
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpInitProtocol (
|
||||
IN DHCP_SERVICE *DhcpSb,
|
||||
IN DHCP_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
Instance->Signature = DHCP_PROTOCOL_SIGNATURE;
|
||||
CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (EFI_DHCP4_PROTOCOL));
|
||||
NetListInit (&Instance->Link);
|
||||
Instance->Handle = NULL;
|
||||
Instance->Service = DhcpSb;
|
||||
Instance->InDestory = FALSE;
|
||||
Instance->CompletionEvent = NULL;
|
||||
Instance->RenewRebindEvent = NULL;
|
||||
Instance->Token = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of DHCP4 services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it
|
||||
is not NULL, then the DHCP4 services are added to
|
||||
the existing child handle.
|
||||
|
||||
@retval EFI_SUCCES The child handle was created with the DHCP4
|
||||
services
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child
|
||||
@retval other The child handle was not created
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
VOID *Udp4;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = NetAllocatePool (sizeof (*Instance));
|
||||
|
||||
if (Instance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (This);
|
||||
DhcpInitProtocol (DhcpSb, Instance);
|
||||
|
||||
//
|
||||
// Install DHCP4 onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
&Instance->Dhcp4Protocol,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetFreePool (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Instance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Udp4 protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
DhcpSb->UdpIo->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
(VOID **) &Udp4,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
Instance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
&Instance->Dhcp4Protocol,
|
||||
NULL
|
||||
);
|
||||
|
||||
NetFreePool (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
NetListInsertTail (&DhcpSb->Children, &Instance->Link);
|
||||
DhcpSb->NumChildren++;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of DHCP4 services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Handle of the child to destroy
|
||||
|
||||
@retval EFI_SUCCES The DHCP4 service is removed from the child handle
|
||||
@retval EFI_UNSUPPORTED The child handle does not support the DHCP4
|
||||
service
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
|
||||
its DHCP4 services are being used.
|
||||
@retval other The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
EFI_DHCP4_PROTOCOL *Dhcp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
(VOID **) &Dhcp,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);
|
||||
DhcpSb = DHCP_SERVICE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Service != DhcpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// A child can be destoried more than once. For example,
|
||||
// Dhcp4DriverBindingStop will destory all of its children.
|
||||
// when caller driver is being stopped, it will destory the
|
||||
// dhcp child it opens.
|
||||
//
|
||||
if (Instance->InDestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
Instance->InDestory = TRUE;
|
||||
|
||||
//
|
||||
// Close the Udp4 protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
DhcpSb->UdpIo->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
gDhcp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the DHCP4 protocol first to enable a top down destruction.
|
||||
//
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiDhcp4ProtocolGuid,
|
||||
Dhcp
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Instance->InDestory = FALSE;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (DhcpSb->ActiveChild == Instance) {
|
||||
DhcpYieldControl (DhcpSb);
|
||||
}
|
||||
|
||||
NetListRemoveEntry (&Instance->Link);
|
||||
DhcpSb->NumChildren--;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
NetFreePool (Instance);
|
||||
return EFI_SUCCESS;
|
||||
}
|
67
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.h
Normal file
67
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.h
Normal file
@ -0,0 +1,67 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Dhcp4Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header for the DHCP4 driver
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_DRIVER_H__
|
||||
#define __EFI_DHCP4_DRIVER_H__
|
||||
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gDhcp4ComponentName;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Dhcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
65
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
Normal file
65
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
Normal file
@ -0,0 +1,65 @@
|
||||
#/** @file
|
||||
# Component name for module Dhcp4
|
||||
#
|
||||
# Copyright (c) 2007, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Dhcp4Dxe
|
||||
FILE_GUID = 94734718-0BBC-47fb-96A5-EE7A5AE6A2AD
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = Dhcp4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Dhcp4Impl.c
|
||||
Dhcp4Io.c
|
||||
Dhcp4Io.h
|
||||
ComponentName.c
|
||||
Dhcp4Driver.h
|
||||
Dhcp4Driver.c
|
||||
Dhcp4Option.c
|
||||
Dhcp4Option.h
|
||||
Dhcp4Impl.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
NetLib
|
||||
UdpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiDhcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiDhcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
77
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.msa
Normal file
77
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.msa
Normal file
@ -0,0 +1,77 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Dhcp4Dxe</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>94734718-0BBC-47fb-96A5-EE7A5AE6A2AD</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Dhcp4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Dhcp4Dxe</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>Dhcp4Impl.h</Filename>
|
||||
<Filename>Dhcp4Option.h</Filename>
|
||||
<Filename>Dhcp4Option.c</Filename>
|
||||
<Filename>Dhcp4Driver.c</Filename>
|
||||
<Filename>Dhcp4Driver.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>Dhcp4Io.h</Filename>
|
||||
<Filename>Dhcp4Io.c</Filename>
|
||||
<Filename>Dhcp4Impl.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiDhcp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiUdp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiDhcp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiUdp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>Dhcp4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
914
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Normal file
914
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Normal file
@ -0,0 +1,914 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Dhcp4Impl.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file implement the EFI_DHCP4_PROTOCOL interface.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Get the current operation parameter and lease for the network interface.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param Dhcp4ModeData The variable to save the DHCP mode data.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid
|
||||
@retval EFI_SUCCESS The Dhcp4ModeData is updated with the current
|
||||
operation parameter.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4GetModeData (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
DHCP_PARAMETER *Para;
|
||||
EFI_TPL OldTpl;
|
||||
IP4_ADDR Ip;
|
||||
|
||||
//
|
||||
// First validate the parameters.
|
||||
//
|
||||
if ((This == NULL) || (Dhcp4ModeData == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb = Instance->Service;
|
||||
|
||||
//
|
||||
// Caller can use GetModeData to retrieve current DHCP states
|
||||
// no matter whether it is the active child or not.
|
||||
//
|
||||
Dhcp4ModeData->State = DhcpSb->DhcpState;
|
||||
CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (EFI_DHCP4_CONFIG_DATA));
|
||||
CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (EFI_MAC_ADDRESS));
|
||||
|
||||
Ip = HTONL (DhcpSb->ClientAddr);
|
||||
NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Ip = HTONL (DhcpSb->Netmask);
|
||||
NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Ip = HTONL (DhcpSb->ServerAddr);
|
||||
NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Para = DhcpSb->Para;
|
||||
|
||||
if (Para != NULL) {
|
||||
Ip = HTONL (Para->Router);
|
||||
NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
Dhcp4ModeData->LeaseTime = Para->Lease;
|
||||
} else {
|
||||
NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
Dhcp4ModeData->LeaseTime = 0xffffffff;
|
||||
}
|
||||
|
||||
Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the resource related to the configure parameters.
|
||||
DHCP driver will make a copy of the user's configure
|
||||
such as the time out value.
|
||||
|
||||
@param Config The DHCP configure data
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpCleanConfigure (
|
||||
IN EFI_DHCP4_CONFIG_DATA *Config
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
if (Config->DiscoverTimeout != NULL) {
|
||||
NetFreePool (Config->DiscoverTimeout);
|
||||
}
|
||||
|
||||
if (Config->RequestTimeout != NULL) {
|
||||
NetFreePool (Config->RequestTimeout);
|
||||
}
|
||||
|
||||
if (Config->OptionList != NULL) {
|
||||
for (Index = 0; Index < Config->OptionCount; Index++) {
|
||||
if (Config->OptionList[Index] != NULL) {
|
||||
NetFreePool (Config->OptionList[Index]);
|
||||
}
|
||||
}
|
||||
|
||||
NetFreePool (Config->OptionList);
|
||||
}
|
||||
|
||||
NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate memory for configure parameter such as timeout value for Dst,
|
||||
then copy the configure parameter from Src to Dst.
|
||||
|
||||
@param Dst The destination DHCP configure data.
|
||||
@param Src The source DHCP configure data.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
||||
@retval EFI_SUCCESS The configure is copied.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpCopyConfigure (
|
||||
IN EFI_DHCP4_CONFIG_DATA *Dst,
|
||||
IN EFI_DHCP4_CONFIG_DATA *Src
|
||||
)
|
||||
{
|
||||
EFI_DHCP4_PACKET_OPTION **DstOptions;
|
||||
EFI_DHCP4_PACKET_OPTION **SrcOptions;
|
||||
INTN Len;
|
||||
UINT32 Index;
|
||||
|
||||
CopyMem (Dst, Src, sizeof (EFI_DHCP4_CONFIG_DATA));
|
||||
Dst->DiscoverTimeout = NULL;
|
||||
Dst->RequestTimeout = NULL;
|
||||
Dst->OptionList = NULL;
|
||||
|
||||
//
|
||||
// Allocate a memory then copy DiscoverTimeout to it
|
||||
//
|
||||
if (Src->DiscoverTimeout != NULL) {
|
||||
Len = Src->DiscoverTryCount * sizeof (UINT32);
|
||||
Dst->DiscoverTimeout = NetAllocatePool (Len);
|
||||
|
||||
if (Dst->DiscoverTimeout == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Src->DiscoverTryCount; Index++) {
|
||||
Dst->DiscoverTimeout[Index] = NET_MAX (Src->DiscoverTimeout[Index], 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a memory then copy RequestTimeout to it
|
||||
//
|
||||
if (Src->RequestTimeout != NULL) {
|
||||
Len = Src->RequestTryCount * sizeof (UINT32);
|
||||
Dst->RequestTimeout = NetAllocatePool (Len);
|
||||
|
||||
if (Dst->RequestTimeout == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Src->RequestTryCount; Index++) {
|
||||
Dst->RequestTimeout[Index] = NET_MAX (Src->RequestTimeout[Index], 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate an array of dhcp option point, then allocate memory
|
||||
// for each option and copy the source option to it
|
||||
//
|
||||
if (Src->OptionList != NULL) {
|
||||
Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);
|
||||
Dst->OptionList = NetAllocateZeroPool (Len);
|
||||
|
||||
if (Dst->OptionList == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DstOptions = Dst->OptionList;
|
||||
SrcOptions = Src->OptionList;
|
||||
|
||||
for (Index = 0; Index < Src->OptionCount; Index++) {
|
||||
Len = sizeof (EFI_DHCP4_PACKET_OPTION) + NET_MAX (SrcOptions[Index]->Length - 1, 0);
|
||||
|
||||
DstOptions[Index] = NetAllocatePool (Len);
|
||||
|
||||
if (DstOptions[Index] == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
DhcpCleanConfigure (Dst);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Give up the control of the DHCP service to let other child
|
||||
resume. Don't change the service's DHCP state and the Client
|
||||
address and option list configure as required by RFC2131.
|
||||
|
||||
@param DhcpSb The DHCP service instance.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
DhcpYieldControl (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
)
|
||||
{
|
||||
EFI_DHCP4_CONFIG_DATA *Config;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
|
||||
Instance = DhcpSb->ActiveChild;
|
||||
Config = &DhcpSb->ActiveConfig;
|
||||
|
||||
DhcpSb->ServiceState = DHCP_UNCONFIGED;
|
||||
DhcpSb->ActiveChild = NULL;
|
||||
|
||||
if (Config->DiscoverTimeout != NULL) {
|
||||
NetFreePool (Config->DiscoverTimeout);
|
||||
|
||||
Config->DiscoverTryCount = 0;
|
||||
Config->DiscoverTimeout = NULL;
|
||||
}
|
||||
|
||||
if (Config->RequestTimeout != NULL) {
|
||||
NetFreePool (Config->RequestTimeout);
|
||||
|
||||
Config->RequestTryCount = 0;
|
||||
Config->RequestTimeout = NULL;
|
||||
}
|
||||
|
||||
Config->Dhcp4Callback = NULL;
|
||||
Config->CallbackContext = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the DHCP protocol instance and its underlying DHCP service
|
||||
for operation. If Dhcp4CfgData is NULL and the child is currently
|
||||
controlling the DHCP service, release the control.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param Dhcp4CfgData The DHCP configure data.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_ACCESS_DENIED The service isn't in one of configurable states,
|
||||
or there is already an active child.
|
||||
@retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.
|
||||
@retval EFI_SUCCESS The child is configured.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Configure (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_DHCP4_CONFIG_DATA *Config;
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
UINT32 Index;
|
||||
IP4_ADDR Ip;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Dhcp4CfgData != NULL) {
|
||||
if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));
|
||||
|
||||
if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
DhcpSb = Instance->Service;
|
||||
Config = &DhcpSb->ActiveConfig;
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
|
||||
if ((DhcpSb->DhcpState != Dhcp4Stopped) &&
|
||||
(DhcpSb->DhcpState != Dhcp4Init) &&
|
||||
(DhcpSb->DhcpState != Dhcp4InitReboot) &&
|
||||
(DhcpSb->DhcpState != Dhcp4Bound)) {
|
||||
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Dhcp4CfgData != NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
DhcpCleanConfigure (Config);
|
||||
|
||||
if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
DhcpSb->UserOptionLen = 0;
|
||||
|
||||
for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {
|
||||
DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;
|
||||
}
|
||||
|
||||
DhcpSb->ActiveChild = Instance;
|
||||
|
||||
if (DhcpSb->DhcpState == Dhcp4Stopped) {
|
||||
DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);
|
||||
|
||||
if (DhcpSb->ClientAddr != 0) {
|
||||
DhcpSb->DhcpState = Dhcp4InitReboot;
|
||||
} else {
|
||||
DhcpSb->DhcpState = Dhcp4Init;
|
||||
}
|
||||
}
|
||||
|
||||
DhcpSb->ServiceState = DHCP_CONFIGED;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
} else if (DhcpSb->ActiveChild == Instance) {
|
||||
Status = EFI_SUCCESS;
|
||||
DhcpYieldControl (DhcpSb);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start the DHCP process.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param CompletionEvent The event to signal is address is acquired.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_NOT_STARTED The protocol hasn't been configured.
|
||||
@retval EFI_ALREADY_STARTED The DHCP process has already been started.
|
||||
@retval EFI_SUCCESS The DHCP process is started.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Start (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN EFI_EVENT CompletionEvent OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb = Instance->Service;
|
||||
|
||||
if (DhcpSb->DhcpState == Dhcp4Stopped) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {
|
||||
Status = EFI_ALREADY_STARTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->IoStatus = EFI_ALREADY_STARTED;
|
||||
|
||||
if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Start/Restart the receiving.
|
||||
//
|
||||
Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Instance->CompletionEvent = CompletionEvent;
|
||||
|
||||
//
|
||||
// Restore the TPL now, don't call poll function at NET_TPL_LOCK.
|
||||
//
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
if (CompletionEvent == NULL) {
|
||||
while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
|
||||
DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
|
||||
}
|
||||
|
||||
return DhcpSb->IoStatus;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Request an extra manual renew/rebind.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param RebindRequest TRUE if request a rebind, otherwise renew it
|
||||
@param CompletionEvent Event to signal when complete
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid
|
||||
@retval EFI_NOT_STARTED The DHCP protocol hasn't been started.
|
||||
@retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.
|
||||
@retval EFI_SUCCESS The DHCP is renewed/rebound.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4RenewRebind (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN BOOLEAN RebindRequest,
|
||||
IN EFI_EVENT CompletionEvent OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb = Instance->Service;
|
||||
|
||||
if (DhcpSb->DhcpState == Dhcp4Stopped) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if (DhcpSb->DhcpState != Dhcp4Bound) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if (DHCP_IS_BOOTP (DhcpSb->Para)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Transit the states then send a extra DHCP request
|
||||
//
|
||||
if (!RebindRequest) {
|
||||
DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
|
||||
} else {
|
||||
DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
|
||||
}
|
||||
|
||||
Status = DhcpSendMessage (
|
||||
DhcpSb,
|
||||
DhcpSb->Selected,
|
||||
DhcpSb->Para,
|
||||
DHCP_MSG_REQUEST,
|
||||
"Extra renew/rebind by the application"
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
DhcpSb->ExtraRefresh = TRUE;
|
||||
DhcpSb->IoStatus = EFI_ALREADY_STARTED;
|
||||
Instance->RenewRebindEvent = CompletionEvent;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
if (CompletionEvent == NULL) {
|
||||
while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
|
||||
DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
|
||||
}
|
||||
|
||||
return DhcpSb->IoStatus;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Release the current acquired lease.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid
|
||||
@retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet
|
||||
@retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected
|
||||
state.
|
||||
@retval EFI_SUCCESS The lease is released.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Release (
|
||||
IN EFI_DHCP4_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb = Instance->Service;
|
||||
|
||||
if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {
|
||||
Status = DhcpSendMessage (
|
||||
DhcpSb,
|
||||
DhcpSb->Selected,
|
||||
DhcpSb->Para,
|
||||
DHCP_MSG_RELEASE,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
DhcpCleanLease (DhcpSb);
|
||||
|
||||
ON_EXIT:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop the current DHCP process. After this, other DHCP child
|
||||
can gain control of the service, configure and use it.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@retval EFI_SUCCESS The DHCP process is stopped.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Stop (
|
||||
IN EFI_DHCP4_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
DHCP_PROTOCOL *Instance;
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = DHCP_INSTANCE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
DhcpSb = Instance->Service;
|
||||
|
||||
DhcpCleanLease (DhcpSb);
|
||||
|
||||
DhcpSb->DhcpState = Dhcp4Stopped;
|
||||
DhcpSb->ServiceState = DHCP_UNCONFIGED;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a new DHCP packet from the seed packet. Options may be deleted or
|
||||
appended. The caller should free the NewPacket when finished using it.
|
||||
|
||||
@param This The DHCP protocol instance.
|
||||
@param SeedPacket The seed packet to start with
|
||||
@param DeleteCount The number of options to delete
|
||||
@param DeleteList The options to delete from the packet
|
||||
@param AppendCount The number of options to append
|
||||
@param AppendList The options to append to the packet
|
||||
@param NewPacket The new packet, allocated and built by this
|
||||
function.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
@retval EFI_SUCCESS The packet is build.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Build (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN EFI_DHCP4_PACKET *SeedPacket,
|
||||
IN UINT32 DeleteCount,
|
||||
IN UINT8 *DeleteList OPTIONAL,
|
||||
IN UINT32 AppendCount,
|
||||
IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
|
||||
OUT EFI_DHCP4_PACKET **NewPacket
|
||||
)
|
||||
{
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if ((This == NULL) || (NewPacket == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
|
||||
EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (((DeleteCount == 0) && (AppendCount == 0)) ||
|
||||
((DeleteCount != 0) && (DeleteList == NULL)) ||
|
||||
((AppendCount != 0) && (AppendList == NULL))) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return DhcpBuild (
|
||||
SeedPacket,
|
||||
DeleteCount,
|
||||
DeleteList,
|
||||
AppendCount,
|
||||
AppendList,
|
||||
NewPacket
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Transmit and receive a packet through this DHCP service.
|
||||
This is unsupported.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param Token The transmit and receive instance
|
||||
|
||||
@retval EFI_UNSUPPORTED It always returns unsupported.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4TransmitReceive (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
|
||||
)
|
||||
{
|
||||
//
|
||||
// This function is for PXE, leave it for now
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Callback function for DhcpIterateOptions. This callback sets the
|
||||
EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
|
||||
the individual DHCP option in the packet.
|
||||
|
||||
@param Tag The DHCP option type
|
||||
@param Len length of the DHCP option data
|
||||
@param Data The DHCP option data
|
||||
@param Context The context, to pass several parameters in.
|
||||
|
||||
@retval EFI_SUCCESS It always returns EFI_SUCCESS
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Dhcp4ParseCheckOption (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_PARSE_CONTEXT *Parse;
|
||||
|
||||
Parse = (DHCP_PARSE_CONTEXT *) Context;
|
||||
Parse->Index++;
|
||||
|
||||
if (Parse->Index < Parse->OptionCount) {
|
||||
//
|
||||
// Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
|
||||
// the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
|
||||
// pass in the point to option data.
|
||||
//
|
||||
Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the DHCP options in the Packet into the PacketOptionList.
|
||||
User should allocate this array of EFI_DHCP4_PACKET_OPTION points.
|
||||
|
||||
@param This The DHCP protocol instance
|
||||
@param Packet The DHCP packet to parse
|
||||
@param OptionCount On input, the size of the PacketOptionList; On
|
||||
output, the actual number of options processed.
|
||||
@param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.
|
||||
@retval EFI_SUCCESS The options are parsed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiDhcp4Parse (
|
||||
IN EFI_DHCP4_PROTOCOL *This,
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_PARSE_CONTEXT Context;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// First validate the parameters
|
||||
//
|
||||
if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||
|
||||
(Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
|
||||
EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
|
||||
|
||||
Context.Option = PacketOptionList;
|
||||
Context.OptionCount = *OptionCount;
|
||||
Context.Index = 0;
|
||||
|
||||
Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*OptionCount = Context.Index;
|
||||
|
||||
if (Context.Index > Context.OptionCount) {
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {
|
||||
EfiDhcp4GetModeData,
|
||||
EfiDhcp4Configure,
|
||||
EfiDhcp4Start,
|
||||
EfiDhcp4RenewRebind,
|
||||
EfiDhcp4Release,
|
||||
EfiDhcp4Stop,
|
||||
EfiDhcp4Build,
|
||||
EfiDhcp4TransmitReceive,
|
||||
EfiDhcp4Parse
|
||||
};
|
159
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h
Normal file
159
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.h
Normal file
@ -0,0 +1,159 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Dhcp4Impl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI DHCP protocol implementation
|
||||
RFCs supported are:
|
||||
RFC 2131: Dynamic Host Configuration Protocol
|
||||
RFC 2132: DHCP Options and BOOTP Vendor Extensions
|
||||
RFC 1534: Interoperation Between DHCP and BOOTP
|
||||
RFC 3396: Encoding Long Options in DHCP
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_IMPL_H__
|
||||
#define __EFI_DHCP4_IMPL_H__
|
||||
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/Dhcp4.h>
|
||||
#include <Protocol/Udp4.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
|
||||
typedef struct _DHCP_SERVICE DHCP_SERVICE;
|
||||
typedef struct _DHCP_PROTOCOL DHCP_PROTOCOL;
|
||||
|
||||
#include "Dhcp4Option.h"
|
||||
#include "Dhcp4Io.h"
|
||||
|
||||
enum {
|
||||
DHCP_SERVICE_SIGNATURE = EFI_SIGNATURE_32 ('D', 'H', 'C', 'P'),
|
||||
DHCP_PROTOCOL_SIGNATURE = EFI_SIGNATURE_32 ('d', 'h', 'c', 'p'),
|
||||
|
||||
//
|
||||
// The state of the DHCP service. It starts as UNCONFIGED. If
|
||||
// and active child configures the service successfully, it
|
||||
// goes to CONFIGED. If the active child configures NULL, it
|
||||
// goes back to UNCONFIGED. It becomes DESTORY if it is (partly)
|
||||
// destoried.
|
||||
//
|
||||
DHCP_UNCONFIGED = 0,
|
||||
DHCP_CONFIGED,
|
||||
DHCP_DESTORY,
|
||||
};
|
||||
|
||||
typedef struct _DHCP_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
EFI_DHCP4_PROTOCOL Dhcp4Protocol;
|
||||
NET_LIST_ENTRY Link;
|
||||
EFI_HANDLE Handle;
|
||||
DHCP_SERVICE *Service;
|
||||
|
||||
BOOLEAN InDestory;
|
||||
|
||||
EFI_EVENT CompletionEvent;
|
||||
EFI_EVENT RenewRebindEvent;
|
||||
|
||||
EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
|
||||
};
|
||||
|
||||
//
|
||||
// DHCP driver is specical in that it is a singleton. Although it
|
||||
// has a service binding, there can be only one active child.
|
||||
//
|
||||
typedef struct _DHCP_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
|
||||
INTN ServiceState; // CONFIGED, UNCONFIGED, and DESTORY
|
||||
BOOLEAN InDestory;
|
||||
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
NET_LIST_ENTRY Children;
|
||||
UINTN NumChildren;
|
||||
|
||||
INTN DhcpState;
|
||||
EFI_STATUS IoStatus; // the result of last user operation
|
||||
UINT32 Xid;
|
||||
|
||||
IP4_ADDR ClientAddr; // lease IP or configured client address
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR ServerAddr;
|
||||
|
||||
EFI_DHCP4_PACKET *LastOffer; // The last received offer
|
||||
EFI_DHCP4_PACKET *Selected;
|
||||
DHCP_PARAMETER *Para;
|
||||
|
||||
UINT32 Lease;
|
||||
UINT32 T1;
|
||||
UINT32 T2;
|
||||
INTN ExtraRefresh; // This refresh is reqested by user
|
||||
|
||||
UDP_IO_PORT *UdpIo; // Udp child receiving all DHCP message
|
||||
UDP_IO_PORT *LeaseIoPort; // Udp child with lease IP
|
||||
NET_BUF *LastPacket; // The last sent packet for retransmission
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
UINT8 HwType;
|
||||
UINT8 HwLen;
|
||||
|
||||
DHCP_PROTOCOL *ActiveChild;
|
||||
EFI_DHCP4_CONFIG_DATA ActiveConfig;
|
||||
UINT32 UserOptionLen;
|
||||
|
||||
//
|
||||
// Timer event and various timer
|
||||
//
|
||||
EFI_EVENT Timer;
|
||||
|
||||
UINT32 PacketToLive; // Retransmission timer for our packets
|
||||
INTN CurRetry;
|
||||
INTN MaxRetries;
|
||||
|
||||
UINT32 WaitOffer; // Time to collect the offers
|
||||
UINT32 LeaseLife;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EFI_DHCP4_PACKET_OPTION **Option;
|
||||
UINT32 OptionCount;
|
||||
UINT32 Index;
|
||||
} DHCP_PARSE_CONTEXT;
|
||||
|
||||
#define DHCP_INSTANCE_FROM_THIS(Proto) \
|
||||
CR ((Proto), DHCP_PROTOCOL, Dhcp4Protocol, DHCP_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define DHCP_SERVICE_FROM_THIS(Sb) \
|
||||
CR ((Sb), DHCP_SERVICE, ServiceBinding, DHCP_SERVICE_SIGNATURE)
|
||||
|
||||
extern EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate;
|
||||
|
||||
VOID
|
||||
DhcpYieldControl (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
#endif
|
1631
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c
Normal file
1631
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c
Normal file
File diff suppressed because it is too large
Load Diff
115
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.h
Normal file
115
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.h
Normal file
@ -0,0 +1,115 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Dhcp4Io.h
|
||||
|
||||
Abstract:
|
||||
|
||||
The DHCP4 protocol implementation.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_IO_H__
|
||||
#define __EFI_DHCP4_IO_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/UdpIoLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
|
||||
enum {
|
||||
DHCP_WAIT_OFFER = 3, // Time to wait the offers
|
||||
DHCP_DEFAULT_LEASE = 7 *24 *60 *60, // Seven days as default.
|
||||
DHCP_SERVER_PORT = 67,
|
||||
DHCP_CLIENT_PORT = 68,
|
||||
|
||||
//
|
||||
// BOOTP header "op" field
|
||||
//
|
||||
BOOTP_REQUEST = 1,
|
||||
BOOTP_REPLY = 2,
|
||||
|
||||
//
|
||||
// DHCP message types
|
||||
//
|
||||
DHCP_MSG_DISCOVER = 1,
|
||||
DHCP_MSG_OFFER = 2,
|
||||
DHCP_MSG_REQUEST = 3,
|
||||
DHCP_MSG_DECLINE = 4,
|
||||
DHCP_MSG_ACK = 5,
|
||||
DHCP_MSG_NAK = 6,
|
||||
DHCP_MSG_RELEASE = 7,
|
||||
DHCP_MSG_INFORM = 8,
|
||||
|
||||
//
|
||||
// DHCP notify user type
|
||||
//
|
||||
DHCP_NOTIFY_COMPLETION = 1,
|
||||
DHCP_NOTIFY_RENEWREBIND,
|
||||
DHCP_NOTIFY_ALL,
|
||||
};
|
||||
|
||||
#define DHCP_IS_BOOTP(Parameter) (((Parameter) == NULL) || ((Parameter)->DhcpType == 0))
|
||||
|
||||
#define DHCP_CONNECTED(State) \
|
||||
(((State) == Dhcp4Bound) || ((State) == (Dhcp4Renewing)) || ((State) == Dhcp4Rebinding))
|
||||
|
||||
EFI_STATUS
|
||||
DhcpSetState (
|
||||
IN DHCP_SERVICE *DhcpSb,
|
||||
IN INTN State,
|
||||
IN BOOLEAN CallUser
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpSendMessage (
|
||||
IN DHCP_SERVICE *DhcpSb,
|
||||
IN EFI_DHCP4_PACKET *Seed,
|
||||
IN DHCP_PARAMETER *Para,
|
||||
IN UINT8 Type,
|
||||
IN UINT8 *Msg
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
DhcpOnTimerTick (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
DhcpInput (
|
||||
NET_BUF *UdpPacket,
|
||||
UDP_POINTS *Points,
|
||||
EFI_STATUS IoStatus,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpInitRequest (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
VOID
|
||||
DhcpCleanLease (
|
||||
IN DHCP_SERVICE *DhcpSb
|
||||
);
|
||||
|
||||
#endif
|
906
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Option.c
Normal file
906
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Option.c
Normal file
@ -0,0 +1,906 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Dhcp4Option.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Function to validate, parse, process the DHCP options
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Dhcp4Impl.h"
|
||||
|
||||
//
|
||||
// A list of the format of DHCP Options sorted by option tag
|
||||
// to validate a dhcp message. Refere the comments of the
|
||||
// DHCP_OPTION_FORMAT structure.
|
||||
//
|
||||
STATIC
|
||||
DHCP_OPTION_FORMAT
|
||||
DhcpOptionFormats [] = {
|
||||
{DHCP_TAG_NETMASK, DHCP_OPTION_IP, 1, 1 , TRUE},
|
||||
{DHCP_TAG_TIME_OFFSET, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP_TAG_ROUTER, DHCP_OPTION_IP, 1, -1 , TRUE},
|
||||
{DHCP_TAG_TIME_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NAME_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_DNS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_LOG_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_COOKIE_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_LPR_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_IMPRESS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_RL_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_HOSTNAME, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_BOOTFILE_LEN, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP_TAG_DUMP, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_DOMAINNAME, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_SWAP_SERVER, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP_TAG_ROOTPATH, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_EXTEND_PATH, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_IPFORWARD, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_NONLOCAL_SRR, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_POLICY_SRR, DHCP_OPTION_IPPAIR, 1, -1 , FALSE},
|
||||
{DHCP_TAG_EMTU, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP_TAG_TTL, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP_TAG_PATHMTU_AGE, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP_TAG_PATHMTU_PLATEAU,DHCP_OPTION_INT16, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_IFMTU, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP_TAG_SUBNET_LOCAL, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_BROADCAST, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP_TAG_DISCOVER_MASK, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_SUPPLY_MASK, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_DISCOVER_ROUTE, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_ROUTER_SOLICIT, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP_TAG_STATIC_ROUTE, DHCP_OPTION_IPPAIR, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_TRAILER, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
{DHCP_TAG_ARPAGE, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP_TAG_ETHER_ENCAP, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
|
||||
{DHCP_TAG_TCP_TTL, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP_TAG_KEEP_INTERVAL, DHCP_OPTION_INT32, 1, 1 , FALSE},
|
||||
{DHCP_TAG_KEEP_GARBAGE, DHCP_OPTION_SWITCH, 1, 1 , FALSE},
|
||||
|
||||
{DHCP_TAG_NIS_DOMAIN, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NIS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NTP_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_VENDOR, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NBNS, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NBDD, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NBTYPE, DHCP_OPTION_INT8, 1, 1 , FALSE},
|
||||
{DHCP_TAG_NBSCOPE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_XFONT, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_XDM, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_REQUEST_IP, DHCP_OPTION_IP, 1, 1 , FALSE},
|
||||
{DHCP_TAG_LEASE, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP_TAG_OVERLOAD, DHCP_OPTION_INT8, 1, 1 , TRUE},
|
||||
{DHCP_TAG_TYPE, DHCP_OPTION_INT8, 1, 1 , TRUE},
|
||||
{DHCP_TAG_SERVER_ID, DHCP_OPTION_IP, 1, 1 , TRUE},
|
||||
{DHCP_TAG_PARA_LIST, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_MESSAGE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_MAXMSG, DHCP_OPTION_INT16, 1, 1 , FALSE},
|
||||
{DHCP_TAG_T1, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP_TAG_T2, DHCP_OPTION_INT32, 1, 1 , TRUE},
|
||||
{DHCP_TAG_VENDOR_CLASS, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_CLIENT_ID, DHCP_OPTION_INT8, 2, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_NISPLUS, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NISPLUS_SERVER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_TFTP, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
{DHCP_TAG_BOOTFILE, DHCP_OPTION_INT8, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_MOBILEIP, DHCP_OPTION_IP, 0, -1 , FALSE},
|
||||
{DHCP_TAG_SMTP, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_POP3, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_NNTP, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_WWW, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_FINGER, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_IRC, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_STTALK, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
{DHCP_TAG_STDA, DHCP_OPTION_IP, 1, -1 , FALSE},
|
||||
|
||||
{DHCP_TAG_CLASSLESS_ROUTE,DHCP_OPTION_INT8, 5, -1 , FALSE},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Binary search the DhcpOptionFormats array to find the format
|
||||
information about a specific option.
|
||||
|
||||
@param Tag The option's tag.
|
||||
|
||||
@return The point to the option's format, NULL if not found.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
DHCP_OPTION_FORMAT *
|
||||
DhcpFindOptionFormat (
|
||||
IN UINT8 Tag
|
||||
)
|
||||
{
|
||||
INTN Left;
|
||||
INTN Right;
|
||||
INTN Middle;
|
||||
|
||||
Left = 0;
|
||||
Right = sizeof (DhcpOptionFormats) / sizeof (DHCP_OPTION_FORMAT) - 1;
|
||||
|
||||
while (Right >= Left) {
|
||||
Middle = (Left + Right) / 2;
|
||||
|
||||
if (Tag == DhcpOptionFormats[Middle].Tag) {
|
||||
return &DhcpOptionFormats[Middle];
|
||||
}
|
||||
|
||||
if (Tag < DhcpOptionFormats[Middle].Tag) {
|
||||
Right = Middle - 1;
|
||||
} else {
|
||||
Left = Middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate whether a single DHCP option is valid according to its format.
|
||||
|
||||
@param Format The option's format
|
||||
@param OptValue The value of the option
|
||||
@param Len The length of the option value
|
||||
|
||||
@return TRUE is the option is valid, otherwise FALSE.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
DhcpOptionIsValid (
|
||||
IN DHCP_OPTION_FORMAT *Format,
|
||||
IN UINT8 *OptValue,
|
||||
IN INTN Len
|
||||
)
|
||||
{
|
||||
INTN Unit;
|
||||
INTN Occur;
|
||||
INTN Index;
|
||||
|
||||
Unit = 0;
|
||||
|
||||
switch (Format->Type) {
|
||||
case DHCP_OPTION_SWITCH:
|
||||
case DHCP_OPTION_INT8:
|
||||
Unit = 1;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_INT16:
|
||||
Unit = 2;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_INT32:
|
||||
case DHCP_OPTION_IP:
|
||||
Unit = 4;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_IPPAIR:
|
||||
Unit = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT (Unit != 0);
|
||||
|
||||
//
|
||||
// Validate that the option appears in the full units.
|
||||
//
|
||||
if ((Len % Unit) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate the occurance of the option unit is with in [MinOccur, MaxOccur]
|
||||
//
|
||||
Occur = Len / Unit;
|
||||
|
||||
if (((Format->MinOccur != -1) && (Occur < Format->MinOccur)) ||
|
||||
((Format->MaxOccur != -1) && (Occur > Format->MaxOccur))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// If the option is of type switch, only 0/1 are valid values.
|
||||
//
|
||||
if (Format->Type == DHCP_OPTION_SWITCH) {
|
||||
for (Index = 0; Index < Occur; Index++) {
|
||||
if ((OptValue[Index] != 0) && (OptValue[Index] != 1)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Extract the client interested options, all the parameters are
|
||||
converted to host byte order.
|
||||
|
||||
@param Tag The DHCP option tag
|
||||
@param Len The length of the option
|
||||
@param Data The value of the DHCP option
|
||||
@param Para The variable to save the interested parameter
|
||||
|
||||
@retval EFI_SUCCESS The DHCP option is successfully extracted.
|
||||
@retval EFI_INVALID_PARAMETER The DHCP option is mal-formated
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
DhcpGetParameter (
|
||||
IN UINT8 Tag,
|
||||
IN INTN Len,
|
||||
IN UINT8 *Data,
|
||||
IN DHCP_PARAMETER *Para
|
||||
)
|
||||
{
|
||||
switch (Tag) {
|
||||
case DHCP_TAG_NETMASK:
|
||||
Para->NetMask = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP_TAG_ROUTER:
|
||||
//
|
||||
// Return the first router to consumer which is the preferred one
|
||||
//
|
||||
Para->Router = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP_TAG_LEASE:
|
||||
Para->Lease = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP_TAG_OVERLOAD:
|
||||
Para->Overload = *Data;
|
||||
|
||||
if ((Para->Overload < 1) || (Para->Overload > 3)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_TAG_TYPE:
|
||||
Para->DhcpType = *Data;
|
||||
|
||||
if ((Para->DhcpType < 1) || (Para->DhcpType > 9)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_TAG_SERVER_ID:
|
||||
Para->ServerId = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP_TAG_T1:
|
||||
Para->T1 = NetGetUint32 (Data);
|
||||
break;
|
||||
|
||||
case DHCP_TAG_T2:
|
||||
Para->T2 = NetGetUint32 (Data);
|
||||
break;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Inspect all the options in a single buffer. DHCP options may be contained
|
||||
in several buffers, such as the BOOTP options filed, boot file or server
|
||||
name. Each option buffer is required to end with DHCP_TAG_EOP.
|
||||
|
||||
@param Buffer The buffer which contains DHCP options
|
||||
@param BufLen The length of the buffer
|
||||
@param Check The callback function for each option found
|
||||
@param Context The opaque parameter for the Check
|
||||
@param Overload variable to save the value of DHCP_TAG_OVERLOAD
|
||||
option.
|
||||
|
||||
@retval EFI_SUCCESS All the options are valid
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
DhcpIterateBufferOptions (
|
||||
IN UINT8 *Buffer,
|
||||
IN INTN BufLen,
|
||||
IN DHCP_CHECK_OPTION Check, OPTIONAL
|
||||
IN VOID *Context,
|
||||
OUT UINT8 *Overload OPTIONAL
|
||||
)
|
||||
{
|
||||
INTN Cur;
|
||||
UINT8 Tag;
|
||||
UINT8 Len;
|
||||
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < BufLen) {
|
||||
Tag = Buffer[Cur];
|
||||
|
||||
if (Tag == DHCP_TAG_PAD) {
|
||||
Cur++;
|
||||
continue;
|
||||
} else if (Tag == DHCP_TAG_EOP) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Cur++;
|
||||
|
||||
if (Cur == BufLen) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Len = Buffer[Cur++];
|
||||
|
||||
if (Cur + Len > BufLen) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Tag == DHCP_TAG_OVERLOAD) && (Overload != NULL)) {
|
||||
if (Len != 1) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*Overload = Buffer[Cur];
|
||||
}
|
||||
|
||||
if ((Check != NULL) && EFI_ERROR (Check (Tag, Len, Buffer + Cur, Context))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
}
|
||||
|
||||
//
|
||||
// Each option buffer is expected to end with an EOP
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Iterate through a DHCP message to visit each option. First inspect
|
||||
all the options in the OPTION field. Then if overloaded, inspect
|
||||
the options in FILENAME and SERVERNAME fields. One option may be
|
||||
encoded in several places. See RFC 3396 Encoding Long Options in DHCP
|
||||
|
||||
@param Packet The DHCP packet to check the options for
|
||||
@param Check The callback function to be called for each option
|
||||
found
|
||||
@param Context The opaque parameter for Check
|
||||
|
||||
@retval EFI_SUCCESS The DHCP packet's options are well formated
|
||||
@retval Others The DHCP packet's options are not well formated
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpIterateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
IN DHCP_CHECK_OPTION Check, OPTIONAL
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 Overload;
|
||||
|
||||
Overload = 0;
|
||||
|
||||
Status = DhcpIterateBufferOptions (
|
||||
Packet->Dhcp4.Option,
|
||||
Packet->Length - sizeof (EFI_DHCP4_HEADER) - sizeof (UINT32),
|
||||
Check,
|
||||
Context,
|
||||
&Overload
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((Overload == DHCP_OVERLOAD_FILENAME) || (Overload == DHCP_OVERLOAD_BOTH)) {
|
||||
Status = DhcpIterateBufferOptions (
|
||||
Packet->Dhcp4.Header.BootFileName,
|
||||
128,
|
||||
Check,
|
||||
Context,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Overload == DHCP_OVERLOAD_SVRNAME) || (Overload == DHCP_OVERLOAD_BOTH)) {
|
||||
Status = DhcpIterateBufferOptions (
|
||||
Packet->Dhcp4.Header.ServerName,
|
||||
64,
|
||||
Check,
|
||||
Context,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call back function to DhcpiterateOptions to compute each option's
|
||||
length. It just adds the data length of all the occurances of this
|
||||
Tag. Context is an array of 256 DHCP_OPTION_COUNT.
|
||||
|
||||
@param Tag The current option to check
|
||||
@param Len The length of the option data
|
||||
@param Data The option data
|
||||
@param Context The context, which is a array of 256
|
||||
DHCP_OPTION_COUNT.
|
||||
|
||||
@retval EFI_SUCCESS It always returns EFI_SUCCESS.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
DhcpGetOptionLen (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_COUNT *OpCount;
|
||||
|
||||
OpCount = (DHCP_OPTION_COUNT *) Context;
|
||||
OpCount[Tag].Offset = OpCount[Tag].Offset + Len;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call back function to DhcpiterateOptions to consolidate each option's
|
||||
data. There are maybe several occurance of the same option.
|
||||
|
||||
@param Tag The option to consolidate its data
|
||||
@param Len The length of option data
|
||||
@param Data The data of the option's current occurance
|
||||
@param Context The context, which is DHCP_OPTION_CONTEXT. This
|
||||
array is just a wrap to pass THREE parameters.
|
||||
|
||||
@retval EFI_SUCCESS It always returns EFI_SUCCESS
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
DhcpFillOption (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_CONTEXT *OptContext;
|
||||
DHCP_OPTION_COUNT *OptCount;
|
||||
DHCP_OPTION *Options;
|
||||
UINT8 *Buf;
|
||||
UINT8 Index;
|
||||
|
||||
OptContext = (DHCP_OPTION_CONTEXT *) Context;
|
||||
|
||||
OptCount = OptContext->OpCount;
|
||||
Index = OptCount[Tag].Index;
|
||||
Options = OptContext->Options;
|
||||
Buf = OptContext->Buf;
|
||||
|
||||
if (Options[Index].Data == NULL) {
|
||||
Options[Index].Tag = Tag;
|
||||
Options[Index].Data = Buf + OptCount[Tag].Offset;
|
||||
}
|
||||
|
||||
NetCopyMem (Buf + OptCount[Tag].Offset, Data, Len);
|
||||
|
||||
OptCount[Tag].Offset = OptCount[Tag].Offset + Len;
|
||||
Options[Index].Len = Options[Index].Len + Len;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the options of a DHCP packet. It supports RFC 3396: Encoding
|
||||
Long Options in DHCP. That is, it will combine all the option value
|
||||
of all the occurances of each option.
|
||||
A little bit of implemenation:
|
||||
It adopts the "Key indexed counting" algorithm. First, it allocates
|
||||
an array of 256 DHCP_OPTION_COUNTs because DHCP option tag is encoded
|
||||
as a UINT8. It then iterates the DHCP packet to get data length of
|
||||
each option by calling DhcpIterOptions with DhcpGetOptionLen. Now, it
|
||||
knows the number of present options and their length. It allocates a
|
||||
array of DHCP_OPTION and a continous buffer after the array to put
|
||||
all the options' data. Each option's data is pointed to by the Data
|
||||
field in DHCP_OPTION structure. At last, it call DhcpIterateOptions
|
||||
with DhcpFillOption to fill each option's data to its position in the
|
||||
buffer.
|
||||
|
||||
@param Packet The DHCP packet to parse the options
|
||||
@param Count The number of valid dhcp options present in the
|
||||
packet
|
||||
@param OptionPoint The array that contains the DHCP options. Caller
|
||||
should free it.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to parse the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpParseOption (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT INTN *Count,
|
||||
OUT DHCP_OPTION **OptionPoint
|
||||
)
|
||||
{
|
||||
DHCP_OPTION_CONTEXT Context;
|
||||
DHCP_OPTION *Options;
|
||||
DHCP_OPTION_COUNT *OptCount;
|
||||
EFI_STATUS Status;
|
||||
UINT16 TotalLen;
|
||||
INTN OptNum;
|
||||
INTN Index;
|
||||
|
||||
ASSERT ((Count != NULL) && (OptionPoint != NULL));
|
||||
|
||||
//
|
||||
// First compute how many options and how long each option is
|
||||
// with the "Key indexed counting" algorithms.
|
||||
//
|
||||
OptCount = NetAllocateZeroPool (DHCP_MAX_OPTIONS * sizeof (DHCP_OPTION_COUNT));
|
||||
|
||||
if (OptCount == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = DhcpIterateOptions (Packet, DhcpGetOptionLen, OptCount);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Before the loop, Offset is the length of the option. After loop,
|
||||
// OptCount[Index].Offset specifies the offset into the continuous
|
||||
// option value buffer to put the data.
|
||||
//
|
||||
TotalLen = 0;
|
||||
OptNum = 0;
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (OptCount[Index].Offset != 0) {
|
||||
OptCount[Index].Index = (UINT8) OptNum;
|
||||
|
||||
TotalLen = TotalLen + OptCount[Index].Offset;
|
||||
OptCount[Index].Offset = TotalLen - OptCount[Index].Offset;
|
||||
|
||||
OptNum++;
|
||||
}
|
||||
}
|
||||
|
||||
*Count = OptNum;
|
||||
*OptionPoint = NULL;
|
||||
|
||||
if (OptNum == 0) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a buffer to hold the DHCP options, and after that, a
|
||||
// continuous buffer to put all the options' data.
|
||||
//
|
||||
Options = NetAllocateZeroPool (OptNum * sizeof (DHCP_OPTION) + TotalLen);
|
||||
|
||||
if (Options == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Context.OpCount = OptCount;
|
||||
Context.Options = Options;
|
||||
Context.Buf = (UINT8 *) (Options + OptNum);
|
||||
|
||||
Status = DhcpIterateOptions (Packet, DhcpFillOption, &Context);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetFreePool (Options);
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
*OptionPoint = Options;
|
||||
|
||||
ON_EXIT:
|
||||
NetFreePool (OptCount);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate the packet's options. If necessary, allocate
|
||||
and fill in the interested parameters.
|
||||
|
||||
@param Packet The packet to validate the options
|
||||
@param Para The variable to save the DHCP parameters.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to validate the packet.
|
||||
@retval EFI_INVALID_PARAMETER The options are mal-formated
|
||||
@retval EFI_SUCCESS The options are parsed into OptionPoint
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpValidateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT DHCP_PARAMETER **Para OPTIONAL
|
||||
)
|
||||
{
|
||||
DHCP_PARAMETER Parameter;
|
||||
DHCP_OPTION_FORMAT *Format;
|
||||
DHCP_OPTION *AllOption;
|
||||
DHCP_OPTION *Option;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN Updated;
|
||||
INTN Count;
|
||||
INTN Index;
|
||||
|
||||
if (Para != NULL) {
|
||||
*Para = NULL;
|
||||
}
|
||||
|
||||
AllOption = NULL;
|
||||
Status = DhcpParseOption (Packet, &Count, &AllOption);
|
||||
|
||||
if (EFI_ERROR (Status) || (Count == 0)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Updated = FALSE;
|
||||
NetZeroMem (&Parameter, sizeof (Parameter));
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
Option = &AllOption[Index];
|
||||
|
||||
//
|
||||
// Find the format of the option then validate it.
|
||||
//
|
||||
Format = DhcpFindOptionFormat (Option->Tag);
|
||||
|
||||
if (Format == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DhcpOptionIsValid (Format, Option->Data, Option->Len)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the client interested parameters
|
||||
//
|
||||
if (Format->Alert && (Para != NULL)) {
|
||||
Updated = TRUE;
|
||||
Status = DhcpGetParameter (Option->Tag, Option->Len, Option->Data, &Parameter);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Updated && (Para != NULL)) {
|
||||
if ((*Para = NetAllocatePool (sizeof (DHCP_PARAMETER))) == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
CopyMem (*Para, &Parameter, sizeof (DHCP_PARAMETER));
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
NetFreePool (AllOption);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Append an option to the memory, if the option is longer than
|
||||
255 bytes, splits it into several options.
|
||||
|
||||
@param Buf The buffer to append the option to
|
||||
@param Tag The option's tag
|
||||
@param DataLen The length of the option's data
|
||||
@param Data The option's data
|
||||
|
||||
@return The position to append the next option
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
DhcpAppendOption (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT8 Tag,
|
||||
IN UINT16 DataLen,
|
||||
IN UINT8 *Data
|
||||
)
|
||||
{
|
||||
INTN Index;
|
||||
INTN Len;
|
||||
|
||||
ASSERT (DataLen != 0);
|
||||
|
||||
for (Index = 0; Index < (DataLen + 254) / 255; Index++) {
|
||||
Len = NET_MIN (255, DataLen - Index * 255);
|
||||
|
||||
*(Buf++) = Tag;
|
||||
*(Buf++) = (UINT8) Len;
|
||||
NetCopyMem (Buf, Data + Index * 255, Len);
|
||||
|
||||
Buf += Len;
|
||||
}
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a new DHCP packet from a seed packet. Options may be deleted or
|
||||
appended. The caller should free the NewPacket when finished using it.
|
||||
|
||||
@param SeedPacket The seed packet to start with
|
||||
@param DeleteCount The number of options to delete
|
||||
@param DeleteList The options to delete from the packet
|
||||
@param AppendCount The number of options to append
|
||||
@param AppendList The options to append to the packet
|
||||
@param NewPacket The new packet, allocated and built by this
|
||||
function.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
@retval EFI_SUCCESS The packet is build.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DhcpBuild (
|
||||
IN EFI_DHCP4_PACKET *SeedPacket,
|
||||
IN UINT32 DeleteCount,
|
||||
IN UINT8 *DeleteList OPTIONAL,
|
||||
IN UINT32 AppendCount,
|
||||
IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
|
||||
OUT EFI_DHCP4_PACKET **NewPacket
|
||||
)
|
||||
{
|
||||
DHCP_OPTION *Mark;
|
||||
DHCP_OPTION *SeedOptions;
|
||||
EFI_DHCP4_PACKET *Packet;
|
||||
EFI_STATUS Status;
|
||||
INTN Count;
|
||||
UINT32 Index;
|
||||
UINT32 Len;
|
||||
UINT8 *Buf;
|
||||
|
||||
//
|
||||
// Use an array of DHCP_OPTION to mark the existance
|
||||
// and position of each valid options.
|
||||
//
|
||||
Mark = NetAllocatePool (sizeof (DHCP_OPTION) * DHCP_MAX_OPTIONS);
|
||||
|
||||
if (Mark == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
Mark[Index].Tag = (UINT8) Index;
|
||||
Mark[Index].Len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Get list of the options from the seed packet, then put
|
||||
// them to the mark array according to their tags.
|
||||
//
|
||||
SeedOptions = NULL;
|
||||
Status = DhcpParseOption (SeedPacket, &Count, &SeedOptions);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < (UINT32) Count; Index++) {
|
||||
Mark[SeedOptions[Index].Tag] = SeedOptions[Index];
|
||||
}
|
||||
|
||||
//
|
||||
// Mark the option's length is zero if it is in the DeleteList.
|
||||
//
|
||||
for (Index = 0; Index < DeleteCount; Index++) {
|
||||
Mark[DeleteList[Index]].Len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Add or replace the option if it is in the append list.
|
||||
//
|
||||
for (Index = 0; Index < AppendCount; Index++) {
|
||||
Mark[AppendList[Index]->OpCode].Len = AppendList[Index]->Length;
|
||||
Mark[AppendList[Index]->OpCode].Data = AppendList[Index]->Data;
|
||||
}
|
||||
|
||||
//
|
||||
// compute the new packet length. No need to add 1 byte for
|
||||
// EOP option since EFI_DHCP4_PACKET includes one extra byte
|
||||
// for option. It is necessary to split the option if it is
|
||||
// longer than 255 bytes.
|
||||
//
|
||||
Len = sizeof (EFI_DHCP4_PACKET);
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (Mark[Index].Len != 0) {
|
||||
Len += ((Mark[Index].Len + 254) / 255) * 2 + Mark[Index].Len;
|
||||
}
|
||||
}
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
Packet = (EFI_DHCP4_PACKET *) NetAllocatePool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Packet->Size = Len;
|
||||
Packet->Length = 0;
|
||||
CopyMem (&Packet->Dhcp4.Header, &SeedPacket->Dhcp4.Header, sizeof (EFI_DHCP4_HEADER));
|
||||
Packet->Dhcp4.Magik = DHCP_OPTION_MAGIC;
|
||||
Buf = Packet->Dhcp4.Option;
|
||||
|
||||
for (Index = 0; Index < DHCP_MAX_OPTIONS; Index++) {
|
||||
if (Mark[Index].Len != 0) {
|
||||
Buf = DhcpAppendOption (Buf, Mark[Index].Tag, Mark[Index].Len, Mark[Index].Data);
|
||||
}
|
||||
}
|
||||
|
||||
*(Buf++) = DHCP_TAG_EOP;
|
||||
Packet->Length = sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)
|
||||
+ (UINT32) (Buf - Packet->Dhcp4.Option);
|
||||
|
||||
*NewPacket = Packet;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
if (SeedOptions != NULL) {
|
||||
NetFreePool (SeedOptions);
|
||||
}
|
||||
|
||||
NetFreePool (Mark);
|
||||
return Status;
|
||||
}
|
266
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Option.h
Normal file
266
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Option.h
Normal file
@ -0,0 +1,266 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Dhcp4Option.h
|
||||
|
||||
Abstract:
|
||||
|
||||
To validate, parse and process the DHCP options
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_DHCP4_OPTION_H__
|
||||
#define __EFI_DHCP4_OPTION_H__
|
||||
|
||||
//
|
||||
// DHCP option tags (types)
|
||||
//
|
||||
enum {
|
||||
//
|
||||
// RFC1497 vendor extensions
|
||||
//
|
||||
DHCP_TAG_PAD = 0, // Pad Option
|
||||
DHCP_TAG_EOP = 255, // End Option
|
||||
DHCP_TAG_NETMASK = 1, // Subnet Mask
|
||||
DHCP_TAG_TIME_OFFSET = 2, // Time Offset from UTC
|
||||
DHCP_TAG_ROUTER = 3, // Router option,
|
||||
DHCP_TAG_TIME_SERVER = 4, // Time Server
|
||||
DHCP_TAG_NAME_SERVER = 5, // Name Server
|
||||
DHCP_TAG_DNS_SERVER = 6, // Domain Name Server
|
||||
DHCP_TAG_LOG_SERVER = 7, // Log Server
|
||||
DHCP_TAG_COOKIE_SERVER = 8, // Cookie Server
|
||||
DHCP_TAG_LPR_SERVER = 9, // LPR Print Server
|
||||
DHCP_TAG_IMPRESS_SERVER = 10, // Impress Server
|
||||
DHCP_TAG_RL_SERVER = 11, // Resource Location Server
|
||||
DHCP_TAG_HOSTNAME = 12, // Host Name
|
||||
DHCP_TAG_BOOTFILE_LEN = 13, // Boot File Size
|
||||
DHCP_TAG_DUMP = 14, // Merit Dump File
|
||||
DHCP_TAG_DOMAINNAME = 15, // Domain Name
|
||||
DHCP_TAG_SWAP_SERVER = 16, // Swap Server
|
||||
DHCP_TAG_ROOTPATH = 17, // Root path
|
||||
DHCP_TAG_EXTEND_PATH = 18, // Extensions Path
|
||||
|
||||
//
|
||||
// IP Layer Parameters per Host
|
||||
//
|
||||
DHCP_TAG_IPFORWARD = 19, // IP Forwarding Enable/Disable
|
||||
DHCP_TAG_NONLOCAL_SRR = 20, // on-Local Source Routing Enable/Disable
|
||||
DHCP_TAG_POLICY_SRR = 21, // Policy Filter
|
||||
DHCP_TAG_EMTU = 22, // Maximum Datagram Reassembly Size
|
||||
DHCP_TAG_TTL = 23, // Default IP Time-to-live
|
||||
DHCP_TAG_PATHMTU_AGE = 24, // Path MTU Aging Timeout
|
||||
DHCP_TAG_PATHMTU_PLATEAU = 25, // Path MTU Plateau Table
|
||||
|
||||
//
|
||||
// IP Layer Parameters per Interface
|
||||
//
|
||||
DHCP_TAG_IFMTU = 26, // Interface MTU
|
||||
DHCP_TAG_SUBNET_LOCAL = 27, // All Subnets are Local
|
||||
DHCP_TAG_BROADCAST = 28, // Broadcast Address
|
||||
DHCP_TAG_DISCOVER_MASK = 29, // Perform Mask Discovery
|
||||
DHCP_TAG_SUPPLY_MASK = 30, // Mask Supplier
|
||||
DHCP_TAG_DISCOVER_ROUTE = 31, // Perform Router Discovery
|
||||
DHCP_TAG_ROUTER_SOLICIT = 32, // Router Solicitation Address
|
||||
DHCP_TAG_STATIC_ROUTE = 33, // Static Route
|
||||
|
||||
//
|
||||
// Link Layer Parameters per Interface
|
||||
//
|
||||
DHCP_TAG_TRAILER = 34, // Trailer Encapsulation
|
||||
DHCP_TAG_ARPAGE = 35, // ARP Cache Timeout
|
||||
DHCP_TAG_ETHER_ENCAP = 36, // Ethernet Encapsulation
|
||||
|
||||
//
|
||||
// TCP Parameters
|
||||
//
|
||||
DHCP_TAG_TCP_TTL = 37, // TCP Default TTL
|
||||
DHCP_TAG_KEEP_INTERVAL = 38, // TCP Keepalive Interval
|
||||
DHCP_TAG_KEEP_GARBAGE = 39, // TCP Keepalive Garbage
|
||||
|
||||
//
|
||||
// Application and Service Parameters
|
||||
//
|
||||
DHCP_TAG_NIS_DOMAIN = 40, // Network Information Service Domain
|
||||
DHCP_TAG_NIS_SERVER = 41, // Network Information Servers
|
||||
DHCP_TAG_NTP_SERVER = 42, // Network Time Protocol Servers
|
||||
DHCP_TAG_VENDOR = 43, // Vendor Specific Information
|
||||
DHCP_TAG_NBNS = 44, // NetBIOS over TCP/IP Name Server
|
||||
DHCP_TAG_NBDD = 45, // NetBIOS Datagram Distribution Server
|
||||
DHCP_TAG_NBTYPE = 46, // NetBIOS over TCP/IP Node Type
|
||||
DHCP_TAG_NBSCOPE = 47, // NetBIOS over TCP/IP Scope
|
||||
DHCP_TAG_XFONT = 48, // X Window System Font Server
|
||||
DHCP_TAG_XDM = 49, // X Window System Display Manager
|
||||
DHCP_TAG_NISPLUS = 64, // Network Information Service+ Domain
|
||||
DHCP_TAG_NISPLUS_SERVER = 65, // Network Information Service+ Servers
|
||||
DHCP_TAG_MOBILEIP = 68, // Mobile IP Home Agent
|
||||
DHCP_TAG_SMTP = 69, // Simple Mail Transport Protocol Server
|
||||
DHCP_TAG_POP3 = 70, // Post Office Protocol (POP3) Server
|
||||
DHCP_TAG_NNTP = 71, // Network News Transport Protocol Server
|
||||
DHCP_TAG_WWW = 72, // Default World Wide Web (WWW) Server
|
||||
DHCP_TAG_FINGER = 73, // Default Finger Server
|
||||
DHCP_TAG_IRC = 74, // Default Internet Relay Chat (IRC) Server
|
||||
DHCP_TAG_STTALK = 75, // StreetTalk Server
|
||||
DHCP_TAG_STDA = 76, // StreetTalk Directory Assistance Server
|
||||
DHCP_TAG_CLASSLESS_ROUTE = 121, // Classless Route
|
||||
|
||||
//
|
||||
// DHCP Extensions
|
||||
//
|
||||
DHCP_TAG_REQUEST_IP = 50, // Requested IP Address
|
||||
DHCP_TAG_LEASE = 51, // IP Address Lease Time
|
||||
DHCP_TAG_OVERLOAD = 52, // Option Overload
|
||||
DHCP_TAG_TFTP = 66, // TFTP server name
|
||||
DHCP_TAG_BOOTFILE = 67, // Bootfile name
|
||||
DHCP_TAG_TYPE = 53, // DHCP Message Type
|
||||
DHCP_TAG_SERVER_ID = 54, // Server Identifier
|
||||
DHCP_TAG_PARA_LIST = 55, // Parameter Request List
|
||||
DHCP_TAG_MESSAGE = 56, // Message
|
||||
DHCP_TAG_MAXMSG = 57, // Maximum DHCP Message Size
|
||||
DHCP_TAG_T1 = 58, // Renewal (T1) Time Value
|
||||
DHCP_TAG_T2 = 59, // Rebinding (T2) Time Value
|
||||
DHCP_TAG_VENDOR_CLASS = 60, // Vendor class identifier
|
||||
DHCP_TAG_CLIENT_ID = 61, // Client-identifier
|
||||
};
|
||||
|
||||
enum {
|
||||
DHCP_OPTION_MAGIC = 0x63538263, // Network byte order
|
||||
DHCP_MAX_OPTIONS = 256,
|
||||
|
||||
//
|
||||
// DHCP option types, this is used to validate the DHCP options.
|
||||
//
|
||||
DHCP_OPTION_SWITCH = 1,
|
||||
DHCP_OPTION_INT8,
|
||||
DHCP_OPTION_INT16,
|
||||
DHCP_OPTION_INT32,
|
||||
DHCP_OPTION_IP,
|
||||
DHCP_OPTION_IPPAIR,
|
||||
|
||||
//
|
||||
// Value of DHCP overload option
|
||||
//
|
||||
DHCP_OVERLOAD_FILENAME = 1,
|
||||
DHCP_OVERLOAD_SVRNAME = 2,
|
||||
DHCP_OVERLOAD_BOTH = 3,
|
||||
};
|
||||
|
||||
//
|
||||
// The DHCP option structure. This structure extends the EFI_DHCP_OPTION
|
||||
// structure to support options longer than 255 bytes, such as classless route.
|
||||
//
|
||||
typedef struct {
|
||||
UINT8 Tag;
|
||||
UINT16 Len;
|
||||
UINT8 *Data;
|
||||
} DHCP_OPTION;
|
||||
|
||||
//
|
||||
// Structures used to parse the DHCP options with RFC3396 support.
|
||||
//
|
||||
typedef struct {
|
||||
UINT8 Index;
|
||||
UINT16 Offset;
|
||||
} DHCP_OPTION_COUNT;
|
||||
|
||||
typedef struct {
|
||||
DHCP_OPTION_COUNT *OpCount;
|
||||
DHCP_OPTION *Options;
|
||||
UINT8 *Buf;
|
||||
} DHCP_OPTION_CONTEXT;
|
||||
|
||||
//
|
||||
// The options that matters to DHCP driver itself. The user of
|
||||
// DHCP clients may be interested in other options, such as
|
||||
// classless route, who can parse the DHCP offer to get them.
|
||||
//
|
||||
typedef struct {
|
||||
IP4_ADDR NetMask; // DHCP_TAG_NETMASK
|
||||
IP4_ADDR Router; // DHCP_TAG_ROUTER, only the first router is used
|
||||
|
||||
//
|
||||
// DHCP specific options
|
||||
//
|
||||
UINT8 DhcpType; // DHCP_TAG_TYPE
|
||||
UINT8 Overload; // DHCP_TAG_OVERLOAD
|
||||
IP4_ADDR ServerId; // DHCP_TAG_SERVER_ID
|
||||
UINT32 Lease; // DHCP_TAG_LEASE
|
||||
UINT32 T1; // DHCP_TAG_T1
|
||||
UINT32 T2; // DHCP_TAG_T2
|
||||
} DHCP_PARAMETER;
|
||||
|
||||
//
|
||||
// Structure used to describe and validate the format of DHCP options.
|
||||
// Type is the options' data type, such as DHCP_OPTION_INT8. MinOccur
|
||||
// is the minium occurance of this data type. MaxOccur is defined
|
||||
// similarly. If MaxOccur is -1, it means that there is no limit on the
|
||||
// maximum occurance. Alert tells whether DHCP client should further
|
||||
// inspect the option to parse DHCP_PARAMETER.
|
||||
//
|
||||
typedef struct {
|
||||
UINT8 Tag;
|
||||
INTN Type;
|
||||
INTN MinOccur;
|
||||
INTN MaxOccur;
|
||||
BOOLEAN Alert;
|
||||
} DHCP_OPTION_FORMAT;
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*DHCP_CHECK_OPTION) (
|
||||
IN UINT8 Tag,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 *Data,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpIterateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
IN DHCP_CHECK_OPTION Check, OPTIONAL
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpValidateOptions (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT DHCP_PARAMETER **Para OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpParseOption (
|
||||
IN EFI_DHCP4_PACKET *Packet,
|
||||
OUT INTN *Count,
|
||||
OUT DHCP_OPTION **OptionPoint
|
||||
);
|
||||
|
||||
UINT8 *
|
||||
DhcpAppendOption (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT8 Tag,
|
||||
IN UINT16 DataLen,
|
||||
IN UINT8 *Data
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
DhcpBuild (
|
||||
IN EFI_DHCP4_PACKET *SeedPacket,
|
||||
IN UINT32 DeleteCount,
|
||||
IN UINT8 *DeleteList OPTIONAL,
|
||||
IN UINT32 AppendCount,
|
||||
IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
|
||||
OUT EFI_DHCP4_PACKET **NewPacket
|
||||
);
|
||||
|
||||
#endif
|
@ -590,6 +590,8 @@ Ip4ConfigOnDhcp4Complete (
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN Perment;
|
||||
IP4_ADDR Subnet;
|
||||
IP4_ADDR Ip1;
|
||||
IP4_ADDR Ip2;
|
||||
|
||||
Instance = (IP4_CONFIG_INSTANCE *) Context;
|
||||
ASSERT (Instance->Dhcp4 != NULL);
|
||||
@ -641,20 +643,24 @@ Ip4ConfigOnDhcp4Complete (
|
||||
//
|
||||
Ip4Config->RouteTableSize = 1;
|
||||
|
||||
Subnet = EFI_NTOHL (Dhcp4Mode.ClientAddress) & EFI_NTOHL (Dhcp4Mode.SubnetMask);
|
||||
NetCopyMem (&Ip1, &Dhcp4Mode.ClientAddress, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&Ip2, &Dhcp4Mode.SubnetMask, sizeof (IP4_ADDR));
|
||||
|
||||
EFI_IP4 (Ip4Config->RouteTable[0].SubnetAddress) = HTONL (Subnet);
|
||||
Ip4Config->RouteTable[0].SubnetMask = Dhcp4Mode.SubnetMask;
|
||||
EFI_IP4 (Ip4Config->RouteTable[0].GatewayAddress) = 0;
|
||||
Subnet = Ip1 & Ip2;
|
||||
|
||||
NetCopyMem (&Ip4Config->RouteTable[0].SubnetAddress, &Subnet, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetCopyMem (&Ip4Config->RouteTable[0].SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetZeroMem (&Ip4Config->RouteTable[0].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
//
|
||||
// Create a route if there is a default router.
|
||||
//
|
||||
if (EFI_IP4 (Dhcp4Mode.RouterAddress) != 0) {
|
||||
if (!EFI_IP4_EQUAL (Dhcp4Mode.RouterAddress, mZeroIp4Addr)) {
|
||||
Ip4Config->RouteTableSize = 2;
|
||||
EFI_IP4 (Ip4Config->RouteTable[1].SubnetAddress) = 0;
|
||||
EFI_IP4 (Ip4Config->RouteTable[1].SubnetMask) = 0;
|
||||
Ip4Config->RouteTable[1].GatewayAddress = Dhcp4Mode.RouterAddress;
|
||||
|
||||
NetZeroMem (&Ip4Config->RouteTable[1].SubnetAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetZeroMem (&Ip4Config->RouteTable[1].SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
||||
NetCopyMem (&Ip4Config->RouteTable[1].GatewayAddress, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
}
|
||||
|
||||
Instance->Result = EFI_SUCCESS;
|
||||
|
@ -60,7 +60,6 @@ EfiIp4ConfigUnload (
|
||||
return NetLibDefaultUnload (ImageHandle);
|
||||
}
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Ip4ConfigDriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
Ip4ConfigDriverEntryPoint (
|
||||
|
166
MdeModulePkg/Universal/Network/Ip4Dxe/ComponentName.c
Normal file
166
MdeModulePkg/Universal/Network/Ip4Dxe/ComponentName.c
Normal file
@ -0,0 +1,166 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, 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 "Ip4Impl.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetControllerName (
|
||||
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 gIp4ComponentName = {
|
||||
Ip4ComponentNameGetDriverName,
|
||||
Ip4ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
static EFI_UNICODE_STRING_TABLE mIp4DriverNameTable[] = {
|
||||
{
|
||||
"eng",
|
||||
L"IP4 Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetDriverName (
|
||||
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_SUCCES - 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,
|
||||
gIp4ComponentName.SupportedLanguages,
|
||||
mIp4DriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ComponentNameGetControllerName (
|
||||
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;
|
||||
}
|
421
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.c
Normal file
421
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.c
Normal file
@ -0,0 +1,421 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Common.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Return the cast type (Unicast/Boradcast) specific to a
|
||||
interface. All the addresses are host byte ordered.
|
||||
|
||||
@param IpAddr The IP address to classify in host byte order
|
||||
@param IpIf The interface that IpAddr received from
|
||||
|
||||
@return The cast type of this IP address specific to the interface.
|
||||
@retval IP4_LOCAL_HOST The IpAddr equals to the interface's address
|
||||
@retval IP4_SUBNET_BROADCAST The IpAddr is a directed subnet boradcast to the
|
||||
interface
|
||||
@retval IP4_NET_BROADCAST The IpAddr is a network broadcast to the interface
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
)
|
||||
{
|
||||
if (IpAddr == IpIf->Ip) {
|
||||
return IP4_LOCAL_HOST;
|
||||
|
||||
} else if (IpAddr == IpIf->SubnetBrdcast) {
|
||||
return IP4_SUBNET_BROADCAST;
|
||||
|
||||
} else if (IpAddr == IpIf->NetBrdcast) {
|
||||
return IP4_NET_BROADCAST;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the cast type of the packet related to the local host.
|
||||
This isn't the same as link layer cast type. For example, DHCP
|
||||
server may send local broadcast to the local unicast MAC.
|
||||
|
||||
@param IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param Dst The destination address in the packet (host byte
|
||||
order)
|
||||
@param Src The source address in the packet (host byte order)
|
||||
|
||||
@return The cast type for the Dst, it will return on the first non-promiscuous
|
||||
@return cast type to a configured interface. If the packet doesn't match any of
|
||||
@return the interface, multicast address and local broadcast address are checked.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
INTN Type;
|
||||
INTN Class;
|
||||
|
||||
Type = 0;
|
||||
|
||||
if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
|
||||
Type = IP4_PROMISCUOUS;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through the interface list of the IP service, most likely.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
//
|
||||
// Skip the unconfigured interface and invalid source address:
|
||||
// source address can't be broadcast.
|
||||
//
|
||||
if (!IpIf->Configured || IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Class = Ip4GetNetCast (Dst, IpIf)) > Type) {
|
||||
return Class;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If it is local broadcast address. The source address must
|
||||
// be a unicast address on one of the direct connected network.
|
||||
// If it is a multicast address, accept it only if we are in
|
||||
// the group.
|
||||
//
|
||||
if (Dst == IP4_ALLONE_ADDRESS) {
|
||||
IpIf = Ip4FindNet (IpSb, Src);
|
||||
|
||||
if (IpIf && !IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {
|
||||
return IP4_LOCAL_BROADCAST;
|
||||
}
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dst) && Ip4FindGroup (&IpSb->IgmpCtrl, Dst)) {
|
||||
return IP4_MULTICAST;
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface whose configured IP address is Ip
|
||||
|
||||
@param IpSb The IP4 service binding instance
|
||||
@param Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface that Ip is on that connected network.
|
||||
|
||||
@param IpSb The IP4 service binding instance
|
||||
@param Ip The Ip address (host byte order) to find
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && IP4_NET_EQUAL (Ip, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find an interface of the service with the same Ip/Netmask pair.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
@param Ip The Ip adress to find (host byte order)
|
||||
@param Netmask The network to find (host byte order)
|
||||
|
||||
@return The IP4_INTERFACE point if found, otherwise NULL
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && (IpIf->Ip == Ip) && (IpIf->SubnetMask == Netmask)) {
|
||||
return IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the MAC address for a multicast IP address. Call
|
||||
Mnp's McastIpToMac to find the MAC address in stead of
|
||||
hard code the NIC to be Ethernet.
|
||||
|
||||
@param Mnp The Mnp instance to get the MAC address.
|
||||
@param Multicast The multicast IP address to translate.
|
||||
@param Mac The buffer to hold the translated address.
|
||||
|
||||
@return Returns EFI_SUCCESS if the multicast IP is successfully
|
||||
@return translated to a multicast MAC address. Otherwise some error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
EFI_IP_ADDRESS EfiIp;
|
||||
|
||||
EFI_IP4 (EfiIp.v4) = HTONL (Multicast);
|
||||
return Mnp->McastIpToMac (Mnp, FALSE, &EfiIp, Mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert the multibyte field in IP header's byter order.
|
||||
In spite of its name, it can also be used to convert from
|
||||
host to network byte order.
|
||||
|
||||
@param Head The IP head to convert
|
||||
|
||||
@return Point to the converted IP head
|
||||
|
||||
**/
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
)
|
||||
{
|
||||
Head->TotalLen = NTOHS (Head->TotalLen);
|
||||
Head->Id = NTOHS (Head->Id);
|
||||
Head->Fragment = NTOHS (Head->Fragment);
|
||||
Head->Src = NTOHL (Head->Src);
|
||||
Head->Dst = NTOHL (Head->Dst);
|
||||
|
||||
return Head;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the Ip4 variable data.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
|
||||
@retval other Set variable failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SetVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
UINT32 NumConfiguredInstance;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
UINTN VariableDataSize;
|
||||
EFI_IP4_VARIABLE_DATA *Ip4VariableData;
|
||||
EFI_IP4_ADDRESS_PAIR *Ip4AddressPair;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
CHAR16 *NewMacString;
|
||||
EFI_STATUS Status;
|
||||
|
||||
NumConfiguredInstance = 0;
|
||||
|
||||
//
|
||||
// Go through the children list to count the configured children.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP4_STATE_CONFIGED) {
|
||||
NumConfiguredInstance++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the size of the Ip4VariableData. As there may be no IP child,
|
||||
// we should add extra buffer for the address paris only if the number of configured
|
||||
// children is more than 1.
|
||||
//
|
||||
VariableDataSize = sizeof (EFI_IP4_VARIABLE_DATA);
|
||||
|
||||
if (NumConfiguredInstance > 1) {
|
||||
VariableDataSize += sizeof (EFI_IP4_ADDRESS_PAIR) * (NumConfiguredInstance - 1);
|
||||
}
|
||||
|
||||
Ip4VariableData = NetAllocatePool (VariableDataSize);
|
||||
if (Ip4VariableData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip4VariableData->DriverHandle = IpSb->Image;
|
||||
Ip4VariableData->AddressCount = NumConfiguredInstance;
|
||||
|
||||
Ip4AddressPair = &Ip4VariableData->AddressPairs[0];
|
||||
|
||||
//
|
||||
// Go through the children list to fill the configured children's address pairs.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Children) {
|
||||
IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
if (IpInstance->State == IP4_STATE_CONFIGED) {
|
||||
Ip4AddressPair->InstanceHandle = IpInstance->Handle;
|
||||
EFI_IP4 (Ip4AddressPair->Ip4Address) = NTOHL (IpInstance->Interface->Ip);
|
||||
EFI_IP4 (Ip4AddressPair->SubnetMask) = NTOHL (IpInstance->Interface->SubnetMask);
|
||||
|
||||
Ip4AddressPair++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the mac string.
|
||||
//
|
||||
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &NewMacString);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if (IpSb->MacString != NULL) {
|
||||
//
|
||||
// The variable is set already, we're going to update it.
|
||||
//
|
||||
if (StrCmp (IpSb->MacString, NewMacString) != 0) {
|
||||
//
|
||||
// The mac address is changed, delete the previous variable first.
|
||||
//
|
||||
gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
NetFreePool (IpSb->MacString);
|
||||
}
|
||||
|
||||
IpSb->MacString = NewMacString;
|
||||
|
||||
Status = gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
VariableDataSize,
|
||||
(VOID *) Ip4VariableData
|
||||
);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
NetFreePool (Ip4VariableData);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clear the variable and free the resource.
|
||||
|
||||
@param IpSb Ip4 service binding instance
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4ClearVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
ASSERT (IpSb->MacString != NULL);
|
||||
|
||||
gRT->SetVariable (
|
||||
IpSb->MacString,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
NetFreePool (IpSb->MacString);
|
||||
IpSb->MacString = NULL;
|
||||
}
|
143
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
Normal file
143
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
Normal file
@ -0,0 +1,143 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Common.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Common definition for IP4.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_COMMON_H__
|
||||
#define __EFI_IP4_COMMON_H__
|
||||
|
||||
typedef struct _IP4_INTERFACE IP4_INTERFACE;
|
||||
typedef struct _IP4_PROTOCOL IP4_PROTOCOL;
|
||||
typedef struct _IP4_SERVICE IP4_SERVICE;
|
||||
|
||||
|
||||
enum {
|
||||
IP4_ETHER_PROTO = 0x0800,
|
||||
|
||||
IP4_PROTO_ICMP = 0x01,
|
||||
IP4_PROTO_IGMP = 0x02,
|
||||
|
||||
//
|
||||
// The packet is received as link level broadcast/multicast/promiscuous.
|
||||
//
|
||||
IP4_LINK_BROADCAST = 0x00000001,
|
||||
IP4_LINK_MULTICAST = 0x00000002,
|
||||
IP4_LINK_PROMISC = 0x00000004,
|
||||
|
||||
//
|
||||
// IP4 address cast type classfication. Keep it true that any
|
||||
// type bigger than or equal to LOCAL_BROADCAST is broadcast.
|
||||
//
|
||||
IP4_PROMISCUOUS = 1,
|
||||
IP4_LOCAL_HOST,
|
||||
IP4_MULTICAST,
|
||||
IP4_LOCAL_BROADCAST, // Destination is 255.255.255.255
|
||||
IP4_SUBNET_BROADCAST,
|
||||
IP4_NET_BROADCAST,
|
||||
|
||||
//
|
||||
// IP4 header flags
|
||||
//
|
||||
IP4_HEAD_DF_MASK = 0x4000,
|
||||
IP4_HEAD_MF_MASK = 0x2000,
|
||||
IP4_HEAD_OFFSET_MASK = 0x1fff,
|
||||
};
|
||||
|
||||
#define IP4_ALLZERO_ADDRESS 0x00000000u
|
||||
#define IP4_ALLONE_ADDRESS 0xFFFFFFFFu
|
||||
#define IP4_ALLSYSTEM_ADDRESS 0xE0000001u
|
||||
#define IP4_ALLROUTER_ADDRESS 0xE0000002u
|
||||
|
||||
//
|
||||
// Compose the fragment field to be used in the IP4 header.
|
||||
//
|
||||
#define IP4_HEAD_FRAGMENT_FIELD(Df, Mf, Offset) \
|
||||
((UINT16)(((Df) ? 0x4000 : 0) | ((Mf) ? 0x2000 : 0) | (((Offset) >> 3) & 0x1fff)))
|
||||
|
||||
#define IP4_LAST_FRAGMENT(FragmentField) \
|
||||
(((FragmentField) & IP4_HEAD_MF_MASK) == 0)
|
||||
|
||||
#define IP4_FIRST_FRAGMENT(FragmentField) \
|
||||
((BOOLEAN)(((FragmentField) & IP4_HEAD_OFFSET_MASK) == 0))
|
||||
|
||||
#define IP4_IS_BROADCAST(CastType) ((CastType) >= IP4_LOCAL_BROADCAST)
|
||||
|
||||
//
|
||||
// Conver the Microsecond to second. IP transmit/receive time is
|
||||
// in the unit of microsecond. IP ticks once per second.
|
||||
//
|
||||
#define IP4_US_TO_SEC(Us) (((Us) + 999999) / 1000000)
|
||||
|
||||
INTN
|
||||
Ip4GetNetCast (
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_INTERFACE *IpIf
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4GetHostCast (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindInterface (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindNet (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4FindStationAddress (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Ip,
|
||||
IN IP4_ADDR Netmask
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4GetMulticastMac (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN IP4_ADDR Multicast,
|
||||
OUT EFI_MAC_ADDRESS *Mac
|
||||
);
|
||||
|
||||
IP4_HEAD *
|
||||
Ip4NtohHead (
|
||||
IN IP4_HEAD *Head
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SetVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4ClearVariableData (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
932
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Normal file
932
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Normal file
@ -0,0 +1,932 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
The driver binding and service binding protocol for IP4 driver.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {
|
||||
Ip4DriverBindingSupported,
|
||||
Ip4DriverBindingStart,
|
||||
Ip4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Ip4DriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The entry point for IP4 driver which install the driver
|
||||
binding and component name protocol on its image.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The image handle of the driver
|
||||
SystemTable - The system table
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS if the driver binding and component name protocols
|
||||
are successfully installed, otherwise if failed.
|
||||
|
||||
--*/
|
||||
{
|
||||
return NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gIp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gIp4ComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver supports this device
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the MNP service binding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Test for the Arp service binding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiArpServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4CleanService (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Create a new IP4 driver service binding protocol
|
||||
|
||||
@param Controller The controller that has MNP service binding
|
||||
installed
|
||||
@param ImageHandle The IP4 driver's image handle
|
||||
@param Service The variable to receive the newly created IP4
|
||||
service.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
|
||||
@retval EFI_SUCCESS A new IP4 service binding private is created.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT IP4_SERVICE **Service
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (Service != NULL);
|
||||
|
||||
*Service = NULL;
|
||||
|
||||
//
|
||||
// allocate a service private data then initialize all the filed to
|
||||
// empty resources, so if any thing goes wrong when allocating
|
||||
// resources, Ip4CleanService can be called to clean it up.
|
||||
//
|
||||
IpSb = NetAllocatePool (sizeof (IP4_SERVICE));
|
||||
|
||||
if (IpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
IpSb->Signature = IP4_SERVICE_SIGNATURE;
|
||||
IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;
|
||||
IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;
|
||||
IpSb->State = IP4_SERVICE_UNSTARTED;
|
||||
IpSb->InDestory = FALSE;
|
||||
|
||||
IpSb->NumChildren = 0;
|
||||
NetListInit (&IpSb->Children);
|
||||
|
||||
NetListInit (&IpSb->Interfaces);
|
||||
IpSb->DefaultInterface = NULL;
|
||||
IpSb->DefaultRouteTable = NULL;
|
||||
|
||||
Ip4InitAssembleTable (&IpSb->Assemble);
|
||||
|
||||
IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;
|
||||
NetListInit (&IpSb->IgmpCtrl.Groups);
|
||||
|
||||
IpSb->Image = ImageHandle;
|
||||
IpSb->Controller = Controller;
|
||||
|
||||
IpSb->MnpChildHandle = NULL;
|
||||
IpSb->Mnp = NULL;
|
||||
|
||||
IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;
|
||||
IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;
|
||||
IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;
|
||||
IpSb->MnpConfigData.EnableUnicastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnableMulticastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;
|
||||
IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;
|
||||
IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;
|
||||
IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;
|
||||
IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;
|
||||
|
||||
NetZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
IpSb->Ip4Config = NULL;
|
||||
IpSb->DoneEvent = NULL;
|
||||
IpSb->ReconfigEvent = NULL;
|
||||
|
||||
//
|
||||
// Create various resources. First create the route table, timer
|
||||
// event and MNP child. IGMP, interface's initialization depend
|
||||
// on the MNP child.
|
||||
//
|
||||
IpSb->DefaultRouteTable = Ip4CreateRouteTable ();
|
||||
|
||||
if (IpSb->DefaultRouteTable == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Ip4TimerTicking,
|
||||
IpSb,
|
||||
&IpSb->Timer
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = NetLibCreateServiceChild (
|
||||
Controller,
|
||||
ImageHandle,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
&IpSb->MnpChildHandle
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **) &IpSb->Mnp,
|
||||
ImageHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4ServiceConfigMnp (IpSb, TRUE);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4InitIgmp (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);
|
||||
|
||||
if (IpSb->DefaultInterface == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);
|
||||
|
||||
IpSb->MacString = NULL;
|
||||
|
||||
*Service = IpSb;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip4CleanService (IpSb);
|
||||
NetFreePool (IpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up a IP4 service binding instance. It will release all
|
||||
the resource allocated by the instance. The instance may be
|
||||
partly initialized, or partly destoried. If a resource is
|
||||
destoried, it is marked as that in case the destory failed and
|
||||
being called again later.
|
||||
|
||||
@param IpSb The IP4 serviceing binding instance to clean up
|
||||
|
||||
@retval EFI_SUCCESS The resource used by the instance are cleaned up
|
||||
@retval Others Failed to clean up some of the resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4CleanService (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (IpSb->DefaultInterface != NULL) {
|
||||
Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
IpSb->DefaultInterface = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->DefaultRouteTable != NULL) {
|
||||
Ip4FreeRouteTable (IpSb->DefaultRouteTable);
|
||||
IpSb->DefaultRouteTable = NULL;
|
||||
}
|
||||
|
||||
Ip4CleanAssembleTable (&IpSb->Assemble);
|
||||
|
||||
if (IpSb->MnpChildHandle != NULL) {
|
||||
if (IpSb->Mnp) {
|
||||
gBS->CloseProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
IpSb->Image,
|
||||
IpSb->Controller
|
||||
);
|
||||
|
||||
IpSb->Mnp = NULL;
|
||||
}
|
||||
|
||||
NetLibDestroyServiceChild (
|
||||
IpSb->Controller,
|
||||
IpSb->Image,
|
||||
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
||||
IpSb->MnpChildHandle
|
||||
);
|
||||
|
||||
IpSb->MnpChildHandle = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->Timer != NULL) {
|
||||
gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
|
||||
gBS->CloseEvent (IpSb->Timer);
|
||||
|
||||
IpSb->Timer = NULL;
|
||||
}
|
||||
|
||||
if (IpSb->Ip4Config != NULL) {
|
||||
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
IpSb->Controller,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
IpSb->Image,
|
||||
IpSb->Controller
|
||||
);
|
||||
|
||||
gBS->CloseEvent (IpSb->DoneEvent);
|
||||
gBS->CloseEvent (IpSb->ReconfigEvent);
|
||||
IpSb->Ip4Config = NULL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCES This driver is added to ControllerHandle
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
||||
@retval other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the Ip4 service binding protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Ip4ServiceBinding Protocol onto ControlerHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
&IpSb->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto FREE_SERVICE;
|
||||
}
|
||||
|
||||
//
|
||||
// ready to go: start the receiving and timer
|
||||
//
|
||||
Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the IP4 ID
|
||||
//
|
||||
mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
|
||||
|
||||
Ip4SetVariableData (IpSb);
|
||||
|
||||
return Status;
|
||||
|
||||
UNINSTALL_PROTOCOL:
|
||||
gBS->UninstallProtocolInterface (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
&IpSb->ServiceBinding
|
||||
);
|
||||
|
||||
FREE_SERVICE:
|
||||
Ip4CleanService (IpSb);
|
||||
NetFreePool (IpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCES This driver is removed ControllerHandle
|
||||
@retval other This driver was not removed from this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
//
|
||||
// IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
|
||||
// by driver. So the ControllerHandle may be the MNP child handle, ARP child
|
||||
// handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
|
||||
// in the NIC handle.
|
||||
//
|
||||
//
|
||||
// First, check whether it is the IP4_CONFIG protocol being uninstalled.
|
||||
// IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
|
||||
// to clean up the default configuration if IP4_CONFIG is being stopped.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
//
|
||||
// Retrieve the IP4 service binding protocol. If failed, it is
|
||||
// likely that Ip4 ServiceBinding is uninstalled already. In this
|
||||
// case, return immediately.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if (IpSb->Ip4Config && (IpSb->State != IP4_SERVICE_DESTORY)) {
|
||||
|
||||
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ConfigProtocolGuid,
|
||||
IpSb->Image,
|
||||
ControllerHandle
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// If the auto configure hasn't complete, mark it as not started.
|
||||
//
|
||||
if (IpSb->State == IP4_SERVICE_STARTED) {
|
||||
IpSb->State = IP4_SERVICE_UNSTARTED;
|
||||
}
|
||||
|
||||
IpSb->Ip4Config = NULL;
|
||||
gBS->CloseEvent (IpSb->DoneEvent);
|
||||
gBS->CloseEvent (IpSb->ReconfigEvent);
|
||||
}
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Either MNP or ARP protocol is being uninstalled. The controller
|
||||
// handle is either the MNP child or ARP child. But, the IP4's
|
||||
// service binding is installed on the NIC handle. So, need to open
|
||||
// the protocol info to find the NIC handle.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
|
||||
}
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the IP4 service binding protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if (IpSb->InDestory) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
IpSb->InDestory = TRUE;
|
||||
|
||||
State = IpSb->State;
|
||||
IpSb->State = IP4_SERVICE_DESTORY;
|
||||
|
||||
//
|
||||
// Destory all the children first. If not all children are destoried,
|
||||
// the IP driver can operate correctly, so restore it state. Don't
|
||||
// use NET_LIST_FOR_EACH_SAFE here, because it will cache the next
|
||||
// pointer, which may point to the child that has already been destoried.
|
||||
// For example, if there are two child in the list, the first is UDP
|
||||
// listen child, the send is the MTFTP's child. When Udp child is
|
||||
// destoried, it will destory the MTFTP's child. Then Next point to
|
||||
// a invalid child.
|
||||
//
|
||||
while (!NetListIsEmpty (&IpSb->Children)) {
|
||||
IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);
|
||||
Ip4ServiceBindingDestroyChild (ServiceBinding, IpInstance->Handle);
|
||||
}
|
||||
|
||||
if (IpSb->NumChildren != 0) {
|
||||
IpSb->State = State;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Clear the variable data.
|
||||
//
|
||||
Ip4ClearVariableData (IpSb);
|
||||
|
||||
//
|
||||
// OK, clean other resources then uninstall the service binding protocol.
|
||||
//
|
||||
Status = Ip4CleanService (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
NetFreePool (IpSb);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
IpSb->InDestory = FALSE;
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it
|
||||
is not NULL, then the I/O services are added to
|
||||
the existing child handle.
|
||||
|
||||
@retval EFI_SUCCES The child handle was created with the I/O services
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
|
||||
the child
|
||||
@retval other The child handle was not created
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
VOID *Mnp;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
|
||||
IpInstance = NetAllocatePool (sizeof (IP4_PROTOCOL));
|
||||
|
||||
if (IpInstance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ip4InitProtocol (IpSb, IpInstance);
|
||||
|
||||
//
|
||||
// Install Ip4 onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
IpInstance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Managed Network protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
(VOID **) &Mnp,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
IpInstance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert it into the service binding instance.
|
||||
//
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
NetListInsertTail (&IpSb->Children, &IpInstance->Link);
|
||||
IpSb->NumChildren++;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
Ip4CleanProtocol (IpInstance);
|
||||
|
||||
NetFreePool (IpInstance);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of I/O services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Handle of the child to destroy
|
||||
|
||||
@retval EFI_SUCCES The I/O services were removed from the child
|
||||
handle
|
||||
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
|
||||
that are being removed
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
|
||||
its I/O services are being used.
|
||||
@retval other The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP4_SERVICE *IpSb;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_IP4_PROTOCOL *Ip4;
|
||||
EFI_TPL OldTpl;
|
||||
INTN State;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
(VOID **) &Ip4,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);
|
||||
|
||||
if (IpInstance->Service != IpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
//
|
||||
// A child can be destoried more than once. For example,
|
||||
// Ip4DriverBindingStop will destory all of its children.
|
||||
// when UDP driver is being stopped, it will destory all
|
||||
// the IP child it opens.
|
||||
//
|
||||
if (IpInstance->State == IP4_STATE_DESTORY) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
State = IpInstance->State;
|
||||
IpInstance->State = IP4_STATE_DESTORY;
|
||||
|
||||
//
|
||||
// Close the Managed Network protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
IpSb->MnpChildHandle,
|
||||
&gEfiManagedNetworkProtocolGuid,
|
||||
gIp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the IP4 protocol first. Many thing happens during
|
||||
// this:
|
||||
// 1. The consumer of the IP4 protocol will be stopped if it
|
||||
// opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
|
||||
// stopped, IP driver's stop function will be called, and uninstall
|
||||
// EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
|
||||
// makes it possible to create the network stack bottom up, and
|
||||
// stop it top down.
|
||||
// 2. the upper layer will recycle the received packet. The recycle
|
||||
// event's TPL is higher than this function. The recycle events
|
||||
// will be called back before preceeding. If any packets not recycled,
|
||||
// that means there is a resource leak.
|
||||
//
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
&IpInstance->Ip4Proto
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4CleanProtocol (IpInstance);
|
||||
|
||||
Ip4SetVariableData (IpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->InstallMultipleProtocolInterfaces (
|
||||
&ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
Ip4,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListRemoveEntry (&IpInstance->Link);
|
||||
IpSb->NumChildren--;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
NetFreePool (IpInstance);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
IpInstance->State = State;
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
84
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.h
Normal file
84
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.h
Normal file
@ -0,0 +1,84 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, 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:
|
||||
|
||||
Ip4Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_DRIVER_H__
|
||||
#define __EFI_IP4_DRIVER_H__
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gIp4ComponentName;
|
||||
|
||||
//
|
||||
// Function prototype for the driver's entry point
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Drivr Binding Protocol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Function ptototypes for the ServiceBinding Prococol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Ip4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
#endif
|
81
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
Normal file
81
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
Normal file
@ -0,0 +1,81 @@
|
||||
#/** @file
|
||||
# Component name for module Ip4
|
||||
#
|
||||
# Copyright (c) 2007, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Ip4Dxe
|
||||
FILE_GUID = 9FB1A1F3-3B71-4324-B39A-745CBB015FFF
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = Ip4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Ip4Driver.c
|
||||
Ip4Option.h
|
||||
Ip4Route.h
|
||||
Ip4If.c
|
||||
Ip4Igmp.h
|
||||
Ip4Output.c
|
||||
Ip4Icmp.c
|
||||
Ip4Igmp.c
|
||||
Ip4Impl.c
|
||||
Ip4Common.h
|
||||
Ip4Impl.h
|
||||
Ip4Driver.h
|
||||
Ip4Common.c
|
||||
Ip4If.h
|
||||
Ip4Option.c
|
||||
Ip4Output.h
|
||||
ComponentName.c
|
||||
Ip4Input.h
|
||||
Ip4Route.c
|
||||
Ip4Icmp.h
|
||||
Ip4Input.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
DebugLib
|
||||
NetLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ConfigProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
101
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.msa
Normal file
101
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.msa
Normal file
@ -0,0 +1,101 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Ip4Dxe</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>9FB1A1F3-3B71-4324-B39A-745CBB015FFF</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Ip4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Ip4Dxe</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiRuntimeServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>Ip4Input.c</Filename>
|
||||
<Filename>Ip4Icmp.h</Filename>
|
||||
<Filename>Ip4Route.c</Filename>
|
||||
<Filename>Ip4Input.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>Ip4Output.h</Filename>
|
||||
<Filename>Ip4Option.c</Filename>
|
||||
<Filename>Ip4If.h</Filename>
|
||||
<Filename>Ip4Common.c</Filename>
|
||||
<Filename>Ip4Driver.h</Filename>
|
||||
<Filename>Ip4Impl.h</Filename>
|
||||
<Filename>Ip4Common.h</Filename>
|
||||
<Filename>Ip4Impl.c</Filename>
|
||||
<Filename>Ip4Igmp.c</Filename>
|
||||
<Filename>Ip4Icmp.c</Filename>
|
||||
<Filename>Ip4Output.c</Filename>
|
||||
<Filename>Ip4Igmp.h</Filename>
|
||||
<Filename>Ip4If.c</Filename>
|
||||
<Filename>Ip4Route.h</Filename>
|
||||
<Filename>Ip4Option.h</Filename>
|
||||
<Filename>Ip4Driver.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiArpServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ConfigProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>Ip4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
372
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
Normal file
372
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
Normal file
@ -0,0 +1,372 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Icmp.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
IP4_ICMP_CLASS
|
||||
mIcmpClass[] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_QUERY_MESSAGE },
|
||||
{1, ICMP_INVALID_MESSAGE},
|
||||
{2, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_SOURCE_QUENCH, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_REDIRECT, ICMP_ERROR_MESSAGE },
|
||||
{6, ICMP_INVALID_MESSAGE},
|
||||
{7, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_ECHO_REQUEST, ICMP_QUERY_MESSAGE },
|
||||
{9, ICMP_INVALID_MESSAGE},
|
||||
{10, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_TIME_EXCEEDED, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_ERROR_MESSAGE },
|
||||
{ICMP_TIMESTAMP , ICMP_QUERY_MESSAGE },
|
||||
{14, ICMP_INVALID_MESSAGE},
|
||||
{ICMP_INFO_REQUEST , ICMP_QUERY_MESSAGE },
|
||||
{ICMP_INFO_REPLY , ICMP_QUERY_MESSAGE },
|
||||
};
|
||||
|
||||
EFI_IP4_ICMP_TYPE
|
||||
mIp4SupportedIcmp [23] = {
|
||||
{ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PROTO_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_PORT_UNREACHABLE },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_FRAGMENT_FAILED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCEROUTE_FAILED},
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNKNOWN },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_SOURCE_ISOLATED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_PROHIBITED },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE_TOS },
|
||||
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE_TOS},
|
||||
|
||||
{ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_REDIRECT, ICMP_NET_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_NET_TOS_REDIRECT },
|
||||
{ICMP_REDIRECT, ICMP_HOST_TOS_REDIRECT },
|
||||
|
||||
{ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },
|
||||
|
||||
{ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT},
|
||||
{ICMP_TIME_EXCEEDED, ICMp_TIMEOUT_REASSEMBLE},
|
||||
|
||||
{ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP redirect. Find the instance then update
|
||||
its route cache.
|
||||
All kinds of redirect is treated as host redirect as
|
||||
specified by RFC1122 3.3.1.2:
|
||||
"Since the subnet mask appropriate to the destination
|
||||
address is generally not known, a Network Redirect
|
||||
message SHOULD be treated identically to a Host Redirect
|
||||
message;"
|
||||
|
||||
@param IpSb The IP4 service binding instance that received the
|
||||
packet
|
||||
@param Head The IP head of the received ICMPpacket.
|
||||
@param Packet The content of the ICMP redirect packet with IP
|
||||
head removed.
|
||||
@param Icmp The buffer to store the ICMP error message if
|
||||
something is wrong.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid
|
||||
@retval EFI_SUCCESS Successfully updated the route caches
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpRedirect (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ICMP_ERROR_HEAD *Icmp
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_PROTOCOL *Ip4Instance;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ADDR Gateway;
|
||||
|
||||
//
|
||||
// Find the interface whose IP address is the source of the
|
||||
// orgianl IP packet.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));
|
||||
Gateway = NTOHL (Icmp->Fourth);
|
||||
|
||||
//
|
||||
// discard the packet if the new gateway address it specifies
|
||||
// is not on the same connected net through which the Redirect
|
||||
// arrived. (RFC1122 3.2.2.2).
|
||||
//
|
||||
if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Update each IP child's route cache on the interface.
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
|
||||
Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
|
||||
|
||||
if (Ip4Instance->RouteTable == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CacheEntry = Ip4FindRouteCache (
|
||||
Ip4Instance->RouteTable,
|
||||
NTOHL (Icmp->IpHead.Dst),
|
||||
NTOHL (Icmp->IpHead.Src)
|
||||
);
|
||||
|
||||
//
|
||||
// Only update the route cache's gateway if the source of the
|
||||
// Redirect is the current first-hop gateway
|
||||
//
|
||||
if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {
|
||||
CacheEntry->NextHop = Gateway;
|
||||
}
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP error packet. If it is an ICMP redirect packet,
|
||||
update call Ip4ProcessIcmpRedirect to update the IP instance's
|
||||
route cache, otherwise, deliver the packet to upper layer.
|
||||
|
||||
@param IpSb The IP service that received the packet.
|
||||
@param Head The IP head of the ICMP error packet
|
||||
@param Packet The content of the ICMP error with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval Others Failed to process the packet.
|
||||
@retval EFI_SUCCESS The ICMP error is processed successfully.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpError (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_ERROR_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
//
|
||||
// If it is an ICMP redirect error, update the route cache
|
||||
// as RFC1122. Otherwise, demultiplex it to IP instances.
|
||||
//
|
||||
if (Icmp.Head.Type == ICMP_REDIRECT) {
|
||||
return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);
|
||||
}
|
||||
|
||||
IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
|
||||
return Ip4Demultiplex (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Replay an ICMP echo request.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP error packet
|
||||
@param Packet The content of the ICMP error with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
|
||||
@retval EFI_SUCCESS The ICMP Echo request is successfully answered.
|
||||
@retval Others Failed to answer the ICMP echo request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpReplyEcho (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD *Icmp;
|
||||
NET_BUF *Data;
|
||||
EFI_STATUS Status;
|
||||
IP4_HEAD ReplyHead;
|
||||
|
||||
//
|
||||
// make a copy the packet, it is really a bad idea to
|
||||
// send the MNP's buffer back to MNP.
|
||||
//
|
||||
Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Data == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Change the ICMP type to echo reply, exchange the source
|
||||
// and destination, then send it. The source is updated to
|
||||
// use specific destination. See RFC1122. SRR/RR option
|
||||
// update is omitted.
|
||||
//
|
||||
Icmp = (IP4_ICMP_QUERY_HEAD *) NetbufGetByte (Data, 0, NULL);
|
||||
Icmp->Head.Type = ICMP_ECHO_REPLY;
|
||||
Icmp->Head.Checksum = 0;
|
||||
Icmp->Head.Checksum = ~NetblockChecksum ((UINT8 *) Icmp, Data->TotalSize);
|
||||
|
||||
ReplyHead.Tos = 0;
|
||||
ReplyHead.Fragment = 0;
|
||||
ReplyHead.Ttl = 64;
|
||||
ReplyHead.Protocol = IP4_PROTO_ICMP;
|
||||
ReplyHead.Src = 0;
|
||||
|
||||
//
|
||||
// Ip4Output will select a source for us
|
||||
//
|
||||
ReplyHead.Dst = Head->Src;
|
||||
|
||||
Status = Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Data,
|
||||
&ReplyHead,
|
||||
NULL,
|
||||
0,
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
|
||||
ON_EXIT:
|
||||
NetbufFree (Packet);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the ICMP query message. If it is an ICMP echo
|
||||
request, answer it. Otherwise deliver it to upper layer.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP query packet
|
||||
@param Packet The content of the ICMP query with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is invalid
|
||||
@retval EFI_SUCCESS The ICMP query message is processed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4ProcessIcmpQuery (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_QUERY_HEAD Icmp;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {
|
||||
return Ip4IcmpReplyEcho (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
return Ip4Demultiplex (IpSb, Head, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the ICMP packet. First validate the message format,
|
||||
then according to the message types, process it as query or
|
||||
error packet.
|
||||
|
||||
@param IpSb The IP service that receivd the packet
|
||||
@param Head The IP head of the ICMP query packet
|
||||
@param Packet The content of the ICMP query with IP head
|
||||
removed.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformated.
|
||||
@retval EFI_SUCCESS The ICMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IP4_ICMP_HEAD Icmp;
|
||||
UINT16 Checksum;
|
||||
|
||||
if (Packet->TotalSize < sizeof (Icmp)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
|
||||
|
||||
if (Icmp.Type > ICMP_TYPE_MAX) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
Checksum = ~NetbufChecksum (Packet);
|
||||
if ((Icmp.Checksum != 0) && (Checksum != 0)) {
|
||||
goto DROP;
|
||||
}
|
||||
|
||||
if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
|
||||
return Ip4ProcessIcmpError (IpSb, Head, Packet);
|
||||
|
||||
} else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {
|
||||
return Ip4ProcessIcmpQuery (IpSb, Head, Packet);
|
||||
|
||||
}
|
||||
|
||||
DROP:
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
99
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.h
Normal file
99
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.h
Normal file
@ -0,0 +1,99 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Icmp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header file for ICMP protocol.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ICMP_H__
|
||||
#define __EFI_IP4_ICMP_H__
|
||||
|
||||
enum {
|
||||
//
|
||||
// ICMP type definations
|
||||
//
|
||||
ICMP_ECHO_REPLY = 0,
|
||||
ICMP_DEST_UNREACHABLE = 3,
|
||||
ICMP_SOURCE_QUENCH = 4,
|
||||
ICMP_REDIRECT = 5,
|
||||
ICMP_ECHO_REQUEST = 8,
|
||||
ICMP_TIME_EXCEEDED = 11,
|
||||
ICMP_PARAMETER_PROBLEM = 12,
|
||||
ICMP_TIMESTAMP = 13,
|
||||
ICMP_INFO_REQUEST = 15,
|
||||
ICMP_INFO_REPLY = 16,
|
||||
ICMP_TYPE_MAX = ICMP_INFO_REPLY,
|
||||
|
||||
ICMP_DEFAULT_CODE = 0,
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_DEST_UNREACHABLE
|
||||
//
|
||||
ICMP_NET_UNREACHABLE = 0,
|
||||
ICMP_HOST_UNREACHABLE = 1,
|
||||
ICMP_PROTO_UNREACHABLE = 2, // Host may generate
|
||||
ICMP_PORT_UNREACHABLE = 3, // Host may generate
|
||||
ICMP_FRAGMENT_FAILED = 4,
|
||||
ICMP_SOURCEROUTE_FAILED = 5, // Host may generate
|
||||
ICMP_NET_UNKNOWN = 6,
|
||||
ICMP_HOST_UNKNOWN = 7,
|
||||
ICMP_SOURCE_ISOLATED = 8,
|
||||
ICMP_NET_PROHIBITED = 9,
|
||||
ICMP_HOST_PROHIBITED = 10,
|
||||
ICMP_NET_UNREACHABLE_TOS = 11,
|
||||
ICMP_HOST_UNREACHABLE_TOS = 12,
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
ICMP_TIMEOUT_IN_TRANSIT = 0,
|
||||
ICMp_TIMEOUT_REASSEMBLE = 1, // Host may generate
|
||||
|
||||
//
|
||||
// ICMP code definations for ICMP_TIME_EXCEEDED
|
||||
//
|
||||
ICMP_NET_REDIRECT = 0,
|
||||
ICMP_HOST_REDIRECT = 1,
|
||||
ICMP_NET_TOS_REDIRECT = 2,
|
||||
ICMP_HOST_TOS_REDIRECT = 3,
|
||||
|
||||
//
|
||||
// ICMP message classes, each class of ICMP message shares
|
||||
// a common message format. INVALID_MESSAGE is only a flag.
|
||||
//
|
||||
ICMP_INVALID_MESSAGE = 0,
|
||||
ICMP_ERROR_MESSAGE = 1,
|
||||
ICMP_QUERY_MESSAGE = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UINT8 IcmpType;
|
||||
UINT8 IcmpClass;
|
||||
} IP4_ICMP_CLASS;
|
||||
|
||||
extern IP4_ICMP_CLASS mIcmpClass[];
|
||||
extern EFI_IP4_ICMP_TYPE mIp4SupportedIcmp[];
|
||||
|
||||
EFI_STATUS
|
||||
Ip4IcmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Header,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
#endif
|
1146
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
Normal file
1146
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
Normal file
File diff suppressed because it is too large
Load Diff
238
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
Normal file
238
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
Normal file
@ -0,0 +1,238 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4If.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Definition for IP4 pesudo interface structure.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IF_H__
|
||||
#define __EFI_IP4_IF_H__
|
||||
|
||||
enum {
|
||||
IP4_FRAME_RX_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'R'),
|
||||
IP4_FRAME_TX_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'T'),
|
||||
IP4_FRAME_ARP_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'F', 'A'),
|
||||
IP4_INTERFACE_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', 'I', 'F'),
|
||||
};
|
||||
|
||||
//
|
||||
// This prototype is used by both receive and transmission.
|
||||
// When receiving Netbuf is allocated by IP4_INTERFACE, and
|
||||
// released by IP4. Flag shows whether the frame is received
|
||||
// as link broadcast/multicast...
|
||||
//
|
||||
// When transmitting, the Netbuf is from IP4, and provided
|
||||
// to the callback as a reference. Flag isn't used.
|
||||
//
|
||||
// IpInstance can be NULL which means that it is the IP4 driver
|
||||
// itself sending the packets. IP4 driver may send packets that
|
||||
// don't belong to any instance, such as ICMP errors, ICMP echo
|
||||
// responses, or IGMP packets. IpInstance is used as a tag in
|
||||
// this module.
|
||||
//
|
||||
typedef
|
||||
VOID
|
||||
(*IP4_FRAME_CALLBACK) (
|
||||
IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each receive request is wrapped in an IP4_LINK_RX_TOKEN.
|
||||
// Upon completion, the Callback will be called. Only one
|
||||
// receive request is send to MNP. IpInstance is always NULL.
|
||||
// Reference MNP's spec for information.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
} IP4_LINK_RX_TOKEN;
|
||||
|
||||
//
|
||||
// Each transmit request is wrapped in an IP4_LINK_TX_TOKEN.
|
||||
// Upon completion, the Callback will be called.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
IP4_FRAME_CALLBACK CallBack;
|
||||
NET_BUF *Packet;
|
||||
VOID *Context;
|
||||
|
||||
EFI_MAC_ADDRESS DstMac;
|
||||
EFI_MAC_ADDRESS SrcMac;
|
||||
|
||||
EFI_MANAGED_NETWORK_COMPLETION_TOKEN MnpToken;
|
||||
EFI_MANAGED_NETWORK_TRANSMIT_DATA MnpTxData;
|
||||
} IP4_LINK_TX_TOKEN;
|
||||
|
||||
//
|
||||
// Only one ARP request is requested for all the frames in
|
||||
// a time. It is started for the first frames to the Ip. Any
|
||||
// subsequent transmission frame will be linked to Frames, and
|
||||
// be sent all at once the ARP requests succeed.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
NET_LIST_ENTRY Frames;
|
||||
IP4_INTERFACE *Interface;
|
||||
|
||||
//
|
||||
// ARP requesting staffs
|
||||
//
|
||||
EFI_EVENT OnResolved;
|
||||
IP4_ADDR Ip;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IP4_ARP_QUE;
|
||||
|
||||
//
|
||||
// Callback to select which frame to cancel. Caller can cancel a
|
||||
// single frame, or all the frame from an IP instance.
|
||||
//
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*IP4_FRAME_TO_CANCEL) (
|
||||
IP4_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Each IP4 instance has its own station address. All the instances
|
||||
// with the same station address share a single interface structure.
|
||||
// Each interface has its own ARP child, and shares one MNP child.
|
||||
// Notice the special cases that DHCP can configure the interface
|
||||
// with 0.0.0.0/0.0.0.0.
|
||||
//
|
||||
typedef struct _IP4_INTERFACE {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
|
||||
//
|
||||
// IP address and subnet mask of the interface. It also contains
|
||||
// the subnet/net broadcast address for quick access. The fileds
|
||||
// are invalid if (Configured == FALSE)
|
||||
//
|
||||
IP4_ADDR Ip;
|
||||
IP4_ADDR SubnetMask;
|
||||
IP4_ADDR SubnetBrdcast;
|
||||
IP4_ADDR NetBrdcast;
|
||||
BOOLEAN Configured;
|
||||
|
||||
//
|
||||
// Handle used to create/destory ARP child. All the IP children
|
||||
// share one MNP which is owned by IP service binding.
|
||||
//
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
EFI_ARP_PROTOCOL *Arp;
|
||||
EFI_HANDLE ArpHandle;
|
||||
|
||||
//
|
||||
// Queues to keep the frames sent and waiting ARP request.
|
||||
//
|
||||
NET_LIST_ENTRY ArpQues;
|
||||
NET_LIST_ENTRY SentFrames;
|
||||
IP4_LINK_RX_TOKEN *RecvRequest;
|
||||
|
||||
//
|
||||
// The interface's MAC and broadcast MAC address.
|
||||
//
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
EFI_MAC_ADDRESS BroadcastMac;
|
||||
UINT32 HwaddrLen;
|
||||
|
||||
//
|
||||
// All the IP instances that have the same IP/SubnetMask are linked
|
||||
// together through IpInstances. If any of the instance enables
|
||||
// promiscuous receive, PromiscRecv is true.
|
||||
//
|
||||
NET_LIST_ENTRY IpInstances;
|
||||
BOOLEAN PromiscRecv;
|
||||
} IP4_INTERFACE;
|
||||
|
||||
IP4_INTERFACE *
|
||||
Ip4CreateInterface (
|
||||
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SetAddress (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_ADDR IpAddr,
|
||||
IN IP4_ADDR SubnetMask
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4FreeInterface (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SendFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_ADDR NextHop,
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelFrames (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN IP4_FRAME_TO_CANCEL FrameToCancel, OPTIONAL
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelReceive (
|
||||
IN IP4_INTERFACE *Interface
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4ReceiveFrame (
|
||||
IN IP4_INTERFACE *Interface,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN IP4_FRAME_CALLBACK CallBack,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
#endif
|
629
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.c
Normal file
629
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.c
Normal file
@ -0,0 +1,629 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Igmp.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file implements the RFC2236: IGMP v2
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
//
|
||||
// Route Alert option in IGMP report to direct routers to
|
||||
// examine the packet more closely.
|
||||
//
|
||||
UINT32 mRouteAlertOption = 0x00000494;
|
||||
|
||||
|
||||
/**
|
||||
Init the IGMP control data of the IP4 service instance, configure
|
||||
MNP to receive ALL SYSTEM multicast.
|
||||
|
||||
@param IpSb The IP4 service whose IGMP is to be initialized.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to initialize IGMP.
|
||||
@retval Others Failed to initialize the IGMP of IpSb.
|
||||
@retval EFI_SUCCESS IGMP of the IpSb is successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Configure MNP to receive ALL_SYSTEM multicast
|
||||
//
|
||||
Group = NetAllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group->Address = IP4_ALLSYSTEM_ADDRESS;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, IP4_ALLSYSTEM_ADDRESS, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NetFreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find the IGMP_GROUP structure which contains the status of multicast
|
||||
group Address in this IGMP control block
|
||||
|
||||
@param IgmpCtrl The IGMP control block to search from
|
||||
@param Address The multicast address to search
|
||||
|
||||
@return NULL if the multicast address isn't in the IGMP control block. Otherwise
|
||||
@return the point to the IGMP_GROUP which contains the status of multicast group
|
||||
@return for Address.
|
||||
|
||||
**/
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (Group->Address == Address) {
|
||||
return Group;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Count the number of IP4 multicast groups that are mapped to the
|
||||
same MAC address. Several IP4 multicast address may be mapped to
|
||||
the same MAC address.
|
||||
|
||||
@param IgmpCtrl The IGMP control block to search in
|
||||
@param Mac The MAC address to search
|
||||
|
||||
@return The number of the IP4 multicast group that mapped to the same
|
||||
@return multicast group Mac.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4FindMac (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN EFI_MAC_ADDRESS *Mac
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
INTN Count;
|
||||
|
||||
Count = 0;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP protocol message to the Dst, such as IGMP v1 membership report.
|
||||
|
||||
@param IpSb The IP4 service instance that requests the
|
||||
transmission
|
||||
@param Dst The destinaton to send to
|
||||
@param Type The IGMP message type, such as IGMP v2 membership
|
||||
report
|
||||
@param Group The group address in the IGMP message head.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message
|
||||
@retval EFI_SUCCESS The IGMP message is successfully send
|
||||
@retval Others Failed to send the IGMP message.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpMessage (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN UINT8 Type,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
IP4_HEAD Head;
|
||||
NET_BUF *Packet;
|
||||
IGMP_HEAD *Igmp;
|
||||
|
||||
//
|
||||
// Allocate a net buffer to hold the message
|
||||
//
|
||||
Packet = NetbufAlloc (IP4_MAX_HEADLEN + sizeof (IGMP_HEAD));
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the IGMP and IP header, then transmit the message
|
||||
//
|
||||
NetbufReserve (Packet, IP4_MAX_HEADLEN);
|
||||
|
||||
Igmp = (IGMP_HEAD *) NetbufAllocSpace (Packet, sizeof (IGMP_HEAD), FALSE);
|
||||
|
||||
Igmp->Type = Type;
|
||||
Igmp->MaxRespTime = 0;
|
||||
Igmp->Checksum = 0;
|
||||
Igmp->Group = HTONL (Group);
|
||||
Igmp->Checksum = ~NetblockChecksum ((UINT8 *) Igmp, sizeof (IGMP_HEAD));
|
||||
|
||||
Head.Tos = 0;
|
||||
Head.Protocol = IP4_PROTO_IGMP;
|
||||
Head.Ttl = 1;
|
||||
Head.Fragment = 0;
|
||||
Head.Dst = Dst;
|
||||
Head.Src = IP4_ALLZERO_ADDRESS;
|
||||
|
||||
return Ip4Output (
|
||||
IpSb,
|
||||
NULL,
|
||||
Packet,
|
||||
&Head,
|
||||
(UINT8 *) &mRouteAlertOption,
|
||||
sizeof (UINT32),
|
||||
IP4_ALLZERO_ADDRESS,
|
||||
Ip4SysPacketSent,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send an IGMP membership report. Depends on whether the server is
|
||||
v1 or v2, it will send either a V1 or V2 membership report.
|
||||
|
||||
@param IpSb The IP4 service instance that requests the
|
||||
transmission.
|
||||
@param Group The group address to report
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory to build the message
|
||||
@retval EFI_SUCCESS The IGMP report message is successfully send
|
||||
@retval Others Failed to send the report.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4SendIgmpReport (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Group
|
||||
)
|
||||
{
|
||||
if (IpSb->IgmpCtrl.Igmpv1QuerySeen != 0) {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V1_MEMBERSHIP_REPORT, Group);
|
||||
} else {
|
||||
return Ip4SendIgmpMessage (IpSb, Group, IGMP_V2_MEMBERSHIP_REPORT, Group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Join the multicast group on behavior of this IP4 child
|
||||
|
||||
@param IpInstance The IP4 child that wants to join the group
|
||||
@param Address The group to join
|
||||
|
||||
@retval EFI_SUCCESS Successfully join the multicast group
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources
|
||||
@retval Others Failed to join the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
//
|
||||
// If the IP service already is a member in the group, just
|
||||
// increase the refernce count and return.
|
||||
//
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group != NULL) {
|
||||
Group->RefCnt++;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, create a new IGMP_GROUP, Get the multicast's MAC address,
|
||||
// send a report, then direct MNP to receive the multicast.
|
||||
//
|
||||
Group = NetAllocatePool (sizeof (IGMP_GROUP));
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Group->Address = Address;
|
||||
Group->RefCnt = 1;
|
||||
Group->DelayTime = IGMP_UNSOLICIATED_REPORT;
|
||||
Group->ReportByUs = TRUE;
|
||||
|
||||
Status = Ip4GetMulticastMac (Mnp, Address, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ip4SendIgmpReport (IpSb, Address);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Mnp->Groups (Mnp, TRUE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
NetListInsertHead (&IgmpCtrl->Groups, &Group->Link);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
NetFreePool (Group);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Leave the IP4 multicast group on behavior of IpInstance.
|
||||
|
||||
@param IpInstance The IP4 child that wants to leave the group
|
||||
address
|
||||
@param Address The group address to leave
|
||||
|
||||
@retval EFI_NOT_FOUND The IP4 service instance isn't in the group
|
||||
@retval EFI_SUCCESS Successfully leave the multicast group.
|
||||
@retval Others Failed to leave the multicast group.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
)
|
||||
{
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
IP4_SERVICE *IpSb;
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_GROUP *Group;
|
||||
EFI_STATUS Status;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
Mnp = IpSb->Mnp;
|
||||
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if (Group == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If more than one instance is in the group, decrease
|
||||
// the RefCnt then return.
|
||||
//
|
||||
if (--Group->RefCnt > 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If multiple IP4 group addresses are mapped to the same
|
||||
// multicast MAC address, don't configure the MNP to leave
|
||||
// the MAC.
|
||||
//
|
||||
if (Ip4FindMac (IgmpCtrl, &Group->Mac) == 1) {
|
||||
Status = Mnp->Groups (Mnp, FALSE, &Group->Mac);
|
||||
|
||||
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send a leave report if the membership is reported by us
|
||||
// and we are talking IGMPv2.
|
||||
//
|
||||
if (Group->ReportByUs && !IgmpCtrl->Igmpv1QuerySeen) {
|
||||
Ip4SendIgmpMessage (IpSb, IP4_ALLROUTER_ADDRESS, IGMP_LEAVE_GROUP, Group->Address);
|
||||
}
|
||||
|
||||
NetListRemoveEntry (&Group->Link);
|
||||
NetFreePool (Group);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle the received IGMP message for the IP4 service instance.
|
||||
|
||||
@param IpSb The IP4 service instance that received the message
|
||||
@param Head The IP4 header of the received message
|
||||
@param Packet The IGMP message, without IP4 header
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IGMP message is malformated.
|
||||
@retval EFI_SUCCESS The IGMP message is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
IGMP_HEAD Igmp;
|
||||
IGMP_GROUP *Group;
|
||||
IP4_ADDR Address;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
//
|
||||
// Must checksum over the whole packet, later IGMP version
|
||||
// may employ message longer than 8 bytes. IP's header has
|
||||
// already been trimmed off.
|
||||
//
|
||||
if ((Packet->TotalSize < sizeof (Igmp)) || (NetbufChecksum (Packet) != 0)) {
|
||||
NetbufFree (Packet);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the packet in case it is fragmented
|
||||
//
|
||||
NetbufCopy (Packet, 0, sizeof (IGMP_HEAD), (UINT8 *)&Igmp);
|
||||
|
||||
switch (Igmp.Type) {
|
||||
case IGMP_MEMBERSHIP_QUERY:
|
||||
//
|
||||
// If MaxRespTIme is zero, it is most likely that we are
|
||||
// talking to a V1 router
|
||||
//
|
||||
if (Igmp.MaxRespTime == 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen = IGMP_V1ROUTER_PRESENT;
|
||||
Igmp.MaxRespTime = 100;
|
||||
}
|
||||
|
||||
//
|
||||
// Igmp is ticking once per second but MaxRespTime is in
|
||||
// the unit of 100ms.
|
||||
//
|
||||
Igmp.MaxRespTime /= 10;
|
||||
Address = NTOHL (Igmp.Group);
|
||||
|
||||
if (Address == IP4_ALLSYSTEM_ADDRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
|
||||
//
|
||||
// If address is all zero, all the memberships will be reported.
|
||||
// otherwise only one is reported.
|
||||
//
|
||||
if ((Address == IP4_ALLZERO_ADDRESS) || (Address == Group->Address)) {
|
||||
//
|
||||
// If the timer is pending, only update it if the time left
|
||||
// is longer than the MaxRespTime. TODO: randomize the DelayTime.
|
||||
//
|
||||
if ((Group->DelayTime == 0) || (Group->DelayTime > Igmp.MaxRespTime)) {
|
||||
Group->DelayTime = NET_MAX (1, Igmp.MaxRespTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IGMP_V1_MEMBERSHIP_REPORT:
|
||||
case IGMP_V2_MEMBERSHIP_REPORT:
|
||||
Address = NTOHL (Igmp.Group);
|
||||
Group = Ip4FindGroup (IgmpCtrl, Address);
|
||||
|
||||
if ((Group != NULL) && (Group->DelayTime > 0)) {
|
||||
Group->DelayTime = 0;
|
||||
Group->ReportByUs = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
NetbufFree (Packet);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The periodical timer function for IGMP. It does the following
|
||||
things:
|
||||
1. Decrease the Igmpv1QuerySeen to make it possible to refresh
|
||||
the IGMP server type.
|
||||
2. Decrease the report timer for each IGMP group in "delaying
|
||||
member" state.
|
||||
|
||||
@param IpSb The IP4 service instance that is ticking
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
IGMP_SERVICE_DATA *IgmpCtrl;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IGMP_GROUP *Group;
|
||||
|
||||
IgmpCtrl = &IpSb->IgmpCtrl;
|
||||
|
||||
if (IgmpCtrl->Igmpv1QuerySeen > 0) {
|
||||
IgmpCtrl->Igmpv1QuerySeen--;
|
||||
}
|
||||
|
||||
//
|
||||
// Decrease the report timer for each IGMP group in "delaying member"
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &IgmpCtrl->Groups) {
|
||||
Group = NET_LIST_USER_STRUCT (Entry, IGMP_GROUP, Link);
|
||||
ASSERT (Group->DelayTime >= 0);
|
||||
|
||||
if (Group->DelayTime > 0) {
|
||||
Group->DelayTime--;
|
||||
|
||||
if (Group->DelayTime == 0) {
|
||||
Ip4SendIgmpReport (IpSb, Group->Address);
|
||||
Group->ReportByUs = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a group address to the array of group addresses.
|
||||
The caller should make sure that no duplicated address
|
||||
existed in the array. Although the function doesn't
|
||||
assume the byte order of the both Source and Addr, the
|
||||
network byte order is used by the caller.
|
||||
|
||||
@param Source The array of group addresses to add to
|
||||
@param Count The number of group addresses in the Source
|
||||
@param Addr The IP4 multicast address to add
|
||||
|
||||
@return NULL if failed to allocate memory for the new groups,
|
||||
@return otherwise the new combined group addresses.
|
||||
|
||||
**/
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *Source,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
IP4_ADDR *Groups;
|
||||
|
||||
Groups = NetAllocatePool (sizeof (IP4_ADDR) * (Count + 1));
|
||||
|
||||
if (Groups == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetCopyMem (Groups, Source, Count * sizeof (IP4_ADDR));
|
||||
Groups[Count] = Addr;
|
||||
|
||||
return Groups;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a group address frome the array of group addresses.
|
||||
Although the function doesn't assume the byte order of the
|
||||
both Groups and Addr, the network byte order is used by
|
||||
the caller.
|
||||
|
||||
@param Groups The array of group addresses to remove from
|
||||
@param Count The number of group addresses in the Groups
|
||||
@param Addr The IP4 multicast address to remove
|
||||
|
||||
@return The nubmer of group addresses in the Groups after remove.
|
||||
@return It is Count if the Addr isn't in the Groups.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN IP4_ADDR *Groups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
if (Groups[Index] == Addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (Index < Count - 1) {
|
||||
Groups[Index] = Groups[Index + 1];
|
||||
Index++;
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
120
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.h
Normal file
120
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.h
Normal file
@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Igmp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IGMP_H__
|
||||
#define __EFI_IP4_IGMP_H__
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 Type;
|
||||
UINT8 MaxRespTime;
|
||||
UINT16 Checksum;
|
||||
IP4_ADDR Group;
|
||||
} IGMP_HEAD;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// The status of multicast group. It isn't necessary to maintain
|
||||
// explicit state of host state diagram. A group with non-zero
|
||||
// DelayTime is in "delaying member" state. otherwise, it is in
|
||||
// "idle member" state.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Address;
|
||||
INTN DelayTime;
|
||||
BOOLEAN ReportByUs;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
} IGMP_GROUP;
|
||||
|
||||
//
|
||||
// The IGMP status. Each IP4 service instance has a IGMP_SERVICE_DATA
|
||||
// attached. The Igmpv1QuerySeen remember whether the server on this
|
||||
// connected network is v1 or v2.
|
||||
//
|
||||
typedef struct {
|
||||
INTN Igmpv1QuerySeen;
|
||||
NET_LIST_ENTRY Groups;
|
||||
} IGMP_SERVICE_DATA;
|
||||
|
||||
enum {
|
||||
//
|
||||
// IGMP message type
|
||||
//
|
||||
IGMP_MEMBERSHIP_QUERY = 0x11,
|
||||
IGMP_V1_MEMBERSHIP_REPORT = 0x12,
|
||||
IGMP_V2_MEMBERSHIP_REPORT = 0x16,
|
||||
IGMP_LEAVE_GROUP = 0x17,
|
||||
|
||||
IGMP_V1ROUTER_PRESENT = 400,
|
||||
IGMP_UNSOLICIATED_REPORT = 10,
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
Ip4InitIgmp (
|
||||
IN IP4_SERVICE *IpService
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4JoinGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4LeaveGroup (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4IgmpHandle (
|
||||
IN IP4_SERVICE *IpService,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4IgmpTicking (
|
||||
IN IP4_SERVICE *IpService
|
||||
);
|
||||
|
||||
IP4_ADDR *
|
||||
Ip4CombineGroups (
|
||||
IN IP4_ADDR *SourceGroups,
|
||||
IN UINT32 Count,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4RemoveGroupAddr (
|
||||
IN IP4_ADDR *Group,
|
||||
IN UINT32 GroupCnt,
|
||||
IN IP4_ADDR Addr
|
||||
);
|
||||
|
||||
IGMP_GROUP *
|
||||
Ip4FindGroup (
|
||||
IN IGMP_SERVICE_DATA *IgmpCtrl,
|
||||
IN IP4_ADDR Address
|
||||
);
|
||||
#endif
|
2022
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
Normal file
2022
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
Normal file
File diff suppressed because it is too large
Load Diff
258
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h
Normal file
258
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h
Normal file
@ -0,0 +1,258 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Impl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Ip4 internal functions and type defintions.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_IMPL_H__
|
||||
#define __EFI_IP4_IMPL_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/IP4.h>
|
||||
#include <Protocol/IP4Config.h>
|
||||
#include <Protocol/Arp.h>
|
||||
#include <Protocol/ManagedNetwork.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include "IP4Common.h"
|
||||
#include "IP4Driver.h"
|
||||
#include "IP4If.h"
|
||||
#include "Ip4Icmp.h"
|
||||
#include "IP4Option.h"
|
||||
#include "Ip4Igmp.h"
|
||||
#include "IP4Route.h"
|
||||
#include "IP4Input.h"
|
||||
#include "IP4Output.h"
|
||||
|
||||
enum {
|
||||
IP4_PROTOCOL_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', '4', 'P'),
|
||||
IP4_SERVICE_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', '4', 'S'),
|
||||
|
||||
//
|
||||
// The state of IP4 protocol. It starts from UNCONFIGED. if it is
|
||||
// successfully configured, it goes to CONFIGED. if configure NULL
|
||||
// is called, it becomes UNCONFIGED again. If (partly) destoried, it
|
||||
// becomes DESTORY.
|
||||
//
|
||||
IP4_STATE_UNCONFIGED = 0,
|
||||
IP4_STATE_CONFIGED,
|
||||
IP4_STATE_DESTORY,
|
||||
|
||||
//
|
||||
// The state of IP4 service. It starts from UNSTARTED. It transits
|
||||
// to STARTED if autoconfigure is started. If default address is
|
||||
// configured, it becomes CONFIGED. and if partly destoried, it goes
|
||||
// to DESTORY.
|
||||
//
|
||||
IP4_SERVICE_UNSTARTED = 0,
|
||||
IP4_SERVICE_STARTED,
|
||||
IP4_SERVICE_CONFIGED,
|
||||
IP4_SERVICE_DESTORY,
|
||||
};
|
||||
|
||||
//
|
||||
// IP4_TXTOKEN_WRAP wraps the upper layer's transmit token.
|
||||
// The user's data is kept in the Packet. When fragment is
|
||||
// needed, each fragment of the Packet has a reference to the
|
||||
// Packet, no data is actually copied. The Packet will be
|
||||
// released when all the fragments of it have been recycled by
|
||||
// MNP. Upon then, the IP4_TXTOKEN_WRAP will be released, and
|
||||
// user's event signalled.
|
||||
//
|
||||
typedef struct {
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
EFI_IP4_COMPLETION_TOKEN *Token;
|
||||
NET_BUF *Packet;
|
||||
BOOLEAN Sent;
|
||||
INTN Life;
|
||||
} IP4_TXTOKEN_WRAP;
|
||||
|
||||
//
|
||||
// IP4_RXDATA_WRAP wraps the data IP4 child delivers to the
|
||||
// upper layers. The received packet is kept in the Packet.
|
||||
// The Packet itself may be constructured from some fragments.
|
||||
// All the fragments of the Packet is organized by a
|
||||
// IP4_ASSEMBLE_ENTRY structure. If the Packet is recycled by
|
||||
// the upper layer, the assemble entry and its associated
|
||||
// fragments will be freed at last.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
IP4_PROTOCOL *IpInstance;
|
||||
NET_BUF *Packet;
|
||||
EFI_IP4_RECEIVE_DATA RxData;
|
||||
} IP4_RXDATA_WRAP;
|
||||
|
||||
typedef struct _IP4_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
|
||||
EFI_IP4_PROTOCOL Ip4Proto;
|
||||
EFI_HANDLE Handle;
|
||||
INTN State;
|
||||
|
||||
IP4_SERVICE *Service;
|
||||
NET_LIST_ENTRY Link; // Link to all the IP protocol from the service
|
||||
|
||||
//
|
||||
// User's transmit/receive tokens, and received/deliverd packets
|
||||
//
|
||||
NET_MAP RxTokens;
|
||||
NET_MAP TxTokens; // map between (User's Token, IP4_TXTOKE_WRAP)
|
||||
NET_LIST_ENTRY Received; // Received but not delivered packet
|
||||
NET_LIST_ENTRY Delivered; // Delivered and to be recycled packets
|
||||
EFI_LOCK RecycleLock;
|
||||
|
||||
//
|
||||
// Instance's address and route tables. There are two route tables.
|
||||
// RouteTable is used by the IP4 driver to route packet. EfiRouteTable
|
||||
// is used to communicate the current route info to the upper layer.
|
||||
//
|
||||
IP4_INTERFACE *Interface;
|
||||
NET_LIST_ENTRY AddrLink; // Ip instances with the same IP address.
|
||||
IP4_ROUTE_TABLE *RouteTable;
|
||||
|
||||
EFI_IP4_ROUTE_TABLE *EfiRouteTable;
|
||||
UINT32 EfiRouteCount;
|
||||
|
||||
//
|
||||
// IGMP data for this instance
|
||||
//
|
||||
IP4_ADDR *Groups; // stored in network byte order
|
||||
UINT32 GroupCount;
|
||||
|
||||
EFI_IP4_CONFIG_DATA ConfigData;
|
||||
|
||||
} IP4_PROTOCOL;
|
||||
|
||||
typedef struct _IP4_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
INTN State;
|
||||
BOOLEAN InDestory;
|
||||
|
||||
//
|
||||
// List of all the IP instances and interfaces, and default
|
||||
// interface and route table and caches.
|
||||
//
|
||||
UINTN NumChildren;
|
||||
NET_LIST_ENTRY Children;
|
||||
|
||||
NET_LIST_ENTRY Interfaces;
|
||||
|
||||
IP4_INTERFACE *DefaultInterface;
|
||||
IP4_ROUTE_TABLE *DefaultRouteTable;
|
||||
|
||||
//
|
||||
// Ip reassemble utilities, and IGMP data
|
||||
//
|
||||
IP4_ASSEMBLE_TABLE Assemble;
|
||||
IGMP_SERVICE_DATA IgmpCtrl;
|
||||
|
||||
//
|
||||
// Low level protocol used by this service instance
|
||||
//
|
||||
EFI_HANDLE Image;
|
||||
EFI_HANDLE Controller;
|
||||
|
||||
EFI_HANDLE MnpChildHandle;
|
||||
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
||||
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
|
||||
EFI_SIMPLE_NETWORK_MODE SnpMode;
|
||||
|
||||
EFI_EVENT Timer;
|
||||
|
||||
//
|
||||
// Auto configure staff
|
||||
//
|
||||
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
|
||||
EFI_EVENT DoneEvent;
|
||||
EFI_EVENT ReconfigEvent;
|
||||
|
||||
//
|
||||
// The string representation of the current mac address of the
|
||||
// NIC this IP4_SERVICE works on.
|
||||
//
|
||||
CHAR16 *MacString;
|
||||
} IP4_SERVICE;
|
||||
|
||||
#define IP4_INSTANCE_FROM_PROTOCOL(Ip4) \
|
||||
CR ((Ip4), IP4_PROTOCOL, Ip4Proto, IP4_PROTOCOL_SIGNATURE)
|
||||
|
||||
#define IP4_SERVICE_FROM_PROTOCOL(Sb) \
|
||||
CR ((Sb), IP4_SERVICE, ServiceBinding, IP4_SERVICE_SIGNATURE)
|
||||
|
||||
#define IP4_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)
|
||||
|
||||
extern EFI_IP4_PROTOCOL mEfiIp4ProtocolTemplete;
|
||||
|
||||
EFI_STATUS
|
||||
Ip4ServiceConfigMnp (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN BOOLEAN Force
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4InitProtocol (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4CleanProtocol (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Cancel (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN EFI_IP4_COMPLETION_TOKEN *Token
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Groups (
|
||||
IN IP4_PROTOCOL *IpInstance,
|
||||
IN BOOLEAN JoinFlag,
|
||||
IN EFI_IPv4_ADDRESS *GroupAddress
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
Ip4TimerTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4SentPacketTicking (
|
||||
IN NET_MAP *Map,
|
||||
IN NET_MAP_ITEM *Item,
|
||||
IN VOID *Context
|
||||
);
|
||||
#endif
|
1235
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Normal file
1235
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c
Normal file
File diff suppressed because it is too large
Load Diff
138
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h
Normal file
138
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h
Normal file
@ -0,0 +1,138 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Input.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_INPUT_H__
|
||||
#define __EFI_IP4_INPUT_H__
|
||||
|
||||
enum {
|
||||
IP4_MIN_HEADLEN = 20,
|
||||
IP4_MAX_HEADLEN = 60,
|
||||
|
||||
IP4_ASSEMLE_HASH_SIZE = 31,
|
||||
IP4_FRAGMENT_LIFE = 120,
|
||||
IP4_MAX_PACKET_SIZE = 65535,
|
||||
};
|
||||
|
||||
//
|
||||
// Per packet information for input process. LinkFlag specifies whether
|
||||
// the packet is received as Link layer unicast, multicast or broadcast.
|
||||
// The CastType is the IP layer cast type, such as IP multicast or unicast.
|
||||
// Start, End and Length are staffs used to assemble the packets. Start
|
||||
// is the sequence number of the first byte of data in the packet. Length
|
||||
// is the number of bytes of data. End = Start + Length, that is, the
|
||||
// sequence number of last byte + 1. Each assembled packet has a count down
|
||||
// life. If it isn't consumed before Life reaches zero, the packet is released.
|
||||
//
|
||||
typedef struct {
|
||||
UINTN LinkFlag;
|
||||
INTN CastType;
|
||||
INTN Start;
|
||||
INTN End;
|
||||
INTN Length;
|
||||
UINT32 Life;
|
||||
EFI_STATUS Status;
|
||||
} IP4_CLIP_INFO;
|
||||
|
||||
//
|
||||
// Structure used to assemble IP packets.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
|
||||
//
|
||||
// Identity of one IP4 packet. Each fragment of a packet has
|
||||
// the same (Dst, Src, Id, Protocol).
|
||||
//
|
||||
IP4_ADDR Dst;
|
||||
IP4_ADDR Src;
|
||||
UINT16 Id;
|
||||
UINT8 Protocol;
|
||||
|
||||
INTN TotalLen;
|
||||
INTN CurLen;
|
||||
NET_LIST_ENTRY Fragments; // List of all the fragments of this packet
|
||||
|
||||
IP4_HEAD *Head; // IP head of the first fragment
|
||||
IP4_CLIP_INFO *Info; // Per packet info of the first fragment
|
||||
INTN Life; // Count down life for the packet.
|
||||
} IP4_ASSEMBLE_ENTRY;
|
||||
|
||||
//
|
||||
// Each Ip service instance has an assemble table to reassemble
|
||||
// the packets before delivery to its children. It is organized
|
||||
// as hash table.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Bucket[IP4_ASSEMLE_HASH_SIZE];
|
||||
} IP4_ASSEMBLE_TABLE;
|
||||
|
||||
#define IP4_GET_CLIP_INFO(Packet) ((IP4_CLIP_INFO *) ((Packet)->ProtoData))
|
||||
|
||||
#define IP4_ASSEMBLE_HASH(Dst, Src, Id, Proto) \
|
||||
(((Dst) + (Src) + ((Id) << 16) + (Proto)) % IP4_ASSEMLE_HASH_SIZE)
|
||||
|
||||
#define IP4_RXDATA_WRAP_SIZE(NumFrag) \
|
||||
(sizeof (IP4_RXDATA_WRAP) + sizeof (EFI_IP4_FRAGMENT_DATA) * ((NumFrag) - 1))
|
||||
|
||||
VOID
|
||||
Ip4InitAssembleTable (
|
||||
IN IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CleanAssembleTable (
|
||||
IN IP4_ASSEMBLE_TABLE *Table
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4AccpetFrame (
|
||||
IN IP4_PROTOCOL *Ip4Instance,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN UINT32 Flag,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Demultiplex (
|
||||
IN IP4_SERVICE *SbInstance,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
INTN
|
||||
Ip4InterfaceEnquePacket (
|
||||
IN IP4_SERVICE *SbInstance,
|
||||
IN IP4_HEAD *Head,
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_INTERFACE *Interface
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4InstanceDeliverPacket (
|
||||
IN IP4_PROTOCOL *Ip4Instance
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4PacketTimerTicking (
|
||||
IN IP4_SERVICE *IpSb
|
||||
);
|
||||
|
||||
#endif
|
231
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
Normal file
231
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
Normal file
@ -0,0 +1,231 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Option.c
|
||||
|
||||
Abstract:
|
||||
|
||||
IP4 option support functions
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Validate the IP4 option format for both the packets we received
|
||||
and will transmit. It will compute the ICMP error message fields
|
||||
if the option is mal-formated. But this information isn't used.
|
||||
|
||||
@param Option The first byte of the option
|
||||
@param OptionLen The length of the whole option
|
||||
@param Rcvd The option is from the packet we received if TRUE,
|
||||
otherwise the option we wants to transmit.
|
||||
|
||||
@return TRUE: The option is properly formated
|
||||
@return FALSE: The option is mal-formated
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN Rcvd
|
||||
)
|
||||
{
|
||||
UINT32 Cur;
|
||||
UINT32 Len;
|
||||
UINT32 Point;
|
||||
UINT8 IcmpType;
|
||||
UINT8 IcmpCode;
|
||||
UINT32 IcmpPoint;
|
||||
|
||||
IcmpType = ICMP_PARAMETER_PROBLEM;
|
||||
IcmpCode = 0;
|
||||
IcmpPoint = 0;
|
||||
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
switch (Option[Cur]) {
|
||||
case IP4_OPTION_NOP:
|
||||
Cur++;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_EOP:
|
||||
Cur = OptionLen;
|
||||
break;
|
||||
|
||||
case IP4_OPTION_LSRR:
|
||||
case IP4_OPTION_SSRR:
|
||||
case IP4_OPTION_RR:
|
||||
Len = Option[Cur + 1];
|
||||
Point = Option[Cur + 2];
|
||||
|
||||
//
|
||||
// SRR/RR options are formated as |Type|Len|Point|Ip1|Ip2|...
|
||||
//
|
||||
if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {
|
||||
IcmpPoint = Cur + 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Point > Len + 1) || (Point % 4 != 0)) {
|
||||
IcmpPoint = Cur + 2;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The Point must point pass the last entry if the packet is received
|
||||
// by us. It must point to 4 if the packet is to be sent by us for
|
||||
// source route option.
|
||||
//
|
||||
if ((Option[Cur] != IP4_OPTION_RR) &&
|
||||
((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {
|
||||
|
||||
IcmpType = ICMP_DEST_UNREACHABLE;
|
||||
IcmpCode = ICMP_SOURCEROUTE_FAILED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
break;
|
||||
|
||||
default:
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if ((OptionLen - Cur < Len) || (Len < 2)) {
|
||||
IcmpPoint = Cur + 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cur = Cur + Len;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy the option from the original option to buffer. It
|
||||
handles the details such as:
|
||||
1. whether copy the single IP4 option to the first/non-first
|
||||
fragments.
|
||||
2. Pad the options copied over to aligened to 4 bytes.
|
||||
|
||||
@param Option The original option to copy from
|
||||
@param OptionLen The length of the original option
|
||||
@param FirstFragment Whether it is the first fragment
|
||||
@param Buf The buffer to copy options to
|
||||
@param BufLen The length of the buffer
|
||||
|
||||
@retval EFI_SUCCESS The options are copied over
|
||||
@retval EFI_BUFFER_TOO_SMALL The buffer caller provided is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptionLen,
|
||||
IN BOOLEAN FirstFragment,
|
||||
IN UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
)
|
||||
{
|
||||
UINT8 OptBuf[40];
|
||||
UINT32 Cur;
|
||||
UINT32 Next;
|
||||
UINT8 Type;
|
||||
UINT32 Len;
|
||||
|
||||
ASSERT ((BufLen != NULL) && (OptionLen <= 40));
|
||||
|
||||
Cur = 0;
|
||||
Next = 0;
|
||||
|
||||
while (Cur < OptionLen) {
|
||||
Type = Option[Cur];
|
||||
Len = Option[Cur + 1];
|
||||
|
||||
if (Type == IP4_OPTION_NOP) {
|
||||
//
|
||||
// Keep the padding, in case that the sender wants to align
|
||||
// the option, say, to 4 bytes
|
||||
//
|
||||
OptBuf[Next] = IP4_OPTION_NOP;
|
||||
Next++;
|
||||
Cur++;
|
||||
|
||||
} else if (Type == IP4_OPTION_EOP) {
|
||||
//
|
||||
// Don't append the EOP to avoid including only a EOP option
|
||||
//
|
||||
break;
|
||||
|
||||
} else {
|
||||
//
|
||||
// don't copy options that is only valid for the first fragment
|
||||
//
|
||||
if (FirstFragment || (Type & IP4_OPTION_COPY_MASK)) {
|
||||
NetCopyMem (OptBuf + Next, Option + Cur, Len);
|
||||
Next += Len;
|
||||
}
|
||||
|
||||
Cur += Len;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Don't append an EOP only option.
|
||||
//
|
||||
if (Next == 0) {
|
||||
*BufLen = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Append an EOP if the end of option doesn't coincide with the
|
||||
// end of the IP header, that is, isn't aligned to 4 bytes..
|
||||
//
|
||||
if ((Next % 4) != 0) {
|
||||
OptBuf[Next] = IP4_OPTION_EOP;
|
||||
Next++;
|
||||
}
|
||||
|
||||
//
|
||||
// Head length is in the unit of 4 bytes. Now, Len is the
|
||||
// acutal option length to appear in the IP header.
|
||||
//
|
||||
Len = ((Next + 3) &~0x03);
|
||||
|
||||
//
|
||||
// If the buffer is too small, set the BufLen then return
|
||||
//
|
||||
if ((Buf == NULL) || (*BufLen < Len)) {
|
||||
*BufLen = Len;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the option to the Buf, zero the buffer first to pad
|
||||
// the options with NOP to align to 4 bytes.
|
||||
//
|
||||
NetZeroMem (Buf, Len);
|
||||
NetCopyMem (Buf, OptBuf, Next);
|
||||
*BufLen = Len;
|
||||
return EFI_SUCCESS;
|
||||
}
|
52
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.h
Normal file
52
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.h
Normal file
@ -0,0 +1,52 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Option.h
|
||||
|
||||
Abstract:
|
||||
|
||||
IP4 option support routines.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OPTION_H__
|
||||
#define __EFI_IP4_OPTION_H__
|
||||
|
||||
enum {
|
||||
IP4_OPTION_EOP = 0,
|
||||
IP4_OPTION_NOP = 1,
|
||||
IP4_OPTION_LSRR = 131, // Loss source and record routing, 10000011
|
||||
IP4_OPTION_SSRR = 137, // Strict source and record routing, 10001001
|
||||
IP4_OPTION_RR = 7, // Record routing, 00000111
|
||||
|
||||
IP4_OPTION_COPY_MASK = 0x80,
|
||||
};
|
||||
|
||||
BOOLEAN
|
||||
Ip4OptionIsValid (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN BOOLEAN Rcvd
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4CopyOption (
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN BOOLEAN Fragment,
|
||||
IN UINT8 *Buf, OPTIONAL
|
||||
IN OUT UINT32 *BufLen
|
||||
);
|
||||
#endif
|
457
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
Normal file
457
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
Normal file
@ -0,0 +1,457 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Output.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Transmit the IP4 packet
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
UINT16 mIp4Id;
|
||||
|
||||
|
||||
/**
|
||||
Prepend an IP4 head to the Packet. It will copy the options and
|
||||
build the IP4 header fields. Used for IP4 fragmentation.
|
||||
|
||||
@param Packet The packet to prepend IP4 header to
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id,
|
||||
Fragment, Ttl, Protocol, Src and Dst. All the fields
|
||||
are in host byte order. This function will fill in
|
||||
the Ver, HeadLen, and checksum.
|
||||
@param Option The orginal IP4 option to copy from
|
||||
@param OptLen The length of the IP4 option
|
||||
|
||||
@retval EFI_BAD_BUFFER_SIZE There is no enought room in the head space of
|
||||
Packet.
|
||||
@retval EFI_SUCCESS The IP4 header is successfully added to the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4PrependHead (
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen
|
||||
)
|
||||
{
|
||||
UINT32 HeadLen;
|
||||
UINT32 Len;
|
||||
IP4_HEAD *PacketHead;
|
||||
BOOLEAN FirstFragment;
|
||||
|
||||
//
|
||||
// Prepend the options: first get the option length, then copy it over.
|
||||
//
|
||||
HeadLen = 0;
|
||||
FirstFragment = IP4_FIRST_FRAGMENT (Head->Fragment);
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, NULL, &Len);
|
||||
|
||||
HeadLen = IP4_MIN_HEADLEN + Len;
|
||||
ASSERT (((Len %4) == 0) && (HeadLen <= IP4_MAX_HEADLEN));
|
||||
|
||||
PacketHead = (IP4_HEAD *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
|
||||
|
||||
if (PacketHead == NULL) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Ip4CopyOption (Option, OptLen, FirstFragment, (UINT8 *) (PacketHead + 1), &Len);
|
||||
|
||||
//
|
||||
// Set the head up, convert the host byte order to network byte order
|
||||
//
|
||||
PacketHead->Ver = 4;
|
||||
PacketHead->HeadLen = (UINT8) (HeadLen >> 2);
|
||||
PacketHead->Tos = Head->Tos;
|
||||
PacketHead->TotalLen = HTONS (Packet->TotalSize);
|
||||
PacketHead->Id = HTONS (Head->Id);
|
||||
PacketHead->Fragment = HTONS (Head->Fragment);
|
||||
PacketHead->Checksum = 0;
|
||||
PacketHead->Ttl = Head->Ttl;
|
||||
PacketHead->Protocol = Head->Protocol;
|
||||
PacketHead->Src = HTONL (Head->Src);
|
||||
PacketHead->Dst = HTONL (Head->Dst);
|
||||
PacketHead->Checksum = ~NetblockChecksum ((UINT8 *) PacketHead, HeadLen);
|
||||
|
||||
Packet->Ip = PacketHead;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Select an interface to send the packet generated in the IP4 driver
|
||||
itself, that is, not by the requests of IP4 child's consumer. Such
|
||||
packets include the ICMP echo replies, and other ICMP error packets.
|
||||
|
||||
@param IpSb The IP4 service that wants to send the packets.
|
||||
@param Dst The destination of the packet
|
||||
@param Src The source of the packet
|
||||
|
||||
@return NULL if no proper interface is found, otherwise the interface that
|
||||
@return can be used to send the system packet from.
|
||||
|
||||
**/
|
||||
IP4_INTERFACE *
|
||||
Ip4SelectInterface (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_INTERFACE *Selected;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
|
||||
//
|
||||
// Select the interface the Dst is on if one of the connected
|
||||
// network. Some IP instance may be configured with 0.0.0.0/0,
|
||||
// don't select that interface now.
|
||||
//
|
||||
IpIf = Ip4FindNet (IpSb, Dst);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// If source is one of the interface address, select it.
|
||||
//
|
||||
IpIf = Ip4FindInterface (IpSb, Src);
|
||||
|
||||
if ((IpIf != NULL) && (IpIf->Ip != IP4_ALLZERO_ADDRESS)) {
|
||||
return IpIf;
|
||||
}
|
||||
|
||||
//
|
||||
// Select a configured interface as the fall back. Always prefer
|
||||
// an interface with non-zero address.
|
||||
//
|
||||
Selected = NULL;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
|
||||
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
|
||||
|
||||
if (IpIf->Configured && ((Selected == NULL) || (Selected->Ip == 0))) {
|
||||
Selected = IpIf;
|
||||
}
|
||||
}
|
||||
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The default callback function for system generated packet.
|
||||
It will free the packet.
|
||||
|
||||
@param Ip4Instance The IP4 child that issued the transmission. It most
|
||||
like is NULL.
|
||||
@param Packet The packet that transmitted.
|
||||
@param IoStatus The result of the transmission, succeeded or failed.
|
||||
@param LinkFlag Not used when transmission. check IP4_FRAME_CALLBACK
|
||||
for reference.
|
||||
@param Context The context provided by us
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 LinkFlag,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
NetbufFree (Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Transmit an IP4 packet. The packet comes either from the IP4
|
||||
child's consumer (IpInstance != NULL) or the IP4 driver itself
|
||||
(IpInstance == NULL). It will route the packet, fragment it,
|
||||
then transmit all the fragments through some interface.
|
||||
|
||||
@param IpSb The IP4 service instance to transmit the packet
|
||||
@param IpInstance The IP4 child that issues the transmission. It is
|
||||
NULL if the packet is from the system.
|
||||
@param Packet The user data to send, excluding the IP header.
|
||||
@param Head The caller supplied header. The caller should set
|
||||
the following header fields: Tos, TotalLen, Id, tl,
|
||||
Fragment, Protocol, Src and Dst. All the fields are
|
||||
in host byte order. This function will fill in the
|
||||
Ver, HeadLen, Fragment, and checksum. The Fragment
|
||||
only need to include the DF flag. Ip4Output will
|
||||
compute the MF and offset for you.
|
||||
@param Option The original option to append to the IP headers
|
||||
@param OptLen The length of the option
|
||||
@param GateWay The next hop address to transmit packet to.
|
||||
255.255.255.255 means broadcast.
|
||||
@param Callback The callback function to issue when transmission
|
||||
completed.
|
||||
@param Context The opaque context for the callback
|
||||
|
||||
@retval EFI_NO_MAPPING There is no interface to the destination.
|
||||
@retval EFI_NOT_FOUND There is no route to the destination
|
||||
@retval EFI_SUCCESS The packet is successfully transmitted.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Packet,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IP4_INTERFACE *IpIf;
|
||||
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
|
||||
IP4_ADDR Dest;
|
||||
EFI_STATUS Status;
|
||||
NET_BUF *Fragment;
|
||||
UINT32 Index;
|
||||
UINT32 HeadLen;
|
||||
UINT32 PacketLen;
|
||||
UINT32 Offset;
|
||||
UINT32 Mtu;
|
||||
UINT32 Num;
|
||||
|
||||
//
|
||||
// Select an interface/source for system packet, application
|
||||
// should select them itself.
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
IpIf = Ip4SelectInterface (IpSb, Head->Dst, Head->Src);
|
||||
} else {
|
||||
IpIf = IpInstance->Interface;
|
||||
}
|
||||
|
||||
if (IpIf == NULL) {
|
||||
return EFI_NO_MAPPING;
|
||||
}
|
||||
|
||||
if ((Head->Src == IP4_ALLZERO_ADDRESS) && (IpInstance == NULL)) {
|
||||
Head->Src = IpIf->Ip;
|
||||
}
|
||||
|
||||
//
|
||||
// Route the packet unless overrided, that is, GateWay isn't zero.
|
||||
//
|
||||
if (GateWay == IP4_ALLZERO_ADDRESS) {
|
||||
Dest = Head->Dst;
|
||||
|
||||
if (IP4_IS_BROADCAST (Ip4GetNetCast (Dest, IpIf)) || (Dest == IP4_ALLONE_ADDRESS)) {
|
||||
//
|
||||
// Set the gateway to local broadcast if the Dest is
|
||||
// is the broadcast address for the connected network
|
||||
// or it is local broadcast.
|
||||
//
|
||||
GateWay = IP4_ALLONE_ADDRESS;
|
||||
|
||||
} else if (IP4_IS_MULTICAST (Dest)) {
|
||||
//
|
||||
// Set the gateway to the destination if it is an multicast
|
||||
// address. The IP4_INTERFACE won't consult ARP to send local
|
||||
// broadcast and multicast.
|
||||
//
|
||||
GateWay = Head->Dst;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Consult the route table to route the packet
|
||||
//
|
||||
if (IpInstance == NULL) {
|
||||
CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
|
||||
} else {
|
||||
CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);
|
||||
}
|
||||
|
||||
if (CacheEntry == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
GateWay = CacheEntry->NextHop;
|
||||
Ip4FreeRouteCacheEntry (CacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// OK, selected the source and route, fragment the packet then send
|
||||
// them. Tag each fragment other than the first one as spawn from it.
|
||||
//
|
||||
Mtu = IpSb->SnpMode.MaxPacketSize;
|
||||
HeadLen = sizeof (IP4_HEAD) + (OptLen + 3) &~0x03;
|
||||
Head->Id = mIp4Id++;
|
||||
|
||||
if (Packet->TotalSize + HeadLen > Mtu) {
|
||||
//
|
||||
// Packet is fragmented from the tail to the head, that is, the
|
||||
// first frame sent is the last fragment of the packet. The first
|
||||
// fragment is NOT sent in this loop. First compute how many
|
||||
// fragments there are.
|
||||
//
|
||||
Mtu = (Mtu - HeadLen) & (~0x07);
|
||||
Num = (Packet->TotalSize + Mtu - 1) / Mtu;
|
||||
|
||||
//
|
||||
// Initialize the packet length and Offset. Other than the last
|
||||
// fragment, the packet length equals to MTU. The offset is always
|
||||
// aligned to MTU.
|
||||
//
|
||||
PacketLen = Packet->TotalSize - (Num - 1) * Mtu;
|
||||
Offset = Mtu * (Num - 1);
|
||||
|
||||
for (Index = 0; Index < Num - 1; Index++, Offset -= Mtu) {
|
||||
Fragment = NetbufGetFragment (Packet, Offset, PacketLen, IP4_MAX_HEADLEN);
|
||||
|
||||
if (Fragment == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the header's fragment. The caller fills the IP4 header
|
||||
// fields that are required by Ip4PrependHead except the fragment.
|
||||
//
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, (Index != 0), Offset);
|
||||
Ip4PrependHead (Fragment, Head, Option, OptLen);
|
||||
|
||||
//
|
||||
// Transmit the fragments, pass the Packet address as the context.
|
||||
// So, we can find all the fragments spawned from the Packet by
|
||||
// compare the NetBuf and Context to the Packet.
|
||||
//
|
||||
Status = Ip4SendFrame (
|
||||
IpIf,
|
||||
IpInstance,
|
||||
Fragment,
|
||||
GateWay,
|
||||
Ip4SysPacketSent,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
PacketLen = Mtu;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim the already sent data, then adjust the head's fragment field.
|
||||
//
|
||||
NetbufTrim (Packet, Packet->TotalSize - Mtu, FALSE);
|
||||
Head->Fragment = IP4_HEAD_FRAGMENT_FIELD (FALSE, TRUE, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Send the first fragment, it is either the orginal packet, or the
|
||||
// first fragment of a fragmented packet. It seems that there is a subtle
|
||||
// bug here: what if the caller free the packet in Callback and IpIf (or
|
||||
// MNP child used by that interface) still holds the fragments and try
|
||||
// to access the data? The caller can free the packet if it recycles the
|
||||
// consumer's (such as UDP) data in the Callback. But this can't happen.
|
||||
// The detailed sequence is:
|
||||
// 1. for the packets generated by IP4 driver itself:
|
||||
// The Callback is Ip4SysPacketSent, which is the same as the
|
||||
// fragments' callback. Ip4SysPacketSent simply calls NetbufFree
|
||||
// to release its reference to the packet. So, no problem for
|
||||
// system packets.
|
||||
//
|
||||
// 2. for the upper layer's packets (use UDP as an example):
|
||||
// UDP requests the IP layer to transmit some data which is
|
||||
// wrapped in an asynchronous token, the token is wrapped
|
||||
// in IP4_TXTOKEN_WRAP by IP4. IP4 also wrap the user's data
|
||||
// in a net buffer, which is Packet we get here. IP4_TXTOKEN_WRAP
|
||||
// is bound with the Packet. It will only be freed when all
|
||||
// the references to Packet have been released. Upon then, the
|
||||
// Packet's OnFree callback will release the IP4_TXTOKEN_WRAP,
|
||||
// and singal the user's recycle event. So, also no problem for
|
||||
// upper layer's packets.
|
||||
//
|
||||
Ip4PrependHead (Packet, Head, Option, OptLen);
|
||||
Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Ip4CancelPacket (IpIf, Packet, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The filter function to find a packet and all its fragments.
|
||||
The packet's fragments have their Context set to the packet.
|
||||
|
||||
@param Frame The frames hold by the low level interface
|
||||
@param Context Context to the function, which is the packet.
|
||||
|
||||
@retval TRUE This is the packet to cancel or its fragments.
|
||||
@retval FALSE This is unrelated packet.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
Ip4CancelPacketFragments (
|
||||
IP4_LINK_TX_TOKEN *Frame,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Cancel the Packet and all its fragments.
|
||||
|
||||
@param IpIf The interface from which the Packet is sent
|
||||
@param Packet The Packet to cancel
|
||||
@param IoStatus The status returns to the sender.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
)
|
||||
{
|
||||
Ip4CancelFrames (IpIf, IoStatus, Ip4CancelPacketFragments, Packet);
|
||||
}
|
54
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.h
Normal file
54
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.h
Normal file
@ -0,0 +1,54 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Output.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_OUTPUT_H__
|
||||
#define __EFI_IP4_OUTPUT_H__
|
||||
|
||||
VOID
|
||||
Ip4SysPacketSent (
|
||||
IP4_PROTOCOL *Ip4Instance,
|
||||
NET_BUF *Packet,
|
||||
EFI_STATUS IoStatus,
|
||||
UINT32 Flag,
|
||||
VOID *Context
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4Output (
|
||||
IN IP4_SERVICE *IpSb,
|
||||
IN IP4_PROTOCOL *IpInstance, OPTIONAL
|
||||
IN NET_BUF *Data,
|
||||
IN IP4_HEAD *Head,
|
||||
IN UINT8 *Option,
|
||||
IN UINT32 OptLen,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN IP4_FRAME_CALLBACK Callback,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4CancelPacket (
|
||||
IN IP4_INTERFACE *IpIf,
|
||||
IN NET_BUF *Packet,
|
||||
IN EFI_STATUS IoStatus
|
||||
);
|
||||
|
||||
extern UINT16 mIp4Id;
|
||||
#endif
|
690
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
Normal file
690
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
Normal file
@ -0,0 +1,690 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Route.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Ip4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Allocate a route entry then initialize it with the Dest/Netmaks
|
||||
and Gateway.
|
||||
|
||||
@param Dest The destination network
|
||||
@param Netmask The destination network mask
|
||||
@param GateWay The nexthop address
|
||||
|
||||
@return NULL if failed to allocate memeory, otherwise the newly created
|
||||
@return route entry.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4CreateRouteEntry (
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR GateWay
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
RtEntry = NetAllocatePool (sizeof (IP4_ROUTE_ENTRY));
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInit (&RtEntry->Link);
|
||||
|
||||
RtEntry->RefCnt = 1;
|
||||
RtEntry->Dest = Dest;
|
||||
RtEntry->Netmask = Netmask;
|
||||
RtEntry->NextHop = GateWay;
|
||||
RtEntry->Flag = 0;
|
||||
|
||||
return RtEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table entry. It is reference counted.
|
||||
|
||||
@param RtEntry The route entry to free.
|
||||
|
||||
@return NONE
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Ip4FreeRouteEntry (
|
||||
IN IP4_ROUTE_ENTRY *RtEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtEntry->RefCnt > 0);
|
||||
|
||||
if (--RtEntry->RefCnt == 0) {
|
||||
NetFreePool (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate and initialize a IP4 route cache entry.
|
||||
|
||||
@param Dst The destination address
|
||||
@param Src The source address
|
||||
@param GateWay The next hop address
|
||||
@param Tag The tag from the caller. This marks all the cache
|
||||
entries spawned from one route table entry.
|
||||
|
||||
@return NULL if failed to allocate memory for the cache, other point
|
||||
@return to the created route cache entry.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4CreateRouteCacheEntry (
|
||||
IN IP4_ADDR Dst,
|
||||
IN IP4_ADDR Src,
|
||||
IN IP4_ADDR GateWay,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
|
||||
RtCacheEntry = NetAllocatePool (sizeof (IP4_ROUTE_CACHE_ENTRY));
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInit (&RtCacheEntry->Link);
|
||||
|
||||
RtCacheEntry->RefCnt = 1;
|
||||
RtCacheEntry->Dest = Dst;
|
||||
RtCacheEntry->Src = Src;
|
||||
RtCacheEntry->NextHop = GateWay;
|
||||
RtCacheEntry->Tag = Tag;
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route cache entry. It is reference counted.
|
||||
|
||||
@param RtCacheEntry The route cache entry to free.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
)
|
||||
{
|
||||
ASSERT (RtCacheEntry->RefCnt > 0);
|
||||
|
||||
if (--RtCacheEntry->RefCnt == 0) {
|
||||
NetFreePool (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize an empty route cache table.
|
||||
|
||||
@param RtCache The rotue cache table to initialize.
|
||||
|
||||
@return NONE
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4InitRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NetListInit (&(RtCache->CacheBucket[Index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up a route cache, that is free all the route cache
|
||||
entries enqueued in the cache.
|
||||
|
||||
@param RtCache The route cache table to clean up
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4CleanRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtCache->CacheBucket[Index])) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Create an empty route table, includes its internal route cache
|
||||
|
||||
None
|
||||
|
||||
@return NULL if failed to allocate memory for the route table, otherwise
|
||||
@return the point to newly created route table.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_TABLE *
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
UINT32 Index;
|
||||
|
||||
RtTable = NetAllocatePool (sizeof (IP4_ROUTE_TABLE));
|
||||
|
||||
if (RtTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtTable->RefCnt = 1;
|
||||
RtTable->TotalNum = 0;
|
||||
|
||||
for (Index = 0; Index < IP4_MASK_NUM; Index++) {
|
||||
NetListInit (&(RtTable->RouteArea[Index]));
|
||||
}
|
||||
|
||||
RtTable->Next = NULL;
|
||||
|
||||
Ip4InitRouteCache (&RtTable->Cache);
|
||||
return RtTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free the route table and its associated route cache. Route
|
||||
table is reference counted.
|
||||
|
||||
@param RtTable The route table to free.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RtTable
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
UINT32 Index;
|
||||
|
||||
ASSERT (RtTable->RefCnt > 0);
|
||||
|
||||
if (--RtTable->RefCnt > 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Free all the route table entry and its route cache.
|
||||
//
|
||||
for (Index = 0; Index < IP4_MASK_NUM; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
}
|
||||
}
|
||||
|
||||
Ip4CleanRouteCache (&RtTable->Cache);
|
||||
|
||||
NetFreePool (RtTable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Remove all the cache entries bearing the Tag. When a route cache
|
||||
entry is created, it is tagged with the address of route entry
|
||||
from which it is spawned. When a route entry is deleted, the cache
|
||||
entries spawned from it are also deleted.
|
||||
|
||||
@param RtCache Route cache to remove the entries from
|
||||
@param Tag The Tag of the entries to remove
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Ip4PurgeRouteCache (
|
||||
IN IP4_ROUTE_CACHE *RtCache,
|
||||
IN UINTN Tag
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < IP4_ROUTE_CACHE_HASH; Index++) {
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &RtCache->CacheBucket[Index]) {
|
||||
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if (RtCacheEntry->Tag == Tag) {
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (RtCacheEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a route entry to the route table. All the IP4_ADDRs are in
|
||||
host byte order.
|
||||
|
||||
@param RtTable Route table to add route to
|
||||
@param Dest The destination of the network
|
||||
@param Netmask The netmask of the destination
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_ACCESS_DENIED The same route already exists
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the entry
|
||||
@retval EFI_SUCCESS The route is added successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
//
|
||||
// All the route entries with the same netmask length are
|
||||
// linke to the same route area
|
||||
//
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
//
|
||||
// First check whether the route exists
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a route entry and insert it to the route area.
|
||||
//
|
||||
RtEntry = Ip4CreateRouteEntry (Dest, Netmask, Gateway);
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (Gateway == IP4_ALLZERO_ADDRESS) {
|
||||
RtEntry->Flag = IP4_DIRECT_ROUTE;
|
||||
}
|
||||
|
||||
NetListInsertHead (Head, &RtEntry->Link);
|
||||
RtTable->TotalNum++;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove a route entry and all the route caches spawn from it.
|
||||
|
||||
@param RtTable The route table to remove the route from
|
||||
@param Dest The destination network
|
||||
@param Netmask The netmask of the Dest
|
||||
@param Gateway The next hop address
|
||||
|
||||
@retval EFI_SUCCESS The route entry is successfully removed
|
||||
@retval EFI_NOT_FOUND There is no route entry in the table with that
|
||||
properity.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
|
||||
Head = &(RtTable->RouteArea[NetGetMaskLength (Netmask)]);
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dest, Netmask) && (RtEntry->NextHop == Gateway)) {
|
||||
Ip4PurgeRouteCache (&RtTable->Cache, (UINTN) RtEntry);
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
|
||||
RtTable->TotalNum--;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find a route cache with the dst and src. This is used by ICMP
|
||||
redirect messasge process. All kinds of redirect is treated as
|
||||
host redirect according to RFC1122. So, only route cache entries
|
||||
are modified according to the ICMP redirect message.
|
||||
|
||||
@param RtTable The route table to search the cache for
|
||||
@param Dest The destination address
|
||||
@param Src The source address
|
||||
|
||||
@return NULL if no route entry to the (Dest, Src). Otherwise the point
|
||||
@return to the correct route cache entry.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
UINT32 Index;
|
||||
|
||||
Index = IP4_ROUTE_CACHE_HASH (Dest, Src);
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, &RtTable->Cache.CacheBucket[Index]) {
|
||||
RtCacheEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
if ((RtCacheEntry->Dest == Dest) && (RtCacheEntry->Src == Src)) {
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table for a most specific match to the Dst. It searches
|
||||
from the longest route area (mask length == 32) to the shortest route area (
|
||||
default routes). In each route area, it will first search the instance's
|
||||
route table, then the default route table. This is required by the following
|
||||
requirements:
|
||||
1. IP search the route table for a most specific match
|
||||
2. The local route entries have precedence over the default route entry.
|
||||
|
||||
@param RtTable The route table to search from
|
||||
@param Dst The destionation address to search
|
||||
|
||||
@return NULL if no route matches the Dst, otherwise the point to the
|
||||
@return most specific route to the Dst.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
IP4_ROUTE_ENTRY *
|
||||
Ip4FindRouteEntry (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dst
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ROUTE_TABLE *Table;
|
||||
INTN Index;
|
||||
|
||||
RtEntry = NULL;
|
||||
|
||||
for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {
|
||||
for (Table = RtTable; Table != NULL; Table = Table->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &Table->RouteArea[Index]) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
if (IP4_NET_EQUAL (RtEntry->Dest, Dst, RtEntry->Netmask)) {
|
||||
NET_GET_REF (RtEntry);
|
||||
return RtEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Search the route table to route the packet. Return/creat a route
|
||||
cache if there is a route to the destination.
|
||||
|
||||
@param RtTable The route table to search from
|
||||
@param Dest The destination address to search for
|
||||
@param Src The source address to search for
|
||||
|
||||
@return NULL if failed to route packet, otherwise a route cache
|
||||
@return entry that can be used to route packet.
|
||||
|
||||
**/
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Head;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
|
||||
IP4_ROUTE_CACHE_ENTRY *Cache;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Count;
|
||||
|
||||
ASSERT (RtTable != NULL);
|
||||
|
||||
Head = &RtTable->Cache.CacheBucket[IP4_ROUTE_CACHE_HASH (Dest, Src)];
|
||||
RtCacheEntry = Ip4FindRouteCache (RtTable, Dest, Src);
|
||||
|
||||
//
|
||||
// If found, promote the cache entry to the head of the hash bucket. LRU
|
||||
//
|
||||
if (RtCacheEntry != NULL) {
|
||||
NetListRemoveEntry (&RtCacheEntry->Link);
|
||||
NetListInsertHead (Head, &RtCacheEntry->Link);
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
//
|
||||
// Search the route table for the most specific route
|
||||
//
|
||||
RtEntry = Ip4FindRouteEntry (RtTable, Dest);
|
||||
|
||||
if (RtEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Found a route to the Dest, if it is a direct route, the packet
|
||||
// will be send directly to the destination, such as for connected
|
||||
// network. Otherwise, it is an indirect route, the packet will be
|
||||
// send the next hop router.
|
||||
//
|
||||
if (RtEntry->Flag & IP4_DIRECT_ROUTE) {
|
||||
NextHop = Dest;
|
||||
} else {
|
||||
NextHop = RtEntry->NextHop;
|
||||
}
|
||||
|
||||
Ip4FreeRouteEntry (RtEntry);
|
||||
|
||||
//
|
||||
// Create a route cache entry, and tag it as spawned from this route entry
|
||||
//
|
||||
RtCacheEntry = Ip4CreateRouteCacheEntry (Dest, Src, NextHop, (UINTN) RtEntry);
|
||||
|
||||
if (RtCacheEntry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInsertHead (Head, &RtCacheEntry->Link);
|
||||
NET_GET_REF (RtCacheEntry);
|
||||
|
||||
//
|
||||
// Each bucket of route cache can contain at most 64 entries.
|
||||
// Remove the entries at the tail of the bucket. These entries
|
||||
// are likely to be used least.
|
||||
//
|
||||
Count = 0;
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
|
||||
if (++Count < IP4_ROUTE_CACHE_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cache = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_CACHE_ENTRY, Link);
|
||||
|
||||
NetListRemoveEntry (Entry);
|
||||
Ip4FreeRouteCacheEntry (Cache);
|
||||
}
|
||||
|
||||
return RtCacheEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of
|
||||
GetModeData. The EFI_IP4_ROUTE_TABLE is clumsy to use in the
|
||||
internal operation of the IP4 driver.
|
||||
|
||||
@param IpInstance The IP4 child that requests the route table.
|
||||
|
||||
@retval EFI_SUCCESS The route table is successfully build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the rotue table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
)
|
||||
{
|
||||
IP4_SERVICE *IpSb;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
IP4_ROUTE_TABLE *RtTable;
|
||||
IP4_ROUTE_ENTRY *RtEntry;
|
||||
EFI_IP4_ROUTE_TABLE *Table;
|
||||
UINT32 Count;
|
||||
INT32 Index;
|
||||
|
||||
IpSb = IpInstance->Service;
|
||||
RtTable = IpInstance->RouteTable;
|
||||
|
||||
if (IpInstance->EfiRouteTable != NULL) {
|
||||
NetFreePool (IpInstance->EfiRouteTable);
|
||||
|
||||
IpInstance->EfiRouteTable = NULL;
|
||||
IpInstance->EfiRouteCount = 0;
|
||||
}
|
||||
|
||||
Count = RtTable->TotalNum;
|
||||
|
||||
if (RtTable->Next != NULL) {
|
||||
Count += RtTable->Next->TotalNum;
|
||||
}
|
||||
|
||||
if (Count == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Table = NetAllocatePool (sizeof (EFI_IP4_ROUTE_TABLE) * Count);
|
||||
|
||||
if (Table == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the route entry to EFI route table. Keep the order of
|
||||
// route entry copied from most specific to default route. That
|
||||
// is, interlevel the route entry from the instance's route area
|
||||
// and those from the default route table's route area.
|
||||
//
|
||||
Count = 0;
|
||||
|
||||
for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {
|
||||
for (RtTable = IpInstance->RouteTable; RtTable != NULL; RtTable = RtTable->Next) {
|
||||
NET_LIST_FOR_EACH (Entry, &(RtTable->RouteArea[Index])) {
|
||||
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
|
||||
|
||||
EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask);
|
||||
EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop);
|
||||
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpInstance->EfiRouteTable = Table;
|
||||
IpInstance->EfiRouteCount = Count;
|
||||
return EFI_SUCCESS;
|
||||
}
|
151
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
Normal file
151
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
Normal file
@ -0,0 +1,151 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 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:
|
||||
|
||||
Ip4Route.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI IP4 route table and route cache table defintions.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_IP4_ROUTE_H__
|
||||
#define __EFI_IP4_ROUTE_H__
|
||||
|
||||
#include "IP4Common.h"
|
||||
|
||||
enum {
|
||||
IP4_DIRECT_ROUTE = 0x00000001,
|
||||
|
||||
IP4_ROUTE_CACHE_HASH = 31,
|
||||
IP4_ROUTE_CACHE_MAX = 64, // Max NO. of cache entry per hash bucket
|
||||
};
|
||||
|
||||
#define IP4_ROUTE_CACHE_HASH(Dst, Src) (((Dst) ^ (Src)) % IP4_ROUTE_CACHE_HASH)
|
||||
|
||||
//
|
||||
// The route entry in the route table. Dest/Netmask is the destion
|
||||
// network. The nexthop is the gateway to send the packet to in
|
||||
// order to reach the Dest/Netmask. If the Flag has IP4_DIRECT_ROUTE
|
||||
// on, the gateway is the destination of the IP packet itself. Route
|
||||
// enties of the connected network have the flag on.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR NextHop;
|
||||
UINT32 Flag;
|
||||
} IP4_ROUTE_ENTRY;
|
||||
|
||||
//
|
||||
// The route cache entry. The route cache entry is optional.
|
||||
// But it is necessary to support the ICMP redirect message.
|
||||
// Check Ip4ProcessIcmpRedirect for information.
|
||||
//
|
||||
// The cache entry field Tag is used to tag all the route
|
||||
// cache entry spawned from a route table entry. This makes
|
||||
// it simple to delete all the route cache entries from a
|
||||
// to-be-deleted route entry.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN RefCnt;
|
||||
IP4_ADDR Dest;
|
||||
IP4_ADDR Src;
|
||||
IP4_ADDR NextHop;
|
||||
UINTN Tag;
|
||||
} IP4_ROUTE_CACHE_ENTRY;
|
||||
|
||||
//
|
||||
// The route cache table is organized as a hash table. Each
|
||||
// IP4 route table has a embedded route cache. For now the
|
||||
// route cache and route table are binded togehter. But keep
|
||||
// the route cache a seperated structure in case we want to
|
||||
// detach them later.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY CacheBucket[IP4_ROUTE_CACHE_HASH];
|
||||
} IP4_ROUTE_CACHE;
|
||||
|
||||
//
|
||||
// Each IP4 instance has its own route table. Each ServiceBinding
|
||||
// instance has a default route table and default address.
|
||||
//
|
||||
// All the route table entries with the same mask are linked
|
||||
// together in one route area. For example, RouteArea[0] contains
|
||||
// the default routes. A route table also contains a route cache.
|
||||
//
|
||||
typedef struct _IP4_ROUTE_TABLE IP4_ROUTE_TABLE;
|
||||
|
||||
typedef struct _IP4_ROUTE_TABLE {
|
||||
INTN RefCnt;
|
||||
UINT32 TotalNum;
|
||||
NET_LIST_ENTRY RouteArea[IP4_MASK_NUM];
|
||||
IP4_ROUTE_TABLE *Next;
|
||||
IP4_ROUTE_CACHE Cache;
|
||||
};
|
||||
|
||||
IP4_ROUTE_TABLE*
|
||||
Ip4CreateRouteTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4FreeRouteTable (
|
||||
IN IP4_ROUTE_TABLE *RouteTable
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4AddRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4DelRoute (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Netmask,
|
||||
IN IP4_ADDR Gateway
|
||||
);
|
||||
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4FindRouteCache (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
VOID
|
||||
Ip4FreeRouteCacheEntry (
|
||||
IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry
|
||||
);
|
||||
|
||||
IP4_ROUTE_CACHE_ENTRY *
|
||||
Ip4Route (
|
||||
IN IP4_ROUTE_TABLE *RtTable,
|
||||
IN IP4_ADDR Dest,
|
||||
IN IP4_ADDR Src
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Ip4BuildEfiRouteTable (
|
||||
IN IP4_PROTOCOL *IpInstance
|
||||
);
|
||||
#endif
|
@ -139,7 +139,7 @@ MnpAddFreeNbuf (
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
|
||||
Nbuf = NetbufAlloc (MnpServiceData->BufferLength);
|
||||
Nbuf = NetbufAlloc (MnpServiceData->BufferLength + MnpServiceData->PaddingSize);
|
||||
if (Nbuf == NULL) {
|
||||
|
||||
MNP_DEBUG_ERROR (("MnpAddFreeNbuf: NetBufAlloc failed.\n"));
|
||||
@ -147,6 +147,14 @@ MnpAddFreeNbuf (
|
||||
break;
|
||||
}
|
||||
|
||||
if (MnpServiceData->PaddingSize > 0) {
|
||||
//
|
||||
// Pad padding bytes before the media header
|
||||
//
|
||||
NetbufAllocSpace (Nbuf, MnpServiceData->PaddingSize, NET_BUF_TAIL);
|
||||
NetbufTrim (Nbuf, MnpServiceData->PaddingSize, NET_BUF_HEAD);
|
||||
}
|
||||
|
||||
NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
|
||||
}
|
||||
|
||||
@ -328,6 +336,12 @@ MnpInitializeServiceData (
|
||||
//
|
||||
MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;
|
||||
|
||||
//
|
||||
// Make sure the protocol headers immediately following the media header
|
||||
// 4-byte aligned
|
||||
//
|
||||
MnpServiceData->PaddingSize = (4 - SnpMode->MediaHeaderSize) & 0x3;
|
||||
|
||||
//
|
||||
// Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
|
||||
//
|
||||
|
@ -521,7 +521,6 @@ MnpServiceBindingDestroyChild (
|
||||
return Status;
|
||||
}
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (MnpDriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
|
@ -82,6 +82,7 @@ typedef struct _MNP_SERVICE_DATA {
|
||||
// store a packet.
|
||||
//
|
||||
UINT32 BufferLength;
|
||||
UINT32 PaddingSize;
|
||||
NET_BUF *RxNbufCache;
|
||||
UINT8 *TxBuf;
|
||||
} MNP_SERVICE_DATA;
|
||||
|
@ -974,7 +974,10 @@ MnpReceivePacket (
|
||||
//
|
||||
// No receiver for this packet.
|
||||
//
|
||||
if (Trimmed > 0) {
|
||||
NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
|
||||
}
|
||||
|
||||
goto EXIT;
|
||||
}
|
||||
//
|
||||
|
161
MdeModulePkg/Universal/Network/Mtftp4Dxe/ComponentName.c
Normal file
161
MdeModulePkg/Universal/Network/Mtftp4Dxe/ComponentName.c
Normal file
@ -0,0 +1,161 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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 "Mtftp4Driver.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp4ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp4ComponentNameGetControllerName (
|
||||
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 gMtftp4ComponentName = {
|
||||
Mtftp4ComponentNameGetDriverName,
|
||||
Mtftp4ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
static EFI_UNICODE_STRING_TABLE mMtftp4DriverNameTable[] = {
|
||||
{
|
||||
"eng",
|
||||
L"MTFTP4 Network Service"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp4ComponentNameGetDriverName (
|
||||
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_SUCCES : 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,
|
||||
gMtftp4ComponentName.SupportedLanguages,
|
||||
mMtftp4DriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp4ComponentNameGetControllerName (
|
||||
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;
|
||||
}
|
643
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
Normal file
643
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
Normal file
@ -0,0 +1,643 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding = {
|
||||
Mtftp4DriverBindingSupported,
|
||||
Mtftp4DriverBindingStart,
|
||||
Mtftp4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete = {
|
||||
Mtftp4ServiceBindingCreateChild,
|
||||
Mtftp4ServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Mtftp4DriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The driver entry point which installs multiple protocols to the ImageHandle.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The MTFTP's image handle
|
||||
SystemTable - The system table
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The handles are successfully installed on the image. Otherwise
|
||||
some EFI_ERROR.
|
||||
|
||||
--*/
|
||||
{
|
||||
return NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gMtftp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gMtftp4ComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test whether MTFTP driver support this controller.
|
||||
|
||||
@param This The MTFTP driver binding instance
|
||||
@param Controller The controller to test
|
||||
@param RemainingDevicePath The remaining device path
|
||||
|
||||
@retval EFI_SUCCESS The controller has UDP service binding protocol
|
||||
installed, MTFTP can support it.
|
||||
@retval Others MTFTP can't support the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiUdp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Config a NULL UDP that is used to keep the connection between UDP
|
||||
and MTFTP. Just leave the Udp child unconfigured. When UDP is
|
||||
unloaded, MTFTP will be informed with DriverBinding Stop.
|
||||
|
||||
@param UdpIo The UDP port to configure
|
||||
@param Context The opaque parameter to the callback
|
||||
|
||||
@retval EFI_SUCCESS It always return EFI_SUCCESS directly.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ConfigNullUdp (
|
||||
IN UDP_IO_PORT *UdpIo,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create then initialize a MTFTP service binding instance.
|
||||
|
||||
@param Controller The controller to install the MTFTP service
|
||||
binding on
|
||||
@param Image The driver binding image of the MTFTP driver
|
||||
@param Service The variable to receive the created service
|
||||
binding instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
|
||||
@retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
|
||||
connection with UDP.
|
||||
@retval EFI_SUCCESS The service instance is created for the
|
||||
controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE Image,
|
||||
OUT MTFTP4_SERVICE **Service
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
*Service = NULL;
|
||||
MtftpSb = NetAllocatePool (sizeof (MTFTP4_SERVICE));
|
||||
|
||||
if (MtftpSb == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;
|
||||
MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;
|
||||
MtftpSb->InDestory = FALSE;
|
||||
MtftpSb->ChildrenNum = 0;
|
||||
NetListInit (&MtftpSb->Children);
|
||||
|
||||
MtftpSb->Timer = NULL;
|
||||
MtftpSb->TimerToGetMap = NULL;
|
||||
MtftpSb->Controller = Controller;
|
||||
MtftpSb->Image = Image;
|
||||
MtftpSb->ConnectUdp = NULL;
|
||||
|
||||
//
|
||||
// Create the timer and a udp to be notified when UDP is uninstalled
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Mtftp4OnTimerTick,
|
||||
MtftpSb,
|
||||
&MtftpSb->Timer
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NetFreePool (MtftpSb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the timer used to time out the procedure which is used to
|
||||
// get the default IP address.
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
NULL,
|
||||
NULL,
|
||||
&MtftpSb->TimerToGetMap
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->CloseEvent (MtftpSb->Timer);
|
||||
NetFreePool (MtftpSb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
MtftpSb->ConnectUdp = UdpIoCreatePort (Controller, Image, Mtftp4ConfigNullUdp, NULL);
|
||||
|
||||
if (MtftpSb->ConnectUdp == NULL) {
|
||||
gBS->CloseEvent (MtftpSb->TimerToGetMap);
|
||||
gBS->CloseEvent (MtftpSb->Timer);
|
||||
NetFreePool (MtftpSb);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
*Service = MtftpSb;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Release all the resource used the MTFTP service binding instance.
|
||||
|
||||
@param MtftpSb The MTFTP service binding instance.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4CleanService (
|
||||
IN MTFTP4_SERVICE *MtftpSb
|
||||
)
|
||||
{
|
||||
UdpIoFreePort (MtftpSb->ConnectUdp);
|
||||
gBS->CloseEvent (MtftpSb->TimerToGetMap);
|
||||
gBS->CloseEvent (MtftpSb->Timer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start the MTFTP driver on this controller. MTFTP driver will
|
||||
install a MTFTP SERVICE BINDING protocol on the supported
|
||||
controller, which can be used to create/destroy MTFTP children.
|
||||
|
||||
@param This The MTFTP driver binding protocol.
|
||||
@param Controller The controller to manage.
|
||||
@param RemainingDevicePath Remaining device path.
|
||||
|
||||
@retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
|
||||
started on the controller.
|
||||
@retval EFI_SUCCESS The MTFTP service binding is installed on the
|
||||
controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Directly return if driver is already running.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiMtftp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Mtftp4ServiceBinding Protocol onto Controller
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Controller,
|
||||
&gEfiMtftp4ServiceBindingProtocolGuid,
|
||||
&MtftpSb->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
Mtftp4CleanService (MtftpSb);
|
||||
NetFreePool (MtftpSb);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop the MTFTP driver on controller. The controller is a UDP
|
||||
child handle.
|
||||
|
||||
@param This The MTFTP driver binding protocol
|
||||
@param Controller The controller to stop
|
||||
@param NumberOfChildren The number of children
|
||||
@param ChildHandleBuffer The array of the child handle.
|
||||
|
||||
@retval EFI_SUCCESS The driver is stopped on the controller.
|
||||
@retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// MTFTP driver opens UDP child, So, Controller is a UDP
|
||||
// child handle. Locate the Nic handle first. Then get the
|
||||
// MTFTP private data back.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiMtftp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);
|
||||
|
||||
if (MtftpSb->InDestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
MtftpSb->InDestory = TRUE;
|
||||
|
||||
while (!NetListIsEmpty (&MtftpSb->Children)) {
|
||||
Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);
|
||||
Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
|
||||
}
|
||||
|
||||
if (MtftpSb->ChildrenNum != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiMtftp4ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Mtftp4CleanService (MtftpSb);
|
||||
NetFreePool (MtftpSb);
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
MtftpSb->InDestory = FALSE;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize a MTFTP protocol instance which is the child of MtftpSb.
|
||||
|
||||
@param MtftpSb The MTFTP service binding protocol.
|
||||
@param Instance The MTFTP instance to initialize.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4InitProtocol (
|
||||
IN MTFTP4_SERVICE *MtftpSb,
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
NetZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));
|
||||
|
||||
Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;
|
||||
NetListInit (&Instance->Link);
|
||||
CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (EFI_MTFTP4_PROTOCOL));
|
||||
Instance->State = MTFTP4_STATE_UNCONFIGED;
|
||||
Instance->Indestory = FALSE;
|
||||
Instance->Service = MtftpSb;
|
||||
|
||||
NetListInit (&Instance->Blocks);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a MTFTP child for the service binding instance, then
|
||||
install the MTFTP protocol to the ChildHandle.
|
||||
|
||||
@param This The MTFTP service binding instance.
|
||||
@param ChildHandle The Child handle to install the MTFTP protocol.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
|
||||
@retval EFI_SUCCESS The child is successfully create.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
VOID *Udp4;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = NetAllocatePool (sizeof (*Instance));
|
||||
|
||||
if (Instance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
|
||||
|
||||
Mtftp4InitProtocol (MtftpSb, Instance);
|
||||
|
||||
Instance->UnicastPort = UdpIoCreatePort (
|
||||
MtftpSb->Controller,
|
||||
MtftpSb->Image,
|
||||
Mtftp4ConfigNullUdp,
|
||||
Instance
|
||||
);
|
||||
|
||||
if (Instance->UnicastPort == NULL) {
|
||||
NetFreePool (Instance);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the MTFTP protocol onto ChildHandle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiMtftp4ProtocolGuid,
|
||||
&Instance->Mtftp4,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Instance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Udp4 protocol BY_CHILD.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
MtftpSb->ConnectUdp->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
(VOID **) &Udp4,
|
||||
gMtftp4DriverBinding.DriverBindingHandle,
|
||||
Instance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiMtftp4ProtocolGuid,
|
||||
&Instance->Mtftp4,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Add it to the parent's child list.
|
||||
//
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
NetListInsertTail (&MtftpSb->Children, &Instance->Link);
|
||||
MtftpSb->ChildrenNum++;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
UdpIoFreePort (Instance->UnicastPort);
|
||||
NetFreePool (Instance);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destory one of the service binding's child.
|
||||
|
||||
@param This The service binding instance
|
||||
@param ChildHandle The child handle to destory
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invaid.
|
||||
@retval EFI_UNSUPPORTED The child may have already been destoried.
|
||||
@retval EFI_SUCCESS The child is destoried and removed from the
|
||||
parent's child list.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_PROTOCOL *Mtftp4;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if ((This == NULL) || (ChildHandle == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the private context data structures
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiMtftp4ProtocolGuid,
|
||||
(VOID **) &Mtftp4,
|
||||
gMtftp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);
|
||||
MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Service != MtftpSb) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Instance->Indestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Instance->Indestory = TRUE;
|
||||
|
||||
//
|
||||
// Close the Udp4 protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
MtftpSb->ConnectUdp->UdpHandle,
|
||||
&gEfiUdp4ProtocolGuid,
|
||||
gMtftp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the MTFTP4 protocol first to enable a top down destruction.
|
||||
//
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiMtftp4ProtocolGuid,
|
||||
Mtftp4
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Instance->Indestory = FALSE;
|
||||
return Status;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
|
||||
UdpIoFreePort (Instance->UnicastPort);
|
||||
|
||||
NetListRemoveEntry (&Instance->Link);
|
||||
MtftpSb->ChildrenNum--;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
NetFreePool (Instance);
|
||||
return EFI_SUCCESS;
|
||||
}
|
69
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.h
Normal file
69
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.h
Normal file
@ -0,0 +1,69 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP4_DRIVER_H__
|
||||
#define __EFI_MTFTP4_DRIVER_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gMtftp4ComponentName;
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding;
|
||||
|
||||
#endif
|
68
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
Normal file
68
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
Normal file
@ -0,0 +1,68 @@
|
||||
#/** @file
|
||||
# Component name for module Mtftp4
|
||||
#
|
||||
# Copyright (c) 2007, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Mtftp4Dxe
|
||||
FILE_GUID = DC3641B8-2FA8-4ed3-BC1F-F9962A03454B
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = Mtftp4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Mtftp4Option.c
|
||||
Mtftp4Rrq.c
|
||||
Mtftp4Impl.h
|
||||
ComponentName.c
|
||||
Mtftp4Support.c
|
||||
Mtftp4Impl.c
|
||||
Mtftp4Option.h
|
||||
Mtftp4Support.h
|
||||
Mtftp4Driver.h
|
||||
Mtftp4Driver.c
|
||||
Mtftp4Wrq.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
NetLib
|
||||
UdpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiMtftp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiMtftp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
79
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.msa
Normal file
79
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.msa
Normal file
@ -0,0 +1,79 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Mtftp4Dxe</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>DC3641B8-2FA8-4ed3-BC1F-F9962A03454B</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Mtftp4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Mtftp4Dxe</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>Mtftp4Wrq.c</Filename>
|
||||
<Filename>Mtftp4Driver.c</Filename>
|
||||
<Filename>Mtftp4Driver.h</Filename>
|
||||
<Filename>Mtftp4Support.h</Filename>
|
||||
<Filename>Mtftp4Option.h</Filename>
|
||||
<Filename>Mtftp4Impl.c</Filename>
|
||||
<Filename>Mtftp4Support.c</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>Mtftp4Impl.h</Filename>
|
||||
<Filename>Mtftp4Rrq.c</Filename>
|
||||
<Filename>Mtftp4Option.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiUdp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiUdp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiMtftp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiMtftp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>Mtftp4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
892
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
Normal file
892
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
Normal file
@ -0,0 +1,892 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Impl.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Interface routine for Mtftp4
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4ReadFile (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Get the current operation parameter for the MTFTP session
|
||||
|
||||
@param This The MTFTP protocol instance
|
||||
@param ModeData The MTFTP mode data
|
||||
|
||||
@retval EFI_INVALID_PARAMETER This or ModeData is NULL
|
||||
@retval EFI_SUCCESS The operation parameter is saved in ModeData
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4GetModeData (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
OUT EFI_MTFTP4_MODE_DATA *ModeData
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if ((This == NULL) || (ModeData == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
|
||||
ModeData->ConfigData = Instance->Config;
|
||||
ModeData->SupportedOptionCount = MTFTP4_SUPPORTED_OPTIONS;
|
||||
ModeData->SupportedOptoins = mMtftp4SupportedOptions;
|
||||
ModeData->UnsupportedOptionCount = 0;
|
||||
ModeData->UnsupportedOptoins = NULL;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clean up the MTFTP session to get ready for new operation.
|
||||
|
||||
@param Instance The MTFTP session to clean up
|
||||
@param Result The result to return to the caller who initiated
|
||||
the operation.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4CleanOperation (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_STATUS Result
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
MTFTP4_BLOCK_RANGE *Block;
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
|
||||
//
|
||||
// Free various resources.
|
||||
//
|
||||
Token = Instance->Token;
|
||||
|
||||
if (Token != NULL) {
|
||||
Token->Status = Result;
|
||||
|
||||
if (Token->Event != NULL) {
|
||||
gBS->SignalEvent (Token->Event);
|
||||
}
|
||||
|
||||
Instance->Token = NULL;
|
||||
}
|
||||
|
||||
ASSERT (Instance->UnicastPort != NULL);
|
||||
UdpIoCleanPort (Instance->UnicastPort);
|
||||
|
||||
if (Instance->LastPacket != NULL) {
|
||||
NetbufFree (Instance->LastPacket);
|
||||
Instance->LastPacket = NULL;
|
||||
}
|
||||
|
||||
if (Instance->McastUdpPort != NULL) {
|
||||
UdpIoFreePort (Instance->McastUdpPort);
|
||||
Instance->McastUdpPort = NULL;
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {
|
||||
Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
|
||||
NetListRemoveEntry (Entry);
|
||||
NetFreePool (Block);
|
||||
}
|
||||
|
||||
NetZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));
|
||||
|
||||
Instance->Operation = 0;
|
||||
|
||||
Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
|
||||
Instance->LastBlock = 0;
|
||||
Instance->ServerIp = 0;
|
||||
Instance->ListeningPort = 0;
|
||||
Instance->ConnectedPort = 0;
|
||||
Instance->Gateway = 0;
|
||||
Instance->PacketToLive = 0;
|
||||
Instance->MaxRetry = 0;
|
||||
Instance->CurRetry = 0;
|
||||
Instance->Timeout = 0;
|
||||
Instance->McastIp = 0;
|
||||
Instance->McastPort = 0;
|
||||
Instance->Master = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the MTFTP session for new operation or reset the current
|
||||
operation if ConfigData is NULL.
|
||||
|
||||
@param This The MTFTP session to configure
|
||||
@param ConfigData The configure parameters
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Some of the parameter is invalid.
|
||||
@retval EFI_ACCESS_DENIED There is pending operation
|
||||
@retval EFI_SUCCESS The instance is configured for operation.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4Configure (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_CONFIG_DATA *ConfigData
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_TPL OldTpl;
|
||||
IP4_ADDR Ip;
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR Gateway;
|
||||
IP4_ADDR ServerIp;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
|
||||
|
||||
if (ConfigData == NULL) {
|
||||
//
|
||||
// Reset the operation if ConfigData is NULL
|
||||
//
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
Mtftp4CleanOperation (Instance, EFI_ABORTED);
|
||||
NetZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));
|
||||
Instance->State = MTFTP4_STATE_UNCONFIGED;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
} else {
|
||||
//
|
||||
// Configure the parameters for new operation.
|
||||
//
|
||||
NetCopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));
|
||||
|
||||
Ip = NTOHL (Ip);
|
||||
Netmask = NTOHL (Netmask);
|
||||
Gateway = NTOHL (Gateway);
|
||||
ServerIp = NTOHL (ServerIp);
|
||||
|
||||
if (!Ip4IsUnicast (ServerIp, 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!ConfigData->UseDefaultSetting &&
|
||||
((!IP4_IS_VALID_NETMASK (Netmask) || !Ip4IsUnicast (Ip, Netmask)))) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Gateway != 0) &&
|
||||
(!IP4_NET_EQUAL (Gateway, Ip, Netmask) || !Ip4IsUnicast (Gateway, Netmask))) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
Instance->Config = *ConfigData;
|
||||
Instance->State = MTFTP4_STATE_CONFIGED;
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check packet for GetInfo. GetInfo is implemented with EfiMtftp4ReadFile.
|
||||
It use Mtftp4GetInfoCheckPacket to inspect the first packet from server,
|
||||
then abort the session.
|
||||
|
||||
@param This The MTFTP4 protocol instance
|
||||
@param Token The user's token
|
||||
@param PacketLen The length of the packet
|
||||
@param Packet The received packet.
|
||||
|
||||
@retval EFI_ABORTED Abort the ReadFile operation and return.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4GetInfoCheckPacket (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token,
|
||||
IN UINT16 PacketLen,
|
||||
IN EFI_MTFTP4_PACKET *Packet
|
||||
)
|
||||
{
|
||||
MTFTP4_GETINFO_STATE *State;
|
||||
EFI_STATUS Status;
|
||||
UINT16 OpCode;
|
||||
|
||||
State = (MTFTP4_GETINFO_STATE *) Token->Context;
|
||||
OpCode = NTOHS (Packet->OpCode);
|
||||
|
||||
//
|
||||
// Set the GetInfo's return status according to the OpCode.
|
||||
//
|
||||
switch (OpCode) {
|
||||
case EFI_MTFTP4_OPCODE_ERROR:
|
||||
State->Status = EFI_TFTP_ERROR;
|
||||
break;
|
||||
|
||||
case EFI_MTFTP4_OPCODE_OACK:
|
||||
State->Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
State->Status = EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate buffer then copy the packet over. Use gBS->AllocatePool
|
||||
// in case NetAllocatePool will implements something tricky.
|
||||
//
|
||||
Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
State->Status = EFI_OUT_OF_RESOURCES;
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
*(State->PacketLen) = PacketLen;
|
||||
NetCopyMem (*(State->Packet), Packet, PacketLen);
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the information of the download from the server. It is implemented
|
||||
with EfiMtftp4ReadFile: build a token, then pass it to EfiMtftp4ReadFile.
|
||||
In its check packet callback abort the opertions.
|
||||
|
||||
@param This The MTFTP protocol instance
|
||||
@param OverrideData The MTFTP override data
|
||||
@param Filename The file to get information
|
||||
@param ModeStr The mode to use
|
||||
@param OptionCount The number of options to append
|
||||
@param OptionList The options to append
|
||||
@param PacketLength The variable to receive the packet length
|
||||
@param Packet The variable to receive the packet.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invaid
|
||||
@retval EFI_SUCCESS The information is got
|
||||
@retval Others Failed to get the information.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4GetInfo (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData, OPTIONAL
|
||||
IN UINT8 *Filename,
|
||||
IN UINT8 *ModeStr, OPTIONAL
|
||||
IN UINT8 OptionCount,
|
||||
IN EFI_MTFTP4_OPTION *OptionList,
|
||||
OUT UINT32 *PacketLength,
|
||||
OUT EFI_MTFTP4_PACKET **Packet OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_TOKEN Token;
|
||||
MTFTP4_GETINFO_STATE State;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||
|
||||
(OptionCount && (OptionList == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Packet != NULL) {
|
||||
*Packet = NULL;
|
||||
}
|
||||
|
||||
*PacketLength = 0;
|
||||
State.Packet = Packet;
|
||||
State.PacketLen = PacketLength;
|
||||
State.Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Fill in the Token to issue an synchronous ReadFile operation
|
||||
//
|
||||
Token.Status = EFI_SUCCESS;
|
||||
Token.Event = NULL;
|
||||
Token.OverrideData = OverrideData;
|
||||
Token.Filename = Filename;
|
||||
Token.ModeStr = ModeStr;
|
||||
Token.OptionCount = OptionCount;
|
||||
Token.OptionList = OptionList;
|
||||
Token.BufferSize = 0;
|
||||
Token.Buffer = NULL;
|
||||
Token.Context = &State;
|
||||
Token.CheckPacket = Mtftp4GetInfoCheckPacket;
|
||||
Token.TimeoutCallback = NULL;
|
||||
Token.PacketNeeded = NULL;
|
||||
|
||||
Status = EfiMtftp4ReadFile (This, &Token);
|
||||
|
||||
if (EFI_ABORTED == Status) {
|
||||
return State.Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the packet into an array of options. The OptionList is allocated
|
||||
by this function, and caller should free it when used.
|
||||
|
||||
@param This The MTFTP protocol instance
|
||||
@param PacketLen The length of the packet
|
||||
@param Packet The packet to parse
|
||||
@param OptionCount The size of the OptionList array allocated.
|
||||
@param OptionList The allocated option array to save the option
|
||||
addresses.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_NOT_FOUND There is no valid option in the packet
|
||||
@retval EFI_SUCCESS The packet is parsed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4ParseOptions (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN UINT32 PacketLen,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||
|
||||
(Packet == NULL) || (OptionCount == NULL)) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (*OptionCount == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether the override data is valid. It will first
|
||||
validate whether the server is a valid unicast. If a gateway
|
||||
is provided in the Override, it also check that it is a
|
||||
unicast on the connected network.
|
||||
|
||||
@param Instance The MTFTP instance
|
||||
@param Override The override data to validate.
|
||||
|
||||
@return TRUE if the override data is valid, otherwise FALSE.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
Mtftp4OverrideValid (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_OVERRIDE_DATA *Override
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_CONFIG_DATA *Config;
|
||||
IP4_ADDR Ip;
|
||||
IP4_ADDR Netmask;
|
||||
IP4_ADDR Gateway;
|
||||
|
||||
NetCopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));
|
||||
if (!Ip4IsUnicast (NTOHL (Ip), 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Config = &Instance->Config;
|
||||
|
||||
NetCopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
|
||||
Gateway = NTOHL (Gateway);
|
||||
|
||||
if (!Config->UseDefaultSetting && (Gateway != 0)) {
|
||||
NetCopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));
|
||||
|
||||
Netmask = NTOHL (Netmask);
|
||||
Ip = NTOHL (Ip);
|
||||
|
||||
if (!Ip4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Poll the UDP to get the IP4 default address, which may be retrieved
|
||||
by DHCP. The default time out value is 5 seconds. If IP has retrieved
|
||||
the default address, the UDP is reconfigured.
|
||||
|
||||
@param Instance The Mtftp instance
|
||||
@param UdpPort The UDP port to poll
|
||||
@param UdpCfgData The UDP configure data to reconfigure the UDP
|
||||
port.
|
||||
|
||||
@return TRUE if the default address is retrieved and UDP is reconfigured.
|
||||
@return Otherwise FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Mtftp4GetMapping (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UDP_IO_PORT *UdpPort,
|
||||
IN EFI_UDP4_CONFIG_DATA *UdpCfgData
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *Service;
|
||||
EFI_IP4_MODE_DATA Ip4Mode;
|
||||
EFI_UDP4_PROTOCOL *Udp;
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (Instance->Config.UseDefaultSetting);
|
||||
|
||||
Service = Instance->Service;
|
||||
Udp = UdpPort->Udp;
|
||||
|
||||
Status = gBS->SetTimer (
|
||||
Service->TimerToGetMap,
|
||||
TimerRelative,
|
||||
MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
|
||||
Udp->Poll (Udp);
|
||||
|
||||
if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&
|
||||
Ip4Mode.IsConfigured) {
|
||||
|
||||
Udp->Configure (Udp, NULL);
|
||||
return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the UDP port for unicast receiving.
|
||||
|
||||
@param UdpIo The UDP port
|
||||
@param Instance The MTFTP session
|
||||
|
||||
@retval EFI_SUCCESS The UDP port is successfully configured for the
|
||||
session to unicast receive.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4ConfigUnicastPort (
|
||||
IN UDP_IO_PORT *UdpIo,
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_CONFIG_DATA *Config;
|
||||
EFI_UDP4_CONFIG_DATA UdpConfig;
|
||||
EFI_STATUS Status;
|
||||
IP4_ADDR Ip;
|
||||
|
||||
Config = &Instance->Config;
|
||||
|
||||
UdpConfig.AcceptBroadcast = FALSE;
|
||||
UdpConfig.AcceptPromiscuous = FALSE;
|
||||
UdpConfig.AcceptAnyPort = FALSE;
|
||||
UdpConfig.AllowDuplicatePort = FALSE;
|
||||
UdpConfig.TypeOfService = 0;
|
||||
UdpConfig.TimeToLive = 64;
|
||||
UdpConfig.DoNotFragment = FALSE;
|
||||
UdpConfig.ReceiveTimeout = 0;
|
||||
UdpConfig.TransmitTimeout = 0;
|
||||
UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
|
||||
UdpConfig.StationAddress = Config->StationIp;
|
||||
UdpConfig.SubnetMask = Config->SubnetMask;
|
||||
UdpConfig.StationPort = 0;
|
||||
UdpConfig.RemotePort = 0;
|
||||
|
||||
Ip = HTONL (Instance->ServerIp);
|
||||
NetCopyMem (&UdpConfig.RemoteAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfig);
|
||||
|
||||
if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start the MTFTP session to do the operation, such as read file,
|
||||
write file, and read directory.
|
||||
|
||||
@param This The MTFTP session
|
||||
@param Token The token than encapsues the user's request.
|
||||
@param Operation The operation to do
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Some of the parameters are invalid.
|
||||
@retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
|
||||
@retval EFI_ALREADY_STARTED There is pending operation for the session.
|
||||
@retval EFI_SUCCESS The operation is successfully started.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4Start (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token,
|
||||
IN UINT16 Operation
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_OVERRIDE_DATA *Override;
|
||||
EFI_MTFTP4_CONFIG_DATA *Config;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Validate the parameters
|
||||
//
|
||||
if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||
|
||||
((Token->OptionCount != 0) && (Token->OptionList == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// User must provide at least one method to collect the data for download.
|
||||
//
|
||||
if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&
|
||||
((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// User must provide at least one method to provide the data for upload.
|
||||
//
|
||||
if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&
|
||||
((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
if (Instance->State != MTFTP4_STATE_CONFIGED) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (Instance->Operation != 0) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the Operation now to prevent the application start other
|
||||
// operations.
|
||||
//
|
||||
Instance->Operation = Operation;
|
||||
Override = Token->OverrideData;
|
||||
|
||||
if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
if (Token->OptionCount != 0) {
|
||||
Status = Mtftp4ParseOption (
|
||||
Token->OptionList,
|
||||
Token->OptionCount,
|
||||
TRUE,
|
||||
&Instance->RequestOption
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set the operation parameters from the configuration or override data.
|
||||
//
|
||||
Config = &Instance->Config;
|
||||
Instance->Token = Token;
|
||||
Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
|
||||
|
||||
NetCopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));
|
||||
Instance->ServerIp = NTOHL (Instance->ServerIp);
|
||||
|
||||
Instance->ListeningPort = Config->InitialServerPort;
|
||||
Instance->ConnectedPort = 0;
|
||||
|
||||
NetCopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));
|
||||
Instance->Gateway = NTOHL (Instance->Gateway);
|
||||
|
||||
Instance->MaxRetry = Config->TryCount;
|
||||
Instance->Timeout = Config->TimeoutValue;
|
||||
Instance->Master = TRUE;
|
||||
|
||||
if (Override != NULL) {
|
||||
NetCopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));
|
||||
NetCopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
|
||||
|
||||
Instance->ServerIp = NTOHL (Instance->ServerIp);
|
||||
Instance->Gateway = NTOHL (Instance->Gateway);
|
||||
|
||||
Instance->ListeningPort = Override->ServerPort;
|
||||
Instance->MaxRetry = Override->TryCount;
|
||||
Instance->Timeout = Override->TimeoutValue;
|
||||
}
|
||||
|
||||
if (Instance->ListeningPort == 0) {
|
||||
Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;
|
||||
}
|
||||
|
||||
if (Instance->MaxRetry == 0) {
|
||||
Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;
|
||||
}
|
||||
|
||||
if (Instance->Timeout == 0) {
|
||||
Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
//
|
||||
// Config the unicast UDP child to send initial request
|
||||
//
|
||||
Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Build and send an initial requests
|
||||
//
|
||||
if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
|
||||
Status = Mtftp4WrqStart (Instance, Operation);
|
||||
} else {
|
||||
Status = Mtftp4RrqStart (Instance, Operation);
|
||||
}
|
||||
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
//
|
||||
// Return immediately for asynchronous operation or poll the
|
||||
// instance for synchronous operation.
|
||||
//
|
||||
Token->Status = EFI_NOT_READY;
|
||||
|
||||
if (Token->Event != NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
while (Token->Status == EFI_NOT_READY) {
|
||||
This->Poll (This);
|
||||
}
|
||||
|
||||
return Token->Status;
|
||||
|
||||
ON_ERROR:
|
||||
Mtftp4CleanOperation (Instance, Status);
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read a file from the server.
|
||||
|
||||
@param This The Mtftp protocol instance.
|
||||
@param Token The user's request wrap token.
|
||||
|
||||
@retval EFI_SUCCESS The ReadFile has finished, the file has been
|
||||
downloaded if it is synchronous operation,
|
||||
otherwise it has been initated.
|
||||
@retval Others Some error happened.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4ReadFile (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Upload a file to the server.
|
||||
|
||||
@param This The MTFTP protocol session
|
||||
@param Token The user's request wrap token.
|
||||
|
||||
@retval EFI_SUCCESS The WriteFile has finished, the file has been
|
||||
uploaded if it is synchronous operation, otherwise
|
||||
it has been initated.
|
||||
@retval Others Some error happened.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4WriteFile (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read a directory from the server. The only difference
|
||||
between ReadFile and ReadDirectory is the opcode used.
|
||||
|
||||
@param This The MTFTP protocol session
|
||||
@param Token The user's request wrap token.
|
||||
|
||||
@retval EFI_SUCCESS The ReadDirectory has finished, the directory has
|
||||
been downloaded as a file if it is synchronous
|
||||
operation, otherwise it has been initated.
|
||||
@retval Others Some error happened.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4ReadDirectory (
|
||||
IN EFI_MTFTP4_PROTOCOL *This,
|
||||
IN EFI_MTFTP4_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Poll the network stack to accelerate the packet process.
|
||||
|
||||
@param This The MTFTP protocol instance.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
|
||||
@retval EFI_DEVICE_ERROR The MTFTP session has been destoried.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp4Poll (
|
||||
IN EFI_MTFTP4_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_UDP4_PROTOCOL *Udp;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
|
||||
|
||||
if (Instance->State == MTFTP4_STATE_UNCONFIGED) {
|
||||
return EFI_NOT_STARTED;
|
||||
} else if (Instance->State == MTFTP4_STATE_DESTORY) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Udp = Instance->UnicastPort->Udp;
|
||||
return Udp->Poll (Udp);
|
||||
}
|
||||
|
||||
EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {
|
||||
EfiMtftp4GetModeData,
|
||||
EfiMtftp4Configure,
|
||||
EfiMtftp4GetInfo,
|
||||
EfiMtftp4ParseOptions,
|
||||
EfiMtftp4ReadFile,
|
||||
EfiMtftp4WriteFile,
|
||||
EfiMtftp4ReadDirectory,
|
||||
EfiMtftp4Poll
|
||||
};
|
176
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h
Normal file
176
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h
Normal file
@ -0,0 +1,176 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Impl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Mtftp4 Implementation, it supports the following RFCs:
|
||||
RFC1350 - THE TFTP PROTOCOL (REVISION 2)
|
||||
RFC2090 - TFTP Multicast Option
|
||||
RFC2347 - TFTP Option Extension
|
||||
RFC2348 - TFTP Blocksize Option
|
||||
RFC2349 - TFTP Timeout Interval and Transfer Size Options
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP4_IMPL_H__
|
||||
#define __EFI_MTFTP4_IMPL_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/Udp4.h>
|
||||
#include <Protocol/Mtftp4.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UdpIoLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
|
||||
typedef struct _MTFTP4_SERVICE MTFTP4_SERVICE;
|
||||
typedef struct _MTFTP4_PROTOCOL MTFTP4_PROTOCOL;
|
||||
|
||||
#include "Mtftp4Driver.h"
|
||||
#include "Mtftp4Option.h"
|
||||
#include "Mtftp4Support.h"
|
||||
|
||||
enum {
|
||||
MTFTP4_SERVICE_SIGNATURE = EFI_SIGNATURE_32 ('T', 'F', 'T', 'P'),
|
||||
MTFTP4_PROTOCOL_SIGNATURE = EFI_SIGNATURE_32 ('t', 'f', 't', 'p'),
|
||||
|
||||
MTFTP4_DEFAULT_SERVER_PORT = 69,
|
||||
MTFTP4_DEFAULT_TIMEOUT = 3,
|
||||
MTFTP4_DEFAULT_RETRY = 5,
|
||||
MTFTP4_DEFAULT_BLKSIZE = 512,
|
||||
MTFTP4_TIME_TO_GETMAP = 5,
|
||||
|
||||
MTFTP4_STATE_UNCONFIGED = 0,
|
||||
MTFTP4_STATE_CONFIGED,
|
||||
MTFTP4_STATE_DESTORY,
|
||||
};
|
||||
|
||||
typedef struct _MTFTP4_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
|
||||
BOOLEAN InDestory;
|
||||
|
||||
UINT16 ChildrenNum;
|
||||
NET_LIST_ENTRY Children;
|
||||
|
||||
EFI_EVENT Timer; // Ticking timer for all the MTFTP clients
|
||||
EFI_EVENT TimerToGetMap;
|
||||
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
//
|
||||
// This UDP child is used to keep the connection between the UDP
|
||||
// and MTFTP, so MTFTP will be notified when UDP is uninstalled.
|
||||
//
|
||||
UDP_IO_PORT *ConnectUdp;
|
||||
};
|
||||
|
||||
typedef struct _MTFTP4_PROTOCOL {
|
||||
UINT32 Signature;
|
||||
NET_LIST_ENTRY Link;
|
||||
EFI_MTFTP4_PROTOCOL Mtftp4;
|
||||
|
||||
INTN State;
|
||||
BOOLEAN Indestory;
|
||||
|
||||
MTFTP4_SERVICE *Service;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
EFI_MTFTP4_CONFIG_DATA Config;
|
||||
|
||||
//
|
||||
// Operation parameters: token and requested options.
|
||||
//
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
MTFTP4_OPTION RequestOption;
|
||||
UINT16 Operation;
|
||||
|
||||
//
|
||||
// Blocks is a list of MTFTP4_BLOCK_RANGE which contains
|
||||
// holes in the file
|
||||
//
|
||||
UINT16 BlkSize;
|
||||
UINT16 LastBlock;
|
||||
NET_LIST_ENTRY Blocks;
|
||||
|
||||
//
|
||||
// The server's communication end point: IP and two ports. one for
|
||||
// initial request, one for its selected port.
|
||||
//
|
||||
IP4_ADDR ServerIp;
|
||||
UINT16 ListeningPort;
|
||||
UINT16 ConnectedPort;
|
||||
IP4_ADDR Gateway;
|
||||
UDP_IO_PORT *UnicastPort;
|
||||
|
||||
//
|
||||
// Timeout and retransmit status
|
||||
//
|
||||
NET_BUF *LastPacket;
|
||||
UINT32 PacketToLive;
|
||||
UINT32 CurRetry;
|
||||
UINT32 MaxRetry;
|
||||
UINT32 Timeout;
|
||||
|
||||
//
|
||||
// Parameter used by RRQ's multicast download.
|
||||
//
|
||||
IP4_ADDR McastIp;
|
||||
UINT16 McastPort;
|
||||
BOOLEAN Master;
|
||||
UDP_IO_PORT *McastUdpPort;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EFI_MTFTP4_PACKET **Packet;
|
||||
UINT32 *PacketLen;
|
||||
EFI_STATUS Status;
|
||||
} MTFTP4_GETINFO_STATE;
|
||||
|
||||
VOID
|
||||
Mtftp4CleanOperation (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_STATUS Result
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4WrqStart (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 Operation
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4RrqStart (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 Operation
|
||||
);
|
||||
|
||||
#define MTFTP4_SERVICE_FROM_THIS(a) \
|
||||
CR (a, MTFTP4_SERVICE, ServiceBinding, MTFTP4_SERVICE_SIGNATURE)
|
||||
|
||||
#define MTFTP4_PROTOCOL_FROM_THIS(a) \
|
||||
CR (a, MTFTP4_PROTOCOL, Mtftp4, MTFTP4_PROTOCOL_SIGNATURE)
|
||||
|
||||
extern EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate;
|
||||
#endif
|
542
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
Normal file
542
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
Normal file
@ -0,0 +1,542 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Mtftp4Option.c
|
||||
|
||||
Abstract:
|
||||
routines to process MTFTP4 options
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
UINT8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {
|
||||
"blksize",
|
||||
"timeout",
|
||||
"tsize",
|
||||
"multicast"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet to fill the Options array with the start
|
||||
addresses of each MTFTP option name/value pair.
|
||||
|
||||
@param Packet The packet to check
|
||||
@param PacketLen The packet's length
|
||||
@param Count The size of the Options on input. The actual
|
||||
options on output
|
||||
@param Options The option array to fill in
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet is mal-formated
|
||||
@retval EFI_BUFFER_TOO_SMALL The Options array is too small
|
||||
@retval EFI_SUCCESS The packet has been parsed into the Options array.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4FillOptions (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *Count,
|
||||
OUT EFI_MTFTP4_OPTION *Options OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT8 *Cur;
|
||||
UINT8 *Last;
|
||||
UINT8 Num;
|
||||
UINT8 *Name;
|
||||
UINT8 *Value;
|
||||
|
||||
Num = 0;
|
||||
Cur = (UINT8 *) Packet + MTFTP4_OPCODE_LEN;
|
||||
Last = (UINT8 *) Packet + PacketLen - 1;
|
||||
|
||||
//
|
||||
// process option name and value pairs. The last byte is always zero
|
||||
//
|
||||
while (Cur < Last) {
|
||||
Name = Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
if (Cur == Last) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value = ++Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
Num++;
|
||||
|
||||
if ((Options != NULL) && (Num <= *Count)) {
|
||||
Options[Num - 1].OptionStr = Name;
|
||||
Options[Num - 1].ValueStr = Value;
|
||||
}
|
||||
|
||||
Cur++;
|
||||
}
|
||||
|
||||
if ((*Count < Num) || (Options == NULL)) {
|
||||
*Count = Num;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*Count = Num;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocate and fill in a array of Mtftp options from the Packet. It
|
||||
first calls Mtftp4FillOption to get the option number, then allocate
|
||||
the array, at last, call Mtftp4FillOption again to save the options.
|
||||
|
||||
@param Packet The packet to parse
|
||||
@param PacketLen The length of the packet
|
||||
@param OptionCount The number of options in the packet
|
||||
@param OptionList The point to get the option array.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The parametera are invalid or packet isn't a
|
||||
well-formated OACK packet.
|
||||
@retval EFI_SUCCESS The option array is build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ExtractOptions (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
*OptionCount = 0;
|
||||
|
||||
if (OptionList != NULL) {
|
||||
*OptionList = NULL;
|
||||
}
|
||||
|
||||
if (NTOHS (Packet->OpCode) != EFI_MTFTP4_OPCODE_OACK) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (PacketLen == MTFTP4_OPCODE_LEN) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// The last byte must be zero to terminate the options
|
||||
//
|
||||
if (*((UINT8 *) Packet + PacketLen - 1) != 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the number of options
|
||||
//
|
||||
Status = Mtftp4FillOptions (Packet, PacketLen, OptionCount, NULL);
|
||||
|
||||
if ((Status == EFI_SUCCESS) || (Status != EFI_BUFFER_TOO_SMALL)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate memory for the options, then call Mtftp4FillOptions to
|
||||
// fill it if caller want that.
|
||||
//
|
||||
if (OptionList == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
*OptionList = NetAllocatePool (*OptionCount * sizeof (EFI_MTFTP4_OPTION));
|
||||
|
||||
if (*OptionList == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mtftp4FillOptions (Packet, PacketLen, OptionCount, *OptionList);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether two ascii strings are equel, ignore the case.
|
||||
|
||||
@param Str1 The first ascii string
|
||||
@param Str2 The second ascii string
|
||||
|
||||
@retval TRUE Two strings are equal when case is ignored.
|
||||
@retval FALSE Two string are not equal.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
NetStringEqualNoCase (
|
||||
IN UINT8 *Str1,
|
||||
IN UINT8 *Str2
|
||||
)
|
||||
{
|
||||
UINT8 Ch1;
|
||||
UINT8 Ch2;
|
||||
|
||||
ASSERT ((Str1 != NULL) && (Str2 != NULL));
|
||||
|
||||
for (; (*Str1 != '\0') && (*Str2 != '\0'); Str1++, Str2++) {
|
||||
Ch1 = *Str1;
|
||||
Ch2 = *Str2;
|
||||
|
||||
//
|
||||
// Convert them to lower case then compare two
|
||||
//
|
||||
if (('A' <= Ch1) && (Ch1 <= 'Z')) {
|
||||
Ch1 += 'a' - 'A';
|
||||
}
|
||||
|
||||
if (('A' <= Ch2) && (Ch2 <= 'Z')) {
|
||||
Ch2 += 'a' - 'A';
|
||||
}
|
||||
|
||||
if (Ch1 != Ch2) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (*Str1 == *Str2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert a string to a UINT32 number.
|
||||
|
||||
@param Str The string to convert from
|
||||
|
||||
@return The number get from the string
|
||||
|
||||
**/
|
||||
UINT32
|
||||
NetStringToU32 (
|
||||
IN UINT8 *Str
|
||||
)
|
||||
{
|
||||
UINT32 Num;
|
||||
|
||||
ASSERT (Str != NULL);
|
||||
|
||||
Num = 0;
|
||||
|
||||
for (; NET_IS_DIGIT (*Str); Str++) {
|
||||
Num = Num * 10 + (*Str - '0');
|
||||
}
|
||||
|
||||
return Num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert a string of the format "192.168.0.1" to an IP address.
|
||||
|
||||
@param Str The string representation of IP
|
||||
@param Ip The varible to get IP.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The IP string is invalid.
|
||||
@retval EFI_SUCCESS The IP is parsed into the Ip
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
NetStringToIp (
|
||||
IN UINT8 *Str,
|
||||
OUT IP4_ADDR *Ip
|
||||
)
|
||||
{
|
||||
UINT32 Byte;
|
||||
UINT32 Addr;
|
||||
UINTN Index;
|
||||
|
||||
*Ip = 0;
|
||||
Addr = 0;
|
||||
|
||||
for (Index = 0; Index < 4; Index++) {
|
||||
if (!NET_IS_DIGIT (*Str)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Byte = NetStringToU32 (Str);
|
||||
|
||||
if (Byte > 255) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Addr = (Addr << 8) | Byte;
|
||||
|
||||
//
|
||||
// Skip all the digitals and check whether the sepeator is the dot
|
||||
//
|
||||
while (NET_IS_DIGIT (*Str)) {
|
||||
Str++;
|
||||
}
|
||||
|
||||
if ((Index < 3) && (*Str != '.')) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Str++;
|
||||
}
|
||||
|
||||
*Ip = Addr;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the MTFTP multicast option.
|
||||
|
||||
@param Value The Mtftp multicast value string
|
||||
@param Option The option to save the info into.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The multicast value string is invalid.
|
||||
@retval EFI_SUCCESS The multicast value is parsed into the Option
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4ExtractMcast (
|
||||
IN UINT8 *Value,
|
||||
IN MTFTP4_OPTION *Option
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Num;
|
||||
|
||||
//
|
||||
// The multicast option is formated like "204.0.0.1,1857,1"
|
||||
// The server can also omit the ip and port, use ",,1"
|
||||
//
|
||||
if (*Value == ',') {
|
||||
Option->McastIp = 0;
|
||||
} else {
|
||||
Status = NetStringToIp (Value, &Option->McastIp);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
while (*Value && (*Value != ',')) {
|
||||
Value++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Value != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value++;
|
||||
|
||||
//
|
||||
// Convert the port setting. the server can send us a port number or
|
||||
// empty string. such as the port in ",,1"
|
||||
//
|
||||
if (*Value == ',') {
|
||||
Option->McastPort = 0;
|
||||
} else {
|
||||
Num = NetStringToU32 (Value);
|
||||
|
||||
if (Num > 65535) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Option->McastPort = (UINT16)Num;
|
||||
|
||||
while (NET_IS_DIGIT (*Value)) {
|
||||
Value++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Value != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Value++;
|
||||
|
||||
//
|
||||
// Check the master/slave setting, 1 for master, 0 for slave.
|
||||
//
|
||||
Num = NetStringToU32 (Value);
|
||||
|
||||
if ((Num != 0) && (Num != 1)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Option->Master = (BOOLEAN)(Num == 1);
|
||||
|
||||
while (NET_IS_DIGIT (*Value)) {
|
||||
Value++;
|
||||
}
|
||||
|
||||
if (*Value != '\0') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the option in Options array to MTFTP4_OPTION which program
|
||||
can access directly.
|
||||
|
||||
@param Options The option array, which contains addresses of each
|
||||
option's name/value string.
|
||||
@param Count The number of options in the Options
|
||||
@param Request Whether this is a request or OACK. The format of
|
||||
multicast is different according to this setting.
|
||||
@param MtftpOption The MTFTP4_OPTION for easy access.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The option is mal-formated
|
||||
@retval EFI_UNSUPPORTED Some option isn't supported
|
||||
@retval EFI_SUCCESS The option are OK and has been parsed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOption (
|
||||
IN EFI_MTFTP4_OPTION *Options,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN Request,
|
||||
OUT MTFTP4_OPTION *MtftpOption
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
UINT32 Value;
|
||||
EFI_MTFTP4_OPTION *This;
|
||||
|
||||
MtftpOption->Exist = 0;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
This = Options + Index;
|
||||
|
||||
if ((This->OptionStr == NULL) || (This->ValueStr == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (NetStringEqualNoCase (This->OptionStr, "blksize")) {
|
||||
//
|
||||
// block size option, valid value is between [8, 65464]
|
||||
//
|
||||
Value = NetStringToU32 (This->ValueStr);
|
||||
|
||||
if ((Value < 8) || (Value > 65464)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MtftpOption->BlkSize = (UINT16) Value;
|
||||
MtftpOption->Exist |= MTFTP4_BLKSIZE_EXIST;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "timeout")) {
|
||||
//
|
||||
// timeout option, valid value is between [1, 255]
|
||||
//
|
||||
Value = NetStringToU32 (This->ValueStr);
|
||||
|
||||
if ((Value < 1) || (Value > 255)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MtftpOption->Timeout = (UINT8) Value;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "tsize")) {
|
||||
//
|
||||
// tsize option, the biggest transfer supported is 4GB with block size option
|
||||
//
|
||||
MtftpOption->Tsize = NetStringToU32 (This->ValueStr);
|
||||
MtftpOption->Exist |= MTFTP4_TSIZE_EXIST;
|
||||
|
||||
} else if (NetStringEqualNoCase (This->OptionStr, "multicast")) {
|
||||
//
|
||||
// Multicast option, if it is a request, the value must be a zero
|
||||
// length string, otherwise, it is formated like "204.0.0.1,1857,1\0"
|
||||
//
|
||||
if (Request) {
|
||||
if (*(This->ValueStr) != '\0') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
} else {
|
||||
Status = Mtftp4ExtractMcast (This->ValueStr, MtftpOption);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
MtftpOption->Exist |= MTFTP4_MCAST_EXIST;
|
||||
|
||||
} else if (Request) {
|
||||
//
|
||||
// Ignore the unsupported option if it is a reply, and return
|
||||
// EFI_UNSUPPORTED if it's a request according to the UEFI spec.
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the options in the OACK packet to MTFTP4_OPTION which program
|
||||
can access directly.
|
||||
|
||||
@param Packet The OACK packet to parse
|
||||
@param PacketLen The length of the packet
|
||||
@param MtftpOption The MTFTP_OPTION for easy access.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The packet option is mal-formated
|
||||
@retval EFI_UNSUPPORTED Some option isn't supported
|
||||
@retval EFI_SUCCESS The option are OK and has been parsed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOptionOack (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
OUT MTFTP4_OPTION *MtftpOption
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_OPTION *OptionList;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Count;
|
||||
|
||||
MtftpOption->Exist = 0;
|
||||
|
||||
Status = Mtftp4ExtractOptions (Packet, PacketLen, &Count, &OptionList);
|
||||
|
||||
if (EFI_ERROR (Status) || (Count == 0)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp4ParseOption (OptionList, Count, FALSE, MtftpOption);
|
||||
|
||||
NetFreePool (OptionList);
|
||||
return Status;
|
||||
}
|
73
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h
Normal file
73
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h
Normal file
@ -0,0 +1,73 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Mtftp4Option.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Mtftp4 option process routines.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP4_OPTION_H__
|
||||
#define __EFI_MTFTP4_OPTION_H__
|
||||
|
||||
enum {
|
||||
MTFTP4_SUPPORTED_OPTIONS = 4,
|
||||
MTFTP4_OPCODE_LEN = 2,
|
||||
MTFTP4_ERRCODE_LEN = 2,
|
||||
MTFTP4_BLKNO_LEN = 2,
|
||||
MTFTP4_DATA_HEAD_LEN = 4,
|
||||
|
||||
MTFTP4_BLKSIZE_EXIST = 0x01,
|
||||
MTFTP4_TIMEOUT_EXIST = 0x02,
|
||||
MTFTP4_TSIZE_EXIST = 0x04,
|
||||
MTFTP4_MCAST_EXIST = 0x08,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UINT16 BlkSize;
|
||||
UINT8 Timeout;
|
||||
UINT32 Tsize;
|
||||
IP4_ADDR McastIp;
|
||||
UINT16 McastPort;
|
||||
BOOLEAN Master;
|
||||
UINT32 Exist;
|
||||
} MTFTP4_OPTION;
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4ExtractOptions (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOption (
|
||||
IN EFI_MTFTP4_OPTION *OptionList,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN Request,
|
||||
OUT MTFTP4_OPTION *Option
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4ParseOptionOack (
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
OUT MTFTP4_OPTION *Option
|
||||
);
|
||||
|
||||
extern UINT8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS];
|
||||
#endif
|
735
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
Normal file
735
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
Normal file
@ -0,0 +1,735 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Rrq.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines to process Rrq (download)
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
VOID
|
||||
Mtftp4RrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_POINTS *Points,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Start the MTFTP session to download. It will first initialize some
|
||||
of the internal states then build and send a RRQ reqeuest packet, at
|
||||
last, it will start receive for the downloading.
|
||||
|
||||
@param Instance The Mtftp session
|
||||
@param Operation The MTFTP opcode, it may be a EFI_MTFTP4_OPCODE_RRQ
|
||||
or EFI_MTFTP4_OPCODE_DIR.
|
||||
|
||||
@retval EFI_SUCCESS The mtftp download session is started.
|
||||
@retval Others Failed to start downloading.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RrqStart (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 Operation
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// The valid block number range are [1, 0xffff]. For example:
|
||||
// the client sends an RRQ request to the server, the server
|
||||
// transfers the DATA1 block. If option negoitation is ongoing,
|
||||
// the server will send back an OACK, then client will send ACK0.
|
||||
//
|
||||
Status = Mtftp4InitBlockRange (&Instance->Blocks, 1, 0xffff);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp4SendRequest (Instance);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build and send a ACK packet for the download session.
|
||||
|
||||
@param Instance The Mtftp session
|
||||
@param BlkNo The BlkNo to ack.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet
|
||||
@retval EFI_SUCCESS The ACK has been sent
|
||||
@retval Others Failed to send the ACK.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RrqSendAck (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 BlkNo
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_PACKET *Ack;
|
||||
NET_BUF *Packet;
|
||||
|
||||
Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER));
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ack = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (
|
||||
Packet,
|
||||
sizeof (EFI_MTFTP4_ACK_HEADER),
|
||||
FALSE
|
||||
);
|
||||
|
||||
Ack->Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);
|
||||
Ack->Ack.Block[0] = HTONS (BlkNo);
|
||||
|
||||
return Mtftp4SendPacket (Instance, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Deliver the received data block to the user, which can be saved
|
||||
in the user provide buffer or through the CheckPacket callback.
|
||||
|
||||
@param Instance The Mtftp session
|
||||
@param Packet The received data packet
|
||||
@param Len The packet length
|
||||
|
||||
@retval EFI_SUCCESS The data is saved successfully
|
||||
@retval EFI_ABORTED The user tells to abort by return an error through
|
||||
CheckPacket
|
||||
@retval EFI_BUFFER_TOO_SMALL The user's buffer is too small and buffer length is
|
||||
updated to the actual buffer size needed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RrqSaveBlock (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 Len
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
EFI_STATUS Status;
|
||||
UINT16 Block;
|
||||
UINT64 Start;
|
||||
UINT32 DataLen;
|
||||
|
||||
Token = Instance->Token;
|
||||
Block = NTOHS (Packet->Data.Block);
|
||||
DataLen = Len - MTFTP4_DATA_HEAD_LEN;
|
||||
|
||||
//
|
||||
// This is the last block, save the block no
|
||||
//
|
||||
if (DataLen < Instance->BlkSize) {
|
||||
Instance->LastBlock = Block;
|
||||
Mtftp4SetLastBlockNum (&Instance->Blocks, Block);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove this block number from the file hole. If Mtftp4RemoveBlockNum
|
||||
// returns EFI_NOT_FOUND, the block has been saved, don't save it again.
|
||||
//
|
||||
Status = Mtftp4RemoveBlockNum (&Instance->Blocks, Block);
|
||||
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
return EFI_SUCCESS;
|
||||
} else if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Token->CheckPacket != NULL) {
|
||||
Status = Token->CheckPacket (&Instance->Mtftp4, Token, (UINT16) Len, Packet);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
|
||||
"User aborted download"
|
||||
);
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (Token->Buffer != NULL) {
|
||||
Start = MultU64x32 (Block - 1, Instance->BlkSize);
|
||||
|
||||
if (Start + DataLen <= Token->BufferSize) {
|
||||
NetCopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen);
|
||||
|
||||
//
|
||||
// Update the file size when received the last block
|
||||
//
|
||||
if (Instance->LastBlock == Block) {
|
||||
Token->BufferSize = Start + DataLen;
|
||||
}
|
||||
|
||||
} else if (Instance->LastBlock != 0) {
|
||||
//
|
||||
// Don't save the data if the buffer is too small, return
|
||||
// EFI_BUFFER_TOO_SMALL if received the last packet. This
|
||||
// will give a accurate file length.
|
||||
//
|
||||
Token->BufferSize = Start + DataLen;
|
||||
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_DISK_FULL,
|
||||
"User provided memory block is too small"
|
||||
);
|
||||
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to process the received data packets. It will save the block
|
||||
then send back an ACK if it is active.
|
||||
|
||||
@param Instance The downloading MTFTP session
|
||||
@param Packet The packet received
|
||||
@param Len The length of the packet
|
||||
@param Multicast Whether this packet is multicast or unicast
|
||||
@param Completed Return whether the download has completed
|
||||
|
||||
@retval EFI_SUCCESS The data packet is successfully processed
|
||||
@retval EFI_ABORTED The download is aborted by the user
|
||||
@retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RrqHandleData (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
IN BOOLEAN Multicast,
|
||||
OUT BOOLEAN *Completed
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT16 BlockNum;
|
||||
INTN Expected;
|
||||
|
||||
*Completed = FALSE;
|
||||
BlockNum = NTOHS (Packet->Data.Block);
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
|
||||
ASSERT (Expected >= 0);
|
||||
|
||||
//
|
||||
// If we are active and received an unexpected packet, retransmit
|
||||
// the last ACK then restart receiving. If we are passive, save
|
||||
// the block.
|
||||
//
|
||||
if (Instance->Master && (Expected != BlockNum)) {
|
||||
Mtftp4Retransmit (Instance);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = Mtftp4RrqSaveBlock (Instance, Packet, Len);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the passive client's timer whenever it received a
|
||||
// valid data packet.
|
||||
//
|
||||
if (!Instance->Master) {
|
||||
Mtftp4SetTimeout (Instance);
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether we have received all the blocks. Send the ACK if we
|
||||
// are active (unicast client or master client for multicast download).
|
||||
// If we have received all the blocks, send an ACK even if we are passive
|
||||
// to tell the server that we are done.
|
||||
//
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
|
||||
if (Instance->Master || (Expected < 0)) {
|
||||
if (Expected < 0) {
|
||||
//
|
||||
// If we are passive client, then the just received Block maybe
|
||||
// isn't the last block. We need to send an ACK to the last block
|
||||
// to inform the server that we are done. If we are active client,
|
||||
// the Block == Instance->LastBlock.
|
||||
//
|
||||
BlockNum = Instance->LastBlock;
|
||||
*Completed = TRUE;
|
||||
|
||||
} else {
|
||||
BlockNum = (UINT16) (Expected - 1);
|
||||
}
|
||||
|
||||
Mtftp4RrqSendAck (Instance, BlockNum);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate whether the options received in the server's OACK packet is valid.
|
||||
The options are valid only if:
|
||||
1. The server doesn't include options not requested by us
|
||||
2. The server can only use smaller blksize than that is requested
|
||||
3. The server can only use the same timeout as requested
|
||||
4. The server doesn't change its multicast channel.
|
||||
|
||||
@param This The downloading Mtftp session
|
||||
@param Reply The options in the OACK packet
|
||||
@param Request The requested options
|
||||
|
||||
@return TRUE if the options in the OACK is OK, otherwise FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Mtftp4RrqOackValid (
|
||||
IN MTFTP4_PROTOCOL *This,
|
||||
IN MTFTP4_OPTION *Reply,
|
||||
IN MTFTP4_OPTION *Request
|
||||
)
|
||||
{
|
||||
|
||||
//
|
||||
// It is invalid for server to return options we don't request
|
||||
//
|
||||
if ((Reply->Exist &~Request->Exist) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Server can only specify a smaller block size to be used and
|
||||
// return the timeout matches that requested.
|
||||
//
|
||||
if (((Reply->Exist & MTFTP4_BLKSIZE_EXIST) && (Reply->BlkSize > Request->BlkSize)) ||
|
||||
((Reply->Exist & MTFTP4_TIMEOUT_EXIST) && (Reply->Timeout != Request->Timeout))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The server can send ",,master" to client to change its master
|
||||
// setting. But if it use the specific multicast channel, it can't
|
||||
// change the setting.
|
||||
//
|
||||
if ((Reply->Exist & MTFTP4_MCAST_EXIST) && (This->McastIp != 0)) {
|
||||
if ((Reply->McastIp != 0) && (Reply->McastIp != This->McastIp)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Reply->McastPort != 0) && (Reply->McastPort != This->McastPort)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure a UDP IO port to receive the multicast.
|
||||
|
||||
@param McastIo The UDP IO port to configure
|
||||
@param Context The opaque parameter to the function which is the
|
||||
MTFTP session.
|
||||
|
||||
@retval EFI_SUCCESS The udp child is successfully configured.
|
||||
@retval Others Failed to configure the UDP child.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Mtftp4RrqConfigMcastPort (
|
||||
IN UDP_IO_PORT *McastIo,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_CONFIG_DATA *Config;
|
||||
EFI_UDP4_CONFIG_DATA UdpConfig;
|
||||
EFI_IPv4_ADDRESS Group;
|
||||
EFI_STATUS Status;
|
||||
IP4_ADDR Ip;
|
||||
|
||||
Instance = (MTFTP4_PROTOCOL *) Context;
|
||||
Config = &Instance->Config;
|
||||
|
||||
UdpConfig.AcceptBroadcast = FALSE;
|
||||
UdpConfig.AcceptPromiscuous = FALSE;
|
||||
UdpConfig.AcceptAnyPort = FALSE;
|
||||
UdpConfig.AllowDuplicatePort = FALSE;
|
||||
UdpConfig.TypeOfService = 0;
|
||||
UdpConfig.TimeToLive = 64;
|
||||
UdpConfig.DoNotFragment = FALSE;
|
||||
UdpConfig.ReceiveTimeout = 0;
|
||||
UdpConfig.TransmitTimeout = 0;
|
||||
UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
|
||||
UdpConfig.StationAddress = Config->StationIp;
|
||||
UdpConfig.SubnetMask = Config->SubnetMask;
|
||||
UdpConfig.StationPort = Instance->McastPort;
|
||||
UdpConfig.RemotePort = 0;
|
||||
|
||||
Ip = HTONL (Instance->ServerIp);
|
||||
NetCopyMem (&UdpConfig.RemoteAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
Status = McastIo->Udp->Configure (McastIo->Udp, &UdpConfig);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// join the multicast group
|
||||
//
|
||||
Ip = HTONL (Instance->McastIp);
|
||||
NetCopyMem (&Group, &Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
return McastIo->Udp->Groups (McastIo->Udp, TRUE, &Group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to process the OACK. It will first validate the OACK
|
||||
packet, then update the various negotiated parameters.
|
||||
|
||||
@param Instance The download MTFTP session
|
||||
@param Packet The packet received
|
||||
@param Len The packet length
|
||||
@param Multicast Whether this packet is received as a multicast
|
||||
@param Completed Returns whether the download has completed. NOT
|
||||
used by this function.
|
||||
|
||||
@retval EFI_DEVICE_ERROR Failed to create/start a multicast UDP child
|
||||
@retval EFI_TFTP_ERROR Some error happened during the process
|
||||
@retval EFI_SUCCESS The OACK is successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RrqHandleOack (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
IN BOOLEAN Multicast,
|
||||
OUT BOOLEAN *Completed
|
||||
)
|
||||
{
|
||||
MTFTP4_OPTION Reply;
|
||||
EFI_STATUS Status;
|
||||
INTN Expected;
|
||||
|
||||
*Completed = FALSE;
|
||||
|
||||
//
|
||||
// If already started the master download, don't change the
|
||||
// setting. Master download always succeeds.
|
||||
//
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
ASSERT (Expected != -1);
|
||||
|
||||
if (Instance->Master && (Expected != 1)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse and validate the options from server
|
||||
//
|
||||
NetZeroMem (&Reply, sizeof (MTFTP4_OPTION));
|
||||
|
||||
Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);
|
||||
|
||||
if (EFI_ERROR (Status) ||
|
||||
!Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) {
|
||||
//
|
||||
// Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
|
||||
//
|
||||
if (Status != EFI_OUT_OF_RESOURCES) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
|
||||
"Mal-formated OACK packet"
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
if (Reply.Exist & MTFTP4_MCAST_EXIST) {
|
||||
|
||||
//
|
||||
// Save the multicast info. Always update the Master, only update the
|
||||
// multicast IP address, block size, timeoute at the first time. If IP
|
||||
// address is updated, create a UDP child to receive the multicast.
|
||||
//
|
||||
Instance->Master = Reply.Master;
|
||||
|
||||
if (Instance->McastIp == 0) {
|
||||
if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
|
||||
"Illegal multicast setting"
|
||||
);
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a UDP child then start receive the multicast from it.
|
||||
//
|
||||
Instance->McastIp = Reply.McastIp;
|
||||
Instance->McastPort = Reply.McastPort;
|
||||
Instance->McastUdpPort = UdpIoCreatePort (
|
||||
Instance->Service->Controller,
|
||||
Instance->Service->Image,
|
||||
Mtftp4RrqConfigMcastPort,
|
||||
Instance
|
||||
);
|
||||
|
||||
if (Instance->McastUdpPort == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION,
|
||||
"Failed to create socket to receive multicast packet"
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the parameters used.
|
||||
//
|
||||
if (Reply.BlkSize != 0) {
|
||||
Instance->BlkSize = Reply.BlkSize;
|
||||
}
|
||||
|
||||
if (Reply.Timeout != 0) {
|
||||
Instance->Timeout = Reply.Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Instance->Master = TRUE;
|
||||
|
||||
if (Reply.BlkSize != 0) {
|
||||
Instance->BlkSize = Reply.BlkSize;
|
||||
}
|
||||
|
||||
if (Reply.Timeout != 0) {
|
||||
Instance->Timeout = Reply.Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send an ACK to (Expected - 1) which is 0 for unicast download,
|
||||
// or tell the server we want to receive the Expected block.
|
||||
//
|
||||
return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The packet process callback for MTFTP download.
|
||||
|
||||
@param UdpPacket The packet received
|
||||
@param Points The local/remote access point of the packet
|
||||
@param IoStatus The status of the receiving
|
||||
@param Context Opaque parameter, which is the MTFTP session
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4RrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_POINTS *Points,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_PACKET *Packet;
|
||||
BOOLEAN Completed;
|
||||
BOOLEAN Multicast;
|
||||
EFI_STATUS Status;
|
||||
UINT16 Opcode;
|
||||
UINT32 Len;
|
||||
|
||||
Instance = (MTFTP4_PROTOCOL *) Context;
|
||||
NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Packet = NULL;
|
||||
Completed = FALSE;
|
||||
Multicast = FALSE;
|
||||
|
||||
if (EFI_ERROR (IoStatus)) {
|
||||
Status = IoStatus;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ASSERT (UdpPacket != NULL);
|
||||
|
||||
//
|
||||
// Find the port this packet is from to restart receive correctly.
|
||||
//
|
||||
Multicast = (BOOLEAN) (Points->LocalAddr == Instance->McastIp);
|
||||
|
||||
if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Client send initial request to server's listening port. Server
|
||||
// will select a UDP port to communicate with the client. The server
|
||||
// is required to use the same port as RemotePort to multicast the
|
||||
// data.
|
||||
//
|
||||
if (Points->RemotePort != Instance->ConnectedPort) {
|
||||
if (Instance->ConnectedPort != 0) {
|
||||
goto ON_EXIT;
|
||||
} else {
|
||||
Instance->ConnectedPort = Points->RemotePort;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
|
||||
//
|
||||
Len = UdpPacket->TotalSize;
|
||||
|
||||
if (UdpPacket->BlockOpNum > 1) {
|
||||
Packet = NetAllocatePool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
|
||||
|
||||
} else {
|
||||
Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
|
||||
}
|
||||
|
||||
Opcode = NTOHS (Packet->OpCode);
|
||||
|
||||
//
|
||||
// Call the user's CheckPacket if provided. Abort the transmission
|
||||
// if CheckPacket returns an EFI_ERROR code.
|
||||
//
|
||||
if ((Instance->Token->CheckPacket != NULL) &&
|
||||
((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {
|
||||
|
||||
Status = Instance->Token->CheckPacket (
|
||||
&Instance->Mtftp4,
|
||||
Instance->Token,
|
||||
(UINT16) Len,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Send an error message to the server to inform it
|
||||
//
|
||||
if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
|
||||
"User aborted the transfer"
|
||||
);
|
||||
}
|
||||
|
||||
Status = EFI_ABORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Opcode) {
|
||||
case EFI_MTFTP4_OPCODE_DATA:
|
||||
if ((Len > (UINT32) (MTFTP4_DATA_HEAD_LEN + Instance->BlkSize)) ||
|
||||
(Len < (UINT32) MTFTP4_DATA_HEAD_LEN)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = Mtftp4RrqHandleData (Instance, Packet, Len, Multicast, &Completed);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP4_OPCODE_OACK:
|
||||
if (Multicast || (Len <= MTFTP4_OPCODE_LEN)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = Mtftp4RrqHandleOack (Instance, Packet, Len, Multicast, &Completed);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP4_OPCODE_ERROR:
|
||||
Status = EFI_TFTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
|
||||
//
|
||||
// Free the resources, then if !EFI_ERROR (Status), restart the
|
||||
// receive, otherwise end the session.
|
||||
//
|
||||
if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
|
||||
NetFreePool (Packet);
|
||||
}
|
||||
|
||||
if (UdpPacket != NULL) {
|
||||
NetbufFree (UdpPacket);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status) && !Completed) {
|
||||
if (Multicast) {
|
||||
Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);
|
||||
} else {
|
||||
Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status) || Completed) {
|
||||
Mtftp4CleanOperation (Instance, Status);
|
||||
}
|
||||
}
|
591
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c
Normal file
591
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c
Normal file
@ -0,0 +1,591 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2007, 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:
|
||||
|
||||
Mtftp4Support.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Support routines for Mtftp
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Allocate a MTFTP4 block range, then init it to the
|
||||
range of [Start, End]
|
||||
|
||||
@param Start The start block number
|
||||
@param End The last block number in the range
|
||||
|
||||
@return NULL if failed to allocate memory, otherwise the created block range.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
MTFTP4_BLOCK_RANGE *
|
||||
Mtftp4AllocateRange (
|
||||
IN UINT16 Start,
|
||||
IN UINT16 End
|
||||
)
|
||||
{
|
||||
MTFTP4_BLOCK_RANGE *Range;
|
||||
|
||||
Range = NetAllocatePool (sizeof (MTFTP4_BLOCK_RANGE));
|
||||
|
||||
if (Range == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetListInit (&Range->Link);
|
||||
Range->Start = Start;
|
||||
Range->End = End;
|
||||
|
||||
return Range;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize the block range for either RRQ or WRQ. RRQ and WRQ have
|
||||
different requirements for Start and End. For example, during start
|
||||
up, WRQ initializes its whole valid block range to [0, 0xffff]. This
|
||||
is bacause the server will send us a ACK0 to inform us to start the
|
||||
upload. When the client received ACK0, it will remove 0 from the range,
|
||||
get the next block number, which is 1, then upload the BLOCK1. For RRQ
|
||||
without option negotiation, the server will directly send us the BLOCK1
|
||||
in response to the client's RRQ. When received BLOCK1, the client will
|
||||
remove it from the block range and send an ACK. It also works if there
|
||||
is option negotiation.
|
||||
|
||||
@param Head The block range head to initialize
|
||||
@param Start The Start block number.
|
||||
@param End The last block number.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for initial block range
|
||||
@retval EFI_SUCCESS The initial block range is created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4InitBlockRange (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Start,
|
||||
IN UINT16 End
|
||||
)
|
||||
{
|
||||
MTFTP4_BLOCK_RANGE *Range;
|
||||
|
||||
Range = Mtftp4AllocateRange (Start, End);
|
||||
|
||||
if (Range == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
NetListInsertTail (Head, &Range->Link);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the first valid block number on the range list.
|
||||
|
||||
@param Head The block range head
|
||||
|
||||
@return -1: if the block range is empty. Otherwise the first valid block number.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Mtftp4GetNextBlockNum (
|
||||
IN NET_LIST_ENTRY *Head
|
||||
)
|
||||
{
|
||||
MTFTP4_BLOCK_RANGE *Range;
|
||||
|
||||
if (NetListIsEmpty (Head)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Range = NET_LIST_HEAD (Head, MTFTP4_BLOCK_RANGE, Link);
|
||||
return Range->Start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the last block number of the block range list. It will
|
||||
remove all the blocks after the Last. MTFTP initialize the
|
||||
block range to the maximum possible range, such as [0, 0xffff]
|
||||
for WRQ. When it gets the last block number, it will call
|
||||
this function to set the last block number.
|
||||
|
||||
@param Head The block range list
|
||||
@param Last The last block number
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4SetLastBlockNum (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Last
|
||||
)
|
||||
{
|
||||
MTFTP4_BLOCK_RANGE *Range;
|
||||
|
||||
//
|
||||
// Iterate from the tail to head to remove the block number
|
||||
// after the last.
|
||||
//
|
||||
while (!NetListIsEmpty (Head)) {
|
||||
Range = NET_LIST_TAIL (Head, MTFTP4_BLOCK_RANGE, Link);
|
||||
|
||||
if (Range->Start > Last) {
|
||||
NetListRemoveEntry (&Range->Link);
|
||||
NetFreePool (Range);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Range->End > Last) {
|
||||
Range->End = Last;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove the block number from the block range list.
|
||||
|
||||
@param Head The block range list to remove from
|
||||
@param Num The block number to remove
|
||||
|
||||
@retval EFI_NOT_FOUND The block number isn't in the block range list
|
||||
@retval EFI_SUCCESS The block number has been removed from the list
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4RemoveBlockNum (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Num
|
||||
)
|
||||
{
|
||||
MTFTP4_BLOCK_RANGE *Range;
|
||||
MTFTP4_BLOCK_RANGE *NewRange;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
|
||||
NET_LIST_FOR_EACH (Entry, Head) {
|
||||
|
||||
//
|
||||
// Each block represents a hole [Start, End] in the file,
|
||||
// skip to the first range with End >= Num
|
||||
//
|
||||
Range = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
|
||||
|
||||
if (Range->End < Num) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// There are three different cases for Start
|
||||
// 1. (Start > Num) && (End >= Num):
|
||||
// because all the holes before this one has the condition of
|
||||
// End < Num, so this block number has been removed.
|
||||
//
|
||||
// 2. (Start == Num) && (End >= Num):
|
||||
// Need to increase the Start by one, and if End == Num, this
|
||||
// hole has been removed completely, remove it.
|
||||
//
|
||||
// 3. (Start < Num) && (End >= Num):
|
||||
// if End == Num, only need to decrease the End by one because
|
||||
// we have (Start < Num) && (Num == End), so (Start <= End - 1).
|
||||
// if (End > Num), the hold is splited into two holes, with
|
||||
// [Start, Num - 1] and [Num + 1, End].
|
||||
//
|
||||
if (Range->Start > Num) {
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
} else if (Range->Start == Num) {
|
||||
Range->Start++;
|
||||
|
||||
if (Range->Start > Range->End) {
|
||||
NetListRemoveEntry (&Range->Link);
|
||||
NetFreePool (Range);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
if (Range->End == Num) {
|
||||
Range->End--;
|
||||
} else {
|
||||
NewRange = Mtftp4AllocateRange (Num + 1, (UINT16) Range->End);
|
||||
|
||||
if (NewRange == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Range->End = Num - 1;
|
||||
NetListInsertAfter (&Range->Link, &NewRange->Link);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build then transmit the request packet for the MTFTP session.
|
||||
|
||||
@param Instance The Mtftp session
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the request
|
||||
@retval EFI_SUCCESS The request is built and sent
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4SendRequest (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_PACKET *Packet;
|
||||
EFI_MTFTP4_OPTION *Options;
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
NET_BUF *Nbuf;
|
||||
UINT8 *Mode;
|
||||
UINT8 *Cur;
|
||||
UINT32 Len;
|
||||
UINTN Index;
|
||||
|
||||
Token = Instance->Token;
|
||||
Options = Token->OptionList;
|
||||
Mode = Instance->Token->ModeStr;
|
||||
|
||||
if (Mode == NULL) {
|
||||
Mode = "octet";
|
||||
}
|
||||
|
||||
//
|
||||
// Compute the packet length
|
||||
//
|
||||
Len = (UINT32) (AsciiStrLen (Token->Filename) + AsciiStrLen (Mode) + 4);
|
||||
|
||||
for (Index = 0; Index < Token->OptionCount; Index++) {
|
||||
Len += (UINT32) (AsciiStrLen (Options[Index].OptionStr) +
|
||||
AsciiStrLen (Options[Index].ValueStr) + 2);
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a packet then copy the data over
|
||||
//
|
||||
if ((Nbuf = NetbufAlloc (Len)) == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Nbuf, Len, FALSE);
|
||||
Packet->OpCode = HTONS (Instance->Operation);
|
||||
Cur = Packet->Rrq.Filename;
|
||||
Cur = AsciiStrCpy (Cur, Token->Filename);
|
||||
Cur = AsciiStrCpy (Cur, Mode);
|
||||
|
||||
for (Index = 0; Index < Token->OptionCount; ++Index) {
|
||||
Cur = AsciiStrCpy (Cur, Options[Index].OptionStr);
|
||||
Cur = AsciiStrCpy (Cur, Options[Index].ValueStr);
|
||||
}
|
||||
|
||||
return Mtftp4SendPacket (Instance, Nbuf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build then send an error message
|
||||
|
||||
@param Instance The MTFTP session
|
||||
@param ErrInfo The error code and message
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the error packet
|
||||
@retval EFI_SUCCESS The error packet is transmitted.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4SendError (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 ErrCode,
|
||||
IN UINT8* ErrInfo
|
||||
)
|
||||
{
|
||||
NET_BUF *Packet;
|
||||
EFI_MTFTP4_PACKET *TftpError;
|
||||
UINT32 Len;
|
||||
|
||||
Len = (UINT32) (AsciiStrLen (ErrInfo) + sizeof (EFI_MTFTP4_ERROR_HEADER));
|
||||
Packet = NetbufAlloc (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
TftpError = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Packet, Len, FALSE);
|
||||
TftpError->OpCode = HTONS (EFI_MTFTP4_OPCODE_ERROR);
|
||||
TftpError->Error.ErrorCode = HTONS (ErrCode);
|
||||
|
||||
AsciiStrCpy (TftpError->Error.ErrorMessage, ErrInfo);
|
||||
|
||||
return Mtftp4SendPacket (Instance, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The callback function called when the packet is transmitted.
|
||||
It simply frees the packet.
|
||||
|
||||
@param Packet The transmitted (or failed to) packet
|
||||
@param Points The local and remote UDP access point
|
||||
@param IoStatus The result of the transmission
|
||||
@param Context Opaque parameter to the callback
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Mtftp4OnPacketSent (
|
||||
NET_BUF *Packet,
|
||||
UDP_POINTS *Points,
|
||||
EFI_STATUS IoStatus,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
NetbufFree (Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the timeout for the instance. User a longer time for
|
||||
passive instances.
|
||||
|
||||
@param Instance The Mtftp session to set time out
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4SetTimeout (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
if (Instance->Master) {
|
||||
Instance->PacketToLive = Instance->Timeout;
|
||||
} else {
|
||||
Instance->PacketToLive = Instance->Timeout * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send the packet for the instance. It will first save a reference to
|
||||
the packet for later retransmission. then determine the destination
|
||||
port, listen port for requests, and connected port for others. At last,
|
||||
send the packet out.
|
||||
|
||||
@param Instance The Mtftp instance
|
||||
@param Packet The packet to send
|
||||
|
||||
@retval EFI_SUCCESS The packet is sent out
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4SendPacket (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN NET_BUF *Packet
|
||||
)
|
||||
{
|
||||
UDP_POINTS UdpPoint;
|
||||
EFI_STATUS Status;
|
||||
UINT16 OpCode;
|
||||
|
||||
//
|
||||
// Save the packet for retransmission
|
||||
//
|
||||
if (Instance->LastPacket != NULL) {
|
||||
NetbufFree (Instance->LastPacket);
|
||||
}
|
||||
|
||||
Instance->LastPacket = Packet;
|
||||
|
||||
Instance->CurRetry = 0;
|
||||
Mtftp4SetTimeout (Instance);
|
||||
|
||||
UdpPoint.LocalAddr = 0;
|
||||
UdpPoint.LocalPort = 0;
|
||||
UdpPoint.RemoteAddr = Instance->ServerIp;
|
||||
|
||||
//
|
||||
// Send the requests to the listening port, other packets
|
||||
// to the connected port
|
||||
//
|
||||
OpCode = NTOHS (*((UINT16 *) NetbufGetByte (Packet, 0, NULL)));
|
||||
|
||||
if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || (OpCode == EFI_MTFTP4_OPCODE_DIR) ||
|
||||
(OpCode == EFI_MTFTP4_OPCODE_WRQ)) {
|
||||
UdpPoint.RemotePort = Instance->ListeningPort;
|
||||
} else {
|
||||
UdpPoint.RemotePort = Instance->ConnectedPort;
|
||||
}
|
||||
|
||||
NET_GET_REF (Packet);
|
||||
|
||||
Status = UdpIoSendDatagram (
|
||||
Instance->UnicastPort,
|
||||
Packet,
|
||||
&UdpPoint,
|
||||
Instance->Gateway,
|
||||
Mtftp4OnPacketSent,
|
||||
Instance
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NET_PUT_REF (Packet);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Retransmit the last packet for the instance
|
||||
|
||||
@param Instance The Mtftp instance
|
||||
|
||||
@retval EFI_SUCCESS The last packet is retransmitted.
|
||||
@retval Others Failed to retransmit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4Retransmit (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
)
|
||||
{
|
||||
UDP_POINTS UdpPoint;
|
||||
EFI_STATUS Status;
|
||||
UINT16 OpCode;
|
||||
|
||||
ASSERT (Instance->LastPacket != NULL);
|
||||
|
||||
UdpPoint.LocalAddr = 0;
|
||||
UdpPoint.LocalPort = 0;
|
||||
UdpPoint.RemoteAddr = Instance->ServerIp;
|
||||
|
||||
//
|
||||
// Set the requests to the listening port, other packets to the connected port
|
||||
//
|
||||
OpCode = NTOHS (*(UINT16 *) NetbufGetByte (Instance->LastPacket, 0, NULL));
|
||||
|
||||
if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || (OpCode == EFI_MTFTP4_OPCODE_DIR) ||
|
||||
(OpCode == EFI_MTFTP4_OPCODE_WRQ)) {
|
||||
UdpPoint.RemotePort = Instance->ListeningPort;
|
||||
} else {
|
||||
UdpPoint.RemotePort = Instance->ConnectedPort;
|
||||
}
|
||||
|
||||
NET_GET_REF (Instance->LastPacket);
|
||||
|
||||
Status = UdpIoSendDatagram (
|
||||
Instance->UnicastPort,
|
||||
Instance->LastPacket,
|
||||
&UdpPoint,
|
||||
Instance->Gateway,
|
||||
Mtftp4OnPacketSent,
|
||||
Instance
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
NET_PUT_REF (Instance->LastPacket);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The timer ticking function for the Mtftp service instance.
|
||||
|
||||
@param Event The ticking event
|
||||
@param Context The Mtftp service instance
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp4OnTimerTick (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP4_SERVICE *MtftpSb;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
|
||||
MtftpSb = (MTFTP4_SERVICE *) Context;
|
||||
|
||||
//
|
||||
// Iterate through all the children of the Mtftp service instance. Time
|
||||
// out the packet. If maximum retries reached, clean the session up.
|
||||
//
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {
|
||||
Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);
|
||||
|
||||
if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Call the user's time out handler
|
||||
//
|
||||
Token = Instance->Token;
|
||||
|
||||
if ((Token->TimeoutCallback != NULL) &&
|
||||
EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token))) {
|
||||
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
|
||||
"User aborted the transfer in time out"
|
||||
);
|
||||
|
||||
Mtftp4CleanOperation (Instance, EFI_ABORTED);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Retransmit the packet if haven't reach the maxmium retry count,
|
||||
// otherwise exit the transfer.
|
||||
//
|
||||
if (++Instance->CurRetry < Instance->MaxRetry) {
|
||||
Mtftp4Retransmit (Instance);
|
||||
Mtftp4SetTimeout (Instance);
|
||||
} else {
|
||||
Mtftp4CleanOperation (Instance, EFI_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
96
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h
Normal file
96
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h
Normal file
@ -0,0 +1,96 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Mtftp4Support.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Support routines for MTFTP
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP4_SUPPORT_H__
|
||||
#define __EFI_MTFTP4_SUPPORT_H__
|
||||
|
||||
//
|
||||
// The structure representing a range of block numbers, [Start, End].
|
||||
// It is used to remember the holes in the MTFTP block space. If all
|
||||
// the holes are filled in, then the download or upload has completed.
|
||||
//
|
||||
typedef struct {
|
||||
NET_LIST_ENTRY Link;
|
||||
INTN Start;
|
||||
INTN End;
|
||||
} MTFTP4_BLOCK_RANGE;
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4InitBlockRange (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Start,
|
||||
IN UINT16 End
|
||||
);
|
||||
|
||||
INTN
|
||||
Mtftp4GetNextBlockNum (
|
||||
IN NET_LIST_ENTRY *Head
|
||||
);
|
||||
|
||||
VOID
|
||||
Mtftp4SetLastBlockNum (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Last
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4RemoveBlockNum (
|
||||
IN NET_LIST_ENTRY *Head,
|
||||
IN UINT16 Num
|
||||
);
|
||||
|
||||
VOID
|
||||
Mtftp4SetTimeout (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4SendPacket (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4SendRequest (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4SendError (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 ErrCode,
|
||||
IN UINT8* ErrInfo
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Mtftp4Retransmit (
|
||||
IN MTFTP4_PROTOCOL *Instance
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp4OnTimerTick (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
#endif
|
522
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c
Normal file
522
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c
Normal file
@ -0,0 +1,522 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
|
||||
Mtftp4Wrq.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines to process Wrq (upload)
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp4Impl.h"
|
||||
|
||||
VOID
|
||||
Mtftp4WrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_POINTS *Points,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Start the MTFTP session for pload. It will first init some states,
|
||||
then send the WRQ request packet, and start receiving the packet.
|
||||
|
||||
@param Instance The MTFTP session
|
||||
@param Operation Redundant parameter, which is always
|
||||
EFI_MTFTP4_OPCODE_WRQ here.
|
||||
|
||||
@retval EFI_SUCCESS The upload process has been started.
|
||||
@retval Others Failed to start the upload.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4WrqStart (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 Operation
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// The valid block number range are [0, 0xffff]. For example:
|
||||
// the client sends an WRQ request to the server, the server
|
||||
// ACK with an ACK0 to let client start transfer the first
|
||||
// packet.
|
||||
//
|
||||
Status = Mtftp4InitBlockRange (&Instance->Blocks, 0, 0xffff);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp4SendRequest (Instance);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build then send a MTFTP data packet for the MTFTP upload session.
|
||||
|
||||
@param Instance The MTFTP upload session
|
||||
@param BlockNum The block number to send
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to build the packet
|
||||
@retval EFI_ABORTED The consumer of this child directs to abort the
|
||||
transmission by return an error through
|
||||
PacketNeeded
|
||||
@retval EFI_SUCCESS The data is sent.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4WrqSendBlock (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN UINT16 BlockNum
|
||||
)
|
||||
{
|
||||
EFI_MTFTP4_PACKET *Packet;
|
||||
EFI_MTFTP4_TOKEN *Token;
|
||||
NET_BUF *UdpPacket;
|
||||
EFI_STATUS Status;
|
||||
UINT16 DataLen;
|
||||
UINT8 *DataBuf;
|
||||
UINT64 Start;
|
||||
|
||||
//
|
||||
// Allocate a buffer to hold the user data
|
||||
//
|
||||
UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP4_DATA_HEAD_LEN);
|
||||
|
||||
if (UdpPacket == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Packet = (EFI_MTFTP4_PACKET *)NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);
|
||||
|
||||
Packet->Data.OpCode = HTONS (EFI_MTFTP4_OPCODE_DATA);
|
||||
Packet->Data.Block = HTONS (BlockNum);
|
||||
|
||||
//
|
||||
// Read the block from either the buffer or PacketNeeded callback
|
||||
//
|
||||
Token = Instance->Token;
|
||||
DataLen = Instance->BlkSize;
|
||||
|
||||
if (Token->Buffer != NULL) {
|
||||
Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
|
||||
|
||||
if (Token->BufferSize < Start + Instance->BlkSize) {
|
||||
DataLen = (UINT16) (Token->BufferSize - Start);
|
||||
Instance->LastBlock = BlockNum;
|
||||
Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
|
||||
}
|
||||
|
||||
if (DataLen > 0) {
|
||||
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
|
||||
NetCopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Get data from PacketNeeded
|
||||
//
|
||||
DataBuf = NULL;
|
||||
Status = Token->PacketNeeded (&Instance->Mtftp4, Token, &DataLen, &DataBuf);
|
||||
|
||||
if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
|
||||
if (DataBuf != NULL) {
|
||||
gBS->FreePool (DataBuf);
|
||||
}
|
||||
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
|
||||
"User aborted the transfer"
|
||||
);
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
if (DataLen < Instance->BlkSize) {
|
||||
Instance->LastBlock = BlockNum;
|
||||
Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
|
||||
}
|
||||
|
||||
if (DataLen > 0) {
|
||||
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
|
||||
NetCopyMem (Packet->Data.Data, DataBuf, DataLen);
|
||||
gBS->FreePool (DataBuf);
|
||||
}
|
||||
}
|
||||
|
||||
return Mtftp4SendPacket (Instance, UdpPacket);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to handle received ACK packet. If the ACK number matches the
|
||||
expected block number, and there are more data pending, send the next
|
||||
block. Otherwise tell the caller that we are done.
|
||||
|
||||
@param Instance The MTFTP upload session
|
||||
@param Packet The MTFTP packet received
|
||||
@param Len The packet length
|
||||
@param Completed Return whether the upload has finished.
|
||||
|
||||
@retval EFI_SUCCESS The ACK is successfully processed.
|
||||
@retval EFI_TFTP_ERROR The block number loops back.
|
||||
@retval Others Failed to transmit the next data packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4WrqHandleAck (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT BOOLEAN *Completed
|
||||
)
|
||||
{
|
||||
UINT16 AckNum;
|
||||
INTN Expected;
|
||||
|
||||
*Completed = FALSE;
|
||||
AckNum = NTOHS (Packet->Ack.Block[0]);
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
|
||||
ASSERT (Expected >= 0);
|
||||
|
||||
//
|
||||
// Get an unwanted ACK, return EFI_SUCCESS to let Mtftp4WrqInput
|
||||
// restart receive.
|
||||
//
|
||||
if (Expected != AckNum) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the acked block number, if this is the last block number,
|
||||
// tell the Mtftp4WrqInput to finish the transfer. This is the last
|
||||
// block number if the block range are empty..
|
||||
//
|
||||
Mtftp4RemoveBlockNum (&Instance->Blocks, AckNum);
|
||||
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
|
||||
if (Expected < 0) {
|
||||
//
|
||||
// The block range is empty. It may either because the the last
|
||||
// block has been ACKed, or the sequence number just looped back,
|
||||
// that is, there is more than 0xffff blocks.
|
||||
//
|
||||
if (Instance->LastBlock == AckNum) {
|
||||
ASSERT (Instance->LastBlock >= 1);
|
||||
*Completed = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
|
||||
"Block number rolls back, not supported, try blksize option"
|
||||
);
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return Mtftp4WrqSendBlock (Instance, (UINT16) Expected);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether the received OACK is valid. The OACK is valid
|
||||
only if:
|
||||
1. It only include options requested by us
|
||||
2. It can only include a smaller block size
|
||||
3. It can't change the proposed time out value.
|
||||
4. Other requirements of the individal MTFTP options as required.s
|
||||
|
||||
@param Reply The options included in the OACK
|
||||
@param Request The options we requested
|
||||
|
||||
@return TRUE if the options included in OACK is valid, otherwise FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Mtftp4WrqOackValid (
|
||||
IN MTFTP4_OPTION *Reply,
|
||||
IN MTFTP4_OPTION *Request
|
||||
)
|
||||
{
|
||||
//
|
||||
// It is invalid for server to return options we don't request
|
||||
//
|
||||
if ((Reply->Exist &~Request->Exist) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Server can only specify a smaller block size to be used and
|
||||
// return the timeout matches that requested.
|
||||
//
|
||||
if (((Reply->Exist & MTFTP4_BLKSIZE_EXIST) && (Reply->BlkSize > Request->BlkSize)) ||
|
||||
((Reply->Exist & MTFTP4_TIMEOUT_EXIST) && (Reply->Timeout != Request->Timeout))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to handle the MTFTP OACK packet. It parses the packet's
|
||||
options, and update the internal states of the session
|
||||
|
||||
@param Instance The MTFTP session
|
||||
@param Packet The received OACK packet
|
||||
@param Len The length of the packet
|
||||
@param Completed Whether the transmisson has completed. NOT used by
|
||||
this function.
|
||||
|
||||
@retval EFI_SUCCESS The OACK process is OK
|
||||
@retval EFI_TFTP_ERROR Some error occured, and the session reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp4WrqHandleOack (
|
||||
IN MTFTP4_PROTOCOL *Instance,
|
||||
IN EFI_MTFTP4_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT BOOLEAN *Completed
|
||||
)
|
||||
{
|
||||
MTFTP4_OPTION Reply;
|
||||
EFI_MTFTP4_PACKET Bogus;
|
||||
EFI_STATUS Status;
|
||||
INTN Expected;
|
||||
|
||||
*Completed = FALSE;
|
||||
|
||||
//
|
||||
// Ignore the OACK if already started the upload
|
||||
//
|
||||
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
|
||||
|
||||
if (Expected != 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse and validate the options from server
|
||||
//
|
||||
NetZeroMem (&Reply, sizeof (MTFTP4_OPTION));
|
||||
Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);
|
||||
|
||||
if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) {
|
||||
//
|
||||
// Don't send a MTFTP error packet when out of resource, it can
|
||||
// only make it worse.
|
||||
//
|
||||
if (Status != EFI_OUT_OF_RESOURCES) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
|
||||
"Mal-formated OACK packet"
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
if (Reply.BlkSize != 0) {
|
||||
Instance->BlkSize = Reply.BlkSize;
|
||||
}
|
||||
|
||||
if (Reply.Timeout != 0) {
|
||||
Instance->Timeout = Reply.Timeout;
|
||||
}
|
||||
|
||||
//
|
||||
// Build a bogus ACK0 packet then pass it to the Mtftp4WrqHandleAck,
|
||||
// which will start the transmission of the first data block.
|
||||
//
|
||||
Bogus.Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);
|
||||
Bogus.Ack.Block[0] = 0;
|
||||
|
||||
return Mtftp4WrqHandleAck (Instance, &Bogus, sizeof (EFI_MTFTP4_ACK_HEADER), Completed);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The input process routine for MTFTP upload.
|
||||
|
||||
@param UdpPacket The received MTFTP packet.
|
||||
@param Points The local/remote access point
|
||||
@param IoStatus The result of the packet receiving
|
||||
@param Context Opaque parameter for the callback, which is the
|
||||
MTFTP session.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp4WrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_POINTS *Points,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP4_PROTOCOL *Instance;
|
||||
EFI_MTFTP4_PACKET *Packet;
|
||||
BOOLEAN Completed;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Len;
|
||||
UINT16 Opcode;
|
||||
|
||||
Instance = (MTFTP4_PROTOCOL *) Context;
|
||||
NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);
|
||||
|
||||
Completed = FALSE;
|
||||
Packet = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (EFI_ERROR (IoStatus)) {
|
||||
Status = IoStatus;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ASSERT (UdpPacket != NULL);
|
||||
|
||||
if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Client send initial request to server's listening port. Server
|
||||
// will select a UDP port to communicate with the client.
|
||||
//
|
||||
if (Points->RemotePort != Instance->ConnectedPort) {
|
||||
if (Instance->ConnectedPort != 0) {
|
||||
goto ON_EXIT;
|
||||
} else {
|
||||
Instance->ConnectedPort = Points->RemotePort;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
|
||||
//
|
||||
Len = UdpPacket->TotalSize;
|
||||
|
||||
if (UdpPacket->BlockOpNum > 1) {
|
||||
Packet = NetAllocatePool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
|
||||
|
||||
} else {
|
||||
Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
|
||||
}
|
||||
|
||||
Opcode = NTOHS (Packet->OpCode);
|
||||
|
||||
//
|
||||
// Call the user's CheckPacket if provided. Abort the transmission
|
||||
// if CheckPacket returns an EFI_ERROR code.
|
||||
//
|
||||
if ((Instance->Token->CheckPacket != NULL) &&
|
||||
((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {
|
||||
|
||||
Status = Instance->Token->CheckPacket (
|
||||
&Instance->Mtftp4,
|
||||
Instance->Token,
|
||||
(UINT16) Len,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Send an error message to the server to inform it
|
||||
//
|
||||
if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {
|
||||
Mtftp4SendError (
|
||||
Instance,
|
||||
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
|
||||
"User aborted the transfer"
|
||||
);
|
||||
}
|
||||
|
||||
Status = EFI_ABORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Opcode) {
|
||||
case EFI_MTFTP4_OPCODE_ACK:
|
||||
if (Len != MTFTP4_OPCODE_LEN + MTFTP4_BLKNO_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = Mtftp4WrqHandleAck (Instance, Packet, Len, &Completed);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP4_OPCODE_OACK:
|
||||
if (Len <= MTFTP4_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = Mtftp4WrqHandleOack (Instance, Packet, Len, &Completed);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP4_OPCODE_ERROR:
|
||||
Status = EFI_TFTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
//
|
||||
// Free the resources, then if !EFI_ERROR (Status) and not completed,
|
||||
// restart the receive, otherwise end the session.
|
||||
//
|
||||
if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
|
||||
NetFreePool (Packet);
|
||||
}
|
||||
|
||||
if (UdpPacket != NULL) {
|
||||
NetbufFree (UdpPacket);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status) && !Completed) {
|
||||
Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Status may have been updated by UdpIoRecvDatagram
|
||||
//
|
||||
if (EFI_ERROR (Status) || Completed) {
|
||||
Mtftp4CleanOperation (Instance, Status);
|
||||
}
|
||||
}
|
2401
MdeModulePkg/Universal/Network/PxeBcDxe/Bc.c
Normal file
2401
MdeModulePkg/Universal/Network/PxeBcDxe/Bc.c
Normal file
File diff suppressed because it is too large
Load Diff
564
MdeModulePkg/Universal/Network/PxeBcDxe/Bc.h
Normal file
564
MdeModulePkg/Universal/Network/PxeBcDxe/Bc.h
Normal file
@ -0,0 +1,564 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Guid/SmBios.h>
|
||||
#include <Protocol/Bis.h>
|
||||
#include <Protocol/PxeBaseCode.h>
|
||||
#include <Protocol/PxeBaseCodeCallBack.h>
|
||||
#include <Protocol/NetworkInterfaceIdentifier.h>
|
||||
#include <Protocol/SimpleNetwork.h>
|
||||
#include <Protocol/LoadFile.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
#include <Protocol/Tcp.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#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 'pxed'
|
||||
|
||||
//
|
||||
// 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_TCP_PROTOCOL Tcp;
|
||||
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 LOADFILE_DEVICE_SIGNATURE 'pxel'
|
||||
|
||||
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_BASE_CODE_DEV_FROM_TCP(a) CR (a, PXE_BASECODE_DEVICE, Tcp, 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_COMPONENT_NAME_PROTOCOL gPxeBcComponentName;
|
||||
|
||||
//
|
||||
// //////////////////////////////////////////////////////////
|
||||
//
|
||||
// prototypes
|
||||
//
|
||||
|
||||
/**
|
||||
Initialize the base code drivers and install the driver binding
|
||||
|
||||
Standard EFI Image Entry
|
||||
|
||||
@retval EFI_SUCCESS This driver was successfully bound
|
||||
|
||||
**/
|
||||
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
|
||||
BcTcpWrite (
|
||||
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
|
||||
IN UINT16 OpFlags,
|
||||
IN UINT16 *UrgentPointer,
|
||||
IN UINT32 *SequenceNumber,
|
||||
IN UINT32 *AckNumber,
|
||||
IN UINT16 *HlenResCode,
|
||||
IN UINT16 *Window,
|
||||
IN EFI_IP_ADDRESS *DestIp,
|
||||
IN EFI_PXE_BASE_CODE_TCP_PORT *DestPort,
|
||||
IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL
|
||||
IN EFI_IP_ADDRESS *SrcIp, OPTIONAL
|
||||
IN OUT EFI_PXE_BASE_CODE_TCP_PORT *SrcPort, OPTIONAL
|
||||
IN UINTN *HeaderSize, OPTIONAL
|
||||
IN VOID *HeaderPtr, OPTIONAL
|
||||
IN UINTN *BufferSize,
|
||||
IN VOID *BufferPtr
|
||||
)
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BcTcpRead (
|
||||
IN EFI_PXE_BASE_CODE_PROTOCOL *This,
|
||||
IN UINT16 OpFlags,
|
||||
IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL
|
||||
IN OUT EFI_PXE_BASE_CODE_TCP_PORT *DestPort, OPTIONAL
|
||||
IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL
|
||||
IN OUT EFI_PXE_BASE_CODE_TCP_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
|
||||
)
|
||||
;
|
||||
|
||||
#ifdef EFI_SIZE_REDUCTION_APPLIED
|
||||
#define COMPONENT_NAME_CODE(code)
|
||||
#define COMPONENT_NAME NULL
|
||||
#else
|
||||
#define COMPONENT_NAME_CODE(code) code
|
||||
#define COMPONENT_NAME &gPxeBcComponentName
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// 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 */
|
160
MdeModulePkg/Universal/Network/PxeBcDxe/ComponentName.c
Normal file
160
MdeModulePkg/Universal/Network/PxeBcDxe/ComponentName.c
Normal file
@ -0,0 +1,160 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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",
|
||||
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;
|
||||
}
|
632
MdeModulePkg/Universal/Network/PxeBcDxe/Dhcp.h
Normal file
632
MdeModulePkg/Universal/Network/PxeBcDxe/Dhcp.h
Normal file
@ -0,0 +1,632 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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 PXE_DISABLE_BROADCAST_DISCOVERY (1 << 0)
|
||||
#define PXE_DISABLE_MULTICAST_DISCOVERY (1 << 1)
|
||||
#define PXE_ACCEPT_ONLY_PXE_BOOT_SERVERS (1 << 2)
|
||||
#define PXE_DO_NOT_PROMPT (1 << 3)
|
||||
#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 */
|
46
MdeModulePkg/Universal/Network/PxeBcDxe/Ebc/PxeArch.c
Normal file
46
MdeModulePkg/Universal/Network/PxeBcDxe/Ebc/PxeArch.c
Normal file
@ -0,0 +1,46 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2007, 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:
|
||||
PxeArch.c
|
||||
|
||||
Abstract:
|
||||
Defines PXE Arch type
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "PxeArch.h"
|
||||
|
||||
UINT16 mSysArch = 0;
|
||||
|
||||
UINT16
|
||||
GetSysArch (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (mSysArch == 0) {
|
||||
//
|
||||
// This is first call
|
||||
// Assign to invalid value
|
||||
//
|
||||
mSysArch = 0xFFFF;
|
||||
|
||||
//
|
||||
// We do not know what is EBC architecture.
|
||||
// Maybe we can try to locate DebugSupport protocol to get ISA.
|
||||
// TBD now.
|
||||
//
|
||||
}
|
||||
|
||||
return mSysArch;
|
||||
}
|
36
MdeModulePkg/Universal/Network/PxeBcDxe/Ebc/PxeArch.h
Normal file
36
MdeModulePkg/Universal/Network/PxeBcDxe/Ebc/PxeArch.h
Normal file
@ -0,0 +1,36 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2007, 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:
|
||||
PxeArch.h
|
||||
|
||||
Abstract:
|
||||
Defines PXE Arch type
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EFI_PXE_ARCH_H_
|
||||
#define _EFI_PXE_ARCH_H_
|
||||
|
||||
//
|
||||
// warning #175: subscript out of range
|
||||
//
|
||||
#pragma warning (disable: 175)
|
||||
|
||||
#define SYS_ARCH GetSysArch()
|
||||
|
||||
UINT16
|
||||
GetSysArch (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
43
MdeModulePkg/Universal/Network/PxeBcDxe/Hton.h
Normal file
43
MdeModulePkg/Universal/Network/PxeBcDxe/Hton.h
Normal file
@ -0,0 +1,43 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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 */
|
26
MdeModulePkg/Universal/Network/PxeBcDxe/Ia32/PxeArch.h
Normal file
26
MdeModulePkg/Universal/Network/PxeBcDxe/Ia32/PxeArch.h
Normal file
@ -0,0 +1,26 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
PxeArch.h
|
||||
|
||||
Abstract:
|
||||
Defines PXE Arch type
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EFI_PXE_ARCH_H_
|
||||
#define _EFI_PXE_ARCH_H_
|
||||
|
||||
#define SYS_ARCH 0x6
|
||||
|
||||
#endif
|
736
MdeModulePkg/Universal/Network/PxeBcDxe/Ip.h
Normal file
736
MdeModulePkg/Universal/Network/PxeBcDxe/Ip.h
Normal file
@ -0,0 +1,736 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 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"
|
||||
|
||||
//
|
||||
// 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 */
|
26
MdeModulePkg/Universal/Network/PxeBcDxe/Ipf/PxeArch.h
Normal file
26
MdeModulePkg/Universal/Network/PxeBcDxe/Ipf/PxeArch.h
Normal file
@ -0,0 +1,26 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
PxeArch.h
|
||||
|
||||
Abstract:
|
||||
Defines PXE Arch type
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EFI_PXE_ARCH_H_
|
||||
#define _EFI_PXE_ARCH_H_
|
||||
|
||||
#define SYS_ARCH 0x2
|
||||
|
||||
#endif
|
92
MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.inf
Normal file
92
MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.inf
Normal file
@ -0,0 +1,92 @@
|
||||
#/** @file
|
||||
# Component name for module BC
|
||||
#
|
||||
# Copyright (c) 2007, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PxeBcDxe
|
||||
FILE_GUID = A3f436EA-A127-4EF8-957C-8048606FF670
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = InitializeBCDriver
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Pxe_bc_mtftp.c
|
||||
Bc.c
|
||||
Dhcp.h
|
||||
Ip.h
|
||||
Pxe_bc_ip.c
|
||||
Pxe_bc_dhcp.c
|
||||
Pxe_bc_arp.c
|
||||
Hton.h
|
||||
ComponentName.c
|
||||
Bc.h
|
||||
Pxe_loadfile.c
|
||||
Tftp.h
|
||||
Pxe_bc_igmp.c
|
||||
Pxe_bc_udp.c
|
||||
|
||||
[Sources.IA32]
|
||||
Ia32\PxeArch.h
|
||||
|
||||
[Sources.X64]
|
||||
X64\PxeArch.h
|
||||
|
||||
[Sources.IPF]
|
||||
Ipf\PxeArch.h
|
||||
|
||||
[Sources.EBC]
|
||||
Ebc\PxeArch.h
|
||||
Ebc\PxeArch.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
|
||||
|
||||
[Guids]
|
||||
gEfiSmbiosTableGuid # ALWAYS_CONSUMED
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiBisProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiPxeBaseCodeCallbackProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiPxeBaseCodeProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiLoadFileProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiNetworkInterfaceIdentifierProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiNetworkInterfaceIdentifierProtocolGuid_31 # PROTOCOL ALWAYS_CONSUMED
|
||||
|
106
MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.msa
Normal file
106
MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.msa
Normal file
@ -0,0 +1,106 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>BC</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>A3f436EA-A127-4EF8-957C-8048606FF670</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module BC</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>BC</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseMemoryLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>pxe_bc_udp.c</Filename>
|
||||
<Filename>pxe_bc_igmp.c</Filename>
|
||||
<Filename>tftp.h</Filename>
|
||||
<Filename>pxe_loadfile.c</Filename>
|
||||
<Filename>bc.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>BcEntry.c</Filename>
|
||||
<Filename>ipf\PxeArch.h</Filename>
|
||||
<Filename>ebc\PxeArch.h</Filename>
|
||||
<Filename SupArchList="X64">x64\PxeArch.h</Filename>
|
||||
<Filename>pxe_bc_tcp.c</Filename>
|
||||
<Filename>hton.h</Filename>
|
||||
<Filename>pxe_bc_arp.c</Filename>
|
||||
<Filename>pxe_bc_dhcp.c</Filename>
|
||||
<Filename>pxe_bc_ip.c</Filename>
|
||||
<Filename>ip.h</Filename>
|
||||
<Filename>dhcp.h</Filename>
|
||||
<Filename>bc.c</Filename>
|
||||
<Filename>pxe_bc_mtftp.c</Filename>
|
||||
<Filename>ia32\PxeArch.h</Filename>
|
||||
<Filename>ebc\PxeArch.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiNetworkInterfaceIdentifierProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiPxeBaseCodeProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiPxeBaseCodeCallbackProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiBisProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Guids>
|
||||
<GuidCNames Usage="ALWAYS_CONSUMED">
|
||||
<GuidCName>gEfiSmbiosTableGuid</GuidCName>
|
||||
</GuidCNames>
|
||||
</Guids>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>InitializeBCDriver</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
583
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_arp.c
Normal file
583
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_arp.c
Normal file
@ -0,0 +1,583 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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()
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
|
||||
@return none
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitArpHeader (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
|
||||
@return TRUE := If IP address was found and MAC address was stored
|
||||
@return FALSE := If IP address was not found
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
GetHwAddr (
|
||||
IN PXE_BASECODE_DEVICE *Private,
|
||||
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
|
||||
OUT EFI_MAC_ADDRESS *HardwareAddrPtr
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS := ARP request sent
|
||||
@return other := ARP request could not be sent
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SendRequest (
|
||||
IN PXE_BASECODE_DEVICE *Private,
|
||||
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
|
||||
IN EFI_MAC_ADDRESS *HardwareAddrPtr
|
||||
)
|
||||
{
|
||||
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),
|
||||
&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
|
||||
)
|
||||
{
|
||||
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 ((DEBUG_ERROR, "BC *This pointer == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
|
||||
|
||||
if (Private == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EfiAcquireLock (&Private->Lock);
|
||||
|
||||
if (This->Mode == NULL || !This->Mode->Started) {
|
||||
DEBUG ((DEBUG_ERROR, "BC was not started."));
|
||||
EfiReleaseLock (&Private->Lock);
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "\nBcArp()"));
|
||||
|
||||
//
|
||||
// Issue BC command
|
||||
//
|
||||
if (ProtocolAddrPtr == NULL) {
|
||||
DEBUG (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_INFO,
|
||||
"\nBcArp() Exit #2 %Xh (%r)",
|
||||
EFI_SUCCESS,
|
||||
EFI_SUCCESS)
|
||||
);
|
||||
|
||||
EfiReleaseLock (&Private->Lock);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
StatCode = DoArp (Private, ProtocolAddrPtr, HardwareAddrPtr);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "\nBcArp() Exit #3 %Xh (%r)", StatCode, StatCode));
|
||||
|
||||
EfiReleaseLock (&Private->Lock);
|
||||
return StatCode;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS := MAC address found
|
||||
@return other := MAC address could not be found
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DoArp (
|
||||
IN PXE_BASECODE_DEVICE *Private,
|
||||
IN EFI_IP_ADDRESS *ProtocolAddrPtr,
|
||||
OUT EFI_MAC_ADDRESS *HardwareAddrPtr
|
||||
)
|
||||
{
|
||||
EFI_STATUS StatCode;
|
||||
EFI_EVENT TimeoutEvent;
|
||||
UINTN HeaderSize;
|
||||
UINTN BufferSize;
|
||||
UINT16 Protocol;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "\nDoArp()"));
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
StatCode = SendRequest (Private, ProtocolAddrPtr, HardwareAddrPtr);
|
||||
|
||||
if (EFI_ERROR (StatCode)) {
|
||||
DEBUG ((DEBUG_INFO, "\nDoArp() Exit #1 %Xh (%r)", StatCode, StatCode));
|
||||
return StatCode;
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
StatCode = gBS->CreateEvent (
|
||||
EVT_TIMER,
|
||||
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 (
|
||||
(DEBUG_INFO,
|
||||
"\nDoArp() Exit #2 %Xh, (%r)",
|
||||
StatCode,
|
||||
StatCode)
|
||||
);
|
||||
|
||||
gBS->CloseEvent (TimeoutEvent);
|
||||
|
||||
return StatCode;
|
||||
}
|
||||
|
||||
/* eof - pxe_bc_arp.c */
|
3284
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_dhcp.c
Normal file
3284
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_dhcp.c
Normal file
File diff suppressed because it is too large
Load Diff
421
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_igmp.c
Normal file
421
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_igmp.c
Normal file
@ -0,0 +1,421 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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
|
||||
)
|
||||
{
|
||||
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 (
|
||||
EVT_TIMER,
|
||||
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
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
//
|
||||
// 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
|
||||
)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
|
||||
@return 0 := Group not found
|
||||
@return other := Group ID#
|
||||
|
||||
**/
|
||||
STATIC
|
||||
INTN
|
||||
FindMulticastGroup (
|
||||
PXE_BASECODE_DEVICE *Private,
|
||||
UINT32 GroupAddress
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
UINT32 Grp;
|
||||
|
||||
Grp = *(UINT32 *) GroupPtr;
|
||||
|
||||
//
|
||||
// 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
|
||||
)
|
||||
{
|
||||
UINT32 Grp;
|
||||
UINTN GroupId;
|
||||
|
||||
Grp = *(UINT32 *) GroupPtr;
|
||||
|
||||
//
|
||||
// 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
|
||||
)
|
||||
{
|
||||
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 (
|
||||
EVT_TIMER,
|
||||
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 */
|
846
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_ip.c
Normal file
846
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_ip.c
Normal file
@ -0,0 +1,846 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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"
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Check if two IP addresses are on the same subnet.
|
||||
|
||||
@param IpLength Length of IP address in bytes.
|
||||
@param Ip1 IP address to check.
|
||||
@param Ip2 IP address to check.
|
||||
@param SubnetMask Subnet mask to check with.
|
||||
|
||||
@retval TRUE IP addresses are on the same subnet.
|
||||
@retval FALSE IP addresses are on different subnets.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
OnSameSubnet (
|
||||
IN UINTN IpLength,
|
||||
IN EFI_IP_ADDRESS *Ip1,
|
||||
IN EFI_IP_ADDRESS *Ip2,
|
||||
IN EFI_IP_ADDRESS *SubnetMask
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Add router to router table.
|
||||
|
||||
@param Private Pointer PxeBc instance data.
|
||||
@param RouterIpPtr Pointer to router IP address.
|
||||
|
||||
@return Nothing
|
||||
|
||||
**/
|
||||
VOID
|
||||
IpAddRouter (
|
||||
IN PXE_BASECODE_DEVICE *Private,
|
||||
IN EFI_IP_ADDRESS *RouterIpPtr
|
||||
)
|
||||
{
|
||||
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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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 ((DEBUG_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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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;
|
||||
}
|
||||
|
||||
#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));
|
||||
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 (
|
||||
(DEBUG_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 ((DEBUG_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 ((DEBUG_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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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 ((DEBUG_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 */
|
2193
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_mtftp.c
Normal file
2193
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_mtftp.c
Normal file
File diff suppressed because it is too large
Load Diff
517
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_udp.c
Normal file
517
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_udp.c
Normal file
@ -0,0 +1,517 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS :=
|
||||
@return EFI_INVALID_PARAMETER :=
|
||||
@return other :=
|
||||
|
||||
**/
|
||||
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
|
||||
)
|
||||
{
|
||||
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 (
|
||||
(DEBUG_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 (
|
||||
(DEBUG_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
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS :=
|
||||
@return other :=
|
||||
|
||||
**/
|
||||
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
|
||||
)
|
||||
{
|
||||
EFI_STATUS StatCode;
|
||||
PXE_BASECODE_DEVICE *Private;
|
||||
|
||||
//
|
||||
// Lock the instance data and make sure started
|
||||
//
|
||||
StatCode = EFI_SUCCESS;
|
||||
|
||||
if (This == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
|
||||
|
||||
if (Private == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EfiAcquireLock (&Private->Lock);
|
||||
|
||||
if (This->Mode == NULL || !This->Mode->Started) {
|
||||
DEBUG ((DEBUG_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
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS :=
|
||||
@return EFI_INVALID_PARAMETER :=
|
||||
@return other :=
|
||||
|
||||
**/
|
||||
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
|
||||
)
|
||||
{
|
||||
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 ((DEBUG_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;
|
||||
TmpDestIp = Private->EfiBc.Mode->StationIp;
|
||||
}
|
||||
|
||||
#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 (
|
||||
(DEBUG_INFO,
|
||||
"\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",
|
||||
Hdrs.Udpv4PseudoHeader)
|
||||
);
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
"\nUdpRead() Header size == %d",
|
||||
HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader))
|
||||
);
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
"\nUdpRead() BufferPtr == %Xh",
|
||||
BufferPtr)
|
||||
);
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
"\nUdpRead() Buffer size == %d",
|
||||
*BufferSizeptr)
|
||||
);
|
||||
DEBUG ((DEBUG_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);
|
||||
}
|
||||
}
|
||||
|
||||
if ((StatCode != EFI_SUCCESS) && (StatCode != EFI_TIMEOUT)) {
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
"\nUdpRead() Exit #3 %Xh %r",
|
||||
StatCode,
|
||||
StatCode)
|
||||
);
|
||||
}
|
||||
|
||||
return StatCode;
|
||||
}
|
||||
}
|
||||
//
|
||||
// //////////////////////////////////////////////////////////
|
||||
//
|
||||
// BC Udp Read Routine
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
@return EFI_SUCCESS :=
|
||||
@return other :=
|
||||
|
||||
**/
|
||||
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 StatCode;
|
||||
PXE_BASECODE_DEVICE *Private;
|
||||
|
||||
//
|
||||
// Lock the instance data and make sure started
|
||||
//
|
||||
StatCode = EFI_SUCCESS;
|
||||
|
||||
if (This == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
|
||||
|
||||
if (Private == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EfiAcquireLock (&Private->Lock);
|
||||
|
||||
if (This->Mode == NULL || !This->Mode->Started) {
|
||||
DEBUG ((DEBUG_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 */
|
1614
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_loadfile.c
Normal file
1614
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_loadfile.c
Normal file
File diff suppressed because it is too large
Load Diff
154
MdeModulePkg/Universal/Network/PxeBcDxe/Tftp.h
Normal file
154
MdeModulePkg/Universal/Network/PxeBcDxe/Tftp.h
Normal file
@ -0,0 +1,154 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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 */
|
26
MdeModulePkg/Universal/Network/PxeBcDxe/X64/PxeArch.h
Normal file
26
MdeModulePkg/Universal/Network/PxeBcDxe/X64/PxeArch.h
Normal file
@ -0,0 +1,26 @@
|
||||
/** @file
|
||||
|
||||
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:
|
||||
PxeArch.h
|
||||
|
||||
Abstract:
|
||||
Defines PXE Arch type
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EFI_PXE_ARCH_H_
|
||||
#define _EFI_PXE_ARCH_H_
|
||||
|
||||
#define SYS_ARCH 0x7
|
||||
|
||||
#endif
|
169
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/ComponentName.c
Normal file
169
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/ComponentName.c
Normal file
@ -0,0 +1,169 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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",
|
||||
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 */
|
355
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4.c
Normal file
355
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4.c
Normal file
@ -0,0 +1,355 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2005, 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,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
//
|
||||
// PxeDhcp4 Driver Entry point funtion
|
||||
//
|
||||
|
||||
/**
|
||||
Register Driver Binding protocol for this driver.
|
||||
|
||||
@param entry EFI_IMAGE_ENTRY_POINT)
|
||||
|
||||
@retval EFI_SUCCESS Driver loaded.
|
||||
@retval other Driver not loaded.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PxeDhcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return EfiLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gPxeDhcp4DriverBinding,
|
||||
NULL,
|
||||
COMPONENT_NAME,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. Any
|
||||
ControllerHandle that contains a PxeBaseCode protocol can be
|
||||
supported.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test.
|
||||
@param RemainingDevicePath Not used.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device.
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device.
|
||||
@retval other This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PxeDhcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle by opening a PxeBaseCode
|
||||
protocol and installing a PxeDhcp4 protocol on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to.
|
||||
@param RemainingDevicePath Not used, always produce all possible children.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle.
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
|
||||
@retval other This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PxeDhcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
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.
|
||||
//
|
||||
Private = AllocateZeroPool (sizeof (PXE_DHCP4_PRIVATE_DATA));
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle by removing PXE DHCP
|
||||
protocol and closing the PXE Base Code protocol on
|
||||
ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on.
|
||||
@param NumberOfChildren Not used.
|
||||
@param ChildHandleBuffer Not used.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed ControllerHandle.
|
||||
@retval other This driver was not removed from this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PxeDhcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
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) {
|
||||
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
|
||||
//
|
||||
FreePool (Private);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF - PxeDhcp4.c */
|
353
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4.h
Normal file
353
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4.h
Normal file
@ -0,0 +1,353 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/PxeBaseCode.h>
|
||||
#include <Protocol/SimpleNetwork.h>
|
||||
#include <Protocol/PxeDhcp4.h>
|
||||
#include <Protocol/PxeDhcp4Callback.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.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_COMPONENT_NAME_PROTOCOL gPxeDhcp4ComponentName;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PxeDhcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Register Driver Binding protocol for this driver.
|
||||
|
||||
Arguments:
|
||||
(Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Driver loaded.
|
||||
other - Driver not loaded.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
#ifdef EFI_SIZE_REDUCTION_APPLIED
|
||||
#define COMPONENT_NAME_CODE(code)
|
||||
#define COMPONENT_NAME NULL
|
||||
#else
|
||||
#define COMPONENT_NAME_CODE(code) code
|
||||
#define COMPONENT_NAME &gPxeDhcp4ComponentName
|
||||
#endif
|
||||
|
||||
#endif /* _PXEDHCP4_H */
|
||||
|
||||
/* EOF - PxeDhcp4.h */
|
64
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.inf
Normal file
64
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.inf
Normal file
@ -0,0 +1,64 @@
|
||||
#/** @file
|
||||
# Component name for module PxeDhcp4
|
||||
#
|
||||
# Copyright (c) 2007, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PxeDhcp4Dxe
|
||||
FILE_GUID = a46c3330-be36-4977-9d24-a7cf92eef0fe
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = PxeDhcp4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
support.c
|
||||
PxeDhcp4Release.c
|
||||
PxeDhcp4Setup.c
|
||||
ComponentName.c
|
||||
PxeDhcp4RenewRebind.c
|
||||
PxeDhcp4.h
|
||||
PxeDhcp4.c
|
||||
PxeDhcp4InitSelect.c
|
||||
PxeDhcp4Run.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiPxeBaseCodeProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiPxeDhcp4CallbackProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiPxeDhcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
78
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.msa
Normal file
78
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.msa
Normal file
@ -0,0 +1,78 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>PxeDhcp4</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>a46c3330-be36-4977-9d24-a7cf92eef0fe</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module PxeDhcp4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</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>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>PxeDhcp4</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseMemoryLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>PxeDhcp4Run.c</Filename>
|
||||
<Filename>PxeDhcp4InitSelect.c</Filename>
|
||||
<Filename>PxeDhcp4Entry.c</Filename>
|
||||
<Filename>PxeDhcp4.c</Filename>
|
||||
<Filename>PxeDhcp4.h</Filename>
|
||||
<Filename>PxeDhcp4RenewRebind.c</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>PxeDhcp4Setup.c</Filename>
|
||||
<Filename>PxeDhcp4Release.c</Filename>
|
||||
<Filename>support.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiPxeDhcp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiPxeDhcp4CallbackProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiPxeBaseCodeProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>PxeDhcp4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
784
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4InitSelect.c
Normal file
784
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4InitSelect.c
Normal file
@ -0,0 +1,784 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
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 */
|
247
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Release.c
Normal file
247
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Release.c
Normal file
@ -0,0 +1,247 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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 */
|
408
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4RenewRebind.c
Normal file
408
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4RenewRebind.c
Normal file
@ -0,0 +1,408 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004, 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"
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/**
|
||||
Parameters:
|
||||
|
||||
@return -2 = ignore, stop waiting
|
||||
@return -1 = ignore, keep waiting
|
||||
@return 0 = accept, keep waiting
|
||||
@return 1 = accept, stop waiting
|
||||
|
||||
**/
|
||||
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
|
||||
)
|
||||
{
|
||||
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 */
|
191
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Run.c
Normal file
191
MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Run.c
Normal file
@ -0,0 +1,191 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2007, 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);
|
||||
|
||||
if ((efi_status != EFI_SUCCESS) &&
|
||||
(efi_status != EFI_TIMEOUT) &&
|
||||
(efi_status != EFI_NO_RESPONSE)) {
|
||||
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 */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user