\r
CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;\r
CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mIfrSupportLibHiiConfigRouting = NULL;\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mIfrSupportLibHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
+\r
+//\r
+// Fake <ConfigHdr>\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
\r
/**\r
This function locate FormBrowser2 protocols for later usage.\r
return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Fake <ConfigHdr>\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
-\r
/**\r
Draw a dialog and return the selected key.\r
\r
// | 8 | 4 | 7 | 4 |\r
//\r
StringPtr = AllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));\r
- *BlockName = StringPtr;\r
if (StringPtr == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+ *BlockName = StringPtr;\r
\r
Buffer += sizeof (UINT32);\r
for (Index = 0; Index < BlockNameNumber; Index++) {\r
if (ConfigAltResp == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+ \r
+ DescHdr = NULL;\r
+ StringPtr = NULL;\r
+ AltCfg = NULL;\r
+ ConfigResp = NULL;\r
+ BlockName = NULL;\r
+ NeedFreeConfigRequest = FALSE;\r
\r
//\r
// Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
Name,\r
DriverHandle\r
);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- ConfigHdr = AllocateZeroPool (StrBufferLen);\r
- Status = ConstructConfigHdr (\r
- ConfigHdr,\r
- &StrBufferLen,\r
- Guid,\r
- Name,\r
- DriverHandle\r
- );\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+ ConfigHdr = AllocateZeroPool (StrBufferLen);\r
+ if (ConfigHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
}\r
+ Status = ConstructConfigHdr (\r
+ ConfigHdr,\r
+ &StrBufferLen,\r
+ Guid,\r
+ Name,\r
+ DriverHandle\r
+ );\r
\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
//\r
// Construct <ConfigResp>\r
//\r
- NeedFreeConfigRequest = FALSE;\r
if (ConfigRequest == NULL) {\r
//\r
// If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray\r
//\r
Status = ExtractBlockName (BlockNameArray, &BlockName);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
Len = StrSize (ConfigHdr);\r
ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16));\r
+ if (ConfigRequest == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
StrCpy (ConfigRequest, ConfigHdr);\r
StrCat (ConfigRequest, BlockName);\r
NeedFreeConfigRequest = TRUE;\r
+\r
}\r
\r
Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
return Status;\r
}\r
\r
+ AltRespLen = 0;\r
//\r
// Construct <AltResp>\r
//\r
- DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));\r
- StringPtr = DescHdr;\r
- AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));\r
- AltRespLen = 0;\r
- VA_START (Args, NumberAltCfg);\r
- for (Index = 0; Index < NumberAltCfg; Index++) {\r
- AltCfgId = (UINT16) VA_ARG (Args, UINT16);\r
- DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);\r
-\r
- //\r
- // '&' <ConfigHdr>\r
- //\r
- AltRespLen += (StrLen (ConfigHdr) + 1);\r
-\r
- StringPtr = DescHdr + Index * 16;\r
- StrCpy (StringPtr, L"&ALTCFG=");\r
- AltRespLen += (8 + sizeof (UINT16) * 2);\r
+ if (NumberAltCfg > 0) {\r
+ DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));\r
+ if (DescHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ StringPtr = DescHdr;\r
+ AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));\r
+ if (AltCfg == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
\r
- StrBufferLen = 5;\r
- BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));\r
- Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ VA_START (Args, NumberAltCfg);\r
+ for (Index = 0; Index < NumberAltCfg; Index++) {\r
+ AltCfgId = (UINT16) VA_ARG (Args, UINT16);\r
+ DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);\r
+ \r
+ //\r
+ // '&' <ConfigHdr>\r
+ //\r
+ AltRespLen += (StrLen (ConfigHdr) + 1);\r
+ \r
+ StringPtr = DescHdr + Index * 16;\r
+ StrCpy (StringPtr, L"&ALTCFG=");\r
+ AltRespLen += (8 + sizeof (UINT16) * 2);\r
+ \r
+ StrBufferLen = 5;\r
+ BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));\r
+ Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ AltRespLen += StrLen (AltCfg[Index]);\r
}\r
- AltRespLen += StrLen (AltCfg[Index]);\r
+ VA_END (Args);\r
}\r
- VA_END (Args);\r
\r
//\r
// Generate the final <ConfigAltResp>\r
TempStr = AllocateZeroPool (StrBufferLen);\r
*ConfigAltResp = TempStr;\r
if (TempStr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
}\r
\r
//\r
StrCat (TempStr, DescHdr + Index * 16);\r
StrCat (TempStr, AltCfg[Index]);\r
\r
- gBS->FreePool (AltCfg[Index]);\r
+ FreePool (AltCfg[Index]);\r
}\r
\r
+Exit:\r
if (NeedFreeConfigRequest) {\r
- gBS->FreePool (ConfigRequest);\r
+ FreePool (ConfigRequest);\r
+ }\r
+ FreePool (ConfigHdr);\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
+\r
+ if (BlockName != NULL) {\r
+ FreePool (BlockName);\r
+ }\r
+\r
+ if (NumberAltCfg > 0) {\r
+ FreePool (DescHdr);\r
+ FreePool (AltCfg);\r
}\r
- gBS->FreePool (ConfigHdr);\r
- gBS->FreePool (ConfigResp);\r
- gBS->FreePool (DescHdr);\r
- gBS->FreePool (AltCfg);\r
\r
return EFI_SUCCESS;\r
}\r
CHAR16 *StrPtr;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
\r
+ //\r
+ // Make sure when ConfigHdr is NULL, StrBufferlen must be 0\r
+ //\r
+ ASSERT (!(ConfigHdr == NULL && *StrBufferLen != 0));\r
+\r
if (Name == NULL) {\r
//\r
// There will be no "NAME" in <ConfigHdr> for Name/Value storage\r
// | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
//\r
BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);\r
- if (*StrBufferLen < BufferSize) {\r
+ if ((*StrBufferLen == 0) || *StrBufferLen < BufferSize) {\r
*StrBufferLen = BufferSize;\r
return EFI_BUFFER_TOO_SMALL;\r
}\r
if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) {\r
Match = FALSE;\r
}\r
- gBS->FreePool (Name);\r
+ FreePool (Name);\r
}\r
\r
return Match;\r
BufferLen = 0x4000;\r
ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
if (ConfigResp == NULL) {\r
- BufferLen = 0;\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
StringPtr = ConfigResp + HeaderLen;\r
VariableName\r
);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
- if (ConfigResp != NULL) {\r
- FreePool (ConfigResp);\r
- }\r
+ FreePool (ConfigResp);\r
\r
ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
if (ConfigResp == NULL) {\r
FreePool (ConfigRequest);\r
return Status;\r
}\r
+\r
+/**\r
+ Test if a Unicode character is a hexadecimal digit. If true, the input\r
+ Unicode character is converted to a byte. \r
+\r
+ This function tests if a Unicode character is a hexadecimal digit. If true, the input\r
+ Unicode character is converted to a byte. For example, Unicode character\r
+ L'A' will be converted to 0x0A. \r
+\r
+ If Digit is NULL, then ASSERT.\r
+\r
+ @param Digit The output hexadecimal digit.\r
+\r
+ @param Char The input Unicode character.\r
+\r
+ @retval TRUE Char is in the range of Hexadecimal number. Digit is updated\r
+ to the byte value of the number.\r
+ @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep\r
+ intact.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsHexDigit (\r
+ OUT UINT8 *Digit,\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ ASSERT (Digit != NULL);\r
+ \r
+ if ((Char >= L'0') && (Char <= L'9')) {\r
+ *Digit = (UINT8) (Char - L'0');\r
+ return TRUE;\r
+ }\r
+\r
+ if ((Char >= L'A') && (Char <= L'F')) {\r
+ *Digit = (UINT8) (Char - L'A' + 0x0A);\r
+ return TRUE;\r
+ }\r
+\r
+ if ((Char >= L'a') && (Char <= L'f')) {\r
+ *Digit = (UINT8) (Char - L'a' + 0x0A);\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/** \r
+ Convert binary buffer to a Unicode String in a specified sequence. \r
+\r
+ This function converts bytes in the memory block pointed by Buffer to a Unicode String Str. \r
+ Each byte will be represented by two Unicode characters. For example, byte 0xA1 will \r
+ be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character \r
+ for the Most Significant Nibble will be put before the Unicode Character for the Least Significant\r
+ Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1". \r
+ For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the \r
+ the last character in the output string. The one next to first byte will be put into the\r
+ character before the last character. This rules applies to the rest of the bytes. The Unicode\r
+ character by the last byte will be put into the first character in the output string. For example,\r
+ the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to\r
+ a Unicode string equal to L"12345678abcdef1234".\r
+\r
+ @param String On input, String is pointed to the buffer allocated for the convertion.\r
+ @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.\r
+ The StringLen required to convert a N bytes Buffer will be a least equal to or greater \r
+ than 2*N + 1.\r
+ @param Buffer The pointer to a input buffer.\r
+ @param BufferSizeInBytes Length in bytes of the input buffer.\r
+\r
+\r
+ @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding\r
+ Unicode character and placed into the right place in String.\r
+ @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to\r
+ complete the convertion. \r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+BufToHexString (\r
+ IN OUT CHAR16 *String,\r
+ IN OUT UINTN *StringLen,\r
+ IN CONST UINT8 *Buffer,\r
+ IN UINTN BufferSizeInBytes\r
+ )\r
+{\r
+ UINTN Idx;\r
+ UINT8 Byte;\r
+ UINTN StrLen;\r
+\r
+ //\r
+ // Make sure string is either passed or allocate enough.\r
+ // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
+ // Plus the Unicode termination character.\r
+ //\r
+ StrLen = BufferSizeInBytes * 2;\r
+ if (StrLen > ((*StringLen) - 1)) {\r
+ *StringLen = StrLen + 1;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *StringLen = StrLen + 1;\r
+ //\r
+ // Ends the string.\r
+ //\r
+ String[StrLen] = L'\0'; \r
+\r
+ for (Idx = 0; Idx < BufferSizeInBytes; Idx++) {\r
+ Byte = Buffer[Idx];\r
+ String[StrLen - 1 - Idx * 2] = mIfrSupportLibHexStr [Byte & 0xF];\r
+ String[StrLen - 2 - Idx * 2] = mIfrSupportLibHexStr [Byte >> 4];\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.\r
+\r
+ This function converts a Unicode string consisting of characters in the range of Hexadecimal\r
+ character (L'0' to L'9', L'A' to L'F' and L'a' to L'f') to a output byte buffer. The function will stop\r
+ at the first non-hexadecimal character or the NULL character. The convertion process can be\r
+ simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be \r
+ converted into one byte. The first Unicode character represents the Most Significant Nibble and the\r
+ second Unicode character represents the Least Significant Nibble in the output byte. \r
+ The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode \r
+ characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes. \r
+ The last pair represent the first byte in the output buffer. \r
+\r
+ For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes \r
+ (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".\r
+\r
+ If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least \r
+ N/2 (if N is even) or (N+1)/2 (if N if odd) bytes. \r
+\r
+ If either Buffer, BufferSizeInBytes or String is NULL, then ASSERT ().\r
+\r
+ @param Buffer The output buffer allocated by the caller.\r
+ @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to \r
+ contain the size of the Buffer which is actually used for the converstion.\r
+ For Unicode string with 2*N hexadecimal characters (not including the \r
+ tailing NULL character), N bytes of Buffer will be used for the output.\r
+ @param String The input hexadecimal string.\r
+ @param ConvertedStrLen The number of hexadecimal characters used to produce content in output\r
+ buffer Buffer.\r
+\r
+ @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes\r
+ will be updated to the size required for the converstion.\r
+ @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String\r
+ is hexadecimal. If ConvertedStrLen is not NULL, it is updated\r
+ to the number of hexadecimal character used for the converstion.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+HexStringToBuf (\r
+ OUT UINT8 *Buffer, \r
+ IN OUT UINTN *BufferSizeInBytes,\r
+ IN CONST CHAR16 *String,\r
+ OUT UINTN *ConvertedStrLen OPTIONAL\r
+ )\r
+{\r
+ UINTN HexCnt;\r
+ UINTN Idx;\r
+ UINTN BufferLength;\r
+ UINT8 Digit;\r
+ UINT8 Byte;\r
+\r
+ ASSERT (Buffer != NULL);\r
+ ASSERT (BufferSizeInBytes != NULL);\r
+ ASSERT (String != NULL);\r
+\r
+ //\r
+ // Find out how many hex characters the string has.\r
+ //\r
+ for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, String[Idx]); Idx++, HexCnt++);\r
+\r
+ if (HexCnt == 0) {\r
+ *ConvertedStrLen = 0;\r
+ return RETURN_SUCCESS;\r
+ }\r
+ //\r
+ // Two Unicode characters make up 1 buffer byte. Round up.\r
+ //\r
+ BufferLength = (HexCnt + 1) / 2; \r
+\r
+ //\r
+ // Test if buffer is passed enough.\r
+ //\r
+ if (BufferLength > (*BufferSizeInBytes)) {\r
+ *BufferSizeInBytes = BufferLength;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *BufferSizeInBytes = BufferLength;\r
+\r
+ for (Idx = 0; Idx < HexCnt; Idx++) {\r
+\r
+ IsHexDigit (&Digit, String[HexCnt - 1 - Idx]);\r
+\r
+ //\r
+ // For odd charaters, write the lower nibble for each buffer byte,\r
+ // and for even characters, the upper nibble.\r
+ //\r
+ if ((Idx & 1) == 0) {\r
+ Byte = Digit;\r
+ } else {\r
+ Byte = Buffer[Idx / 2];\r
+ Byte &= 0x0F;\r
+ Byte = (UINT8) (Byte | Digit << 4);\r
+ }\r
+\r
+ Buffer[Idx / 2] = Byte;\r
+ }\r
+\r
+ if (ConvertedStrLen != NULL) {\r
+ *ConvertedStrLen = HexCnt;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r