[BOOTLIB]:

- Fix multiple bugs in ETFS code (confusion between file offset vs. disk offset)
- Implement EtfsGetInformation, EtfsSetInformation, and fix ETFS_FILE definition to make this easy.
- Implement EtfsRead.
- Fix multiple bugs in file I/O code (swapped/reversed validation checks)
- Make BlStatusPrint call EfiPrintf on debug builds, even without BD.
- Add some additional error logging.

svn path=/trunk/; revision=69452
This commit is contained in:
Alex Ionescu 2015-10-05 05:53:40 +00:00
parent 10dbbf573b
commit 0cc3cfadf3
6 changed files with 170 additions and 29 deletions

View file

@ -49,7 +49,7 @@ typedef struct _BL_PACKED_BOOT_ERROR
ULONG Size;
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
#define BL_FATAL_ERROR_BCD_READ 0x02
#define BL_FATAL_ERROR_BCD_READ 0x01
/* FUNCTIONS *****************************************************************/

View file

@ -321,7 +321,7 @@ NTSTATUS
_In_ struct _BL_FILE_ENTRY* FileEntry,
_In_ PVOID Buffer,
_In_ ULONG Size,
_Out_ PULONG BytesRead
_Out_opt_ PULONG BytesRead
);
typedef
@ -786,8 +786,10 @@ typedef struct _BL_ADDRESS_RANGE
typedef struct _BL_FILE_INFORMATION
{
ULONGLONG FileSize;
ULONGLONG CurrentOffset;
ULONGLONG Size;
ULONGLONG Offset;
PWCHAR FsName;
ULONG Flags;
} BL_FILE_INFORMATION, *PBL_FILE_INFORMATION;
typedef struct _BL_FILE_CALLBACKS
@ -809,7 +811,7 @@ typedef struct _BL_FILE_ENTRY
ULONG Flags;
ULONG ReferenceCount;
ULONG Unknown;
ULONGLONG Unknown1;
ULONGLONG TotalBytesRead;
ULONGLONG Unknown2;
BL_FILE_CALLBACKS Callbacks;
PVOID FsSpecificData;

View file

@ -36,12 +36,12 @@ typedef struct _BL_ETFS_DEVICE
typedef struct _BL_ETFS_FILE
{
ULONG DiskOffset;
ULONG DirOffset;
ULONG DirEntOffset;
ULONGLONG Size;
ULONGLONG Offset;
PWCHAR FsName;
ULONG Flags;
BL_FILE_INFORMATION;
ULONG DeviceId;
} BL_ETFS_FILE, *PBL_ETFS_FILE;
@ -56,9 +56,35 @@ EtfsOpen (
_Out_ PBL_FILE_ENTRY *FileEntry
);
NTSTATUS
EtfsGetInformation (
_In_ PBL_FILE_ENTRY FileEntry,
_Out_ PBL_FILE_INFORMATION FileInfo
);
NTSTATUS
EtfsSetInformation (
_In_ PBL_FILE_ENTRY FileEntry,
_In_ PBL_FILE_INFORMATION FileInfo
);
NTSTATUS
EtfsRead (
_In_ PBL_FILE_ENTRY FileEntry,
_In_ PVOID Buffer,
_In_ ULONG Size,
_Out_opt_ PULONG BytesReturned
);
BL_FILE_CALLBACKS EtfsFunctionTable =
{
EtfsOpen,
NULL,
EtfsRead,
NULL,
NULL,
EtfsGetInformation,
EtfsSetInformation
};
/* FUNCTIONS *****************************************************************/
@ -205,7 +231,7 @@ EtfspGetDirent (
EtfsFile = DirectoryEntry->FsSpecificData;
DeviceId = EtfsFile->DeviceId;
FileOffset = EtfsFile->Offset;
FileOffset = EtfsFile->DiskOffset;
EtfsDevice = EtfsDeviceTable[DeviceId];
DirectoryOffset = *DirentOffset;
@ -362,7 +388,7 @@ EtfspCachedSearchForDirent (
DirentOffset = EtfsFile->DirEntOffset;
if ((KeepOffset) ||
(ALIGN_DOWN_BY((DirentOffset + EtfsFile->Offset), CD_SECTOR_SIZE) ==
(ALIGN_DOWN_BY((DirentOffset + EtfsFile->DiskOffset), CD_SECTOR_SIZE) ==
EtfsDevice->Offset))
{
Status = EtfspGetDirent(DirectoryEntry, &Dirent, &DirentOffset);
@ -406,6 +432,108 @@ EtfspCachedSearchForDirent (
return Status;
}
NTSTATUS
EtfsRead (
_In_ PBL_FILE_ENTRY FileEntry,
_In_ PVOID Buffer,
_In_ ULONG Size,
_Out_opt_ PULONG BytesReturned
)
{
ULONG BytesRead;
PBL_ETFS_FILE EtfsFile;
NTSTATUS Status;
/* Assume failure for now */
BytesRead = 0;
/* Make sure that the read is within the file's boundaries */
EtfsFile = FileEntry->FsSpecificData;
if ((Size + EtfsFile->Offset) > EtfsFile->Size)
{
/* Bail out otherwise */
Status = STATUS_INVALID_PARAMETER;
}
else
{
/* Read the offset that matches this file's offset, on the disk */
Status = BlDeviceReadAtOffset(FileEntry->DeviceId,
Size,
EtfsFile->Offset + EtfsFile->DiskOffset,
Buffer,
&BytesRead);
if (NT_SUCCESS(Status))
{
/* Update the file offset and return the size as having been read */
EtfsFile->Offset += Size;
BytesRead = Size;
}
}
/* Check if caller wanted to know how many bytes were read */
if (BytesReturned)
{
/* Return the value */
*BytesReturned = BytesRead;
}
/* All done */
return Status;
}
NTSTATUS
EtfsSetInformation (
_In_ PBL_FILE_ENTRY FileEntry,
_In_ PBL_FILE_INFORMATION FileInfo
)
{
PBL_ETFS_FILE EtfsFile;
BL_FILE_INFORMATION LocalFileInfo;
/* Get the underlying ETFS file data structure */
EtfsFile = (PBL_ETFS_FILE)FileEntry->FsSpecificData;
/* Make a copy of the incoming attributes, but ignore the new offset */
LocalFileInfo = *FileInfo;
LocalFileInfo.Offset = EtfsFile->Offset;
/* Check if these match exactly the current file */
if (!RtlEqualMemory(&LocalFileInfo, &EtfsFile->Size, sizeof(*FileInfo)))
{
/* Nope -- which means caller is trying to change an immutable */
EfiPrintf(L"Incorrect information change\r\n");
return STATUS_INVALID_PARAMETER;
}
/* Is the offset past the end of the file? */
if (FileInfo->Offset >= EtfsFile->Size)
{
/* Don't allow EOF */
EfiPrintf(L"Offset too large: %lx vs %lx \r\n", FileInfo->Offset, EtfsFile->Size);
return STATUS_INVALID_PARAMETER;
}
/* Update the offset */
EtfsFile->Offset = FileInfo->Offset;
return STATUS_SUCCESS;
}
NTSTATUS
EtfsGetInformation (
_In_ PBL_FILE_ENTRY FileEntry,
_Out_ PBL_FILE_INFORMATION FileInfo
)
{
PBL_ETFS_FILE EtfsFile;
/* Get the underlying ETFS file data structure */
EtfsFile = (PBL_ETFS_FILE)FileEntry->FsSpecificData;
/* Copy the cached information structure within it */
RtlCopyMemory(FileInfo, &EtfsFile->Size, sizeof(*FileInfo));
return STATUS_SUCCESS;
}
NTSTATUS
EtfsOpen (
_In_ PBL_FILE_ENTRY Directory,
@ -486,7 +614,7 @@ EtfsOpen (
RtlCopyMemory(&NewFile->Callbacks,
&EtfsFunctionTable,
sizeof(NewFile->Callbacks));
EtfsFile->Offset = FileOffset;
EtfsFile->DiskOffset = FileOffset;
EtfsFile->DirOffset = DirOffset;
EtfsFile->Size = FileSize;
EtfsFile->DeviceId = DeviceId;
@ -794,7 +922,7 @@ EtfsMount (
RootEntry->FsSpecificData = EtfsFile;
EtfsFile->DeviceId = DeviceId;
EtfsFile->Flags |= 1;
EtfsFile->Offset = EtfsDevice->RootDirOffset;
EtfsFile->DiskOffset = EtfsDevice->RootDirOffset;
EtfsFile->DirOffset = 0;
EtfsFile->Size = EtfsDevice->RootDirSize;
EtfsFile->FsName = L"cdfs";

View file

@ -434,7 +434,7 @@ FileOpened:
if (++FileEntry->ReferenceCount == 1)
{
/* Reset unknowns */
FileEntry->Unknown1 = 0;
FileEntry->TotalBytesRead = 0;
FileEntry->Unknown2 = 0;
}
@ -548,7 +548,7 @@ BlFileSetInformation (
}
/* Validate file ID */
if (FileEntries > FileId)
if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
@ -579,7 +579,7 @@ BlFileGetInformation (
}
/* Validate file ID */
if (FileEntries > FileId)
if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
@ -612,7 +612,7 @@ FileInformationCheck (
Size = 0;
/* Make sure we didn't overshoot */
if (FileInformation->CurrentOffset > FileInformation->FileSize)
if (FileInformation->Offset > FileInformation->Size)
{
/* Bail out */
Status = STATUS_INVALID_PARAMETER;
@ -621,9 +621,9 @@ FileInformationCheck (
/* Compute the appropriate 32-bit size of this read, based on file size */
Size = ULONG_MAX;
if ((FileInformation->FileSize - FileInformation->CurrentOffset) <= ULONG_MAX)
if ((FileInformation->Size - FileInformation->Offset) <= ULONG_MAX)
{
Size = (ULONG)(FileInformation->FileSize) - (ULONG)(FileInformation->CurrentOffset);
Size = (ULONG)(FileInformation->Size) - (ULONG)(FileInformation->Offset);
}
/* Check if the caller has an input buffer */
@ -683,7 +683,7 @@ BlFileReadEx (
}
/* Bail out of the file ID is invalid */
if (FileEntries > FileId)
if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
@ -774,7 +774,7 @@ BlFileReadEx (
}
/* Increment the number of bytes read */
FileEntry->Unknown1 += RequiredSize;
FileEntry->TotalBytesRead += RequiredSize;
/* Check if the unknown flag on the device was changed during this routine */
if (ChangedUnknown)
@ -811,8 +811,8 @@ BlFileReadAtOffsetEx (
}
/* Save the current offset, and overwrite it with the one we want */
FileOffset = FileInfo.CurrentOffset;
FileInfo.CurrentOffset = ByteOffset;
FileOffset = FileInfo.Offset;
FileInfo.Offset = ByteOffset;
/* Check the validity of the read and the actual size to read */
RequiredSize = Size;
@ -824,11 +824,12 @@ BlFileReadAtOffsetEx (
if (!NT_SUCCESS(Status))
{
/* Bail out if the read is invalid */
EfiPrintf(L"File info check failure: %lx\n", Status);
return Status;
}
/* Check if the offset we're requesting is not the current offset */
if (FileInfo.CurrentOffset != FileOffset)
if (FileInfo.Offset != FileOffset)
{
/* Set the new offset to use */
Status = BlFileSetInformation(FileId, &FileInfo);
@ -848,10 +849,10 @@ BlFileReadAtOffsetEx (
if (!NT_SUCCESS(Status))
{
/* The read failed -- had we modified the offset? */
if (FileInfo.CurrentOffset != FileOffset)
if (FileInfo.Offset != FileOffset)
{
/* Restore the offset back to its original value */
FileInfo.CurrentOffset = FileOffset;
FileInfo.Offset = FileOffset;
BlFileSetInformation(FileId, &FileInfo);
}
}

View file

@ -83,11 +83,19 @@ BlStatusPrint (
va_start(va, Format);
/* Check if the boot debugger is enabled */
if (BlBdDebuggerEnabled())
if (BlBdDebuggerEnabled()
#if (defined(DBG))
|| TRUE
#endif
)
{
/* Print the string out into a buffer */
if (vswprintf(BlScratchBuffer, Format, va) > 0)
{
#if defined(DBG)
EfiPrintf(BlScratchBuffer);
EfiPrintf(L"\r\n");
#endif
/* Make it a UNICODE_STRING */
RtlInitUnicodeString(&UnicodeString, BlScratchBuffer);

View file

@ -39,8 +39,8 @@ ImgpGetFileSize (
}
/* We only support files less than 4GB in the Image Mapped */
Size = FileInformation.FileSize;
if (FileInformation.FileSize > ULONG_MAX)
Size = FileInformation.Size;
if (FileInformation.Size > ULONG_MAX)
{
return STATUS_NOT_SUPPORTED;
}
@ -392,6 +392,7 @@ BlImgLoadImageWithProgress2 (
Status = ImgpOpenFile(DeviceId, FileName, DeviceId, &FileHandle);
if (!NT_SUCCESS(Status))
{
EfiPrintf(L"Error opening file: %lx\r\n", Status);
goto Quickie;
}
@ -399,6 +400,7 @@ BlImgLoadImageWithProgress2 (
Status = ImgpGetFileSize(&FileHandle, &ImageSize);
if (!NT_SUCCESS(Status))
{
EfiPrintf(L"Error getting file size: %lx\r\n", Status);
goto Quickie;
}