-extern IP4_ADDR mIp4AllMasks [IP4_MASK_NUM];
-
-
-extern EFI_IPv4_ADDRESS mZeroIp4Addr;
-
-#define NET_IS_DIGIT(Ch) (('0' <= (Ch)) && ((Ch) <= '9'))
-//
-// 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
- );
-
-//\r
-// The debug level definition. This value is also used as the\r
-// syslog's servity 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
-\r
-#ifdef EFI_NETWORK_STACK_DEBUG\r
-\r
-//\r
-// The debug output expects the ASCII format string, Use %a to print ASCII\r
-// string, and %s to print UNICODE string. PrintArg must be enclosed in ().\r
-// For example: NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name));\r
-//\r
-#define NET_DEBUG_TRACE(Module, PrintArg) \\r
- NetDebugOutput ( \\r
- NETDEBUG_LEVEL_TRACE, \\r
- Module, \\r
- __FILE__, \\r
- __LINE__, \\r
- NetDebugASPrint PrintArg \\r
- )\r
-\r
-#define NET_DEBUG_WARNING(Module, PrintArg) \\r
- NetDebugOutput ( \\r
- NETDEBUG_LEVEL_WARNING, \\r
- Module, \\r
- __FILE__, \\r
- __LINE__, \\r
- NetDebugASPrint PrintArg \\r
- )\r
-\r
-#define NET_DEBUG_ERROR(Module, PrintArg) \\r
- NetDebugOutput ( \\r
- NETDEBUG_LEVEL_ERROR, \\r
- Module, \\r
- __FILE__, \\r
- __LINE__, \\r
- 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
+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_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, and then copies it to the \r
+ byte stream.\r
+\r
+ @param[in, out] Buf The buffer to put the UINT32.\r
+ @param[in] Data The data to put.\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.\r
+ \r
+ Get current time first. Then initialize a random seed based on some basic \r
+ mathematical operations on the hour, day, minute, second, nanosecond and year \r
+ of the current time.\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
+//\r
+// Object container: EFI network stack spec defines various kinds of\r
+// tokens. The drivers can share code to manage those objects.\r
+//\r
+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