winntblockio.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,018 行 · 第 1/2 页
C
1,018 行
{
EFI_STATUS Status;
UINT64 FileSize;
UINT64 EndOfFile;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
BlockIo = &Private->BlockIo;
EfiAcquireLock (&Private->Lock);
//
// If the device is already opened, close it
//
if (Private->NtHandle != INVALID_HANDLE_VALUE) {
BlockIo->Reset(BlockIo, FALSE);
}
//
// Open the device
//
Private->NtHandle = Private->WinNtThunk->CreateFile (
Private->Filename,
Private->ReadMode,
Private->ShareMode,
NULL,
Private->OpenMode,
0,
NULL
);
Status = Private->WinNtThunk->GetLastError();
if (Private->NtHandle == INVALID_HANDLE_VALUE) {
DEBUG((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError()));
BlockIo->Media->MediaPresent = FALSE;
Status = EFI_NO_MEDIA;
goto Done;
}
if (!BlockIo->Media->MediaPresent) {
//
// BugBug: try to emulate if a CD appears - notify drivers to check it out
//
BlockIo->Media->MediaPresent = TRUE;
EfiReleaseLock (&Private->Lock);
// gBS->ReinstallProtocolInterface (Private->EfiHandle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
EfiAcquireLock (&Private->Lock);
}
//
// get the size of the file
//
//FileSizeLow = Private->WinNtThunk->SetFilePointer (Private->NtHandle, 0, NULL, FILE_END);
Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
if (EFI_ERROR(Status)) {
FileSize = DriverLibMultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
if (Private->DeviceType == EfiWinNtVirtualDisks) {
DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));
Status = EFI_UNSUPPORTED;
goto Done;
}
}
if (Private->NumberOfBlocks == 0) {
Private->NumberOfBlocks = DriverLibDivU64x32 (FileSize, Private->BlockSize, NULL);
}
EndOfFile = DriverLibMultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
if (FileSize != EndOfFile) {
// file is not the proper size, change it
DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename));
//
// first set it to 0
//
//Private->WinNtThunk->SetFilePointer (Private->NtHandle, 0, NULL, FILE_BEGIN);
SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);
Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
//
// then set it to the needed file size (OS will zero fill it)
//
//Private->WinNtThunk->SetFilePointer (Private->NtHandle, EndOfFile, NULL, FILE_BEGIN);
SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN);
Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
}
DEBUG((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));
Status = EFI_SUCCESS;
Done:
if (EFI_ERROR(Status)) {
if (Private->NtHandle != INVALID_HANDLE_VALUE) {
BlockIo->Reset (BlockIo, FALSE);
}
}
EfiReleaseLock (&Private->Lock);
return Status;
}
STATIC
EFI_STATUS
WinNtBlockIoError (
IN WIN_NT_BLOCK_IO_PRIVATE *Private
)
{
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_STATUS Status;
BOOLEAN ReinstallBlockIoFlag;
BlockIo = &Private->BlockIo;
switch (Private->WinNtThunk->GetLastError()) {
case ERROR_NOT_READY:
BlockIo->Media->ReadOnly = FALSE;
BlockIo->Media->MediaPresent = FALSE;
ReinstallBlockIoFlag = FALSE;
Status = EFI_DEVICE_ERROR;
break;
case ERROR_WRONG_DISK:
BlockIo->Media->ReadOnly = FALSE;
BlockIo->Media->MediaPresent = TRUE;
BlockIo->Media->MediaId += 1;
ReinstallBlockIoFlag = TRUE;
Status = EFI_MEDIA_CHANGED;
break;
case ERROR_WRITE_PROTECT:
BlockIo->Media->ReadOnly = TRUE;
ReinstallBlockIoFlag = FALSE;
Status = EFI_WRITE_PROTECTED;
break;
default:
ReinstallBlockIoFlag = FALSE;
Status = EFI_DEVICE_ERROR;
break;
}
if (ReinstallBlockIoFlag) {
BlockIo->Reset (BlockIo, FALSE);
gBS->ReinstallProtocolInterface (
Private->EfiHandle,
&gEfiBlockIoProtocolGuid,
BlockIo,
BlockIo
);
}
return Status;
}
STATIC
EFI_STATUS
WinNtBlockIoReadWriteCommon (
IN WIN_NT_BLOCK_IO_PRIVATE *Private,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer,
IN BOOLEAN Write,
IN CHAR8 *CallerName
)
{
EFI_STATUS Status;
EFI_BLOCK_IO_MEDIA *Media;
UINTN BlockSize;
UINT64 LastBlock;
INT64 DistanceToMove;
UINT64 DistanceMoved;
if (Private->NtHandle == INVALID_HANDLE_VALUE) {
Status = WinNtBlockIoOpenDevice (Private);
if (EFI_ERROR(Status)) {
return Status;
}
}
Media = Private->BlockIo.Media;
if (!(Media->MediaPresent)) {
Status = EFI_NO_MEDIA;
}
if (MediaId != Media->MediaId) {
Status = EFI_MEDIA_CHANGED;
}
if (Write) {
if (Media->ReadOnly) {
return EFI_WRITE_PROTECTED;
}
}
//
// Verify buffer size
//
BlockSize = Private->BlockSize;
LastBlock = Lba + (BufferSize/BlockSize) - 1;
if (LastBlock > Private->LastBlock) {
DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
return EFI_INVALID_PARAMETER;
}
if ((BufferSize % BlockSize) != 0) {
DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
return EFI_BAD_BUFFER_SIZE;
}
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0) {
DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
return EFI_SUCCESS;
}
//
// Seek to End of File
//
DistanceToMove = DriverLibMultU64x32 (Lba, BlockSize);
//DistanceMoved = Private->WinNtThunk->SetFilePointer (Private->NtHandle, DistanceToMove, NULL, FILE_BEGIN);
Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
return WinNtBlockIoError (Private);
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
WinNtBlockIoReadBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Read BufferSize bytes from Lba into Buffer.
Arguments:
This - Protocol instance pointer.
MediaId - Id of the media, changes every time the media is replaced.
Lba - The starting Logical Block Address to read from
BufferSize - Size of Buffer, must be a multiple of device block size.
Buffer - Buffer containing read data
Returns:
EFI_SUCCES - The data was read correctly from the device.
EFI_DEVICE_ERROR - The device reported an error while performing the read.
EFI_NO_MEDIA - There is no media in the device.
EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
device.
EFI_INVALID_PARAMETER - The read request contains device addresses that are not
valid for the device.
--*/
{
WIN_NT_BLOCK_IO_PRIVATE *Private;
BOOL Flag;
EFI_STATUS Status;
DWORD BytesRead;
Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(This);
Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, FALSE, "WinNtReadBlocks");
if (EFI_ERROR(Status)) {
return Status;
}
Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesRead, NULL);
if (!Flag || (BytesRead != BufferSize)) {
DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError()));
return WinNtBlockIoError (Private);
}
//
// If we wrote then media is present.
//
This->Media->MediaPresent = TRUE;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
WinNtBlockIoWriteBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Write BufferSize bytes from Lba into Buffer.
Arguments:
This - Protocol instance pointer.
MediaId - Id of the media, changes every time the media is replaced.
Lba - The starting Logical Block Address to read from
BufferSize - Size of Buffer, must be a multiple of device block size.
Buffer - Buffer containing read data
Returns:
EFI_SUCCES - The data was written correctly to the device.
EFI_WRITE_PROTECTED - The device can not be written to.
EFI_DEVICE_ERROR - The device reported an error while performing the write.
EFI_NO_MEDIA - There is no media in the device.
EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
device.
EFI_INVALID_PARAMETER - The write request contains a LBA that is not
valid for the device.
--*/
{
WIN_NT_BLOCK_IO_PRIVATE *Private;
UINTN BytesWritten;
BOOL Flag;
EFI_STATUS Status;
Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(This);
Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, TRUE, "WinNtWriteBlocks");
if (EFI_ERROR(Status)) {
return Status;
}
Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesWritten, NULL);
if (!Flag || (BytesWritten != BufferSize)) {
DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError()));
return WinNtBlockIoError (Private);
}
//
// If the write succeeded, we are not write protected and media is present.
//
This->Media->MediaPresent = TRUE;
This->Media->ReadOnly = FALSE;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
WinNtBlockIoFlushBlocks(
IN EFI_BLOCK_IO_PROTOCOL *This
)
/*++
Routine Description:
Flush the Block Device.
Arguments:
This - Protocol instance pointer.
Returns:
EFI_SUCCES - All outstanding data was written to the device
EFI_DEVICE_ERROR - The device reported an error while writting back the data
EFI_NO_MEDIA - There is no media in the device.
--*/
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
WinNtBlockIoResetBlock(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
/*++
Routine Description:
Reset the Block Device.
Arguments:
This - Protocol instance pointer.
ExtendedVerification - Driver may perform diagnostics on reset.
Returns:
EFI_SUCCES - The device was reset.
EFI_DEVICE_ERROR - The device is not functioning properly and could
not be reset.
--*/
{
WIN_NT_BLOCK_IO_PRIVATE *Private;
Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(This);
Private->WinNtThunk->CloseHandle (Private->NtHandle);
Private->NtHandle = INVALID_HANDLE_VALUE;
return EFI_SUCCESS;
}
UINTN
Atoi (
CHAR16 *String
)
/*++
Routine Description:
Convert a unicode string to a UINTN
Arguments:
String - Unicode string.
Returns:
UINTN of the number represented by String.
--*/
{
UINTN Number;
CHAR16 *Str;
//
// skip preceeding white space
//
Str = String;
while ((*Str) && (*Str == ' ')) {
Str++;
}
//
// Convert ot a Number
//
Number = 0;
while (*Str != '\0') {
if ((*Str >= '0') && (*Str <= '9')) {
Number = (Number * 10) + *Str - '0';
} else {
break;
}
Str++;
}
return Number;
}
EFI_STATUS
SetFilePointer64 (
IN WIN_NT_BLOCK_IO_PRIVATE *Private,
IN INT64 DistanceToMove,
OUT UINT64 *NewFilePointer,
IN DWORD MoveMethod
)
/*++
This function extends the capability of SetFilePointer to accept 64 bit parameters
--*/
{
EFI_STATUS Status;
LARGE_INTEGER LargeInt;
UINT32 ErrorCode;
LargeInt.QuadPart = DistanceToMove;
Status = EFI_SUCCESS;
LargeInt.LowPart = Private->WinNtThunk->SetFilePointer(Private->NtHandle,
LargeInt.LowPart,
&LargeInt.HighPart,
MoveMethod
);
if (LargeInt.LowPart == -1 &&
(ErrorCode = Private->WinNtThunk->GetLastError()) != NO_ERROR)
{
Status = EFI_INVALID_PARAMETER;
}
if (NewFilePointer != NULL)
{
*NewFilePointer = LargeInt.QuadPart;
}
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?