如何使用efi toolkit搭建编译efi app的环境
来源:互联网 发布:欧洲难民问题知乎 编辑:程序博客网 时间:2024/06/10 00:31
前几天与人聊到efi下的程序编写。突然意识到从刚开始接触efi的时候,写过几个sample 程序之外,已经很久没动过EDK或者 efi_toolkit了。记得那时候和老虎同学一起学习的劲儿,经常一起讨论问题,相互学习。当时对新生事物的那股热情真让你记忆犹新。
记得是用EDK模拟了EFI shell的环境,然后可以在该环境中熟悉efi shell和efi编程。具体的模拟环境的搭建现在还没好到当时的记录。不过如何编译efi shell下的app,因为有部分source code,所以还能回想起流程。
这里转发一篇当时学习过的文章:如何使用efi toolkit搭建编译efi app的环境。
-----------------------以下为转载--------------------------------
本文说明:关于UEFI Application编写及测试,论坛里的很多帖子及其回复都有说过,过程并不复杂,但是如果不知道的话可能也会像我一样折腾很久很久的时间。自然很多弟兄都已经轻车熟路了,写本文希望对不知道的弟兄做一个引导作用。我觉得先了解Application,再来学习UEFI是很有帮助的,可以写写小程序来亲身体会像Service或者Protocol的运作。小弟我还是一如既往的唠唠叨叨的写的很长,希望已经把关键地方都说明白了。
一.环境配置
1.VS2008
为避免一些奇怪的问题,切记完整安装,我的是安装的默认路径。
2.UDK
下载完UDK(http://sourceforge.net/projects/edk2/files/)后,把它放在D:\MyWorkspace目录下面。安装Release Notes里面“HOW TO BUILD NT32”所说方法进行编译,步骤简单,我就翻译过来:
第一步,打开VS2008命令行,进入D:\MyWorkspace。
第二步,运行edksetup.bat。
第三步,运行命令:build -a IA32 -p Nt32pkg\nt32pkg.dsc。
第四步,启动模拟器命令build run。(自然以后运行模拟器的时候就不用第三步了,我很唠叨,呵呵)
看到的模拟器界面是如下:
其中fsnt0对应的目录是D:\MyWorkspace\Build\NT32\DEBUG_MYTOOLS\IA32,fsnt1对应的目录是D:\MyWorkspace\EdkShellBinPkg\Bin\Ia32\Apps。
3.EFI_Toolkit
下载EFI_Toolkit(http://sourceforge.net/projects/efi-toolkit/files/)后,我的是把它放在D:\EFI_Toolkit_2.0下面。然后就修改一下配置:
一是build.cmd里面SDK_INSTALL_DIR=D:\EFI_Toolkit_2.0,SDK_BUILD_ENV=bios32。
二是build\bios32\sdk.env里面将/Gs8192改为/GS-,然后为了以后方便修改SDK_BIN_DIR:SDK_BIN_DIR=D:\MyWorkspace\Build\NT32\DEBUG_MYTOOLS\IA32\MyProject,这样编译后的程序就到了这个目录下面,在UDK模拟器中对应的也就是fsnt0\MyProject。
可以编译EFI_Toolkit了,再翻译一下步骤:
第一步:打开VS2008命令行,进入D:\EFI_Toolkit_2.0
第二步:运行build (或者build bios32)
第三步:nmake
这样就编译完成了,所有的efi程序都生成到指定的目录下面了,可以在模拟器上运行。
二.几个简单的Application例子
在EFI_Toolkit_2.0\apps下面建立目录hello,并在该目录下新建hello.c和hello.mak
hello.c程序如下:
EFI_STATUS
HelloEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){
UINTN Index;
SystemTable->ConOut->OutputString(SystemTable->ConOut,L"Hello,World!\r\n");
SystemTable->ConOut->OutputString(SystemTable->ConOut,L"Press any key to continue...");
SystemTable->BootServices->WaitForEvent(1,&(SystemTable->ConIn->WaitForKey),&Index);
return EFI_SUCCESS;
}
hello.mak如下(除了红色字体部分,其余可以作为模板来理解):
BASE_NAME= hello
IMAGE_ENTRY_POINT = HelloEntry
TARGET_APP = $(BASE_NAME)
SOURCE_DIR = $(SDK_INSTALL_DIR)\apps\hello
BUILD_DIR= $(SDK_BUILD_DIR)\apps\$(BASE_NAME)
!include $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR)\makefile.hdr
INC = -I $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR) \
-I $(SDK_INSTALL_DIR)\include\$(EFI_INC_DIR)\$(PROCESSOR) $(INC)
LIBS = $(LIBS) $(SDK_BUILD_DIR)\lib\libefi\libefi.lib
all : dirs $(LIBS) $(OBJECTS)
OBJECTS = $(OBJECTS) $(BUILD_DIR)\$(BASE_NAME).obj
$(BUILD_DIR)\$(BASE_NAME).obj : $(*B).c $(INC_DEPS)
!include $(SDK_INSTALL_DIR)\build\master.mak
VS2008命令行模式下进入D:\EFI_Toolkit_2.0\目录,运行build之后,进入apps\hello目录,执行命令nmake –f hello.mak。这样hello.efi就生成在指定目录了。
再举个使用了efilib的例子(makefile文件模仿上面写):
#include <efi.h>
#include <efilib.h>
EFI_STATUS
ShowTimeEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable) {
EFI_TIME time;
EFI_RUNTIME_SERVICES * mRT=SystemTable->RuntimeServices;
InitializeLib(ImageHandle,SystemTable);
mRT->GetTime(&time,NULL);
Print(L"%04d-%02d-%02d %02d:%02d:%02d", \
time.Year,time.Month,time.Day,time.Hour,time.Minute,time.Second);
return EFI_SUCCESS;
}
上面两个程序运行效果如下:
下面再举一个例子,用来说明参数ImageHandle的作用,正如这个名字,它用来反映程序的在Image上面的信息。Handle本身是没有任何意义的,它的意义在于通过它可以访问到挂接在它下面的各种Protocol实例。而这个ImageHandle是调用者(比如说Shell)在调用这个程序之前,检索程序Image信息时创建的,并传入给这个程序作为入口参数。这个程序就可以通过这个ImageHandle访问到自己的Image相关信息。(Image相当于存储设备上的文件)。下面的例子是通过ImageHandle获得当前程序的Image路径(差不多也就是文件路径了)。
#include <efi.h>
#include <efilib.h>
EFI_STATUS
TestEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){
EFI_LOADED_IMAGE *LoadedImage;
EFI_DEVICE_PATH *DevicePath;
EFI_STATUS Status;
CHAR16 *DevicePathAsString;
InitializeLib(ImageHandle,SystemTable);
Status = BS->HandleProtocol (ImageHandle,&LoadedImageProtocol,&LoadedImage);
if(EFI_ERROR(Status)){
Print(L"Error Occur!");
return EFI_SUCCESS;
}
Status = BS->HandleProtocol (LoadedImage->DeviceHandle,&DevicePathProtocol,&DevicePath);
if(EFI_ERROR(Status)){
Print(L"Error Occur!");
return EFI_SUCCESS;
}
DevicePathAsString = DevicePathToStr(LoadedImage->FilePath);
if (DevicePathAsString != NULL) {
Print (L"Image file : %s\n", DevicePathAsString);
FreePool(DevicePathAsString);
}
return EFI_SUCCESS;
}
上面程序运行效果图如下:
关于UEFI Application就说明到这里。
附:
1.有些efi程序在模拟器中运行失败,可以尝试在U盘UEFI Shell下面运行。制作U盘UEFI Shell的方法在UDK的ReleaseNote中有介绍。
2.发帖至今已经很久没有搞BIOS了,一些编译环境现在也没有了,弟兄们搭建环境过程中的各种问题我也没办法回答。所以有什么问题,可以发帖问问,总有人知道的。对不住了。
原文链接: http://www.biosren.com/thread-3515-1-1.html
- 如何使用efi toolkit搭建编译efi app的环境
- 关于EFI toolkit的编译环境的搭建
- EFI
- efi
- uefi 是如何找到grubaa64.efi的
- EFI 函数的问题
- EFI Protocol 的分析
- EFI方式编译启动Xen
- 如何安装 EFI 分区引导
- 安装ubuntu失败,如何删除烦人的efi分区
- efi下的的shell
- 使用diskpart修复EFI分区变主分区的问题
- 【EFI系统分区】关于EFI系统分区的说明
- EFI相关的一些链接
- 修改 EFI EDK2 的logo
- 关于EFI的一点介绍
- MACBook EFI升级的后患
- efi的sys文件系统接口
- C++指针函数应用
- 接口的应用
- 【9个方法黑屏故障消失不见】
- DSS Stream BroadCast
- 模式识别/机器学习/图像视频/ 常见概念科普
- 如何使用efi toolkit搭建编译efi app的环境
- Programming ASP.NET MVC-Fundamentals of ASP.NET MVC(七)Models
- eclipse tomcat部署完毕,在tomcatwebapps下却找不到项目文件夹
- poj 3660 Cow Contest
- iPhone上如何侦测到系统的语言设定
- Splunk
- Ensemble如何将外部数据源数据迁入cache数据库
- oracle 使用flashback(闪回)恢复误删除的数据 或 误删除的表
- Android访问第三方资源通用接口(自我整理)