这一节UEFI原理与编程的书籍里面貌似没有提到,不过在我上次使用飞腾源代码增加功能的过程中发现logo界面的左上角有个光标,后来发现源代码也有,这就让有强迫症的人非常不爽啦,这个光标怎么来的呢,我找了几个地方,都不对,后来懒得找了,既然在logo出现前就有这个光标了,那我直接在logo显示前清屏不就ok了么,然后把这个问题顺利解决。

输入输出在UEFI中使用非常广泛,随便举个栗子,大家经常使用的Print打印输出在屏幕上:

UINTN
InternalPrint (
  IN  CONST CHAR16                     *Format,
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *Console,
  IN  VA_LIST                          Marker
  )
{
  EFI_STATUS  Status;
  UINTN       Return;
  CHAR16      *Buffer;
  UINTN       BufferSize;

  ASSERT (Format != NULL);
  ASSERT (((UINTN) Format & BIT0) == 0);
  ASSERT (Console != NULL);

  BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);

  Buffer = (CHAR16 *) AllocatePool(BufferSize);
  ASSERT (Buffer != NULL);

  Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker);

  if (Console != NULL && Return > 0) {
    //
    // To be extra safe make sure Console has been initialized
    //
    Status = Console->OutputString (Console, Buffer);
    if (EFI_ERROR (Status)) {
      Return = 0;
    }
  }

  FreePool (Buffer);

  return Return;
}


UINTN
EFIAPI
Print (
  IN CONST CHAR16  *Format,
  ...
  )
{
  VA_LIST Marker;
  UINTN   Return;

  VA_START (Marker, Format);

  Return = InternalPrint (Format, gST->ConOut, Marker);

  VA_END (Marker);

  return Return;
}

使用的就是EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL中的OutputString,那么我们来看下这个EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL里面都有什么:

struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
  EFI_TEXT_RESET                Reset;

  EFI_TEXT_STRING               OutputString;
  EFI_TEXT_TEST_STRING          TestString;

  EFI_TEXT_QUERY_MODE           QueryMode;
  EFI_TEXT_SET_MODE             SetMode;
  EFI_TEXT_SET_ATTRIBUTE        SetAttribute;

  EFI_TEXT_CLEAR_SCREEN         ClearScreen;
  EFI_TEXT_SET_CURSOR_POSITION  SetCursorPosition;
  EFI_TEXT_ENABLE_CURSOR        EnableCursor;

  ///
  /// Pointer to SIMPLE_TEXT_OUTPUT_MODE data.
  ///
  EFI_SIMPLE_TEXT_OUTPUT_MODE   *Mode;
};

既然输入输出,有OUTPUT,那么肯定有INPUT:

struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
  EFI_INPUT_RESET     Reset;
  EFI_INPUT_READ_KEY  ReadKeyStroke;
  ///
  /// Event to use with WaitForEvent() to wait for a key to be available
  ///
  EFI_EVENT           WaitForKey;
};

具体使用:

Reset:重新输出

gST->ConOut->Reset (gST->ConOut, FALSE);//有清屏作用?

OutputString:输出到显示屏幕

gST->ConOut->OutputString (gST->ConOut, L"XXXXXXXXX \n");

QueryMode:查询输出模式,和图像查询类似,但没那么多功能 ,Rows为行, Columns为列,所以这个查询很明显,就是查询当前输出位置在哪。 

 UINTN                                GetCol,GetRow;

  gST->ConOut->QueryMode (
                  gST->ConOut,
                  gST->ConOut->Mode->Mode,
                  &GetCol,
                  &GetRow
                  );

 SetMode:设置输出模式

UINTN   LoopVar;
Status = gST->ConOut->SetMode(gST->ConOut, LoopVar);

看下dsc文件,这就是模式的区别,有可能是1、2、3,看具体那种模式,一般固定好不用设置

gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|80
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25


gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|40
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|56

SetAttribute:设置属性,什么属性?那就是输出文字的背景是什么,黑色、红色、还是其他,但是只能是纯色,还有文字颜色,蓝色、白色、黑色、高亮、低亮啥的:

gST->ConOut->SetAttribute( gST->ConOut, EFI_BACKGROUND_BLACK | EFI_LIGHTGRAY );

ClearScreen:清屏,看名字就能看出来:

gST->ConOut->ClearScreen( gST->ConOut );

EnableCursor:设置光标,也就是屏幕上会来个光标,当然前提得为TRUE

gST->ConOut->EnableCursor( gST->ConOut, TRUE );

SetCursorPosition:设置光标位置:

gST->ConOut->SetCursorPosition (gST->ConOut, Col, Row);

ok,上述输出的功能就已经写完了,输入的就不写了,部分没实践,特别是这个reset,是不是清屏有待验证

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐