Thursday, June 25, 2015

Use C Library in EDK II UEFI Driver

When we use C library in EDK II UEFI Driver, build failure occurs. Please refer UEFI原理與編程 for the detail. This page describes my way to solve it.

We want to use sprintf() of C library in UEFI driver to provide the driver information (e.g., build-date). I like to write the code as below,

#include <stdio.h>

EFI_STATUS
EFIAPI
LibCDxeEntryPoint (
  IN EFI_HANDLE ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  CHAR8 Info [256];
            
  sprintf (Info, "Build Date: %s", __DATE__);

  return EFI_SUCCESS;
}  

, but build failure occurs. Please,

1. Add the following statements in your package DSC file.

These statements declare that we will build C library for UEFI driver.

[LibraryClasses.Common.UEFI_DRIVER]  
  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf  
  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
  
  LibC|StdLib/LibC/LibC_ForDriver.inf
  #LibC|StdLib/LibC/LibC.inf
  LibCType|StdLib/LibC/Ctype/Ctype.inf  
  LibLocale|StdLib/LibC/Locale/Locale.inf  
  LibSignal|StdLib/LibC/Signal/Signal.inf  
  LibStdio|StdLib/LibC/Stdio/Stdio.inf  
  LibStdLib|StdLib/LibC/StdLib/StdLib.inf
  LibString|StdLib/LibC/String/String.inf  
  LibTime|StdLib/LibC/Time/Time.inf  
  LibUefi|StdLib/LibC/Uefi/Uefi.inf  
  LibWchar|StdLib/LibC/Wchar/Wchar.inf  
  
  LibGen|StdLib/PosixLib/Gen/LibGen.inf  
  LibIIO|StdLib/LibC/Uefi/InteractiveIO/IIO.inf

  LibContainer|StdLib/LibC/Containers/ContainerLib.inf   
  
  LibGdtoa|StdLib/LibC/gdtoa/gdtoa.inf  
  DevConsole|StdLib/LibC/Uefi/Devices/daConsole.inf
  DevUtility|StdLib/LibC/Uefi/Devices/daUtility.inf

2. Use LibC_ForDriver.inf instead of LibC.inf.

We removes ShellCEntryLib from LibC_ForDriver.inf. If we don't do it, the error occurs.

error 1001: Module type [UEFI_DRIVER] is not supported by library instance [...\MdePkg\Library\UefiApplicationEntryPoint\UefiApplicationEntryPoint.inf]

LibC_ForDriver.inf

[LibraryClasses]
#  ShellCEntryLib
  UefiLib
  BaseLib
  BaseMemoryLib
  MemoryAllocationLib
  LibStdLib
  LibStdio
  LibString
  DevConsole

3. Add dummy main().

After we follow the steps, the link error occurs, the main symbol is not defined. Please add dummy main() in your driver.

int
main (
  IN int Argc,
  IN char **Argv
  )
{
  return 0;
}

Now we can build the UEFI driver with C standard library.

-Count

4 comments:

  1. in stdio.h,sprintf defined as below
    int sprintf (char * __restrict Buff, const char * __restrict Format, ...);
    but type of arrary Info[] is char8
    how to void conflict of the type error?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I commented out ShellCEntryLib in my own LibC_ForDriver.inf. I also tried to remove all inclusions of UefiShellLib and still get an error from clause 2:
    c:\edk2\OvmfPkg\OvmfPkgX64.dsc(...): error 1001: Module type [DXE_SMM_DRIVER] is not supported by library instance [c:\edk2\ShellPkg\Library\UefiShellLib\UefiShellLib.inf]
    consumed by [My SMM/DXE Driver.inf]

    ReplyDelete