根据之前的研究,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 输出