+// Returns TRUE if the file is byte-for-byte identical with the fallback file
+// on the volume AND if the file is not itself the fallback file; returns
+// FALSE if the file is not identical to the fallback file OR if the file
+// IS the fallback file. Intended for use in excluding the fallback boot
+// loader when it's a duplicate of another boot loader.
+BOOLEAN DuplicatesFallback(IN REFIT_VOLUME *Volume, IN CHAR16 *FileName) {
+ CHAR8 *FileContents, *FallbackContents;
+ EFI_FILE_HANDLE FileHandle, FallbackHandle;
+ EFI_FILE_INFO *FileInfo, *FallbackInfo;
+ UINTN FileSize = 0, FallbackSize = 0;
+ EFI_STATUS Status;
+ BOOLEAN AreIdentical = FALSE;
+
+ CleanUpPathNameSlashes(FileName);
+
+ if (StriCmp(FileName, FALLBACK_FULLNAME) == 0)
+ return FALSE; // identical filenames, so not a duplicate....
+
+ Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
+ if (Status == EFI_SUCCESS) {
+ FileInfo = LibFileInfo(FileHandle);
+ FileSize = FileInfo->FileSize;
+ } else {
+ return FALSE;
+ }
+
+ Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FallbackHandle, FALLBACK_FULLNAME, EFI_FILE_MODE_READ, 0);
+ if (Status == EFI_SUCCESS) {
+ FallbackInfo = LibFileInfo(FallbackHandle);
+ FallbackSize = FallbackInfo->FileSize;
+ } else {
+ refit_call1_wrapper(FileHandle->Close, FileHandle);
+ return FALSE;
+ }
+
+ if (FallbackSize != FileSize) { // not same size, so can't be identical
+ AreIdentical = FALSE;
+ } else { // could be identical; do full check....
+ FileContents = AllocatePool(FileSize);
+ FallbackContents = AllocatePool(FallbackSize);
+ if (FileContents && FallbackContents) {
+ Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &FileSize, FileContents);
+ if (Status == EFI_SUCCESS)
+ Status = refit_call3_wrapper(FallbackHandle->Read, FallbackHandle, &FallbackSize, FallbackContents);
+ if (Status == EFI_SUCCESS) {
+ AreIdentical = (CompareMem(FileContents, FallbackContents, FileSize) == 0);
+ } // if
+ } // if
+ MyFreePool(FileContents);
+ MyFreePool(FallbackContents);
+ } // if/else
+
+ refit_call1_wrapper(FileHandle->Close, FileHandle);
+ refit_call1_wrapper(FileHandle->Close, FallbackHandle);
+ return AreIdentical;
+
+} // BOOLEAN DuplicatesFallback()
+