UEFI Console Splitter 2nd

为了巩固对 Console Splitter 这只driver 认知上的巩固,这么篇文章我们会写一个虚拟的简单的输入设备。具体的思路是以下几点:

  • 经过上篇文章对Splitter 这只driver 的分析,我们知道,如果想让Splitter 能够管理一个device,那么这个device至少应该安装了gEfiConsoleInDeviceGuid && gEfiSimpleTextInProtocolGuid 所以我们应该让我们这个device被安装上这两个GUID。
  • gEfiSimpleTextInProtocolGuid 是每个driver 独立实现自己的protocol 所以这个GUID我们可以自己手动给安装。但是gEfiConsoleInDeviceGuid 是另外一只driver (ConPlatform.c )给自己能support的device handle上安装的GUID ,那么ConPlatromr.c 这只driver support 哪些device呢 。我们上篇也做过简单地介绍就ConPlatform 这只driver 它能够管理的device 是这些device handle 上安装了 gEfiSimpleTextInProtocolGuid, gDevicePathProtocolGuid, 并且该device的path 记录ConIn在这个变量里(热插拔设备除外)。
  • 因为在应用程序里,我们用ReadKeyStorke 和 WaitForKey,所以我们要给这个虚拟device 实例化一个SimpleTextInProtocol 。为了让程序尽量简单,我们只是不停的汇报一个字母‘A’。

经过上述分析,我们知道我们这个device 上要手动安装一个SimpleTextInProtocol 和 EfiDevicePathProtocol (这个path 必须在ConIn 里,或者是一个热插拔的device path)然后我们EDK 里的ConPlatform.c 这只driver 就会给这个虚拟的device 安装一个gEfiConsoleInDeviceGuid 最后,这个device就会满足我们Con Splitter.c 这只driver support函数的要求,我们虚拟device 就会动起来。可能说起来会有点啰嗦,看个流程图就一目了然了。
(待画,第一次用CSDN 不太会画流程图)

看code

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Protocol/SimpleTextIn.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Protocol/DevicePath.h>
#include <Library/DevicePathLib.h>
#include "NonDriver.h"

VHidDev   *gVirHidDev;
EFI_KEY   Buffer[10];
UINT8     Keyflag;

VOID
EFIAPI
CallBack (
    IN  EFI_EVENT  Event,
    IN  VOID       *Context
    )
{
  gBS->SignalEvent (Event);
}

STATIC vPath_T gvHidDevPath = {
  {
    {
      MESSAGING_DEVICE_PATH,
      MSG_USB_WWID_DP,
      {
        (UINT8) (sizeof (USB_WWID_DEVICE_PATH)),
        (UINT8) (sizeof (USB_WWID_DEVICE_PATH) >> 8)
      }
    },
    0x01,
    0xaa,
    0xbb
  },
  {
    END_DEVICE_PATH_TYPE,
    END_ENTIRE_DEVICE_PATH_SUBTYPE,
    {
      (UINT8) (END_DEVICE_PATH_LENGTH),   
      (UINT8) (END_DEVICE_PATH_LENGTH >> 8)   
    }
  }

};

EFI_STATUS
EFIAPI
vReadKeyStroke (
  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL    *This,
  OUT EFI_INPUT_KEY                     *Key
  )
{
  Key->UnicodeChar = L'A';
  return EFI_SUCCESS;    
}

EFI_STATUS
EFIAPI
TestNonDriver (
    IN EFI_HANDLE          ImageHandle,
    IN EFI_SYSTEM_TABLE    *SystemTable
    )
{

  EFI_STATUS       Status;

  DEBUG((EFI_D_INFO, " NonDriver Test Start\n"));

  Status = gBS->AllocatePool (
                 EfiBootServicesData,
                 sizeof (VHidDev),
                 (void **)&gVirHidDev
                 );
  if (EFI_ERROR (Status)) {
    DEBUG((EFI_D_INFO, "allocate pool %r\n", Status));
    return EFI_OUT_OF_RESOURCES;
  }


  gVirHidDev->vConIn.Reset = NULL;
  gVirHidDev->vConIn.ReadKeyStroke = vReadKeyStroke;
  gVirHidDev->Handle = NULL;

  Status = gBS->CreateEvent (
                   EVT_NOTIFY_WAIT,
                   TPL_NOTIFY,
                   CallBack,
                   NULL,
                   &gVirHidDev->vConIn.WaitForKey
                   );
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "Create Event %r\n", Status));
    return Status;
  }

  Status = gBS->InstallMultipleProtocolInterfaces(
                  &gVirHidDev->Handle,
                  &gEfiDevicePathProtocolGuid,
                  &gvHidDevPath,
                  &gEfiSimpleTextInProtocolGuid,
                  &gVirHidDev->vConIn,
                  NULL
                  );

  return EFI_SUCCESS;
}

其实有了上述分析,我们看code就会很容易,简单地分析一下。首先我们先给我们的虚拟device分配一个地址空间,我们会实例化一个SimpleTextInProtocol在ReadKeyStroke函数里只是简单地向Splitter driver 汇报字母A。然后我们会创建一个Event,上篇我们提到过,如果我们想读用户输入,我们会把程序阻塞住,直到这个Event被Signal起来。所以我们在虚拟device里把这个Event的Callback只是简单地实现一个Signal Event,好让用户程序结束阻塞,继续运行。最后我们会给这个device安装一个device path protocol 好让蒙过ConPlatform.c 这只driver检查那一关,为了简单,我们把这个device模拟成一个USB WWID 那么就不会对这个device path 和 ConIn 记录里的path 进行比对。 主函数大概就是这样,如果想下载code,下面是链接地址

程序下载地址

最后我们可以把这个虚拟device 加入EDK source code 里,我这边是用Linux 下的模拟器,所以把.inf 档放进Emulator.dsc 和 Emulator.fdf 里,然后开虚拟我们就会看到屏幕上一直出现字符A。

这里写图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值