根据之前的研究,UDK中带的 NT32 模拟环境里面的很多操作都是直接和 Windows API挂钩来实现的。最近查看了一下 NT32 下面的 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 的实现。具体代码可以在\Nt32Pkg\WinNtSimpleFileSystemDxe\WinNtSimpleFileSystem.c 下面看到。
首先,在 WinNtSimpleFileSystem.c 中有下面这样的代码:
Private->SimpleFileSystem.OpenVolume = WinNtSimpleFileSystemOpenVolume;
这样,当我们调用EFI_SIMPLE_FILE_SYSTEM_PROTOCOL OpenVolume 的时候,实际工作的是WinNtSimpleFileSystemOpenVolume 的代码。此外,还有下面这样的代码,都是用Windows API 来替换 Protocol 中的操作。
PrivateFile->EfiFile.Open = WinNtSimpleFileSystemOpen; PrivateFile->EfiFile.Close = WinNtSimpleFileSystemClose; PrivateFile->EfiFile.Delete = WinNtSimpleFileSystemDelete; PrivateFile->EfiFile.Read = WinNtSimpleFileSystemRead; PrivateFile->EfiFile.Write = WinNtSimpleFileSystemWrite; PrivateFile->EfiFile.GetPosition = WinNtSimpleFileSystemGetPosition; PrivateFile->EfiFile.SetPosition = WinNtSimpleFileSystemSetPosition; PrivateFile->EfiFile.GetInfo = WinNtSimpleFileSystemGetInfo; PrivateFile->EfiFile.SetInfo = WinNtSimpleFileSystemSetInfo; PrivateFile->EfiFile.Flush = WinNtSimpleFileSystemFlush; PrivateFile->IsValidFindBuf = FALSE;
通过这样的赋值,当我们在NT32 模拟环境中调用打开读取等等Protocol 的函数时,实际上是用Windows 对应的API来完成实际操作的。
为了证明这一点,可以在上面的函数中插入输出 Debug 信息的代码【参考1】,比如:修改 WinNTSimpleFileSystemOpenVolume() 代码,插入Debug 信息:
/*++
Routine Description:
Open the root directory on a volume.
Arguments:
This - A pointer to the volume to open.
Root - A pointer to storage for the returned opened file handle of the root directory.
Returns:
EFI_SUCCESS - The volume was opened.
EFI_UNSUPPORTED - The volume does not support the requested file system type.
EFI_NO_MEDIA - The device has no media.
EFI_DEVICE_ERROR - The device reported an error.
EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
EFI_ACCESS_DENIED - The service denied access to the file.
EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
--*/
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
{
EFI_STATUS Status;
WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
EFI_TPL OldTpl;
CHAR16 *TempFileName;
UINTN Size;
//LABZ_Start
DEBUG ((EFI_D_INFO, "www.lab-z.com\n"));
//LABZ_End
if (This == NULL || Root == NULL) {
return EFI_INVALID_PARAMETER;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
if (PrivateFile == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));
if (PrivateFile->FileName == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));
if (PrivateFile->FilePath == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
StrCpy (PrivateFile->FilePath, Private->FilePath);
StrCpy (PrivateFile->FileName, PrivateFile->FilePath);
PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;
PrivateFile->WinNtThunk = Private->WinNtThunk;
PrivateFile->SimpleFileSystem = This;
PrivateFile->IsRootDirectory = TRUE;
PrivateFile->IsDirectoryPath = TRUE;
PrivateFile->IsOpenedByRead = TRUE;
PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
PrivateFile->EfiFile.Open = WinNtSimpleFileSystemOpen;
PrivateFile->EfiFile.Close = WinNtSimpleFileSystemClose;
PrivateFile->EfiFile.Delete = WinNtSimpleFileSystemDelete;
PrivateFile->EfiFile.Read = WinNtSimpleFileSystemRead;
PrivateFile->EfiFile.Write = WinNtSimpleFileSystemWrite;
PrivateFile->EfiFile.GetPosition = WinNtSimpleFileSystemGetPosition;
PrivateFile->EfiFile.SetPosition = WinNtSimpleFileSystemSetPosition;
PrivateFile->EfiFile.GetInfo = WinNtSimpleFileSystemGetInfo;
PrivateFile->EfiFile.SetInfo = WinNtSimpleFileSystemSetInfo;
PrivateFile->EfiFile.Flush = WinNtSimpleFileSystemFlush;
PrivateFile->IsValidFindBuf = FALSE;
//
// Set DirHandle
//
PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
PrivateFile->FilePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
Status = EFI_NOT_FOUND;
goto Done;
}
//
// Find the first file under it
//
Size = StrSize (PrivateFile->FilePath);
Size += StrSize (L"\\*");
Status = gBS->AllocatePool (
EfiBootServicesData,
Size,
(VOID **)&TempFileName
);
if (EFI_ERROR (Status)) {
goto Done;
}
StrCpy (TempFileName, PrivateFile->FilePath);
StrCat (TempFileName, L"\\*");
PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &PrivateFile->FindBuf);
FreePool (TempFileName);
if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
PrivateFile->IsValidFindBuf = FALSE;
} else {
PrivateFile->IsValidFindBuf = TRUE;
}
*Root = &PrivateFile->EfiFile;
Status = EFI_SUCCESS;
Done:
if (EFI_ERROR (Status)) {
if (PrivateFile) {
if (PrivateFile->FileName) {
FreePool (PrivateFile->FileName);
}
if (PrivateFile->FilePath) {
FreePool (PrivateFile->FilePath);
}
FreePool (PrivateFile);
}
}
gBS->RestoreTPL (OldTpl);
return Status;
}
之后在启动的过程中就能够看到如下的 Debug 信息:
参考:
1. http://www.lab-z.com/stu130nt32/ NT32 模拟器中的 Debug Message 输出

































