//\r
Pri = ((NET_SYSLOG_FACILITY & 31) << 3) | (Level & 7);\r
gRT->GetTime (&Time, NULL);\r
+ ASSERT ((Time.Month <= 12) && (Time.Month >= 1));\r
\r
//\r
// Use %a to format the ASCII strings, %s to format UNICODE strings\r
UINT8 Bit;\r
UINT8 Mask;\r
\r
- ASSERT (Ip1 != NULL && Ip2 != NULL);\r
+ ASSERT ((Ip1 != NULL) && (Ip2 != NULL) && (PrefixLength < IP6_PREFIX_NUM));\r
\r
if (PrefixLength == 0) {\r
return TRUE;\r
if (Bit > 0) {\r
Mask = (UINT8) (0xFF << (8 - Bit));\r
\r
+ ASSERT (Byte < 16);\r
if ((Ip1->Addr[Byte] & Mask) != (Ip2->Addr[Byte] & Mask)) {\r
return FALSE;\r
}\r
byte stream.\r
\r
@param[in, out] Buf The buffer to put the UINT32.\r
- @param[in] Data The data to put.\r
+ @param[in] Data The data to be converted and put into the byte stream.\r
\r
**/\r
VOID\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Detect media status for specified network device.\r
+\r
+ The underlying UNDI driver may or may not support reporting media status from\r
+ GET_STATUS command (PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED). This routine\r
+ will try to invoke Snp->GetStatus() to get the media status: if media already\r
+ present, it return directly; if media not present, it will stop SNP and then\r
+ restart SNP to get the latest media status, this give chance to get the correct\r
+ media status for old UNDI driver which doesn't support reporting media status\r
+ from GET_STATUS command.\r
+ Note: there will be two limitations for current algorithm:\r
+ 1) for UNDI with this capability, in case of cable is not attached, there will\r
+ be an redundant Stop/Start() process;\r
+ 2) for UNDI without this capability, in case that network cable is attached when\r
+ Snp->Initialize() is invoked while network cable is unattached later,\r
+ NetLibDetectMedia() will report MediaPresent as TRUE, causing upper layer\r
+ apps to wait for timeout time.\r
+\r
+ @param[in] ServiceHandle The handle where network service binding protocols are\r
+ installed on.\r
+ @param[out] MediaPresent The pointer to store the media status.\r
+\r
+ @retval EFI_SUCCESS Media detection success.\r
+ @retval EFI_INVALID_PARAMETER ServiceHandle is not valid network device handle.\r
+ @retval EFI_UNSUPPORTED Network device does not support media detection.\r
+ @retval EFI_DEVICE_ERROR SNP is in unknown state.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibDetectMedia (\r
+ IN EFI_HANDLE ServiceHandle,\r
+ OUT BOOLEAN *MediaPresent\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE SnpHandle;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+ UINT32 InterruptStatus;\r
+ UINT32 OldState;\r
+ EFI_MAC_ADDRESS *MCastFilter;\r
+ UINT32 MCastFilterCount;\r
+ UINT32 EnableFilterBits;\r
+ UINT32 DisableFilterBits;\r
+ BOOLEAN ResetMCastFilters;\r
+\r
+ ASSERT (MediaPresent != NULL);\r
+\r
+ //\r
+ // Get SNP handle\r
+ //\r
+ Snp = NULL;\r
+ SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);\r
+ if (SnpHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether SNP support media detection\r
+ //\r
+ if (!Snp->Mode->MediaPresentSupported) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Invoke Snp->GetStatus() to refresh MediaPresent field in SNP mode data\r
+ //\r
+ Status = Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Snp->Mode->MediaPresent) {\r
+ //\r
+ // Media is present, return directly\r
+ //\r
+ *MediaPresent = TRUE;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Till now, GetStatus() report no media; while, in case UNDI not support\r
+ // reporting media status from GetStatus(), this media status may be incorrect.\r
+ // So, we will stop SNP and then restart it to get the correct media status.\r
+ //\r
+ OldState = Snp->Mode->State;\r
+ if (OldState >= EfiSimpleNetworkMaxState) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ MCastFilter = NULL;\r
+\r
+ if (OldState == EfiSimpleNetworkInitialized) {\r
+ //\r
+ // SNP is already in use, need Shutdown/Stop and then Start/Initialize\r
+ //\r
+\r
+ //\r
+ // Backup current SNP receive filter settings\r
+ //\r
+ EnableFilterBits = Snp->Mode->ReceiveFilterSetting;\r
+ DisableFilterBits = Snp->Mode->ReceiveFilterMask ^ EnableFilterBits;\r
+\r
+ ResetMCastFilters = TRUE;\r
+ MCastFilterCount = Snp->Mode->MCastFilterCount;\r
+ if (MCastFilterCount != 0) {\r
+ MCastFilter = AllocateCopyPool (\r
+ MCastFilterCount * sizeof (EFI_MAC_ADDRESS),\r
+ Snp->Mode->MCastFilter\r
+ );\r
+ ASSERT (MCastFilter != NULL);\r
+\r
+ ResetMCastFilters = FALSE;\r
+ }\r
+\r
+ //\r
+ // Shutdown/Stop the simple network\r
+ //\r
+ Status = Snp->Shutdown (Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Snp->Stop (Snp);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Start/Initialize the simple network\r
+ //\r
+ Status = Snp->Start (Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Snp->Initialize (Snp, 0, 0);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Here we get the correct media status\r
+ //\r
+ *MediaPresent = Snp->Mode->MediaPresent;\r
+\r
+ //\r
+ // Restore SNP receive filter settings\r
+ //\r
+ Status = Snp->ReceiveFilters (\r
+ Snp,\r
+ EnableFilterBits,\r
+ DisableFilterBits,\r
+ ResetMCastFilters,\r
+ MCastFilterCount,\r
+ MCastFilter\r
+ );\r
+\r
+ if (MCastFilter != NULL) {\r
+ FreePool (MCastFilter);\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // SNP is not in use, it's in state of EfiSimpleNetworkStopped or EfiSimpleNetworkStarted\r
+ //\r
+ if (OldState == EfiSimpleNetworkStopped) {\r
+ //\r
+ // SNP not start yet, start it\r
+ //\r
+ Status = Snp->Start (Snp);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Initialize the simple network\r
+ //\r
+ Status = Snp->Initialize (Snp, 0, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Here we get the correct media status\r
+ //\r
+ *MediaPresent = Snp->Mode->MediaPresent;\r
+\r
+ //\r
+ // Shut down the simple network\r
+ //\r
+ Snp->Shutdown (Snp);\r
+\r
+Exit:\r
+ if (OldState == EfiSimpleNetworkStopped) {\r
+ //\r
+ // Original SNP sate is Stopped, restore to original state\r
+ //\r
+ Snp->Stop (Snp);\r
+ }\r
+\r
+ if (MCastFilter != NULL) {\r
+ FreePool (MCastFilter);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Check the default address used by the IPv4 driver is static or dynamic (acquired\r
from DHCP).\r
IsStatic = TRUE;\r
\r
Status = gBS->LocateProtocol (\r
- &gEfiHiiConfigRoutingProtocolGuid,\r
- NULL,\r
- (VOID **) &HiiConfigRouting\r
- );\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **) &HiiConfigRouting\r
+ );\r
if (EFI_ERROR (Status)) {\r
return TRUE;\r
}\r
gBS->FreePool (OpenBuffer);\r
return Handle;\r
}\r
+\r
+/**\r
+ Convert one Null-terminated ASCII string (decimal dotted) to EFI_IPv4_ADDRESS.\r
+\r
+ @param[in] String The pointer to the Ascii string.\r
+ @param[out] Ip4Address The pointer to the converted IPv4 address.\r
+\r
+ @retval EFI_SUCCESS Convert to IPv4 address successfully.\r
+ @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+NetLibAsciiStrToIp4 (\r
+ IN CONST CHAR8 *String,\r
+ OUT EFI_IPv4_ADDRESS *Ip4Address\r
+ )\r
+{\r
+ UINT8 Index;\r
+ CHAR8 *Ip4Str;\r
+ CHAR8 *TempStr;\r
+ UINTN NodeVal;\r
+\r
+ if ((String == NULL) || (Ip4Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip4Str = (CHAR8 *) String;\r
+\r
+ for (Index = 0; Index < 4; Index++) {\r
+ TempStr = Ip4Str;\r
+\r
+ while ((*Ip4Str != '\0') && (*Ip4Str != '.')) {\r
+ Ip4Str++;\r
+ }\r
+\r
+ //\r
+ // The IPv4 address is X.X.X.X\r
+ //\r
+ if (*Ip4Str == '.') {\r
+ if (Index == 3) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ if (Index != 3) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Convert the string to IPv4 address. AsciiStrDecimalToUintn stops at the\r
+ // first character that is not a valid decimal character, '.' or '\0' here.\r
+ //\r
+ NodeVal = AsciiStrDecimalToUintn (TempStr);\r
+ if (NodeVal > 0xFF) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip4Address->Addr[Index] = (UINT8) NodeVal;\r
+\r
+ Ip4Str++;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Convert one Null-terminated ASCII string to EFI_IPv6_ADDRESS. The format of the\r
+ string is defined in RFC 4291 - Text Pepresentation of Addresses.\r
+\r
+ @param[in] String The pointer to the Ascii string.\r
+ @param[out] Ip6Address The pointer to the converted IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Convert to IPv6 address successfully.\r
+ @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+NetLibAsciiStrToIp6 (\r
+ IN CONST CHAR8 *String,\r
+ OUT EFI_IPv6_ADDRESS *Ip6Address\r
+ )\r
+{\r
+ UINT8 Index;\r
+ CHAR8 *Ip6Str;\r
+ CHAR8 *TempStr;\r
+ CHAR8 *TempStr2;\r
+ UINT8 NodeCnt;\r
+ UINT8 TailNodeCnt;\r
+ UINT8 AllowedCnt;\r
+ UINTN NodeVal;\r
+ BOOLEAN Short;\r
+ BOOLEAN Update;\r
+\r
+ if ((String == NULL) || (Ip6Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip6Str = (CHAR8 *) String;\r
+ AllowedCnt = 6;\r
+\r
+ //\r
+ // An IPv6 address leading with : looks strange.\r
+ //\r
+ if (*Ip6Str == ':') {\r
+ if (*(Ip6Str + 1) != ':') {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else {\r
+ AllowedCnt = 7;\r
+ }\r
+ }\r
+\r
+ ZeroMem (Ip6Address, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+ NodeCnt = 0;\r
+ TailNodeCnt = 0;\r
+ Short = FALSE;\r
+ Update = FALSE;\r
+\r
+ for (Index = 0; Index < 15; Index = (UINT8) (Index + 2)) {\r
+ TempStr = Ip6Str;\r
+\r
+ while ((*Ip6Str != '\0') && (*Ip6Str != ':')) {\r
+ Ip6Str++;\r
+ }\r
+\r
+ if ((*Ip6Str == '\0') && (Index != 14)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (*Ip6Str == ':') {\r
+ if (*(Ip6Str + 1) == ':') {\r
+ if ((*(Ip6Str + 2) == '0') || (NodeCnt > 6)) {\r
+ //\r
+ // ::0 looks strange. report error to user.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Skip the abbreviation part of IPv6 address.\r
+ //\r
+ TempStr2 = Ip6Str + 2;\r
+ while ((*TempStr2 != '\0')) {\r
+ if (*TempStr2 == ':') {\r
+ if (*(TempStr2 + 1) == ':') {\r
+ //\r
+ // :: can only appear once in IPv6 address.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TailNodeCnt++;\r
+ if (TailNodeCnt >= (AllowedCnt - NodeCnt)) {\r
+ //\r
+ // :: indicates one or more groups of 16 bits of zeros.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ TempStr2++;\r
+ }\r
+\r
+ Short = TRUE;\r
+ Update = TRUE;\r
+\r
+ Ip6Str = Ip6Str + 2;\r
+ } else {\r
+ Ip6Str++;\r
+ NodeCnt++;\r
+ if ((Short && (NodeCnt > 6)) || (!Short && (NodeCnt > 7))) {\r
+ //\r
+ // There are more than 8 groups of 16 bits of zeros.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Convert the string to IPv6 address. AsciiStrHexToUintn stops at the first\r
+ // character that is not a valid hexadecimal character, ':' or '\0' here.\r
+ //\r
+ NodeVal = AsciiStrHexToUintn (TempStr);\r
+ if ((NodeVal > 0xFFFF) || (Index > 14)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip6Address->Addr[Index] = (UINT8) (NodeVal >> 8);\r
+ Ip6Address->Addr[Index + 1] = (UINT8) (NodeVal & 0xFF);\r
+\r
+ //\r
+ // Skip the groups of zeros by ::\r
+ //\r
+ if (Short && Update) {\r
+ Index = (UINT8) (16 - (TailNodeCnt + 2) * 2);\r
+ Update = FALSE;\r
+ }\r
+ }\r
+\r
+ if ((!Short && Index != 16) || (*Ip6Str != '\0')) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Convert one Null-terminated Unicode string (decimal dotted) to EFI_IPv4_ADDRESS.\r
+\r
+ @param[in] String The pointer to the Ascii string.\r
+ @param[out] Ip4Address The pointer to the converted IPv4 address.\r
+\r
+ @retval EFI_SUCCESS Convert to IPv4 address successfully.\r
+ @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip4Address is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource.\r
+\r
+**/\r
+EFI_STATUS\r
+NetLibStrToIp4 (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv4_ADDRESS *Ip4Address\r
+ )\r
+{\r
+ CHAR8 *Ip4Str;\r
+ EFI_STATUS Status;\r
+\r
+ if ((String == NULL) || (Ip4Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip4Str = (CHAR8 *) AllocatePool ((StrLen (String) + 1) * sizeof (CHAR8));\r
+ if (Ip4Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStr (String, Ip4Str);\r
+\r
+ Status = NetLibAsciiStrToIp4 (Ip4Str, Ip4Address);\r
+\r
+ FreePool (Ip4Str);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Convert one Null-terminated Unicode string to EFI_IPv6_ADDRESS. The format of\r
+ the string is defined in RFC 4291 - Text Pepresentation of Addresses.\r
+\r
+ @param[in] String The pointer to the Ascii string.\r
+ @param[out] Ip6Address The pointer to the converted IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Convert to IPv6 address successfully.\r
+ @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource.\r
+\r
+**/\r
+EFI_STATUS\r
+NetLibStrToIp6 (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv6_ADDRESS *Ip6Address\r
+ )\r
+{\r
+ CHAR8 *Ip6Str;\r
+ EFI_STATUS Status;\r
+\r
+ if ((String == NULL) || (Ip6Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip6Str = (CHAR8 *) AllocatePool ((StrLen (String) + 1) * sizeof (CHAR8));\r
+ if (Ip6Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStr (String, Ip6Str);\r
+\r
+ Status = NetLibAsciiStrToIp6 (Ip6Str, Ip6Address);\r
+\r
+ FreePool (Ip6Str);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert one Null-terminated Unicode string to EFI_IPv6_ADDRESS and prefix length.\r
+ The format of the string is defined in RFC 4291 - Text Pepresentation of Addresses\r
+ Prefixes: ipv6-address/prefix-length.\r
+\r
+ @param[in] String The pointer to the Ascii string.\r
+ @param[out] Ip6Address The pointer to the converted IPv6 address.\r
+ @param[out] PrefixLength The pointer to the converted prefix length.\r
+\r
+ @retval EFI_SUCCESS Convert to IPv6 address successfully.\r
+ @retval EFI_INVALID_PARAMETER The string is mal-formated or Ip6Address is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource.\r
+\r
+**/\r
+EFI_STATUS\r
+NetLibStrToIp6andPrefix (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv6_ADDRESS *Ip6Address,\r
+ OUT UINT8 *PrefixLength\r
+ )\r
+{\r
+ CHAR8 *Ip6Str;\r
+ CHAR8 *PrefixStr;\r
+ CHAR8 *TempStr;\r
+ EFI_STATUS Status;\r
+ UINT8 Length;\r
+\r
+ if ((String == NULL) || (Ip6Address == NULL) || (PrefixLength == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip6Str = (CHAR8 *) AllocatePool ((StrLen (String) + 1) * sizeof (CHAR8));\r
+ if (Ip6Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStr (String, Ip6Str);\r
+\r
+ //\r
+ // Get the sub string describing prefix length.\r
+ //\r
+ TempStr = Ip6Str;\r
+ while (*TempStr != '\0' && (*TempStr != '/')) {\r
+ TempStr++;\r
+ }\r
+\r
+ if (*TempStr == '/') {\r
+ PrefixStr = TempStr + 1;\r
+ } else {\r
+ PrefixStr = NULL;\r
+ }\r
+\r
+ //\r
+ // Get the sub string describing IPv6 address and convert it.\r
+ //\r
+ *TempStr = '\0';\r
+\r
+ Status = NetLibAsciiStrToIp6 (Ip6Str, Ip6Address);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // If input string doesn't indicate the prefix length, return 0xff.\r
+ //\r
+ Length = 0xFF;\r
+ \r
+ //\r
+ // Convert the string to prefix length\r
+ //\r
+ if (PrefixStr != NULL) {\r
+\r
+ Status = EFI_INVALID_PARAMETER;\r
+ Length = 0;\r
+ while (*PrefixStr != '\0') {\r
+ if (NET_IS_DIGIT (*PrefixStr)) {\r
+ Length = (UINT8) (Length * 10 + (*PrefixStr - '0'));\r
+ if (Length >= IP6_PREFIX_NUM) {\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ goto Exit;\r
+ }\r
+\r
+ PrefixStr++;\r
+ }\r
+ }\r
+\r
+ *PrefixLength = Length;\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+ FreePool (Ip6Str);\r
+ return Status;\r
+}\r
+\r