I'm a beginner in UEFI. I'm trying to open a file from my UEFI application. The path of file is
fs1:/myfolder/myfile.txt
The code (With the help of this answer) :
efiStatus = bs->LocateHandleBuffer(ByProtocol,
&sfspGuid,
NULL,
&handleCount,
&handles);
for (index = 0; index < (int)handleCount; ++ index)
{
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;
efiStatus = bs->HandleProtocol(
handles[index],
&sfspGuid,
(void**)&fs);
EFI_FILE_PROTOCOL* root = NULL;
...
efiStatus = fs->OpenVolume(fs, &root);
EFI_FILE_PROTOCOL* token = NULL;
efiStatus = root->Open(
root,
&token,
L"myfolder\\myfile.txt",
EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
}
But using this method, I can only go through all the file system handles and open each volume and try opening my file.
But I want to give full path to my file and open it in it's volume.
How can I acheive this?
EDIT:
I tried using Shell APIs for opening the file as suggested by @Alex in comments.
Below is the code. But it hangs in function OpenFileByName
.
What is the mistake in this code? (argv[ 1 ] would be my file path fs1:\myfile.txt
)
EFI_STATUS
EFIAPI
main (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS status;
UINTN argc;
CHAR16 **argv;
SHELL_FILE_HANDLE Handle;
status = get_args(&argc, &argv);
if (EFI_ERROR(status)) {
Print(L"ERROR: Parsing command line arguments: %d\n", status);
return status;
}
if (argc <= 1){
Print(L"No file name to open\n");
return (EFI_UNSUPPORTED); //need to have at least one parameter
}
Print(L"File to open is: %s\n", argv[1]);
status = gEfiShellProtocol->OpenFileByName (argv[1], &Handle,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE);
if (EFI_ERROR(status)) {
Print(L"\nFile Open did not work %s\n", argv[1]);
return (status);
}else{
Print(L"\nFile Open worked %s\n", argv[1]);
gEfiShellProtocol->CloseFile(Handle);
}
return EFI_SUCCESS;
}
And the code hangs even if I try GetCurDir
function.
Print(L"Dir: %s \n",gEfiShellProtocol->GetCurDir(NULL));
Any pointers would be helpful.
Answer to the comment how to get EFI_SHELL_PROTOCOL: The procedure is basically the same as for any Efi protocols. First, grab a handle to the interface:
UINTN BufferSize;
EFI_HANDLE* Buffer;
Status = bs->LocateHandle(ByProtocol, &gEfiShellProtocolGuid, NULL, &BufferSize, Buffer);
Than, allocate and recall with the buffer of the correct size:
Status = bs->AllocatePool(EfiBootServicesData, BufferSize, &Buffer);
Status = bs->LocateHandle(ByProtocol, &gEfiShellProtocolGuid, NULL, &BufferSize, Buffer);
Now, you can grab a handle to the protocol. Remember, it's EFI, there might be multiple protocols installed! That's why we have to iterate through all of them. But in this case most likely there will be just one instance of the SHELL protocol:
UINTN HandleCounter;
for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++)
{
Status = bs->OpenProtocol(Buffer[HandleCounter],
&gEfiShellProtocolGuid,
(VOID**)&gEfiShellProtocol,
imageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
And don't forget to check Status for every step!
And of course don't forget:
bs->FreePool(buffer);
As for the protocol itself you don't have to close it. EFI starting from 2.31 doesn't require it anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With