+\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
+EFIAPI\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
+ if (!NET_IS_DIGIT (*Ip4Str)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\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
+EFIAPI\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
+ BOOLEAN LeadZero;\r
+ UINT8 LeadZeroCnt;\r
+ UINT8 Cnt;\r
+\r
+ if ((String == NULL) || (Ip6Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Ip6Str = (CHAR8 *) String;\r
+ AllowedCnt = 6;\r
+ LeadZeroCnt = 0;\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
+ LeadZero = 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 ((NodeCnt > 6) || \r
+ ((*(Ip6Str + 2) != '\0') && (AsciiStrHexToUintn (Ip6Str + 2) == 0))) {\r
+ //\r
+ // ::0 looks strange. report error to user.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((NodeCnt == 6) && (*(Ip6Str + 2) != '\0') && \r
+ (AsciiStrHexToUintn (Ip6Str + 2) != 0)) {\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
+ if (*(Ip6Str + 1) == '\0') {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\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
+ if (NodeVal != 0) {\r
+ if ((*TempStr == '0') && \r
+ ((*(TempStr + 2) == ':') || (*(TempStr + 3) == ':') || \r
+ (*(TempStr + 2) == '\0') || (*(TempStr + 3) == '\0'))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((*TempStr == '0') && (*(TempStr + 4) != '\0') && \r
+ (*(TempStr + 4) != ':')) { \r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ if (((*TempStr == '0') && (*(TempStr + 1) == '0') && \r
+ ((*(TempStr + 2) == ':') || (*(TempStr + 2) == '\0'))) ||\r
+ ((*TempStr == '0') && (*(TempStr + 1) == '0') && (*(TempStr + 2) == '0') && \r
+ ((*(TempStr + 3) == ':') || (*(TempStr + 3) == '\0')))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ Cnt = 0;\r
+ while ((TempStr[Cnt] != ':') && (TempStr[Cnt] != '\0')) {\r
+ Cnt++; \r
+ }\r
+ if (LeadZeroCnt == 0) {\r
+ if ((Cnt == 4) && (*TempStr == '0')) {\r
+ LeadZero = TRUE;\r
+ LeadZeroCnt++;\r
+ }\r
+ if ((Cnt != 0) && (Cnt < 4)) {\r
+ LeadZero = FALSE;\r
+ LeadZeroCnt++;\r
+ }\r
+ } else {\r
+ if ((Cnt == 4) && (*TempStr == '0') && !LeadZero) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((Cnt != 0) && (Cnt < 4) && LeadZero) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\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
+EFIAPI\r
+NetLibStrToIp4 (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv4_ADDRESS *Ip4Address\r
+ )\r
+{\r
+ CHAR8 *Ip4Str;\r
+ UINTN StringSize;\r
+ EFI_STATUS Status;\r
+\r
+ if ((String == NULL) || (Ip4Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringSize = StrLen (String) + 1;\r
+ Ip4Str = (CHAR8 *) AllocatePool (StringSize * sizeof (CHAR8));\r
+ if (Ip4Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (String, Ip4Str, StringSize);\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
+EFIAPI\r
+NetLibStrToIp6 (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv6_ADDRESS *Ip6Address\r
+ )\r
+{\r
+ CHAR8 *Ip6Str;\r
+ UINTN StringSize;\r
+ EFI_STATUS Status;\r
+\r
+ if ((String == NULL) || (Ip6Address == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringSize = StrLen (String) + 1;\r
+ Ip6Str = (CHAR8 *) AllocatePool (StringSize * sizeof (CHAR8));\r
+ if (Ip6Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (String, Ip6Str, StringSize);\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
+EFIAPI\r
+NetLibStrToIp6andPrefix (\r
+ IN CONST CHAR16 *String,\r
+ OUT EFI_IPv6_ADDRESS *Ip6Address,\r
+ OUT UINT8 *PrefixLength\r
+ )\r
+{\r
+ CHAR8 *Ip6Str;\r
+ UINTN StringSize;\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
+ StringSize = StrLen (String) + 1;\r
+ Ip6Str = (CHAR8 *) AllocatePool (StringSize * sizeof (CHAR8));\r
+ if (Ip6Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (String, Ip6Str, StringSize);\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_MAX) {\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
+/**\r
+\r
+ Convert one EFI_IPv6_ADDRESS to Null-terminated Unicode string.\r
+ The text representation of address is defined in RFC 4291.\r
+ \r
+ @param[in] Ip6Address The pointer to the IPv6 address.\r
+ @param[out] String The buffer to return the converted string.\r
+ @param[in] StringSize The length in bytes of the input String.\r
+ \r
+ @retval EFI_SUCCESS Convert to string successfully.\r
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been \r
+ updated with the size needed to complete the request.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibIp6ToStr (\r
+ IN EFI_IPv6_ADDRESS *Ip6Address,\r
+ OUT CHAR16 *String,\r
+ IN UINTN StringSize\r
+ )\r
+{\r
+ UINT16 Ip6Addr[8];\r
+ UINTN Index;\r
+ UINTN LongestZerosStart;\r
+ UINTN LongestZerosLength;\r
+ UINTN CurrentZerosStart;\r
+ UINTN CurrentZerosLength;\r
+ CHAR16 Buffer[sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];\r
+ CHAR16 *Ptr;\r
+\r
+ if (Ip6Address == NULL || String == NULL || StringSize == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Convert the UINT8 array to an UINT16 array for easy handling.\r
+ // \r
+ ZeroMem (Ip6Addr, sizeof (Ip6Addr));\r
+ for (Index = 0; Index < 16; Index++) {\r
+ Ip6Addr[Index / 2] |= (Ip6Address->Addr[Index] << ((1 - (Index % 2)) << 3));\r
+ }\r
+\r
+ //\r
+ // Find the longest zeros and mark it.\r
+ //\r
+ CurrentZerosStart = DEFAULT_ZERO_START;\r
+ CurrentZerosLength = 0;\r
+ LongestZerosStart = DEFAULT_ZERO_START;\r
+ LongestZerosLength = 0;\r
+ for (Index = 0; Index < 8; Index++) {\r
+ if (Ip6Addr[Index] == 0) {\r
+ if (CurrentZerosStart == DEFAULT_ZERO_START) {\r
+ CurrentZerosStart = Index;\r
+ CurrentZerosLength = 1;\r
+ } else {\r
+ CurrentZerosLength++;\r
+ }\r
+ } else {\r
+ if (CurrentZerosStart != DEFAULT_ZERO_START) {\r
+ if (CurrentZerosLength > 2 && (LongestZerosStart == (DEFAULT_ZERO_START) || CurrentZerosLength > LongestZerosLength)) {\r
+ LongestZerosStart = CurrentZerosStart;\r
+ LongestZerosLength = CurrentZerosLength;\r
+ }\r
+ CurrentZerosStart = DEFAULT_ZERO_START;\r
+ CurrentZerosLength = 0;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (CurrentZerosStart != DEFAULT_ZERO_START && CurrentZerosLength > 2) {\r
+ if (LongestZerosStart == DEFAULT_ZERO_START || LongestZerosLength < CurrentZerosLength) {\r
+ LongestZerosStart = CurrentZerosStart;\r
+ LongestZerosLength = CurrentZerosLength;\r
+ }\r
+ }\r
+\r
+ Ptr = Buffer;\r
+ for (Index = 0; Index < 8; Index++) {\r
+ if (LongestZerosStart != DEFAULT_ZERO_START && Index >= LongestZerosStart && Index < LongestZerosStart + LongestZerosLength) {\r
+ if (Index == LongestZerosStart) {\r
+ *Ptr++ = L':';\r
+ }\r
+ continue;\r
+ }\r
+ if (Index != 0) {\r
+ *Ptr++ = L':';\r
+ }\r
+ Ptr += UnicodeSPrint(Ptr, 10, L"%x", Ip6Addr[Index]);\r
+ }\r
+ \r
+ if (LongestZerosStart != DEFAULT_ZERO_START && LongestZerosStart + LongestZerosLength == 8) {\r
+ *Ptr++ = L':';\r
+ }\r
+ *Ptr = L'\0';\r
+\r
+ if ((UINTN)Ptr - (UINTN)Buffer > StringSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ StrCpyS (String, StringSize / sizeof (CHAR16), Buffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function obtains the system guid from the smbios table.\r
+\r
+ @param[out] SystemGuid The pointer of the returned system guid.\r
+\r
+ @retval EFI_SUCCESS Successfully obtained the system guid.\r
+ @retval EFI_NOT_FOUND Did not find the SMBIOS table.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NetLibGetSystemGuid (\r
+ OUT EFI_GUID *SystemGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;\r
+ SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30Table;\r
+ SMBIOS_STRUCTURE_POINTER Smbios;\r
+ SMBIOS_STRUCTURE_POINTER SmbiosEnd;\r
+ CHAR8 *String;\r
+\r
+ SmbiosTable = NULL;\r
+ Status = EfiGetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID **) &Smbios30Table);\r
+ if (!(EFI_ERROR (Status) || Smbios30Table == NULL)) {\r
+ Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) Smbios30Table->TableAddress;\r
+ SmbiosEnd.Raw = (UINT8 *) (UINTN) (Smbios30Table->TableAddress + Smbios30Table->TableMaximumSize);\r
+ } else {\r
+ Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable);\r
+ if (EFI_ERROR (Status) || SmbiosTable == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress;\r
+ SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength);\r
+ }\r
+\r
+ do {\r
+ if (Smbios.Hdr->Type == 1) {\r
+ if (Smbios.Hdr->Length < 0x19) {\r
+ //\r
+ // Older version did not support UUID.\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ //\r
+ // SMBIOS tables are byte packed so we need to do a byte copy to\r
+ // prevend alignment faults on Itanium-based platform.\r
+ //\r
+ CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts:\r
+ // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed\r
+ // to skip one SMBIOS structure.\r
+ //\r
+ \r
+ //\r
+ // Step 1: Skip over formatted section.\r
+ //\r
+ String = (CHAR8 *) (Smbios.Raw + Smbios.Hdr->Length);\r
+ \r
+ //\r
+ // Step 2: Skip over unformated string section.\r
+ //\r
+ do {\r
+ //\r
+ // Each string is terminated with a NULL(00h) BYTE and the sets of strings\r
+ // is terminated with an additional NULL(00h) BYTE.\r
+ //\r
+ for ( ; *String != 0; String++) {\r
+ }\r
+\r
+ if (*(UINT8*)++String == 0) {\r
+ //\r
+ // Pointer to the next SMBIOS structure.\r
+ //\r
+ Smbios.Raw = (UINT8 *)++String;\r
+ break;\r
+ } \r
+ } while (TRUE);\r
+ } while (Smbios.Raw < SmbiosEnd.Raw);\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Create Dns QName according the queried domain name. \r
+ QName is a domain name represented as a sequence of labels, \r
+ where each label consists of a length octet followed by that \r
+ number of octets. The QName terminates with the zero \r
+ length octet for the null label of the root. Caller should \r
+ take responsibility to free the buffer in returned pointer.\r
+\r
+ @param DomainName The pointer to the queried domain name string. \r
+\r
+ @retval NULL Failed to fill QName.\r
+ @return QName filled successfully.\r
+ \r
+**/ \r
+CHAR8 *\r
+EFIAPI\r
+NetLibCreateDnsQName (\r
+ IN CHAR16 *DomainName\r
+ )\r
+{\r
+ CHAR8 *QueryName;\r
+ UINTN QueryNameSize;\r
+ CHAR8 *Header;\r
+ CHAR8 *Tail;\r
+ UINTN Len;\r
+ UINTN Index;\r
+\r
+ QueryName = NULL;\r
+ QueryNameSize = 0;\r
+ Header = NULL;\r
+ Tail = NULL;\r
+\r
+ //\r
+ // One byte for first label length, one byte for terminated length zero. \r
+ //\r
+ QueryNameSize = StrLen (DomainName) + 2;\r
+ \r
+ if (QueryNameSize > DNS_MAX_NAME_SIZE) {\r
+ return NULL;\r
+ }\r
+\r
+ QueryName = AllocateZeroPool (QueryNameSize);\r
+ if (QueryName == NULL) {\r
+ return NULL;\r
+ }\r
+ \r
+ Header = QueryName;\r
+ Tail = Header + 1;\r
+ Len = 0;\r
+ for (Index = 0; DomainName[Index] != 0; Index++) {\r
+ *Tail = (CHAR8) DomainName[Index];\r
+ if (*Tail == '.') {\r
+ *Header = (CHAR8) Len;\r
+ Header = Tail;\r
+ Tail ++;\r
+ Len = 0;\r
+ } else {\r
+ Tail++;\r
+ Len++;\r
+ }\r
+ }\r
+ *Header = (CHAR8) Len;\r
+ *Tail = 0;\r
+\r
+ return QueryName;\r
+}
\ No newline at end of file