+/**\r
+ Returns the size of a device path in bytes.\r
+\r
+ This function returns the size, in bytes, of the device path data structure \r
+ specified by DevicePath including the end of device path node. If DevicePath \r
+ is NULL, then 0 is returned. If the length of the device path is bigger than\r
+ MaxSize, also return 0 to indicate this is an invalidate device path.\r
+\r
+ @param DevicePath A pointer to a device path data structure.\r
+ @param MaxSize Max valid device path size. If big than this size, \r
+ return error.\r
+ \r
+ @retval 0 An invalid device path.\r
+ @retval Others The size of a device path in bytes.\r
+\r
+**/\r
+UINTN\r
+GetDevicePathSizeEx (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINTN MaxSize\r
+ )\r
+{\r
+ UINTN Size;\r
+ UINTN NodeSize;\r
+\r
+ if (DevicePath == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Search for the end of the device path structure\r
+ //\r
+ Size = 0;\r
+ while (!IsDevicePathEnd (DevicePath)) {\r
+ NodeSize = DevicePathNodeLength (DevicePath);\r
+ if (NodeSize < END_DEVICE_PATH_LENGTH) {\r
+ return 0;\r
+ }\r
+ Size += NodeSize;\r
+ if (Size > MaxSize) {\r
+ return 0;\r
+ }\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ }\r
+ Size += DevicePathNodeLength (DevicePath);\r
+ if (Size > MaxSize) {\r
+ return 0;\r
+ }\r
+\r
+ return Size;\r
+}\r
+\r
+/**\r
+ Returns the length of a Null-terminated Unicode string. If the length is \r
+ bigger than MaxStringLen, return length 0 to indicate that this is an \r
+ invalidate string.\r
+\r
+ This function returns the byte length of Unicode characters in the Null-terminated\r
+ Unicode string specified by String. \r
+\r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ @param String A pointer to a Null-terminated Unicode string.\r
+ @param MaxStringLen Max string len in this string.\r
+\r
+ @retval 0 An invalid string.\r
+ @retval Others The length of String.\r
+\r
+**/\r
+UINTN\r
+StrSizeEx (\r
+ IN CONST CHAR16 *String,\r
+ IN UINTN MaxStringLen\r
+ )\r
+{\r
+ UINTN Length;\r
+\r
+ ASSERT (String != NULL && MaxStringLen != 0);\r
+ ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+ for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);\r
+\r
+ if (*String != L'\0' && MaxStringLen == Length) {\r
+ return 0;\r
+ }\r
+\r
+ return Length + 2;\r
+}\r
+\r
+/**\r
+ Validate the EFI Boot#### variable (VendorGuid/Name)\r
+\r
+ @param Variable Boot#### variable data.\r
+ @param VariableSize Returns the size of the EFI variable that was read\r
+\r
+ @retval TRUE The variable data is correct.\r
+ @retval FALSE The variable data is corrupted.\r
+\r
+**/\r
+BOOLEAN \r
+ValidateOption (\r
+ UINT8 *Variable,\r
+ UINTN VariableSize\r
+ )\r
+{\r
+ UINT16 FilePathSize;\r
+ UINT8 *TempPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN TempSize;\r
+\r
+ if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Skip the option attribute\r
+ //\r
+ TempPtr = Variable;\r
+ TempPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // Get the option's device path size\r
+ //\r
+ FilePathSize = *(UINT16 *) TempPtr;\r
+ TempPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Get the option's description string size\r
+ //\r
+ TempSize = StrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));\r
+ TempPtr += TempSize;\r
+\r
+ //\r
+ // Get the option's device path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+ TempPtr += FilePathSize;\r
+\r
+ //\r
+ // Validation boot option variable.\r
+ //\r
+ if ((FilePathSize == 0) || (TempSize == 0)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {\r
+ return FALSE;\r
+ }\r
+\r
+ return (BOOLEAN) (GetDevicePathSizeEx (DevicePath, FilePathSize) != 0);\r
+}\r
+\r
+/**\r
+ Convert a single character to number.\r
+ It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'\r
+ \r
+ @param Char The input char which need to change to a hex number.\r
+ \r
+**/\r
+UINTN\r
+CharToUint (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if ((Char >= L'0') && (Char <= L'9')) {\r
+ return (UINTN) (Char - L'0');\r
+ }\r
+\r
+ if ((Char >= L'A') && (Char <= L'F')) {\r
+ return (UINTN) (Char - L'A' + 0xA);\r
+ }\r
+\r
+ ASSERT (FALSE);\r
+ return 0;\r
+}\r