+/**\r
+ Check whether Left and Right are the same without matching the specific\r
+ device path data in IP device path and URI device path node.\r
+\r
+ @retval TRUE Left and Right are the same.\r
+ @retval FALSE Left and Right are the different.\r
+**/\r
+BOOLEAN\r
+BmMatchHttpBootDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Left,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Right\r
+ )\r
+{\r
+ for (; !IsDevicePathEnd (Left) && !IsDevicePathEnd (Right)\r
+ ; Left = NextDevicePathNode (Left), Right = NextDevicePathNode (Right)\r
+ ) {\r
+ if (CompareMem (Left, Right, DevicePathNodeLength (Left)) != 0) {\r
+ if ((DevicePathType (Left) != MESSAGING_DEVICE_PATH) || (DevicePathType (Right) != MESSAGING_DEVICE_PATH)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (((DevicePathSubType (Left) != MSG_IPv4_DP) || (DevicePathSubType (Right) != MSG_IPv4_DP)) &&\r
+ ((DevicePathSubType (Left) != MSG_IPv6_DP) || (DevicePathSubType (Right) != MSG_IPv6_DP)) &&\r
+ ((DevicePathSubType (Left) != MSG_URI_DP) || (DevicePathSubType (Right) != MSG_URI_DP))\r
+ ) {\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+ return (BOOLEAN) (IsDevicePathEnd (Left) && IsDevicePathEnd (Right));\r
+}\r
+\r
+/**\r
+ Get the file buffer from Load File instance.\r
+\r
+ @param FilePath The media device path pointing to a LoadFile instance.\r
+ @param FullPath Return the full device path pointing to the load option.\r
+ @param FileSize Return the size of the load option.\r
+\r
+ @return The load option buffer.\r
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFile (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
+ OUT UINTN *FileSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ VOID *FileBuffer;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+ UINTN BufferSize;\r
+\r
+ //\r
+ // Get file buffer from load file instance.\r
+ //\r
+ Node = FilePath;\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {\r
+ //\r
+ // When wide match happens, pass full device path to LoadFile (),\r
+ // otherwise, pass remaining device path to LoadFile ().\r
+ //\r
+ FilePath = Node;\r
+ } else {\r
+ Handle = NULL;\r
+ //\r
+ // Use wide match algorithm to find one when\r
+ // cannot find a LoadFile instance to exactly match the FilePath\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadFileProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Handles = NULL;\r
+ HandleCount = 0;\r
+ }\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ if (BmMatchHttpBootDevicePath (DevicePathFromHandle (Handles[Index]), FilePath)) {\r
+ Handle = Handles[Index];\r
+ break;\r
+ }\r
+ }\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+ }\r
+\r
+ if (Handle == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **) &LoadFile);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ BufferSize = 0;\r
+ FileBuffer = NULL;\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FileBuffer = AllocatePool (BufferSize);\r
+ if (FileBuffer != NULL) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // LoadFile () may cause the device path of the Handle be updated.\r
+ //\r
+ *FullPath = DuplicateDevicePath (DevicePathFromHandle (Handle));\r
+ *FileSize = BufferSize;\r
+ return FileBuffer;\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+\r