]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c
Update Performance library instances to adapt to the update in Performance infrastruc...
[mirror_edk2.git] / MdeModulePkg / Library / UefiIfrSupportLib / UefiIfrForm.c
index 878898ffeab8e567e44926522db1c4ca21cebf00..9e6d3382f70682e6fa80e684e70ba650c91069fb 100644 (file)
@@ -17,6 +17,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \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
@@ -49,11 +55,6 @@ LocateFormBrowser2Protocols (
   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
@@ -341,10 +342,10 @@ ExtractBlockName (
   //                 |   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
@@ -521,6 +522,13 @@ ConstructConfigAltResp (
   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
@@ -534,39 +542,47 @@ ConstructConfigAltResp (
              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
@@ -586,36 +602,48 @@ ConstructConfigAltResp (
     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
@@ -624,7 +652,7 @@ ConstructConfigAltResp (
   TempStr = AllocateZeroPool (StrBufferLen);\r
   *ConfigAltResp = TempStr;\r
   if (TempStr == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
   }\r
 \r
   //\r
@@ -637,16 +665,26 @@ ConstructConfigAltResp (
     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
@@ -935,6 +973,11 @@ ConstructConfigHdr (
   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
@@ -966,7 +1009,7 @@ ConstructConfigHdr (
   // | 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
@@ -1087,7 +1130,7 @@ IsConfigHdrMatch (
     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
@@ -1212,7 +1255,7 @@ GetBrowserData (
   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
@@ -1228,9 +1271,7 @@ GetBrowserData (
                            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
@@ -1391,3 +1432,223 @@ SetBrowserData (
   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