一、EDK2简介

1.EDK2工作流

二、EDK2 Packages

1.Packages介绍

EDK2 Packages是一个容器,其中包含一组模块模块的相关定义。每个Package是一个EDK2单元。

整个Project的源代码可以被分割成不同的Pkg。这样的设计不仅可以降低耦合性,还有利于分发和复用。

1.1.EDK2 Packages

​ 每个Package中包含一个DEC文件,该文件用来组织Package中的一系列Module。EDK2提供了一些兼容UEFI和PI的包(如MdePkg、MdeModulePkg等)。

MdeModulePkg包中有一组符合UEFI和PI规范的跨平台驱动程序。在开发新的UEFI和PI驱动时可以用来参考。

1.2.DEC文件

DEC文件用来定义每个Package中的公共接口公共头文件GUIDPCDs

  • DEC文件主要包括以下部分:

(1)[Defines]

​ 定义PKG的名字PKG的GUID

(2)[Includes]

​ 列出公共头文件所处目录的根目录

(3)[LibraryClasses]

​ 列出在Include\Library下的每个Library Class头文件

(4)[Guids]

​ 给Include\Guid下的Guid赋值

(5)[Ppis]

​ 给Include\Ppi下的Ppi赋Guid值

(6)[Protocols]

​ 给Include\Protocol下的Protocol赋Guid值

(7)PCDs

​ 相关类型的PCD声明:FeatureFlag, FixedAtBuild, PatchableInModule, Dynamic, and DynamicEx。Dynamic类型的PCD在第四章:附录章节还有补充说明。

  • 若一个PCD支持多种类型,则需要在全部类型中全部声明
  • DEC文件写法示例:

1.3.DSC文件

​ 编译时使用到的文件,所有模块均可加入来进行Package编译验证

DSC文件主要包括以下部分:

(1)[Defines]

​ 设置Build的相关信息,如build输出目录build目的Guidbuild arch

(2)[LibraryClasses]

​ 对每个LibraryClasses指定选择的Library实例

(3)PCD

​ 用于配置[Components]部分中各模块使用的PCD类型和PCD值。

  • 如果PCD的值与DEC中的默认值相同,且PCD类型没有具体要求,则将使用DEC中的默认值。

(4)[Components]

​ 列出所有将被编译的Module,如Drivers, Application, and Library Instances

  • Path是相对路径,相对于Package根目录

  • DSC文件写法示例:

2.Packages管理

2.1.创建Package

2.1.1.创建要求

(1)将有意义的包名作为包目录名,并创建一个包目录,例如PackageNamePkg

(2)在包根目录下创建包DECDSC文件来描述这个包

(3)创建子目录来包含不同的源文件

3.EDK II Module

​ 一个EDKII Module包含源文件或者二进制文件,和一个Module定义文件(inf文件

3.1.Module组成

​ 对于一个典型的EDK II Module而言,Module是一个固件组件。Module在构建完成后,首先被放入FFS文件,然后放入FV Image。

​ Module可以以源代码EFI二进制格式发布,Module的内容可以是下列几种类型:

(1)Raw data binary

例如:$(WORKSPACE)\MdeModulePkg\Logo\Logo.inf ,这就是包含了一个logo bitmap的image

(2)可选的设备ROM驱动

(3)独立的UEFI驱动或者UEFI应用

(4)一个 .lib 形式的library instance

3.2.Module分类

​ EDK II给Module定义了许多不同的Module类型。定义这些Module类型主要是为了:

(1)区分不同类型模块的生命周期

​ 例如:PEIM在PEI阶段调度,DXE_DRIVER或uefi_driver在DXE阶段

(2)表示不同类型模块的二进制image

(3)为不同类型的模块指定合适的library instance

  • 主要的EDKII Module类型:

3.3.Module创建

Driver ModuleLibrary Module创建步骤相仿:

(1)选择或者创建一个Package,来存放Module

(2)为该Module创建一个目录,并且放入一个inf文件

(3)在inf文件中添加Package dependencies

(4)在inf文件中添加PPI Protocol Guid等相关dependencies

(5)如果模块依赖PPI Protocol Guid,则需要加入项[depex]

(6)创建源文件,并且在inf中填入源文件的相对路径

3.4.增加Module目录

​ Module目录需要按照以下规则添加到合适的Package中:

3.5.INF文件写法

​ INF文件是对于所在Module说明文件,放在根目录中,其中:

(1)Module的基础信息有:名字、GUID、模块类型等

(2)Module所依赖的所有Packages路径根目录相对路径

  • 所有模块都依赖MdePkg,需要将其加入
  • 如果使用来自Intel框架规范的定义,则IntelFrameworkPkg也是必需
  • 如果使用到了其它Package中的内容,则需要添加其它Packeage的dec文件

    (3)源文件或者二进制文件路径

(4)模块用到的系列接口,如Protocol、Ppi、GUID

(5)模块所需的所有pcdLibrary类的列表

(6)其它内容,例如不同类型Module需要的不同的依赖部分

  • App Module的inf文件:

  • Library Module的inf文件

3.6.添加Source文件

1.INF中的 [sources] 模块定义了Source文件的相关内容,相关规则如下:

(1)不同的体系结构Source文件,放在不同的模块下,例如:

(2)使用的不同工具链需要标注,例如:

  • 相关Tool Tag

3.7.添加Library Class References

Library类(Class)将相关的宏定义、结构定义函数声明进行了抽象;而Library实例(instance)将这些内容进行了实现。

​ Library实例(Instance)根据不同Platform,和相同Platform的不同阶段,其具体实现会有所差异。

3.7.1.在模块中使用Library类的步骤:

(1)在INF文件中,给包含Library Class的package添加Dependency

(2)在INF文件中,给Library Class添加dependency

(3)在代码头文件中,包含LibraryClass

  • 头文件的路径是相对路径,相对于package DEC文件[include]中写的路径

  • 实例

#include <Library/OemHookStatusCodeLib.h>


3.8.添加PCD References

​ EDK II引入了PCD来实现宏定义的效果。例如,对于“FeatureFlag”类型的PCD,如果PCD的值为TRUE,则会启用某些特性或功能。

​ EDK II提供了以下类型的PCD:

3.8.1.使用PCD的步骤

(1)在Module的INF文件中,为PcdLib添加Dependency

(2)在Module的INF文件中,给MdePkg添加dependency

  • MdePkg是必需的,因为MdePkg中的“PcdLib”Library Class,提供了PCD访问函数和宏。

(3)在代码头文件中,添加==<Library/PcdLib.h>==

(4)使用PcdLib提供的接口进行PCD Value的操作

  • PCD操作函数:
  • PCD添加与使用实例:

3.9.添加Prorocol、PPI、GUID Reference

​ Protocol、PPI、Guid是UEFI中固件之间通信的接口。

3.9.1.在模块中使用Protocol、PPI、Guid

(1)在INF文件中,对应类别([Protocol]、[Ppi]或[Guid])添加需要的Protocol

(2)相应头文件必须清楚包含在Source code的头中

  • 头文件中都是相对路径,相对于package DEC文件[include]中写的路径

3.10.为Module添加Dependency

​ Module的Dependency限定了关于驱动程序的Entry Point的条件。

​ 通过它,可以确定PEIM和DXE模块的调度顺序。

​ 一个表达式由一个或多个Protocol、PPI或GUID和操作符组成,例如“AND”, “OR”, “TRUE”, “FALSE”, “NOT” 等。
表示gEfiSampleGuid 的值和gEfiSamplePpiGuid的值进行布尔和运算

  • 具体运算法则描述,参考Platform Initialization SpecificationDependency Expressions 章节
    Dependency Expression Grammar章节

3.11.Define Library Class

​ Library Instance总是与Library Class相关,Library Instance实现了Library Class中定义的所有接口。

因此,==Library Class名必须在Library Instance的INF文件的[definitions]==中说明。

  • 如下所示:

UefiDriverEntryPoint 是Library Class的名字,这个名字由Library Instance所来。

DXE_DRIVER和DXE_RUNTIME_DRIVER是这个Library Instance所支持的类型。

3.12 Driver Module的额外步骤

​ PEIM或者DXE Driver需要在INF文件中的==[Defines]中标明函数Entry_Point==。不同的Module类型具有不同的Entry_Point。

  • 示例图:

3.13 常见Library Class

MdePkg中提供了许多Library Class,用来基于UEFI和PI开发固件组件。

3.14 使用HII的Module

​ DXE Module可以在BDS阶段中打印或更新,browser将使用到下列资源:

3.14.1 Forms

(1)VFR Resource File

​ VFR文件用来描述form(即格式)资源。VFR文件的用法和其它Source Code用法相似。

需要将其在Module的INF文件的[Sources]部分中列出。

  • 用法示例:

(2)打印VFR

​ 在Module编译时,vfr文件会由Vfr编译器编译为一个.vfr文件,并且作为全局数组变量插入到Module image的IFR二进制区域中。这个全局数组变量的名字是:Vfr文件名+Bin。

  • 示例如下:

    Inventory.vfr in the MdeModulePkg\Universal\DriverSampleDxe driver

is compiled into the global array variable InventoryBin.

(3)将VFR全局数组变量加入HII数据库

​ 使用以下代码段:

//
// Create HII driver handle, paramter DriverHandle will hold the
// returned new handle.
// HiiLibCreateHiiDriverHandle defined in UefiHiiLib library class.
//
Status = HiiLibCreateHiiDriverHandle(&DriverHandle);
//
// Prepare HII package list, parameter InventoryBin is the VFR form data
// HiiLibPreparePackageList defined in UefiHiiLib library class
//
PackageList = HiiLibPreparePackageList (2,&mInventoryGuid,InventoryBin,DriverSampleStrings);
ASSERT (PackageList != NULL);
//
// Create package into HII database via EFI_HII_PROTOCOL->NewPackageList
//
Status = gHiiDatabase->NewPackageList (gHiiDatabase,PackageList,DriverHandle,&HiiHandle);
3.14.2 Unicode Strings

​ Unicode字符串被放到.uni文件中,并在Module的INF文件的[Sources]部分列出,和C文件一样。

  • 示例如图:

(1)打印Unicode String文件

​ uni文件中的内容会被编译工具解析和编译为一个二进制字符串包数组。这个二进制数组的名字为ModuleName+ “Strings”。

  • 例如:MdeModulePkg\Universal\DriverSampleDxe 中的inventorystring.uni最终的二进制数组名将会是:

    extern UINT8 DriverSampleStrings[];
    

(2)将Strings array variable 添加进 HII Database

//
// Create HII driver handle, paramter DriverHandle will hold the
// returned new handle.
// HiiLibCreateHiiDriverHandle defined in UefiHiiLib library class.
//
Status = HiiLibCreateHiiDriverHandle(&DriverHandle);
//
// Prepare HII package list, parameter DriverSampleStrings is the
// strings binary data.
// HiiLibPreparePackageList defined in UefiHiiLib library class
//
PackageList = HiiLibPreparePackageList (2,&mFormSetGuid,DriverSampleStrings,VfrBin);
if (PackageList == NULL) {return EFI_OUT_OF_RESOURCES;
}
//
// Create package into HII database via EFI_HII_PROTOCOL->NewPackageList
//
Status = HiiDatabase->NewPackageList (HiiDatabase,PackageList,DriverHandle[0],&HiiHandle[0]);

4. Module的编译

​ 当Module Source Code完成以后,Module的INF文件会被加入到Platform的DSC文件里,Module将被编译到预期的二进制Image中。

​ EDK2编译系统支持编译Library ImageEFI ImageOptionRom Image

4.1 将Module INF文件加入到Packeage DSC文件

​ 为了编译一个Module,会在DSC文件的[Components]部分,指定Module的INF文件(路径是Package目录开始的相对路径,到INF文件名字为止)

​ DSC的[Defines]部分会列出所有支持的体系。[Components]部分会详细列出Module的支持体系。

  • 示例:

4.2. 为Module选择Library Instance(library instance不需要此步)

​ 对于Driver和Application来说,每个Library Class必须选中对应的Library Instance,并且链接到二进制EFI Image处。

​ Module INF文件的==[LibraryClasses] 部分列出了所有需要的Library Class==,这些Library Class都是Library Instance所产生的。

​ 对于不同的目的(例如对性能和大小的优化),Library Instance可以有不同的实现方式。

​ 在初始开发中,通常使用没有经过优化的Library Instance来降低开发风险。完成模块的基本功能后,可以进一步调整其大小和性能。

​ 在MdePkg中,为用户选择提供了许多可用的Library Instances,详细信息可以在其INF文件或MdePkg规范中找到。

  • 举例:

    ​ 在MdePkg中,对于LibraryClass:BaseMemory的Library Instance:BaseMemoryLibOptDxe的实现,采用了寄存器操作内存的方式,获得了更好的性能表现。

    ​ 另一个例子是,在MdePkg中,LibraryInstance:PeiIoLibCpuIo通过使用CpuIo PPI的服务来实现IO的LibraryClass,减少了代码大小。

4.3 对于PCD的配置

​ 对于使用到PCD的Module,需要提前在Package DSC文件中配置。配置完成的PCD会被应用到Module和其链接的Library Instance两处。

​ PCD会在Package的DEC文件中声明。当PCD的Value和DEC文件中的默认值一致时,这些PCD则不需要再DSC中再次赋值。

​ 在DSC中,PCD类型和值可以根据Platform要求进行配置。在DSC中,一个PCD的类型只允许是唯一的类型。如果DSC中没有对其进行指定,那么PCD的类型将和DEC中声明的类型保持一致。如果一个PCD支持多种PCD类型,那么其默认PCD类型是固定PCD类型。

4.3.1 PCD的类型

(1)Feature Flag PCD

​ 如果一个PCD被声明为PcdsFeatureFlag ,那么它只能是FeatureFlag PCD type或者BOOLEAN data type。如果Module需要使用本类PCD,则需要在INF的[FeaturePcd]中预先指定。

  • 只有通过FeaturePcdGet接口才可以操作此种类型的PCD

  • 示意:

(2)Fixed PCD

​ 如果一个PCD的Value在整个编译期间都是固定的,那么它的类型应设置为PcdsFixedAtBuild 。

当Module使用此类PCD时,它可以选择归属在==Module INF的[FixedPcd]或者[PCD]==中。

​ 此外,操作本类型的PCD,需要使用FixedPcdGet或者PcdGet接口。

(3)Patchable PCD

​ 如果一个PCD的Value在二进制Image中不固定(会被修改),它的类型应设置为PcdsPatchable 。在Module中使用此类PCD时,它可以分在==[FatchPcd]或者[PCD]==。

(4)Dynamic PCD

​ 如果PCD的Value在运行期间获得,那么它的类型应设置为Dynamic。如果一个Dynamic PCD是从Driver共享的PCD数据库取得Value,那么它的类型应该是PcdsDynamicDefault;如果一个Dynamic PCD和UEFI Variable相关,那么它的类型应该是PcdsDynamicHII。

​ 当在Module中使用Dynamic PCD,那么INF的 [PCD]部分需要注明。

​ 此外,操作Dynamic PCD只有通过PcdGet、PcdSet两个接口。

  • 示例图:

4.4 Build选项修改

​ Build Option为不同的工具链提供了不同的编译选项,来编译出Image。它们在==$(WORKSPACE)/Conf/tools_def.txt file==被定义。在这个文件中,列出了不同工具链常见的编译器选项。

  • 编译器选项(compiler option)主要被分成两大类(详细选项可见EDK II Build Specification ):

​ 编译选项(compile option)

​ 链接选项 (link option)

​ EDKII 编译系统提供了四种层次的override机制来实现Compiler Options的定制。

影响范围从大到小,依次是:Tool_def.txt,DSC(最为推荐,只修改了DSC文件),INF。

​ 这些Options可以通过指定顺序实现互相覆盖。

4.4.1 修改Tool_def.txt

​ 直接对tool_def.txt 进行修改,将会影响workspace里的所有Modulesplatforms

4.4.2 修改INF文件

​ 在Module INF文件的**[BuildOptions]**中,添加额外的编译器选项(compiler option),将会对该Module生效,并且在任何DSC中都可被编译。

  • 不同编译工具可选的编译器选项(compiler option)并不相同

  • Module INF示例:

4.4.3 修改DSC文件

​ 在DSC的 [BuildOptions]部分添加额外的编译器选项(compiler option),同一个DSC中描述的所有Module的编译器选项都会被影响。

  • DSC示例

​ 在DSC的==[Components]部分,为某个Module添加编译器选项(compiler option),则只对该Module==,且只在该DSC生效。

  • DSC [Components]示例

4.5 Build Module Image

​ 在DSC文件的 [Components] 中所添加的描述

4.5.1 Build Package(-p)

​ 如果 [Components] 没有指明build module option,那么package DSC的[Components]所列出来的Module都会被编译。如果build module option有多个,只有最后一个会生效

  • 示例:

4.5.2 Build Module(-m)

​ 如果一个指定Module需要build,则其必须首先在DSC的 [Components] 中列出。如果没有列出,DSC的所有Module都会被build。如果command line指定指令不止一次,只有最后一个会生效。

  • 示例:

4.5.3 Build Arch

​ 支持的ARCH Option有: IA32X64IPFEBC。如果在命令行中指定了不止一次,则每个ARCH会按顺序构建。

  • 示例:

4.5.4 Build Target

​ 支持的Target有:DEBUGRELEASE。如果在命令行上指定多次,则按顺序构建每个Target。

  • 示例:

4.5.5 Build Tool Tag Name

Tool Tag Name定义在Conf\Tools_def.txt文件中,表示编译器工具链。例如,MYTOOLS是Microsoft VS2005工具链的默认Tool Tag Name。

​ 如果在命令行上指定多次,则会按顺序使用每个工具链。

4.5.6 示例:Build Helloworld

​ 在build DEBUG文件夹中会创建以下文件:EFI ImageIntermediate FilesAutoGen.hAutoGen.cModule.map 文件

​ EDK II build工具根据所需的Module信息,为每个Module生成AutoGen.h和AutoGen.c文件。其中包括了依赖的pcdGuid值包含Module Entry Point相关的函数

​ 这些AutoGen函数在ModuleEntryPoint库实例中被引用。对于每个Module, Entry Point函数首先调用AutoGen Code,然后进入Module functions。

​ Module.Map是由compiler tool生成的,用于列出该Module中所有函数及其相对地址。它们可用于在运行时定位Module函数地址。

  • AutoGen.c如图:

  • PcdDxe.map如图:

4.6 Build EFI Option Rom Image

EFI Option Rom是一个标准的EFI image。EFI image可以通过上述build Module命令编译。与普通Module的不同在于: EFI Option Rom Image INF文件的 [Defines] 中会包含相关的PCI Option。当Module INF文件中设置了PCI Option。这个Module会被编译成EFI和Option Rom Images

​ 在build DEUBG文件下,会出现ModuleName.efiModuleName.rom

  • Option Rom INF示例:

4.6.1 常见build Module报错


4.7 Debug Module

​ 在开始Debug Module之前,需要执行以下4个步骤:

  • 指令:“Build –b DEBUG”

​ EDK II支持生成DEBUG/RELEASE目标。target.txt中的"BuildTarget"字段与" ToolChain "字段共同生效,以确定编译器tool-chain和build option的实际路径。开发人员可以直接打开

$(WORKSPACE)\Conf\ TARGET .txt并更改“TARGET = DEBUG”作为调试提示。开发人员也可以使用命令行来覆盖该值,例如在调试提示中使用“build -b DEBUG”。

  • 选择合适的DebugLib Library Instance

​ 对于DebugLib库类,MdePkg和IntelFrameworkModulePkg核心包提供了几个库实例。其中包括BaseDebugLibNullBaseDebugLibSerialPort UefiDebugLibConOut,

UefiDebugLibStdErr, PeiDxeDebugLibReportStatusCode。开发人员可以按实际要求在Package的DSC文件中,选择合适的DebugLib库实例。

  • 配置DebugLib使用的Pcds

​ DebugLib library class header定义了两个用于调试库配置的pcd。与debug ability相关的pcd包括PcdDebugPropertyMaskPcdDebugPrintErrorLevel。前者用于控制print/assert,并确定assert宏是通过CpuDeadLoop还是通过BreakPoint实现的。对于后者,开发人员可以设置各种值来控制打印或过滤错误信息。

  • Change build option

​ 开发人员可以修改或重写module build option。例如,开发人员可以使用Microsoft 编译器的“/Od”选项来禁用编译器的优化,并避免无序指令。还可以使用Microsoft编译器的“/FAsc”选项来生成一个源代码和汇编(.cod)文件来帮助调试。

4.7.1 基本调试方法

​ 以下是三个基本的调试方法:

  • 使用DEBUG打印语句

​ 在EDK II项目中,有一组PCD,用于开启/关闭DEBUG。开发人员可以在开始调试时打开该功能。

  • CpuDeadLoop()

​ 开发人员可以使用API halt control flow,有助于快速定位问题。

  • Module的 Map file

​ EDK II为每个模块生成一个对应的FV Map文件

​ 开发人员可以根据已加载Module的基址Map File来计算函数的内存地址。

EDK II Module Writers Guide上相关推荐

  1. EDK II Module Writers Guide下

    三.常见UEFI Module类型 1.UEFI APP ​ UEFI Application是EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION类型的EFI Image. UEF ...

  2. The Linux Kernel Module Programming Guide 2.4 中文版

    The Linux Kernel Module Programming Guide 2.4 中文版 分类: Linux/os 2007-09-29 11:14 820人阅读 评论(0) 收藏 举报 T ...

  3. UEFI学习---EDK II开发环境的搭建

    EDK II的开发环境搭建(Windows系统) 一.搭建前的准备工作 二.软件安装 1.安装VS2019 社区版 2.安装Python 3.安装Git 4.安装Nasm 5.安装IASL 6.安装Q ...

  4. TianoCore、UEFI、EDK II

    TianoCore是支持统一可扩展固件接口(UEFI)的开源实现的社区. EDK II是现代的,功能丰富的跨平台固件开发环境,适用于UEFI和UEFI平台初始化(PI)规范. EDK2---" ...

  5. EDK II工程文档官方网址

    EDK II Documentation · tianocore/tianocore.github.io Wiki · GitHub 打开此页面后,会有很多类型的工程文件格式可供选择  这里列出几个比 ...

  6. UEFI入门之EDK II开发环境搭建

    EDK II是开源的对UEFI标准的实现,目前主流的IBV(BIOS代码供应商,像AMI.Insyde和Byosoft等)的代码都是基于EDK II做二次开发.本文将介绍在Windows10系统中使用 ...

  7. UEFI学习(一)-EDK II环境搭建

    UEFI_edk2环境搭建 UEFI_edk2环境搭建 环境搭建准备 软件安装 (一) vs2019安装 (二)Python安装 (三)IASL.NASM安装 (四)edk2的选择与安装 环境变量配置 ...

  8. EDK II编译过程

    1 EDKII Build过程简介 EDKII Build主要是用来处理EDKII meta-data文件(包括build_rule.txt,tools_def.txt,target.txt等),ED ...

  9. EDK II之USB主控制器(EHCI)驱动的实现框架

    本文简要介绍一下UEFI中EHCI驱动的代码实现框架: 下图是HCDI: 上图是Host驱动程序向上层驱动提供的接口图: 1.大部分接口的最后动作都是去操作主控制器寄存器,ECHI的spec:< ...

最新文章

  1. 【Tools】Windows下Git 2.18安装步骤
  2. 决策树基本原理与sklearn应用
  3. kite 使用 go_使用Apache Storm和Kite SDK Morphlines的可配置ETL处理
  4. ap6212 Linux 蓝牙,替代正基AP6212、AP6330的SDIO WiFi+UART蓝牙组合
  5. mysql控制台导出查询结果_MySQL 命令行导出、导入Select 查询结果
  6. html 忽略标签属性,限制文本一定数目的字符忽略HTML标签/属性
  7. Linux FastDFS 分布式文件系统安装
  8. Spring整合CXF发布及调用WebService
  9. php 修改文件所有者,PHP 改变文件的所有者
  10. Atitit 提升语法级别4gl 4.5g 4.9g 5g 目录 1. 语言级别表 1 2. 4.9g实现细节 2 2.1. $dollor前导符 2 2.2. Static变量 2 2.3. S
  11. Windows10系统打开程序应用提示『不支持此接口』的解决方案
  12. 2022迅雷ios版下载beta
  13. oracle rman在线备份,Oracle的RMAN备份与恢复脚本
  14. ubuntu20.04 显卡驱动 cuda cudnn安装
  15. 【计算机网络】零拷贝之MMAP
  16. ie 远程控制计算机,通过IE浏览器连接“远程桌面”方法详解
  17. 如何将应用隐藏成一个计算机,局域网中如何隐藏自己的计算机
  18. 【笔记】H5跳转手机应用商店(指定应用页/第三方应用商店)
  19. Discuz3.4-SSRF-从触发点到构造payload
  20. 华硕笔记本扇热声音大

热门文章

  1. OJ《程序设计基础I 》实验5-一维数组
  2. 产品运营之道:用户反馈(一)
  3. 移动终端管理系统的关键技术研究 - 转贴
  4. 移动GM220S光猫超级密码及改桥接模式方法
  5. 字节跳动高工面试:java高级程序员面试宝典蔡羽豆瓣
  6. IE浏览器提示代理服务器没有响应,但是360浏览器可以用
  7. 『TensorFlow』pad图片
  8. python怎么解矩阵方程_基于python解线性矩阵方程(numpy中的matrix类)
  9. SVLsimulator与apollo6.0联合仿真
  10. xposed新版52下载_kyqp游戏合集-kyqp游戏下载推荐