"Dec"\r
};\r
\r
+//\r
+// VLAN device path node template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = {\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_VLAN_DP,\r
+ {\r
+ (UINT8) (sizeof (VLAN_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (VLAN_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ 0\r
+};\r
+\r
/**\r
Locate the handles that support SNP, then open one of them\r
to send the syslog packets. The caller isn't required to close\r
return Status;\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
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *SnpInstance;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_HANDLE SnpHandle;\r
+\r
+ //\r
+ // Try to open SNP from ServiceHandle\r
+ //\r
+ SnpInstance = NULL;\r
+ Status = gBS->HandleProtocol (ServiceHandle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &SnpInstance);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Snp != NULL) {\r
+ *Snp = SnpInstance;\r
+ }\r
+ return ServiceHandle;\r
+ }\r
+\r
+ //\r
+ // Failed to open SNP, try to get SNP handle by LocateDevicePath()\r
+ //\r
+ DevicePath = DevicePathFromHandle (ServiceHandle);\r
+ if (DevicePath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ SnpHandle = NULL;\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &DevicePath, &SnpHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Failed to find SNP handle\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (SnpHandle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &SnpInstance);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Snp != NULL) {\r
+ *Snp = SnpInstance;\r
+ }\r
+ return SnpHandle;\r
+ }\r
+\r
+ return NULL;\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
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+\r
+ DevicePath = DevicePathFromHandle (ServiceHandle);\r
+ if (DevicePath == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Node = DevicePath;\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) {\r
+ return ((VLAN_DEVICE_PATH *) Node)->VlanId;\r
+ }\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+\r
+ return 0;\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] ServiceHandle 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
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *VlanDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ VLAN_DEVICE_PATH VlanNode;\r
+ EFI_HANDLE Handle;\r
+\r
+ ParentDevicePath = DevicePathFromHandle (ControllerHandle);\r
+ if (ParentDevicePath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Construct VLAN device path\r
+ //\r
+ CopyMem (&VlanNode, &mNetVlanDevicePathTemplate, sizeof (VLAN_DEVICE_PATH));\r
+ VlanNode.VlanId = VlanId;\r
+ VlanDevicePath = AppendDevicePathNode (\r
+ ParentDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &VlanNode\r
+ );\r
+ if (VlanDevicePath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Find VLAN device handle\r
+ //\r
+ Handle = NULL;\r
+ DevicePath = VlanDevicePath;\r
+ gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &DevicePath,\r
+ &Handle\r
+ );\r
+ if (!IsDevicePathEnd (DevicePath)) {\r
+ //\r
+ // Device path is not exactly match\r
+ //\r
+ Handle = NULL;\r
+ }\r
+\r
+ FreePool (VlanDevicePath);\r
+ return Handle;\r
+}\r
\r
/**\r
- Convert the mac address of the simple network protocol installed on\r
- SnpHandle to a unicode string. Callers are responsible for freeing the\r
- string storage.\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 is 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
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
+ EFI_SIMPLE_NETWORK_MODE SnpModeData;\r
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
+ EFI_SERVICE_BINDING_PROTOCOL *MnpSb;\r
+ EFI_HANDLE *SnpHandle;\r
+ EFI_HANDLE MnpChildHandle;\r
+\r
+ ASSERT (MacAddress != NULL);\r
+ ASSERT (AddressSize != NULL);\r
+\r
+ //\r
+ // Try to get SNP handle\r
+ //\r
+ Snp = NULL;\r
+ SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);\r
+ if (SnpHandle != NULL) {\r
+ //\r
+ // SNP found, use it directly\r
+ //\r
+ SnpMode = Snp->Mode;\r
+ } else {\r
+ //\r
+ // Failed to get SNP handle, try to get MAC address from MNP\r
+ //\r
+ MnpChildHandle = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ ServiceHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ (VOID **) &MnpSb\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- Get the mac address of the Simple Network protocol from the SnpHandle. Then convert\r
- the mac address into a unicode string. It takes 2 unicode characters to represent \r
- a 1 byte binary buffer. Plus one unicode character for the null-terminator.\r
+ //\r
+ // Create a MNP child\r
+ //\r
+ Status = MnpSb->CreateChild (MnpSb, &MnpChildHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open MNP protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ (VOID **) &Mnp\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Try to get SNP mode from MNP\r
+ //\r
+ Status = Mnp->GetModeData (Mnp, NULL, &SnpModeData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ SnpMode = &SnpModeData;\r
+\r
+ //\r
+ // Destroy the MNP child\r
+ //\r
+ MnpSb->DestroyChild (MnpSb, MnpChildHandle);\r
+ }\r
+\r
+ *AddressSize = SnpMode->HwAddressSize;\r
+ CopyMem (MacAddress->Addr, SnpMode->CurrentAddress.Addr, SnpMode->HwAddressSize);\r
\r
+ return EFI_SUCCESS;\r
+}\r
\r
- @param[in] SnpHandle The handle where the simple network protocol is\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 on.\r
@param[in] ImageHandle The image handle used to act as the agent handle to\r
get the simple network protocol.\r
EFI_STATUS\r
EFIAPI\r
NetLibGetMacString (\r
- IN EFI_HANDLE SnpHandle,\r
+ IN EFI_HANDLE ServiceHandle,\r
IN EFI_HANDLE ImageHandle,\r
OUT CHAR16 **MacString\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
- EFI_SIMPLE_NETWORK_MODE *Mode;\r
- CHAR16 *MacAddress;\r
+ EFI_MAC_ADDRESS MacAddress;\r
UINT8 *HwAddress;\r
+ UINTN HwAddressSize;\r
+ UINT16 VlanId;\r
+ CHAR16 *String;\r
UINTN Index;\r
\r
- *MacString = NULL;\r
+ ASSERT (MacString != NULL);\r
\r
//\r
- // Get the Simple Network protocol from the SnpHandle.\r
+ // Get MAC address of the network device\r
//\r
- Status = gBS->OpenProtocol (\r
- SnpHandle,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- (VOID **) &Snp,\r
- ImageHandle,\r
- SnpHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
+ Status = NetLibGetMacAddress (ServiceHandle, &MacAddress, &HwAddressSize);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Mode = Snp->Mode;\r
-\r
//\r
// It takes 2 unicode characters to represent a 1 byte binary buffer.\r
+ // If VLAN is configured, it will need extra 5 characters like "\0005".\r
// Plus one unicode character for the null-terminator.\r
//\r
- MacAddress = AllocatePool ((2 * Mode->HwAddressSize + 1) * sizeof (CHAR16));\r
- if (MacAddress == NULL) {\r
+ String = AllocateZeroPool ((2 * HwAddressSize + 5 + 1) * sizeof (CHAR16));\r
+ if (String == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- *MacString = MacAddress;\r
+ *MacString = String;\r
\r
//\r
- // Convert the mac address into a unicode string.\r
+ // Convert the MAC address into a unicode string.\r
//\r
- HwAddress = Mode->CurrentAddress.Addr;\r
- for (Index = 0; Index < Mode->HwAddressSize; Index++) {\r
- MacAddress += UnicodeValueToString (MacAddress, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2);\r
+ HwAddress = &MacAddress.Addr[0];\r
+ for (Index = 0; Index < HwAddressSize; Index++) {\r
+ String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2);\r
}\r
\r
- MacAddress[Mode->HwAddressSize * 2] = L'\0';\r
+ //\r
+ // Append VLAN ID if any\r
+ //\r
+ VlanId = NetLibGetVlanId (ServiceHandle);\r
+ if (VlanId != 0) {\r
+ *String++ = L'\\';\r
+ String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4);\r
+ }\r
\r
+ //\r
+ // Null terminate the Unicode string\r
+ //\r
+ *String = L'\0';\r
\r
return EFI_SUCCESS;\r
}\r