我正在编写一个适用于 efi 环境的应用程序(fe 可以从 EFI shell 运行)。我的问题是我无法在我的机器卷上创建任何文件。我在 WMVare 和带有 ntfs 的真实机器上测试它,甚至在带有 hfs+ 的 mac 上测试它(获得驱动程序 frim http://efi.akeo.ie/)。我可以阅读所有内容,但是当我尝试写入时,我得到了错误代码 8 (EFI_WRITE_PROTECTED)。
有没有办法避免这种保护?也许我应该更深入地使用块设备而不是文件系统(真的不想这样做)?
我的代码。驱动程序加载(我认为它工作正常,仅适用于这种情况):
Print(L"\nLoading NTFS Driver... ");
Status = BS->LocateHandleBuffer(ByProtocol, &FileSystemProtocol, NULL, &NumHandles, &Handle);
if (EFI_ERROR(Status))
{
PrintStatusError(Status, L"\n Failed to list file systems");
goto exit;
}
for (i = 0; i < NumHandles; i++)
{
// Look for our NTFS driver. Note: the path MUST be specified using backslashes!
DevicePath = FileDevicePath(Handle[i], DriverPath);
if (DevicePath == NULL)
continue;
// Attempt to load the driver. If that fails, it means we weren't on the right partition
Status = BS->LoadImage(FALSE, ImageHandle, DevicePath, NULL, 0, &DriverHandle);
SafeFree(DevicePath);
if (EFI_ERROR(Status))
continue;
// Load was a success - attempt to start the driver
Status = BS->StartImage(DriverHandle, NULL, NULL);
if (EFI_ERROR(Status))
{
PrintStatusError(Status, L"\n Driver did not start");
goto exit;
}
Print(L"LOADED");
break;
}
SafeFree(Handle);
if (i >= NumHandles)
{
Print(L"\n Failed to locate driver. Please check that '%s' exists on the FAT partition", DriverPath);
Status = EFI_NOT_FOUND;
goto exit;
}
文件读/写:
// Now enumerate all disk handles again
Status = BS->LocateHandleBuffer(ByProtocol, &DiskIoProtocol, NULL, &NumHandles, &Handle);
if (EFI_ERROR(Status))
{
PrintStatusError(Status, L"\n Failed to list disks");
goto exit;
}
// Go through the partitions and find the NTFS one
for (i = 0; i < NumHandles; i++)
{
dev_path = DevicePathFromHandle(Handle[i]);
Print(L"\nVolume [%d]: ", i);
// Calling ConnectController() on a handle starts all the drivers that can service it
Status = BS->ConnectController(Handle[i], NULL, NULL, TRUE);
if (Status == EFI_SUCCESS)
{
Print(L"Driver connected! ");
}
// Open the the volume
Status = BS->HandleProtocol(Handle[i], &FileSystemProtocol, (VOID**)&Volume);
if (EFI_ERROR(Status))
{
PrintStatusError(Status, L"\n Could not find volume");
continue;
}
// Open the root directory
Root = NULL;
Status = Volume->OpenVolume(Volume, &Root);
if ((EFI_ERROR(Status)) || (Root == NULL))
{
PrintStatusError(Status, L"\n Could not open Root directory");
continue;
}
Status = Root->Open(Root, &FileHandle, L"bb.txt", EFI_FILE_MODE_READ, 0);
Print(L"\n Read %d", Status);
if (Status == EFI_SUCCESS)
{
UINTN fsize = 5;
char fdata[5];
Status = FileHandle->Read(FileHandle, &fsize, fdata);
fdata[4] = 0;
Print(L" %d [%x%x%x%x] ", Status, fdata[0], fdata[1], fdata[2], fdata[3]);
FileHandle->Close(FileHandle);
}
Status = Root->Open(Root, &FileHandle, L"aa.txt", EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
Print(L" Create %d", Status);
if (Status == EFI_SUCCESS)
{
UINTN fsize = 4;
Status = FileHandle->Write(FileHandle, &fsize, file_content);
Print(L" Wr %d", Status);
Status = FileHandle->Flush(FileHandle);
Print(L" Fl %d", Status);
Status = FileHandle->Close(FileHandle);
Print(L" Cl %d", Status);
}
}
<---------------- 经过一番调查 ------------------------------------>
事实证明,我们对机器文件系统唯一能做的就是改变现有的文件内容。似乎这是没有几个月研究的唯一可能方法。但是,它仍然不容易做到:
我有“EFI_FILE *fileHandle”变量,可以读取我预先创建的文件。如何找到对应的 LBA(或 DiskIO 的偏移量)?
我查看了 EFI 源(来自 AMI bios 源),发现在 EFI_FILE 结构之后放置了隐藏数据:
typedef struct _FILE_HANDLE_INSTANCE {
EFI_FILE_PROTOCOL FileHandle; // Should be the first entry in the structure
EFI_STATUS HandleInstanceStatus;
FILE_HANDLE *pFH;
UINT64 OpenMode; // Open Modes
UINT64 Position; //
UINT32 CurrentCluster; // will point to sector number where the position is pointing currently
UINT32 CurrentClusterOffset; // will point to sector number where the position is pointing currently
BOOLEAN MEDIA_NOT_VALID; // Will be true if for any reason current instances cannot use the volume Eg: Change in Media
DLINK ViFILink; // This link is for the DLIST OpenFIs in the VOLUME_INFO
} FILE_HANDLE_INSTANCE;
他们像这样使用它:
void example_read_inside_efi(EFI_FILE *FileHandle, ...)
{
FILE_HANDLE_INSTANCE *fhi = (FILE_HANDLE_INSTANCE *)FileHandle;
...
但是当我尝试读取该结构时,该结构似乎没有正确的字段值(fe FILE_HANDLE 指针无效)。我不知道接下来该怎么办。没想法。。
所以,问题是:如果我有有效的 EFI_FILE 指针,我如何找到相应的 LBA(或 diskIO 的偏移量)?