Is it possible to copy files to EFI using some sort of network protocol?
For example, I have a computer and a virtual machine. The virtual machine boots to EFI and I need to copy file to it and then execute it in EFI environment.
Is this possible?
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.
Sign up to join this communityIs it possible to copy files to EFI using some sort of network protocol?
For example, I have a computer and a virtual machine. The virtual machine boots to EFI and I need to copy file to it and then execute it in EFI environment.
Is this possible?
Well, when i started developing EFI applications, i found the same problem. How to send file on EFI environment? For now I know these ways:
1. USB storage device.
Probably the easiest way if you copy files not too often. Just put files on USB flash drive and connect it to virtual machine (VM).
To access file from EFI environment you need EFI shell or something like that. VMware already has integrated shell, while on other VMs you may need to obtain it. To do this you can use wonderful rEFInd Boot Manager, which contains shell. Unzip it, insert iso image in VM's CD-ROM and boot from it. In the rEFInd menu choose "Start EFI Shell". You will see command prompt, where all storage devices mapped as FS0, FS1,... If you see only FS0 (rEFInd file system), then you probably forgot to connect USB drive to VM.
Now to get your file just type commands like this:
fs1:
cd directory_with_file
All shell commands can be found by help
command.
2. Transfer via TFTP.
Longer to setup, faster to use. Nice if you send files often, while developing EFI applications for example. For this method you need TFTP server like tftpd-hpa working (it could be on your host machine), EFI Shell + TFTP client on your VM. There is plenty information about starting TFTP server, so you can find manual yourself. Also it is nice to have DHCP server (it is optional, but configuration will be much easier with DHCP).
TFTP client can be built from Tianocore sources or downloaded as x64 precompiled binary from my cloud (i dont know why Tianocore maintainers do not provide it in binary). Put tftp.efi
on your VM somewhere you can access it (USB drive or virtual HDD). Put your file in TFTP root directory (like /srv/tftp). Probably you should turn your VM's network adapter into bridge mode, so it has real ip, if you want to use DHCP. Start EFI shell VM as described above. When you see command prompt, type these commands.
ifconfig -s eth0 dhcp
fs1:
cd destination_directory
tftp 192.168.3.1 file_to_copy
Where:
eth0
is your network adapter, you can find required one with ifconfig -l
. Also you can use static ip instead of dhcp, see help ifconfig
fs1:
is your file system with tftp.efi
, it could be fs0:
or other depends on your booting devicetftp
is tftp.efi
app, 192.168.3.1
is ip address of TFTP server (host machine or real server)Also you can write this commands in startup.nsh file in the root of your bootable file system to do it on VM loading. Or only last line in another *.nsh script file to download while EFI running.
3. QEMU virtual machine
It is very handy for simple testings, you do not need TFTP, DHCP, USB drive, etc. If it is ok to recreate VM each time you boot, there is wonderful article about creating and debugging EFI applications with QEMU on osdev.org.
Adding on to Dmitry's Solution:
4. Transfer via HTTP
This one is similar to TFTP in that you will need to build the binary for it and place it in the same location as your shell (or elsewhere, but typing out the path to the application gets tiresome).
I've found that I need to run connect
prior to ifconfig
to properly connect drivers to their handlers. I use a simple startup.nsh
script to make things a bit faster:
FS0:
connect
ifconfig -r eth0
ifconfig -s eth0 dhcp
ifconfig -l eth0
Be aware that if you have multiple block devices, you may have a different FS<x>:
to input. You can use map
to list the devices out.
Then to pull your file from an HTTP server (given that you have http.efi
):
http <server_ip> <remote_path_to_file>
This will overwrite the current file. If you want to keep it:
http <server_ip> <remote_path_to_file> <new_local_filename>
To set up a local HTTP server (Ubuntu):
sudo apt-get install apache2
/etc/init.d/apache2 start
Drop your desired files in /var/www/html
for top access.
I've also documented some personal notes from my experiences in building the TianoCore Shell and applications since there seem to be several README's out of date and/or floating in various locations.
These instructions were ONLY tested on UBUNTU 18.04, 20.10 with EDK II repository head at 35ed29f
1. Clone the EDK II repository
git clone --recursive https://github.com/tianocore/edk2.git
or
git clone https://github.com/tianocore/edk2.git
cd edk2
git submodule update --init
2. Install requirements
Not sure which of these are required due to multiple READMEs. I used all as 'better safe than sorry'.
sudo apt-get install uuid-dev nasm gcc-5 build-essential \
iasl git python3-distutils texinfo \
bison flex libgmp3-dev libmpfr-dev subversion
3. Compile build tools
cd edk2
make -C BaseTools
4. Initialize the environment
. edksetup.sh
5. Adjust config (in my case for X64 architecture)
vi ./Conf/target.txt
ACTIVE_PLATFORM = ./ShellPkg/ShellPkg.dsc
TARGET_ARCH = X64
TOOL_CHAIN_TAG = GCC5
There are flags to override the platform, arch, tool chain when building but I prefer to just adjust the config.
6. Build the package
build
7. Locate the files
cd ./edk2/Build/Shell/DEBUG_GCC5/X64/
Either Shell_<GUID>.efi
file is fine. I had:
Shell_7C04A583-9E3E-4f1c-AD65-E05268D0B4D1.efi
Shell_EA4BB293-2D7F-4456-A681-1F22F42CD0BC.efi
http.efi
If you just want to execute a remote EFI binary, look for the "rload" command if its available in your EFI shell.
This uses TFTP. And this assume your EFI has network drivers and all.
In my shell, haven't found a command to actually copy the remote file to the filesystem, which is kind of annoying.