efi 環境で動作するアプリケーションを作成しています (fe は EFI シェルから実行できます)。私の問題は、マシンのボリュームにファイルを作成できないことです。私はWMVareとntfsを備えた実際のマシン、さらにはhfs +を備えたMacでテストしました(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 のオフセット) を見つけるにはどうすればよいかということです。