Loading files under UEFI: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
m added GNU-EFI
m Bot: Replace deprecated source tag with syntaxhighlight
 
(3 intermediate revisions by 3 users not shown)
Line 1:
UEFI is supposed to provide an easy way of loading files from partitions. Sadly it is not so easy, considerably more complicated than [[Reading_sectors_under_UEFI|reading sectors]], but at least it parses the file system for you.
 
HINT: [[POSIX-UEFI]] makes this a whole lot easier by providing an "fopen" / "fread" / "fclose" interface for you under UEFI.
 
== Volume Handle ==
 
There's no common "Open File" function in UEFI. Instead each volume has its own. So the first thing you need to do is locate a volume handle. You probably want to use the same file system that your application was loaded from, so you need to use the image handle provided to your '''efi_main'''. Then you need to use the EFI_LOADED_IMAGE_PROTOCOL to figure out the device your application resides on.
<sourcesyntaxhighlight lang="c">
EFI_FILE_HANDLE GetVolume(EFI_HANDLE image)
{
Line 33 ⟶ 31:
}
 
</syntaxhighlight>
</source>
Here [[GNU-EFI]]'s libefi.a provides a '''LibOpenRoot''' function, which can be used instead of IOVolume:
<sourcesyntaxhighlight lang="c">
/* get the volume handle */
return LibOpenRoot(loaded_image->DeviceHandle);
</syntaxhighlight>
</source>
 
== Read Data from File ==
Line 45 ⟶ 43:
 
=== Open ===
<sourcesyntaxhighlight lang="c">
CHAR16 *FileName = L"DATA.TXT";
EFI_FILE_HANDLE FileHandle;
Line 51 ⟶ 49:
/* open the file */
uefi_call_wrapper(Volume->Open, 5, Volume, &FileHandle, FileName, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
</syntaxhighlight>
</source>
Note that the file name passed to '''Volume->Open''' is a UNICODE16 string, meaning all characters are 2 bytes long. To get the L"" string literal correctly, you'll need to pass the "-fshort-wchar" command line option to gcc.
 
=== Read ===
<sourcesyntaxhighlight lang="c">
/* read from the file */
UINT64 ReadSize = FileSize(FileHandle);
Line 61 ⟶ 59:
 
uefi_call_wrapper(FileHandle->Read, 3, FileHandle, &ReadSize, Buffer);
</syntaxhighlight>
</source>
 
=== Close ===
<sourcesyntaxhighlight lang="c">
/* close the file */
uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
</syntaxhighlight>
</source>
 
=== Get File Size ===
 
In order to know how much to read ('''ReadSize''' variable above), you'll need to know the file's size. For that, you should use '''FileHandle->GetInfo'''. The problem is, there's no way of knowing how big buffer the information structure requires, so you'll have to grow the buffer dynamically if GetInfo fails. GNU-EFI provides a pretty handy wrapper for that, [https://sourceforge.net/p/gnu-efi/code/ci/master/tree/lib/hand.c LibFileInfo].
<sourcesyntaxhighlight lang="c">
UINT64 FileSize(EFI_FILE_HANDLE FileHandle)
{
Line 83 ⟶ 81:
return ret;
}
</syntaxhighlight>
</source>
 
== See also ==
Line 98 ⟶ 96:
* [https://sourceforge.net/p/gnu-efi/code/ci/master/tree/ GNU-EFI source]
 
[[Category:x86-64]]
[[Category:UEFI]]