List of Tips for UEFI Developmen

2018-03-14  本文已影响0人  Ramperouge

Last Updated on 04/11/18

This is the extraction of the UEFI development in form of an organized tips list. In this passage, we focus more on the implementation details than the general concepts involved in Tianocore.

(1) Pre-EFI Initialization

// MdeModulePkg/Core/Pei/Image/Image.c
   if (Machine != EFI_IMAGE_MACHINE_IA64) {
      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
    } else {
      // For IPF Image, the real entry point should be print.
      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
}

(2) Debugging

# Ensure that the OVMF is built in DEBUG mode with DEBUG_ON_SERIAL_PORT enabled
# For common firmware on physical machine, ensure that the fundamental \
# debug library classes are included in the specific platform DSC
# and debug headers are included in the testing programmes.

../vtpm-support/qemu-tpm/x86_64-softmmu/qemu-system-x86_64 -display sdl \
-m 2048 -serial file:/home/hecmay/debug.log -global isa-debugcon.iobase=0x402 \
-net none -boot c -bios Build/Ovmf3264/DEBUG_GCC5/FV/OVMF.fd -boot menu=on \
-tpmdev cuse-tpm,id=tpm0,path=/dev/vtpm0 \
-device tpm-tis,tpmdev=tpm0 Build/test.img
# create the test image file
 dd if=/dev/zero of=test.img bs=1M count=128

# format the file system of the image
mkfs -t vfat test.img

# Map the image to loop device && mount the formated image to /mnt/
sudo mount -o loop test.img /mnt/

# copy the compiled UEFI Apps to /mnt/ and run QEMU with it
qemu-system-x86_64 -bios Build/Ovmf3264/DEBUG_GCC5/FV/OVMF.fd test.img

Simply build up a naked virtual machine without OS installed in VMware, and enable the EFI Support in VMware configuration, we are able to enter the EFI Shell stage in virtual machine (without using OVMF).

By inserting a USB stick with FAT compatible File System and dump the EFI Applications into it, the testing job will be much easier.
https://blog.fpmurphy.com/2014/07/using-vmware-workstation-to-experiment-with-uefi.html

(3) Tricks for UEFI Aplication

# If using the Print function defined in UEFI, ensure UefiLib.h is included
# For string of CHAR8 type, conversion to CHAR16 is needed like

static VOID
AsciiToUnicodeSize( CHAR8 *String, 
                   UINT8 length, 
                   CHAR16 *UniString)
{
   int len = length;

   while (*String != '\0' && len > 0) {
       *(UniString++) = (CHAR16) *(String++);
       len--;
   }
   *UniString = '\0';
}

CHAR16 Buffer[100];
AsciiToUnicodeSize(Str, length, Buffer);
Print(L"text here: %x, %d, %s", Addr, Status, Buffer);
// When running UEFI App in UEFI Shell
>FS: xxx.efi
>Error Command Status : Not Found
  // edk2/ShellPkg/Application/Shell/Shell.c +2583
  //
  // Now print errors
  // 
  if (EFI_ERROR(Status)) {
    ConstScriptFile = ShellCommandGetCurrentScriptFile();
    if (ConstScriptFile == NULL || ConstScriptFile->CurrentCommand == NULL) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));
    } else {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID*)(Status), ConstScriptFile->CurrentCommand->Line);
    }
  }

//
// ......
//

// edk2/ShellPkg/Application/Shell/Shell.uni
#string STR_SHELL_ERROR     #language en-US  "%NCommand Error Status: %r\r\n"

Make sure the type selection and variable correspondent, otherwise the Shell.efi will not be able to read out the script from it.

>>> cat /proc/sys/kernel/random/uuid
... 968b810c-00ea-42a5-88dc-6f8fa952c9b9
> ShellPkg/Include/Library/ShellCEntryLib.h
>>  This header includes the initial definition of function ShellAppMain(), which is compulsory for UEFI Shell App

> ShellPkg/Include/Library/ShellLib.h
>> Similar but includes function handles for Efi Shell.
>> And redefinition of ShellAppMain() Should return a INTN instead of EFI_STATUS

* A simple example of gRT
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/ShellLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>

#include <Protocol/EfiShell.h>
#include <Protocol/LoadedImage.h>

INTN
EFIAPI
ShellAppMain (
          IN UINTN    Argc,
          IN CHAR16   **Argv
          )
{
    EFI_STATUS  Status = EFI_SUCCESS;
    gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
    return Status;
}
// MdePkg/Include/Ipf/ProcesserBind.h

// Other frequently-used base type in UEFI please refer to
// MdePkg/Include/Uefi/UefiBaseType.h

  ///
  /// 1-byte Character.
  ///
  typedef char                CHAR8;
  ///
  /// 1-byte signed value.
  ///
  typedef signed char         INT8;
#else
  ///
  /// 8-byte unsigned value.
  ///
  typedef unsigned long long  UINT64;
  ///
  /// 8-byte signed value.
  ///
  typedef long long           INT64;
  ///
  /// 4-byte unsigned value.
  ///
  typedef unsigned int        UINT32;
  ///
  /// 4-byte signed value.
  ///
  typedef int                 INT32;

The Platform includes the "Include" Path, the Protocol GUID, Platform Configuration Database items and the path of headers of the library in this specific Pkg

The DEC file includes the "Include" Path, with which the compiler will search for if encountering phrase like #include <Library/xxx.h> in the pragma code. In order to tell the compiler which Pkg "Include" Path the module is going to use, you should also declare the Pkg's DEC file path in the module's INF file.

About the Library you want to use: Please include the Library's INF files in the [LibraryClass] Part of the platform DSC File

上一篇 下一篇

猜你喜欢

热点阅读