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

Reply via email to