V2: * Return error status code directly when Aip protocol falied to detect media rather than wait for another time's check. * Set media state default value to EFI_SUCCESS since some platforms may not support retrieving media state from Aip protocol.
Cc: Fu Siyuan <siyuan...@intel.com> Cc: Ye Ting <ting...@intel.com> Cc: Jiaxin Wu <jiaxin...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wang Fan <fan.w...@intel.com> --- MdeModulePkg/Include/Library/NetLib.h | 40 +++++++ MdeModulePkg/Library/DxeNetLib/DxeNetLib.c | 163 +++++++++++++++++++++++++++ MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf | 2 + 3 files changed, 205 insertions(+) diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h index b9df46c..7862df9 100644 --- a/MdeModulePkg/Include/Library/NetLib.h +++ b/MdeModulePkg/Include/Library/NetLib.h @@ -93,10 +93,16 @@ typedef UINT16 TCP_PORTNO; #define DNS_CLASS_INET 1 #define DNS_CLASS_CH 3 #define DNS_CLASS_HS 4 #define DNS_CLASS_ANY 255 +// +// Number of 100ns units time Interval for network media state detect +// +#define MEDIA_STATE_DETECT_TIME_INTERVAL 1000000U + + #pragma pack(1) // // Ethernet head definition // @@ -1246,10 +1252,44 @@ NetLibDetectMedia ( IN EFI_HANDLE ServiceHandle, OUT BOOLEAN *MediaPresent ); /** + + Detect media state for a network device. This routine will wait for a period of time at + a specified checking interval when a certain network is under connecting until connection + process finishes or timeout. If Aip protocol is supported by low layer drivers, three kinds + of media states can be detected: EFI_SUCCESS, EFI_NOT_READY and EFI_NO_MEDIA, represents + connected state, connecting state and no media state respectively. When function detects + the current state is EFI_NOT_READY, it will loop to wait for next time's check until state + turns to be EFI_SUCCESS or EFI_NO_MEDIA. If Aip protocol is not supported, function will + call NetLibDetectMedia() and return state directly. + + @param[in] ServiceHandle The handle where network service binding protocols are + installed on. + @param[in] Timeout The maximum number of 100ns units to wait when network + is connecting. Zero value means detect once and return + immediately. + @param[out] MediaState The pointer to the detected media state. + + @retval EFI_SUCCESS Media detection success. + @retval EFI_INVALID_PARAMETER ServiceHandle is not a valid network device handle or + MediaState pointer is NULL. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_TIMEOUT Network is connecting but timeout. + +**/ +EFI_STATUS +EFIAPI +NetLibDetectMediaWaitTimeout ( + IN EFI_HANDLE ServiceHandle, + IN UINT64 Timeout, + OUT EFI_STATUS *MediaState + ); + + +/** Create an IPv4 device path node. The header type of IPv4 device path node is MESSAGING_DEVICE_PATH. The header subtype of IPv4 device path node is MSG_IPv4_DP. The length of the IPv4 device path node in bytes is 19. diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c index b8544b8..1bfa33d 100644 --- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c +++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c @@ -17,10 +17,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include <IndustryStandard/SmBios.h> #include <Protocol/DriverBinding.h> #include <Protocol/ServiceBinding.h> #include <Protocol/SimpleNetwork.h> +#include <Protocol/AdapterInformation.h> #include <Protocol/ManagedNetwork.h> #include <Protocol/Ip4Config2.h> #include <Protocol/ComponentName.h> #include <Protocol/ComponentName2.h> @@ -2501,10 +2502,172 @@ Exit: return Status; } /** + + Detect media state for a network device. This routine will wait for a period of time at + a specified checking interval when a certain network is under connecting until connection + process finishs or timeout. If Aip protocol is supported by low layer drivers, three kinds + of media states can be detected: EFI_SUCCESS, EFI_NOT_READY and EFI_NO_MEDIA, represents + connected state, connecting state and no media state respectively. When function detects + the current state is EFI_NOT_READY, it will loop to wait for next time's check until state + turns to be EFI_SUCCESS or EFI_NO_MEDIA. If Aip protocol is not supported, function will + call NetLibDetectMedia() and return state directly. + + @param[in] ServiceHandle The handle where network service binding protocols are + installed on. + @param[in] Timeout The maximum number of 100ns units to wait when network + is connecting. Zero value means detect once and return + immediately. + @param[out] MediaState The pointer to the detected media state. + + @retval EFI_SUCCESS Media detection success. + @retval EFI_INVALID_PARAMETER ServiceHandle is not a valid network device handle or + MediaState pointer is NULL. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_TIMEOUT Network is connecting but timeout. + +**/ + +EFI_STATUS +EFIAPI +NetLibDetectMediaWaitTimeout ( + IN EFI_HANDLE ServiceHandle, + IN UINT64 Timeout, + OUT EFI_STATUS *MediaState + ) +{ + EFI_STATUS Status; + EFI_HANDLE SnpHandle; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + EFI_ADAPTER_INFO_MEDIA_STATE *MediaInfo; + BOOLEAN MediaPresent; + UINTN DataSize; + EFI_STATUS TimerStatus; + EFI_EVENT Timer; + UINT64 TimeRemained; + + if (MediaState == NULL) { + return EFI_INVALID_PARAMETER; + } + *MediaState = EFI_SUCCESS; + MediaInfo = NULL; + + // + // Get SNP handle + // + Snp = NULL; + SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp); + if (SnpHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->HandleProtocol ( + SnpHandle, + &gEfiAdapterInformationProtocolGuid, + (VOID *) &Aip + ); + if (EFI_ERROR (Status)) { + + MediaPresent = TRUE; + Status = NetLibDetectMedia (ServiceHandle, &MediaPresent); + if (!EFI_ERROR (Status)) { + if (MediaPresent == TRUE) { + *MediaState = EFI_SUCCESS; + } else { + *MediaState = EFI_NO_MEDIA; + } + } + + // + // NetLibDetectMedia doesn't support EFI_NOT_READY status, return now! + // + return Status; + } + + Status = Aip->GetInformation ( + Aip, + &gEfiAdapterInfoMediaStateGuid, + (VOID **) &MediaInfo, + &DataSize + ); + if (!EFI_ERROR (Status)) { + + *MediaState = MediaInfo->MediaState; + FreePool (MediaInfo); + if (*MediaState != EFI_NOT_READY || Timeout < MEDIA_STATE_DETECT_TIME_INTERVAL) { + + return EFI_SUCCESS; + } + } else { + + if (MediaInfo != NULL) { + FreePool (MediaInfo); + } + return Status; + } + + // + // Loop to check media state + // + + Timer = NULL; + TimeRemained = Timeout; + Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + do { + Status = gBS->SetTimer ( + Timer, + TimerRelative, + MEDIA_STATE_DETECT_TIME_INTERVAL + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent(Timer); + return EFI_DEVICE_ERROR; + } + + do { + TimerStatus = gBS->CheckEvent (Timer); + if (!EFI_ERROR (TimerStatus)) { + + TimeRemained -= MEDIA_STATE_DETECT_TIME_INTERVAL; + Status = Aip->GetInformation ( + Aip, + &gEfiAdapterInfoMediaStateGuid, + (VOID **) &MediaInfo, + &DataSize + ); + if (!EFI_ERROR (Status)) { + + *MediaState = MediaInfo->MediaState; + FreePool (MediaInfo); + } else { + + if (MediaInfo != NULL) { + FreePool (MediaInfo); + } + gBS->CloseEvent(Timer); + return Status; + } + } + } while (TimerStatus == EFI_NOT_READY); + } while (*MediaState == EFI_NOT_READY && TimeRemained >= MEDIA_STATE_DETECT_TIME_INTERVAL); + + gBS->CloseEvent(Timer); + if (*MediaState == EFI_NOT_READY && TimeRemained < MEDIA_STATE_DETECT_TIME_INTERVAL) { + return EFI_TIMEOUT; + } else { + return EFI_SUCCESS; + } +} + +/** Check the default address used by the IPv4 driver is static or dynamic (acquired from DHCP). If the controller handle does not have the EFI_IP4_CONFIG2_PROTOCOL installed, the default address is static. If failed to get the policy from Ip4 Config2 Protocol, diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf index 1ff3a4f..ad0727c 100644 --- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf +++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf @@ -52,14 +52,16 @@ [Guids] gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES [Protocols] gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES gEfiManagedNetworkProtocolGuid ## SOMETIMES_CONSUMES gEfiManagedNetworkServiceBindingProtocolGuid ## SOMETIMES_CONSUMES gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES \ No newline at end of file -- 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel