summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Include/Library/NetLib.h40
-rw-r--r--MdeModulePkg/Library/DxeNetLib/DxeNetLib.c163
-rw-r--r--MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf2
3 files changed, 205 insertions, 0 deletions
diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h
index b9df46c50f..7862df9d43 100644
--- a/MdeModulePkg/Include/Library/NetLib.h
+++ b/MdeModulePkg/Include/Library/NetLib.h
@@ -95,6 +95,12 @@ typedef UINT16 TCP_PORTNO;
#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)
//
@@ -1248,6 +1254,40 @@ NetLibDetectMedia (
);
/**
+
+ 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.
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
index b8544b89ab..1bfa33d58d 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
@@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#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>
@@ -2503,6 +2504,168 @@ Exit:
}
/**
+
+ 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).
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
index 1ff3a4fe55..ad0727c42f 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
@@ -54,6 +54,7 @@
[Guids]
gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable
gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES
[Protocols]
@@ -63,3 +64,4 @@
gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES
gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES
gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES \ No newline at end of file