参考从零开始的UEFI裸机编程 (kagurazakakotori.github.io)https://kagurazakakotori.github.io/ubmp-cn/print.html

下载EDK2

不习惯它的开发方式,改!

头文件Uefi.h,搜索,在MdePkg/Include/Uefi.h。

UEFI文档Welcome to Unified Extensible Firmware Interface Forum | Unified Extensible Firmware Interface Forumhttps://uefi.org

开始按照教程

环境ubuntu,交叉编译工具链使用教程方式,做一个OS LOADER的EFI

1. HELLO UEFI

1.1 编译efi

struct EFI_SYSTEM_TABLE {char _buf[60];struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {unsigned long long _buf;unsigned long long (*OutputString)(struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,unsigned short *String);unsigned long long _buf2[4];unsigned long long (*ClearScreen)(struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This);} *ConOut;
};void efi_main(void *ImageHandle __attribute__ ((unused)),struct EFI_SYSTEM_TABLE *SystemTable)
{SystemTable->ConOut->ClearScreen(SystemTable->ConOut);SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello UEFI!\n");while (1);
}

BIOS的EFI初始化好了,放在了struct EFI_SYSTEM_TABLE *SystemTable中,再运行自己的EFI,然后调用其中的接口。

main.c

#include <uefi.h>

/*
4.1 UEFI Image Entry Point
*/
EFI_STATUS floader_main(IN EFI_HANDLE handle, IN EFI_SYSTEM_TABLE *table)
{
    table->conout->clear_screen(table->conout);
    table->conout->output_string(table->conout, L"Hello UEFI by floader\n");
    while(1) { ; }
}

Makefile

TOPDIR = $(shell pwd)

CC = x86_64-w64-mingw32-gcc

CFLAGS = -Wall -Wextra -nostdinc -fno-builtin
CFLAGS += -I$(TOPDIR)/include
CFLAGS += -D__BUILD_X64__

TARG = floader
OBJS = main.o

LDFLAGS = -e $(TARG)_main -nostdlib -Wl,--subsystem,10

# x86_64: PE32+
all: $(TARG).efi
        @echo "move $(TARG).efi to udisk/EFI/BOOT/BOOTX64.efi"

TOOLCHAIN:
        sudo apt install gcc-mingw-w64-x86-64

$(TARG).efi: $(OBJS)
        $(CC) $^ $(LDFLAGS) -o $@
        #$(CC) -Wall -Wextra -e efi_main -nostdinc -nostdlib -fno-builtin -Wl,--subsystem,10 -o main.efi main.c

$(OBJS): %.o: %.c
        $(CC) $(CFLAGS) -c $^ -o $@

clean:
        rm -f *.o

distclean: clean
        rm -f $(TARG)*

sudo apt install gcc-mingw-w64-x86-64 安装交叉编译工具链

make (即教程的x86_64-w64-mingw32-gcc -Wall -Wextra -e efi_main -nostdinc -nostdlib \ -fno-builtin -Wl,--subsystem,10 -o main.efi main.c)编译出.efi

1.2 运行efi

(1)准备U盘,格式化为FAT32文件系统

(2)(若要U盘启动,需要创建文件夹EFI\BOOT,然后放置其下,并重命名为BOOTX64.EFI)

这里使用BIOS UEFI SHELL运行,将.efi放置根目录

(3)vmware创建一个虚拟机(最好创建时选择win10,固件类型会自动选择为uefi。其他类型,创建好后uefi选项是灰色的,不能更改)

(4)选择“打开电源时进入固件”

(5)将U盘连接进虚拟机

(6)选择“EFI Internal Shell (Unsupported option)”

(7)进入shell,看到fs0,U盘fat32文件系统可用,输入“fs0:”,“ls” (这不错,linux shell风格,但显示确实windows风格),“xxx.efi”(可使用tab补全)

回车运行

2. 回显

main.c

#include <uefi.h>

/*
4.1 UEFI Image Entry Point
*/
EFI_STATUS floader_main(IN EFI_HANDLE handle, IN EFI_SYSTEM_TABLE *table)
{
    EFI_INPUT_KEY key;
    char16 str[3];
    
    table->conout->clear_screen(table->conout);
    table->conout->output_string(table->conout, L"Hello UEFI by floader\r\n");

table->conout->output_string(table->conout, L"floader> ");
    while(1) { 
        if(!table->conin->read_key_stroke(table->conin, &key)) {
            if(key.unicode_char != L'\r') {
                str[0] = key.unicode_char;
                str[1] = L'\0';
                table->conout->output_string(table->conout, str);
            } else {
                table->conout->output_string(table->conout, L"\r\nfloader> ");
            }
        }
    }
}

运行

添加等待

EFI_STATUS floader_main(IN EFI_HANDLE handle, IN EFI_SYSTEM_TABLE *table)
{
    EFI_INPUT_KEY key;
    char16 str[3];
    size_t idx;
    
    table->conout->clear_screen(table->conout);
    table->conout->output_string(table->conout, L"Hello UEFI by floader\r\n");

table->conout->output_string(table->conout, L"floader> ");
    while(1) {
        table->boot_services->wait_for_event(1, &(table->conin->wait_for_key), &idx);
        table->conin->read_key_stroke(table->conin, &key);
        if(key.unicode_char != L'\r') {
            str[0] = key.unicode_char;
            str[1] = L'\0';
            table->conout->output_string(table->conout, str);
        } else {
            table->conout->output_string(table->conout, L"\r\nfloader> ");
        }
    }
}

3. shell

main.c

#include <uefi.h>EFI_SYSTEM_TABLE *g_table;void efi_init(IN EFI_SYSTEM_TABLE *table)
{g_table = table;
}void clear_screen(void)
{if(NULL == g_table) {return;}g_table->conout->clear_screen(g_table->conout);
}void putc(char16 c)
{char16 str[2] = L" ";if(NULL == g_table) {return;}str[0] = c;g_table->conout->output_string(g_table->conout, str);
}void puts(char16 *s)
{if(NULL == g_table) {return;}g_table->conout->output_string(g_table->conout, s);
}char16 getc(void)
{EFI_INPUT_KEY key;size_t idx;if(NULL == g_table) {return CHAR_NULL;}g_table->boot_services->wait_for_event(1, &(g_table->conin->wait_for_key), &idx);while(g_table->conin->read_key_stroke(g_table->conin, &key)) { ;}return key.unicode_char;
}size_t gets(char16 *buf, size_t size)
{size_t i;if(NULL == g_table) {return 0;}for(i=0; i<size-1; ) {buf[i] = getc();putc(buf[i]);if(L'\b' == buf[i]) {i--;continue;}if(L'\r' == buf[i]) {putc(L'\n');break;}i++;}buf[i] = CHAR_NULL;return i;
}#define LINE_MAX_LEN   100/*
4.1 UEFI Image Entry Point
*/
EFI_STATUS floader_main(IN __UNUSED EFI_HANDLE handle, IN EFI_SYSTEM_TABLE *table)
{char16 line[LINE_MAX_LEN];efi_init(table);clear_screen();puts(L"****************\r\n");puts(L"* UEFI FLoader *\r\n");puts(L"****************\r\n");puts(L"\r\n");while(TRUE) {puts(L"floader> ");if(gets(line, LINE_MAX_LEN) <= 0) {continue;}}
}

4. print

有了putc,就可以写print了,把自己之前写的print拿来,稍微修改下就可以用了

(代码 字符串是VS风格,前面还得加个'L',char16 和 char,在小端字节序中,ascii字符是一致的,所以format还是用const char *format)

main.c

#include "common.h"static size_t gets(char16 *buf, size_t size)
{size_t i;for(i=0; i<size-1; ) {buf[i] = getc();putc(buf[i]);if(L'\b' == buf[i]) {i--;continue;}if(L'\r' == buf[i]) {putc(L'\n');break;}i++;}buf[i] = CHAR_NULL;return i;
}#define LINE_MAX_LEN   100/*
4.1 UEFI Image Entry Point
*/
EFI_STATUS floader_main(IN __UNUSED EFI_HANDLE handle, IN EFI_SYSTEM_TABLE *table)
{char16 line[LINE_MAX_LEN];efi_init(table);clear_screen();puts(L"************************************\r\n");print("* UEFI FLoader (BUILD %s) *\r\n", __DATE__);puts(L"************************************\r\n");puts(L"Vendor: ");if(NULL != table->fw_vendor) {puts(table->fw_vendor);}print(" FW Ver: 0x%08X\n", table->fw_revision);puts(L"\r\n");while(TRUE) {puts(L"floader> ");if(gets(line, LINE_MAX_LEN) <= 0) {continue;}}
}

真机测试

格式化U盘 FAT32,建立efi/boot目录,复制.efi,并重命名为bootx64.efi (名字都小写是可以的)

由于.efi没有做签名等操作,所以首先(一般是按F2)进入BIOS,需要把secure boot 安全启动关闭, 然后(一般是F12)启动选择项选择U盘启动

UEFI(使用EDK2)编程相关推荐

  1. UEFI原理与编程(一)

    第一章 UEFI概述(Unified Extensible Firmware Interface 统一的可扩展固件接口) 常见缩写及描述: 缩略词 全名 描述 UEFI Unified Extensi ...

  2. UEFI原理与编程实践--EFI System Table中的输入输出

    这一节UEFI原理与编程的书籍里面貌似没有提到,不过在我上次使用飞腾源代码增加功能的过程中发现logo界面的左上角有个光标,后来发现源代码也有,这就让有强迫症的人非常不爽啦,这个光标怎么来的呢,我找了 ...

  3. UEFI原理与编程(四)(dec dsc inf文件)

    1 .inf文件 以下面 .inf文件为例 [Defines] # 块用于定义模块的属性和其他变量,块内定义的变量可被其他块引用INF_VERSION = 0x00010006 #INF 标准的版本号 ...

  4. UEFI原理与编程第二章学习- .dsc .dec .fdf文件与包

    .dsc .dec .fdf文件及包    上一篇介绍了 .inf文件, .inf文件相当于Visual Studio中的工程文件.而 .dsc(Platform Description File)则 ...

  5. UEFI原理与编程实践--UEFI系统的启动过程

    看图粗略说一下: SEC: 安全验证阶段,这个阶段,需要用Assembly做一些 C 无法处理的工作,C语言无法处理CPU的特殊寄存器.让CPU进入Protected Mode(Flat Mode)的 ...

  6. UEFI原理与编程实践--UEFI工程模块文件

    标准应用程序工程模块 该模块是其他应用程序工程模块的基础,也是UEFI中常见的一种应用程序工程模块,标准应用程序工程模块,UefiMain就是这个模块的入口函数 EFI_STATUS EFIAPI U ...

  7. UEFI原理与编程实践--Device Path

    系统中的每个设备都有一个唯一的路径.例如,每次进入shell时,都会打印出系统中的硬盘设备以及设备路径.针对硬盘和文件系统,将在BIOS学习实战中通过获取U盘路径,读取BIOS文件,然后进行更新的具体 ...

  8. UEFI原理与编程实践--PCD的使用

    PCD说白了就是个全局变量,就看你怎么去调用了,先看一下它的定义用法: 然后再看一下通过编译后有AutoGen生成的一个定义: PCD的类型有很多种,但是经常使用的也就是静态PCD与动态PCD 静态P ...

  9. UEFI原理与编程实践--UEFI驱动模型之显卡(UEFI方向)驱动分析

    拆开一台国产电脑,会发现,很多重要芯片,其实已经国产化了,CPU.GPU.电源管理芯片等等,刚做了一下GOP的笔记,回头想想,之前包入厂商的显卡驱动一直没怎么关注他们的运行逻辑是什么,那么,这篇文章就 ...

最新文章

  1. R语言使用ggplot2包使用geom_density()函数绘制分组密度图(添加直方图、分组颜色配置)实战(density plot)
  2. idea 升级到2020后 无法启动_【维修案例】2020年一汽奥迪Q5L发动机无法启动
  3. Hadoop安装与配置问题说明
  4. mysql查询语句习题._MySql数据库基本select查询语句练习题,初学者易懂。
  5. 11种必知的word embeddings模型
  6. Gym 101194D Ice Cream Tower
  7. websocke 在线测试地址
  8. 深度学习的实用层面 —— 1.1 训练/开发/测试集
  9. python0x80070643_Win10提示Python 0x80070643安装时发生严重错误
  10. nsga2代码解读python_python自动化办公系列 | python操作pdf—— PyPDF2 和 pdfplumber模块(1)...
  11. Unity实现发射子弹的功能
  12. Python办公自动化(四) | 批量处理文件
  13. 关于if __name__ == '__main__'的理解
  14. 安装 卸载 mysql linux,Linux 下MySQL 安装与卸载
  15. php 图片印章_PHP实现中文圆形印章的特效
  16. Ubuntu 截图工具 Flameshot
  17. MetaQ 简单使用(数据同步框架)
  18. 算法导论第二章部分习题自我解答
  19. android中如何保存对象集合中,如何序列化对象并将其保存到Android中的文件?
  20. MyBatis从入门到精通(十):使用association标签实现嵌套查询

热门文章

  1. 使用 Visual Studio 2005中的ASP.NET 移动控件创建电子书浏览器应用程序
  2. 基于Springboot+mybatis+mysql+html实现CRM智能办公系统
  3. 使用js+css样式实现淘宝详情页图片放大镜的效果
  4. php guzzlehttp,使用Guzzle执行HTTP请求
  5. 对抖音App评论进行抓取
  6. 第三章 灰度变换与空间滤波
  7. 用Python手把手教你做一只口红色号识别器,秒变李佳琦
  8. python实现向qq邮箱发送邮件
  9. Cubic(Custom Ubuntu ISO Creator)创建自定义镜像
  10. 安卓APP自动更新功能实现