NTSTATUS FatMount ( _In_ ULONG DeviceId, _In_ ULONG Unknown, _Out_ PBL_FILE_ENTRY* FileEntry ) { BL_DEVICE_INFORMATION DeviceInformation; ULONG UnknownFlag; NTSTATUS Status; PACKED_BOOT_SECTOR FatBootSector; BIOS_PARAMETER_BLOCK BiosBlock; /* Capture thing */ BlDeviceGetInformation(DeviceId, &DeviceInformation); UnknownFlag = DeviceInformation.BlockDeviceInfo.Unknown; /* Set thing to 1 */ DeviceInformation.BlockDeviceInfo.Unknown |= 1; BlDeviceSetInformation(DeviceId, &DeviceInformation); /* Read the boot sector */ Status = BlDeviceReadAtOffset(DeviceId, sizeof(FatBootSector), 0, &FatBootSector, NULL); /* Restore thing back */ DeviceInformation.BlockDeviceInfo.Unknown = UnknownFlag; BlDeviceSetInformation(DeviceId, &DeviceInformation); if (!NT_SUCCESS(Status)) { EfiPrintf(L"Failed reading drive: %lx\r\n", Status); return Status; } FatUnpackBios(&BiosBlock, &FatBootSector.PackedBpb); /* For now, quickly fail if this isn't FAT */ if (FatBootSector.Jump[0] != 0xE9) { return STATUS_UNSUCCESSFUL; } EfiPrintf(L"Jump: %lx Bytes Per Sector: %d Sectors Per Cluster: %d Reserved: %d Fats: %d Sectors: %d Large Sectors: %d Media: %lx RootEntries: %d\r\n", FatBootSector.Jump[0], BiosBlock.BytesPerSector, BiosBlock.SectorsPerCluster, BiosBlock.ReservedSectors, BiosBlock.Fats, BiosBlock.Sectors, BiosBlock.LargeSectors, BiosBlock.Media, BiosBlock.RootEntries); return STATUS_NOT_IMPLEMENTED; }
NTSTATUS BlFileOpen ( _In_ ULONG DeviceId, _In_ PWCHAR FileName, _In_ ULONG Flags, _Out_ PULONG FileId ) { NTSTATUS Status; PBL_FILE_ENTRY FileEntry; BL_DEVICE_INFORMATION DeviceInformation; /* Make sure we have a valid file name, access flags and parameters */ if (!(FileName) || (*FileName != OBJ_NAME_PATH_SEPARATOR) || !(FileId) || !(Flags & (BL_FILE_READ_ACCESS | BL_FILE_WRITE_ACCESS))) { EfiPrintf(L"Invalid file options\r\n"); return STATUS_INVALID_PARAMETER; } /* Get information on the underlying device */ Status = BlDeviceGetInformation(DeviceId, &DeviceInformation); if (!NT_SUCCESS(Status)) { EfiPrintf(L"Get device info failed: %lx\r\n", Status); return Status; } /* Make sure it's a device that can host files */ if ((DeviceInformation.DeviceType != DiskDevice) && (DeviceInformation.DeviceType != LegacyPartitionDevice) && (DeviceInformation.DeviceType != UdpDevice)) { EfiPrintf(L"Invalid device type\r\n"); return STATUS_INVALID_PARAMETER; } /* Open a file on this device, creating one if needed */ Status = FileIoOpen(DeviceId, FileName, Flags, 0, FileTableCompareWithSameAttributes, &FileEntry); if (NT_SUCCESS(Status)) { /* Return the file ID back to the caller */ EfiPrintf(L"File opened: %lx\r\n", FileEntry->FileId); *FileId = FileEntry->FileId; } /* All good */ return Status; }
NTSTATUS BlFileReadEx ( _In_ ULONG FileId, _Out_ PVOID Buffer, _In_ ULONG Size, _Out_ PULONG BytesReturned, _In_ ULONG Flags ) { PBL_FILE_ENTRY FileEntry; NTSTATUS Status; ULONG OldUnknown, RequiredSize; BOOLEAN ChangedUnknown; BL_DEVICE_INFORMATION DeviceInfo; BL_FILE_INFORMATION fileInfo; /* Initialize variables */ RtlZeroMemory(&DeviceInfo, sizeof(DeviceInfo)); OldUnknown = 0; ChangedUnknown = FALSE; /* Bail out if there's no buffer */ if (!Buffer) { return STATUS_INVALID_PARAMETER; } /* Bail out of the file ID is invalid */ if (FileId > FileEntries) { return STATUS_INVALID_PARAMETER; } /* Bail out if there's no file opened for read access */ FileEntry = FileTable[FileId]; if (!(FileEntry) || !(FileEntry->Flags & (BL_FILE_ENTRY_OPENED | BL_FILE_ENTRY_READ_ACCESS))) { return STATUS_INVALID_PARAMETER; } /* Bail out if we can't read the file's information */ Status = BlFileGetInformation(FileId, &fileInfo); if (!NT_SUCCESS(Status)) { return Status; } /* Ensure the read attempt is valid, and fix up the size if needed */ RequiredSize = Size; Status = FileInformationCheck(&fileInfo, FALSE, &RequiredSize, BytesReturned, &RequiredSize); if (!NT_SUCCESS(Status)) { /* Invalid or illegal read attempt */ return Status; } /* Is there anything left to read after all? */ if (RequiredSize) { /* Check if flags 2 or 4 are set */ if ((Flags & 2) || (Flags & 4)) { /* Check if this is a disk or partition device */ BlDeviceGetInformation(FileEntry->DeviceId, &DeviceInfo); if ((DeviceInfo.DeviceType == DiskDevice) || (DeviceInfo.DeviceType == LegacyPartitionDevice)) { /* Check if request flags are incompatible with device flags */ if ((!(DeviceInfo.BlockDeviceInfo.Unknown & 1) && (Flags & 2)) || (!(DeviceInfo.BlockDeviceInfo.Unknown & 2) && (Flags & 4))) { /* We're going to change the device flags */ ChangedUnknown = TRUE; /* Set unknown flag 1 for request flag 2 */ if (Flags & 2) { DeviceInfo.BlockDeviceInfo.Unknown |= 1; } /* Set unknown flag 2 for request flag 4 */ if (Flags & 4) { DeviceInfo.BlockDeviceInfo.Unknown |= 2; } /* Save the new device flags */ BlDeviceSetInformation(FileEntry->DeviceId, &DeviceInfo); } } } /* Issue the read to the underlying file system */ Status = FileEntry->Callbacks.Read(FileEntry, Buffer, RequiredSize, BytesReturned); if (!NT_SUCCESS(Status)) { /* Don't update the bytes read on failure */ RequiredSize = 0; } } else { /* There's nothing to do, return success and 0 bytes */ Status = STATUS_SUCCESS; if (BytesReturned) { *BytesReturned = 0; } } /* Increment the number of bytes read */ FileEntry->TotalBytesRead += RequiredSize; /* Check if the unknown flag on the device was changed during this routine */ if (ChangedUnknown) { /* Reset it back to its original value */ DeviceInfo.BlockDeviceInfo.Unknown = OldUnknown; BlDeviceSetInformation(FileEntry->DeviceId, &DeviceInfo); } /* Return the final status */ return Status; }