]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
MdeModulePkg/UefiHiiLib: Validate question with bit fields
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index 583b9e516c65645d06c6e98cc674fd9f6bd1ff3e..ce894c08b573b529313c5048c1dea3f9b23a7ebe 100644 (file)
@@ -1169,6 +1169,13 @@ ValidateQuestionFromVfr (
   UINTN                        Index;\r
   CHAR16                       *QuestionName;\r
   CHAR16                       *StringPtr;\r
+  UINT16                       BitOffset;\r
+  UINT16                       BitWidth;\r
+  UINT16                       TotalBits;\r
+  UINTN                        StartBit;\r
+  UINTN                        EndBit;\r
+  BOOLEAN                      QuestionReferBitField;\r
+  UINT32                       BufferValue;\r
 \r
   //\r
   // Initialize the local variables.\r
@@ -1182,6 +1189,9 @@ ValidateQuestionFromVfr (
   IfrEfiVarStore    = NULL;\r
   ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
   ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
+  BitOffset = 0;\r
+  BitWidth = 0;\r
+  QuestionReferBitField = FALSE;\r
 \r
   //\r
   // Check IFR value is in block data, then Validate Value\r
@@ -1345,8 +1355,19 @@ ValidateQuestionFromVfr (
             //\r
             // Get Offset by Question header and Width by DataType Flags\r
             //\r
-            Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
-            Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            }\r
             //\r
             // Check whether this question is in current block array.\r
             //\r
@@ -1370,7 +1391,17 @@ ValidateQuestionFromVfr (
             // Get the current value for oneof opcode\r
             //\r
             VarValue = 0;\r
-            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            }\r
           }\r
           //\r
           // Set Block Data, to be checked in the following Oneof option opcode.\r
@@ -1416,8 +1447,19 @@ ValidateQuestionFromVfr (
             //\r
             // Get Offset by Question header and Width by DataType Flags\r
             //\r
-            Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
-            Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = IfrNumeric->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width  = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            }\r
             //\r
             // Check whether this question is in current block array.\r
             //\r
@@ -1441,77 +1483,108 @@ ValidateQuestionFromVfr (
             // Check the current value is in the numeric range.\r
             //\r
             VarValue = 0;\r
-            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
-          }\r
-          if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {\r
-            switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
-            case EFI_IFR_NUMERIC_SIZE_1:\r
-              if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_2:\r
-              if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_4:\r
-              if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_8:\r
-              if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in the bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
             }\r
+          }\r
+          if ( QuestionReferBitField) {\r
+             //\r
+             // Value in bit fields was stored as UINt32 type.\r
+             //\r
+             if ((IfrNumeric->Flags & EDKII_IFR_DISPLAY_BIT) == 0) {\r
+               if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+             } else {\r
+               if (VarValue < IfrNumeric->data.u32.MinValue || VarValue > IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+             }\r
           } else {\r
-            switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
-            case EFI_IFR_NUMERIC_SIZE_1:\r
-              if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_2:\r
-              if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
-              }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_4:\r
-              if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
+            if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {\r
+              switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+              case EFI_IFR_NUMERIC_SIZE_1:\r
+                if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_2:\r
+                if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_4:\r
+                if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_8:\r
+                if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
               }\r
-              break;\r
-            case EFI_IFR_NUMERIC_SIZE_8:\r
-              if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
-                //\r
-                // Not in the valid range.\r
-                //\r
-                return EFI_INVALID_PARAMETER;\r
+            } else {\r
+              switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+              case EFI_IFR_NUMERIC_SIZE_1:\r
+                if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_2:\r
+                if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_4:\r
+                if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_8:\r
+                if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
               }\r
-              break;\r
             }\r
           }\r
           break;\r
@@ -1554,8 +1627,19 @@ ValidateQuestionFromVfr (
             //\r
             // Get Offset by Question header\r
             //\r
-            Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
-            Width  = (UINT16) sizeof (BOOLEAN);\r
+           if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = 1;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) sizeof (BOOLEAN);\r
+            }\r
             //\r
             // Check whether this question is in current block array.\r
             //\r
@@ -1578,7 +1662,17 @@ ValidateQuestionFromVfr (
             // Check the current value is in the numeric range.\r
             //\r
             VarValue = 0;\r
-            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            }\r
           }\r
           //\r
           // Boolean type, only 1 and 0 is valid.\r
@@ -1703,6 +1797,7 @@ ValidateQuestionFromVfr (
           }\r
           break;\r
         case EFI_IFR_END_OP:\r
+          QuestionReferBitField = FALSE;\r
           //\r
           // Decrease opcode scope for the validated opcode\r
           //\r
@@ -1717,6 +1812,11 @@ ValidateQuestionFromVfr (
             return EFI_INVALID_PARAMETER;\r
           }\r
           break;\r
+        case EFI_IFR_GUID_OP:\r
+          if (CompareGuid ((EFI_GUID *)((UINT8*)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+            QuestionReferBitField = TRUE;\r
+          }\r
+          break;\r
         default:\r
           //\r
           // Increase Scope for the validated opcode\r