[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; ULONG Size;
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR; } BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
#define BL_FATAL_ERROR_BCD_READ 0x02 #define BL_FATAL_ERROR_BCD_READ 0x01
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/

View file

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

View file

@ -36,12 +36,12 @@ typedef struct _BL_ETFS_DEVICE
typedef struct _BL_ETFS_FILE typedef struct _BL_ETFS_FILE
{ {
ULONG DiskOffset;
ULONG DirOffset; ULONG DirOffset;
ULONG DirEntOffset; ULONG DirEntOffset;
ULONGLONG Size;
ULONGLONG Offset; BL_FILE_INFORMATION;
PWCHAR FsName;
ULONG Flags;
ULONG DeviceId; ULONG DeviceId;
} BL_ETFS_FILE, *PBL_ETFS_FILE; } BL_ETFS_FILE, *PBL_ETFS_FILE;
@ -56,9 +56,35 @@ EtfsOpen (
_Out_ PBL_FILE_ENTRY *FileEntry _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 = BL_FILE_CALLBACKS EtfsFunctionTable =
{ {
EtfsOpen, EtfsOpen,
NULL,
EtfsRead,
NULL,
NULL,
EtfsGetInformation,
EtfsSetInformation
}; };
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -205,7 +231,7 @@ EtfspGetDirent (
EtfsFile = DirectoryEntry->FsSpecificData; EtfsFile = DirectoryEntry->FsSpecificData;
DeviceId = EtfsFile->DeviceId; DeviceId = EtfsFile->DeviceId;
FileOffset = EtfsFile->Offset; FileOffset = EtfsFile->DiskOffset;
EtfsDevice = EtfsDeviceTable[DeviceId]; EtfsDevice = EtfsDeviceTable[DeviceId];
DirectoryOffset = *DirentOffset; DirectoryOffset = *DirentOffset;
@ -362,7 +388,7 @@ EtfspCachedSearchForDirent (
DirentOffset = EtfsFile->DirEntOffset; DirentOffset = EtfsFile->DirEntOffset;
if ((KeepOffset) || if ((KeepOffset) ||
(ALIGN_DOWN_BY((DirentOffset + EtfsFile->Offset), CD_SECTOR_SIZE) == (ALIGN_DOWN_BY((DirentOffset + EtfsFile->DiskOffset), CD_SECTOR_SIZE) ==
EtfsDevice->Offset)) EtfsDevice->Offset))
{ {
Status = EtfspGetDirent(DirectoryEntry, &Dirent, &DirentOffset); Status = EtfspGetDirent(DirectoryEntry, &Dirent, &DirentOffset);
@ -406,6 +432,108 @@ EtfspCachedSearchForDirent (
return Status; 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 NTSTATUS
EtfsOpen ( EtfsOpen (
_In_ PBL_FILE_ENTRY Directory, _In_ PBL_FILE_ENTRY Directory,
@ -486,7 +614,7 @@ EtfsOpen (
RtlCopyMemory(&NewFile->Callbacks, RtlCopyMemory(&NewFile->Callbacks,
&EtfsFunctionTable, &EtfsFunctionTable,
sizeof(NewFile->Callbacks)); sizeof(NewFile->Callbacks));
EtfsFile->Offset = FileOffset; EtfsFile->DiskOffset = FileOffset;
EtfsFile->DirOffset = DirOffset; EtfsFile->DirOffset = DirOffset;
EtfsFile->Size = FileSize; EtfsFile->Size = FileSize;
EtfsFile->DeviceId = DeviceId; EtfsFile->DeviceId = DeviceId;
@ -794,7 +922,7 @@ EtfsMount (
RootEntry->FsSpecificData = EtfsFile; RootEntry->FsSpecificData = EtfsFile;
EtfsFile->DeviceId = DeviceId; EtfsFile->DeviceId = DeviceId;
EtfsFile->Flags |= 1; EtfsFile->Flags |= 1;
EtfsFile->Offset = EtfsDevice->RootDirOffset; EtfsFile->DiskOffset = EtfsDevice->RootDirOffset;
EtfsFile->DirOffset = 0; EtfsFile->DirOffset = 0;
EtfsFile->Size = EtfsDevice->RootDirSize; EtfsFile->Size = EtfsDevice->RootDirSize;
EtfsFile->FsName = L"cdfs"; EtfsFile->FsName = L"cdfs";

View file

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

View file

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

View file

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