UEFI 基础教程 (一) - 运行第一个APP HelloWorld

  • UEFI 基础教程 (二) - 运行第一个APP HelloWorld

一.代码编写:

1.edk2/OvmfPkg/HelloWorld/HelloWorld.c:

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>

//ShellCEntryLib call user interface ShellAppMain
EFI_STATUS
EFIAPI
HelloWorldEntry(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
)
{
  EFI_STATUS  Status = EFI_SUCCESS;
  Print (L"[Console]  HelloWorldEntry Start..\n");

  Print (L"[Console]  HelloWorldEntry  End ... \n");
  return Status;
}

2.OvmfPkg/HelloWorld/HelloWorld.inf:

[Defines]
  INF_VERSION = 0x00010007
  BASE_NAME = HelloWorld
  FILE_GUID = 69A6DE6D-FA9F-485E-9A4E-EA70FDCFD82F
  MODULE_TYPE = UEFI_APPLICATION
  VERSION_STRING = 1.0
  ENTRY_POINT = HelloWorldEntry

[Sources]
  HelloWorld.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib

3.OvmfPkg/OvmfPkgX64.dsc:

diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index c9235e4..c42708a 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -661,6 +661,7 @@
 ################################################################################
 [Components]
   OvmfPkg/ResetVector/ResetVector.inf
+  OvmfPkg/HelloWorld/HelloWorld.inf

二.编译生成EFI文件

1.编译

$ build -a X64 -p OvmfPkg/OvmfPkgX64.dsc -D DEBUG_ON_SERIAL_PORT

2.检查efi文件

Build/OvmfX64/DEBUG_GCC5/X64/HelloWorld.efi

三.运行HelloWorld.efi (参考:https://github.com/emvivre/uefi_hello_world)

git clone https://github.com/emvivre/uefi_hello_world.git

将文件build_and_test.sh拷贝到edk2根目录下,然后修改:

#!/bin/sh
set -e

dd if=/dev/zero of=uefi.img bs=512 count=93750
sgdisk -n 1 -t 1:ef00 -c 1:"EFI System Partition" uefi.img
dd if=/dev/zero of=part.img bs=512 count=91669
mformat -i part.img -h 32 -t 32 -n 64 -c 1
mcopy -i part.img HelloWorld.efi ::
dd if=part.img of=uefi.img bs=512 count=91669 seek=2048 conv=notrunc
sgdisk -p uefi.img

#qemu-system-x86_64 -cpu qemu64 -bios /usr/share/ovmf/OVMF.fd -drive file=uefi.img,if=ide -net none
qemu-system-x86_64 -cpu qemu64 -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -drive file=uefi.img,if=ide -net none

执行./build_and_test.sh
在这里插入图片描述

三.标准应用程序加载过程

  编译过程:

  • HelloWorld.c 首先被编译成目标文件 HelloWorld.obj
  • 连接器将目标文件HelloWorld.c 和其它库连接成HelloWorld.dll
  • GenFw 工具将HelloWorld.dll 转化成 HelloWorld.efi

  上述过程由 build 命令自动完成,连接器在生成HelloWorld.dll时使用了/dll/entry:_ModuleEntryPoint。.efi是遵循了PE32格式的二进制文件,_ModuleEntryPoint便是这个二进制文件的入口函数。下面探讨应用程序加载过程,主要看_ModuleEntryPoint和源文件中入口函数UefiMain的关系。

  • 将HelloWorld.efi 文件加载到内存
    当shell中执行HelloWorld.efi时,shell首先用gBS->LoadImage()将HelloWorld.efi文件加载到内存生成Image对象,然后调用gBS->StartImag(Image)启动这个Image对象。gBS->StartImage()是一个函数指针,它实际指向的是CoreStartImage()。

  • 进入映像入口函数
    CoreStartImage()的主要作用是调用映像入口函数,在gBS->StartImage 的核心是Image->EntryPoint(···),它就是程序映像的入口函数,对应程序来说就是_ModuleEntryPoint 函数。进入 _ModuleEntryPoint 后,控制权才转交给应用程序(HelloWorld.efi)。
      _ModuleEntryPoint主要处理三件事:
      1. 初始化:初始化函数ProcessLibraryConstructorList中调用一系列构造函数
      2. 调用本模块的入口函数 : ProcessModuleEntryPointList 中调用的是工程模块定义的入口函数
      3. 析构:ProcessLibraryDestructorList 中调用一系列析构函数。
    这三个对应的函数AutoGen.h,AutoGen.c中。

  • 进入模块入口函数
    在ProcessModuleEntryPointList函数中调用了工程模块的真正入口函数UefiMain。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值