[BOOTMGFW]
authorAlex Ionescu <aionescu@gmail.com>
Thu, 10 Sep 2015 04:01:41 +0000 (04:01 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Thu, 10 Sep 2015 04:01:41 +0000 (04:01 +0000)
- Implement initial File I/O routines.
- We now die on attempting to mount the FAT volume.

svn path=/trunk/; revision=69165

reactos/boot/environ/app/bootmgr/bootmgr.c
reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/io/device.c
reactos/boot/environ/lib/io/fat.c
reactos/boot/environ/lib/io/file.c

index ab84d03..abaa92b 100644 (file)
@@ -180,8 +180,7 @@ BmFwInitializeBootDirectoryPath (
 
     /* Try to open the file */
     EfiPrintf(L"Opening: %s\r\n", FinalPath);
-#if 0
-    Status = BlFileOpen(DeviceHandle, FinalPath, 1u, &FileHandle);
+    Status = BlFileOpen(DeviceHandle, FinalPath, 1, &FileHandle);
     if (!NT_SUCCESS(Status))
     {
         BootDirectory = BcdDirectory;
@@ -189,7 +188,6 @@ BmFwInitializeBootDirectoryPath (
     }
 
     BootDirectory = L"\\EFI\\Microsoft\\Boot";
-#endif
 
 Quickie:
     /* Free all the allocations we made */
@@ -205,7 +203,7 @@ Quickie:
     /* Close the BCD file */
     if (FileHandle != -1)
     {
-        //Status = BlFileClose(FileHandle);
+        Status = BlFileClose(FileHandle);
     }
 
     /* Close the boot device */
index 2bf8a18..5c94c3a 100644 (file)
@@ -265,6 +265,52 @@ typedef enum _BL_MEMORY_ATTR
 
 /* CALLBACKS *****************************************************************/
 
+struct _BL_FILE_ENTRY;
+typedef
+NTSTATUS
+(*PBL_FILE_OPEN) (
+    _In_ struct _BL_FILE_ENTRY* ParentFileEntry,
+    _In_ PWCHAR FileName,
+    _In_ ULONG OpenFlags,
+    _Out_ struct _BL_FILE_ENTRY** FileEntry
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_CLOSE) (
+    _In_ struct _BL_FILE_ENTRY* FileEntry
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_READ) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_WRITE) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_GET_NEXT) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_GET_INFO) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_FILE_SET_INFO) (
+    VOID
+    );
+
 typedef
 NTSTATUS
 (*PBL_FS_INIT_CALLBACK) (
@@ -280,7 +326,9 @@ NTSTATUS
 typedef
 NTSTATUS
 (*PBL_FS_MOUNT_CALLBACK) (
-    VOID
+    _In_ ULONG DeviceId,
+    _In_ ULONG Unknown,
+    _Out_ struct _BL_FILE_ENTRY** FileEntry
     );
 
 typedef
@@ -398,6 +446,73 @@ ULONG
     _In_ ULONG TableSize
     );
 
+struct _BL_DEVICE_ENTRY;
+struct _BL_DEVICE_DESCRIPTOR;
+struct _BL_DEVICE_INFORMATION;
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_ENUMERATE_DEVICE_CLASS) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_OPEN) (
+    _In_ struct _BL_DEVICE_DESCRIPTOR* Device,
+    _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_CLOSE) (
+    _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_READ) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_WRITE) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_GET_INFORMATION) (
+    _In_ struct _BL_DEVICE_ENTRY* DeviceEntry,
+    _Out_ struct _BL_DEVICE_INFORMATION* DeviceInformation
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_SET_INFORMATION) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_RESET) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_FLUSH) (
+    VOID
+    );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_CREATE) (
+    VOID
+    );
+
+
 /* DATA STRUCTURES ***********************************************************/
 
 typedef struct _BL_LIBRARY_PARAMETERS
@@ -626,9 +741,28 @@ typedef struct _BL_ADDRESS_RANGE
     ULONGLONG Maximum;
 } BL_ADDRESS_RANGE, *PBL_ADDRESS_RANGE;
 
+typedef struct _BL_FILE_CALLBACKS
+{
+    PBL_FILE_OPEN Open;
+    PBL_FILE_CLOSE Close;
+    PBL_FILE_READ Read;
+    PBL_FILE_WRITE Write;
+    PBL_FILE_GET_NEXT GetNext;
+    PBL_FILE_GET_INFO GetInfo;
+    PBL_FILE_SET_INFO SetInfo;
+} BL_FILE_CALLBACKS, *PBL_FILE_CALLBACKS;
+
 typedef struct _BL_FILE_ENTRY
 {
-    ULONG DeviceIndex;
+    ULONG ReferenceCount;
+    ULONG FileId;
+    ULONG DeviceId;
+    ULONG Flags;
+    PWCHAR FilePath;
+    ULONG Unknown;
+    ULONG Unknown1;
+    ULONG Unknown2;
+    BL_FILE_CALLBACKS Callbacks;
     PBL_FILE_DESTROY_CALLBACK DestroyCallback;
 } BL_FILE_ENTRY, *PBL_FILE_ENTRY;
 
@@ -752,7 +886,7 @@ typedef struct _BL_HASH_NODE
     BL_HASH_VALUE Value;
 } BL_HASH_NODE, *PBL_HASH_NODE;
 
-typedef struct _BL_BLOCK_DEVICE
+typedef struct _BL_BLOCK_DEVICE_INFORMATION
 {
     BL_LOCAL_DEVICE_TYPE Type;
     ULONG DeviceFlags;
@@ -774,6 +908,20 @@ typedef struct _BL_BLOCK_DEVICE
             } Gpt;
         };
     } Disk;
+} BL_BLOCK_DEVICE_INFORMATION, *PBL_BLOCK_DEVICE_INFORMATION;
+
+typedef struct _BL_DEVICE_INFORMATION
+{
+    BL_DEVICE_TYPE DeviceType;
+    union
+    {
+        BL_BLOCK_DEVICE_INFORMATION BlockDeviceInfo;
+    };
+} BL_DEVICE_INFORMATION, *PBL_DEVICE_INFORMATION;
+
+typedef struct _BL_BLOCK_DEVICE
+{
+    BL_BLOCK_DEVICE_INFORMATION;
     ULONGLONG LastBlock;
     EFI_BLOCK_IO* Protocol;
     EFI_HANDLE Handle;
@@ -785,6 +933,31 @@ typedef struct _BL_PROTOCOL_HANDLE
     PVOID Interface;
 } BL_PROTOCOL_HANDLE, *PBL_PROTOCOL_HANDLE;
 
+typedef struct _BL_DEVICE_CALLBACKS
+{
+    PBL_DEVICE_ENUMERATE_DEVICE_CLASS EnumerateDeviceClass;
+    PBL_DEVICE_OPEN Open;
+    PBL_DEVICE_CLOSE Close;
+    PBL_DEVICE_READ Read;
+    PBL_DEVICE_WRITE Write;
+    PBL_DEVICE_GET_INFORMATION GetInformation;
+    PBL_DEVICE_SET_INFORMATION SetInformation;
+    PBL_DEVICE_RESET Reset;
+    PBL_DEVICE_FLUSH Flush;
+    PBL_DEVICE_CREATE Create;
+} BL_DEVICE_CALLBACKS, *PBL_DEVICE_CALLBACKS;
+
+typedef struct _BL_DEVICE_ENTRY
+{
+    ULONG DeviceId;
+    ULONG Flags;
+    ULONG Unknown;
+    ULONG ReferenceCount;
+    BL_DEVICE_CALLBACKS Callbacks;
+    PVOID DeviceSpecificData;
+    PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
+} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
+
 /* INLINE ROUTINES ***********************************************************/
 
 FORCEINLINE
@@ -893,11 +1066,6 @@ BlpFileInitialize (
     VOID
     );
 
-NTSTATUS
-FatInitialize (
-    VOID
-    );
-
 NTSTATUS
 BlpDisplayInitialize (
     _In_ ULONG Flags
@@ -1036,6 +1204,20 @@ BlpTimeCalibratePerformanceCounter (
     VOID
     );
 
+/* FILESYSTEM ROUTINES *******************************************************/
+
+NTSTATUS
+FatInitialize (
+    VOID
+    );
+
+NTSTATUS
+FatMount (
+    _In_ ULONG DeviceId,
+    _In_ ULONG Unknown,
+    _Out_ PBL_FILE_ENTRY* FileEntry
+    );
+
 /* UTILITY ROUTINES **********************************************************/
 
 EFI_STATUS
@@ -1295,6 +1477,27 @@ BlpDeviceOpen (
     _Out_ PULONG DeviceId
     );
 
+NTSTATUS
+BlDeviceGetInformation (
+    _In_ ULONG DeviceId,
+    _Out_ PBL_DEVICE_INFORMATION DeviceInformation
+    );
+
+/* FILE I/O ROUTINES *********************************************************/
+
+NTSTATUS
+BlFileClose (
+    _In_ ULONG FileId
+    );
+
+NTSTATUS
+BlFileOpen (
+    _In_ ULONG DeviceId,
+    _In_ PWCHAR FileName,
+    _In_ ULONG OpenFlags,
+    _Out_ PULONG FileId
+    );
+
 /* TEXT CONSOLE ROUTINES *****************************************************/
 
 NTSTATUS
index a5aac41..c2c768a 100644 (file)
 
 /* DATA VARIABLES ************************************************************/
 
-typedef struct _BL_DEVICE_INFORMATION
+typedef struct _BL_DEVICE_IO_INFORMATION
 {
     ULONG Unknown0;
     ULONG Unknown1;
     ULONG Unknown2;
     ULONG Unknown3;
-} BL_DEVICE_INFORMATION, *PBL_DEVICE_INFORMATION;
+} BL_DEVICE_IO_INFORMATION, *PBL_DEVICE_IO_INFORMATION;
 
 LIST_ENTRY DmRegisteredDevices;
 ULONG DmTableEntries;
 LIST_ENTRY DmRegisteredDevices;
 PVOID* DmDeviceTable;
 
-BL_DEVICE_INFORMATION DmDeviceIoInformation;
+BL_DEVICE_IO_INFORMATION DmDeviceIoInformation;
 
 /* FUNCTIONS *****************************************************************/
 
-struct _BL_DEVICE_ENTRY;
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_ENUMERATE_DEVICE_CLASS) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_OPEN) (
-    _In_ PBL_DEVICE_DESCRIPTOR Device,
-    _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_CLOSE) (
-    _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_READ) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_WRITE) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_GET_INFORMATION) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_SET_INFORMATION) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_RESET) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_FLUSH) (
-    VOID
-    );
-
-typedef
-NTSTATUS
-(*PBL_DEVICE_CREATE) (
-    VOID
-    );
-
-typedef struct _BL_DEVICE_CALLBACKS
-{
-    PBL_DEVICE_ENUMERATE_DEVICE_CLASS EnumerateDeviceClass;
-    PBL_DEVICE_OPEN Open;
-    PBL_DEVICE_CLOSE Close;
-    PBL_DEVICE_READ Read;
-    PBL_DEVICE_WRITE Write;
-    PBL_DEVICE_GET_INFORMATION GetInformation;
-    PBL_DEVICE_SET_INFORMATION SetInformation;
-    PBL_DEVICE_RESET Reset;
-    PBL_DEVICE_FLUSH Flush;
-    PBL_DEVICE_CREATE Create;
-} BL_DEVICE_CALLBACKS, *PBL_DEVICE_CALLBACKS;
-
-typedef struct _BL_DEVICE_ENTRY
-{
-    ULONG DeviceId;
-    ULONG Flags;
-    ULONG Unknown;
-    ULONG ReferenceCount;
-    BL_DEVICE_CALLBACKS Callbacks;
-    PVOID DeviceSpecificData;
-    PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
-} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
-
 typedef struct _BL_REGISTERED_DEVICE
 {
     LIST_ENTRY ListEntry;
@@ -151,13 +63,72 @@ BlockIoOpen (
     _In_ PBL_DEVICE_ENTRY DeviceEntry
     );
 
+NTSTATUS
+BlockIoGetInformation (
+    _In_ PBL_DEVICE_ENTRY DeviceEntry,
+    _Out_ PBL_DEVICE_INFORMATION DeviceInformation
+    );
+
 BL_DEVICE_CALLBACKS BlockIoDeviceFunctionTable =
 {
     NULL,
     BlockIoOpen,
     NULL,
+    NULL,
+    NULL,
+    BlockIoGetInformation
 };
 
+NTSTATUS
+BlockIoGetInformation (
+    _In_ PBL_DEVICE_ENTRY DeviceEntry,
+    _Out_ PBL_DEVICE_INFORMATION DeviceInformation
+    )
+{
+    PBL_BLOCK_DEVICE BlockDevice;
+
+    BlockDevice = DeviceEntry->DeviceSpecificData;
+
+    RtlCopyMemory(&DeviceInformation->BlockDeviceInfo,
+                  BlockDevice,
+                  sizeof(DeviceInformation->BlockDeviceInfo));
+    DeviceInformation->DeviceType = DiskDevice;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlDeviceGetInformation (
+    _In_ ULONG DeviceId, 
+    _Out_ PBL_DEVICE_INFORMATION DeviceInformation
+    )
+{
+    PBL_DEVICE_ENTRY DeviceEntry;
+
+    if (!(DeviceInformation))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (DmTableEntries <= DeviceId)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    DeviceEntry = DmDeviceTable[DeviceId];
+    if (!DeviceEntry)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!(DeviceEntry->Flags & 1))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    DeviceInformation->DeviceType = DeviceEntry->DeviceDescriptor->DeviceType;
+    return DeviceEntry->Callbacks.GetInformation(DeviceEntry, DeviceInformation);
+}
+
 BOOLEAN
 BlpDeviceCompare (
     _In_ PBL_DEVICE_DESCRIPTOR Device1,
@@ -879,8 +850,6 @@ BL_DEVICE_CALLBACKS VirtualDiskDeviceFunctionTable =
     NULL,
 };
 
-
-
 BL_DEVICE_CALLBACKS UdpFunctionTable =
 {
     NULL,
@@ -895,9 +864,6 @@ BL_DEVICE_CALLBACKS SerialPortFunctionTable =
     NULL,
 };
 
-
-
-
 BOOLEAN
 DeviceTableCompare (
     _In_ PVOID Entry,
index a8c0925..46f0595 100644 (file)
@@ -18,6 +18,18 @@ PWCHAR FatpLongFileName;
 
 /* FUNCTIONS *****************************************************************/
 
+NTSTATUS
+FatMount (
+    _In_ ULONG DeviceId,
+    _In_ ULONG Unknown,
+    _Out_ PBL_FILE_ENTRY* FileEntry
+    )
+{
+    EfiPrintf(L"FAT Mount on Device %d TODO\r\n", DeviceId);
+    EfiStall(3000000);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 NTSTATUS
 FatInitialize (
     VOID
index 5a4982c..fcf2564 100644 (file)
@@ -19,15 +19,460 @@ LIST_ENTRY RegisteredFileSystems;
 BL_FILE_SYSTEM_REGISTRATION_TABLE FatRegisterFunctionTable =
 {
     FatInitialize,
-#if 0
-    FatDestroy,
+    NULL,
     FatMount,
     NULL
-#endif
 };
 
+extern ULONG DmTableEntries;
+extern PVOID* DmDeviceTable;
+
 /* FUNCTIONS *****************************************************************/
 
+PWCHAR
+FileIoCopyParentDirectoryPath (
+    _In_ PWCHAR FilePath
+    )
+{
+    ULONG PathSize, PathSizeWithNull;
+    PWCHAR Backslash, ParentCopy;
+
+    PathSize = wcslen(FilePath) * sizeof(WCHAR);
+
+    PathSizeWithNull = PathSize + sizeof(UNICODE_NULL);
+    if (PathSizeWithNull < PathSize)
+    {
+        return NULL;
+    }
+
+    ParentCopy = BlMmAllocateHeap(PathSizeWithNull);
+    if (!ParentCopy)
+    {
+        return NULL;
+    }
+    wcsncpy(ParentCopy, FilePath, PathSizeWithNull / sizeof(WCHAR));
+
+    Backslash = wcsrchr(ParentCopy, '\\');
+    if (!Backslash)
+    {
+        BlMmFreeHeap(ParentCopy);
+        return NULL;
+    }
+
+    if (Backslash == ParentCopy)
+    {
+        ++Backslash;
+    }
+
+    *Backslash = UNICODE_NULL;
+    return ParentCopy;
+}
+
+PWCHAR
+FileIoCopyFileName (
+    _In_ PWCHAR FilePath
+    )
+{
+    PWCHAR Separator, FileCopy;
+    ULONG PathSize;
+
+    Separator = wcsrchr(FilePath, '\\');
+    if (!Separator)
+    {
+        return NULL;
+    }
+
+    PathSize = wcslen(Separator) * sizeof(WCHAR);
+
+    FileCopy = BlMmAllocateHeap(PathSize);
+    if (!FileCopy)
+    {
+        return NULL;
+    }
+
+    wcsncpy(FileCopy, Separator + 1, PathSize / sizeof(WCHAR));
+    return FileCopy;
+}
+
+BOOLEAN
+FileTableCompareWithSubsetAttributes (
+    _In_ PVOID Entry,
+    _In_ PVOID Argument1,
+    _In_ PVOID Argument2,
+    _In_ PVOID Argument3,
+    _In_ PVOID Argument4
+    )
+{
+    PBL_FILE_ENTRY FileEntry = (PBL_FILE_ENTRY)Entry;
+    ULONG DeviceId = *(PULONG)Argument1;
+    PWCHAR FilePath = (PWCHAR)Argument2;
+    ULONG OpenFlags = *(PULONG)Argument3;
+    ULONG Unknown = *(PULONG)Argument4;
+    BOOLEAN Found;
+
+    Found = FALSE;
+
+    if ((FileEntry->DeviceId == DeviceId) && !(_wcsicmp(FileEntry->FilePath, FilePath)) && (FileEntry->Unknown == Unknown))
+    {
+        if ((!(OpenFlags & 1) || (FileEntry->Flags & 2)) && (!(OpenFlags & 2) || (FileEntry->Flags & 4)))
+        {
+            if ((!(OpenFlags & 4) || (FileEntry->Flags & 0x10000)) && ((OpenFlags & 4) || !(FileEntry->Flags & 0x10000)))
+            {
+                Found = TRUE;
+            }
+        }
+    }
+    return Found;
+}
+
+BOOLEAN
+FileTableCompareWithSameAttributes (
+    _In_ PVOID Entry,
+    _In_ PVOID Argument1,
+    _In_ PVOID Argument2,
+    _In_ PVOID Argument3,
+    _In_ PVOID Argument4
+    )
+{
+    PBL_FILE_ENTRY FileEntry = (PBL_FILE_ENTRY)Entry;
+    ULONG DeviceId = *(PULONG)Argument1;
+    PWCHAR FilePath = (PWCHAR)Argument2;
+    ULONG OpenFlags = *(PULONG)Argument3;
+    ULONG Unknown = *(PULONG)Argument4;
+    BOOLEAN Found;
+
+    Found = FALSE;
+
+    if ((FileEntry->DeviceId == DeviceId) && !(_wcsicmp(FileEntry->FilePath, FilePath)) && (FileEntry->Unknown == Unknown))
+    {
+        if ((!(OpenFlags & 1) || (FileEntry->Flags & 2)) && ((OpenFlags & 1) || !(FileEntry->Flags & 2)) && (!(OpenFlags & 2) || (FileEntry->Flags & 4)) && ((OpenFlags & 2) || !(FileEntry->Flags & 4)))
+        {
+            if ((!(OpenFlags & 4) || (FileEntry->Flags & 0x10000)) && ((OpenFlags & 4) || !(FileEntry->Flags & 0x10000)))
+            {
+                Found = TRUE;
+            }
+        }
+    }
+    return Found;
+}
+
+NTSTATUS
+FileTableDestroyEntry (
+    _In_ PBL_FILE_ENTRY FileEntry, 
+    _In_ ULONG Index
+    )
+{
+    ULONG DeviceId;
+    PBL_DEVICE_ENTRY DeviceEntry;
+    NTSTATUS Status;
+
+    DeviceId = FileEntry->DeviceId;
+    if (DmTableEntries > DeviceId)
+    {
+        DeviceEntry = DmDeviceTable[DeviceId];
+        if (DeviceEntry)
+        {
+            --DeviceEntry->ReferenceCount;
+        }
+    }
+
+    Status = FileEntry->Callbacks.Close(FileEntry);
+
+    BlMmFreeHeap(FileEntry);
+
+    FileTable[Index] = NULL;
+    return Status;
+}
+
+NTSTATUS
+FileTablePurgeEntry (
+    _In_ PVOID Entry
+    )
+{
+    PBL_FILE_ENTRY FileEntry = (PBL_FILE_ENTRY)Entry;
+    NTSTATUS Status;
+
+    if (((FileEntry->Flags & 1) || (FileEntry->Flags & 0x10000)) && (FileEntries < 0x200))
+    {
+        Status = STATUS_UNSUCCESSFUL;
+    }
+    else
+    {
+        Status = FileTableDestroyEntry(FileEntry, FileEntry->FileId);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+BlFileClose (
+    _In_ ULONG FileId
+    )
+{
+    PBL_FILE_ENTRY FileEntry;
+
+    if (FileEntries <= FileId)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    FileEntry = FileTable[FileId];
+    if (!FileEntry)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!(FileEntry->Flags & 1))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    --FileEntry->ReferenceCount;
+    if (!FileEntry->ReferenceCount)
+    {
+        FileEntry->Flags &= ~1;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FileIoOpen (
+    _In_ ULONG DeviceId,
+    _In_ PWCHAR FileName,
+    _In_ ULONG OpenFlags,
+    _In_ ULONG Unknown,
+    _In_ PBL_TBL_LOOKUP_ROUTINE CompareRoutine,
+    _Out_ PBL_FILE_ENTRY *ReturnFileEntry
+    )
+{
+    PWCHAR FileNameCopy, ParentFileName;
+    NTSTATUS Status;
+    PBL_DEVICE_ENTRY DeviceEntry;
+    PBL_FILE_SYSTEM_ENTRY FileSystem;
+    ULONG FileId;
+    PBL_FILE_ENTRY ParentDirectoryEntry, FileEntry;
+    PLIST_ENTRY NextEntry, ListHead;
+
+    ParentDirectoryEntry = NULL;
+    FileNameCopy = NULL;
+    OpenFlags |= 1;
+    ParentFileName = NULL;
+    Status = STATUS_SUCCESS;
+
+    if (DmTableEntries <= DeviceId)
+    {
+        return STATUS_ACCESS_DENIED;
+    }
+
+    DeviceEntry = DmDeviceTable[DeviceId];
+    if (!DeviceEntry)
+    {
+        return STATUS_ACCESS_DENIED;
+    }
+
+    if ((OpenFlags & 1) && (!(DeviceEntry->Flags & 1) || !(DeviceEntry->Flags & 2)))
+    {
+        EfiPrintf(L"Access denied\r\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    if ((OpenFlags & 2) && (!(DeviceEntry->Flags & 1) || !(DeviceEntry->Flags & 4)))
+    {
+        EfiPrintf(L"Access denied2\r\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    FileEntry = (PBL_FILE_ENTRY )BlTblFindEntry(FileTable,
+                                                FileEntries,
+                                                &FileId,
+                                                CompareRoutine,
+                                                &DeviceId,
+                                                FileName,
+                                                &OpenFlags,
+                                                &Unknown);
+    if (FileEntry)
+    {
+        EfiPrintf(L"Entry exists: %p\n", FileEntry);
+        goto FileOpened;
+    }
+
+    if ((*FileName != OBJ_NAME_PATH_SEPARATOR) || (FileName[1]))
+    {
+        ParentFileName = FileIoCopyParentDirectoryPath(FileName);
+        if (!ParentFileName)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto FileOpenEnd;
+        }
+
+        Status = FileIoOpen(DeviceId,
+                            ParentFileName,
+                            5,
+                            Unknown,
+                            FileTableCompareWithSubsetAttributes,
+                            &ParentDirectoryEntry);
+        if (Status < 0)
+        {
+            goto FileOpenEnd;
+        }
+
+        FileNameCopy = FileIoCopyFileName(FileName);
+        if (!FileNameCopy)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto FileOpenEnd;
+        }
+
+        Status = ParentDirectoryEntry->Callbacks.Open(ParentDirectoryEntry,
+                                                      FileNameCopy,
+                                                      OpenFlags,
+                                                      &FileEntry);
+    }
+    else
+    {
+        EfiPrintf(L"Opening root drive\r\n");
+        Status = STATUS_UNSUCCESSFUL;
+
+        ListHead = &RegisteredFileSystems;
+        NextEntry = ListHead->Flink;
+        while (NextEntry != ListHead)
+        {
+            FileSystem = CONTAINING_RECORD(NextEntry, BL_FILE_SYSTEM_ENTRY, ListEntry);
+
+            EfiPrintf(L"Calling filesystem %p mount routine: %p\r\n", FileSystem, FileSystem->MountCallback);
+            Status = FileSystem->MountCallback(DeviceId, Unknown, &FileEntry);
+            if (NT_SUCCESS(Status))
+            {
+                break;
+            }
+
+            NextEntry = NextEntry->Flink;
+        }
+
+        FileNameCopy = 0;
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"Could not open file!: %lx\r\n", Status);
+        goto FileOpenEnd;
+    }
+
+    FileEntry->Unknown = Unknown;
+
+    if (OpenFlags & 1)
+    {
+        FileEntry->Flags |= 2u;
+    }
+    
+    if (OpenFlags & 2)
+    {
+        FileEntry->Flags |= 4u;
+    }
+
+    Status = BlTblSetEntry(&FileTable,
+                           &FileEntries,
+                           (PVOID)FileEntry,
+                           &FileId,
+                           FileTablePurgeEntry);
+    if (!NT_SUCCESS(Status))
+    {
+        FileEntry->Callbacks.Close(FileEntry);
+        goto FileOpenEnd;
+    }
+
+    ++DeviceEntry->ReferenceCount;
+    Status = STATUS_SUCCESS;
+
+    FileEntry->FileId = FileId;
+
+FileOpened:
+    if (++FileEntry->ReferenceCount == 1)
+    {
+        FileEntry->Unknown1 = 0;
+        FileEntry->Unknown2 = 0;
+    }
+
+    FileEntry->Flags |= 1;
+    
+    if (OpenFlags & 0x10)
+    {
+        FileEntry->Flags |= 0x10;
+    }
+
+    if (ReturnFileEntry)
+    {
+        *ReturnFileEntry = FileEntry;
+    }
+
+FileOpenEnd:
+    if (ParentDirectoryEntry)
+    {
+        BlFileClose(ParentDirectoryEntry->FileId);
+    }
+    if (ParentFileName)
+    {
+        BlMmFreeHeap(ParentFileName);
+    }
+    if (FileNameCopy)
+    {
+        BlMmFreeHeap(FileNameCopy);
+    }
+    return Status;
+}
+
+NTSTATUS
+BlFileOpen (
+    _In_ ULONG DeviceId,
+    _In_ PWCHAR FileName,
+    _In_ ULONG OpenFlags,
+    _Out_ PULONG FileId
+    )
+{
+    NTSTATUS Status;
+    PBL_FILE_ENTRY FileEntry;
+    BL_DEVICE_INFORMATION DeviceInformation;
+
+    if (!(FileName) ||
+        (*FileName != OBJ_NAME_PATH_SEPARATOR) ||
+        !(FileId) ||
+        !(OpenFlags & 3))
+    {
+        EfiPrintf(L"Invalid file options\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
+    if (!NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"Get device info failed: %lx\r\n", Status);
+        return Status;
+    }
+
+    if ((DeviceInformation.DeviceType != DiskDevice) &&
+        (DeviceInformation.DeviceType != LegacyPartitionDevice) &&
+        (DeviceInformation.DeviceType != UdpDevice))
+    {
+        EfiPrintf(L"Invalid device type\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Status = FileIoOpen(DeviceId,
+                        FileName,
+                        OpenFlags,
+                        0,
+                        FileTableCompareWithSameAttributes,
+                        &FileEntry);
+    if (NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"File opened: %lx\r\n", FileEntry->FileId);
+        *FileId = FileEntry->FileId;
+    }
+
+    return Status;
+}
+
 NTSTATUS
 BlpFileRegisterFileSystem (
     _In_ PBL_FS_INIT_CALLBACK InitCallback,
@@ -40,14 +485,16 @@ BlpFileRegisterFileSystem (
     PBL_FILE_SYSTEM_ENTRY FsEntry;
     NTSTATUS Status;
 
+    /* Allocate an entry */
     FsEntry = BlMmAllocateHeap(sizeof(*FsEntry));
     if (!FsEntry)
     {
         return STATUS_NO_MEMORY;
     }
 
+    /* Initialize the file system */
     Status = InitCallback();
-    if (NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
         BlMmFreeHeap(FsEntry);
         return Status;