首页 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
资讯 业界资讯 软件杂谈 编程开发 网站建设 网络观查 搜索引擎 移动应用 网站运营 网络地图
开发 移动开发 Web前端 架构设计 编程语言 互联网 数据库 系统运维 云计算 开发杂谈
[架构设计] uefi bios代码中如果找到函数的实现?
uefi bios代码中如果找到函数的实现?

写在最前,摘自 K&R
The only legal operations on a structure are copying it or assigning to it as a unit, taking its address with & (读作
ampersand),  and accessing its members,
翻译成中文是这样的,对于一个结构体而言,唯一合法的操作是把它当成一个整体去给它赋值,或者拷贝到另一个地方。
取它的地址,访问它的成员。
UEFI 定义了很多个I (interface). 说穿了,就是函数指针,或者函数原型,它定义了这个interface
需要有哪些功能,需要有哪些参数。至于这个函数的具体实现,各IBV就怎么搞都可以了。比如
EFI_PCI_IO_PROTOCOL.Pollmem()     摘自  UEFI SPEC Chapter 13.
Reads from the memory space of a PCI Root Bridge.
从pci root bridge 中去读(一段数据)
函数原型
typedef
EFI_STATUS
(EFI *API_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM) (
 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL	    *This,
 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
 IN UINT64				     Address,
 IN UINT64 				     Mask,
 IN UINT64                                   Value,
 IN UINT64				     Delay,
 OUT UINT64                                  *Result
);

参数
This    一个指向EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL的指针


Width    标识出对内存操作的宽度


Address  内存操作的基地址,调用这个函数的函数有义务去给它赋一个明确的值

Mask     用来去检测polling(轮询)的标准,即是否达到了结束轮询的标准

Value    用来和退出标准去比较的一个值

Dealy    以100纳秒为单位去延时。

Result    一个指针,指向操作后最后读的那个值。pointer to the last value read from the 
          memory location.


这个函数提供了一个标准的方法去轮询 pci 内存位置,当然里面的Address指定之前,就会对他做一次内存读操作,
读多大,则取决于参数 width, 这个操作会重复进行直到timeout,(以100纳秒为单位) 或者  Resut & Mask = Value.
....
说了这么一大堆,可是我们应该怎么去实现这个函数呢?
首先,它是对pci 内存的操作,所以,BIOS 代码中,肯定会大量用到,我们以它为关键字,用source insight 搜一下。
返回两个结果:
typedef
EFI_STATUS
(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)(
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
  IN  UINT64                                   Address,
  IN  UINT64                                   Mask,
  IN  UINT64                                   Value,
  IN  UINT64                                   Delay,
  OUT UINT64                                   *Result
  );

struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL {
  ///
  /// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member.
  ///
  EFI_HANDLE                                      ParentHandle;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM     PollMem;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM     PollIo;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Mem;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Io;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Pci;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM        CopyMem;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP             Map;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP           Unmap;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER     FreeBuffer;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH           Flush;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES  GetAttributes;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES  SetAttributes;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION   Configuration;
  
  ///
  /// The segment number that this PCI root bridge resides.
  ///
  UINT32                                          SegmentNumber;
}

第一个是它的定义,第二个是把它作为一个类型(指针类型)声明了一个变量。
既然是一个类型,那与int , float , double ,本质上,也就是一样的,标识出不同的长度而已。
这时候,回到文章最开始,对于结构体的操作,只可能把它作为一个整体去赋值。
那么我们以这个结构体的名字为关键字去搜一把
typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL;
它把这种类型,重命名为了 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL。 以后_EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL 就是 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
那就以EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL 再搜一把,这时候,出来一大片,因为到处都要用下,这也正是UEFI的精华所在


可以看到,绝大多数情况都是声明了一个指向这个结构体类型的指针(方便使用嘛)
但是!!  顺着找,可以有这么一段:
static EFI_PCI_IO_PROTOCOL gPciIoInstance = {
    PciIoPollMem,
    PciIoPollIo, 
    {
        PciIoMemRead,  
        PciIoMemWrite
    },
    {
        PciIoIoRead,   
        PciIoIoWrite
    },
    {
        PciIoConfigRead, 
        PciIoConfigWrite
    },
    PciIoCopyMem,
    PciIoMap,
    PciIoUnmap,
    PciIoAllocateBuffer,
    PciIoFreeBuffer,
    PciIoFlush,
    PciIoGetLocation,
    PciIoAttributes,
    PciIoGetBarAttributes,
    PciIoSetBarAttributes,
    0,                      //RomSize;
    NULL                    //RomImage
};

有没有很兴奋,里面,摆的都是实打实的函数名,用你的source insight 直接Jump To Definition 吧
// Procedure:	PciIoMemRead()
//
// Description: Protocol Function Performs a PCI Memory Read Cycle
//
// Notes: See EFI Specification for detail description
//
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS PciIoMemRead(IN EFI_PCI_IO_PROTOCOL        *This,
						IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
						IN UINT8                      BarIndex,
						IN UINT64                     Offset,
						IN UINTN                      Count,
						IN OUT VOID                   *Buffer)
{
	EFI_STATUS     Status;
	PCI_DEV_INFO	*dev=(PCI_DEV_INFO*)This;
//---------------------------------------------

	if (Width < 0 || Width >= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;

	Status=PciIoCheckBar(dev, BarIndex, tBarMem, Width, Count, &Offset);
	if(EFI_ERROR(Status)) return EFI_UNSUPPORTED;

	Status=dev->RbIo->Mem.Read(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
							   Offset, Count, Buffer);
	
	return Status;

至此,文章结束,耐心的去追code吧。。。。

上一篇:浅谈三层
下一篇:Netty代码分析

 此文从网络中自动搜索生成,不代表本网站赞成被搜索网站的内容或立场    查看原文
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 新闻资讯 小游戏 Chinese Culture 股票 三丰软件 开发 中国文化 网文精选 阅读网 看图 日历 万年历 2018年10日历
2018-10-22 0:15:02
 
  网站联系 软件世界网-www.sjsjw.com ©2014 蜀ICP备06016416号 三峰网旗下网站