From b3626c28a1b5412853113d48719c13fc07c4a0c1 Mon Sep 17 00:00:00 2001 From: Tait Hoyem Date: Sat, 24 Apr 2021 15:26:51 -0600 Subject: [PATCH] Add UEFI post #1 --- ...2021-04-18-uefi-development-environment.md | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 _posts/2021-04-18-uefi-development-environment.md diff --git a/_posts/2021-04-18-uefi-development-environment.md b/_posts/2021-04-18-uefi-development-environment.md new file mode 100644 index 0000000..78359bb --- /dev/null +++ b/_posts/2021-04-18-uefi-development-environment.md @@ -0,0 +1,138 @@ +--- +layout: post +title: "UEFI Development On x86 With EDK2" +--- + +I made this blog so I could remember how to do stuff that had instructions spread around the internet. +So here is how I setup my environment for developing EFI applications. + +## Requirements + +On Artix or other Arch-based distros like Manjaro I installed the following packages: `gcc nasm iasl` + +Here is what the packages do: + +* GCC is obviously the GNU Compiler Collection and it allows us to compile C code to machine code. +* NASM stands for Netwide Assembler. It is an assembler and disassembler for 32 and 64 bit Intel x86 platforms. +* IASL stands for the ACPI Source Language Compiler/Decompiler. This will compile any ACPI calls to our local machine's code. + +We need all these packages to start our (U)EFI journey. +Now that these are installed, let's setup our environment. + +## Building EDK2 + +I used the stable/202011 branch as that is latest stable version of the EDK2 project. + +So first let's pull the project: + +`git clone https://github.com/tianocore/edk2.git` + +Now, let's fetch the tags and switch to the latest stable version: + +``` +cd edk2 +git fetch +git checkout stable/202011 +``` + +Perfect! We're on stable now! Let's grab all our submodules: `git submodule update --init` + +This will take a bit the first time you do it. But no fear, once that's done, we can finally build the base tools. + +``` +make -C BaseTools +export EDK_TOOLS_PATH=$HOME/Documents/edk2/BaseTools +. edksetup.sh BaseTools +``` + +Notice we source a file with `.` before continuing. This is needed to load some tools and options into our shell for later. The environment variable `EDK_TOOLS_PATH` is set so that EDK knows where to find itself later. Now that everything is loaded up, we can modify a config file located at `Conf/target.txt`. + +The most important options are these, feel free to append them to the end of the file; there is no default value for them. + +
+ACTIVE_PLATFORM = MdeModulePkg/MdeModulePkg.dsc
+TOOL_CHAIN_TAG = GCC5
+# for 64-bit development
+TARGET_ARCH = X64
+# for 32-bit development
+TARGET_ARCH = IA32
+# for 32 and 64-bit development
+TARGET_ARCH = IA32 X64
+
+# set multithreading to 1 + (2 x # of cores)
+MAX_CONCURRENT_THREAD_NUMBER = 9
+
+ +There are other options, but I don't know about them much, so I'm just sticking with this for now. + +Finally, after all this work, we can build some .efi files. Let's compile the `Helloworld.efi` file! +Simply run the `build` command in the terminal. +You can find your compiled EFI files by running this `ls` command: + +``` +ls Build/MdeModule/DEBUG_*/*/HelloWorld.efi +``` + +This will show all HelloWorld.efi files for all architectures and toolchains (if you decide to change them). + +## Running In UEFI Shell + +Once all this is complete, you will want to run your EFI files. +To do so, let's first add an EFI shell to use at boot. +This will appear as an option in your bootloader, like GRUB, which is what I will show documentation for in this article. + +So, first thing is first, +[download and EFI shell file](https://github.com/tianocore/edk2/blob/UDK2018/ShellBinPkg/UefiShell/X64/Shell.efi?raw=true). +Second, move it to a partition (FAT formatted) which can be used for the UEFI. +On my Linux system, this is /boot. On others there may be no FAT filesystem so attach a USB and format it as FAT. +Third, add the `EFI Shell` option to your grub boot file. +Substitute hdX with the right hard drive (I did it with trial and error) as when it doesn't work I would hit 'e' on grub and add the `ls` GRUB command. +Substitute the gptX with the correct partition, or msdosX if it is a DOS formatted partition table. +My `Shell.efi` was placed in /boot/EFI/. + + +
+menuentry "EFI Shell" {
+        insmod part_gpt
+        insmod chain
+        insmod fat
+        set root='(hd4,gpt2)'
+        chainloader /EFI/Shell.efi
+}
+
+ +Now regenerate your grub configuration file with `grub-update` (Debian-based) or `grub-mkconfig -o /boot/grub/grub.cfg` (Other). + +You'll know if your shell is working if you see the following text on boot into the EFI shell: + +
+UEFI Interactive Shell v2.1
+EDK II
+UEFI v2.4 (EDI II, 0x000100000)
+Mapping table:
+	...
+Shell> 
+
+ +## Running Hello World + +When we run our `ls` command from earlier, remember we saw our `HelloWorld.efi` file. +Let's move this file somewhere useful, like for me, `/boot`. +Then, once we're in our UEFI shell we can run commands: + +
+Shell> .\HelloWorld.efi
+UEFI Hello World!
+Shell> 
+
+ +And that... All that is how you set up a UEFI development environment. + +## Conclusion + +This took me a long time to figure out. +I needed to scrounge resources from around the internet, +and I had to look at my config files for hours to make sure that I hadn't missed a step that I did without thinking. +I hope this will be useful to you and my future self. + +Happy UEFI hacking :)