]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Include/Library/NetLib.h
MdeModulePkg: Update IP4 stack to support point-to-point link with 31-bit mask.
[mirror_edk2.git] / MdeModulePkg / Include / Library / NetLib.h
index 150b97936ea26a0337a1b5910b4175ecf5d28e2d..b9df46c50f63f73671654e246bdb37d8caf8d603 100644 (file)
-/** @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:
-
-  NetLib.h
-
-Abstract:
-
-  Library for the UEFI network stack.
-
-
-**/
-
-#ifndef _NET_LIB_H_
-#define _NET_LIB_H_
-
-#include <PiDxe.h>
-#include <Protocol/DriverBinding.h>
-#include <Protocol/ComponentName.h>
-#include <Protocol/DriverConfiguration.h>
-#include <Protocol/DriverDiagnostics.h>
-
-#define EFI_NET_LITTLE_ENDIAN
-
-typedef UINT32          IP4_ADDR;
-typedef UINT32          TCP_SEQNO;
-typedef UINT16          TCP_PORTNO;
-
-enum {
-  NET_ETHER_ADDR_LEN    = 6,
-  NET_IFTYPE_ETHERNET   = 0x01,
-
-  EFI_IP_PROTO_UDP      = 0x11,
-  EFI_IP_PROTO_TCP      = 0x06,
-  EFI_IP_PROTO_ICMP     = 0x01,
-
-  //
-  // The address classfication
-  //
-  IP4_ADDR_CLASSA       = 1,
-  IP4_ADDR_CLASSB,
-  IP4_ADDR_CLASSC,
-  IP4_ADDR_CLASSD,
-  IP4_ADDR_CLASSE,
-
-  IP4_MASK_NUM          = 33,
-};
-
-#pragma pack(1)
-
-//
-// Ethernet head definition
-//
-typedef struct {
-  UINT8                 DstMac [NET_ETHER_ADDR_LEN];
-  UINT8                 SrcMac [NET_ETHER_ADDR_LEN];
-  UINT16                EtherType;
-} ETHER_HEAD;
-
-
-//
-// The EFI_IP4_HEADER is hard to use because the source and
-// destination address are defined as EFI_IPv4_ADDRESS, which
-// is a structure. Two structures can't be compared or masked
-// directly. This is why there is an internal representation.
-//
-typedef struct {
-#ifdef EFI_NET_LITTLE_ENDIAN
-  UINT8                 HeadLen : 4;
-  UINT8                 Ver     : 4;
-#else
-  UINT8                 Ver     : 4;
-  UINT8                 HeadLen : 4;
-#endif
-  UINT8                 Tos;
-  UINT16                TotalLen;
-  UINT16                Id;
-  UINT16                Fragment;
-  UINT8                 Ttl;
-  UINT8                 Protocol;
-  UINT16                Checksum;
-  IP4_ADDR              Src;
-  IP4_ADDR              Dst;
-} IP4_HEAD;
-
-
-//
-// ICMP head definition. ICMP message is categoried as either an error
-// message or query message. Two message types have their own head format.
-//
-typedef struct {
-  UINT8                 Type;
-  UINT8                 Code;
-  UINT16                Checksum;
-} IP4_ICMP_HEAD;
-
-typedef struct {
-  IP4_ICMP_HEAD         Head;
-  UINT32                Fourth; // 4th filed of the head, it depends on Type.
-  IP4_HEAD              IpHead;
-} IP4_ICMP_ERROR_HEAD;
-
-typedef struct {
-  IP4_ICMP_HEAD         Head;
-  UINT16                Id;
-  UINT16                Seq;
-} IP4_ICMP_QUERY_HEAD;
-
-
-//
-// UDP header definition
-//
-typedef struct {
-  UINT16                SrcPort;
-  UINT16                DstPort;
-  UINT16                Length;
-  UINT16                Checksum;
-} EFI_UDP4_HEADER;
-
-
-//
-// TCP header definition
-//
-typedef struct {
-  TCP_PORTNO            SrcPort;
-  TCP_PORTNO            DstPort;
-  TCP_SEQNO             Seq;
-  TCP_SEQNO             Ack;
-#ifdef EFI_NET_LITTLE_ENDIAN
-  UINT8                 Res     : 4;
-  UINT8                 HeadLen : 4;
-#else
-  UINT8                 HeadLen : 4;
-  UINT8                 Res     : 4;
-#endif
-  UINT8                 Flag;
-  UINT16                Wnd;
-  UINT16                Checksum;
-  UINT16                Urg;
-} TCP_HEAD;
-
-#pragma pack()
-
-#define NET_MAC_EQUAL(pMac1, pMac2, Len)     \
-    (NetCompareMem ((pMac1), (pMac2), Len) == 0)
-
-#define NET_MAC_IS_MULTICAST(Mac, BMac, Len) \
-    (((*((UINT8 *) Mac) & 0x01) == 0x01) && (!NET_MAC_EQUAL (Mac, BMac, Len)))
-
-#ifdef EFI_NET_LITTLE_ENDIAN
-#define NTOHL(x) (UINT32)((((UINT32) (x) & 0xff)     << 24) | \
-                          (((UINT32) (x) & 0xff00)   << 8)  | \
-                          (((UINT32) (x) & 0xff0000) >> 8)  | \
-                          (((UINT32) (x) & 0xff000000) >> 24))
-
-#define HTONL(x)  NTOHL(x)
-
-#define NTOHS(x)  (UINT16)((((UINT16) (x) & 0xff) << 8) | \
-                           (((UINT16) (x) & 0xff00) >> 8))
-
-#define HTONS(x)  NTOHS(x)
-#else
-#define NTOHL(x)  (UINT32)(x)
-#define HTONL(x)  (UINT32)(x)
-#define NTOHS(x)  (UINT16)(x)
-#define HTONS(x)  (UINT16)(x)
-#endif
-
-//
-// Test the IP's attribute, All the IPs are in host byte order.
-//
-#define IP4_IS_MULTICAST(Ip)              (((Ip) & 0xF0000000) == 0xE0000000)
-#define IP4_IS_LOCAL_BROADCAST(Ip)        ((Ip) == 0xFFFFFFFF)
-#define IP4_NET_EQUAL(Ip1, Ip2, NetMask)  (((Ip1) & (NetMask)) == ((Ip2) & (NetMask)))
-#define IP4_IS_VALID_NETMASK(Ip)          (NetGetMaskLength (Ip) != IP4_MASK_NUM)
-
-//
-// Convert the EFI_IP4_ADDRESS to plain UINT32 IP4 address.
-//
-#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))
-
-INTN
-NetGetMaskLength (
-  IN IP4_ADDR               Mask
-  );
-
-INTN
-NetGetIpClass (
-  IN IP4_ADDR               Addr
-  );
-
-BOOLEAN
-Ip4IsUnicast (
-  IN IP4_ADDR               Ip,
-  IN IP4_ADDR               NetMask
-  );
-
-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)
-
-//
-// Wrap functions to ease the impact of EFI library changes.
-//
-#define NetAllocateZeroPool     AllocateZeroPool
-#define NetAllocatePool         AllocatePool
-#define NetFreePool             gBS->FreePool
-#define NetCopyMem              CopyMem
-#define NetSetMem               SetMem
-#define NetZeroMem(Dest, Len)   SetMem ((Dest), (Len), 0)
-#define NetCompareMem           CompareMem
-
-//
-// Lock primitives: the stack implements its lock primitives according
-// to the standard EFI enviornment. It will NOT consider multiprocessor.
-//
-#define NET_TPL_LOCK            TPL_CALLBACK
-#define NET_TPL_RECYCLE_LOCK    (NET_TPL_LOCK + 1)
-#define NET_TPL_EVENT           TPL_CALLBACK
-#define NET_TPL_RECYCLE         (NET_TPL_LOCK + 1)
-#define NET_TPL_SLOW_TIMER      (TPL_CALLBACK - 1)
-#define NET_TPL_FAST_TIMER      NET_TPL_RECYCLE
-#define NET_TPL_TIMER           TPL_CALLBACK
-
-#define NET_LOCK                 EFI_LOCK
-#define NET_LOCK_INIT(x)         EfiInitializeLock (x, NET_TPL_LOCK)
-#define NET_RECYCLE_LOCK_INIT(x) EfiInitializeLock (x, NET_TPL_RECYCLE_LOCK)
-#define NET_TRYLOCK(x)           EfiAcquireLockOrFail (x)
-#define NET_UNLOCK(x)            EfiReleaseLock (x)
-
-#define NET_RAISE_TPL(x)        (gBS->RaiseTPL (x))
-#define NET_RESTORE_TPL(x)      (gBS->RestoreTPL (x))
-
-#define TICKS_PER_MS            10000U
-#define TICKS_PER_SECOND        10000000U
-
-#define NET_MIN(a, b)           ((a) < (b) ? (a) : (b))
-#define NET_MAX(a, b)           ((a) > (b) ? (a) : (b))
-#define NET_RANDOM(Seed)        (((Seed) * 1103515245L + 12345) % 4294967295L)
-
-
-UINT32
-NetGetUint32 (
-  IN UINT8                  *Buf
-  );
-
-VOID
-NetPutUint32 (
-  IN UINT8                  *Buf,
-  IN UINT32                 Data
-  );
-
-UINT32
-NetRandomInitSeed (
-  VOID
-  );
-
-
-//
-// Double linked list entry functions, this extends the
-// EFI list functions.
-//
-typedef LIST_ENTRY      NET_LIST_ENTRY;
-
-#define NetListInit(Head)              InitializeListHead(Head)
-#define NetListInsertHead(Head, Entry) InsertHeadList((Head), (Entry))
-#define NetListInsertTail(Head, Entry) InsertTailList((Head), (Entry))
-#define NetListIsEmpty(List)           IsListEmpty(List)
-
-#define NET_LIST_USER_STRUCT(Entry, Type, Field)        \
-          _CR(Entry, Type, Field)
-
-#define NET_LIST_USER_STRUCT_S(Entry, Type, Field, Sig)  \
-          CR(Entry, Type, Field, Sig)
-
-//
-// Iterate through the doule linked list. It is NOT delete safe
-//
-#define NET_LIST_FOR_EACH(Entry, ListHead) \
-  for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
-
-//
-// Iterate through the doule linked list. This is delete-safe.
-// Don't touch NextEntry. Also, don't use this macro if list
-// entries other than the Entry may be deleted when processing
-// the current Entry.
-//
-#define NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \
-  for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink; \
-      Entry != (ListHead); \
-      Entry = NextEntry, NextEntry = Entry->ForwardLink \
-     )
-
-//
-// Make sure the list isn't empty before get the frist/last record.
-//
-#define NET_LIST_HEAD(ListHead, Type, Field)  \
-          NET_LIST_USER_STRUCT((ListHead)->ForwardLink, Type, Field)
-
-#define NET_LIST_TAIL(ListHead, Type, Field)  \
-          NET_LIST_USER_STRUCT((ListHead)->BackLink, Type, Field)
-
-#define NetListRemoveEntry(Entry) RemoveEntryList (Entry)
-
-NET_LIST_ENTRY*
-NetListRemoveHead (
-  NET_LIST_ENTRY            *Head
-  );
-
-NET_LIST_ENTRY*
-NetListRemoveTail (
-  NET_LIST_ENTRY            *Head
-  );
-
-VOID
-NetListInsertAfter (
-  IN NET_LIST_ENTRY         *PrevEntry,
-  IN NET_LIST_ENTRY         *NewEntry
-  );
-
-VOID
-NetListInsertBefore (
-  IN NET_LIST_ENTRY         *PostEntry,
-  IN NET_LIST_ENTRY         *NewEntry
-  );
-
-
-//
-// Object container: EFI network stack spec defines various kinds of
-// tokens. The drivers can share code to manage those objects.
-//
-typedef struct {
-  NET_LIST_ENTRY            Link;
-  VOID                      *Key;
-  VOID                      *Value;
-} NET_MAP_ITEM;
-
-typedef struct {
-  NET_LIST_ENTRY            Used;
-  NET_LIST_ENTRY            Recycled;
-  UINTN                     Count;
-} NET_MAP;
-
-#define NET_MAP_INCREAMENT  64
-
-VOID
-NetMapInit (
-  IN NET_MAP                *Map
-  );
-
-VOID
-NetMapClean (
-  IN NET_MAP                *Map
-  );
-
-BOOLEAN
-NetMapIsEmpty (
-  IN NET_MAP                *Map
-  );
-
-UINTN
-NetMapGetCount (
-  IN NET_MAP                *Map
-  );
-
-EFI_STATUS
-NetMapInsertHead (
-  IN NET_MAP                *Map,
-  IN VOID                   *Key,
-  IN VOID                   *Value    OPTIONAL
-  );
-
-EFI_STATUS
-NetMapInsertTail (
-  IN NET_MAP                *Map,
-  IN VOID                   *Key,
-  IN VOID                   *Value    OPTIONAL
-  );
-
-NET_MAP_ITEM  *
-NetMapFindKey (
-  IN  NET_MAP               *Map,
-  IN  VOID                  *Key
-  );
-
-VOID *
-NetMapRemoveItem (
-  IN  NET_MAP               *Map,
-  IN  NET_MAP_ITEM          *Item,
-  OUT VOID                  **Value   OPTIONAL
-  );
-
-VOID *
-NetMapRemoveHead (
-  IN  NET_MAP               *Map,
-  OUT VOID                  **Value   OPTIONAL
-  );
-
-VOID *
-NetMapRemoveTail (
-  IN  NET_MAP               *Map,
-  OUT VOID                  **Value OPTIONAL
-  );
-
-typedef
-EFI_STATUS
-(*NET_MAP_CALLBACK) (
-  IN NET_MAP                *Map,
-  IN NET_MAP_ITEM           *Item,
-  IN VOID                   *Arg
-  );
-
-EFI_STATUS
-NetMapIterate (
-  IN NET_MAP                *Map,
-  IN NET_MAP_CALLBACK       CallBack,
-  IN VOID                   *Arg      OPTIONAL
-  );
-
-
-//
-// Helper functions to implement driver binding and service binding protocols.
-//
-EFI_STATUS
-NetLibCreateServiceChild (
-  IN  EFI_HANDLE            ControllerHandle,
-  IN  EFI_HANDLE            ImageHandle,
-  IN  EFI_GUID              *ServiceBindingGuid,
-  OUT EFI_HANDLE            *ChildHandle
-  );
-
-EFI_STATUS
-NetLibDestroyServiceChild (
-  IN  EFI_HANDLE            ControllerHandle,
-  IN  EFI_HANDLE            ImageHandle,
-  IN  EFI_GUID              *ServiceBindingGuid,
-  IN  EFI_HANDLE            ChildHandle
-  );
-
-EFI_STATUS
-NetLibGetMacString (
-  IN           EFI_HANDLE  SnpHandle,
-  IN           EFI_HANDLE  ImageHandle,
-  IN OUT       CHAR16      **MacString
-  );
-
-EFI_HANDLE
-NetLibGetNicHandle (
-  IN EFI_HANDLE             Controller,
-  IN EFI_GUID               *ProtocolGuid
-  );
-
-typedef
-EFI_STATUS
-(EFIAPI *NET_LIB_DRIVER_UNLOAD) (
-  IN EFI_HANDLE             ImageHandle
-  );
-
-EFI_STATUS
-EFIAPI
-NetLibDefaultUnload (
-  IN EFI_HANDLE             ImageHandle
-  );
-
-EFI_STATUS
-NetLibInstallAllDriverProtocolsWithUnload (
-  IN EFI_HANDLE                         ImageHandle,
-  IN EFI_SYSTEM_TABLE                   *SystemTable,
-  IN EFI_DRIVER_BINDING_PROTOCOL        *DriverBinding,
-  IN EFI_HANDLE                         DriverBindingHandle,
-  IN EFI_COMPONENT_NAME_PROTOCOL        *ComponentName,       OPTIONAL
-  IN EFI_DRIVER_CONFIGURATION_PROTOCOL  *DriverConfiguration, OPTIONAL
-  IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL    *DriverDiagnostics, OPTIONAL
-  IN NET_LIB_DRIVER_UNLOAD              CustomizedUnload
-  );
-
-EFI_STATUS
-NetLibInstallAllDriverProtocols (
-  IN EFI_HANDLE                         ImageHandle,
-  IN EFI_SYSTEM_TABLE                   *SystemTable,
-  IN EFI_DRIVER_BINDING_PROTOCOL        *DriverBinding,
-  IN EFI_HANDLE                         DriverBindingHandle,
-  IN EFI_COMPONENT_NAME_PROTOCOL        *ComponentName,       OPTIONAL
-  IN EFI_DRIVER_CONFIGURATION_PROTOCOL  *DriverConfiguration, OPTIONAL
-  IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL    *DriverDiagnostics OPTIONAL
-  );
-\r
-enum {
-  //
-  //Various signatures
-  //
-  NET_BUF_SIGNATURE    = EFI_SIGNATURE_32 ('n', 'b', 'u', 'f'),
-  NET_VECTOR_SIGNATURE = EFI_SIGNATURE_32 ('n', 'v', 'e', 'c'),
-  NET_QUE_SIGNATURE    = EFI_SIGNATURE_32 ('n', 'b', 'q', 'u'),
-
-
-  NET_PROTO_DATA       = 64,   // Opaque buffer for protocols
-  NET_BUF_HEAD         = 1,    // Trim or allocate space from head
-  NET_BUF_TAIL         = 0,    // Trim or allocate space from tail
-  NET_VECTOR_OWN_FIRST = 0x01, // We allocated the 1st block in the vector
-};
-
-#define NET_CHECK_SIGNATURE(PData, SIGNATURE) \
-  ASSERT (((PData) != NULL) && ((PData)->Signature == (SIGNATURE)))
-
-#define NET_SWAP_SHORT(Value) \
-  ((((Value) & 0xff) << 8) | (((Value) >> 8) & 0xff))
-
-//
-// Single memory block in the vector.
-//
-typedef struct {
-  UINT32              Len;        // The block's length
-  UINT8               *Bulk;      // The block's Data
-} NET_BLOCK;
-
-typedef VOID (*NET_VECTOR_EXT_FREE) (VOID *Arg);
-
-//
-//NET_VECTOR contains several blocks to hold all packet's
-//fragments and other house-keeping stuff for sharing. It
-//doesn't specify the where actual packet fragment begins.
-//
-typedef struct {
-  UINT32              Signature;
-  INTN                RefCnt;  // Reference count to share NET_VECTOR.
-  NET_VECTOR_EXT_FREE Free;    // external function to free NET_VECTOR
-  VOID                *Arg;    // opeque argument to Free
-  UINT32              Flag;    // Flags, NET_VECTOR_OWN_FIRST
-  UINT32              Len;     // Total length of the assocated BLOCKs
-
-  UINT32              BlockNum;
-  NET_BLOCK           Block[1];
-} NET_VECTOR;
-
-//
-//NET_BLOCK_OP operate on the NET_BLOCK, It specifies
-//where the actual fragment begins and where it ends
-//
-typedef struct {
-  UINT8               *BlockHead;   // Block's head, or the smallest valid Head
-  UINT8               *BlockTail;   // Block's tail. BlockTail-BlockHead=block length
-  UINT8               *Head;        // 1st byte of the data in the block
-  UINT8               *Tail;        // Tail of the data in the block, Tail-Head=Size
-  UINT32              Size;         // The size of the data
-} NET_BLOCK_OP;
-
-
-//
-//NET_BUF is the buffer manage structure used by the
-//network stack. Every network packet may be fragmented,
-//and contains multiple fragments. The Vector points to
-//memory blocks used by the each fragment, and BlockOp
-//specifies where each fragment begins and ends.
-//
-//It also contains a opaque area for protocol to store
-//per-packet informations. Protocol must be caution not
-//to overwrite the members after that.
-//
-typedef struct {
-  UINT32              Signature;
-  INTN                RefCnt;
-  NET_LIST_ENTRY      List;       // The List this NET_BUF is on
-
-  IP4_HEAD            *Ip;        // Network layer header, for fast access
-  TCP_HEAD            *Tcp;       // Transport layer header, for fast access
-  UINT8               ProtoData [NET_PROTO_DATA]; //Protocol specific data
-
-  NET_VECTOR          *Vector;    // The vector containing the packet
-
-  UINT32              BlockOpNum; // Total number of BlockOp in the buffer
-  UINT32              TotalSize;  // Total size of the actual packet
-  NET_BLOCK_OP        BlockOp[1]; // Specify the position of actual packet
-} NET_BUF;
-
-
-//
-//A queue of NET_BUFs, It is just a thin extension of
-//NET_BUF functions.
-//
-typedef struct {
-  UINT32              Signature;
-  INTN                RefCnt;
-  NET_LIST_ENTRY      List;       // The List this buffer queue is on
-
-  NET_LIST_ENTRY      BufList;    // list of queued buffers
-  UINT32              BufSize;    // total length of DATA in the buffers
-  UINT32              BufNum;     // total number of buffers on the chain
-} NET_BUF_QUEUE;
-
-//
-// Pseudo header for TCP and UDP checksum
-//
-#pragma pack(1)
-typedef struct {
-  IP4_ADDR            SrcIp;
-  IP4_ADDR            DstIp;
-  UINT8               Reserved;
-  UINT8               Protocol;
-  UINT16              Len;
-} NET_PSEUDO_HDR;
-#pragma pack()
-
-//
-// The fragment entry table used in network interfaces. This is
-// the same as NET_BLOCK now. Use two different to distinguish
-// the two in case that NET_BLOCK be enhanced later.
-//
-typedef struct {
-  UINT32              Len;
-  UINT8               *Bulk;
-} NET_FRAGMENT;
-
-#define NET_GET_REF(PData)      ((PData)->RefCnt++)
-#define NET_PUT_REF(PData)      ((PData)->RefCnt--)
-#define NETBUF_FROM_PROTODATA(Info) _CR((Info), NET_BUF, ProtoData)
-
-#define NET_BUF_SHARED(Buf) \
-  (((Buf)->RefCnt > 1) || ((Buf)->Vector->RefCnt > 1))
-
-#define NET_VECTOR_SIZE(BlockNum) \
-  (sizeof (NET_VECTOR) + ((BlockNum) - 1) * sizeof (NET_BLOCK))
-
-#define NET_BUF_SIZE(BlockOpNum)  \
-  (sizeof (NET_BUF) + ((BlockOpNum) - 1) * sizeof (NET_BLOCK_OP))
-
-#define NET_HEADSPACE(BlockOp)  \
-  (UINTN)((BlockOp)->Head - (BlockOp)->BlockHead)
-
-#define NET_TAILSPACE(BlockOp)  \
-  (UINTN)((BlockOp)->BlockTail - (BlockOp)->Tail)
-
-NET_BUF  *
-NetbufAlloc (
-  IN UINT32                 Len
-  );
-
-VOID
-NetbufFree (
-  IN NET_BUF                *Nbuf
-  );
-
-
-UINT8  *
-NetbufGetByte (
-  IN  NET_BUF               *Nbuf,
-  IN  UINT32                Offset,
-  OUT UINT32                *Index      OPTIONAL
-  );
-
-NET_BUF  *
-NetbufClone (
-  IN NET_BUF                *Nbuf
-  );
-
-NET_BUF  *
-NetbufDuplicate (
-  IN NET_BUF                *Nbuf,
-  IN NET_BUF                *Duplicate    OPTIONAL,
-  IN UINT32                 HeadSpace
-  );
-
-NET_BUF  *
-NetbufGetFragment (
-  IN NET_BUF                *Nbuf,
-  IN UINT32                 Offset,
-  IN UINT32                 Len,
-  IN UINT32                 HeadSpace
-  );
-
-VOID
-NetbufReserve (
-  IN NET_BUF                *Nbuf,
-  IN UINT32                 Len
-  );
-
-UINT8  *
-NetbufAllocSpace (
-  IN NET_BUF                *Nbuf,
-  IN UINT32                 Len,
-  IN BOOLEAN                FromHead
-  );
-
-UINT32
-NetbufTrim (
-  IN NET_BUF                *Nbuf,
-  IN UINT32                 Len,
-  IN BOOLEAN                FromHead
-  );
-
-UINT32
-NetbufCopy (
-  IN NET_BUF                *Nbuf,
-  IN UINT32                 Offset,
-  IN UINT32                 Len,
-  IN UINT8                  *Dest
-  );
-
-NET_BUF  *
-NetbufFromExt (
-  IN NET_FRAGMENT           *ExtFragment,
-  IN UINT32                 ExtNum,
-  IN UINT32                 HeadSpace,
-  IN UINT32                 HeadLen,
-  IN NET_VECTOR_EXT_FREE    ExtFree,
-  IN VOID                   *Arg          OPTIONAL
-  );
-
-EFI_STATUS
-NetbufBuildExt (
-  IN NET_BUF                *Nbuf,
-  IN NET_FRAGMENT           *ExtFragment,
-  IN UINT32                 *ExtNum
-  );
-
-NET_BUF  *
-NetbufFromBufList (
-  IN NET_LIST_ENTRY         *BufList,
-  IN UINT32                 HeadSpace,
-  IN UINT32                 HeaderLen,
-  IN NET_VECTOR_EXT_FREE    ExtFree,
-  IN VOID                   *Arg                OPTIONAL
-  );
-
-VOID
-NetbufFreeList (
-  IN NET_LIST_ENTRY         *Head
-  );
-
-VOID
-NetbufQueInit (
-  IN NET_BUF_QUEUE          *NbufQue
-  );
-
-NET_BUF_QUEUE  *
-NetbufQueAlloc (
-  VOID
-  );
-
-VOID
-NetbufQueFree (
-  IN NET_BUF_QUEUE          *NbufQue
-  );
-
-NET_BUF  *
-NetbufQueRemove (
-  IN NET_BUF_QUEUE          *NbufQue
-  );
-
-VOID
-NetbufQueAppend (
-  IN NET_BUF_QUEUE          *NbufQue,
-  IN NET_BUF                *Nbuf
-  );
-
-UINT32
-NetbufQueCopy (
-  IN NET_BUF_QUEUE          *NbufQue,
-  IN UINT32                 Offset,
-  IN UINT32                 Len,
-  IN UINT8                  *Dest
-  );
-
-UINT32
-NetbufQueTrim (
-  IN NET_BUF_QUEUE          *NbufQue,
-  IN UINT32                 Len
-  );
-
-VOID
-NetbufQueFlush (
-  IN NET_BUF_QUEUE          *NbufQue
-  );
-
-UINT16
-NetblockChecksum (
-  IN UINT8                  *Bulk,
-  IN UINT32                 Len
-  );
-
-UINT16
-NetAddChecksum (
-  IN UINT16                 Checksum1,
-  IN UINT16                 Checksum2
-  );
-
-UINT16
-NetbufChecksum (
-  IN NET_BUF                *Nbuf
-  );
-
-UINT16
-NetPseudoHeadChecksum (
-  IN IP4_ADDR               Src,
-  IN IP4_ADDR               Dst,
-  IN UINT8                  Proto,
-  IN UINT16                 Len
-  );
-
+/** @file\r
+  This library is only intended to be used by UEFI network stack modules.\r
+  It provides basic functions for the UEFI network stack.\r
+\r
+Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at<BR>\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _NET_LIB_H_\r
+#define _NET_LIB_H_\r
+\r
+#include <Protocol/Ip6.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+typedef UINT32          IP4_ADDR;\r
+typedef UINT32          TCP_SEQNO;\r
+typedef UINT16          TCP_PORTNO;\r
+\r
+\r
+#define  NET_ETHER_ADDR_LEN    6\r
+#define  NET_IFTYPE_ETHERNET   0x01\r
+\r
+#define  NET_VLAN_TAG_LEN      4\r
+#define  ETHER_TYPE_VLAN       0x8100\r
+\r
+#define  EFI_IP_PROTO_UDP      0x11\r
+#define  EFI_IP_PROTO_TCP      0x06\r
+#define  EFI_IP_PROTO_ICMP     0x01\r
+#define  IP4_PROTO_IGMP        0x02\r
+#define  IP6_ICMP              58\r
+#define  DNS_MAX_NAME_SIZE     255\r
+#define  DNS_MAX_MESSAGE_SIZE  512\r
+\r
+//\r
+// The address classification\r
+//\r
+#define  IP4_ADDR_CLASSA       1     // Deprecated\r
+#define  IP4_ADDR_CLASSB       2     // Deprecated\r
+#define  IP4_ADDR_CLASSC       3     // Deprecated\r
+#define  IP4_ADDR_CLASSD       4\r
+#define  IP4_ADDR_CLASSE       5\r
+\r
+#define  IP4_MASK_NUM          33\r
+#define  IP6_PREFIX_NUM        129\r
+\r
+#define  IP4_MASK_MAX          32 \r
+#define  IP6_PREFIX_MAX        128\r
+\r
+#define  IP6_HOP_BY_HOP        0\r
+#define  IP6_DESTINATION       60\r
+#define  IP6_ROUTING           43\r
+#define  IP6_FRAGMENT          44\r
+#define  IP6_AH                51\r
+#define  IP6_ESP               50\r
+#define  IP6_NO_NEXT_HEADER    59\r
+\r
+#define  IP_VERSION_4          4\r
+#define  IP_VERSION_6          6\r
+\r
+#define  IP6_PREFIX_LENGTH     64\r
+\r
+//\r
+// DNS QTYPE values\r
+//\r
+#define  DNS_TYPE_A            1\r
+#define  DNS_TYPE_NS           2\r
+#define  DNS_TYPE_CNAME        5\r
+#define  DNS_TYPE_SOA          6\r
+#define  DNS_TYPE_WKS          11\r
+#define  DNS_TYPE_PTR          12\r
+#define  DNS_TYPE_HINFO        13\r
+#define  DNS_TYPE_MINFO        14\r
+#define  DNS_TYPE_MX           15\r
+#define  DNS_TYPE_TXT          16\r
+#define  DNS_TYPE_AAAA         28\r
+#define  DNS_TYPE_SRV_RR       33\r
+#define  DNS_TYPE_AXFR         252\r
+#define  DNS_TYPE_MAILB        253\r
+#define  DNS_TYPE_ANY          255\r
+\r
+//\r
+// DNS QCLASS values\r
+//\r
+#define  DNS_CLASS_INET        1\r
+#define  DNS_CLASS_CH          3\r
+#define  DNS_CLASS_HS          4\r
+#define  DNS_CLASS_ANY         255\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Ethernet head definition\r
+//\r
+typedef struct {\r
+  UINT8                 DstMac [NET_ETHER_ADDR_LEN];\r
+  UINT8                 SrcMac [NET_ETHER_ADDR_LEN];\r
+  UINT16                EtherType;\r
+} ETHER_HEAD;\r
+\r
+//\r
+// 802.1Q VLAN Tag Control Information\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT16              Vid      : 12;  // Unique VLAN identifier (0 to 4094)\r
+    UINT16              Cfi      : 1;   // Canonical Format Indicator\r
+    UINT16              Priority : 3;   // 802.1Q priority level (0 to 7)\r
+  } Bits;\r
+  UINT16                Uint16;\r
+} VLAN_TCI;\r
+\r
+#define VLAN_TCI_CFI_CANONICAL_MAC      0\r
+#define VLAN_TCI_CFI_NON_CANONICAL_MAC  1\r
+\r
+//\r
+// The EFI_IP4_HEADER is hard to use because the source and\r
+// destination address are defined as EFI_IPv4_ADDRESS, which\r
+// is a structure. Two structures can't be compared or masked\r
+// directly. This is why there is an internal representation.\r
+//\r
+typedef struct {\r
+  UINT8                 HeadLen : 4;\r
+  UINT8                 Ver     : 4;\r
+  UINT8                 Tos;\r
+  UINT16                TotalLen;\r
+  UINT16                Id;\r
+  UINT16                Fragment;\r
+  UINT8                 Ttl;\r
+  UINT8                 Protocol;\r
+  UINT16                Checksum;\r
+  IP4_ADDR              Src;\r
+  IP4_ADDR              Dst;\r
+} IP4_HEAD;\r
+\r
+\r
+//\r
+// ICMP head definition. Each ICMP message is categorized as either an error\r
+// message or query message. Two message types have their own head format.\r
+//\r
+typedef struct {\r
+  UINT8                 Type;\r
+  UINT8                 Code;\r
+  UINT16                Checksum;\r
+} IP4_ICMP_HEAD;\r
+\r
+typedef struct {\r
+  IP4_ICMP_HEAD         Head;\r
+  UINT32                Fourth; // 4th filed of the head, it depends on Type.\r
+  IP4_HEAD              IpHead;\r
+} IP4_ICMP_ERROR_HEAD;\r
+\r
+typedef struct {\r
+  IP4_ICMP_HEAD         Head;\r
+  UINT16                Id;\r
+  UINT16                Seq;\r
+} IP4_ICMP_QUERY_HEAD;\r
+\r
+typedef struct {\r
+  UINT8                 Type;\r
+  UINT8                 Code;\r
+  UINT16                Checksum;\r
+} IP6_ICMP_HEAD;\r
+\r
+typedef struct {\r
+  IP6_ICMP_HEAD         Head;\r
+  UINT32                Fourth;\r
+  EFI_IP6_HEADER        IpHead;\r
+} IP6_ICMP_ERROR_HEAD;\r
+\r
+typedef struct {\r
+  IP6_ICMP_HEAD         Head;\r
+  UINT32                Fourth;\r
+} IP6_ICMP_INFORMATION_HEAD;\r
+\r
+//\r
+// UDP header definition\r
+//\r
+typedef struct {\r
+  UINT16                SrcPort;\r
+  UINT16                DstPort;\r
+  UINT16                Length;\r
+  UINT16                Checksum;\r
+} EFI_UDP_HEADER;\r
+\r
+//\r
+// TCP header definition\r
+//\r
+typedef struct {\r
+  TCP_PORTNO            SrcPort;\r
+  TCP_PORTNO            DstPort;\r
+  TCP_SEQNO             Seq;\r
+  TCP_SEQNO             Ack;\r
+  UINT8                 Res     : 4;\r
+  UINT8                 HeadLen : 4;\r
+  UINT8                 Flag;\r
+  UINT16                Wnd;\r
+  UINT16                Checksum;\r
+  UINT16                Urg;\r
+} TCP_HEAD;\r
+\r
+#pragma pack()\r
+\r
+#define NET_MAC_EQUAL(pMac1, pMac2, Len)     \\r
+    (CompareMem ((pMac1), (pMac2), Len) == 0)\r
+\r
+#define NET_MAC_IS_MULTICAST(Mac, BMac, Len) \\r
+    (((*((UINT8 *) Mac) & 0x01) == 0x01) && (!NET_MAC_EQUAL (Mac, BMac, Len)))\r
+\r
+#define NTOHL(x)  SwapBytes32 (x)\r
+\r
+#define HTONL(x)  NTOHL(x)\r
+\r
+#define NTOHS(x)  SwapBytes16 (x)\r
+\r
+#define HTONS(x)   NTOHS(x)\r
+#define NTOHLL(x)  SwapBytes64 (x)\r
+#define HTONLL(x)  NTOHLL(x)\r
+#define NTOHLLL(x) Ip6Swap128 (x)\r
+#define HTONLLL(x) NTOHLLL(x)\r
+\r
+//\r
+// Test the IP's attribute, All the IPs are in host byte order.\r
+//\r
+#define IP4_IS_MULTICAST(Ip)              (((Ip) & 0xF0000000) == 0xE0000000)\r
+#define IP4_IS_UNSPECIFIED(Ip)            ((Ip) == 0)\r
+#define IP4_IS_LOCAL_BROADCAST(Ip)        ((Ip) == 0xFFFFFFFF)\r
+#define IP4_NET_EQUAL(Ip1, Ip2, NetMask)  (((Ip1) & (NetMask)) == ((Ip2) & (NetMask)))\r
+#define IP4_IS_VALID_NETMASK(Ip)          (NetGetMaskLength (Ip) != (IP4_MASK_MAX + 1))\r
+\r
+#define IP6_IS_MULTICAST(Ip6)             (((Ip6)->Addr[0]) == 0xFF)\r
+\r
+//\r
+// Convert the EFI_IP4_ADDRESS to plain UINT32 IP4 address.\r
+//\r
+#define EFI_IP4(EfiIpAddr)       (*(IP4_ADDR *) ((EfiIpAddr).Addr))\r
+#define EFI_NTOHL(EfiIp)         (NTOHL (EFI_IP4 ((EfiIp))))\r
+#define EFI_IP4_EQUAL(Ip1, Ip2)  (CompareMem ((Ip1), (Ip2), sizeof (EFI_IPv4_ADDRESS)) == 0)\r
+\r
+#define EFI_IP6_EQUAL(Ip1, Ip2)  (CompareMem ((Ip1), (Ip2), sizeof (EFI_IPv6_ADDRESS)) == 0)\r
+\r
+#define IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
+#define IP6_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv6_ADDRESS)))\r
+#define IP6_COPY_LINK_ADDRESS(Mac1, Mac2) (CopyMem ((Mac1), (Mac2), sizeof (EFI_MAC_ADDRESS)))\r
+\r
 //\r
 // The debug level definition. This value is also used as the\r
-// syslog's servity level. Don't change it.\r
+// syslog's severity level. Don't change it.\r
 //\r
-enum {\r
-  NETDEBUG_LEVEL_TRACE   = 5,\r
-  NETDEBUG_LEVEL_WARNING = 4,\r
-  NETDEBUG_LEVEL_ERROR   = 3,\r
-};\r
+#define NETDEBUG_LEVEL_TRACE   5\r
+#define NETDEBUG_LEVEL_WARNING 4\r
+#define NETDEBUG_LEVEL_ERROR   3\r
 \r
-#ifdef EFI_NETWORK_STACK_DEBUG\r
+//\r
+// Network debug message is sent out as syslog packet.\r
+//\r
+#define NET_SYSLOG_FACILITY    16                 // Syslog local facility local use\r
+#define NET_SYSLOG_PACKET_LEN  512\r
+#define NET_SYSLOG_TX_TIMEOUT  (500 * 1000 * 10)  // 500ms\r
+#define NET_DEBUG_MSG_LEN      470                // 512 - (ether+ip4+udp4 head length)\r
 \r
 //\r
 // The debug output expects the ASCII format string, Use %a to print ASCII\r
@@ -854,34 +299,1891 @@ enum {
     NetDebugASPrint PrintArg \\r
     )\r
 \r
-#else\r
-#define NET_DEBUG_TRACE(Module, PrintString)\r
-#define NET_DEBUG_WARNING(Module, PrintString)\r
-#define NET_DEBUG_ERROR(Module, PrintString)\r
-#endif\r
+/**\r
+  Allocate a buffer, then format the message to it. This is a\r
+  help function for the NET_DEBUG_XXX macros. The PrintArg of\r
+  these macros treats the variable length print parameters as a\r
+  single parameter, and pass it to the NetDebugASPrint. For\r
+  example, NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name))\r
+  if extracted to:\r
+\r
+         NetDebugOutput (\r
+           NETDEBUG_LEVEL_TRACE,\r
+           "Tcp",\r
+           __FILE__,\r
+           __LINE__,\r
+           NetDebugASPrint ("State transit to %a\n", Name)\r
+         )\r
 \r
-UINT8 *\r
+  @param Format  The ASCII format string.\r
+  @param ...     The variable length parameter whose format is determined\r
+                 by the Format string.\r
+\r
+  @return        The buffer containing the formatted message,\r
+                 or NULL if memory allocation failed.\r
+\r
+**/\r
+CHAR8 *\r
+EFIAPI\r
 NetDebugASPrint (\r
-  UINT8                     *Format,\r
+  IN CHAR8                  *Format,\r
   ...\r
   );\r
 \r
+/**\r
+  Builds an UDP4 syslog packet and send it using SNP.\r
+\r
+  This function will locate a instance of SNP then send the message through it.\r
+  Because it isn't open the SNP BY_DRIVER, apply caution when using it.\r
+\r
+  @param Level    The severity level of the message.\r
+  @param Module   The Module that generates the log.\r
+  @param File     The file that contains the log.\r
+  @param Line     The exact line that contains the log.\r
+  @param Message  The user message to log.\r
+\r
+  @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory for the packet\r
+  @retval EFI_SUCCESS           The log is discard because that it is more verbose\r
+                                than the mNetDebugLevelMax. Or, it has been sent out.\r
+**/\r
 EFI_STATUS\r
+EFIAPI\r
 NetDebugOutput (\r
-  UINT32                    Level,\r
-  UINT8                     *Module,\r
-  UINT8                     *File,\r
-  UINT32                    Line,\r
-  UINT8                     *Message\r
+  IN UINT32                    Level,\r
+  IN UINT8                     *Module,\r
+  IN UINT8                     *File,\r
+  IN UINT32                    Line,\r
+  IN UINT8                     *Message\r
+  );\r
+\r
+\r
+/**\r
+  Return the length of the mask.\r
+\r
+  Return the length of the mask. Valid values are 0 to 32.\r
+  If the mask is invalid, return the invalid length 33, which is IP4_MASK_NUM.\r
+  NetMask is in the host byte order.\r
+\r
+  @param[in]  NetMask              The netmask to get the length from.\r
+\r
+  @return The length of the netmask, or IP4_MASK_NUM (33) if the mask is invalid.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+NetGetMaskLength (\r
+  IN IP4_ADDR               NetMask\r
+  );\r
+\r
+/**\r
+  Return the class of the IP address, such as class A, B, C.\r
+  Addr is in host byte order.\r
+\r
+  [ATTENTION]\r
+  Classful addressing (IP class A/B/C) has been deprecated according to RFC4632.\r
+  Caller of this function could only check the returned value against\r
+  IP4_ADDR_CLASSD (multicast) or IP4_ADDR_CLASSE (reserved) now.\r
+\r
+  The address of class A  starts with 0.\r
+  If the address belong to class A, return IP4_ADDR_CLASSA.\r
+  The address of class B  starts with 10.\r
+  If the address belong to class B, return IP4_ADDR_CLASSB.\r
+  The address of class C  starts with 110.\r
+  If the address belong to class C, return IP4_ADDR_CLASSC.\r
+  The address of class D  starts with 1110.\r
+  If the address belong to class D, return IP4_ADDR_CLASSD.\r
+  The address of class E  starts with 1111.\r
+  If the address belong to class E, return IP4_ADDR_CLASSE.\r
+\r
+\r
+  @param[in]   Addr                  The address to get the class from.\r
+\r
+  @return IP address class, such as IP4_ADDR_CLASSA.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+NetGetIpClass (\r
+  IN IP4_ADDR               Addr\r
+  );\r
+\r
+/**\r
+  Check whether the IP is a valid unicast address according to\r
+  the netmask. \r
+\r
+  ASSERT if NetMask is zero.\r
+  \r
+  If all bits of the host address of IP are 0 or 1, IP is also not a valid unicast address,\r
+  except when the originator is one of the endpoints of a point-to-point link with a 31-bit\r
+  mask (RFC3021).\r
+  \r
+  @param[in]  Ip                    The IP to check against.\r
+  @param[in]  NetMask               The mask of the IP.\r
+\r
+  @return TRUE if IP is a valid unicast address on the network, otherwise FALSE.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIp4IsUnicast (\r
+  IN IP4_ADDR               Ip,\r
+  IN IP4_ADDR               NetMask\r
+  );\r
+\r
+/**\r
+  Check whether the incoming IPv6 address is a valid unicast address.\r
+\r
+  If the address is a multicast address has binary 0xFF at the start, it is not\r
+  a valid unicast address. If the address is unspecified ::, it is not a valid\r
+  unicast address to be assigned to any node. If the address is loopback address\r
+  ::1, it is also not a valid unicast address to be assigned to any physical\r
+  interface.\r
+\r
+  @param[in]  Ip6                   The IPv6 address to check against.\r
+\r
+  @return TRUE if Ip6 is a valid unicast address on the network, otherwise FALSE.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIp6IsValidUnicast (\r
+  IN EFI_IPv6_ADDRESS       *Ip6\r
+  );\r
+\r
+\r
+/**\r
+  Check whether the incoming Ipv6 address is the unspecified address or not.\r
+\r
+  @param[in] Ip6   - Ip6 address, in network order.\r
+\r
+  @retval TRUE     - Yes, incoming Ipv6 address is the unspecified address.\r
+  @retval FALSE    - The incoming Ipv6 address is not the unspecified address\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIp6IsUnspecifiedAddr (\r
+  IN EFI_IPv6_ADDRESS       *Ip6\r
+  );\r
+\r
+/**\r
+  Check whether the incoming Ipv6 address is a link-local address.\r
+\r
+  @param[in] Ip6   - Ip6 address, in network order.\r
+\r
+  @retval TRUE  - The incoming Ipv6 address is a link-local address.\r
+  @retval FALSE - The incoming Ipv6 address is not a link-local address.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIp6IsLinkLocalAddr (\r
+  IN EFI_IPv6_ADDRESS *Ip6\r
+  );\r
+\r
+/**\r
+  Check whether the Ipv6 address1 and address2 are on the connected network.\r
+\r
+  @param[in] Ip1          - Ip6 address1, in network order.\r
+  @param[in] Ip2          - Ip6 address2, in network order.\r
+  @param[in] PrefixLength - The prefix length of the checking net.\r
+\r
+  @retval TRUE            - Yes, the Ipv6 address1 and address2 are connected.\r
+  @retval FALSE           - No the Ipv6 address1 and address2 are not connected.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIp6IsNetEqual (\r
+  EFI_IPv6_ADDRESS *Ip1,\r
+  EFI_IPv6_ADDRESS *Ip2,\r
+  UINT8            PrefixLength\r
+  );\r
+\r
+/**\r
+  Switches the endianess of an IPv6 address.\r
+\r
+  This function swaps the bytes in a 128-bit IPv6 address to switch the value\r
+  from little endian to big endian or vice versa. The byte swapped value is\r
+  returned.\r
+\r
+  @param  Ip6 Points to an IPv6 address.\r
+\r
+  @return The byte swapped IPv6 address.\r
+\r
+**/\r
+EFI_IPv6_ADDRESS *\r
+EFIAPI\r
+Ip6Swap128 (\r
+  EFI_IPv6_ADDRESS *Ip6\r
+  );\r
+\r
+extern IP4_ADDR gIp4AllMasks[IP4_MASK_NUM];\r
+\r
+\r
+extern EFI_IPv4_ADDRESS  mZeroIp4Addr;\r
+\r
+#define NET_IS_DIGIT(Ch)            (('0' <= (Ch)) && ((Ch) <= '9'))\r
+#define NET_IS_HEX(Ch)              ((('0' <= (Ch)) && ((Ch) <= '9')) || (('A' <= (Ch)) && ((Ch) <= 'F')) || (('a' <= (Ch)) && ((Ch) <= 'f')))\r
+#define NET_ROUNDUP(size, unit)     (((size) + (unit) - 1) & (~((unit) - 1)))\r
+#define NET_IS_LOWER_CASE_CHAR(Ch)  (('a' <= (Ch)) && ((Ch) <= 'z'))\r
+#define NET_IS_UPPER_CASE_CHAR(Ch)  (('A' <= (Ch)) && ((Ch) <= 'Z'))\r
+\r
+#define TICKS_PER_MS            10000U\r
+#define TICKS_PER_SECOND        10000000U\r
+\r
+#define NET_RANDOM(Seed)        ((UINT32) ((UINT32) (Seed) * 1103515245UL + 12345) % 4294967295UL)\r
+\r
+/**\r
+  Extract a UINT32 from a byte stream.\r
+\r
+  This function copies a UINT32 from a byte stream, and then converts it from Network\r
+  byte order to host byte order. Use this function to avoid alignment error.\r
+\r
+  @param[in]  Buf                 The buffer to extract the UINT32.\r
+\r
+  @return The UINT32 extracted.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetGetUint32 (\r
+  IN UINT8                  *Buf\r
+  );\r
+\r
+/**\r
+  Puts a UINT32 into the byte stream in network byte order.\r
+\r
+  Converts a UINT32 from host byte order to network byte order, then copies it to the\r
+  byte stream.\r
+\r
+  @param[in, out]  Buf          The buffer in which to put the UINT32.\r
+  @param[in]       Data         The data to be converted and put into the byte stream.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetPutUint32 (\r
+  IN OUT UINT8                 *Buf,\r
+  IN     UINT32                Data\r
+  );\r
+\r
+/**\r
+  Initialize a random seed using current time and monotonic count.\r
+\r
+  Get current time and monotonic count first. Then initialize a random seed \r
+  based on some basic mathematics operation on the hour, day, minute, second,\r
+  nanosecond and year of the current time and the monotonic count value.\r
+\r
+  @return The random seed initialized with current time.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetRandomInitSeed (\r
+  VOID\r
+  );\r
+\r
+\r
+#define NET_LIST_USER_STRUCT(Entry, Type, Field)        \\r
+          BASE_CR(Entry, Type, Field)\r
+\r
+#define NET_LIST_USER_STRUCT_S(Entry, Type, Field, Sig)  \\r
+          CR(Entry, Type, Field, Sig)\r
+\r
+//\r
+// Iterate through the double linked list. It is NOT delete safe\r
+//\r
+#define NET_LIST_FOR_EACH(Entry, ListHead) \\r
+  for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)\r
+\r
+//\r
+// Iterate through the double linked list. This is delete-safe.\r
+// Don't touch NextEntry. Also, don't use this macro if list\r
+// entries other than the Entry may be deleted when processing\r
+// the current Entry.\r
+//\r
+#define NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \\r
+  for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink; \\r
+      Entry != (ListHead); \\r
+      Entry = NextEntry, NextEntry = Entry->ForwardLink \\r
+     )\r
+\r
+//\r
+// Make sure the list isn't empty before getting the first/last record.\r
+//\r
+#define NET_LIST_HEAD(ListHead, Type, Field)  \\r
+          NET_LIST_USER_STRUCT((ListHead)->ForwardLink, Type, Field)\r
+\r
+#define NET_LIST_TAIL(ListHead, Type, Field)  \\r
+          NET_LIST_USER_STRUCT((ListHead)->BackLink, Type, Field)\r
+\r
+\r
+/**\r
+  Remove the first node entry on the list, and return the removed node entry.\r
+\r
+  Removes the first node entry from a doubly linked list. It is up to the caller of\r
+  this function to release the memory used by the first node, if that is required. On\r
+  exit, the removed node is returned.\r
+\r
+  If Head is NULL, then ASSERT().\r
+  If Head was not initialized, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
+  linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,\r
+  then ASSERT().\r
+\r
+  @param[in, out]  Head                  The list header.\r
+\r
+  @return The first node entry that is removed from the list, NULL if the list is empty.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+NetListRemoveHead (\r
+  IN OUT LIST_ENTRY            *Head\r
+  );\r
+\r
+/**\r
+  Remove the last node entry on the list and return the removed node entry.\r
+\r
+  Removes the last node entry from a doubly linked list. It is up to the caller of\r
+  this function to release the memory used by the first node, if that is required. On\r
+  exit, the removed node is returned.\r
+\r
+  If Head is NULL, then ASSERT().\r
+  If Head was not initialized, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
+  linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,\r
+  then ASSERT().\r
+\r
+  @param[in, out]  Head                  The list head.\r
+\r
+  @return The last node entry that is removed from the list, NULL if the list is empty.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+NetListRemoveTail (\r
+  IN OUT LIST_ENTRY            *Head\r
+  );\r
+\r
+/**\r
+  Insert a new node entry after a designated node entry of a doubly linked list.\r
+\r
+  Inserts a new node entry designated by NewEntry after the node entry designated by PrevEntry\r
+  of the doubly linked list.\r
+\r
+  @param[in, out]  PrevEntry             The entry after which to insert.\r
+  @param[in, out]  NewEntry              The new entry to insert.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetListInsertAfter (\r
+  IN OUT LIST_ENTRY         *PrevEntry,\r
+  IN OUT LIST_ENTRY         *NewEntry\r
+  );\r
+\r
+/**\r
+  Insert a new node entry before a designated node entry of a doubly linked list.\r
+\r
+  Inserts a new node entry designated by NewEntry before the node entry designated by PostEntry\r
+  of the doubly linked list.\r
+\r
+  @param[in, out]  PostEntry             The entry to insert before.\r
+  @param[in, out]  NewEntry              The new entry to insert.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetListInsertBefore (\r
+  IN OUT LIST_ENTRY     *PostEntry,\r
+  IN OUT LIST_ENTRY     *NewEntry\r
+  );\r
+\r
+/**\r
+  Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+  \r
+  @param[in]    Entry           The entry to be removed.\r
+  @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+  @retval EFI_SUCCESS           The entry has been removed successfully.\r
+  @retval Others                Fail to remove the entry.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *NET_DESTROY_LINK_LIST_CALLBACK) (\r
+  IN LIST_ENTRY         *Entry,\r
+  IN VOID               *Context   OPTIONAL\r
+  );\r
+\r
+/**\r
+  Safe destroy nodes in a linked list, and return the length of the list after all possible operations finished.\r
+\r
+  Destroy network children list by list traversals is not safe due to graph dependencies between nodes.\r
+  This function performs a safe traversal to destroy these nodes by checking to see if the node being destroyed\r
+  has been removed from the list or not.\r
+  If it has been removed, then restart the traversal from the head.\r
+  If it hasn't been removed, then continue with the next node directly.\r
+  This function will end the iterate and return the CallBack's last return value if error happens,\r
+  or retrun EFI_SUCCESS if 2 complete passes are made with no changes in the number of children in the list.  \r
+\r
+  @param[in]    List             The head of the list.\r
+  @param[in]    CallBack         Pointer to the callback function to destroy one node in the list.\r
+  @param[in]    Context          Pointer to the callback function's context: corresponds to the\r
+                                 parameter Context in NET_DESTROY_LINK_LIST_CALLBACK.\r
+  @param[out]   ListLength       The length of the link list if the function returns successfully.\r
+\r
+  @retval EFI_SUCCESS            Two complete passes are made with no changes in the number of children.\r
+  @retval EFI_INVALID_PARAMETER  The input parameter is invalid.\r
+  @retval Others                 Return the CallBack's last return value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetDestroyLinkList (\r
+  IN   LIST_ENTRY                       *List,\r
+  IN   NET_DESTROY_LINK_LIST_CALLBACK   CallBack,\r
+  IN   VOID                             *Context,    OPTIONAL\r
+  OUT  UINTN                            *ListLength  OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function checks the input Handle to see if it's one of these handles in ChildHandleBuffer.\r
+\r
+  @param[in]  Handle             Handle to be checked.\r
+  @param[in]  NumberOfChildren   Number of Handles in ChildHandleBuffer.\r
+  @param[in]  ChildHandleBuffer  An array of child handles to be freed. May be NULL\r
+                                 if NumberOfChildren is 0.\r
+\r
+  @retval TRUE                   Found the input Handle in ChildHandleBuffer.\r
+  @retval FALSE                  Can't find the input Handle in ChildHandleBuffer.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetIsInHandleBuffer (\r
+  IN  EFI_HANDLE          Handle,\r
+  IN  UINTN               NumberOfChildren,\r
+  IN  EFI_HANDLE          *ChildHandleBuffer OPTIONAL\r
   );\r
 \r
 //\r
-// Network debug message is sent out as syslog.\r
+// Object container: EFI network stack spec defines various kinds of\r
+// tokens. The drivers can share code to manage those objects.\r
 //\r
-enum {\r
-  NET_SYSLOG_FACILITY       = 16,             // Syslog local facility local use\r
-  NET_SYSLOG_PACKET_LEN     = 512,\r
-  NET_DEBUG_MSG_LEN         = 470,            // 512 - (ether+ip+udp head length)\r
-  NET_SYSLOG_TX_TIMEOUT     = 500 *1000 *10,  // 500ms\r
-};
-#endif
+typedef struct {\r
+  LIST_ENTRY                Link;\r
+  VOID                      *Key;\r
+  VOID                      *Value;\r
+} NET_MAP_ITEM;\r
+\r
+typedef struct {\r
+  LIST_ENTRY                Used;\r
+  LIST_ENTRY                Recycled;\r
+  UINTN                     Count;\r
+} NET_MAP;\r
+\r
+#define NET_MAP_INCREAMENT  64\r
+\r
+/**\r
+  Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.\r
+\r
+  Initialize the forward and backward links of two head nodes donated by Map->Used\r
+  and Map->Recycled of two doubly linked lists.\r
+  Initializes the count of the <Key, Value> pairs in the netmap to zero.\r
+\r
+  If Map is NULL, then ASSERT().\r
+  If the address of Map->Used is NULL, then ASSERT().\r
+  If the address of Map->Recycled is NULl, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to initialize.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetMapInit (\r
+  IN OUT NET_MAP                *Map\r
+  );\r
+\r
+/**\r
+  To clean up the netmap, that is, release allocated memories.\r
+\r
+  Removes all nodes of the Used doubly linked list and frees memory of all related netmap items.\r
+  Removes all nodes of the Recycled doubly linked list and free memory of all related netmap items.\r
+  The number of the <Key, Value> pairs in the netmap is set to zero.\r
+\r
+  If Map is NULL, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to clean up.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetMapClean (\r
+  IN OUT NET_MAP            *Map\r
+  );\r
+\r
+/**\r
+  Test whether the netmap is empty and return true if it is.\r
+\r
+  If the number of the <Key, Value> pairs in the netmap is zero, return TRUE.\r
+\r
+  If Map is NULL, then ASSERT().\r
+\r
+\r
+  @param[in]  Map                   The net map to test.\r
+\r
+  @return TRUE if the netmap is empty, otherwise FALSE.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NetMapIsEmpty (\r
+  IN NET_MAP                *Map\r
+  );\r
+\r
+/**\r
+  Return the number of the <Key, Value> pairs in the netmap.\r
+\r
+  @param[in]  Map                   The netmap to get the entry number.\r
+\r
+  @return The entry number in the netmap.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NetMapGetCount (\r
+  IN NET_MAP                *Map\r
+  );\r
+\r
+/**\r
+  Allocate an item to save the <Key, Value> pair to the head of the netmap.\r
+\r
+  Allocate an item to save the <Key, Value> pair and add corresponding node entry\r
+  to the beginning of the Used doubly linked list. The number of the <Key, Value>\r
+  pairs in the netmap increase by 1.\r
+\r
+  If Map is NULL, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to insert into.\r
+  @param[in]       Key                   The user's key.\r
+  @param[in]       Value                 The user's value for the key.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate the memory for the item.\r
+  @retval EFI_SUCCESS           The item is inserted to the head.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetMapInsertHead (\r
+  IN OUT NET_MAP            *Map,\r
+  IN VOID                   *Key,\r
+  IN VOID                   *Value    OPTIONAL\r
+  );\r
+\r
+/**\r
+  Allocate an item to save the <Key, Value> pair to the tail of the netmap.\r
+\r
+  Allocate an item to save the <Key, Value> pair and add corresponding node entry\r
+  to the tail of the Used doubly linked list. The number of the <Key, Value>\r
+  pairs in the netmap increase by 1.\r
+\r
+  If Map is NULL, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to insert into.\r
+  @param[in]       Key                   The user's key.\r
+  @param[in]       Value                 The user's value for the key.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate the memory for the item.\r
+  @retval EFI_SUCCESS           The item is inserted to the tail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetMapInsertTail (\r
+  IN OUT NET_MAP            *Map,\r
+  IN VOID                   *Key,\r
+  IN VOID                   *Value    OPTIONAL\r
+  );\r
+\r
+/**\r
+  Finds the key in the netmap and returns the point to the item containing the Key.\r
+\r
+  Iterate the Used doubly linked list of the netmap to get every item. Compare the key of every\r
+  item with the key to search. It returns the point to the item contains the Key if found.\r
+\r
+  If Map is NULL, then ASSERT().\r
+\r
+  @param[in]  Map                   The netmap to search within.\r
+  @param[in]  Key                   The key to search.\r
+\r
+  @return The point to the item contains the Key, or NULL if Key isn't in the map.\r
+\r
+**/\r
+NET_MAP_ITEM *\r
+EFIAPI\r
+NetMapFindKey (\r
+  IN  NET_MAP               *Map,\r
+  IN  VOID                  *Key\r
+  );\r
+\r
+/**\r
+  Remove the node entry of the item from the netmap and return the key of the removed item.\r
+\r
+  Remove the node entry of the item from the Used doubly linked list of the netmap.\r
+  The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node\r
+  entry of the item to the Recycled doubly linked list of the netmap. If Value is not NULL,\r
+  Value will point to the value of the item. It returns the key of the removed item.\r
+\r
+  If Map is NULL, then ASSERT().\r
+  If Item is NULL, then ASSERT().\r
+  if item in not in the netmap, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to remove the item from.\r
+  @param[in, out]  Item                  The item to remove.\r
+  @param[out]      Value                 The variable to receive the value if not NULL.\r
+\r
+  @return                                The key of the removed item.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+NetMapRemoveItem (\r
+  IN  OUT NET_MAP             *Map,\r
+  IN  OUT NET_MAP_ITEM        *Item,\r
+  OUT VOID                    **Value           OPTIONAL\r
+  );\r
+\r
+/**\r
+  Remove the first node entry on the netmap and return the key of the removed item.\r
+\r
+  Remove the first node entry from the Used doubly linked list of the netmap.\r
+  The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node\r
+  entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,\r
+  parameter Value will point to the value of the item. It returns the key of the removed item.\r
+\r
+  If Map is NULL, then ASSERT().\r
+  If the Used doubly linked list is empty, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to remove the head from.\r
+  @param[out]      Value                 The variable to receive the value if not NULL.\r
+\r
+  @return                                The key of the item removed.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+NetMapRemoveHead (\r
+  IN OUT NET_MAP            *Map,\r
+  OUT VOID                  **Value         OPTIONAL\r
+  );\r
+\r
+/**\r
+  Remove the last node entry on the netmap and return the key of the removed item.\r
+\r
+  Remove the last node entry from the Used doubly linked list of the netmap.\r
+  The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node\r
+  entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,\r
+  parameter Value will point to the value of the item. It returns the key of the removed item.\r
+\r
+  If Map is NULL, then ASSERT().\r
+  If the Used doubly linked list is empty, then ASSERT().\r
+\r
+  @param[in, out]  Map                   The netmap to remove the tail from.\r
+  @param[out]      Value                 The variable to receive the value if not NULL.\r
+\r
+  @return                                The key of the item removed.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+NetMapRemoveTail (\r
+  IN OUT NET_MAP            *Map,\r
+  OUT VOID                  **Value       OPTIONAL\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *NET_MAP_CALLBACK) (\r
+  IN NET_MAP                *Map,\r
+  IN NET_MAP_ITEM           *Item,\r
+  IN VOID                   *Arg\r
+  );\r
+\r
+/**\r
+  Iterate through the netmap and call CallBack for each item.\r
+\r
+  It will continue the traverse if CallBack returns EFI_SUCCESS, otherwise, break\r
+  from the loop. It returns the CallBack's last return value. This function is\r
+  delete safe for the current item.\r
+\r
+  If Map is NULL, then ASSERT().\r
+  If CallBack is NULL, then ASSERT().\r
+\r
+  @param[in]  Map                   The Map to iterate through.\r
+  @param[in]  CallBack              The callback function to call for each item.\r
+  @param[in]  Arg                   The opaque parameter to the callback.\r
+\r
+  @retval EFI_SUCCESS            There is no item in the netmap, or CallBack for each item\r
+                                 returns EFI_SUCCESS.\r
+  @retval Others                 It returns the CallBack's last return value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetMapIterate (\r
+  IN NET_MAP                *Map,\r
+  IN NET_MAP_CALLBACK       CallBack,\r
+  IN VOID                   *Arg      OPTIONAL\r
+  );\r
+\r
+\r
+//\r
+// Helper functions to implement driver binding and service binding protocols.\r
+//\r
+/**\r
+  Create a child of the service that is identified by ServiceBindingGuid.\r
+\r
+  Get the ServiceBinding Protocol first, then use it to create a child.\r
+\r
+  If ServiceBindingGuid is NULL, then ASSERT().\r
+  If ChildHandle is NULL, then ASSERT().\r
+\r
+  @param[in]       Controller            The controller which has the service installed.\r
+  @param[in]       Image                 The image handle used to open service.\r
+  @param[in]       ServiceBindingGuid    The service's Guid.\r
+  @param[in, out]  ChildHandle           The handle to receive the created child.\r
+\r
+  @retval EFI_SUCCESS           The child was successfully created.\r
+  @retval Others                Failed to create the child.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibCreateServiceChild (\r
+  IN  EFI_HANDLE            Controller,\r
+  IN  EFI_HANDLE            Image,\r
+  IN  EFI_GUID              *ServiceBindingGuid,\r
+  IN  OUT EFI_HANDLE        *ChildHandle\r
+  );\r
+\r
+/**\r
+  Destroy a child of the service that is identified by ServiceBindingGuid.\r
+\r
+  Get the ServiceBinding Protocol first, then use it to destroy a child.\r
+\r
+  If ServiceBindingGuid is NULL, then ASSERT().\r
+\r
+  @param[in]   Controller            The controller which has the service installed.\r
+  @param[in]   Image                 The image handle used to open service.\r
+  @param[in]   ServiceBindingGuid    The service's Guid.\r
+  @param[in]   ChildHandle           The child to destroy.\r
+\r
+  @retval EFI_SUCCESS           The child was destroyed.\r
+  @retval Others                Failed to destroy the child.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibDestroyServiceChild (\r
+  IN  EFI_HANDLE            Controller,\r
+  IN  EFI_HANDLE            Image,\r
+  IN  EFI_GUID              *ServiceBindingGuid,\r
+  IN  EFI_HANDLE            ChildHandle\r
+  );\r
+\r
+/**\r
+  Get handle with Simple Network Protocol installed on it.\r
+\r
+  There should be MNP Service Binding Protocol installed on the input ServiceHandle.\r
+  If Simple Network Protocol is already installed on the ServiceHandle, the\r
+  ServiceHandle will be returned. If SNP is not installed on the ServiceHandle,\r
+  try to find its parent handle with SNP installed.\r
+\r
+  @param[in]   ServiceHandle    The handle where network service binding protocols are\r
+                                installed on.\r
+  @param[out]  Snp              The pointer to store the address of the SNP instance.\r
+                                This is an optional parameter that may be NULL.\r
+\r
+  @return The SNP handle, or NULL if not found.\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+NetLibGetSnpHandle (\r
+  IN   EFI_HANDLE                  ServiceHandle,\r
+  OUT  EFI_SIMPLE_NETWORK_PROTOCOL **Snp  OPTIONAL\r
+  );\r
+\r
+/**\r
+  Retrieve VLAN ID of a VLAN device handle.\r
+\r
+  Search VLAN device path node in Device Path of specified ServiceHandle and\r
+  return its VLAN ID. If no VLAN device path node found, then this ServiceHandle\r
+  is not a VLAN device handle, and 0 will be returned.\r
+\r
+  @param[in]   ServiceHandle    The handle where network service binding protocols are\r
+                                installed on.\r
+\r
+  @return VLAN ID of the device handle, or 0 if not a VLAN device.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetLibGetVlanId (\r
+  IN EFI_HANDLE             ServiceHandle\r
+  );\r
+\r
+/**\r
+  Find VLAN device handle with specified VLAN ID.\r
+\r
+  The VLAN child device handle is created by VLAN Config Protocol on ControllerHandle.\r
+  This function will append VLAN device path node to the parent device path,\r
+  and then use LocateDevicePath() to find the correct VLAN device handle.\r
+\r
+  @param[in]   ControllerHandle The handle where network service binding protocols are\r
+                                installed on.\r
+  @param[in]   VlanId           The configured VLAN ID for the VLAN device.\r
+\r
+  @return The VLAN device handle, or NULL if not found.\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+NetLibGetVlanHandle (\r
+  IN EFI_HANDLE             ControllerHandle,\r
+  IN UINT16                 VlanId\r
+  );\r
+\r
+/**\r
+  Get MAC address associated with the network service handle.\r
+\r
+  There should be MNP Service Binding Protocol installed on the input ServiceHandle.\r
+  If SNP is installed on the ServiceHandle or its parent handle, MAC address will\r
+  be retrieved from SNP. If no SNP found, try to get SNP mode data use MNP.\r
+\r
+  @param[in]   ServiceHandle    The handle where network service binding protocols are\r
+                                installed on.\r
+  @param[out]  MacAddress       The pointer to store the returned MAC address.\r
+  @param[out]  AddressSize      The length of returned MAC address.\r
+\r
+  @retval EFI_SUCCESS           MAC address was returned successfully.\r
+  @retval Others                Failed to get SNP mode data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibGetMacAddress (\r
+  IN  EFI_HANDLE            ServiceHandle,\r
+  OUT EFI_MAC_ADDRESS       *MacAddress,\r
+  OUT UINTN                 *AddressSize\r
+  );\r
+\r
+/**\r
+  Convert MAC address of the NIC associated with specified Service Binding Handle\r
+  to a unicode string. Callers are responsible for freeing the string storage.\r
+\r
+  Locate simple network protocol associated with the Service Binding Handle and\r
+  get the mac address from SNP. Then convert the mac address into a unicode\r
+  string. It takes 2 unicode characters to represent a 1 byte binary buffer.\r
+  Plus one unicode character for the null-terminator.\r
+\r
+  @param[in]   ServiceHandle         The handle where network service binding protocol is\r
+                                     installed.\r
+  @param[in]   ImageHandle           The image handle used to act as the agent handle to\r
+                                     get the simple network protocol. This parameter is\r
+                                     optional and may be NULL.\r
+  @param[out]  MacString             The pointer to store the address of the string\r
+                                     representation of  the mac address.\r
+\r
+  @retval EFI_SUCCESS           Converted the mac address a unicode string successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough memory resources.\r
+  @retval Others                Failed to open the simple network protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibGetMacString (\r
+  IN  EFI_HANDLE            ServiceHandle,\r
+  IN  EFI_HANDLE            ImageHandle, OPTIONAL\r
+  OUT CHAR16                **MacString\r
+  );\r
+\r
+/**\r
+  Detect media status for specified network device.\r
+\r
+  The underlying UNDI driver may or may not support reporting media status from\r
+  GET_STATUS command (PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED). This routine\r
+  will try to invoke Snp->GetStatus() to get the media status. If media is already\r
+  present, it returns directly. If media is not present, it will stop SNP and then\r
+  restart SNP to get the latest media status. This provides an opportunity to get \r
+  the correct media status for old UNDI driver, which doesn't support reporting \r
+  media status from GET_STATUS command.\r
+  Note: there are two limitations for the current algorithm:\r
+  1) For UNDI with this capability, when the cable is not attached, there will\r
+     be an redundant Stop/Start() process.\r
+  2) for UNDI without this capability, in case that network cable is attached when\r
+     Snp->Initialize() is invoked while network cable is unattached later,\r
+     NetLibDetectMedia() will report MediaPresent as TRUE, causing upper layer\r
+     apps to wait for timeout time.\r
+\r
+  @param[in]   ServiceHandle    The handle where network service binding protocols are\r
+                                installed.\r
+  @param[out]  MediaPresent     The pointer to store the media status.\r
+\r
+  @retval EFI_SUCCESS           Media detection success.\r
+  @retval EFI_INVALID_PARAMETER ServiceHandle is not a valid network device handle.\r
+  @retval EFI_UNSUPPORTED       The network device does not support media detection.\r
+  @retval EFI_DEVICE_ERROR      SNP is in an unknown state.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibDetectMedia (\r
+  IN  EFI_HANDLE            ServiceHandle,\r
+  OUT BOOLEAN               *MediaPresent\r
+  );\r
+\r
+/**\r
+  Create an IPv4 device path node.\r
+\r
+  The header type of IPv4 device path node is MESSAGING_DEVICE_PATH.\r
+  The header subtype of IPv4 device path node is MSG_IPv4_DP.\r
+  The length of the IPv4 device path node in bytes is 19.\r
+  Get other information from parameters to make up the whole IPv4 device path node.\r
+\r
+  @param[in, out]  Node                  The pointer to the IPv4 device path node.\r
+  @param[in]       Controller            The controller handle.\r
+  @param[in]       LocalIp               The local IPv4 address.\r
+  @param[in]       LocalPort             The local port.\r
+  @param[in]       RemoteIp              The remote IPv4 address.\r
+  @param[in]       RemotePort            The remote port.\r
+  @param[in]       Protocol              The protocol type in the IP header.\r
+  @param[in]       UseDefaultAddress     Whether this instance is using default address or not.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetLibCreateIPv4DPathNode (\r
+  IN OUT IPv4_DEVICE_PATH  *Node,\r
+  IN EFI_HANDLE            Controller,\r
+  IN IP4_ADDR              LocalIp,\r
+  IN UINT16                LocalPort,\r
+  IN IP4_ADDR              RemoteIp,\r
+  IN UINT16                RemotePort,\r
+  IN UINT16                Protocol,\r
+  IN BOOLEAN               UseDefaultAddress\r
+  );\r
+\r
+/**\r
+  Create an IPv6 device path node.\r
+\r
+  The header type of IPv6 device path node is MESSAGING_DEVICE_PATH.\r
+  The header subtype of IPv6 device path node is MSG_IPv6_DP.\r
+  The length of the IPv6 device path node in bytes is 43.\r
+  Get other information from parameters to make up the whole IPv6 device path node.\r
+\r
+  @param[in, out]  Node                  The pointer to the IPv6 device path node.\r
+  @param[in]       Controller            The controller handle.\r
+  @param[in]       LocalIp               The local IPv6 address.\r
+  @param[in]       LocalPort             The local port.\r
+  @param[in]       RemoteIp              The remote IPv6 address.\r
+  @param[in]       RemotePort            The remote port.\r
+  @param[in]       Protocol              The protocol type in the IP header.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetLibCreateIPv6DPathNode (\r
+  IN OUT IPv6_DEVICE_PATH  *Node,\r
+  IN EFI_HANDLE            Controller,\r
+  IN EFI_IPv6_ADDRESS      *LocalIp,\r
+  IN UINT16                LocalPort,\r
+  IN EFI_IPv6_ADDRESS      *RemoteIp,\r
+  IN UINT16                RemotePort,\r
+  IN UINT16                Protocol\r
+  );\r
+\r
+\r
+/**\r
+  Find the UNDI/SNP handle from controller and protocol GUID.\r
+\r
+  For example, IP will open an MNP child to transmit/receive\r
+  packets. When MNP is stopped, IP should also be stopped. IP\r
+  needs to find its own private data that is related the IP's\r
+  service binding instance that is installed on the UNDI/SNP handle.\r
+  The controller is then either an MNP or an ARP child handle. Note that\r
+  IP opens these handles using BY_DRIVER. Use that information to get the\r
+  UNDI/SNP handle.\r
+\r
+  @param[in]  Controller            The protocol handle to check.\r
+  @param[in]  ProtocolGuid          The protocol that is related with the handle.\r
+\r
+  @return The UNDI/SNP handle or NULL for errors.\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+NetLibGetNicHandle (\r
+  IN EFI_HANDLE             Controller,\r
+  IN EFI_GUID               *ProtocolGuid\r
+  );\r
+\r
+/**\r
+  This is the default unload handle for all the network drivers.\r
+\r
+  Disconnect the driver specified by ImageHandle from all the devices in the handle database.\r
+  Uninstall all the protocols installed in the driver entry point.\r
+\r
+  @param[in]  ImageHandle       The drivers' driver image.\r
+\r
+  @retval EFI_SUCCESS           The image is unloaded.\r
+  @retval Others                Failed to unload the image.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibDefaultUnload (\r
+  IN EFI_HANDLE             ImageHandle\r
+  );\r
+\r
+/**\r
+  Convert one Null-terminated ASCII string (decimal dotted) to EFI_IPv4_ADDRESS.\r
+\r
+  @param[in]      String         The pointer to the Ascii string.\r
+  @param[out]     Ip4Address     The pointer to the converted IPv4 address.\r
+\r
+  @retval EFI_SUCCESS            Converted to an IPv4 address successfully.\r
+  @retval EFI_INVALID_PARAMETER  The string is malformatted, or Ip4Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibAsciiStrToIp4 (\r
+  IN CONST CHAR8                 *String,\r
+  OUT      EFI_IPv4_ADDRESS      *Ip4Address\r
+  );\r
+\r
+/**\r
+  Convert one Null-terminated ASCII string to EFI_IPv6_ADDRESS. The format of the\r
+  string is defined in RFC 4291 - Text Representation of Addresses.\r
+\r
+  @param[in]      String         The pointer to the Ascii string.\r
+  @param[out]     Ip6Address     The pointer to the converted IPv6 address.\r
+\r
+  @retval EFI_SUCCESS            Converted to an IPv6 address successfully.\r
+  @retval EFI_INVALID_PARAMETER  The string is malformatted, or Ip6Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibAsciiStrToIp6 (\r
+  IN CONST CHAR8                 *String,\r
+  OUT      EFI_IPv6_ADDRESS      *Ip6Address\r
+  );\r
+\r
+/**\r
+  Convert one Null-terminated Unicode string (decimal dotted) to EFI_IPv4_ADDRESS.\r
+\r
+  @param[in]      String         The pointer to the Ascii string.\r
+  @param[out]     Ip4Address     The pointer to the converted IPv4 address.\r
+\r
+  @retval EFI_SUCCESS            Converted to an IPv4 address successfully.\r
+  @retval EFI_INVALID_PARAMETER  The string is mal-formatted or Ip4Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibStrToIp4 (\r
+  IN CONST CHAR16                *String,\r
+  OUT      EFI_IPv4_ADDRESS      *Ip4Address\r
+  );\r
+\r
+/**\r
+  Convert one Null-terminated Unicode string to EFI_IPv6_ADDRESS.  The format of\r
+  the string is defined in RFC 4291 - Text Representation of Addresses.\r
+\r
+  @param[in]      String         The pointer to the Ascii string.\r
+  @param[out]     Ip6Address     The pointer to the converted IPv6 address.\r
+\r
+  @retval EFI_SUCCESS            Converted to an IPv6 address successfully.\r
+  @retval EFI_INVALID_PARAMETER  The string is malformatted or Ip6Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibStrToIp6 (\r
+  IN CONST CHAR16                *String,\r
+  OUT      EFI_IPv6_ADDRESS      *Ip6Address\r
+  );\r
+\r
+/**\r
+  Convert one Null-terminated Unicode string to EFI_IPv6_ADDRESS and prefix length.\r
+  The format of the string is defined in RFC 4291 - Text Representation of Addresses\r
+  Prefixes: ipv6-address/prefix-length.\r
+\r
+  @param[in]      String         The pointer to the Ascii string.\r
+  @param[out]     Ip6Address     The pointer to the converted IPv6 address.\r
+  @param[out]     PrefixLength   The pointer to the converted prefix length.\r
+\r
+  @retval EFI_SUCCESS            Converted to an  IPv6 address successfully.\r
+  @retval EFI_INVALID_PARAMETER  The string is malformatted, or Ip6Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibStrToIp6andPrefix (\r
+  IN CONST CHAR16                *String,\r
+  OUT      EFI_IPv6_ADDRESS      *Ip6Address,\r
+  OUT      UINT8                 *PrefixLength\r
+  );\r
+\r
+/**\r
+\r
+  Convert one EFI_IPv6_ADDRESS to Null-terminated Unicode string.\r
+  The text representation of address is defined in RFC 4291.\r
+  \r
+  @param[in]       Ip6Address     The pointer to the IPv6 address.\r
+  @param[out]      String         The buffer to return the converted string.\r
+  @param[in]       StringSize     The length in bytes of the input String.\r
+                                  \r
+  @retval EFI_SUCCESS             Convert to string successfully.\r
+  @retval EFI_INVALID_PARAMETER   The input parameter is invalid.\r
+  @retval EFI_BUFFER_TOO_SMALL    The BufferSize is too small for the result. BufferSize has been \r
+                                  updated with the size needed to complete the request.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibIp6ToStr (\r
+  IN         EFI_IPv6_ADDRESS      *Ip6Address,\r
+  OUT        CHAR16                *String,\r
+  IN         UINTN                 StringSize\r
+  );\r
+\r
+//\r
+// Various signatures\r
+//\r
+#define  NET_BUF_SIGNATURE    SIGNATURE_32 ('n', 'b', 'u', 'f')\r
+#define  NET_VECTOR_SIGNATURE SIGNATURE_32 ('n', 'v', 'e', 'c')\r
+#define  NET_QUE_SIGNATURE    SIGNATURE_32 ('n', 'b', 'q', 'u')\r
+\r
+\r
+#define  NET_PROTO_DATA       64   // Opaque buffer for protocols\r
+#define  NET_BUF_HEAD         1    // Trim or allocate space from head\r
+#define  NET_BUF_TAIL         0    // Trim or allocate space from tail\r
+#define  NET_VECTOR_OWN_FIRST 0x01  // We allocated the 1st block in the vector\r
+\r
+#define NET_CHECK_SIGNATURE(PData, SIGNATURE) \\r
+  ASSERT (((PData) != NULL) && ((PData)->Signature == (SIGNATURE)))\r
+\r
+//\r
+// Single memory block in the vector.\r
+//\r
+typedef struct {\r
+  UINT32              Len;        // The block's length\r
+  UINT8               *Bulk;      // The block's Data\r
+} NET_BLOCK;\r
+\r
+typedef VOID (EFIAPI *NET_VECTOR_EXT_FREE) (VOID *Arg);\r
+\r
+//\r
+//NET_VECTOR contains several blocks to hold all packet's\r
+//fragments and other house-keeping stuff for sharing. It\r
+//doesn't specify the where actual packet fragment begins.\r
+//\r
+typedef struct {\r
+  UINT32              Signature;\r
+  INTN                RefCnt;  // Reference count to share NET_VECTOR.\r
+  NET_VECTOR_EXT_FREE Free;    // external function to free NET_VECTOR\r
+  VOID                *Arg;    // opaque argument to Free\r
+  UINT32              Flag;    // Flags, NET_VECTOR_OWN_FIRST\r
+  UINT32              Len;     // Total length of the associated BLOCKs\r
+\r
+  UINT32              BlockNum;\r
+  NET_BLOCK           Block[1];\r
+} NET_VECTOR;\r
+\r
+//\r
+//NET_BLOCK_OP operates on the NET_BLOCK. It specifies\r
+//where the actual fragment begins and ends\r
+//\r
+typedef struct {\r
+  UINT8               *BlockHead;   // Block's head, or the smallest valid Head\r
+  UINT8               *BlockTail;   // Block's tail. BlockTail-BlockHead=block length\r
+  UINT8               *Head;        // 1st byte of the data in the block\r
+  UINT8               *Tail;        // Tail of the data in the block, Tail-Head=Size\r
+  UINT32              Size;         // The size of the data\r
+} NET_BLOCK_OP;\r
+\r
+typedef union {\r
+  IP4_HEAD          *Ip4;\r
+  EFI_IP6_HEADER    *Ip6;\r
+} NET_IP_HEAD;\r
+\r
+//\r
+//NET_BUF is the buffer manage structure used by the\r
+//network stack. Every network packet may be fragmented. The Vector points to\r
+//memory blocks used by each fragment, and BlockOp\r
+//specifies where each fragment begins and ends.\r
+//\r
+//It also contains an opaque area for the protocol to store\r
+//per-packet information. Protocol must be careful not\r
+//to overwrite the members after that.\r
+//\r
+typedef struct {\r
+  UINT32         Signature;\r
+  INTN           RefCnt;\r
+  LIST_ENTRY     List;                       // The List this NET_BUF is on\r
+\r
+  NET_IP_HEAD    Ip;                         // Network layer header, for fast access\r
+  TCP_HEAD       *Tcp;                       // Transport layer header, for fast access\r
+  EFI_UDP_HEADER *Udp;                       // User Datagram Protocol header\r
+  UINT8          ProtoData [NET_PROTO_DATA]; //Protocol specific data\r
+\r
+  NET_VECTOR     *Vector;                    // The vector containing the packet\r
+\r
+  UINT32         BlockOpNum;                 // Total number of BlockOp in the buffer\r
+  UINT32         TotalSize;                  // Total size of the actual packet\r
+  NET_BLOCK_OP   BlockOp[1];                 // Specify the position of actual packet\r
+} NET_BUF;\r
+\r
+//\r
+//A queue of NET_BUFs. It is a thin extension of\r
+//NET_BUF functions.\r
+//\r
+typedef struct {\r
+  UINT32              Signature;\r
+  INTN                RefCnt;\r
+  LIST_ENTRY          List;       // The List this buffer queue is on\r
+\r
+  LIST_ENTRY          BufList;    // list of queued buffers\r
+  UINT32              BufSize;    // total length of DATA in the buffers\r
+  UINT32              BufNum;     // total number of buffers on the chain\r
+} NET_BUF_QUEUE;\r
+\r
+//\r
+// Pseudo header for TCP and UDP checksum\r
+//\r
+#pragma pack(1)\r
+typedef struct {\r
+  IP4_ADDR            SrcIp;\r
+  IP4_ADDR            DstIp;\r
+  UINT8               Reserved;\r
+  UINT8               Protocol;\r
+  UINT16              Len;\r
+} NET_PSEUDO_HDR;\r
+\r
+typedef struct {\r
+  EFI_IPv6_ADDRESS    SrcIp;\r
+  EFI_IPv6_ADDRESS    DstIp;\r
+  UINT32              Len;\r
+  UINT32              Reserved:24;\r
+  UINT32              NextHeader:8;\r
+} NET_IP6_PSEUDO_HDR;\r
+#pragma pack()\r
+\r
+//\r
+// The fragment entry table used in network interfaces. This is\r
+// the same as NET_BLOCK now. Use two different to distinguish\r
+// the two in case that NET_BLOCK be enhanced later.\r
+//\r
+typedef struct {\r
+  UINT32              Len;\r
+  UINT8               *Bulk;\r
+} NET_FRAGMENT;\r
+\r
+#define NET_GET_REF(PData)      ((PData)->RefCnt++)\r
+#define NET_PUT_REF(PData)      ((PData)->RefCnt--)\r
+#define NETBUF_FROM_PROTODATA(Info) BASE_CR((Info), NET_BUF, ProtoData)\r
+\r
+#define NET_BUF_SHARED(Buf) \\r
+  (((Buf)->RefCnt > 1) || ((Buf)->Vector->RefCnt > 1))\r
+\r
+#define NET_VECTOR_SIZE(BlockNum) \\r
+  (sizeof (NET_VECTOR) + ((BlockNum) - 1) * sizeof (NET_BLOCK))\r
+\r
+#define NET_BUF_SIZE(BlockOpNum)  \\r
+  (sizeof (NET_BUF) + ((BlockOpNum) - 1) * sizeof (NET_BLOCK_OP))\r
+\r
+#define NET_HEADSPACE(BlockOp)  \\r
+  ((UINTN)((BlockOp)->Head) - (UINTN)((BlockOp)->BlockHead))\r
+\r
+#define NET_TAILSPACE(BlockOp)  \\r
+  ((UINTN)((BlockOp)->BlockTail) - (UINTN)((BlockOp)->Tail))\r
+\r
+/**\r
+  Allocate a single block NET_BUF. Upon allocation, all the\r
+  free space is in the tail room.\r
+\r
+  @param[in]  Len              The length of the block.\r
+\r
+  @return                      The pointer to the allocated NET_BUF, or NULL if the\r
+                               allocation failed due to resource limitations.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufAlloc (\r
+  IN UINT32                 Len\r
+  );\r
+\r
+/**\r
+  Free the net buffer and its associated NET_VECTOR.\r
+\r
+  Decrease the reference count of the net buffer by one. Free the associated net\r
+  vector and itself if the reference count of the net buffer is decreased to 0.\r
+  The net vector free operation decreases the reference count of the net\r
+  vector by one, and performs the resource free operation when the reference count\r
+  of the net vector is 0.\r
+\r
+  @param[in]  Nbuf                  The pointer to the NET_BUF to be freed.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufFree (\r
+  IN NET_BUF                *Nbuf\r
+  );\r
+\r
+/**\r
+  Get the index of NET_BLOCK_OP that contains the byte at Offset in the net\r
+  buffer.\r
+\r
+  For example, this function can be used to retrieve the IP header in the packet. It\r
+  also can be used to get the fragment that contains the byte used\r
+  mainly by the library implementation itself.\r
+\r
+  @param[in]   Nbuf      The pointer to the net buffer.\r
+  @param[in]   Offset    The offset of the byte.\r
+  @param[out]  Index     Index of the NET_BLOCK_OP that contains the byte at\r
+                         Offset.\r
+\r
+  @return       The pointer to the Offset'th byte of data in the net buffer, or NULL\r
+                if there is no such data in the net buffer.\r
+\r
+**/\r
+UINT8  *\r
+EFIAPI\r
+NetbufGetByte (\r
+  IN  NET_BUF               *Nbuf,\r
+  IN  UINT32                Offset,\r
+  OUT UINT32                *Index  OPTIONAL\r
+  );\r
+\r
+/**\r
+  Create a copy of the net buffer that shares the associated net vector.\r
+\r
+  The reference count of the newly created net buffer is set to 1. The reference\r
+  count of the associated net vector is increased by one.\r
+\r
+  @param[in]  Nbuf              The pointer to the net buffer to be cloned.\r
+\r
+  @return                       The pointer to the cloned net buffer, or NULL if the\r
+                                allocation failed due to resource limitations.\r
+\r
+**/\r
+NET_BUF *\r
+EFIAPI\r
+NetbufClone (\r
+  IN NET_BUF                *Nbuf\r
+  );\r
+\r
+/**\r
+  Create a duplicated copy of the net buffer with data copied and HeadSpace\r
+  bytes of head space reserved.\r
+\r
+  The duplicated net buffer will allocate its own memory to hold the data of the\r
+  source net buffer.\r
+\r
+  @param[in]       Nbuf         The pointer to the net buffer to be duplicated from.\r
+  @param[in, out]  Duplicate    The pointer to the net buffer to duplicate to. If\r
+                                NULL, a new net buffer is allocated.\r
+  @param[in]      HeadSpace     The length of the head space to reserve.\r
+\r
+  @return                       The pointer to the duplicated net buffer, or NULL if\r
+                                the allocation failed due to resource limitations.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufDuplicate (\r
+  IN NET_BUF                *Nbuf,\r
+  IN OUT NET_BUF            *Duplicate        OPTIONAL,\r
+  IN UINT32                 HeadSpace\r
+  );\r
+\r
+/**\r
+  Create a NET_BUF structure which contains Len byte data of Nbuf starting from\r
+  Offset.\r
+\r
+  A new NET_BUF structure will be created but the associated data in NET_VECTOR\r
+  is shared. This function exists to perform IP packet fragmentation.\r
+\r
+  @param[in]  Nbuf         The pointer to the net buffer to be extracted.\r
+  @param[in]  Offset       Starting point of the data to be included in the new\r
+                           net buffer.\r
+  @param[in]  Len          The bytes of data to be included in the new net buffer.\r
+  @param[in]  HeadSpace    The bytes of the head space to reserve for the protocol header.\r
+\r
+  @return                  The pointer to the cloned net buffer, or NULL if the\r
+                           allocation failed due to resource limitations.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufGetFragment (\r
+  IN NET_BUF                *Nbuf,\r
+  IN UINT32                 Offset,\r
+  IN UINT32                 Len,\r
+  IN UINT32                 HeadSpace\r
+  );\r
+\r
+/**\r
+  Reserve some space in the header room of the net buffer.\r
+\r
+  Upon allocation, all the space is in the tail room of the buffer. Call this\r
+  function to move space to the header room. This function is quite limited\r
+  in that it can only reserve space from the first block of an empty NET_BUF not\r
+  built from the external. However, it should be enough for the network stack.\r
+\r
+  @param[in, out]  Nbuf     The pointer to the net buffer.\r
+  @param[in]       Len      The length of buffer to be reserved from the header.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufReserve (\r
+  IN OUT NET_BUF            *Nbuf,\r
+  IN UINT32                 Len\r
+  );\r
+\r
+/**\r
+  Allocate Len bytes of space from the header or tail of the buffer.\r
+\r
+  @param[in, out]  Nbuf       The pointer to the net buffer.\r
+  @param[in]       Len        The length of the buffer to be allocated.\r
+  @param[in]       FromHead   The flag to indicate whether to reserve the data\r
+                              from head (TRUE) or tail (FALSE).\r
+\r
+  @return                     The pointer to the first byte of the allocated buffer,\r
+                              or NULL, if there is no sufficient space.\r
+\r
+**/\r
+UINT8*\r
+EFIAPI\r
+NetbufAllocSpace (\r
+  IN OUT NET_BUF            *Nbuf,\r
+  IN UINT32                 Len,\r
+  IN BOOLEAN                FromHead\r
+  );\r
+\r
+/**\r
+  Trim Len bytes from the header or the tail of the net buffer.\r
+\r
+  @param[in, out]  Nbuf         The pointer to the net buffer.\r
+  @param[in]       Len          The length of the data to be trimmed.\r
+  @param[in]      FromHead      The flag to indicate whether trim data is from the \r
+                                head (TRUE) or the tail (FALSE).\r
+\r
+  @return    The length of the actual trimmed data, which may be less\r
+             than Len if the TotalSize of Nbuf is less than Len.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetbufTrim (\r
+  IN OUT NET_BUF            *Nbuf,\r
+  IN UINT32                 Len,\r
+  IN BOOLEAN                FromHead\r
+  );\r
+\r
+/**\r
+  Copy Len bytes of data from the specific offset of the net buffer to the\r
+  destination memory.\r
+\r
+  The Len bytes of data may cross several fragments of the net buffer.\r
+\r
+  @param[in]   Nbuf         The pointer to the net buffer.\r
+  @param[in]   Offset       The sequence number of the first byte to copy.\r
+  @param[in]   Len          The length of the data to copy.\r
+  @param[in]   Dest         The destination of the data to copy to.\r
+\r
+  @return           The length of the actual copied data, or 0 if the offset\r
+                    specified exceeds the total size of net buffer.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetbufCopy (\r
+  IN NET_BUF                *Nbuf,\r
+  IN UINT32                 Offset,\r
+  IN UINT32                 Len,\r
+  IN UINT8                  *Dest\r
+  );\r
+\r
+/**\r
+  Build a NET_BUF from external blocks.\r
+\r
+  A new NET_BUF structure will be created from external blocks. An additional block\r
+  of memory will be allocated to hold reserved HeadSpace bytes of header room\r
+  and existing HeadLen bytes of header, but the external blocks are shared by the\r
+  net buffer to avoid data copying.\r
+\r
+  @param[in]  ExtFragment           The pointer to the data block.\r
+  @param[in]  ExtNum                The number of the data blocks.\r
+  @param[in]  HeadSpace             The head space to be reserved.\r
+  @param[in]  HeadLen               The length of the protocol header. The function\r
+                                    pulls this amount of data into a linear block.\r
+  @param[in]  ExtFree               The pointer to the caller-provided free function.\r
+  @param[in]  Arg                   The argument passed to ExtFree when ExtFree is\r
+                                    called.\r
+\r
+  @return                  The pointer to the net buffer built from the data blocks,\r
+                           or NULL if the allocation failed due to resource\r
+                           limit.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufFromExt (\r
+  IN NET_FRAGMENT           *ExtFragment,\r
+  IN UINT32                 ExtNum,\r
+  IN UINT32                 HeadSpace,\r
+  IN UINT32                 HeadLen,\r
+  IN NET_VECTOR_EXT_FREE    ExtFree,\r
+  IN VOID                   *Arg          OPTIONAL\r
+  );\r
+\r
+/**\r
+  Build a fragment table to contain the fragments in the net buffer. This is the\r
+  opposite operation of the NetbufFromExt.\r
+\r
+  @param[in]       Nbuf                  Points to the net buffer.\r
+  @param[in, out]  ExtFragment           The pointer to the data block.\r
+  @param[in, out]  ExtNum                The number of the data blocks.\r
+\r
+  @retval EFI_BUFFER_TOO_SMALL  The number of non-empty blocks is bigger than\r
+                                ExtNum.\r
+  @retval EFI_SUCCESS           The fragment table was built successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetbufBuildExt (\r
+  IN NET_BUF                *Nbuf,\r
+  IN OUT NET_FRAGMENT       *ExtFragment,\r
+  IN OUT UINT32             *ExtNum\r
+  );\r
+\r
+/**\r
+  Build a net buffer from a list of net buffers.\r
+\r
+  All the fragments will be collected from the list of NEW_BUF, and then a new\r
+  net buffer will be created through NetbufFromExt.\r
+\r
+  @param[in]   BufList    A List of the net buffer.\r
+  @param[in]   HeadSpace  The head space to be reserved.\r
+  @param[in]   HeaderLen  The length of the protocol header. The function\r
+                          pulls this amount of data into a linear block.\r
+  @param[in]   ExtFree    The pointer to the caller provided free function.\r
+  @param[in]   Arg        The argument passed to ExtFree when ExtFree is called.\r
+\r
+  @return                 The pointer to the net buffer built from the list of net\r
+                          buffers.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufFromBufList (\r
+  IN LIST_ENTRY             *BufList,\r
+  IN UINT32                 HeadSpace,\r
+  IN UINT32                 HeaderLen,\r
+  IN NET_VECTOR_EXT_FREE    ExtFree,\r
+  IN VOID                   *Arg              OPTIONAL\r
+  );\r
+\r
+/**\r
+  Free a list of net buffers.\r
+\r
+  @param[in, out]  Head              The pointer to the head of linked net buffers.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufFreeList (\r
+  IN OUT LIST_ENTRY         *Head\r
+  );\r
+\r
+/**\r
+  Initiate the net buffer queue.\r
+\r
+  @param[in, out]  NbufQue   The pointer to the net buffer queue to be initialized.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufQueInit (\r
+  IN OUT NET_BUF_QUEUE          *NbufQue\r
+  );\r
+\r
+/**\r
+  Allocate and initialize a net buffer queue.\r
+\r
+  @return         The pointer to the allocated net buffer queue, or NULL if the\r
+                  allocation failed due to resource limit.\r
+\r
+**/\r
+NET_BUF_QUEUE  *\r
+EFIAPI\r
+NetbufQueAlloc (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Free a net buffer queue.\r
+\r
+  Decrease the reference count of the net buffer queue by one. The real resource\r
+  free operation isn't performed until the reference count of the net buffer\r
+  queue is decreased to 0.\r
+\r
+  @param[in]  NbufQue               The pointer to the net buffer queue to be freed.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufQueFree (\r
+  IN NET_BUF_QUEUE          *NbufQue\r
+  );\r
+\r
+/**\r
+  Remove a net buffer from the head in the specific queue and return it.\r
+\r
+  @param[in, out]  NbufQue               The pointer to the net buffer queue.\r
+\r
+  @return           The pointer to the net buffer removed from the specific queue,\r
+                    or NULL if there is no net buffer in the specific queue.\r
+\r
+**/\r
+NET_BUF  *\r
+EFIAPI\r
+NetbufQueRemove (\r
+  IN OUT NET_BUF_QUEUE          *NbufQue\r
+  );\r
+\r
+/**\r
+  Append a net buffer to the net buffer queue.\r
+\r
+  @param[in, out]  NbufQue            The pointer to the net buffer queue.\r
+  @param[in, out]  Nbuf               The pointer to the net buffer to be appended.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufQueAppend (\r
+  IN OUT NET_BUF_QUEUE          *NbufQue,\r
+  IN OUT NET_BUF                *Nbuf\r
+  );\r
+\r
+/**\r
+  Copy Len bytes of data from the net buffer queue at the specific offset to the\r
+  destination memory.\r
+\r
+  The copying operation is the same as NetbufCopy, but applies to the net buffer\r
+  queue instead of the net buffer.\r
+\r
+  @param[in]   NbufQue         The pointer to the net buffer queue.\r
+  @param[in]   Offset          The sequence number of the first byte to copy.\r
+  @param[in]   Len             The length of the data to copy.\r
+  @param[out]  Dest            The destination of the data to copy to.\r
+\r
+  @return       The length of the actual copied data, or 0 if the offset\r
+                specified exceeds the total size of net buffer queue.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetbufQueCopy (\r
+  IN NET_BUF_QUEUE          *NbufQue,\r
+  IN UINT32                 Offset,\r
+  IN UINT32                 Len,\r
+  OUT UINT8                 *Dest\r
+  );\r
+\r
+/**\r
+  Trim Len bytes of data from the buffer queue and free any net buffer\r
+  that is completely trimmed.\r
+\r
+  The trimming operation is the same as NetbufTrim but applies to the net buffer\r
+  queue instead of the net buffer.\r
+\r
+  @param[in, out]  NbufQue               The pointer to the net buffer queue.\r
+  @param[in]       Len                   The length of the data to trim.\r
+\r
+  @return   The actual length of the data trimmed.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+NetbufQueTrim (\r
+  IN OUT NET_BUF_QUEUE      *NbufQue,\r
+  IN UINT32                 Len\r
+  );\r
+\r
+\r
+/**\r
+  Flush the net buffer queue.\r
+\r
+  @param[in, out]  NbufQue               The pointer to the queue to be flushed.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NetbufQueFlush (\r
+  IN OUT NET_BUF_QUEUE          *NbufQue\r
+  );\r
+\r
+/**\r
+  Compute the checksum for a bulk of data.\r
+\r
+  @param[in]   Bulk                  The pointer to the data.\r
+  @param[in]   Len                   The length of the data, in bytes.\r
+\r
+  @return    The computed checksum.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetblockChecksum (\r
+  IN UINT8                  *Bulk,\r
+  IN UINT32                 Len\r
+  );\r
+\r
+/**\r
+  Add two checksums.\r
+\r
+  @param[in]   Checksum1             The first checksum to be added.\r
+  @param[in]   Checksum2             The second checksum to be added.\r
+\r
+  @return         The new checksum.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetAddChecksum (\r
+  IN UINT16                 Checksum1,\r
+  IN UINT16                 Checksum2\r
+  );\r
+\r
+/**\r
+  Compute the checksum for a NET_BUF.\r
+\r
+  @param[in]   Nbuf                  The pointer to the net buffer.\r
+\r
+  @return    The computed checksum.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetbufChecksum (\r
+  IN NET_BUF                *Nbuf\r
+  );\r
+\r
+/**\r
+  Compute the checksum for TCP/UDP pseudo header.\r
+\r
+  Src and Dst are in network byte order, and Len is in host byte order.\r
+\r
+  @param[in]   Src                   The source address of the packet.\r
+  @param[in]   Dst                   The destination address of the packet.\r
+  @param[in]   Proto                 The protocol type of the packet.\r
+  @param[in]   Len                   The length of the packet.\r
+\r
+  @return   The computed checksum.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetPseudoHeadChecksum (\r
+  IN IP4_ADDR               Src,\r
+  IN IP4_ADDR               Dst,\r
+  IN UINT8                  Proto,\r
+  IN UINT16                 Len\r
+  );\r
+\r
+/**\r
+  Compute the checksum for the TCP6/UDP6 pseudo header.\r
+\r
+  Src and Dst are in network byte order, and Len is in host byte order.\r
+\r
+  @param[in]   Src                   The source address of the packet.\r
+  @param[in]   Dst                   The destination address of the packet.\r
+  @param[in]   NextHeader            The protocol type of the packet.\r
+  @param[in]   Len                   The length of the packet.\r
+\r
+  @return   The computed checksum.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+NetIp6PseudoHeadChecksum (\r
+  IN EFI_IPv6_ADDRESS       *Src,\r
+  IN EFI_IPv6_ADDRESS       *Dst,\r
+  IN UINT8                  NextHeader,\r
+  IN UINT32                 Len\r
+  );\r
+\r
+/**\r
+  The function frees the net buffer which allocated by the IP protocol. It releases \r
+  only the net buffer and doesn't call the external free function. \r
+\r
+  This function should be called after finishing the process of mIpSec->ProcessExt() \r
+  for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new \r
+  buffer for the ESP, so there needs a function to free the old net buffer.\r
+\r
+  @param[in]  Nbuf       The network buffer to be freed.\r
+\r
+**/\r
+VOID\r
+NetIpSecNetbufFree (\r
+  NET_BUF   *Nbuf\r
+  );\r
+\r
+/**\r
+  This function obtains the system guid from the smbios table.\r
+\r
+  @param[out]  SystemGuid     The pointer of the returned system guid.\r
+\r
+  @retval EFI_SUCCESS         Successfully obtained the system guid.\r
+  @retval EFI_NOT_FOUND       Did not find the SMBIOS table.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibGetSystemGuid (\r
+  OUT EFI_GUID              *SystemGuid\r
+  );\r
+\r
+/**\r
+  Create Dns QName according the queried domain name. \r
+  QName is a domain name represented as a sequence of labels, \r
+  where each label consists of a length octet followed by that \r
+  number of octets. The QName terminates with the zero \r
+  length octet for the null label of the root. Caller should \r
+  take responsibility to free the buffer in returned pointer.\r
+\r
+  @param  DomainName    The pointer to the queried domain name string.  \r
+\r
+  @retval NULL          Failed to fill QName.\r
+  @return               QName filled successfully.\r
+  \r
+**/ \r
+CHAR8 *\r
+EFIAPI\r
+NetLibCreateDnsQName (\r
+  IN  CHAR16              *DomainName\r
+  );\r
+\r
+#endif\r