Re: Examples opening and reading/writing a file with EDK2


Laszlo Ersek
 

On 11/22/19 02:54, alejandro.estay@gmail.com wrote:
Hi, I'm making a little UEFI app, just for check basic functionality
of the firmware. inside this app I want to load, read and write a
file, binary or text. However I can't find a "complete explanation" or
examples about the use of the procedures (EFI_FILE_PROTOCOL.Open(),
EFI_FILE_PROTOCOL.Read()) from the UEFI API (steps, what to check).
The only thing I found was some little Uefi Shell apps doing this
using the shell API. However I would like to do it using the "bare
firmware" instead of loading the shell. For me, the most confusing
part, is when the program has to check the handle database to find
the particular handle of the file that is being opened. Also I have
some doubts about how to check, without the shell, what volume or
partition would have the exact file I'm looking for (i.e. what if 2
volumes have simmilar, or even identical root directories).
First, you need to find the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance in
the protocol database that is right for your purposes. You could locate
this protocol instance for example with the LocateDevicePath() boot
service. There could be other ways for you to locate the right handle,
and then open the Simple File System protocol interface on that handle.

This really depends on your use case. It's your application that has to
know on what device (such as, what PCI(e) controller, what SCSI disk,
what ATAPI disk, what partition, etc) to look for the interesting file.

For example, if you simply check every EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
in the protocol database, and among those, you cannot distinguish two
from each other (because both look suitable), then you'll have to
investigate the device path protocol installed on each handle. You might
be able to make a decision based on the structure / semantics of the
device paths themselves. Alternatively, you might have to traverse the
device paths node by node, and open further protocol interfaces on the
corresponding handles, to ultimately pick the right
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.


Once you have the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL interface open, you
need to call its OpenVolume() member function. See the UEFI spec for
details please. It will give you the EFI_FILE_PROTOCOL for the root
directory of that file system.

Once you got the EFI_FILE_PROTOCOL interface for the root directory, you
can call the Open() member function for opening files or directories
relative to the root directory. Either way, you'll get a new
EFI_FILE_PROTOCOL interface for the opened object (file or directory).
If you've opened a directory previously, then you can issue further
Open() calls for opening files or directories relative to *that*
(sub)directory.

In case you start with an EFI_DEVICE_PATH_PROTOCOL instance that
identifies a particular file in a particular filesystem, then the device
path protocol will contain *at least one* File Path Media Device Path
node. It is important that there may be more than one such device path
node, and the full pathname (within the filesystem), from the root
directory to the particular file, may be split over a number of device
path nodes.

For example, you could have just one File Path node containing
"\dir1\dir2\hello.txt". Or you could have three File Path nodes
containing "dir1", "dir2", "hello.txt", respectively. Or you could have
two File Path nodes containing "dir1\dir2\" and "hello.txt",
respectively.

In these cases, you'd need one, three, or two, EFI_FILE_PROTOCOL.Open()
calls, accordingly.

Alternatively, you'd need to concatenate the pathname fragments into a
whole pathname, making sure that there be precisely one backslash
separator between each pair of pathname components, and then issue a
single EFI_FILE_PROTOCOL.Open() call in the end.


You can find a helper function called EfiOpenFileByDevicePath() in
"MdePkg/Library/UefiLib/UefiLib.c".

A somewhat similar function is GetFileBufferByFilePath(), in
"MdePkg/Library/DxeServicesLib/DxeServicesLib.c".

Thanks,
Laszlo

Join discuss@edk2.groups.io to automatically receive all group messages.