初识UEFI

初识UEFI
按惯例,首先让我们用HelloWorld跟UEFI打个招呼吧
标准application
/*main.c */
#include 
< Uefi.h >
EFI_STATUS
UefiMain (
          IN EFI_HANDLE        ImageHandle,
          IN EFI_SYSTEM_TABLE  
* SystemTable
          )
{
   SystemTable 
->  ConOut ->  OutputString(SystemTable -> ConOut, L"HelloWorld\n"); 
   return EFI_SUCCESS;
}
有以下几点需要注意:
1。 头文件, 所有的UEFI程序都有include <Uefi.h>
2。 main函数, UEFI 基本Application的main函数是UefiMain
3。 main函数的返回值类型 EFI_STATUS。 在UEFI中基本上所有的返回值类型都是EFI_STATUS。
它本质上是UINTN。 

4。 main函数的参数。.efi 文件加载到内存后称为Image, ImageHandle 用来描述、访问、控制此Image。 第二个参数是SystemTable,它是我们的程序同UEFI内核打交道的桥梁,通过它我们可以使用UEFI提供的各种服务,如Boot Services和 Runtime Services。 SystemTable是UEFI内核中的一个全局结构体。
5。  输出是通过EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL的OutputString服务完成的。 服务(函数)的第一个参数是This指针,指向Protocol本身。 OutputString()的第二个参数是Unicode字符串。
要想编译main.c,我们还需要.inf文件, 在main.c所在的目录下编辑main.inf文件
##

[Defines]
  INF_VERSION                    
=   0x00010005
  BASE_NAME                      
=  main                    #输出文件的名字为 main.efi
  FILE_GUID                        
=  6987936E - ED34 - ffdb - AE97 - 1FA5E4ED2117
  MODULE_TYPE                   
=  UEFI_APPLICATION #模块类型:
UEFI_DRIVER
DXE_DRIVER
DXE_RUNTIME_DRIVER
,
UEFI_APPLICATION
,BASE,等
  VERSION_STRING                =   1.0
  ENTRY_POINT                    
=  UefiMain               #入口函数

#
# The following information 
is   for  reference only and not required by the build tools.
#
#  VALID_ARCHITECTURES           
=  IA32 X64 IPF EBC
#

# 源文件
[Sources]  
   main.c 

# .dec里面定义 include的路径
[Packages]
  MdePkg
/ MdePkg.dec

#要链接的库
[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib

[Protocols] 
[FeaturePcd]
[Pcd.common]
[Guids]
 
#编译选项, = 表示选项附加到默认选项后面。 == 表示仅使用所定义的选项,弃用默认选项。
[BuildOptions]
  #MSFT:
* _ * _ * _CC_FLAGS  ==    / nologo  / / WX  / GS -   / W4  / Gs32768  / D UNICODE  / O1ib2  / GL   / EHs - c -   / GR -   / GF  / Gy  / Zi  / Gm  / D EFI_SPECIFICATION_VERSION = 0x0002000A   / D TIANO_RELEASE_VERSION = 0x00080006   / FAs  / Oi -
  #MSFT:
* _ * _ * _CC_FLAGS  =     / wd4804 
  #MSFT:Debug_
* _IA32_CC_FLAGS  =  
  #MSFT:Debug_
* _X64_CC_FLAGS  =  
  #MSFT:Release_
* _IA32_CC_FLAGS  =  
  #MSFT:Release_
* _IA32_CC_FLAGS  =  
  #MSFT:Release_
* _IA32_DLINK_FLAGS  =  
  #GCC:Release_
* _IA32_CC_FLAGS  =  

然后将  main.inf 添加到 Nt32Pkg.dsc 或UnixPkg.dsc 的[Components]部分, 例如添加下面一行(example目录在EDK2下)
example / main / main.inf
然后就可以使用BaseTools下的build进行编译了。
Windows下执行
edksetup.bat
build 
- p Nt32Pkg\t32Pkg.dsc  - a IA32

Linux 执行
source .
/ edksetup.sh BaseTools
build 
- p UnixPkg / UnixPkg.dsc  - a IA32

其他类型的inf文件
 (1)    可以看出标准的application处理命令行参数不方便,UEFI提供了帮我们处理命令行参数的入口函数 ShellCEntryLib 。 我们要实现INTN  ShellAppMain(UINTN Argc, CHAR16** Argv) 作为(开发者视角的)入口函数。
/* Main.c  */
#include <Uefi.h>
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
 gST -> ConOut-> OutputString(gST -> ConOut, L"HelloWorld\n"); 
   return 0;
}
inf文件。 我们需要连接 ShellCEntryLib  库。
[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = Main
  FILE_GUID                        = 4ea97c46-7491-4dfd-b442-747010f3ce5f
  MODULE_TYPE                   = UEFI_APPLICATION
  VERSION_STRING               = 0.1
  ENTRY_POINT                    = ShellCEntryLib

#
#  VALID_ARCHITECTURES           = IA32 X64 IPF
#

[Sources]
  Main.c

[Packages]
  MdePkg/MdePkg.dec
  ShellPkg/ShellPkg.dec

[LibraryClasses]   
  ShellCEntryLib
  UefiLib

[BuildOptions]
  

(2)使用main函数的application。如果你想像C一样使用main函数,那么你需要用到LibC。 LibC 中提供了ShellAppMain函数,我们要提供 int main(int Argc, char** Argv) 供其调用。
/*Main.c */
#include 
<Uefi.h>
int
EFIAPI
main (
  IN 
int  Argc,
  IN 
char   ** Argv
  )
{
 gST  ->  ConOut ->  OutputString(gST -> ConOut, L"HelloWorld\n"); 
   return   0 ;
}
真正的入口函数是   ShellCEntryLib, 调用过程为    ShellCEntryLib  -> ShellAppMain -> main.
inf 文件: 我们需要连接   ShellCEntryLib 和LibC库。
[Defines]
  INF_VERSION                    
=   0x00010006
  BASE_NAME                      
=  Main
  FILE_GUID                        
=  4ea97c46 - 7491 - 4dfd - b442 - 747010f3ce5f
  MODULE_TYPE                   
=  UEFI_APPLICATION
  VERSION_STRING               
=   0.1
  ENTRY_POINT                    
=  ShellCEntryLib

#
#  VALID_ARCHITECTURES           
=  IA32 X64 IPF
#

[Sources]
  Main.c

[Packages]

  MdePkg
/ MdePkg.dec
  ShellPkg
/ ShellPkg.dec

[LibraryClasses]   
  LibC
  ShellCEntryLib
  UefiLib

[BuildOptions]
  MSFT: * _ * _IA32_CC_FLAGS   =   / Oi -
还要再说明一点,如果你的程序中用到了printf(...)等等标准C的库函数,那么一定要使用此种类型的application。 因为   ShellCEntryLib 函数中会调用 ShellAppMain(...), StdLib的ShellAppMain(...) 会对stdlib 进行初始化。 然后才可以调用stdlib的函数。 (当然,如果你已经清楚地了解了入口函数的处理流程,你也可以手工调用StdLib的ShellAppMain进行出事后).
(3)Lib 模块的inf文件。开发大型工程的时候我们会用到lib,例如我们要开发视频解码程序,会用到zlib库,
[Defines]
  INF_VERSION                    
=   0x00010005
  BASE_NAME                      
=  zlib
  FILE_GUID                        
=  348aaa62 - BFBD - 4882 - 9ECE - C80BBbbbb736
  VERSION_STRING               
=   1.0
  MODULE_TYPE                   
=  BASE    #Base 表示此模块编译为library
  LIBRARY_CLASS                 
=  zlib

#
# The following information 
is   for  reference only and not required by the build tools.
#
#  VALID_ARCHITECTURES           
=  IA32 X64 IPF EBC
#

[Sources]
  adler32.c
  crc32.c
  deflate.c
  infback.c
  inffast.c
  inflate.c
  inftrees.c
  trees.c
  zutil.c
  compress.c
  uncompr.c
  gzclose.c
  gzlib.c
  gzread.c
  gzwrite.c

[Packages]
  MdePkg
/ MdePkg.dec
  MdeModulePkg
/ MdeModulePkg.dec
  StdLib
/ StdLib.dec

[LibraryClasses]
  MemoryAllocationLib
  BaseLib
  UefiBootServicesTableLib
  BaseMemoryLib
  UefiLib
  UefiRuntimeServicesTableLib

[Protocols]
 

[FeaturePcd]

[Pcd]

[Guids]
 

[BuildOptions]
   GCC: * _ * _IA32_CC_FLAGS  =   - D__UEFI__  -DLARGEFILE64_SOURCE=1  -w
然后将 
zlib | zlib - 1.2 . 6 / zlib.inf # zlib-1.2.6 在EKD2的根目录下
放到.dsc 文件 [LibraryClasses]中。 需要链接zlib的时候,在.inf文件的
[LibraryClasses]
中添加 zlib即可。
(4)driver模块的inf文件。例如DiskIo的inf(
MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
)
[Defines]
  INF_VERSION                    
=   0x00010005
  BASE_NAME                      
=  DiskIoDxe
  FILE_GUID                        
=  6B38F7B4 - AD98 - 40e9 - 9093 - ACA2B5A253C4
  MODULE_TYPE                   
=  UEFI_DRIVER
  VERSION_STRING               
=   1.0
  ENTRY_POINT                    
=  InitializeDiskIo

#
# The following information 
is   for  reference only and not required by the build tools.
#
#  VALID_ARCHITECTURES           
=  IA32 X64 IPF EBC
#
#  DRIVER_BINDING                
=   gDiskIoDriverBinding
#  COMPONENT_NAME                
=   gDiskIoComponentName
#  COMPONENT_NAME2               
=   gDiskIoComponentName2
#

[Sources]
  ComponentName.c
  DiskIo.h
  DiskIo.c


[Packages]
  MdePkg
/ MdePkg.dec

[LibraryClasses]
  UefiBootServicesTableLib
  MemoryAllocationLib
  BaseMemoryLib
  BaseLib
  UefiLib
  UefiDriverEntryPoint
  DebugLib


[Protocols]
  gEfiDiskIoProtocolGuid                        ## BY_START
  gEfiBlockIoProtocolGuid                       ## TO_START

现在我们已经扫除了编译UEFI应用的所有障碍。 在下一部分,我们将了解开发UEFI一定用到的系统服务。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值