winntblockio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,122 行 · 第 1/3 页
C
1,122 行
// Shut down our device
//
Private->WinNtThunk->CloseHandle (Private->NtHandle);
//
// Free our instance data
//
EfiLibFreeUnicodeStringTable (Private->ControllerNameTable);
gBS->FreePool (Private);
}
return Status;
}
STATIC
CHAR16 *
GetNextElementPastTerminator (
IN CHAR16 *EnvironmentVariable,
IN CHAR16 Terminator
)
/*++
Routine Description:
Worker function to parse environment variables.
Arguments:
EnvironmentVariable - Envirnment variable to parse.
Terminator - Terminator to parse for.
Returns:
Pointer to next eliment past the first occurence of Terminator or the '\0'
at the end of the string.
--*/
{
CHAR16 *Ptr;
for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
if (*Ptr == Terminator) {
Ptr++;
break;
}
}
return Ptr;
}
STATIC
EFI_STATUS
WinNtBlockIoCreateMapping (
IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo,
IN EFI_HANDLE EfiDeviceHandle,
IN CHAR16 *Filename,
IN BOOLEAN ReadOnly,
IN BOOLEAN RemovableMedia,
IN UINTN NumberOfBlocks,
IN UINTN BlockSize,
IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType
)
/*++
Routine Description:
TODO: Add function description
Arguments:
WinNtIo - TODO: add argument description
EfiDeviceHandle - TODO: add argument description
Filename - TODO: add argument description
ReadOnly - TODO: add argument description
RemovableMedia - TODO: add argument description
NumberOfBlocks - TODO: add argument description
BlockSize - TODO: add argument description
DeviceType - TODO: add argument description
Returns:
TODO: add return values
--*/
{
EFI_STATUS Status;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
WIN_NT_BLOCK_IO_PRIVATE *Private;
UINTN Index;
WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (WIN_NT_BLOCK_IO_PRIVATE),
&Private
);
ASSERT_EFI_ERROR (Status);
EfiInitializeLock (&Private->Lock, EFI_TPL_NOTIFY);
Private->WinNtThunk = WinNtIo->WinNtThunk;
Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
Private->LastBlock = NumberOfBlocks - 1;
Private->BlockSize = BlockSize;
for (Index = 0; Filename[Index] != 0; Index++) {
Private->Filename[Index] = Filename[Index];
}
Private->Filename[Index] = 0;
Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE);
Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
Private->NumberOfBlocks = NumberOfBlocks;
Private->DeviceType = DeviceType;
Private->NtHandle = INVALID_HANDLE_VALUE;
Private->ControllerNameTable = NULL;
EfiLibAddUnicodeString (
"eng",
gWinNtBlockIoComponentName.SupportedLanguages,
&Private->ControllerNameTable,
Private->Filename
);
BlockIo = &Private->BlockIo;
BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
BlockIo->Media = &Private->Media;
BlockIo->Media->BlockSize = Private->BlockSize;
BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
BlockIo->Media->MediaId = 0;;
BlockIo->Reset = WinNtBlockIoResetBlock;
BlockIo->ReadBlocks = WinNtBlockIoReadBlocks;
BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks;
BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks;
BlockIo->Media->ReadOnly = ReadOnly;
BlockIo->Media->RemovableMedia = RemovableMedia;
BlockIo->Media->LogicalPartition = FALSE;
BlockIo->Media->MediaPresent = TRUE;
BlockIo->Media->WriteCaching = FALSE;
if (DeviceType == EfiWinNtVirtualDisks) {
BlockIo->Media->IoAlign = 1;
//
// Create a file to use for a virtual disk even if it does not exist.
//
Private->OpenMode = OPEN_ALWAYS;
} else if (DeviceType == EfiWinNtPhysicalDisks) {
//
// Physical disk and floppy devices require 4 byte alignment.
//
BlockIo->Media->IoAlign = 4;
//
// You can only open a physical device if it exists.
//
Private->OpenMode = OPEN_EXISTING;
} else {
ASSERT (FALSE);
}
Private->EfiHandle = EfiDeviceHandle;
Status = WinNtBlockIoOpenDevice (Private);
if (!EFI_ERROR (Status)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->EfiHandle,
&gEfiBlockIoProtocolGuid,
&Private->BlockIo,
NULL
);
if (EFI_ERROR (Status)) {
EfiLibFreeUnicodeStringTable (Private->ControllerNameTable);
gBS->FreePool (Private);
}
DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename));
}
return Status;
}
STATIC
EFI_STATUS
WinNtBlockIoOpenDevice (
WIN_NT_BLOCK_IO_PRIVATE *Private
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Private - TODO: add argument description
Returns:
TODO: add return values
--*/
{
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);
EfiAcquireLock (&Private->Lock);
}
//
// get the size of the file
//
Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
if (EFI_ERROR (Status)) {
FileSize = MultU64x32 (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 = DivU64x32 (FileSize, Private->BlockSize, NULL);
}
EndOfFile = MultU64x32 (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
//
SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);
Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
//
// then set it to the needed file size (OS will zero fill it)
//
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
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Private - TODO: add argument description
Returns:
TODO: add return values
--*/
{
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_STATUS Status;
BOOLEAN ReinstallBlockIoFlag;
BlockIo = &Private->BlockIo;
switch (Private->WinNtThunk->GetLastError ()) {
case ERROR_NOT_READY:
Status = EFI_NO_MEDIA;
BlockIo->Media->ReadOnly = FALSE;
BlockIo->Media->MediaPresent = FALSE;
ReinstallBlockIoFlag = FALSE;
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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?