From: xdu2 Date: Wed, 3 Feb 2010 04:37:53 +0000 (+0000) Subject: For network dynamic media support: X-Git-Tag: edk2-stable201903~16417 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=dd29f3edb9849b7bb51f0ae4be8941a760846ef3 For network dynamic media support: 1. add library function NetLibDetectMedia to NetLib for media detection 2. update MnpDxe to periodically poll for media status update and check for media status before packet transmit 3. update Ip4Dxe to return ModeData using Mnp->GetModeData() 4. update IScsiDxe to check for media status before try to do DHCP and session login 5. update UefiPxeBcDxe to check for media status before PXE start git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9919 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h index 3a3b1901f6..854aa0fee0 100644 --- a/MdeModulePkg/Include/Library/NetLib.h +++ b/MdeModulePkg/Include/Library/NetLib.h @@ -1092,6 +1092,40 @@ NetLibGetMacString ( OUT CHAR16 **MacString ); +/** + Detect media status for specified network device. + + The underlying UNDI driver may or may not support reporting media status from + GET_STATUS command (PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED). This routine + will try to invoke Snp->GetStatus() to get the media status: if media already + present, it return directly; if media not present, it will stop SNP and then + restart SNP to get the latest media status, this give chance to get the correct + media status for old UNDI driver which doesn't support reporting media status + from GET_STATUS command. + Note: there will be two limitations for current algorithm: + 1) for UNDI with this capability, in case of cable is not attached, there will + be an redundant Stop/Start() process; + 2) for UNDI without this capability, in case cable is attached in UNDI + initialize while unattached latter, NetLibDetectMedia() will report + MediaPresent as TRUE, this cause upper layer apps wait for timeout time. + + @param[in] ServiceHandle The handle where network service binding protocols are + installed on. + @param[out] MediaPresent The pointer to store the media status. + + @retval EFI_SUCCESS Media detection success. + @retval EFI_INVALID_PARAMETER ServiceHandle is not valid network device handle. + @retval EFI_UNSUPPORTED Network device does not support media detection. + @retval EFI_DEVICE_ERROR SNP is in unknown state. + +**/ +EFI_STATUS +EFIAPI +NetLibDetectMedia ( + IN EFI_HANDLE ServiceHandle, + OUT BOOLEAN *MediaPresent + ); + /** Create an IPv4 device path node. @@ -1201,7 +1235,7 @@ NetLibDefaultUnload ( @param[in] String The pointer to the Ascii string. @param[out] Ip4Address The pointer to the converted IPv4 address. - @retval EFI_SUCCESS Convert to IPv4 address successfully. + @retval EFI_SUCCESS Convert to IPv4 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL. **/ @@ -1218,7 +1252,7 @@ NetLibAsciiStrToIp4 ( @param[in] String The pointer to the Ascii string. @param[out] Ip6Address The pointer to the converted IPv6 address. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. **/ @@ -1234,7 +1268,7 @@ NetLibAsciiStrToIp6 ( @param[in] String The pointer to the Ascii string. @param[out] Ip4Address The pointer to the converted IPv4 address. - @retval EFI_SUCCESS Convert to IPv4 address successfully. + @retval EFI_SUCCESS Convert to IPv4 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. @@ -1252,7 +1286,7 @@ NetLibStrToIp4 ( @param[in] String The pointer to the Ascii string. @param[out] Ip6Address The pointer to the converted IPv6 address. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. @@ -1272,7 +1306,7 @@ NetLibStrToIp6 ( @param[out] Ip6Address The pointer to the converted IPv6 address. @param[out] PrefixLength The pointer to the converted prefix length. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c index a5a6762985..5037243b37 100644 --- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c +++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c @@ -2145,6 +2145,213 @@ NetLibGetMacString ( return EFI_SUCCESS; } +/** + Detect media status for specified network device. + + The underlying UNDI driver may or may not support reporting media status from + GET_STATUS command (PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED). This routine + will try to invoke Snp->GetStatus() to get the media status: if media already + present, it return directly; if media not present, it will stop SNP and then + restart SNP to get the latest media status, this give chance to get the correct + media status for old UNDI driver which doesn't support reporting media status + from GET_STATUS command. + Note: there will be two limitations for current algorithm: + 1) for UNDI with this capability, in case of cable is not attached, there will + be an redundant Stop/Start() process; + 2) for UNDI without this capability, in case cable is attached in UNDI + initialize while unattached latter, NetLibDetectMedia() will report + MediaPresent as TRUE, this cause upper layer apps wait for timeout time. + + @param[in] ServiceHandle The handle where network service binding protocols are + installed on. + @param[out] MediaPresent The pointer to store the media status. + + @retval EFI_SUCCESS Media detection success. + @retval EFI_INVALID_PARAMETER ServiceHandle is not valid network device handle. + @retval EFI_UNSUPPORTED Network device does not support media detection. + @retval EFI_DEVICE_ERROR SNP is in unknown state. + +**/ +EFI_STATUS +EFIAPI +NetLibDetectMedia ( + IN EFI_HANDLE ServiceHandle, + OUT BOOLEAN *MediaPresent + ) +{ + EFI_STATUS Status; + EFI_HANDLE SnpHandle; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + UINT32 InterruptStatus; + UINT32 OldState; + EFI_MAC_ADDRESS *MCastFilter; + UINT32 MCastFilterCount; + UINT32 EnableFilterBits; + UINT32 DisableFilterBits; + BOOLEAN ResetMCastFilters; + + ASSERT (MediaPresent != NULL); + + // + // Get SNP handle + // + Snp = NULL; + SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp); + if (SnpHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether SNP support media detection + // + if (!Snp->Mode->MediaPresentSupported) { + return EFI_UNSUPPORTED; + } + + // + // Invoke Snp->GetStatus() to refresh MediaPresent field in SNP mode data + // + Status = Snp->GetStatus (Snp, &InterruptStatus, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Snp->Mode->MediaPresent) { + // + // Media is present, return directly + // + *MediaPresent = TRUE; + return EFI_SUCCESS; + } + + // + // Till now, GetStatus() report no media; while, in case UNDI not support + // reporting media status from GetStatus(), this media status may be incorrect. + // So, we will stop SNP and then restart it to get the correct media status. + // + OldState = Snp->Mode->State; + if (OldState >= EfiSimpleNetworkMaxState) { + return EFI_DEVICE_ERROR; + } + + MCastFilter = NULL; + + if (OldState == EfiSimpleNetworkInitialized) { + // + // SNP is already in use, need Shutdown/Stop and then Start/Initialize + // + + // + // Backup current SNP receive filter settings + // + EnableFilterBits = Snp->Mode->ReceiveFilterSetting; + DisableFilterBits = Snp->Mode->ReceiveFilterMask ^ EnableFilterBits; + + ResetMCastFilters = TRUE; + MCastFilterCount = Snp->Mode->MCastFilterCount; + if (MCastFilterCount != 0) { + MCastFilter = AllocateCopyPool ( + MCastFilterCount * sizeof (EFI_MAC_ADDRESS), + Snp->Mode->MCastFilter + ); + ASSERT (MCastFilter != NULL); + + ResetMCastFilters = FALSE; + } + + // + // Shutdown/Stop the simple network + // + Status = Snp->Shutdown (Snp); + if (!EFI_ERROR (Status)) { + Status = Snp->Stop (Snp); + } + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Start/Initialize the simple network + // + Status = Snp->Start (Snp); + if (!EFI_ERROR (Status)) { + Status = Snp->Initialize (Snp, 0, 0); + } + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Here we get the correct media status + // + *MediaPresent = Snp->Mode->MediaPresent; + + // + // Restore SNP receive filter settings + // + Status = Snp->ReceiveFilters ( + Snp, + EnableFilterBits, + DisableFilterBits, + ResetMCastFilters, + MCastFilterCount, + MCastFilter + ); + + if (MCastFilter != NULL) { + FreePool (MCastFilter); + } + + return Status; + } + + // + // SNP is not in use, it's in state of EfiSimpleNetworkStopped or EfiSimpleNetworkStarted + // + if (OldState == EfiSimpleNetworkStopped) { + // + // SNP not start yet, start it + // + Status = Snp->Start (Snp); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + + // + // Initialize the simple network + // + Status = Snp->Initialize (Snp, 0, 0); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + // + // Here we get the correct media status + // + *MediaPresent = Snp->Mode->MediaPresent; + + // + // Shut down the simple network + // + Snp->Shutdown (Snp); + +Exit: + if (OldState == EfiSimpleNetworkStopped) { + // + // Original SNP sate is Stopped, restore to original state + // + Snp->Stop (Snp); + } + + if (MCastFilter != NULL) { + FreePool (MCastFilter); + } + + return Status; +} + /** Check the default address used by the IPv4 driver is static or dynamic (acquired from DHCP). @@ -2417,7 +2624,7 @@ NetLibGetNicHandle ( @param[in] String The pointer to the Ascii string. @param[out] Ip4Address The pointer to the converted IPv4 address. - @retval EFI_SUCCESS Convert to IPv4 address successfully. + @retval EFI_SUCCESS Convert to IPv4 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL. **/ @@ -2460,7 +2667,7 @@ NetLibAsciiStrToIp4 ( // // Convert the string to IPv4 address. AsciiStrDecimalToUintn stops at the - // first character that is not a valid decimal character, '.' or '\0' here. + // first character that is not a valid decimal character, '.' or '\0' here. // NodeVal = AsciiStrDecimalToUintn (TempStr); if (NodeVal > 0xFF) { @@ -2483,7 +2690,7 @@ NetLibAsciiStrToIp4 ( @param[in] String The pointer to the Ascii string. @param[out] Ip6Address The pointer to the converted IPv6 address. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. **/ @@ -2519,7 +2726,7 @@ NetLibAsciiStrToIp6 ( return EFI_INVALID_PARAMETER; } else { AllowedCnt = 7; - } + } } ZeroMem (Ip6Address, sizeof (EFI_IPv6_ADDRESS)); @@ -2547,7 +2754,7 @@ NetLibAsciiStrToIp6 ( // ::0 looks strange. report error to user. // return EFI_INVALID_PARAMETER; - } + } // // Skip the abbreviation part of IPv6 address. @@ -2561,7 +2768,7 @@ NetLibAsciiStrToIp6 ( // return EFI_INVALID_PARAMETER; } - + TailNodeCnt++; if (TailNodeCnt >= (AllowedCnt - NodeCnt)) { // @@ -2572,7 +2779,7 @@ NetLibAsciiStrToIp6 ( } TempStr2++; - } + } Short = TRUE; Update = TRUE; @@ -2587,12 +2794,12 @@ NetLibAsciiStrToIp6 ( // return EFI_INVALID_PARAMETER; } - } - } + } + } // // Convert the string to IPv6 address. AsciiStrHexToUintn stops at the first - // character that is not a valid hexadecimal character, ':' or '\0' here. + // character that is not a valid hexadecimal character, ':' or '\0' here. // NodeVal = AsciiStrHexToUintn (TempStr); if ((NodeVal > 0xFFFF) || (Index > 14)) { @@ -2625,7 +2832,7 @@ NetLibAsciiStrToIp6 ( @param[in] String The pointer to the Ascii string. @param[out] Ip4Address The pointer to the converted IPv4 address. - @retval EFI_SUCCESS Convert to IPv4 address successfully. + @retval EFI_SUCCESS Convert to IPv4 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. @@ -2638,7 +2845,7 @@ NetLibStrToIp4 ( { CHAR8 *Ip4Str; EFI_STATUS Status; - + if ((String == NULL) || (Ip4Address == NULL)) { return EFI_INVALID_PARAMETER; } @@ -2665,7 +2872,7 @@ NetLibStrToIp4 ( @param[in] String The pointer to the Ascii string. @param[out] Ip6Address The pointer to the converted IPv6 address. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. @@ -2674,11 +2881,11 @@ EFI_STATUS NetLibStrToIp6 ( IN CONST CHAR16 *String, OUT EFI_IPv6_ADDRESS *Ip6Address - ) + ) { CHAR8 *Ip6Str; EFI_STATUS Status; - + if ((String == NULL) || (Ip6Address == NULL)) { return EFI_INVALID_PARAMETER; } @@ -2706,7 +2913,7 @@ NetLibStrToIp6 ( @param[out] Ip6Address The pointer to the converted IPv6 address. @param[out] PrefixLength The pointer to the converted prefix length. - @retval EFI_SUCCESS Convert to IPv6 address successfully. + @retval EFI_SUCCESS Convert to IPv6 address successfully. @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL. @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource. @@ -2716,14 +2923,14 @@ NetLibStrToIp6andPrefix ( IN CONST CHAR16 *String, OUT EFI_IPv6_ADDRESS *Ip6Address, OUT UINT8 *PrefixLength - ) + ) { - CHAR8 *Ip6Str; + CHAR8 *Ip6Str; CHAR8 *PrefixStr; CHAR8 *TempStr; EFI_STATUS Status; UINT8 Length; - + if ((String == NULL) || (Ip6Address == NULL) || (PrefixLength == NULL)) { return EFI_INVALID_PARAMETER; } diff --git a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c index a0a53a4e33..f470844ee4 100644 --- a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c +++ b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c @@ -770,6 +770,7 @@ ON_EXIT: @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the DHCP process. @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NO_MEDIA There was a media error. **/ EFI_STATUS diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.c b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.c index 996a290610..c770e27631 100644 --- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.c +++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.c @@ -1,7 +1,7 @@ /** @file iSCSI DHCP related configuration routines. -Copyright (c) 2004 - 2009, Intel Corporation.
+Copyright (c) 2004 - 2010, 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 @@ -344,7 +344,9 @@ IScsiParseDhcpAck ( @retval EFI_SUCCESS The DNS information is got from the DHCP ACK. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. + **/ EFI_STATUS IScsiDoDhcp ( @@ -358,11 +360,21 @@ IScsiDoDhcp ( EFI_STATUS Status; EFI_DHCP4_PACKET_OPTION *ParaList; EFI_DHCP4_CONFIG_DATA Dhcp4ConfigData; + BOOLEAN MediaPresent; Dhcp4Handle = NULL; Dhcp4 = NULL; ParaList = NULL; + // + // Check media status before do DHCP + // + MediaPresent = TRUE; + NetLibDetectMedia (Controller, &MediaPresent); + if (!MediaPresent) { + return EFI_NO_MEDIA; + } + // // Create a DHCP4 child instance and get the protocol. // diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.h b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.h index 07b30a936c..eefc5b37a8 100644 --- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.h +++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiDhcp.h @@ -1,7 +1,7 @@ /** @file The header file of IScsiDhcp. -Copyright (c) 2004 - 2009, Intel Corporation.
+Copyright (c) 2004 - 2010, 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 @@ -47,7 +47,9 @@ typedef struct _ISCSI_ROOT_PATH_FIELD { @retval EFI_SUCCESS The DNS information is got from the DHCP ACK. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. + **/ EFI_STATUS IScsiDoDhcp ( diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c index ac0d8d821f..2261bc17f0 100644 --- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c +++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c @@ -1,7 +1,7 @@ /** @file The implementation of iSCSI protocol based on RFC3720. -Copyright (c) 2004 - 2009, Intel Corporation.
+Copyright (c) 2004 - 2010, 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 @@ -276,7 +276,9 @@ IScsiDestroyConnection ( @retval EFI_SUCCESS The iSCSI session login procedure finished. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. + **/ EFI_STATUS IScsiSessionLogin ( @@ -287,9 +289,19 @@ IScsiSessionLogin ( ISCSI_SESSION *Session; ISCSI_CONNECTION *Conn; EFI_TCP4_PROTOCOL *Tcp4; + BOOLEAN MediaPresent; Session = &Private->Session; + // + // Check media status before session login + // + MediaPresent = TRUE; + NetLibDetectMedia (Private->Controller, &MediaPresent); + if (!MediaPresent) { + return EFI_NO_MEDIA; + } + // // Create a connection for the session. // diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.h b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.h index 93fe2af5b7..e11565e301 100644 --- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.h +++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.h @@ -1,7 +1,7 @@ /** @file The header file of iSCSI Protocol that defines many specific data structures. -Copyright (c) 2004 - 2009, Intel Corporation.
+Copyright (c) 2004 - 2010, 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 @@ -692,7 +692,9 @@ IScsiDestroyConnection ( @retval EFI_SUCCESS The iSCSI session login procedure finished. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. + **/ EFI_STATUS IScsiSessionLogin ( diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index ec545a6c54..06358f06ef 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -440,16 +440,13 @@ EfiIp4GetModeData ( } } - if (MnpConfigData != NULL) { - CopyMem (MnpConfigData, &IpSb->MnpConfigData, sizeof (*MnpConfigData)); - } - - if (SnpModeData != NULL) { - CopyMem (SnpModeData, &IpSb->SnpMode, sizeof (*SnpModeData)); - } + // + // Get fresh mode data from MNP, since underlying media status may change + // + Status = IpSb->Mnp->GetModeData (IpSb->Mnp, MnpConfigData, SnpModeData); gBS->RestoreTPL (OldTpl); - return EFI_SUCCESS; + return Status; } diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c index af642a50d9..115185afe2 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c @@ -1,7 +1,7 @@ /** @file Implementation of Managed Network Protocol private services. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -355,6 +355,22 @@ MnpInitializeDeviceData ( goto ERROR; } + // + // Create the timer for media detection. + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL | EVT_TIMER, + TPL_CALLBACK, + MnpCheckMediaStatus, + MnpDeviceData, + &MnpDeviceData->MediaDetectTimer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n")); + + goto ERROR; + } + // // Create the timer for tx timeout check. // @@ -382,6 +398,10 @@ ERROR: gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer); } + if (MnpDeviceData->MediaDetectTimer != NULL) { + gBS->CloseEvent (MnpDeviceData->MediaDetectTimer); + } + if (MnpDeviceData->PollTimer != NULL) { gBS->CloseEvent (MnpDeviceData->PollTimer); } @@ -443,9 +463,10 @@ MnpDestroyDeviceData ( // // Close the event. // - gBS->CloseEvent (&MnpDeviceData->TxTimeoutEvent); - gBS->CloseEvent (&MnpDeviceData->TimeoutCheckTimer); - gBS->CloseEvent (&MnpDeviceData->PollTimer); + gBS->CloseEvent (MnpDeviceData->TxTimeoutEvent); + gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer); + gBS->CloseEvent (MnpDeviceData->MediaDetectTimer); + gBS->CloseEvent (MnpDeviceData->PollTimer); // // Free the tx buffer. @@ -1010,6 +1031,24 @@ MnpStart ( goto ErrorExit; } + + // + // Start the media detection timer. + // + Status = gBS->SetTimer ( + MnpDeviceData->MediaDetectTimer, + TimerPeriodic, + MNP_MEDIA_DETECT_INTERVAL + ); + if (EFI_ERROR (Status)) { + DEBUG ( + (EFI_D_ERROR, + "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n", + Status) + ); + + goto ErrorExit; + } } } @@ -1095,6 +1134,11 @@ MnpStop ( // Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0); + // + // Cancel the media detect timer. + // + Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0); + // // Stop the simple network. // diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c index e3abd48cf3..d2d5924c77 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c @@ -1,7 +1,7 @@ /** @file Implementation of driver entry point and driver binding protocol. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -336,7 +336,7 @@ MnpDriverBindingStop ( } // - // Destroy the Mnp device data + // Destroy Mnp Device Data // MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle); FreePool (MnpDeviceData); diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h index e9698d2aac..d410af2726 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h @@ -1,7 +1,7 @@ /** @file Declaration of strctures and functions for MnpDxe driver. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -70,6 +70,7 @@ typedef struct { BOOLEAN EnableSystemPoll; EFI_EVENT TimeoutCheckTimer; + EFI_EVENT MediaDetectTimer; UINT32 UnicastCount; UINT32 BroadcastCount; diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h index d35086221e..54a61c3961 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h @@ -1,7 +1,7 @@ /** @file Declaration of structures and functions of MnpDxe driver. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define MNP_SYS_POLL_INTERVAL (10 * TICKS_PER_MS) // 10 milliseconds #define MNP_TIMEOUT_CHECK_INTERVAL (50 * TICKS_PER_MS) // 50 milliseconds +#define MNP_MEDIA_DETECT_INTERVAL (500 * TICKS_PER_MS) // 500 milliseconds #define MNP_TX_TIMEOUT_TIME (500 * TICKS_PER_MS) // 500 milliseconds #define MNP_INIT_NET_BUFFER_NUM 512 #define MNP_NET_BUFFER_INCREASEMENT 64 @@ -448,9 +449,8 @@ MnpFreeNbuf ( /** Remove the received packets if timeout occurs. - @param[in] Event The event this notify function registered to. - @param[in] Context Pointer to the context data registered to the - event. + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. **/ VOID @@ -460,19 +460,33 @@ MnpCheckPacketTimeout ( IN VOID *Context ); +/** + Poll to update MediaPresent field in SNP ModeData by Snp.GetStatus(). + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + +**/ +VOID +EFIAPI +MnpCheckMediaStatus ( + IN EFI_EVENT Event, + IN VOID *Context + ); + /** Poll to receive the packets from Snp. This function is either called by upperlayer protocols/applications or the system poll timer notify mechanism. - @param[in] Event The event this notify function registered to. - @param[in, out] Context Pointer to the context data registered to the event. + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. **/ VOID EFIAPI MnpSystemPoll ( - IN EFI_EVENT Event, - IN OUT VOID *Context + IN EFI_EVENT Event, + IN VOID *Context ); /** diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c index 65268a8d74..32cffd5730 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c @@ -1,7 +1,7 @@ /** @file Implementation of Managed Network Protocol I/O functions. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -210,6 +210,18 @@ MnpSyncSendPacket ( HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength; + // + // Check media status before transmit packet. + // Note: media status will be updated by periodic timer MediaDetectTimer. + // + if (!Snp->Mode->MediaPresent) { + // + // Media not present, skip packet transmit and report EFI_NO_MEDIA + // + Status = EFI_NO_MEDIA; + goto SIGNAL_TOKEN; + } + // // Start the timeout event. // @@ -998,9 +1010,8 @@ EXIT: /** Remove the received packets if timeout occurs. - @param[in] Event The event this notify function registered to. - @param[in] Context Pointer to the context data registered to the - event. + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. **/ VOID @@ -1065,19 +1076,50 @@ MnpCheckPacketTimeout ( } } +/** + Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus(). + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + +**/ +VOID +EFIAPI +MnpCheckMediaStatus ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + MNP_DEVICE_DATA *MnpDeviceData; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + UINT32 InterruptStatus; + + MnpDeviceData = (MNP_DEVICE_DATA *) Context; + NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE); + + Snp = MnpDeviceData->Snp; + if (Snp->Mode->MediaPresentSupported) { + // + // Upon successful return of GetStatus(), the MediaPresent field of + // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status + // + Snp->GetStatus (Snp, &InterruptStatus, NULL); + } +} + /** Poll to receive the packets from Snp. This function is either called by upperlayer protocols/applications or the system poll timer notify mechanism. - @param[in] Event The event this notify function registered to. - @param[in, out] Context Pointer to the context data registered to the event. + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. **/ VOID EFIAPI MnpSystemPoll ( - IN EFI_EVENT Event, - IN OUT VOID *Context + IN EFI_EVENT Event, + IN VOID *Context ) { MNP_DEVICE_DATA *MnpDeviceData; diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c index e34936f3b8..1f7b1e6bf0 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c @@ -1,7 +1,7 @@ /** @file Implementation of Managed Network Protocol public services. -Copyright (c) 2005 - 2009, Intel Corporation.
+Copyright (c) 2005 - 2010, 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 @@ -52,6 +52,7 @@ MnpGetModeData ( EFI_SIMPLE_NETWORK_PROTOCOL *Snp; EFI_TPL OldTpl; EFI_STATUS Status; + UINT32 InterruptStatus; if (This == NULL) { return EFI_INVALID_PARAMETER; @@ -73,6 +74,12 @@ MnpGetModeData ( // Copy the underlayer Snp mode data. // Snp = Instance->MnpServiceData->MnpDeviceData->Snp; + + // + // Upon successful return of GetStatus(), the Snp->Mode->MediaPresent + // will be updated to reflect any change of media status + // + Snp->GetStatus (Snp, &InterruptStatus, NULL); CopyMem (SnpModeData, Snp->Mode, sizeof (*SnpModeData)); } diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c index 3d92ba3dd1..8652ba5256 100644 --- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c +++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c @@ -1,7 +1,7 @@ /** @file Interface routine for Mtftp4. -Copyright (c) 2006 - 2009, Intel Corporation
+Copyright (c) 2006 - 2010, 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 @@ -776,6 +776,7 @@ EfiMtftp4ParseOptions ( @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received. @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + @retval EFI_NO_MEDIA There was a media error. **/ EFI_STATUS @@ -971,7 +972,8 @@ EfiMtftp4ReadDirectory ( in the Buffer. @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. - + @retval EFI_NO_MEDIA There was a media error. + **/ EFI_STATUS EFIAPI diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c index df9d2df5be..f0fc48f8ac 100644 --- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c +++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c @@ -2585,6 +2585,7 @@ EfiPxeLoadFile ( BOOLEAN NewMakeCallback; EFI_STATUS Status; UINT64 TmpBufSize; + BOOLEAN MediaPresent; Private = PXEBC_PRIVATE_DATA_FROM_LOADFILE (This); PxeBc = &Private->PxeBc; @@ -2603,6 +2604,15 @@ EfiPxeLoadFile ( return EFI_UNSUPPORTED; } + // + // Check media status before PXE start + // + MediaPresent = TRUE; + NetLibDetectMedia (Private->Controller, &MediaPresent); + if (!MediaPresent) { + return EFI_NO_MEDIA; + } + Status = PxeBc->Start (PxeBc, FALSE); if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { return Status;