美文网首页
List of Tips for UEFI Developmen

List of Tips for UEFI Developmen

作者: Ramperouge | 来源:发表于2018-03-14 10:53 被阅读0次

    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

    • Debug information output in PEI pahse
    // 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)));
    }
    
    • The dependency expression in PEI phase
    • The PcdLIb instances will read the Module INF to ensure whether the PCD exists, and replace the PCD Token used in Module C source file with the value defined in platform DEC according to the [Pcd] part of Module INF

    (2) Debugging

    • Usage of QEMU serial port 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
    
    • Tesing UEFI Apps with virtual hard-disk
    # 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
    
    • Testing UEFI Application on VMware WorkStation

    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

    • Useful Hot-Keys of QEMU
      Ctrl + Alt: release the mouse
      Ctrl + Alt + 1: The main graphic console
      Ctrl + Alt + 2: The QEMU Command condole
      Ctrl + Alt + 3: Serial port debugging output

    (3) Tricks for UEFI Aplication

    • The console output of UEFI Application
    # 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);
    
    • The String type incompatibility error
    // 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
    
    • The definition of headers and compulsory inclusion for specific situation
    > 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;
    }
    
    • The definition of fundamental types in UEFI
    // 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;
    
    • Mechanism of Library/PCD/GUID Usage in Pkg Description File

    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

    相关文章

      网友评论

          本文标题:List of Tips for UEFI Developmen

          本文链接:https://www.haomeiwen.com/subject/dqkczxtx.html