Skip to content

Latest commit

 

History

History

Lesson_16

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

In previous lesson we've developed an app that showed us current boot options:

FS0:\> ShowBootVariables.efi
Boot0000
UiApp
Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)

Boot0001
UEFI QEMU DVD-ROM QM00003
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)

Boot0002
UEFI QEMU HARDDISK QM00001
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)

Boot0003*
EFI Internal Shell
Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)

Boot0004
UEFI PXEv4 (MAC:525400123456)
PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)

If you want to know information about the printed GUIDs here it is:

As for the 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1 it is a GUID for the firmware volume in our OVMF image. https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.fdf

This *.fdf file lists what drivers/apps are placed in every volume in the image (this includes volumes for SEC, PEI or DXE stages):

...

[FV.SECFV]
FvNameGuid         = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
BlockSize          = 0x1000
FvAlignment        = 16
...
INF <...>
...

[FV.PEIFV]
FvNameGuid         = 6938079B-B503-4E3D-9D24-B28337A25806
BlockSize          = 0x10000
FvAlignment        = 16
...
INF <...>
...

[FV.DXEFV]
FvForceRebase      = FALSE
FvNameGuid         = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1        ### <---- this is a GUID from our output
BlockSize          = 0x10000
FvAlignment        = 16
...
INF  ShellPkg/Application/Shell/Shell.inf          <--- this apps are placed in the FV.DXEFV firmware volume
...
INF  MdeModulePkg/Application/UiApp/UiApp.inf

For the complete edk2 FDF file specification look at the https://edk2-docs.gitbook.io/edk-ii-fdf-specification/

If you look at the https://github.com/tianocore/edk2/blob/master/ShellPkg/Application/Shell/Shell.inf you'll see that EFI Shell is a simple UEFI_APPLICATION. We've developed a lot of those in these lessons, so let's try to add one of our apps to boot options.

We will try to add our HelloWorld application to the boot options. We will look at how Shell app is included and try to do the same.

First we need to add our app to OVMF image. So let's add UefiLessonsPkg/HelloWorld/HelloWorld.inf to the [FV.DXEFV] section next to INF ShellPkg/Application/Shell/Shell.inf in a OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf we've already discussed.

[FV.DXEFV]
FvForceRebase      = FALSE
FvNameGuid         = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1
BlockSize          = 0x10000
FvAlignment        = 16
...

  INF  ShellPkg/Application/Shell/Shell.inf
+ INF  UefiLessonsPkg/HelloWorld/HelloWorld.inf
...

If we try to build OVMF now we would get:

$ build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5
...
build.py...
 : error F001: Module /home/kostr/tiano/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.inf NOT found in DSC file; Is it really a binary module?
...

Ok, so we need to add information to the OvmfPkg/OvmfPkgX64.dsc file. If you look at this file, you'll see that ShellPkg/Application/Shell/Shell.inf is listed under [Components] section. We've already used it in our first lesson when we've tried to compile our app without package. Add UefiLessonsPkg/HelloWorld/HelloWorld.inf next to the Shell INF file.

[Components]
  ...
  ShellPkg/Application/Shell/Shell.inf {
   ...
  }
+ UefiLessonsPkg/HelloWorld/HelloWorld.inf
  ...

Shell.inf file has some information inside the brackets {...}. Don't mind it, we don't need such info for our simple HelloWorld.inf.

Now we can compile OVMF without errors:

$ build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5

Our HelloWorld app would be compiled and embedded in the OVMF image but unfortunately in wouldn't be listed in a boot options.

When we used our ShowBootVariables.efi app we saw that UEFI shell boot option had a description EFI Internal Shell. Let's try search for that in a edk2 codebase:

$ grep "EFI Internal Shell" -r ./ --exclude=Build
./ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c:    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
./OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
./OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.c:    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
./OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c:    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE

For our case we're interested in a ./OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c file:

VOID
EFIAPI
PlatformBootManagerAfterConsole (
  VOID
  )
{
  ...
  //
  // Register UEFI Shell
  //
  PlatformRegisterFvBootOption (
    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
    );

  ...
}

If you grep for a gUefiShellFileGuid:

./OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
./OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf:  gUefiShellFileGuid
./ShellPkg/Application/Shell/Shell.inf:  FILE_GUID                      = 7C04A583-9E3E-4f1c-AD65-E05268D0B4D1 # gUefiShellFileGuid
./ShellPkg/ShellPkg.dec:  gUefiShellFileGuid              = {0x7c04a583, 0x9e3e, 0x4f1c, {0xad, 0x65, 0xe0, 0x52, 0x68, 0xd0, 0xb4, 0xd1}}

Ok it looks like we need to create a UefiLessonsPkg/UefiLessonsPkg.dec file with something like gHelloWorldFileGuid with a value equal to the one that is listed in a UefiLessonsPkg/HelloWorld/HelloWorld.inf file.

Let's do it:

[Defines]
  DEC_SPECIFICATION              = 0x00010005
  PACKAGE_NAME                   = UefiLessonsPkg
  PACKAGE_GUID                   = 7e7edbba-ca2c-4177-a3f0-d3371358773a
  PACKAGE_VERSION                = 1.01

[Guids]
  # FILE_GUID as defined in UefiLessonsPkg/HelloWorld/HelloWorld.inf
  gHelloWorldFileGuid            = {0x2e55fa38, 0xf148, 0x42d3, {0xaf, 0x90, 0x1b, 0xe2, 0x47, 0x32, 0x3e, 0x30}}

EDK2 Package Declaration (DEC) File Format Specification can be found at link https://edk2-docs.gitbook.io/edk-ii-dec-specification/

Let's add our GUID to the OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf file

[Guids]
 ...
  gUefiShellFileGuid
+ gHelloWorldFileGuid

So we could use it in a OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c file:

VOID
EFIAPI
PlatformBootManagerAfterConsole (
  VOID
  )
{
  ...
  //
  // Register UEFI Shell
  //
  PlatformRegisterFvBootOption (
    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
    );

  //
  // Register HelloWorld app
  //
  PlatformRegisterFvBootOption (
    &gHelloWorldFileGuid, L"Hello World", LOAD_OPTION_ACTIVE
    );
  ...
}

If we try to build OVMF now we would get an error:

$ build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5
...

build.py...
/home/kostr/tiano/edk2/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf(87): error 4000: Value of Guid [gHelloWorldFileGuid] is not found under [Guids] section in
        /home/kostr/tiano/edk2/MdePkg/MdePkg.dec
        /home/kostr/tiano/edk2/MdeModulePkg/MdeModulePkg.dec
        /home/kostr/tiano/edk2/SourceLevelDebugPkg/SourceLevelDebugPkg.dec
        /home/kostr/tiano/edk2/OvmfPkg/OvmfPkg.dec
        /home/kostr/tiano/edk2/SecurityPkg/SecurityPkg.dec
        /home/kostr/tiano/edk2/ShellPkg/ShellPkg.dec
...

To correct in we need our newly created UefiLessonsPkg/UefiLessonsPkg.dec to the OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf:

[Packages]
  ...
  ShellPkg/ShellPkg.dec
  UefiLessonsPkg/UefiLessonsPkg.dec

Finally we can successfully build OVMF. Let's run it and test our newly created boot option.

Execute QEMU launch as usual. Now if you'll execute our ShowBootVariables.efi app you would get:

FS0:\> ShowBootVariables.efi
Boot0000
UiApp
Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)

Boot0001
UEFI QEMU DVD-ROM QM00003
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)

Boot0002
UEFI QEMU HARDDISK QM00001
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)

Boot0003*
EFI Internal Shell
Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)

Boot0004
Hello World
Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(2E55FA38-F148-42D3-AF90-1BE247323E30)

Boot0005
UEFI PXEv4 (MAC:525400123456)
PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)

Hooraay! Our boot option is present in the system.

UEFI shell has a command bcfg to print boot variables. You can check that the data from our app is correct, if you execute bcfg boot dump:

Shell> bcfg boot dump
Option: 00. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  Optional- N
Option: 01. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 02. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Shell>  03. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N
Option: 04. Variable: Boot0004
  Desc    - Hello World
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(2E55FA38-F148-42D3-AF90-1BE247323E30)
  Optional- N
Option: 05. Variable: Boot0005
  Desc    - UEFI PXEv4 (MAC:525400123456)
  DevPath - PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)
  Optional- Y

Just in case I've placed Ovmf.diff in this lesson folder that shows all the necessary changes.