这一节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,是不是清屏有待验证