Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open a file by it's full path in UEFI

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.

like image 754
Keshava GN Avatar asked Sep 27 '16 08:09

Keshava GN


1 Answers

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.

like image 116
Alex D Avatar answered Nov 15 '22 04:11

Alex D