diff options
Diffstat (limited to 'MdeModulePkg/Library/DxeNetLib')
-rw-r--r-- | MdeModulePkg/Library/DxeNetLib/DxeNetLib.c | 2640 |
1 files changed, 1250 insertions, 1390 deletions
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c index ddcd6c93ec..0eee6076f7 100644 --- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c +++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c @@ -1,85 +1,85 @@ -/** @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.c - -Abstract: - - - -**/ - -#include <PiDxe.h> - -#include <Protocol/ServiceBinding.h> -#include <Protocol/SimpleNetwork.h> -#include <Protocol/LoadedImage.h> -#include <Protocol/NicIp4Config.h> - -#include <Library/NetLib.h> -#include <Library/BaseLib.h> -#include <Library/DebugLib.h> -#include <Library/BaseMemoryLib.h> -#include <Library/UefiBootServicesTableLib.h> -#include <Library/UefiRuntimeServicesTableLib.h> +/** @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.c
+
+Abstract:
+
+
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/NicIp4Config.h>
+
+#include <Library/NetLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
-#include <Library/MemoryAllocationLib.h> - - -// -// All the supported IP4 maskes in host byte order. -// -IP4_ADDR mIp4AllMasks[IP4_MASK_NUM] = { - 0x00000000, - 0x80000000, - 0xC0000000, - 0xE0000000, - 0xF0000000, - 0xF8000000, - 0xFC000000, - 0xFE000000, - - 0xFF000000, - 0xFF800000, - 0xFFC00000, - 0xFFE00000, - 0xFFF00000, - 0xFFF80000, - 0xFFFC0000, - 0xFFFE0000, - - 0xFFFF0000, - 0xFFFF8000, - 0xFFFFC000, - 0xFFFFE000, - 0xFFFFF000, - 0xFFFFF800, - 0xFFFFFC00, - 0xFFFFFE00, - - 0xFFFFFF00, - 0xFFFFFF80, - 0xFFFFFFC0, - 0xFFFFFFE0, - 0xFFFFFFF0, - 0xFFFFFFF8, - 0xFFFFFFFC, - 0xFFFFFFFE, - 0xFFFFFFFF, -}; - -EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}}; - +#include <Library/MemoryAllocationLib.h>
+
+
+//
+// All the supported IP4 maskes in host byte order.
+//
+IP4_ADDR mIp4AllMasks[IP4_MASK_NUM] = {
+ 0x00000000,
+ 0x80000000,
+ 0xC0000000,
+ 0xE0000000,
+ 0xF0000000,
+ 0xF8000000,
+ 0xFC000000,
+ 0xFE000000,
+
+ 0xFF000000,
+ 0xFF800000,
+ 0xFFC00000,
+ 0xFFE00000,
+ 0xFFF00000,
+ 0xFFF80000,
+ 0xFFFC0000,
+ 0xFFFE0000,
+
+ 0xFFFF0000,
+ 0xFFFF8000,
+ 0xFFFFC000,
+ 0xFFFFE000,
+ 0xFFFFF000,
+ 0xFFFFF800,
+ 0xFFFFFC00,
+ 0xFFFFFE00,
+
+ 0xFFFFFF00,
+ 0xFFFFFF80,
+ 0xFFFFFFC0,
+ 0xFFFFFFE0,
+ 0xFFFFFFF0,
+ 0xFFFFFFF8,
+ 0xFFFFFFFC,
+ 0xFFFFFFFE,
+ 0xFFFFFFFF,
+};
+
+EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}};
+
/**
Converts the low nibble of a byte to hex unicode character.
@@ -107,1312 +107,1172 @@ NibbleToHexChar ( return (CHAR16)(Nibble - 0xA + L'A');
}
-/** - Return the length of the mask. If the mask is invalid, - return the invalid length 33, which is IP4_MASK_NUM. - NetMask is in the host byte order. - - @param NetMask The netmask to get the length from - - @return The length of the netmask, IP4_MASK_NUM if the mask isn't - @return supported. - -**/ -INTN -NetGetMaskLength ( - IN IP4_ADDR NetMask - ) -{ - INTN Index; - - for (Index = 0; Index < IP4_MASK_NUM; Index++) { - if (NetMask == mIp4AllMasks[Index]) { - break; - } - } - - return Index; -} - - - -/** - Return the class of the address, such as class a, b, c. - Addr is in host byte order. - - @param Addr The address to get the class from - - @return IP address class, such as IP4_ADDR_CLASSA - -**/ -INTN -NetGetIpClass ( - IN IP4_ADDR Addr - ) -{ - UINT8 ByteOne; - - ByteOne = (UINT8) (Addr >> 24); - - if ((ByteOne & 0x80) == 0) { - return IP4_ADDR_CLASSA; - - } else if ((ByteOne & 0xC0) == 0x80) { - return IP4_ADDR_CLASSB; - - } else if ((ByteOne & 0xE0) == 0xC0) { - return IP4_ADDR_CLASSC; - - } else if ((ByteOne & 0xF0) == 0xE0) { - return IP4_ADDR_CLASSD; - - } else { - return IP4_ADDR_CLASSE; - - } -} - - -/** - Check whether the IP is a valid unicast address according to - the netmask. If NetMask is zero, use the IP address's class to - get the default mask. - - @param Ip The IP to check againist - @param NetMask The mask of the IP - - @return TRUE if IP is a valid unicast address on the network, otherwise FALSE - -**/ -BOOLEAN -Ip4IsUnicast ( - IN IP4_ADDR Ip, - IN IP4_ADDR NetMask - ) -{ - INTN Class; - - Class = NetGetIpClass (Ip); - - if ((Ip == 0) || (Class >= IP4_ADDR_CLASSD)) { - return FALSE; - } - - if (NetMask == 0) { - NetMask = mIp4AllMasks[Class << 3]; - } - - if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) { - return FALSE; - } - - return TRUE; -} - - -/** - Initialize a random seed using current time. - - None - - @return The random seed initialized with current time. - -**/ -UINT32 -NetRandomInitSeed ( - VOID - ) -{ - EFI_TIME Time; - UINT32 Seed; - - gRT->GetTime (&Time, NULL); - Seed = (~Time.Hour << 24 | Time.Second << 16 | Time.Minute << 8 | Time.Day); - Seed ^= Time.Nanosecond; - Seed ^= Time.Year << 7; - - return Seed; -} - - -/** - Extract a UINT32 from a byte stream, then convert it to host - byte order. Use this function to avoid alignment error. - - @param Buf The buffer to extract the UINT32. - - @return The UINT32 extracted. - -**/ -UINT32 -NetGetUint32 ( - IN UINT8 *Buf - ) -{ - UINT32 Value; - - NetCopyMem (&Value, Buf, sizeof (UINT32)); - return NTOHL (Value); -} - - -/** - Put a UINT32 to the byte stream. Convert it from host byte order - to network byte order before putting. - - @param Buf The buffer to put the UINT32 - @param Data The data to put - - @return None - -**/ -VOID -NetPutUint32 ( - IN UINT8 *Buf, - IN UINT32 Data - ) -{ - Data = HTONL (Data); - NetCopyMem (Buf, &Data, sizeof (UINT32)); -} - - -/** - Remove the first entry on the list - - @param Head The list header - - @return The entry that is removed from the list, NULL if the list is empty. - -**/ -NET_LIST_ENTRY * -NetListRemoveHead ( - NET_LIST_ENTRY *Head - ) -{ - NET_LIST_ENTRY *First; - - ASSERT (Head != NULL); - - if (NetListIsEmpty (Head)) { - return NULL; - } - - First = Head->ForwardLink; - Head->ForwardLink = First->ForwardLink; - First->ForwardLink->BackLink = Head; - - DEBUG_CODE ( - First->ForwardLink = (LIST_ENTRY *) NULL; - First->BackLink = (LIST_ENTRY *) NULL; - ); - - return First; -} - - -/** - Remove the last entry on the list - - @param Head The list head - - @return The entry that is removed from the list, NULL if the list is empty. - -**/ -NET_LIST_ENTRY * -NetListRemoveTail ( - NET_LIST_ENTRY *Head - ) -{ - NET_LIST_ENTRY *Last; - - ASSERT (Head != NULL); - - if (NetListIsEmpty (Head)) { - return NULL; - } - - Last = Head->BackLink; - Head->BackLink = Last->BackLink; - Last->BackLink->ForwardLink = Head; - - DEBUG_CODE ( - Last->ForwardLink = (LIST_ENTRY *) NULL; - Last->BackLink = (LIST_ENTRY *) NULL; - ); - - return Last; -} - - -/** - Insert the NewEntry after the PrevEntry - - @param PrevEntry The previous entry to insert after - @param NewEntry The new entry to insert - - @return None - -**/ -VOID -NetListInsertAfter ( - IN NET_LIST_ENTRY *PrevEntry, - IN NET_LIST_ENTRY *NewEntry - ) -{ - NewEntry->BackLink = PrevEntry; - NewEntry->ForwardLink = PrevEntry->ForwardLink; - PrevEntry->ForwardLink->BackLink = NewEntry; - PrevEntry->ForwardLink = NewEntry; -} - - -/** - Insert the NewEntry before the PostEntry - - @param PostEntry The entry to insert before - @param NewEntry The new entry to insert - - @return None - -**/ -VOID -NetListInsertBefore ( - IN NET_LIST_ENTRY *PostEntry, - IN NET_LIST_ENTRY *NewEntry - ) -{ - NewEntry->ForwardLink = PostEntry; - NewEntry->BackLink = PostEntry->BackLink; - PostEntry->BackLink->ForwardLink = NewEntry; - PostEntry->BackLink = NewEntry; -} - - -/** - Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs. - - @param Map The netmap to initialize - - @return None - -**/ -VOID -NetMapInit ( - IN NET_MAP *Map - ) -{ - ASSERT (Map != NULL); - - NetListInit (&Map->Used); - NetListInit (&Map->Recycled); - Map->Count = 0; -} - - -/** - To clean up the netmap, that is, release allocated memories. - - @param Map The netmap to clean up. - - @return None - -**/ -VOID -NetMapClean ( - IN NET_MAP *Map - ) -{ - NET_MAP_ITEM *Item; - NET_LIST_ENTRY *Entry; - NET_LIST_ENTRY *Next; - - ASSERT (Map != NULL); - - NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Used) { - Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); - - NetListRemoveEntry (&Item->Link); - Map->Count--; - - NetFreePool (Item); - } - - ASSERT ((Map->Count == 0) && NetListIsEmpty (&Map->Used)); - - NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Recycled) { - Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); - - NetListRemoveEntry (&Item->Link); - NetFreePool (Item); - } - - ASSERT (NetListIsEmpty (&Map->Recycled)); -} - - -/** - Test whether the netmap is empty - - @param Map The net map to test - - @return TRUE if the netmap is empty, otherwise FALSE. - -**/ -BOOLEAN -NetMapIsEmpty ( - IN NET_MAP *Map - ) -{ - ASSERT (Map != NULL); - return (BOOLEAN) (Map->Count == 0); -} - - -/** - Return the number of the <Key, Value> pairs in the netmap. - - @param Map The netmap to get the entry number - - @return The entry number in the netmap. - -**/ -UINTN -NetMapGetCount ( - IN NET_MAP *Map - ) -{ - return Map->Count; -} - - -/** - Allocate an item for the netmap. It will try to allocate - a batch of items and return one. - - @param Map The netmap to allocate item for - - @return The allocated item or NULL - -**/ -STATIC -NET_MAP_ITEM * -NetMapAllocItem ( - IN NET_MAP *Map - ) -{ - NET_MAP_ITEM *Item; - NET_LIST_ENTRY *Head; - UINTN Index; - - ASSERT (Map != NULL); - - Head = &Map->Recycled; - - if (NetListIsEmpty (Head)) { - for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) { - Item = NetAllocatePool (sizeof (NET_MAP_ITEM)); - - if (Item == NULL) { - if (Index == 0) { - return NULL; - } - - break; - } - - NetListInsertHead (Head, &Item->Link); - } - } - - Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link); - NetListRemoveHead (Head); - - return Item; -} - - -/** - Allocate an item to save the <Key, Value> pair to the head of the netmap. - - @param Map The netmap to insert into - @param Key The user's key - @param Value The user's value for the key - - @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item - @retval EFI_SUCCESS The item is inserted to the head - -**/ -EFI_STATUS -NetMapInsertHead ( - IN NET_MAP *Map, - IN VOID *Key, - IN VOID *Value OPTIONAL - ) -{ - NET_MAP_ITEM *Item; - - ASSERT (Map != NULL); - - Item = NetMapAllocItem (Map); - - if (Item == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Item->Key = Key; - Item->Value = Value; - NetListInsertHead (&Map->Used, &Item->Link); - - Map->Count++; - return EFI_SUCCESS; -} - - -/** - Allocate an item to save the <Key, Value> pair to the tail of the netmap. - - @param Map The netmap to insert into - @param Key The user's key - @param Value The user's value for the key - - @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item - @retval EFI_SUCCESS The item is inserted to the tail - -**/ -EFI_STATUS -NetMapInsertTail ( - IN NET_MAP *Map, - IN VOID *Key, - IN VOID *Value OPTIONAL - ) -{ - NET_MAP_ITEM *Item; - - ASSERT (Map != NULL); - - Item = NetMapAllocItem (Map); - - if (Item == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Item->Key = Key; - Item->Value = Value; - NetListInsertTail (&Map->Used, &Item->Link); - - Map->Count++; - - return EFI_SUCCESS; -} - - -/** - Check whther the item is in the Map - - @param Map The netmap to search within - @param Item The item to search - - @return TRUE if the item is in the netmap, otherwise FALSE. - -**/ -STATIC -BOOLEAN -NetItemInMap ( - IN NET_MAP *Map, - IN NET_MAP_ITEM *Item - ) -{ - NET_LIST_ENTRY *ListEntry; - - NET_LIST_FOR_EACH (ListEntry, &Map->Used) { - if (ListEntry == &Item->Link) { - return TRUE; - } - } - - return FALSE; -} - - -/** - Find the key in the netmap - - @param Map The netmap to search within - @param Key The key to search - - @return The point to the item contains the Key, or NULL if Key isn't in the map. - -**/ -NET_MAP_ITEM * -NetMapFindKey ( - IN NET_MAP *Map, - IN VOID *Key - ) -{ - NET_LIST_ENTRY *Entry; - NET_MAP_ITEM *Item; - - ASSERT (Map != NULL); - - NET_LIST_FOR_EACH (Entry, &Map->Used) { - Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); - - if (Item->Key == Key) { - return Item; - } - } - - return NULL; -} - - -/** - Remove the item from the netmap - - @param Map The netmap to remove the item from - @param Item The item to remove - @param Value The variable to receive the value if not NULL - - @return The key of the removed item. - -**/ -VOID * -NetMapRemoveItem ( - IN NET_MAP *Map, - IN NET_MAP_ITEM *Item, - OUT VOID **Value OPTIONAL - ) -{ - ASSERT ((Map != NULL) && (Item != NULL)); - ASSERT (NetItemInMap (Map, Item)); - - NetListRemoveEntry (&Item->Link); - Map->Count--; - NetListInsertHead (&Map->Recycled, &Item->Link); - - if (Value != NULL) { - *Value = Item->Value; - } - - return Item->Key; -} - - -/** - Remove the first entry on the netmap - - @param Map The netmap to remove the head from - @param Value The variable to receive the value if not NULL - - @return The key of the item removed - -**/ -VOID * -NetMapRemoveHead ( - IN NET_MAP *Map, - OUT VOID **Value OPTIONAL - ) -{ - NET_MAP_ITEM *Item; - - // - // Often, it indicates a programming error to remove - // the first entry in an empty list - // - ASSERT (Map && !NetListIsEmpty (&Map->Used)); - - Item = NET_LIST_HEAD (&Map->Used, NET_MAP_ITEM, Link); - NetListRemoveEntry (&Item->Link); - Map->Count--; - NetListInsertHead (&Map->Recycled, &Item->Link); - - if (Value != NULL) { - *Value = Item->Value; - } - - return Item->Key; -} - - -/** - Remove the last entry on the netmap - - @param Map The netmap to remove the tail from - @param Value The variable to receive the value if not NULL - - @return The key of the item removed - -**/ -VOID * -NetMapRemoveTail ( - IN NET_MAP *Map, - OUT VOID **Value OPTIONAL - ) -{ - NET_MAP_ITEM *Item; - - // - // Often, it indicates a programming error to remove - // the last entry in an empty list - // - ASSERT (Map && !NetListIsEmpty (&Map->Used)); - - Item = NET_LIST_TAIL (&Map->Used, NET_MAP_ITEM, Link); - NetListRemoveEntry (&Item->Link); - Map->Count--; - NetListInsertHead (&Map->Recycled, &Item->Link); - - if (Value != NULL) { - *Value = Item->Value; - } - - return Item->Key; -} - - -/** - Iterate through the netmap and call CallBack for each item. It will - contiue the traverse if CallBack returns EFI_SUCCESS, otherwise, break - from the loop. It returns the CallBack's last return value. This - function is delete safe for the current item. - - @param Map The Map to iterate through - @param CallBack The callback function to call for each item. - @param Arg The opaque parameter to the callback - - @return It returns the CallBack's last return value. - -**/ -EFI_STATUS -NetMapIterate ( - IN NET_MAP *Map, - IN NET_MAP_CALLBACK CallBack, - IN VOID *Arg - ) -{ - - NET_LIST_ENTRY *Entry; - NET_LIST_ENTRY *Next; - NET_LIST_ENTRY *Head; - NET_MAP_ITEM *Item; - EFI_STATUS Result; - - ASSERT ((Map != NULL) && (CallBack != NULL)); - - Head = &Map->Used; - - if (NetListIsEmpty (Head)) { - return EFI_SUCCESS; - } - - NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) { - Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link); - Result = CallBack (Map, Item, Arg); - - if (EFI_ERROR (Result)) { - return Result; - } - } - - return EFI_SUCCESS; -} - - -/** - This is the default unload handle for all the network drivers. - - @param ImageHandle The drivers' driver image. - - @retval EFI_SUCCESS The image is unloaded. - @retval Others Failed to unload the image. - -**/ -EFI_STATUS -EFIAPI -NetLibDefaultUnload ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - EFI_HANDLE *DeviceHandleBuffer; - UINTN DeviceHandleCount; - UINTN Index; - EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; - EFI_COMPONENT_NAME_PROTOCOL *ComponentName; - EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration; - EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics; - - // - // Get the list of all the handles in the handle database. - // If there is an error getting the list, then the unload - // operation fails. - // - Status = gBS->LocateHandleBuffer ( - AllHandles, - NULL, - NULL, - &DeviceHandleCount, - &DeviceHandleBuffer - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Disconnect the driver specified by ImageHandle from all - // the devices in the handle database. - // - for (Index = 0; Index < DeviceHandleCount; Index++) { - Status = gBS->DisconnectController ( - DeviceHandleBuffer[Index], - ImageHandle, - NULL - ); - } - - // - // Uninstall all the protocols installed in the driver entry point - // - for (Index = 0; Index < DeviceHandleCount; Index++) { - Status = gBS->HandleProtocol ( - DeviceHandleBuffer[Index], - &gEfiDriverBindingProtocolGuid, - (VOID **) &DriverBinding - ); - - if (EFI_ERROR (Status)) { - continue; - } - - if (DriverBinding->ImageHandle != ImageHandle) { - continue; - } - - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiDriverBindingProtocolGuid, - DriverBinding - ); - Status = gBS->HandleProtocol ( - DeviceHandleBuffer[Index], - &gEfiComponentNameProtocolGuid, - (VOID **) &ComponentName - ); - if (!EFI_ERROR (Status)) { - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiComponentNameProtocolGuid, - ComponentName - ); - } - - Status = gBS->HandleProtocol ( - DeviceHandleBuffer[Index], - &gEfiDriverConfigurationProtocolGuid, - (VOID **) &DriverConfiguration - ); - - if (!EFI_ERROR (Status)) { - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiDriverConfigurationProtocolGuid, - DriverConfiguration - ); - } - - Status = gBS->HandleProtocol ( - DeviceHandleBuffer[Index], - &gEfiDriverDiagnosticsProtocolGuid, - (VOID **) &DriverDiagnostics - ); - - if (!EFI_ERROR (Status)) { - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiDriverDiagnosticsProtocolGuid, - DriverDiagnostics - ); - } - } - - // - // Free the buffer containing the list of handles from the handle database - // - if (DeviceHandleBuffer != NULL) { - gBS->FreePool (DeviceHandleBuffer); - } - - return EFI_SUCCESS; -} - - - -/** - Create a child of the service that is identified by ServiceBindingGuid. - - @param Controller The controller which has the service installed. - @param Image The image handle used to open service. - @param ServiceBindingGuid The service's Guid. - @param ChildHandle The handle to receive the create child - - @retval EFI_SUCCESS The child is successfully created. - @retval Others Failed to create the child. - -**/ -EFI_STATUS -NetLibCreateServiceChild ( - IN EFI_HANDLE Controller, - IN EFI_HANDLE Image, - IN EFI_GUID *ServiceBindingGuid, - OUT EFI_HANDLE *ChildHandle - ) -{ - EFI_STATUS Status; - EFI_SERVICE_BINDING_PROTOCOL *Service; - - - ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL)); - - // - // Get the ServiceBinding Protocol - // - Status = gBS->OpenProtocol ( - Controller, - ServiceBindingGuid, - (VOID **) &Service, - Image, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Create a child - // - Status = Service->CreateChild (Service, ChildHandle); - return Status; -} - - -/** - Destory a child of the service that is identified by ServiceBindingGuid. - - @param Controller The controller which has the service installed. - @param Image The image handle used to open service. - @param ServiceBindingGuid The service's Guid. - @param ChildHandle The child to destory - - @retval EFI_SUCCESS The child is successfully destoried. - @retval Others Failed to destory the child. - -**/ -EFI_STATUS -NetLibDestroyServiceChild ( - IN EFI_HANDLE Controller, - IN EFI_HANDLE Image, - IN EFI_GUID *ServiceBindingGuid, - IN EFI_HANDLE ChildHandle - ) -{ - EFI_STATUS Status; - EFI_SERVICE_BINDING_PROTOCOL *Service; - - ASSERT (ServiceBindingGuid != NULL); - - // - // Get the ServiceBinding Protocol - // - Status = gBS->OpenProtocol ( - Controller, - ServiceBindingGuid, - (VOID **) &Service, - Image, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // destory the child - // - Status = Service->DestroyChild (Service, ChildHandle); - return Status; -} - - -/** - Convert the mac address of the simple network protocol installed on - SnpHandle to a unicode string. Callers are responsible for freeing the - string storage. - - @param SnpHandle The handle where the simple network protocol is - installed on. - @param ImageHandle The image handle used to act as the agent handle to - get the simple network protocol. - @param MacString The pointer to store the address of the string - representation of the mac address. - - @retval EFI_OUT_OF_RESOURCES There are not enough memory resource. - @retval other Failed to open the simple network protocol. - -**/ -EFI_STATUS -NetLibGetMacString ( - IN EFI_HANDLE SnpHandle, - IN EFI_HANDLE ImageHandle, - IN OUT CHAR16 **MacString - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_PROTOCOL *Snp; - EFI_SIMPLE_NETWORK_MODE *Mode; - CHAR16 *MacAddress; - UINTN Index; - - *MacString = NULL; - - // - // Get the Simple Network protocol from the SnpHandle. - // - Status = gBS->OpenProtocol ( - SnpHandle, - &gEfiSimpleNetworkProtocolGuid, - (VOID **) &Snp, - ImageHandle, - SnpHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Mode = Snp->Mode; - - // - // It takes 2 unicode characters to represent a 1 byte binary buffer. - // Plus one unicode character for the null-terminator. - // - MacAddress = NetAllocatePool ((2 * Mode->HwAddressSize + 1) * sizeof (CHAR16)); - if (MacAddress == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Convert the mac address into a unicode string. - // - for (Index = 0; Index < Mode->HwAddressSize; Index++) { - MacAddress[Index * 2] = NibbleToHexChar ((UINT8) (Mode->CurrentAddress.Addr[Index] >> 4)); - MacAddress[Index * 2 + 1] = NibbleToHexChar (Mode->CurrentAddress.Addr[Index]); - } - - MacAddress[Mode->HwAddressSize * 2] = L'\0'; - - *MacString = MacAddress; - - return EFI_SUCCESS; -} - -/** - Check the default address used by the IPv4 driver is static or dynamic (acquired - from DHCP). - - @param Controller The controller handle which has the NIC Ip4 Config Protocol - relative with the default address to judge. - - @retval TRUE If the default address is static. - @retval FALSE If the default address is acquired from DHCP. - -**/ -STATIC -BOOLEAN -NetLibDefaultAddressIsStatic ( - IN EFI_HANDLE Controller - ) -{ - EFI_STATUS Status; - EFI_NIC_IP4_CONFIG_PROTOCOL *NicIp4; - UINTN Len; - NIC_IP4_CONFIG_INFO *ConfigInfo; - BOOLEAN IsStatic; - - Status = gBS->HandleProtocol ( - Controller, - &gEfiNicIp4ConfigProtocolGuid, - (VOID **) &NicIp4 - ); - if (EFI_ERROR (Status)) { - return TRUE; - } - - Len = 0; - Status = NicIp4->GetInfo (NicIp4, &Len, NULL); - if (Status != EFI_BUFFER_TOO_SMALL) { - return TRUE; - } - - ConfigInfo = NetAllocatePool (Len); - if (ConfigInfo == NULL) { - return TRUE; - } - - IsStatic = TRUE; - Status = NicIp4->GetInfo (NicIp4, &Len, ConfigInfo); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - IsStatic = (BOOLEAN) (ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC); - -ON_EXIT: - - NetFreePool (ConfigInfo); - - return IsStatic; -} - -/** - Create an IPv4 device path node. - - @param Node Pointer to the IPv4 device path node. - @param Controller The handle where the NIC IP4 config protocol resides. - @param LocalIp The local IPv4 address. - @param LocalPort The local port. - @param RemoteIp The remote IPv4 address. - @param RemotePort The remote port. - @param Protocol The protocol type in the IP header. - @param UseDefaultAddress Whether this instance is using default address or not. - - @retval None -**/ -VOID -NetLibCreateIPv4DPathNode ( - IN OUT IPv4_DEVICE_PATH *Node, - IN EFI_HANDLE Controller, - IN IP4_ADDR LocalIp, - IN UINT16 LocalPort, - IN IP4_ADDR RemoteIp, - IN UINT16 RemotePort, - IN UINT16 Protocol, - IN BOOLEAN UseDefaultAddress - ) -{ - Node->Header.Type = MESSAGING_DEVICE_PATH; - Node->Header.SubType = MSG_IPv4_DP; - SetDevicePathNodeLength (&Node->Header, 19); - - NetCopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS)); - NetCopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS)); - - Node->LocalPort = LocalPort; - Node->RemotePort = RemotePort; - - Node->Protocol = Protocol; - - if (!UseDefaultAddress) { - Node->StaticIpAddress = TRUE; - } else { - Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller); - } -} - - -/** - Find the UNDI/SNP handle from controller and protocol GUID. - For example, IP will open a MNP child to transmit/receive - packets, when MNP is stopped, IP should also be stopped. IP - needs to find its own private data which is related the IP's - service binding instance that is install on UNDI/SNP handle. - Now, the controller is either a MNP or ARP child handle. But - IP opens these handle BY_DRIVER, use that info, we can get the - UNDI/SNP handle. - - @param Controller Then protocol handle to check - @param ProtocolGuid The protocol that is related with the handle. - - @return The UNDI/SNP handle or NULL. - -**/ -EFI_HANDLE -NetLibGetNicHandle ( - IN EFI_HANDLE Controller, - IN EFI_GUID *ProtocolGuid - ) -{ - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenBuffer; - EFI_HANDLE Handle; - EFI_STATUS Status; - UINTN OpenCount; - UINTN Index; - - Status = gBS->OpenProtocolInformation ( - Controller, - ProtocolGuid, - &OpenBuffer, - &OpenCount - ); - - if (EFI_ERROR (Status)) { - return NULL; - } - - Handle = NULL; - - for (Index = 0; Index < OpenCount; Index++) { - if (OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { - Handle = OpenBuffer[Index].ControllerHandle; - break; - } - } - - gBS->FreePool (OpenBuffer); - return Handle; -} - -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 - ) -/*++ - -Routine Description: - - Intialize a driver by installing the Driver Binding Protocol onto the - driver's DriverBindingHandle. This is typically the same as the driver's - ImageHandle, but it can be different if the driver produces multiple - DriverBinding Protocols. This function also initializes the EFI Driver - Library that initializes the global variables gST, gBS, gRT. - -Arguments: - - ImageHandle - The image handle of the driver - SystemTable - The EFI System Table that was passed to the driver's - entry point - DriverBinding - A Driver Binding Protocol instance that this driver - is producing. - DriverBindingHandle - The handle that DriverBinding is to be installe onto. - If this parameter is NULL, then a new handle is created. - ComponentName - A Component Name Protocol instance that this driver is - producing. - DriverConfiguration - A Driver Configuration Protocol instance that this - driver is producing. - DriverDiagnostics - A Driver Diagnostics Protocol instance that this - driver is producing. - -Returns: - - EFI_SUCCESS if all the protocols were installed onto DriverBindingHandle - Otherwise, then return status from gBS->InstallProtocolInterface() - ---*/ -{ - return NetLibInstallAllDriverProtocolsWithUnload ( - ImageHandle, - SystemTable, - DriverBinding, - DriverBindingHandle, - ComponentName, - DriverConfiguration, - DriverDiagnostics, - NetLibDefaultUnload - ); -} - -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 Unload - ) -/*++ - -Routine Description: - - Intialize a driver by installing the Driver Binding Protocol onto the - driver's DriverBindingHandle. This is typically the same as the driver's - ImageHandle, but it can be different if the driver produces multiple - DriverBinding Protocols. This function also initializes the EFI Driver - Library that initializes the global variables gST, gBS, gRT. - -Arguments: - - ImageHandle - The image handle of the driver - SystemTable - The EFI System Table that was passed to the driver's - entry point - DriverBinding - A Driver Binding Protocol instance that this driver - is producing. - DriverBindingHandle - The handle that DriverBinding is to be installe onto. - If this parameter is NULL, then a new handle is created. - ComponentName - A Component Name Protocol instance that this driver is - producing. - DriverConfiguration - A Driver Configuration Protocol instance that this - driver is producing. - DriverDiagnostics - A Driver Diagnostics Protocol instance that this - driver is producing. - Unload - The customized unload to install. - -Returns: - - EFI_SUCCESS if all the protocols were installed onto DriverBindingHandle - Otherwise, then return status from gBS->InstallProtocolInterface() - ---*/ -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - - Status = EfiLibInstallAllDriverProtocols ( - ImageHandle, - SystemTable, - DriverBinding, - DriverBindingHandle, - ComponentName, - DriverConfiguration, - DriverDiagnostics - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Retrieve the Loaded Image Protocol from Image Handle - // - Status = gBS->OpenProtocol ( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage, - ImageHandle, - ImageHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Fill in the Unload() service of the Loaded Image Protocol - // - LoadedImage->Unload = (Unload == NULL) ? NetLibDefaultUnload : Unload; - return EFI_SUCCESS; -} - +/**
+ Return the length of the mask. If the mask is invalid,
+ return the invalid length 33, which is IP4_MASK_NUM.
+ NetMask is in the host byte order.
+
+ @param NetMask The netmask to get the length from
+
+ @return The length of the netmask, IP4_MASK_NUM if the mask isn't
+ @return supported.
+
+**/
+INTN
+NetGetMaskLength (
+ IN IP4_ADDR NetMask
+ )
+{
+ INTN Index;
+
+ for (Index = 0; Index < IP4_MASK_NUM; Index++) {
+ if (NetMask == mIp4AllMasks[Index]) {
+ break;
+ }
+ }
+
+ return Index;
+}
+
+
+
+/**
+ Return the class of the address, such as class a, b, c.
+ Addr is in host byte order.
+
+ @param Addr The address to get the class from
+
+ @return IP address class, such as IP4_ADDR_CLASSA
+
+**/
+INTN
+NetGetIpClass (
+ IN IP4_ADDR Addr
+ )
+{
+ UINT8 ByteOne;
+
+ ByteOne = (UINT8) (Addr >> 24);
+
+ if ((ByteOne & 0x80) == 0) {
+ return IP4_ADDR_CLASSA;
+
+ } else if ((ByteOne & 0xC0) == 0x80) {
+ return IP4_ADDR_CLASSB;
+
+ } else if ((ByteOne & 0xE0) == 0xC0) {
+ return IP4_ADDR_CLASSC;
+
+ } else if ((ByteOne & 0xF0) == 0xE0) {
+ return IP4_ADDR_CLASSD;
+
+ } else {
+ return IP4_ADDR_CLASSE;
+
+ }
+}
+
+
+/**
+ Check whether the IP is a valid unicast address according to
+ the netmask. If NetMask is zero, use the IP address's class to
+ get the default mask.
+
+ @param Ip The IP to check againist
+ @param NetMask The mask of the IP
+
+ @return TRUE if IP is a valid unicast address on the network, otherwise FALSE
+
+**/
+BOOLEAN
+Ip4IsUnicast (
+ IN IP4_ADDR Ip,
+ IN IP4_ADDR NetMask
+ )
+{
+ INTN Class;
+
+ Class = NetGetIpClass (Ip);
+
+ if ((Ip == 0) || (Class >= IP4_ADDR_CLASSD)) {
+ return FALSE;
+ }
+
+ if (NetMask == 0) {
+ NetMask = mIp4AllMasks[Class << 3];
+ }
+
+ if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Initialize a random seed using current time.
+
+ None
+
+ @return The random seed initialized with current time.
+
+**/
+UINT32
+NetRandomInitSeed (
+ VOID
+ )
+{
+ EFI_TIME Time;
+ UINT32 Seed;
+
+ gRT->GetTime (&Time, NULL);
+ Seed = (~Time.Hour << 24 | Time.Second << 16 | Time.Minute << 8 | Time.Day);
+ Seed ^= Time.Nanosecond;
+ Seed ^= Time.Year << 7;
+
+ return Seed;
+}
+
+
+/**
+ Extract a UINT32 from a byte stream, then convert it to host
+ byte order. Use this function to avoid alignment error.
+
+ @param Buf The buffer to extract the UINT32.
+
+ @return The UINT32 extracted.
+
+**/
+UINT32
+NetGetUint32 (
+ IN UINT8 *Buf
+ )
+{
+ UINT32 Value;
+
+ NetCopyMem (&Value, Buf, sizeof (UINT32));
+ return NTOHL (Value);
+}
+
+
+/**
+ Put a UINT32 to the byte stream. Convert it from host byte order
+ to network byte order before putting.
+
+ @param Buf The buffer to put the UINT32
+ @param Data The data to put
+
+ @return None
+
+**/
+VOID
+NetPutUint32 (
+ IN UINT8 *Buf,
+ IN UINT32 Data
+ )
+{
+ Data = HTONL (Data);
+ NetCopyMem (Buf, &Data, sizeof (UINT32));
+}
+
+
+/**
+ Remove the first entry on the list
+
+ @param Head The list header
+
+ @return The entry that is removed from the list, NULL if the list is empty.
+
+**/
+NET_LIST_ENTRY *
+NetListRemoveHead (
+ NET_LIST_ENTRY *Head
+ )
+{
+ NET_LIST_ENTRY *First;
+
+ ASSERT (Head != NULL);
+
+ if (NetListIsEmpty (Head)) {
+ return NULL;
+ }
+
+ First = Head->ForwardLink;
+ Head->ForwardLink = First->ForwardLink;
+ First->ForwardLink->BackLink = Head;
+
+ DEBUG_CODE (
+ First->ForwardLink = (LIST_ENTRY *) NULL;
+ First->BackLink = (LIST_ENTRY *) NULL;
+ );
+
+ return First;
+}
+
+
+/**
+ Remove the last entry on the list
+
+ @param Head The list head
+
+ @return The entry that is removed from the list, NULL if the list is empty.
+
+**/
+NET_LIST_ENTRY *
+NetListRemoveTail (
+ NET_LIST_ENTRY *Head
+ )
+{
+ NET_LIST_ENTRY *Last;
+
+ ASSERT (Head != NULL);
+
+ if (NetListIsEmpty (Head)) {
+ return NULL;
+ }
+
+ Last = Head->BackLink;
+ Head->BackLink = Last->BackLink;
+ Last->BackLink->ForwardLink = Head;
+
+ DEBUG_CODE (
+ Last->ForwardLink = (LIST_ENTRY *) NULL;
+ Last->BackLink = (LIST_ENTRY *) NULL;
+ );
+
+ return Last;
+}
+
+
+/**
+ Insert the NewEntry after the PrevEntry
+
+ @param PrevEntry The previous entry to insert after
+ @param NewEntry The new entry to insert
+
+ @return None
+
+**/
+VOID
+NetListInsertAfter (
+ IN NET_LIST_ENTRY *PrevEntry,
+ IN NET_LIST_ENTRY *NewEntry
+ )
+{
+ NewEntry->BackLink = PrevEntry;
+ NewEntry->ForwardLink = PrevEntry->ForwardLink;
+ PrevEntry->ForwardLink->BackLink = NewEntry;
+ PrevEntry->ForwardLink = NewEntry;
+}
+
+
+/**
+ Insert the NewEntry before the PostEntry
+
+ @param PostEntry The entry to insert before
+ @param NewEntry The new entry to insert
+
+ @return None
+
+**/
+VOID
+NetListInsertBefore (
+ IN NET_LIST_ENTRY *PostEntry,
+ IN NET_LIST_ENTRY *NewEntry
+ )
+{
+ NewEntry->ForwardLink = PostEntry;
+ NewEntry->BackLink = PostEntry->BackLink;
+ PostEntry->BackLink->ForwardLink = NewEntry;
+ PostEntry->BackLink = NewEntry;
+}
+
+
+/**
+ Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.
+
+ @param Map The netmap to initialize
+
+ @return None
+
+**/
+VOID
+NetMapInit (
+ IN NET_MAP *Map
+ )
+{
+ ASSERT (Map != NULL);
+
+ NetListInit (&Map->Used);
+ NetListInit (&Map->Recycled);
+ Map->Count = 0;
+}
+
+
+/**
+ To clean up the netmap, that is, release allocated memories.
+
+ @param Map The netmap to clean up.
+
+ @return None
+
+**/
+VOID
+NetMapClean (
+ IN NET_MAP *Map
+ )
+{
+ NET_MAP_ITEM *Item;
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *Next;
+
+ ASSERT (Map != NULL);
+
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Used) {
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
+
+ NetListRemoveEntry (&Item->Link);
+ Map->Count--;
+
+ NetFreePool (Item);
+ }
+
+ ASSERT ((Map->Count == 0) && NetListIsEmpty (&Map->Used));
+
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Recycled) {
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
+
+ NetListRemoveEntry (&Item->Link);
+ NetFreePool (Item);
+ }
+
+ ASSERT (NetListIsEmpty (&Map->Recycled));
+}
+
+
+/**
+ Test whether the netmap is empty
+
+ @param Map The net map to test
+
+ @return TRUE if the netmap is empty, otherwise FALSE.
+
+**/
+BOOLEAN
+NetMapIsEmpty (
+ IN NET_MAP *Map
+ )
+{
+ ASSERT (Map != NULL);
+ return (BOOLEAN) (Map->Count == 0);
+}
+
+
+/**
+ Return the number of the <Key, Value> pairs in the netmap.
+
+ @param Map The netmap to get the entry number
+
+ @return The entry number in the netmap.
+
+**/
+UINTN
+NetMapGetCount (
+ IN NET_MAP *Map
+ )
+{
+ return Map->Count;
+}
+
+
+/**
+ Allocate an item for the netmap. It will try to allocate
+ a batch of items and return one.
+
+ @param Map The netmap to allocate item for
+
+ @return The allocated item or NULL
+
+**/
+STATIC
+NET_MAP_ITEM *
+NetMapAllocItem (
+ IN NET_MAP *Map
+ )
+{
+ NET_MAP_ITEM *Item;
+ NET_LIST_ENTRY *Head;
+ UINTN Index;
+
+ ASSERT (Map != NULL);
+
+ Head = &Map->Recycled;
+
+ if (NetListIsEmpty (Head)) {
+ for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) {
+ Item = NetAllocatePool (sizeof (NET_MAP_ITEM));
+
+ if (Item == NULL) {
+ if (Index == 0) {
+ return NULL;
+ }
+
+ break;
+ }
+
+ NetListInsertHead (Head, &Item->Link);
+ }
+ }
+
+ Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link);
+ NetListRemoveHead (Head);
+
+ return Item;
+}
+
+
+/**
+ Allocate an item to save the <Key, Value> pair to the head of the netmap.
+
+ @param Map The netmap to insert into
+ @param Key The user's key
+ @param Value The user's value for the key
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
+ @retval EFI_SUCCESS The item is inserted to the head
+
+**/
+EFI_STATUS
+NetMapInsertHead (
+ IN NET_MAP *Map,
+ IN VOID *Key,
+ IN VOID *Value OPTIONAL
+ )
+{
+ NET_MAP_ITEM *Item;
+
+ ASSERT (Map != NULL);
+
+ Item = NetMapAllocItem (Map);
+
+ if (Item == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Item->Key = Key;
+ Item->Value = Value;
+ NetListInsertHead (&Map->Used, &Item->Link);
+
+ Map->Count++;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allocate an item to save the <Key, Value> pair to the tail of the netmap.
+
+ @param Map The netmap to insert into
+ @param Key The user's key
+ @param Value The user's value for the key
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
+ @retval EFI_SUCCESS The item is inserted to the tail
+
+**/
+EFI_STATUS
+NetMapInsertTail (
+ IN NET_MAP *Map,
+ IN VOID *Key,
+ IN VOID *Value OPTIONAL
+ )
+{
+ NET_MAP_ITEM *Item;
+
+ ASSERT (Map != NULL);
+
+ Item = NetMapAllocItem (Map);
+
+ if (Item == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Item->Key = Key;
+ Item->Value = Value;
+ NetListInsertTail (&Map->Used, &Item->Link);
+
+ Map->Count++;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Check whther the item is in the Map
+
+ @param Map The netmap to search within
+ @param Item The item to search
+
+ @return TRUE if the item is in the netmap, otherwise FALSE.
+
+**/
+STATIC
+BOOLEAN
+NetItemInMap (
+ IN NET_MAP *Map,
+ IN NET_MAP_ITEM *Item
+ )
+{
+ NET_LIST_ENTRY *ListEntry;
+
+ NET_LIST_FOR_EACH (ListEntry, &Map->Used) {
+ if (ListEntry == &Item->Link) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Find the key in the netmap
+
+ @param Map The netmap to search within
+ @param Key The key to search
+
+ @return The point to the item contains the Key, or NULL if Key isn't in the map.
+
+**/
+NET_MAP_ITEM *
+NetMapFindKey (
+ IN NET_MAP *Map,
+ IN VOID *Key
+ )
+{
+ NET_LIST_ENTRY *Entry;
+ NET_MAP_ITEM *Item;
+
+ ASSERT (Map != NULL);
+
+ NET_LIST_FOR_EACH (Entry, &Map->Used) {
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
+
+ if (Item->Key == Key) {
+ return Item;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ Remove the item from the netmap
+
+ @param Map The netmap to remove the item from
+ @param Item The item to remove
+ @param Value The variable to receive the value if not NULL
+
+ @return The key of the removed item.
+
+**/
+VOID *
+NetMapRemoveItem (
+ IN NET_MAP *Map,
+ IN NET_MAP_ITEM *Item,
+ OUT VOID **Value OPTIONAL
+ )
+{
+ ASSERT ((Map != NULL) && (Item != NULL));
+ ASSERT (NetItemInMap (Map, Item));
+
+ NetListRemoveEntry (&Item->Link);
+ Map->Count--;
+ NetListInsertHead (&Map->Recycled, &Item->Link);
+
+ if (Value != NULL) {
+ *Value = Item->Value;
+ }
+
+ return Item->Key;
+}
+
+
+/**
+ Remove the first entry on the netmap
+
+ @param Map The netmap to remove the head from
+ @param Value The variable to receive the value if not NULL
+
+ @return The key of the item removed
+
+**/
+VOID *
+NetMapRemoveHead (
+ IN NET_MAP *Map,
+ OUT VOID **Value OPTIONAL
+ )
+{
+ NET_MAP_ITEM *Item;
+
+ //
+ // Often, it indicates a programming error to remove
+ // the first entry in an empty list
+ //
+ ASSERT (Map && !NetListIsEmpty (&Map->Used));
+
+ Item = NET_LIST_HEAD (&Map->Used, NET_MAP_ITEM, Link);
+ NetListRemoveEntry (&Item->Link);
+ Map->Count--;
+ NetListInsertHead (&Map->Recycled, &Item->Link);
+
+ if (Value != NULL) {
+ *Value = Item->Value;
+ }
+
+ return Item->Key;
+}
+
+
+/**
+ Remove the last entry on the netmap
+
+ @param Map The netmap to remove the tail from
+ @param Value The variable to receive the value if not NULL
+
+ @return The key of the item removed
+
+**/
+VOID *
+NetMapRemoveTail (
+ IN NET_MAP *Map,
+ OUT VOID **Value OPTIONAL
+ )
+{
+ NET_MAP_ITEM *Item;
+
+ //
+ // Often, it indicates a programming error to remove
+ // the last entry in an empty list
+ //
+ ASSERT (Map && !NetListIsEmpty (&Map->Used));
+
+ Item = NET_LIST_TAIL (&Map->Used, NET_MAP_ITEM, Link);
+ NetListRemoveEntry (&Item->Link);
+ Map->Count--;
+ NetListInsertHead (&Map->Recycled, &Item->Link);
+
+ if (Value != NULL) {
+ *Value = Item->Value;
+ }
+
+ return Item->Key;
+}
+
+
+/**
+ Iterate through the netmap and call CallBack for each item. It will
+ contiue the traverse if CallBack returns EFI_SUCCESS, otherwise, break
+ from the loop. It returns the CallBack's last return value. This
+ function is delete safe for the current item.
+
+ @param Map The Map to iterate through
+ @param CallBack The callback function to call for each item.
+ @param Arg The opaque parameter to the callback
+
+ @return It returns the CallBack's last return value.
+
+**/
+EFI_STATUS
+NetMapIterate (
+ IN NET_MAP *Map,
+ IN NET_MAP_CALLBACK CallBack,
+ IN VOID *Arg
+ )
+{
+
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *Next;
+ NET_LIST_ENTRY *Head;
+ NET_MAP_ITEM *Item;
+ EFI_STATUS Result;
+
+ ASSERT ((Map != NULL) && (CallBack != NULL));
+
+ Head = &Map->Used;
+
+ if (NetListIsEmpty (Head)) {
+ return EFI_SUCCESS;
+ }
+
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
+ Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
+ Result = CallBack (Map, Item, Arg);
+
+ if (EFI_ERROR (Result)) {
+ return Result;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This is the default unload handle for all the network drivers.
+
+ @param ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibDefaultUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *DeviceHandleBuffer;
+ UINTN DeviceHandleCount;
+ UINTN Index;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+ EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration;
+ EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics;
+
+ //
+ // Get the list of all the handles in the handle database.
+ // If there is an error getting the list, then the unload
+ // operation fails.
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &DeviceHandleCount,
+ &DeviceHandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Disconnect the driver specified by ImageHandle from all
+ // the devices in the handle database.
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index],
+ ImageHandle,
+ NULL
+ );
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (DriverBinding->ImageHandle != ImageHandle) {
+ continue;
+ }
+
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ DriverBinding
+ );
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiComponentNameProtocolGuid,
+ (VOID **) &ComponentName
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiComponentNameProtocolGuid,
+ ComponentName
+ );
+ }
+
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiDriverConfigurationProtocolGuid,
+ (VOID **) &DriverConfiguration
+ );
+
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDriverConfigurationProtocolGuid,
+ DriverConfiguration
+ );
+ }
+
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiDriverDiagnosticsProtocolGuid,
+ (VOID **) &DriverDiagnostics
+ );
+
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDriverDiagnosticsProtocolGuid,
+ DriverDiagnostics
+ );
+ }
+ }
+
+ //
+ // Free the buffer containing the list of handles from the handle database
+ //
+ if (DeviceHandleBuffer != NULL) {
+ gBS->FreePool (DeviceHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Create a child of the service that is identified by ServiceBindingGuid.
+
+ @param Controller The controller which has the service installed.
+ @param Image The image handle used to open service.
+ @param ServiceBindingGuid The service's Guid.
+ @param ChildHandle The handle to receive the create child
+
+ @retval EFI_SUCCESS The child is successfully created.
+ @retval Others Failed to create the child.
+
+**/
+EFI_STATUS
+NetLibCreateServiceChild (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ IN EFI_GUID *ServiceBindingGuid,
+ OUT EFI_HANDLE *ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *Service;
+
+
+ ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL));
+
+ //
+ // Get the ServiceBinding Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ ServiceBindingGuid,
+ (VOID **) &Service,
+ Image,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create a child
+ //
+ Status = Service->CreateChild (Service, ChildHandle);
+ return Status;
+}
+
+
+/**
+ Destory a child of the service that is identified by ServiceBindingGuid.
+
+ @param Controller The controller which has the service installed.
+ @param Image The image handle used to open service.
+ @param ServiceBindingGuid The service's Guid.
+ @param ChildHandle The child to destory
+
+ @retval EFI_SUCCESS The child is successfully destoried.
+ @retval Others Failed to destory the child.
+
+**/
+EFI_STATUS
+NetLibDestroyServiceChild (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ IN EFI_GUID *ServiceBindingGuid,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *Service;
+
+ ASSERT (ServiceBindingGuid != NULL);
+
+ //
+ // Get the ServiceBinding Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ ServiceBindingGuid,
+ (VOID **) &Service,
+ Image,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // destory the child
+ //
+ Status = Service->DestroyChild (Service, ChildHandle);
+ return Status;
+}
+
+
+/**
+ Convert the mac address of the simple network protocol installed on
+ SnpHandle to a unicode string. Callers are responsible for freeing the
+ string storage.
+
+ @param SnpHandle The handle where the simple network protocol is
+ installed on.
+ @param ImageHandle The image handle used to act as the agent handle to
+ get the simple network protocol.
+ @param MacString The pointer to store the address of the string
+ representation of the mac address.
+
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resource.
+ @retval other Failed to open the simple network protocol.
+
+**/
+EFI_STATUS
+NetLibGetMacString (
+ IN EFI_HANDLE SnpHandle,
+ IN EFI_HANDLE ImageHandle,
+ IN OUT CHAR16 **MacString
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ CHAR16 *MacAddress;
+ UINTN Index;
+
+ *MacString = NULL;
+
+ //
+ // Get the Simple Network protocol from the SnpHandle.
+ //
+ Status = gBS->OpenProtocol (
+ SnpHandle,
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &Snp,
+ ImageHandle,
+ SnpHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Mode = Snp->Mode;
+
+ //
+ // It takes 2 unicode characters to represent a 1 byte binary buffer.
+ // Plus one unicode character for the null-terminator.
+ //
+ MacAddress = NetAllocatePool ((2 * Mode->HwAddressSize + 1) * sizeof (CHAR16));
+ if (MacAddress == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Convert the mac address into a unicode string.
+ //
+ for (Index = 0; Index < Mode->HwAddressSize; Index++) {
+ MacAddress[Index * 2] = NibbleToHexChar ((UINT8) (Mode->CurrentAddress.Addr[Index] >> 4));
+ MacAddress[Index * 2 + 1] = NibbleToHexChar (Mode->CurrentAddress.Addr[Index]);
+ }
+
+ MacAddress[Mode->HwAddressSize * 2] = L'\0';
+
+ *MacString = MacAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the default address used by the IPv4 driver is static or dynamic (acquired
+ from DHCP).
+
+ @param Controller The controller handle which has the NIC Ip4 Config Protocol
+ relative with the default address to judge.
+
+ @retval TRUE If the default address is static.
+ @retval FALSE If the default address is acquired from DHCP.
+
+**/
+STATIC
+BOOLEAN
+NetLibDefaultAddressIsStatic (
+ IN EFI_HANDLE Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_NIC_IP4_CONFIG_PROTOCOL *NicIp4;
+ UINTN Len;
+ NIC_IP4_CONFIG_INFO *ConfigInfo;
+ BOOLEAN IsStatic;
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiNicIp4ConfigProtocolGuid,
+ (VOID **) &NicIp4
+ );
+ if (EFI_ERROR (Status)) {
+ return TRUE;
+ }
+
+ Len = 0;
+ Status = NicIp4->GetInfo (NicIp4, &Len, NULL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return TRUE;
+ }
+
+ ConfigInfo = NetAllocatePool (Len);
+ if (ConfigInfo == NULL) {
+ return TRUE;
+ }
+
+ IsStatic = TRUE;
+ Status = NicIp4->GetInfo (NicIp4, &Len, ConfigInfo);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ IsStatic = (BOOLEAN) (ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC);
+
+ON_EXIT:
+
+ NetFreePool (ConfigInfo);
+
+ return IsStatic;
+}
+
+/**
+ Create an IPv4 device path node.
+
+ @param Node Pointer to the IPv4 device path node.
+ @param Controller The handle where the NIC IP4 config protocol resides.
+ @param LocalIp The local IPv4 address.
+ @param LocalPort The local port.
+ @param RemoteIp The remote IPv4 address.
+ @param RemotePort The remote port.
+ @param Protocol The protocol type in the IP header.
+ @param UseDefaultAddress Whether this instance is using default address or not.
+
+ @retval None
+**/
+VOID
+NetLibCreateIPv4DPathNode (
+ IN OUT IPv4_DEVICE_PATH *Node,
+ IN EFI_HANDLE Controller,
+ IN IP4_ADDR LocalIp,
+ IN UINT16 LocalPort,
+ IN IP4_ADDR RemoteIp,
+ IN UINT16 RemotePort,
+ IN UINT16 Protocol,
+ IN BOOLEAN UseDefaultAddress
+ )
+{
+ Node->Header.Type = MESSAGING_DEVICE_PATH;
+ Node->Header.SubType = MSG_IPv4_DP;
+ SetDevicePathNodeLength (&Node->Header, 19);
+
+ NetCopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS));
+ NetCopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS));
+
+ Node->LocalPort = LocalPort;
+ Node->RemotePort = RemotePort;
+
+ Node->Protocol = Protocol;
+
+ if (!UseDefaultAddress) {
+ Node->StaticIpAddress = TRUE;
+ } else {
+ Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller);
+ }
+}
+
+
+/**
+ Find the UNDI/SNP handle from controller and protocol GUID.
+ For example, IP will open a MNP child to transmit/receive
+ packets, when MNP is stopped, IP should also be stopped. IP
+ needs to find its own private data which is related the IP's
+ service binding instance that is install on UNDI/SNP handle.
+ Now, the controller is either a MNP or ARP child handle. But
+ IP opens these handle BY_DRIVER, use that info, we can get the
+ UNDI/SNP handle.
+
+ @param Controller Then protocol handle to check
+ @param ProtocolGuid The protocol that is related with the handle.
+
+ @return The UNDI/SNP handle or NULL.
+
+**/
+EFI_HANDLE
+NetLibGetNicHandle (
+ IN EFI_HANDLE Controller,
+ IN EFI_GUID *ProtocolGuid
+ )
+{
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenBuffer;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN OpenCount;
+ UINTN Index;
+
+ Status = gBS->OpenProtocolInformation (
+ Controller,
+ ProtocolGuid,
+ &OpenBuffer,
+ &OpenCount
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Handle = NULL;
+
+ for (Index = 0; Index < OpenCount; Index++) {
+ if (OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ Handle = OpenBuffer[Index].ControllerHandle;
+ break;
+ }
+ }
+
+ gBS->FreePool (OpenBuffer);
+ return Handle;
+}
+
|