[BOOTLIB]:
authorAlex Ionescu <aionescu@gmail.com>
Mon, 5 Oct 2015 05:53:40 +0000 (05:53 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 5 Oct 2015 05:53:40 +0000 (05:53 +0000)
- 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

reactos/boot/environ/app/bootmgr/bootmgr.h
reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/io/etfs.c
reactos/boot/environ/lib/io/file.c
reactos/boot/environ/lib/misc/debug.c
reactos/boot/environ/lib/misc/image.c

index e5342d4..76dea63 100644 (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 *****************************************************************/
 
index 025ff6d..aa4a608 100644 (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;
index bf07428..eddf2bb 100644 (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";
index ce0cb72..0984354 100644 (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);
         }
     }
index 773d78f..a4c82e2 100644 (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);
 
index 7573755..e3009fc 100644 (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;
     }