UEFI开发探索70- YIE001PCIe开发板(06 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

前两篇中,我们了解了UEFI驱动模型的基本架构。 在此基础上,本篇将以一个有趣的UEFI驱动GopRotate,配合自己编写的测试用UEFI应用TestGopRotate,演示UEFI驱动的运行和测试过程。

1 UEFI驱动GopRotate

此示例由apop2提供,源码仓库为https://github.com/apop2/GopRotate。工程GopRotate包含5个源文件:ComponentName.c、GopRotate.c、GopRotate.h、GopRotateBlt.c和GopRotate.inf。这几个文件的作用分别如下:

1) ComponentName.c。实现了EFI_COMPONENT_NAME_PROTOCOL的接口函数,提供UEFI驱动的名称;
2)GopRotate.c。实现EFI_DRIVER_BINDING_PROTOCOL及其接口函数,安装EFI_DRIVER_BINDING_PROTOCOL和EFI_COMPONENT_NAME_PROTOCOL,以及实现UEFI Shell界面旋转功能的Protocol;
3) GopRotate.h。定义了驱动所需数据结构以及Protocol接口函数原型;
4) GopRotateBlt.c。实现UEFI Shell界面旋转的函数,以及提供此功能的Protocol接口函数的实现;
5) GopRotate.inf,编译UEFI驱动的INF文件。

为实现UEFI Shell界面的旋转,示例工程GopRotate主要做了以下工作:

  • 找到安装了EFI_GRAPHICS_OUTPUT_PROTOCOL的控制器,并且不能是虚拟设备;
  • 对EFI_GRAPHICS_OUTPUT_PROTOCOL的Blt()接口函数进行替换,更换为GopRotate中实现旋转显示的函数BltRotate();
  • Shell界面旋转多少度,由内部私有结构体的成员变量Rotation决定。实现控制此变量的GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL,此Protocol提供了两个接口函数,用来获取Rotation值和设置Rotation的值。

示例工程GopRotate的私有结构体如示例1所示。

继续阅读“UEFI开发探索70- YIE001PCIe开发板(06 UEFI驱动)”

1,616 total views, no views today

UEFI开发探索69- YIE001PCIe开发板(05 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

上一篇中,驱动BlankDrv完成了核心的EFI_DRIVER_BINDING_PROTOCOL,以及获取驱动名Protocol的处理后,整个UEFI驱动框架还有两项工作等待完成:

  • 安装UEFI驱动所提供的Protocol;
  • 驱动加载后是常驻内存的,应该提供UEFI驱动的卸载函数,以支持将驱动系统中移除的功能。

1 完成驱动框架

安装Protocol可以使用InstallMultipleProtocolInterfaces()函数,由于BlankDrv中有三种Protocol需要安装,所以使用了库函数EfiLibInstallDriverBindingComponentName2()来安装所有的Protocol。如示例1所示。

【示例1】安装BlankDrv所提供的Protocol

EFI_STATUS EFIAPI UefiMain(
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_STATUS          Status;
  …..
//安装需要提供的三种Protocol
  Status = EfiLibInstallDriverBindingComponentName2 (
             ImageHandle,
             SystemTable,
             &gBlankDrvDriverBinding, 
             ImageHandle,
             &gBlankDrvComponentName,
             &gBlankDrvComponentName2
             );
  return Status;
}

驱动的卸载函数,在使用UEFI Shell命令unload的时候会被调用。此函数的入口在UEFI工程的INF文件中添加,由[Defines] Section的UNLOAD_IMAGE字段给出。在示例工程BlankDrv的BlankDrv.inf中,按照如下方式进行了定义:

[Defines]
  ……
ENTRY_POINT                    = UefiMain         //驱动的入口函数
UNLOAD_IMAGE                   = DefaultUnload   //驱动的卸载函数

继续阅读“UEFI开发探索69- YIE001PCIe开发板(05 UEFI驱动)”

2,237 total views, 1 views today

UEFI开发探索68- YIE001PCIe开发板(04 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

插个新告知:YIE001的开发板,思路已经比较清晰了-使用PCIE芯片,编写Option ROM,在此基础上控制硬件,做一些有趣的实验。由于主要是用业余时间,估计在这两个月内就能把要做的实验完成。

因此,有了新的想法-做一个USB的开发板YIE002,实现从UEFI访问、Windows/Linux访问的全通道USB HID设备。当然,可以用它来收集温度、产生随机数等。准备做成U盘大小,方便直接插在电脑上进行实验。我正在收集网友的想法,有啥想实现的,留言就行,资源允许,我就在板子上实现了。

回到UEFI驱动的介绍。

UEFI开发探索66和67,介绍了服务型驱动的构建和实现。下面几篇,用来介绍符合UEFI驱动模型的驱动程序。本篇主要介绍其框架结构和程序接口,内容有点枯燥,最好对照着源码进行阅读。

一个完整的符合UEFI驱动模型的驱动程序,大致可以分为两个部分:EFI Driver Binding Protocol和驱动本身提供的服务。前者用来管理驱动,后者才是用户需要使用的部分,一般包括一个或多个Protocol。

比如UEFI的USB主控制器驱动,它提供了两个Protocol供用户使用,包括EFI_USB_HC_PROOCOL和EFI_USB2_HC_PROTOCOL,用来访问USB设备。另外,为了方便用户使用,驱动程序一般还会包含EFI Component Name Protocol,用来显示驱动信息。

在网页https://sourceforge.net/projects/edk2/files/EDK%20II%20Releases/Demo%20apps/上,可以下载Intel早期提供的驱动框架示例BlankDrv,用来学习UEFI驱动模型。

1 EFI Driver Binding Protocol

示例工程BlankDrv包含四个文件:

  1. BlankDrv.c。实现EFI_DRIVER_BINDING_PROTOCOL及其接口函数,并安装EFI_DRIVER_BINDING_PROTOCOL和EFI_COMPONENT_NAME_PROTOCOL。
  2. BlankDrv.h。定义了驱动所需数据结构以及Protocol接口函数原型;
  3.  ComponentName.c。实现了EFI_COMPONENT_NAME_PROTOCOL的接口函数;
  4. BlankDrv.inf,编译UEFI驱动的INF文件。
继续阅读“UEFI开发探索68- YIE001PCIe开发板(04 UEFI驱动)”

1,450 total views, 1 views today

UEFI开发探索67- YIE001PCIe开发板(03 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

上一篇做好了服务型UEFI驱动的示例工程,本篇准备编写测试用的UEFI应用,演示如何使用驱动提供的Protocol。另外,对于如何加载驱动进行测试,也会详细讲述。

1 编写测试驱动的UEFI应用

完成了服务型驱动和相应示例Protocol的构建后,我们准备编写访问示例Protocol的UEFI应用。本节准备的示例工程TestServiceDrv,在文末提供了下载地址。

编写测试示例Protocol的代码,步骤如下:

  • 将示例工程ServiceDrv的头文件MyProtocol.h拷贝到示例工程TestServiceDrv的文件夹下。同时修改TestServiceDrv.inf文件,在[Sources] Section下添加此头文件名;
  • 在TestServiceDrv的主程序所在源文件TestServiceDrv.c中添加GUID的声明和定义;
  • 在主程序中添加测试用的代码。

在我们准备的服务型驱动例子中,准备了三个接口函数。其中,接口函数My_SampleIn()和

MySample_DoSth()对私有数据进行了不同赋值,接口函数My_SampleOut()则将私有数据打印了出来。我们可以据此编写测试用的代码,如示例1所示。

【示例1】测试示例Protocol

EFI_STATUS EFIAPI UefiMain (IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE  *SystemTable)
{
  EFI_STATUS      Status;
  EFI_MYSAMPLE_PROTOCOL *myprotocol;
  Status=gBS->LocateProtocol(&gEfiMYSampleProtocolGUID,//示例Protocol GUID
NULL, (VOID **)&myprotocol);
  if(EFI_ERROR(Status))
  {
    Print(L”LocatProtocol error: %r\n”, Status);
    return Status;
  }
  //测试示例Protocol的接口函数
  myprotocol->MySample_In(myprotocol,L”Hello,My protocol!”);
  myprotocol->MySample_Out(myprotocol);
  myprotocol->MySample_DoSth(myprotocol,L”Enjoy UEFI!”);
  myprotocol->MySample_Out(myprotocol);
  return EFI_SUCCESS;
}

示例应用TestServiceDrv是配合之前构建的服务型驱动ServiceDrv工作的,如果ServiceDrv没有加载,则提示找不到Protocol;如果ServiceDrv加载后,则会如示例1所示,依次调用示例Protocol的接口函数。

继续阅读“UEFI开发探索67- YIE001PCIe开发板(03 UEFI驱动)”

1,413 total views, no views today

UEFI开发探索66- YIE001PCIe开发板(02 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在之前的篇章中,或多或少地介绍了一些UEFI驱动的内容。我们要在YIE001上实现的PCIE Option ROM,实际上就是一种UEFI驱动。这点与Legacy BIOS的Option ROM完全不同,在系列博客的第34篇中,可以知道Legacy Option ROM完全是并行于BIOS的。

当然,这样描述Legacy Option ROM也不准确,Legacy BIOS与Legacy Option ROM只是遵循一个调用标准,双方并不干涉。而UEFI Option ROM则是完全遵循UEFI驱动模型的,甚至可以用它安装Protocol,供其他程序使用。

在实际进行编程前,必须理清UEFI驱动的结构和编写方法。预计将用3篇左右的篇幅,把这些内容介绍清楚,以方便对YIE001代码的调试和测试。

1 UEFI驱动分类

从类型上来看,UEFI驱动可以分为启动服务驱动(Boot Service Drivers)和运行时驱动(Runtime Drivers)。两者的区别在于,在UEFI BIOS的RT阶段OS Loader获得平台控制权后,运行时驱动仍然有效。

从功能上划分,UEFI驱动可以分为以下类别。

1) 符合UEFI驱动模型(UEFI Driver Model)的驱动。这类驱动包括总线驱动(Bus Drivers)、设备驱动(Device Drivers)和混合驱动(Hybrid Drivers),一般用来驱动对应的硬件设备;

2) 服务型驱动(Service Drivers)。这类驱动不管理任何设备,一般用来产生Protocol;

3) 初始化驱动(Initializing Drivers)。它不会产生任何句柄,也不增加任何Protocol到系统数据库,主要用来进行一些初始化操作,执行完就会从系统内存中卸载;

4) 根桥型驱动(Root Bridge Drivers)。它用来初始化平台上的根桥控制器,并产生一个设备地址Protocol,以及访问总线设备的Protocol,一般由总线驱动用来访问设备。在7.1节中,我们使用的支持访问PCI/PCIe设备的EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL,就是一个典型的例子。

符合UEFI驱动模型的驱动和服务型驱动,在实际项目中运用较多,其他两种则使用较少。本篇主要介绍下服务型驱动。

2 服务型驱动的功能

在前面的探索中,大量使用了Protocol构建各种应用。也在某些篇章了解了Protocol的基本运作方式,特别是42、43中,构建了完整的服务型驱动和测试程序。

本篇介绍的服务型驱动,和之前的并没有太大区别。主要是为了将来阅读方便,以YIE001的名义,将服务型驱动和UEFI驱动的其他内容整理在一起了。闲言少叙,下面进入正篇。

UEFI中,Protocol可算是最重要的概念了。对它的理解和使用,贯穿了整个UEFI探索系列博客。Protocol由各类驱动提供,在这其中,服务型驱动不需遵循UEFI驱动模型,也不需要管理任何硬件设备。其主要的目的就是用来产生一个或多个Protocol,安装到相应的服务句柄上。

Protocol由一个128位的全局唯一ID(GUID)和Protocol接口的结构体组成,结构体中包含了Protocol的接口函数,可以用来访问对应的设备。在UEFI的系统中,其句柄数据库维护了设备句柄、Protocol接口和镜像句柄、控制器句柄之间的关系。对于Protocol接口的增加、移除或者替代,都可以在句柄数据库中跟踪到,如图1所示。

图1 句柄数据库
继续阅读“UEFI开发探索66- YIE001PCIe开发板(02 UEFI驱动)”

1,465 total views, no views today

UEFI开发探索65- YIE001PCIe开发板(01开篇)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

有段时间没有更新博客了,最近大部分时间都用在公司项目上、以及整理书稿了。在整理书稿的过程中,到了讲述PCIe协议这章的时候,总觉得只是介绍协议和UEFI代码,未免有点太枯燥了。

因此,我把之前写好的章节全部推翻,介绍PCI协议的内容,改为做一个PCIE的开发板,并动手实现板卡的UEFI Option ROM。

也就是说,我按照想象开发了带Flash ROM的PCIE开发板,把UEFI Oprom代码灌入,设备插在计算机上,就可以显示编写好的界面,并能控制开发板上器件,实现一些有趣的功能。

开发板我取名为YIE001,来源于我们博客网站的缩写。目前的计划如下:

  1. 实现基本的Oprom代码;
  2. 实现界面和键盘控制功能;
  3. 实现跑马灯程序;
  4. 实现开发板的按键控制功能;
  5. 实现开发板上的屏幕显示功能;
  6. 移植基础的GUI到开发板上;
  7. 读取插在主机上U盘的内容;
  8. 做个贪吃蛇的游戏。
  9. More……

其中第5个,是指开发板上的I2C接口的OLED屏幕,而不是主机的屏幕。目前不确定这个功能是否能实现,我所用的PCIE芯片Ch366,它的I2C时序很奇怪,我还没有调试,不知道结果如何。当然,时间原因,以上的计划很有可能改变,我尽量按照这些目标开展计划。

另一个计划是关于UEFI与USB的,我准备稍微拓展一下,把如何用单片机实现HID通讯,Windows下如何访问HID设备、UEFI下如何访问HID设备,作为一个大专题,全面讲一下。时间足够的话,Linux系统下访问HID设备的方法也试着实现一下。这就把USB HID从上到下,我觉得应该掌握的知识,全部都探索了一遍。

本篇博客,主要介绍下刚打样回来的YIE001的硬件结构。

开发板YIE001主要就是为开发UEFI Option ROM而制作的,其目的为了演示Option ROM代码如何调用Protocol、如何控制硬件。它是一块PCIe的板卡,提供了拨动开关控制、LED灯的控制以及I2C的接口,其产品结构示如图1所示。

图1 YIE001开发板结构
继续阅读“UEFI开发探索65- YIE001PCIe开发板(01开篇)”

1,786 total views, no views today

UEFI开发探索64- VS2015调试UEFI代码(续27、53篇)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在27篇、53篇中,已经很详细地描述了如何建立调试环境。最近有些朋友问我,总是无法在VS2015下编译通过,所得到的信息也很奇怪,没法进行调试。

鉴于此,我觉得有必要再深入些,谈谈如何使用VS2015来调试UEFI代码。

我一般是遵循如下的原则来建立UEFI的VS调试环境的:

  1. 保证直接使用edksetup.bat和build工具,代码可以编译通过。VS有它自己的一套检测机制,并不适合UEFI工程。编译不通过时,它会提示找不到各种头文件,这些信息对我们毫无作用。简而言之,VS的调试工具,主要是为了找到代码无法如期运行的原因,不是为了寻找编译错误的;
  2. 调试IA32的程序,使用Nt32Pkg或者EmulatorPkg都行;调试X64程序,只能使用UDK2018之后的EmulatorPkg(具体哪个版本开始支持的不记得了,直接用2020版的branch吧)。除了必须硬件支持的程序,比如鼠标、PCIE卡等,我都是在模拟环境下调试的;
  3. 需要调试的工程,最好添加到模拟器所在Package的DSC文件中。这个步骤在53篇中描述过,操作的时候经常容易忘掉,我就是如此;
  4. 调试的时候,如果发现某些语句无法加载断点,或者直接就跳过去了;有些变量无法显示等。不要怀疑自己代码有问题,这一般是程序优化导致的结果。在编译选项中,将优化的开关关掉就可以了。

1 使用示例调试工程

本篇的博客中,提供了IA32和X64的调试工程模板,见篇末的指引。

X64dbg_vs是调试X64代码的,使用EmulatorPkg进行搭建。它使用模拟器WinHost运行程序,图1是使用我的EDK2环境搭建的(最新的EDK2):

图1 X64调试设置
继续阅读“UEFI开发探索64- VS2015调试UEFI代码(续27、53篇)”

2,333 total views, no views today

UEFI开发探索63 – C与C++、汇编的调用约定

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在编写代码的时候,如果发现函数不如自己预期的运作,我的第一个反应并不是添加调试代码,或者使用调试工具。我反而更习惯于去读函数的汇编代码,查看逻辑上是否有漏洞,这都是以前开发oprom/bios汇编代码时留下的习惯。

这个习惯我认为很好,有助于让我专注在代码本身。不过,由此带来了一些问题,C与汇编的函数约定,参数入栈顺序、堆栈平衡等,很难记忆。我实际上更习惯于16位时代的汇编语言,现在32/64位的接口约定,总是需要思考一会才能想起来。

最近一直在把UEFI的代码转到C++上,又遇到调用约定的问题。正好趁这个机会整理下相关的知识,以备后用。

以下的记录,都是基于VS2015,Windows平台的。少部分内容基于Linux平台,使用Gcc的,会特别说明。

1 C/C++的调用约定

Visual C/C++提供了多个不同的调用约定,以供内部或者外部函数使用。为了加快调用速度,针对64位的调用,编译器又做了额外的规定,微软的网站上有详细介绍:https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019

常用的调用约定,有__cdecl、__stdcall、__fastcall、 __clrcall、__thiscall、__vectorcall ,前三个比较常用,其相关信息如下。

继续阅读“UEFI开发探索63 – C与C++、汇编的调用约定”

2,808 total views, 1 views today

UEFI开发探索62-环境搭建4(总结EDK2各种版本)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

开发UEFI代码的时候,起码有近三分之一的时间,在研究各种编译环境的搭建。从Windows到Linux,x86架构到Arm架构,甚至各种不同版本的EDK2,有时候着实让人无语。

之前的代码都在github上下载,速度慢得出奇,搭建好的环境一般也不想乱动。今年3月份,疫情期间,在家鼓捣着把github上与uefi相关的库,全部都导到了gitee上了。解决了下载速度的问题,总算可以不受限制地搭建开发环境了。

最近刚好遇到一个奇怪的问题,我怀疑与最新的EDK2不成熟有关,搭建了几个稳定版本进行实验,证实了自己的猜想。

现在搭建一个环境,大概只需要十几分钟。考虑到其他技术同好也可能遇到我这种需求,本篇博客就完整地探讨下如何安装各种EDK2的版本。

如图1,EDK2实际上准备了很多的分支和tags,可以根据自己的需求去下载。需要注意的是,我是把github上的EDK2和edk2-libc导入到了gitee上,作为私有仓库使用的。需要进行下面的各项操作,请首先完成这个步骤,具体可以参考我的这篇:https://blog.csdn.net/luobing4365/article/details/105658274

图1 edk2的各种分支

总体来说,搭建环境大致可以分为以下几个步骤:

1) 安装必要的开发工具,包括VS2015(或者其他VS编译器)、python、asl和nasm;
2) 使用git下载edk2和edk2-libc(使用C标准库开发时必需);
3) 更新edk2中的submodules;
4) 重新编译BaseTools;

这些步骤完成后,就可以编写各类UEFI应用和驱动了。下面详细介绍操作过程。

继续阅读“UEFI开发探索62-环境搭建4(总结EDK2各种版本)”

6,693 total views, 9 views today

UEFI开发探索61-VFR文件和其他资源文件2(NVRAM上存储数据)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

NVRAM全称为Non-Volatile Ram(非易失性内存) ,Legacy BIOS下这块是使用CMOS来实现的,UEFI下则可以直接在ROM中分出一部分来实现。(问题来了,在UEFI下CMOS到底怎么用的呢? 有机会再研究一下)

UEFI下,对NVRAM的使用如图1所示。

图 1 配置参数存储于NVRAM

在上一篇博客代码的基础上,进行部分修改,将用户的选择存储于NVRAM,修改步骤如下。

继续阅读“UEFI开发探索61-VFR文件和其他资源文件2(NVRAM上存储数据)”

4,241 total views, 4 views today

UEFI开发探索60-VFR文件和其他资源文件1(在BIOS setup上增加项)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

如何使用VFR文件,是我这一段时间比较感兴趣的课题。包括VFR文件在内,UNI文件、IDF文件,都属于资源文件。UNI文件的使用,在之前Hii的例子中,已经讨论过了。而如何使用VFR文件,一直没有涉及到。

接下来的几篇博客,将以修改BIOS Setup(当然,还是以OvmfPkg编译的镜像来做BIOS文件)为例,演示如何使用VFR文件和相关的资源文件。

图1 OVMF镜像的BIOS界面

本篇的例子以Intel提供的示例驱动MyWizardDriver为基础,添加了字符串和窗体,修改步骤如下。

继续阅读“UEFI开发探索60-VFR文件和其他资源文件1(在BIOS setup上增加项)”

6,432 total views, 9 views today

UEFI开发探索59-UDK Debugger Tool调试Firmware

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

这篇博客使用的是Windbg+UDK Debugger Tool调试代码,在Windows10下操作,具体搭建方法可以查看以前的博客。

在最近的开发中,因为碰到不少问题,对UEFI的调试方法更为深入了。在第39篇博客中留下的问题(7 小尾巴),也有了解答,后续看什么时候再把解答补上。

虽然在日常开发中,很少直接用到固件,但在学习中,需要跟踪UEFI每个阶段的工作,直接使用OvmfPkg编译后的Firmware,对其进行调试是个不错的方法。

图1为UEFI运行的7个阶段:

图1 UEFI运行过程
继续阅读“UEFI开发探索59-UDK Debugger Tool调试Firmware”

3,231 total views, no views today

UEFI开发探索58-UTF-8编码问题

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

这篇要记录的知识,实际上不限于UEFI编程,在其他编程上也一样会遇到。只是因为最近这段时间,沉迷于国产机器开发的项目,频繁地调试UEFI代码,遇到了这些问题,我觉得应该有普遍性,姑且记录下来。

在日常的编程中,特别是处理字符串以及显示汉字的时候,会被各种编码搞得糊里糊涂。毕竟编码是给计算机程序看的,记忆起来还是比较费事,即使当时搞清楚了,过一段时间不用,好像又会混淆。

1 历史

计算机从美国发展起来,最早是使用1个字节来表示各种字符和控制符。0x020以下的用来做控制,称为为“控制码”;0x20以上直至0x7F,用来表示各种英文字母、标点和各种符号的编码。

这种编码方式,就是我们现在熟知的ANSI的ASCII编码。其后计算机广泛发展,曾经也使用过0x7F~0xFF用来表示新的符号和字模,比如交叉等形状,这些字符集被称为“扩展字符集”。

在中国,我们有上万汉字,几个个常用字,使用1个字节明显无法表示完。我们制定了一个汉字的解决方案:小于0x7F的字符的意义与原来相同,但两个大于0x7F的字符连在一起时,就表示一个汉字,前面的一个字节(高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样就可以组合出大约7000多个简体汉字了。

在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在0x7F号以下的那些就叫“半角”字符了。

这种方案称为GB2312,是对ASCII的扩展。后来发现还是不够用,于是干脆取消了低字节必须大于0x7F的规定了,只要高字节大于0x7F,就是汉字了。这个方案就是GBK,它比GB2312多了2万多个新汉字和符号。再后来增加几千少数民族的字,GBK扩展成了GB18030。

好了,我们汉字这么搞,其他国家也制定自己的文字编码方案。互相之间谁都不懂,也不支持。于是ISO(国际标准化组织)出来搞定这件事,他们准备废了所有地区性编码方案,建立一套新的编码方案,包括地球上所有文化、所有字母和符号的编码,取名为“Universal Multiple-Octet Coded Character Set”,简称 UCS, 就是我们常说的 UNICODE方案。

图1 我的Unicode启蒙书
继续阅读“UEFI开发探索58-UTF-8编码问题”

2,794 total views, 1 views today

UEFI开发探索57-如使用最新的EDK2搭建编译环境

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近浏览github上edk2的发布代码,注意到一个问题,现在发布的方式有点不一样了。之前过一段时间,就会发布一个完整的打包源代码,比如2018年3月发布的UDK2018,我一直都用这个开发的。不过,我没有找到UDK2019,更别说UDK2020了。

为什么我关注这个呢?主要是因为这种打好包的源码,整理得比较好,也比较稳定,并且还提供完整的API文档。另外,如果直接git EDK2的主线,编程时会发现它其实缺一些包是,有的包些还需要在Google的项目中下载。(观察下https://github.com/tianocore/edk2下的.gitmodules就知道了)

既然没有更新的打包源码,就只能用git下载最新的EDK2来编译了。不过,github那感人的下载网速,没有一定的定力,还真扛不住。

之前的博客中,其实已经给了解决的方法了。但是没有详细讲如何搭建最新的EDK2编译环境,正好用这篇博客完整地说一遍。

1 将github上项目导入到gitee仓库上

具体的方法可以参考我之前的博客:

或者

https://blog.csdn.net/luobing4365/article/details/105658274

继续阅读“UEFI开发探索57-如使用最新的EDK2搭建编译环境”

12,636 total views, 10 views today

UEFI开发探索56-使用WSL编译Arm架构的UEFI镜像

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

这篇本想讨论USB的,学习过程中不小心迷上了WSL,又正好想在树莓派上折腾点UEFI的软件,顺理成章地就用WSL搭建了Arm架构的编译环境。

从结论来说,还不错,省得打开虚拟机了,编译速度也很快,有空把X86架构的编译环境也在WSL上搭建起来。

1 搭建WSL

个人比较喜欢用Ubuntu18.04,很多软件都在上面写的。搭建方法就不具体描述了,可以参考我的另外一篇博客:

https://blog.csdn.net/luobing4365/article/details/105752549

2 所需下载的代码

可以从github的仓库上下载以下开源代码,准备用来搭建开发环境。不过,github像乌龟一样的速度,如果不是为了修心养性,还是建议用gitee来下载。至于如何将github的库转到gitee上,同样可以参考我之前写的博客:

或者https://blog.csdn.net/luobing4365/article/details/105658274

1) edk2  仓库tianocore\edk2   仓库地址:https://github.com/tianocore/edk2.git
         这是包含固件开发环境的仓库,编译UEFI固件所需要的库都在其中。
2) edk2-platforms 仓库:tianocore\edk2-platforms
                仓库地址:https://github.com/tianocore/edk2-platforms.git
         各种平台的工作环境和相关的模块
3) ACPICA 仓库acpica\acpica  仓库地址:https://github.com/acpica/acpica.git
          ACPI组件框架(ACPI Component Architecture)工具,提供开源的iASL编译工具。

后面的这个是非必需的,不过建议下载,编程比较方便。
4) edk2-libc 仓库:tianocore\edk2-libc
           仓库地址:https://github.com/tianocore/edk2-libc.git
           UEFI下的StdLib库,可以使用C标准库进行UEFI的编程。

打开WSL(我的环境是Ubuntu18.04),建立工作目录,比如取名为MyWorkspce。并把上述需要的仓库代码git到本地,示例如下:

$ mkdir Myworkspace
$ git clone –recursive https://github.com/tianocore/edk2.git
$ git clone https://github.com/tianocore/edk2-platforms.git
$ git clone https://github.com/acpica/acpica.git

如需要编译使用StdLib库的程序,把edk2-libc库也git下来:

$ git clone https://github.com/tianocore/edk2-libc.git

下载后,我的目录夹如下所示:

图1 EDK2的工作目录
继续阅读“UEFI开发探索56-使用WSL编译Arm架构的UEFI镜像”

2,976 total views, 1 views today

使用gitee下载github项目

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

这段时间在写UEFI的代码,总需要从github上下载东西。众所周知的原因,github下载非常的慢,有时甚至只有8Kb/s。在这个外网速度动辄百兆的时代,这种下载速度也是比较感人了。也试过修改hosts,修改DNS,没什么作用。

最近实在忍受不了了,我用gitee把需要下载的项目,从github上同步过来,终于解决了这个问题。

这里把步骤记录一下。

1 为gitee设置ssh key

申请一个gitee账号,如同github一样,现在提供两种下载方法:

https://gitee.com/luobing4365/edk2.git
git@gitee.com:luobing4365/edk2.git

使用git clone,跟上两者任何一个地址,都可以把项目git到本地。不过,如果需要提交项目时,前者必须要输入用户名和密码;后者可以通过ssh key通过rsa把私钥存在本地,公钥存在远程库的网站上,省去认证的过程。

也就是说,设不设置ssh key都可以。不过,作为一个可以躺着绝对不站着的极懒程序员,我建议还是设置下比较好。

以下的操作,我是在windows 10的WSL(ubuntu 18)中进行的。

1) 设置git的用户名和邮件地址

命令如下,当然,git应该已经安装了才行:

git config –global user.name “luobing”  #注意是双中横线
git config –global user.mail “luobingxxxx@yyy.com”

提醒:git config -? 可以获取支持的命令参数。

使用 git config –list获取当前设置的用户名和邮箱。

继续阅读“使用gitee下载github项目”

23,338 total views, 7 views today