1. ubuntu中UEFI在环境中运行Hello world
运行“make -C BaseTools”。
具体步骤:
首先安装必须的软件:sudo apt-get install build-essential uuid-dev iasl git gcc-5 nasm python3-distutils。
第二步,将edk2-vUDK2018.tar.gz解压到~/src/MyWorkspace下。
第三步,拷贝OpenSSL Crypto Library,到指定的网站下载openssl库解压到指定文件夹下。
第四步,生成BaseTools。进入目录~/src/MyWorkspace,运行“make -C BaseTools”,生成所需的工具软件。
2. 如何生成uefi启动文件 如何添加UEFI启动
uefi作为传统bios的接班者,拥有图形化界面、植入硬件驱动等bios无法支持的功能,早在win8发布时就已宣布全面支持uefi,让众多主板厂商争相把uefi作为主板标准配置之一。日前,u深度发布出uefi版u盘启动盘制作工具,方便使用ufei启动的电脑实现u盘启动,现在我们就给大家介绍u深度uefi版启动盘制作工具制作uefi启动u盘的步骤。
制作ufei启动u盘前,需要准备一个可以正常使用的u盘,推荐使用容量2GB以上的空间大小。
1、运行u深度v3.0ufei版u盘启动盘制作工具,如图所示:
以上关于运用u深度ufei版制作uefi启动u盘的全过程,首次使用该软件的用户可以参照以上步骤进行学习制作。在使用ufei启动u盘进入电脑时,需要注意选择uefi开头的启动项才可以体验uefi启动的效果。
3. 第五章 UEFI 的基础服务
[TOC]
系统表是重要的数据接口之一,是用户空间通往内核空间的通道。
(1)在应用程序和驱动中访问系统表
系统表是 UEFI 内核的一个全局结构体,其指针作为程序映像入口函数的参数传递到用户空间。程序映像(包括 UEFI 应用程序、DXE 驱动程序、UEFI 驱动程序)的入口函数有统一的格式,函数原型如下:
(2)系统表指针从内核传递到用户空间的过程
程序映像的入口函数通常是 _MoleEntryPoint。当应用程序或驱动加载到内存形成 Image 后,_MoleEntryPoint 函数地址被赋值给 Image 对象的 EntryPoint,然后 Image->EntryPoint 会被执行,最终会从 Image 的入口函数 _MoleEntryPoint 执行到模块的入口函数。
系统表可分为以下6个部分
系统表数据结构:
UEFI 中的表通常都以 EFI_TABLE_HEADER 开头,数据结构如下:
这三个控制台设备以及 ConIn、ConOut、StdErr 三个 Protocol 在驱动 ConSplitterDxe 中被初始化。
ConfigurationTable 是系统配置表,指向 EFI_CONFIGUTATION_TABLE 数组,数组中每一项是一个表,这个表的数据结构如下:
在 UEFI 中只有一个地址空间,所有程序都运行在 RING0 优先级,应用程序地址空间(用户空间)占用 UEFI 地址空间的一部分。
系统表的地址可以通过模块的入口函数的参数得到。示例:
上面示例中的模块入口函数 UefiMain 中使用传入的参数 SystemTable 访问系统表。EDK2 为了方便开发者,提供了 UefiBootServicesTableLib,在 UefiLib 定义了全局变量 gST
、gBS、gImageHandle。这三个全局变量在函数 中被初始化,该函数是库 UefiBootServicesTableLib 的构造函数,在 AutoGen.c 中的 ProcessLibraryConstructorList 被调用,而 ProcessLibraryConstructorList 是在 UefiMain 之前被调用的。
构造函数 源码:
gST 变量是定义在用户空间的变量,而它指向的系统表定义在 UEFI 内核中。在应用程序或驱动工程文件的 [LibraryClasses] 里引用 UefiBootServicesTableLib 后,就可以使用 gST 访问系统表了。示例:
其实就是使用 gST 和 gBS 替换掉 SystemTable 和 SystemTable->BootServices。
启动服务是 UEFI 的核心数据结构,可以分为以下几类:UEFI 事件服务、内存管理服务、Protocol 管理服务、Protocol 使用类服务、驱动管理服务、Image 管理服务、ExitBootServices、其他服务。
启动服务由 UEFI 表头和表项组成,表中每一项是一个函数指针,该函数用于提供一项服务。
事件是异步操作的基础,使得在 UEFI 系统内可以执行并发操作。UEFI 事件服务包含事件(Event)、定时器(Timer)、任务优先级(TPL)三类服务。
详见第六章。
内存管理服务主要提供内存的分配与释放服务、管理系统内存映射。主要包括:AllocatePages、FreePages、AllocatePool、FreePool、GetMemoryMap。
AllocatePool/FreePool 用法
AllocatePool 和 FreePool 服务函数原型:
枚举类型 EFI_MEMORY_TYPE:
调用 gBS->ExitBootServices 之后, EfiBootServicesCode 和 EfiBootServicesData 类型内存被回收;EfiLoaderCode 和 EfiLoaderData 由 OS Loader 和操作系统决定是否回收;EfiACPIReclaimMemory 类型内存在 APCI 启用后被回收;其他类型内存保留。
AllocatePages/FreePages 用法
内存和驱动开发中经常会要求分配到的内存不得跨页,或需要分配完整的内存页,为此提供了分配页的服务 AllocatePages。
AllocatePages 和 FreePages 服务函数原型:
枚举类型 EFI_AlLOCATE_TYPE
GetMemoryMap 用法
GetMemoryMap 用于取得系统中所有的内存映射。
GetMemoryMap 服务函数原型:
EFI_MEMORY_DESCRIPTOR 数据结构
Protocol 管理服务提供安装与卸载 Protocol 的服务,以及注册 Protocol 通知函书(安装时调用)的服务。
详见第八章、第九章。
Protocol 使用类服务包括 Protocol 的打开与关闭,查找支持 Protocol 的控制器,主要提供 Protocol 使用者使用。
详见第四章。
驱动管理服务包括将驱动安装到控制器的 connect 服务和将驱动从控制器上卸载的 disconnect 服务。
详见第九章。
Image 管理服务包括加载、卸载、启动、退出 UEFI 应用程序或驱动。
启动服务中的 Image 管理服务
ExitBootService 用于结束启动服务,该服务成功返回后,系统进入 RT 期。操作系统加载器从启动服务接过对计算机系统的控制权后必须调用该服务。
启动服务中的其他服务
从进入 DXE 阶段运行时服务被初始化,直到操作系统结束,运行时服务都一直存在并向上层提供服务。运行时服务主要包括:时间服务、读写系统变量、虚拟内存服务、其他服务。
时间服务包括:读取 / 设置硬件事件、读取 / 设置唤醒定时器。
GetTime/SetTime
计算机硬件时钟由单独的电池供电,操作系统启动时通过读取硬件时钟获得事件。
GetTime/SetTime 服务函数原型:
时钟性能用 EFI_TIME_CAPABILITIES 表示:
GetWakeupTime/SetWakeupTime
GetWakeupTime 用于读取唤醒定时器的状态,SetWakeupTime 用于启用或禁用唤醒定时器。
GetWakeupTime/SetWakeupTime 服务函数原型:
UEFI 系统变量服务包括:GetVariable、SetVariable、GetNextVariableName。
GetVariable 用法
GetVariable 用于根据变量名获取变量值和属性。
GetVariable 服务函数原型:
SetVariable 用法
SetVariable 有三项功能:新建、更新、删除变量。
SetVariable 服务函数原型:
GetNextVariableName 用法
GetNextVariableName 用于获取下一个系统变量,通过这个服务可以遍历系统中的变量。
GetNextVariableName 服务函数原型:
要启动搜索(获得第一个变量),需要 VariableName 指向空字符串。
虚拟内存服务包括:SetVirtualAddressMap 和 ConvertPointer。这两个服务只有在运行时期间被操作系统加载器调用。
调用流程:
SetVirtualAddressMap/ConvertPointer 服务函数原型:
*Address 作为输入参数时是物理地址,作为输出参数时返回对应的虚拟地址。ConvertPointer 通过查询系统的内存映射表计算出给定物理地址的虚拟地址。当 DebugDispositon 设置了 EFI_OPTION_PTR 标志时,输入参数 *Address 允许为空。
4. 编译UEFI版本Grub2引导多系统文件efi
官网源码地址
首先要从grub官网下在grub2,grub2中包含所有grub2相关的命令,可以用来生成grub2引导,这里着重介绍制作UEFI版本的grub2
内置配置文件为:grub.cfg,内置配置文件搜索/EFI/grub/compile.cfg 文件,并将其设定为配置文件。
将其保存在grub2解压的压缩目录下,内容如下:
在grub2压缩包下面解压目录下打开命令行,输入以下命令:下面是编译64的文件
以上生成完毕,在文件夹下会出现一个bootx64.efi文件,BOOTIA32.efi 文件夹,
将其和x86_64-efi、locale文件夹、unicode.pf2一起拷贝到第一个fat/fat32分区,并新建一个grub.cfg。
其中,x86_64-efi为模块目录,locale为地区语言,unicode.pf2为字体,grub.cfg为引导加载的配置文件
目录如下:
FAT/FAT32
#########################
/EFI/Boot/bootx64.efi
/EFI/Boot/BOOTIA32.efi
/EFI/grub/grub.cfg
/EFI/grub/unicode.pf2
/EFI/grub/x86_64-efi/
/EFI/grub/locale/
#####################
x64.cfg内容示例:
[plain] view plain
function load_video {
if [ x$feature_all_video_mole = xy ]; then
insmod all_video
else
insmod efi_gop
insmod efi_uga
insmod ieee1275_fb
insmod vbe
insmod vga
insmod video_bochs
insmod video_cirrus
fi
}
insmod part_gpt
insmod fat
set root='hd0,gpt1'
font="/EFI/grub/unicode.pf2"
if loadfont prefix/locale
set lang=zh_CN
insmod gettext
fi
terminal_output gfxterm
insmod jpeg
if background_image /EFI/grub/background.jpg; then
true
else
set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
if background_color 255,255,155,0; then
clear
fi
fi
set default=0
set timeout_style=menu
set timeout=5
menuentry "启动 delta win7" --class windows --class os {
insmod ntfs
set root='(hd0,gpt2)'
}
menuentry "local win7" --class windows --class os {
insmod ntfs
set root='(hd0,gpt3)'
}
menuentry "ubuntu16.04 x86" --class ubuntu --class os {
insmod ext2
set root='(hd0,gpt5)'
linux /vmlinuz ro root=/dev/sda5
initrd /initrd.img
echo "Start Ubuntu 16.04"
}
menuentry "ubuntu16.04 x64" --class ubuntu --class os {
insmod ext2
set root='(hd0,gpt6)'
linux /vmlinuz ro root=/dev/sda6
initrd /initrd.img
echo "Start Ubuntu 16.04"
}
menuentry "-------------------" --class ubuntu --class os{
set root=(hd0,gpt1)
}
menuentry "ubuntu-efi" --class ubuntu --class os {
insmod ext2
set root='(hd0,gpt5)'
chainloader /efi/grub.efi
}
menuentry "install ubuntu" --class ubuntu --class os {
insmod ext2
insmod loopback
set root=(hd0,gpt4)
set isofile=/OS/linux/ubuntu-16.04.2-desktop-amd64.iso
loopback loop isofile
initrd (loop)/casper/initrd.lz
}
menuentry "-------------------" --class ubuntu --class os{
set root=(hd0,gpt1)
}
menuentry "reboot" --class windows --class os{
insmod reboot
reboot
}
menuentry "halt" --class windows --class os{
insmod halt
halt
}
https://wiki.archlinux.org/index.php/GRUB_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
https://help.ubuntu.com/community/UEFIBooting
http://ftp.gnu.org/gnu/grub/
http://ftp.gnu.org/gnu/grub/grub-2.02-for-windows.zip
https://www.gnu.org/software/grub/manual/grub.html
http://jingyan..com/article/c85b7a640cd7d6003bac95f8.html
https://packages.ubuntu.com/source/trusty/grub2
https://www.kernel.org/pub/linux/utils/boot/syslinux/
http://www.jinbuguo.com/linux/grub.cfg.html
http://blog.csdn.net/listener_ri/article/details/45621947
http://bbs.wuyou.net/forum.php?mod=viewthread&tid=385353
在进入grub界面如果出现
问题出在引导配置文件没有找到.
那么如何调试呢?
可以尝试打印变量的方法,输入C进入命令模式
输入gettext $prefix
我们发现还是提示(hd0,gp1)/EFI/grub
说明目录并没有被更改,我们可以验证一下放到此目录在跑起来.
发现果然又可以了,后面原因就是便宜目录的compile.cfg里面的目录并没有修改到根目录。
打开cfg文件查看是不是配置了语言文件,但是目录不存在
如果依然乱码,修改文件编码为utf-8
在④步骤中,已经生成BIOS模式所需的内核文件Core.img,其大小是86.5 KB
生成的只是单单BIOS模式的内核文件,还无法引导Grub2,还需要个启动文件Boot.img,该文件很小,只有512Byte,位于i386-pc文件夹,该文件的作用是启动Grub2,然后加载内核文件Core.img
所以这里的最后壹步就是把启动文件Boot.img和内核文件Core.img以二进制形式合并,合并后的文件我个人称呼为扇区文件G2ldr(不知道这个文件有没标准的名称),因为可以直接导入到扇区,来引导启动Grub2,也可以由GRUB4DOS直接加载这个扇区文件来启动Grub2。
老样子,先给出命令(如果命令行的路径不是Grub2包所在的路径,就先要修改命令行的路径,前面有提到)
Copy /B i386-pc\Boot.img+Core.img G2ldr
用bootice 导入扇区
恢复扇区数改成63不能大于63的
之所以会超过是定制问题, 那么这个不会
学习uefi和bios所使用的启动器仿真
http://bbs.wuyou.net/forum.php?mod=viewthread&tid=335197
具体教程来自 http://bbs.wuyou.net/forum.php?mod=viewthread&tid=339411&extra=page%3D1
: qq5274202
我的cmd批处理定制
那么bios加载方式如何启动呢。
出现这个错误,说明文件系统是不支持引导此分区,可以一个一个测试
输入 ls
出现了(hd0) (hd0,msdos2) (hd0,msdos1)
(hd1)
出现了msdos的都可以引导bios,
尝试输入了ls (hd0,msdos2)显示的是存储盘的内容,
尝试输入(hd0,msdos1)显示的是uefi分区内容.
而输入 其他的都显示未知的系统,也验证了bios只识别mbr分区表.
于是我把grub移动到了uefi分区 也就是(hd0,msdos1) 然后输入如下内容
后依次输入如下内容:
成功加载菜单.
5. 如何编译第一个uefi程序
1,按EDK推荐,相应的子模块放到相应的文件夹中,所以新建文件夹hello,里面放入hello.c和hello.inf,结构如下:
“C:\MyWorkSpace\MdeMolePkg\Application\hello\hello.c”
“C:\MyWorkSpace\MdeMolePkg\Application\hello\hello.inf”
2,记事本打开”C:\MyWorkSpace\Nt32Pkg\Nt32Pkg.dsc”,在 [Components] 下,加入一句:
MdeMolePkg/Application/hello/hello.inf
//相当于Visual_studio在sln中加入一个proj.
3,hello.c的代码如下:
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
EFI_STATUS
EFIAPI
UefiMain
(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
SystemTable->ConOut->OutputStri