设置文字颜色和背景色

通过调用SetAttribute()函数我们可以设置文字的颜色和背景色(图2.1)。

本节示例代码的目录为text-color (日文版为010_simple_text_output_set_attribute)。1

//*******************************************************
// Attributes
//*******************************************************
#define EFI_BLACK         0x00
#define EFI_BLUE          0x01
#define EFI_GREEN         0x02
#define EFI_CYAN          0x03
#define EFI_RED           0x04
#define EFI_MAGENTA       0x05
#define EFI_BROWN         0x06
#define EFI_LIGHTGRAY     0x07
#define EFI_BRIGHT        0x08
#define EFI_DARKGRAY      0x08
#define EFI_LIGHTBLUE     0x09
#define EFI_LIGHTGREEN    0x0A
#define EFI_LIGHTCYAN     0x0B
#define EFI_LIGHTRED      0x0C
#define EFI_LIGHTMAGENTA  0x0D
#define EFI_YELLOW        0x0E
#define EFI_WHITE         0x0F

#define EFI_BACKGROUND_BLACK      0x00
#define EFI_BACKGROUND_BLUE       0x10
#define EFI_BACKGROUND_GREEN      0x20
#define EFI_BACKGROUND_CYAN       0x30
#define EFI_BACKGROUND_RED        0x40
#define EFI_BACKGROUND_MAGENTA    0x50
#define EFI_BACKGROUND_BROWN      0x60
#define EFI_BACKGROUND_LIGHTGRAY  0x70

struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
    ...
    unsigned long long (*SetAttribute)(
        struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
        unsigned long long Attribute
            /* 要设置的文字颜色和背景色,可设置的颜色如上面的宏定义所示 */
        );
    ...
};

图2.1: SetAttribute()相关的定义(位于efi.h中)

第二个参数Attribute是1个字节的文字颜色和背景色的值,其中高4位为背景色,低4位为文字颜色。

使用SetAttribute()函数来输出本书封面的代码如图2.2所示.

#include "efi.h"
#include "common.h"

void efi_main(void *ImageHandle __attribute__ ((unused)),
          struct EFI_SYSTEM_TABLE *SystemTable)
{
    efi_init(SystemTable);

    puts(L" ");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGREEN | EFI_BACKGROUND_LIGHTGRAY);
    ST->ConOut->ClearScreen(ST->ConOut);
    puts(L"Light Green Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"Light Red Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTBLUE | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"Light Blue Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTMAGENTA | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"Light Magenta Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_WHITE | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"White Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTCYAN | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"Light Cyan Text\r\n");

    ST->ConOut->SetAttribute(ST->ConOut, EFI_MAGENTA | EFI_BACKGROUND_LIGHTGRAY);
    puts(L"Magenta Text\r\n");

    while (TRUE);
}

图2.2: 使用SetAttribute()的例子

上面的代码在调用efi_init()后先输出了一个空格,这是为了适配部分计算机的UEFI固件。某些UEFI固件,例如作者的联想笔记本的固件,在启动后不输出任何内容的情况下直接调用ClearScreen()进行清屏似乎会被忽略。即使这里我们先调用SetAttribute()设置背景色,再调用ClearScreen()清屏,屏幕的背景色也不会被设为我们指定的颜色。2

图2.2程序显示的彩色字符

图2.3: 图2.2程序显示的彩色字符

1

译者注:日文版中这一节的例子是输出本书的封面,考虑到大部分计算机的UEFI固件和OVMF都不支持显示日语字符,这里将其修改成了其它内容。

2

不能理解为什么固件实现上要在没有任何内容被输出到屏幕时忽略对ClearScreen()的调用。这里要实现的效果是在调用SetAttribute()之后改变整个画面的背景色。