=====================================================================
固件C字营·版权所有·欢迎转载
敬请关注微信公众号:“固件C字营”
敬请关注QQ群:1052307
敬请关注CSDN博客:Cstyle_0x007
=====================================================================
我们通常的显示设备都被我们称作为显卡,不管是独立显卡,集成显卡,或者是核心显卡,这些设备都是用来作为输出设备把pre-OS环境中BIOS需要呈现给用户的信息显示在显示器上。我们今天要讨论的就是关于显示的问题,怎么把文字,图形等等显示在我们的显示器上,这里面最重要的一个就是Graphics Driver,我们平时听到的最多的那个GOP的东西,包在BIOS中的那个EFI的ROM,下面来看下什么是GOP以及Graphics driver stack是怎么样的。
作为一个显示设备它必须要满足一下的一些基本的条件才能被用来作为输出设备,可以看出基本的就是四个方面,显存,内存,EDID,显示模式这四个东西的操作。我们也可以使用GOP和字模库一起来使用GOP driver生产出Simple Text Output Protocol,这样我们就可以从终端输出各种类型和编码的文字了(MdeModulePkg/Universal/Console/GraphicsConsoleDxe)。
1• Block transfer to
fill a region of the
frame buffer
2• Block transfer from
system memory to region of
frame buffer
3• Block transfer from region of
frame buffer to
system memory
4• Block transfer between
two regions of the
frame buffer
5•
Query attached display devices for
EDID information
6•
Set the supported graphics
modes that is intersection of modes that the graphics controller supports and the display device supports
显示设备通常通常都pci设备,并且一个显示设备比如显卡,通常会有一个或者多个显示接口,那么我们就需要为每一个显示接口提供一个child handle来管理这个显示接口。所以Graphics Driver通常都是bus driver或者是Hybrid Drivers。以下是GOP driver的数据结构:
通常来说我们的显示设备都会连接到到显示器上面去,但是各个厂家生产的显示器千差万别,PC行业为了解决这个问题,会在每个显示器上都会附带一块I2C的存储芯片,这个芯片的目的就是来记录我们的显示器的厂商,型号,支持的分辨率等等信息。所以我们的从上的GOPdriver的原型我们可以看到里面并没有涉及到这些信息,那么这些信息是怎么获取的的呢?我们有另外一个protocol来解决这个问题,那就是EDID Discovered Protocol/EDID Override Protocol;所以我们必须为我们没一个由driver创建出来的child handle install GOP driver,device patch protocol,edie相关的protocol,这样我们的显示设备才能真确的把需要显示的信息呈现给我们的用户。当然现在有些笔记本,一体机之类的由于显示屏幕是预先知道的,那么我们就可以把EDID的相关信息记录在我们的system BIOS里面,这样虽然是减小了系统的兼容性能,但是能节省一点成本。
以下是两个常见的显卡的Graphics Driver SW stack结构,左侧的是单显示接口的设备,右侧的是多显示接口的设备,当然这里省略了device patch, EDID相关的描述:
前面说过Graphics Driver是遵循UEFI driver modle的,那么driver binding protocol是不能少的,那我们来看下,怎么实现它:
Graphics Driver_ Driver Binding Protocol:Supported()
这部分和其他的所有的UEFI driver modle的driver一样,我们都是来检测该设备是否能被dirver所控制,只要是任务无非就是两个方面,一个是检查相关的protocol是否有被install到设备handle上,第二部分也就是使用这些protocol来获取设备的DID,VID,class code来检测该设备是否是我们需要控制的设备,这里就不赘述,详情可以参考其他的几篇文章里面提到的其的driver的做法.
Graphics Driver _Driver Binding Protocol:Start()
这部分和设备息息相关,主要有以下介个方面:
1.
Initialize the adapter.
2.
Enable the PCI device.
3.
Allocate resources.
4. Construct
data structures for the driver to use (if required by the device).-建立是有数据结构
5. Enumerate the outputs that are enabled on the device.--扫描所有被enable的可作为显示输出的设备。
6.
Create child handles for each
detected (and enabled) physical output(physical child handles) and install
EFI_DEVICE_PATH_PROTOCOL.为每一个侦测到的被允许的物理设备安装protocol
7.Get EDID information from each
physical output device connected and install
EFI_EDID_DISCOVERED_PROTOCOL on the child handle.获取显示器的edid信息,并安装protocol,
8
. Create child handles for each valid combination of 2 or more video outputs
(
logical child handles) and install
EFI_DEVICE_PATH_PROTOCOL.逻辑设备安装protocol
9. Check
RemainingDevicePath to see if the correct child or children were created or if NULL select a default set. If incorrect children (no defaults) clean up memory and return EFI_UNSUPPORTED. If default or correct children set them active.用来加快post时间,如果 RemainingDevicePath不为空,我们就不需要创建child handle,直接从它指示的路径启动。
10. Call GetEdid() function to check for overrides on each active physical child handle and produce EFI_EDID_ACTIVE_PROTOCOL on each child protocol based on the result.
11. Install
EFI_GRAPHICS_OUTPUT_PROTOCOL on each active child handle (
physical or logical).最重要的部分
12. Install the EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL.用来显示名字
13. In order to suppor
t faster boot times, a
default mode set and
clear screenoperation must not be performed in the Start() function. This allows the UEFI Boot Manager to select the best mode for the current boot scenario and set the mode one time.
Graphics Driver _Driver Binding Protocol:Stop()
做和start相反的事情:
1.
Uninstall all protocols on all child handles and
close all the child handles.
2.
Uninstall all protocols that were attached on the
host controller handle.
3.
Close all protocol instances that were opened in the Start() function.
4.
Release all resources that were allocated for this driver.
5.
Disable the adapter.
EFI_GRAPHICS_OUTPUT_PROTOCOL的实现:
EFI_GRAPHICS_OUTPUT_PROTOCOL:QueryMode()
获取连接到显示接口上的显示器的所支持的显示模式,如:分辨率,颜色等等,这些不会影响到硬件,也不会影响到当前的显示;
EFI_GRAPHICS_OUTPUT_PROTOCOL:SetMode()
设置当前的显示模式,并且会清屏,为黑色。
EFI_GRAPHICS_OUTPUT_PROTOCOL:Blt()
这个是最重要的显示部分,它实现了如何把要显示的信息传输到显示缓冲器中,也就完成了最终的显示,这个和硬件相关,主要可能要用的pci的memery map IO,IO或者是DMA的方式,总之及时要把BltBuffer的内容传输到显示缓冲区就可以了。为了提高显示的效率和显示的速度,我们建议把显示缓冲器的内容保存一份到内存中来,这样我们操作起来会比较快,尤其是在做屏幕的切换,滑动的时候。
下面是一个经典的内存中的显示缓存的排列布局,这不仅仅是在GOP driver里面能用到,在我们能接触到的几乎所有的更显示有关的设备里面都能看到它的身影,比如单片机,LCD显示等等:
Graphics Driver _Driver Binding Protocol:Mode
指示当前的工作的模式,在BS退出之前我们这些都是有效的,可以提供给OS loader使用,每次使用SetMode()服务的时候,我们需要更新这个字段。
EDID相关的protocol:
EFI_EDID_DISCOVERED_PROTOCOL:它不包含任何的实际操作,仅仅是提供了EDID的信息给显示设备的device handle。
EFI_EDID_ACTIVE_PROTOCOL:它同样不提供任何的实际操作,仅仅是提供了EDID格式的数据信息,它的数据是来自于edid descovery或者是edid override。
EFI_EDID_OVERRIDE_PROTOCOL:由平台driver去实现,被install到一个单独的handle上,当Graphics driver创建EDID active protocol的时候需要用到它;
EFI_EDID_OVERRIDE_PROTOCOL:GetEdid():获取EDID信息(EdidOverride.c);
The GetEdid() function returns the
handle, attributes (override always, never, only if nothing is returned), and the
n
ew EDID information. This is then used by UEFI Drivers
for graphics controller to produce the EDID Active Protocol.
OK,done,today。
转载请注明出处Cstyle.z.zhou@gmail.com//http://blog.csdn.net/CStyle_0x007
=====================================================================
固件C字营·版权所有·欢迎转载
敬请关注微信公众号:“固件C字营”
敬请关注QQ群:1052307
敬请关注CSDN博客:Cstyle_0x007
=====================================================================
@微信公众号《固件C字营》不定期更新状态,关注&订阅公众号不迷路。
完整PDF版整理中,可以在CSDN下载频道搜索”UEFI内核导读“下载样张......