OpenCorePkg/Library/OcConsoleLib/AsciiTextOutput.c
2020-02-05 22:29:41 +03:00

658 lines
20 KiB
C

/** @file
Copyright (C) 2020, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Guid/AppleVariable.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcConsoleLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/GraphicsOutput.h>
/*
* ISO Latin-1 Font
*
* Copyright (c) 2000
* Ka-Ping Yee <ping@lfw.org>
*
* This font may be freely used for any purpose.
*/
#define ISO_CHAR_MIN 0x21
#define ISO_CHAR_MAX 0x7E
#define ISO_CHAR_WIDTH 8
#define ISO_CHAR_HEIGHT 16
STATIC UINT8 mIsoFontData[(ISO_CHAR_MAX - ISO_CHAR_MIN + 1)*(ISO_CHAR_HEIGHT - 2)] = {
/* 33 */ 0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,
/* 34 */ 0x00,0x6c,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 35 */ 0x00,0x00,0x36,0x36,0x7f,0x36,0x36,0x7f,0x36,0x36,0x00,0x00,0x00,0x00,
/* 36 */ 0x08,0x08,0x3e,0x6b,0x0b,0x0b,0x3e,0x68,0x68,0x6b,0x3e,0x08,0x08,0x00,
/* 37 */ 0x00,0x00,0x33,0x13,0x18,0x08,0x0c,0x04,0x06,0x32,0x33,0x00,0x00,0x00,
/* 38 */ 0x00,0x1c,0x36,0x36,0x1c,0x6c,0x3e,0x33,0x33,0x7b,0xce,0x00,0x00,0x00,
/* 39 */ 0x00,0x18,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 40 */ 0x00,0x30,0x18,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x18,0x30,0x00,0x00,
/* 41 */ 0x00,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x18,0x18,0x0c,0x00,0x00,
/* 42 */ 0x00,0x00,0x00,0x00,0x36,0x1c,0x7f,0x1c,0x36,0x00,0x00,0x00,0x00,0x00,
/* 43 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
/* 44 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0c,0x00,0x00,
/* 45 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 46 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
/* 47 */ 0x00,0x60,0x20,0x30,0x10,0x18,0x08,0x0c,0x04,0x06,0x02,0x03,0x00,0x00,
/* 48 */ 0x00,0x3e,0x63,0x63,0x63,0x6b,0x6b,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 49 */ 0x00,0x18,0x1e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,
/* 50 */ 0x00,0x3e,0x63,0x60,0x60,0x30,0x18,0x0c,0x06,0x03,0x7f,0x00,0x00,0x00,
/* 51 */ 0x00,0x3e,0x63,0x60,0x60,0x3c,0x60,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,
/* 52 */ 0x00,0x30,0x38,0x3c,0x36,0x33,0x7f,0x30,0x30,0x30,0x30,0x00,0x00,0x00,
/* 53 */ 0x00,0x7f,0x03,0x03,0x3f,0x60,0x60,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,
/* 54 */ 0x00,0x3c,0x06,0x03,0x03,0x3f,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 55 */ 0x00,0x7f,0x60,0x30,0x30,0x18,0x18,0x18,0x0c,0x0c,0x0c,0x00,0x00,0x00,
/* 56 */ 0x00,0x3e,0x63,0x63,0x63,0x3e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 57 */ 0x00,0x3e,0x63,0x63,0x63,0x7e,0x60,0x60,0x60,0x30,0x1e,0x00,0x00,0x00,
/* 58 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
/* 59 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x0c,0x00,0x00,
/* 60 */ 0x00,0x60,0x30,0x18,0x0c,0x06,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,
/* 61 */ 0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
/* 62 */ 0x00,0x06,0x0c,0x18,0x30,0x60,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,
/* 63 */ 0x00,0x3e,0x63,0x60,0x30,0x30,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,
/* 64 */ 0x00,0x3c,0x66,0x73,0x7b,0x6b,0x6b,0x7b,0x33,0x06,0x3c,0x00,0x00,0x00,
/* 65 */ 0x00,0x3e,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,
/* 66 */ 0x00,0x3f,0x63,0x63,0x63,0x3f,0x63,0x63,0x63,0x63,0x3f,0x00,0x00,0x00,
/* 67 */ 0x00,0x3c,0x66,0x03,0x03,0x03,0x03,0x03,0x03,0x66,0x3c,0x00,0x00,0x00,
/* 68 */ 0x00,0x1f,0x33,0x63,0x63,0x63,0x63,0x63,0x63,0x33,0x1f,0x00,0x00,0x00,
/* 69 */ 0x00,0x7f,0x03,0x03,0x03,0x3f,0x03,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,
/* 70 */ 0x00,0x7f,0x03,0x03,0x03,0x3f,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,
/* 71 */ 0x00,0x3c,0x66,0x03,0x03,0x03,0x73,0x63,0x63,0x66,0x7c,0x00,0x00,0x00,
/* 72 */ 0x00,0x63,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,
/* 73 */ 0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,
/* 74 */ 0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x33,0x1e,0x00,0x00,0x00,
/* 75 */ 0x00,0x63,0x33,0x1b,0x0f,0x07,0x07,0x0f,0x1b,0x33,0x63,0x00,0x00,0x00,
/* 76 */ 0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,
/* 77 */ 0x00,0x63,0x63,0x77,0x7f,0x7f,0x6b,0x6b,0x63,0x63,0x63,0x00,0x00,0x00,
/* 78 */ 0x00,0x63,0x63,0x67,0x6f,0x6f,0x7b,0x7b,0x73,0x63,0x63,0x00,0x00,0x00,
/* 79 */ 0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 80 */ 0x00,0x3f,0x63,0x63,0x63,0x63,0x3f,0x03,0x03,0x03,0x03,0x00,0x00,0x00,
/* 81 */ 0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x63,0x6f,0x7b,0x3e,0x30,0x60,0x00,
/* 82 */ 0x00,0x3f,0x63,0x63,0x63,0x63,0x3f,0x1b,0x33,0x63,0x63,0x00,0x00,0x00,
/* 83 */ 0x00,0x3e,0x63,0x03,0x03,0x0e,0x38,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,
/* 84 */ 0x00,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,
/* 85 */ 0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 86 */ 0x00,0x63,0x63,0x63,0x63,0x63,0x36,0x36,0x1c,0x1c,0x08,0x00,0x00,0x00,
/* 87 */ 0x00,0x63,0x63,0x6b,0x6b,0x6b,0x6b,0x7f,0x36,0x36,0x36,0x00,0x00,0x00,
/* 88 */ 0x00,0x63,0x63,0x36,0x36,0x1c,0x1c,0x36,0x36,0x63,0x63,0x00,0x00,0x00,
/* 89 */ 0x00,0xc3,0xc3,0x66,0x66,0x3c,0x3c,0x18,0x18,0x18,0x18,0x00,0x00,0x00,
/* 90 */ 0x00,0x7f,0x30,0x30,0x18,0x18,0x0c,0x0c,0x06,0x06,0x7f,0x00,0x00,0x00,
/* 91 */ 0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,
/* 92 */ 0x00,0x03,0x02,0x06,0x04,0x0c,0x08,0x18,0x10,0x30,0x20,0x60,0x00,0x00,
/* 93 */ 0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,
/* 94 */ 0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 95 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,
/* 96 */ 0x00,0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 97 */ 0x00,0x00,0x00,0x00,0x3e,0x60,0x7e,0x63,0x63,0x73,0x6e,0x00,0x00,0x00,
/* 98 */ 0x00,0x03,0x03,0x03,0x3b,0x67,0x63,0x63,0x63,0x67,0x3b,0x00,0x00,0x00,
/* 99 */ 0x00,0x00,0x00,0x00,0x3e,0x63,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,
/* 100 */ 0x00,0x60,0x60,0x60,0x6e,0x73,0x63,0x63,0x63,0x73,0x6e,0x00,0x00,0x00,
/* 101 */ 0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x7f,0x03,0x63,0x3e,0x00,0x00,0x00,
/* 102 */ 0x00,0x3c,0x66,0x06,0x1f,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,
/* 103 */ 0x00,0x00,0x00,0x00,0x6e,0x73,0x63,0x63,0x63,0x73,0x6e,0x60,0x63,0x3e,
/* 104 */ 0x00,0x03,0x03,0x03,0x3b,0x67,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,
/* 105 */ 0x00,0x0c,0x0c,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x38,0x00,0x00,0x00,
/* 106 */ 0x00,0x30,0x30,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x33,0x1e,
/* 107 */ 0x00,0x03,0x03,0x03,0x63,0x33,0x1b,0x0f,0x1f,0x33,0x63,0x00,0x00,0x00,
/* 108 */ 0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x38,0x00,0x00,0x00,
/* 109 */ 0x00,0x00,0x00,0x00,0x35,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x00,0x00,0x00,
/* 110 */ 0x00,0x00,0x00,0x00,0x3b,0x67,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,
/* 111 */ 0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,
/* 112 */ 0x00,0x00,0x00,0x00,0x3b,0x67,0x63,0x63,0x63,0x67,0x3b,0x03,0x03,0x03,
/* 113 */ 0x00,0x00,0x00,0x00,0x6e,0x73,0x63,0x63,0x63,0x73,0x6e,0x60,0xe0,0x60,
/* 114 */ 0x00,0x00,0x00,0x00,0x3b,0x67,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,
/* 115 */ 0x00,0x00,0x00,0x00,0x3e,0x63,0x0e,0x38,0x60,0x63,0x3e,0x00,0x00,0x00,
/* 116 */ 0x00,0x00,0x0c,0x0c,0x3e,0x0c,0x0c,0x0c,0x0c,0x0c,0x38,0x00,0x00,0x00,
/* 117 */ 0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x73,0x6e,0x00,0x00,0x00,
/* 118 */ 0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1c,0x1c,0x08,0x00,0x00,0x00,
/* 119 */ 0x00,0x00,0x00,0x00,0x63,0x6b,0x6b,0x6b,0x3e,0x36,0x36,0x00,0x00,0x00,
/* 120 */ 0x00,0x00,0x00,0x00,0x63,0x36,0x1c,0x1c,0x1c,0x36,0x63,0x00,0x00,0x00,
/* 121 */ 0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1c,0x1c,0x0c,0x0c,0x06,0x03,
/* 122 */ 0x00,0x00,0x00,0x00,0x7f,0x60,0x30,0x18,0x0c,0x06,0x7f,0x00,0x00,0x00,
/* 123 */ 0x00,0x70,0x18,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,
/* 124 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,
/* 125 */ 0x00,0x0e,0x18,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,
/* 126 */ 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
STATIC UINT32 mGraphicsEfiColors[16] = {
0x00000000, // BLACK
0x00000098, // LIGHTBLUE
0x00009800, // LIGHTGREEN
0x00009898, // LIGHTCYAN
0x00980000, // LIGHTRED
0x00980098, // MAGENTA
0x00989800, // BROWN
0x00989898, // LIGHTGRAY
0x00303030, // DARKGRAY - BRIGHT BLACK
0x000000ff, // BLUE
0x0000ff00, // LIME
0x0000ffff, // CYAN
0x00ff0000, // RED
0x00ff00ff, // FUCHSIA
0x00ffff00, // YELLOW
0x00ffffff // WHITE
};
STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL *mGraphicsOutput;
STATIC UINTN mConsoleWidth;
STATIC UINTN mConsoleHeight;
STATIC UINTN mConsoleMaxPosX;
STATIC UINTN mConsoleMaxPosY;
STATIC UINTN mCursorPosX;
STATIC UINTN mCursorPosY;
STATIC BOOLEAN mCursorOnscreen;
STATIC UINT8 mFontScale;
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION mBackgroundColor;
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION mForegroundColor;
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *mCharacterBuffer;
#define TGT_CHAR_WIDTH ((UINTN)(ISO_CHAR_WIDTH) * mFontScale)
#define TGT_CHAR_HEIGHT ((UINTN)(ISO_CHAR_HEIGHT) * mFontScale)
#define TGT_CHAR_AREA ((TGT_CHAR_WIDTH) * (TGT_CHAR_HEIGHT))
/**
Render character to TGT_CHAR_AREA buffer.
@param[in] Char Character code.
@param[in] FgColor Character colour.
@param[in] BgColor Background colour.
@param[out] Buffer Character buffer.
**/
STATIC
VOID
RenderChar (
IN CHAR16 Char,
OUT VOID *Buffer
)
{
UINT32 *DstBuffer;
UINT8 *SrcBuffer;
UINT32 Line;
UINT32 Index;
UINT32 Index2;
UINT8 Mask;
DstBuffer = Buffer;
if ((Char >= 0 && Char < ISO_CHAR_MIN) || Char == 0x7F) {
SetMem32 (DstBuffer, TGT_CHAR_AREA * sizeof (DstBuffer[0]), mBackgroundColor.Raw);
return;
}
if (Char < ISO_CHAR_MIN || Char > ISO_CHAR_MAX) {
Char = L'_';
}
SrcBuffer = mIsoFontData + ((Char - ISO_CHAR_MIN) * (ISO_CHAR_HEIGHT - 2));
SetMem32 (DstBuffer, TGT_CHAR_WIDTH * mFontScale * sizeof (DstBuffer[0]), mBackgroundColor.Raw);
DstBuffer += TGT_CHAR_WIDTH * mFontScale;
for (Line = 0; Line < ISO_CHAR_HEIGHT - 2; ++Line) {
//
// Iterate, while the single bit drops to the right.
//
for (Index = 0; Index < mFontScale; ++Index) {
Mask = 1;
do {
for (Index2 = 0; Index2 < mFontScale; ++Index2) {
*DstBuffer = (*SrcBuffer & Mask) ? mForegroundColor.Raw : mBackgroundColor.Raw;
++DstBuffer;
}
Mask <<= 1U;
} while (Mask != 0);
}
++SrcBuffer;
}
SetMem32 (DstBuffer, TGT_CHAR_WIDTH * mFontScale * sizeof (DstBuffer[0]), mBackgroundColor.Raw);
}
STATIC
VOID
RenderCursor (
IN UINTN PosX,
IN UINTN PosY,
IN BOOLEAN Enabled
)
{
//
// Disabled and invisible.
//
if (!Enabled && !mCursorOnscreen) {
return;
}
if (Enabled && mCursorOnscreen && PosX == mCursorPosX && PosY == mCursorPosY) {
return;
}
//
// Hide previous.
//
if (mCursorOnscreen) {
mGraphicsOutput->Blt (
mGraphicsOutput,
&mBackgroundColor.Pixel,
EfiBltVideoFill,
0,
0,
TGT_CHAR_WIDTH + mCursorPosX * TGT_CHAR_WIDTH + mFontScale,
TGT_CHAR_HEIGHT + mCursorPosY * TGT_CHAR_HEIGHT - mFontScale + TGT_CHAR_HEIGHT,
TGT_CHAR_WIDTH - mFontScale * 2,
mFontScale,
0
);
mCursorOnscreen = FALSE;
}
//
// Draw new.
//
if (Enabled) {
mGraphicsOutput->Blt (
mGraphicsOutput,
&mForegroundColor.Pixel,
EfiBltVideoFill,
0,
0,
TGT_CHAR_WIDTH + PosX * TGT_CHAR_WIDTH + mFontScale,
TGT_CHAR_HEIGHT + PosY * TGT_CHAR_HEIGHT - mFontScale + TGT_CHAR_HEIGHT,
TGT_CHAR_WIDTH - mFontScale * 2,
mFontScale,
0
);
mCursorPosX = PosX;
mCursorPosY = PosY;
mCursorOnscreen = TRUE;
}
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextReset (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &mGraphicsOutput
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Info = mGraphicsOutput->Mode->Info;
if (Info->HorizontalResolution < TGT_CHAR_WIDTH * 3
|| Info->VerticalResolution < TGT_CHAR_HEIGHT * 3
|| (Info->PixelFormat != PixelRedGreenBlueReserved8BitPerColor
&& Info->PixelFormat != PixelBlueGreenRedReserved8BitPerColor)) {
return EFI_DEVICE_ERROR;
}
if (mCharacterBuffer != NULL) {
FreePool (mCharacterBuffer);
}
mCharacterBuffer = AllocatePool (TGT_CHAR_AREA * sizeof (mCharacterBuffer[0]));
if (mCharacterBuffer == NULL) {
return EFI_DEVICE_ERROR;
}
mConsoleWidth = (Info->HorizontalResolution / TGT_CHAR_WIDTH) - 2;
mConsoleHeight = (Info->VerticalResolution / TGT_CHAR_HEIGHT) - 2;
This->Mode->CursorColumn = 0;
This->Mode->CursorRow = 0;
mCursorOnscreen = FALSE;
mCursorPosX = 0;
mCursorPosY = 0;
mConsoleMaxPosX = 0;
mConsoleMaxPosY = 0;
mBackgroundColor.Raw = mGraphicsEfiColors[0];
mForegroundColor.Raw = mGraphicsEfiColors[ARRAY_SIZE (mGraphicsEfiColors) - 1];
mGraphicsOutput->Blt (
mGraphicsOutput,
&mBackgroundColor.Pixel,
EfiBltVideoFill,
0,
0,
0,
0,
Info->HorizontalResolution,
Info->VerticalResolution,
0
);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextOutputString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
UINTN Index;
for (Index = 0; String[Index] != '\0'; ++Index) {
if (String[Index] == '\r') {
This->Mode->CursorColumn = 0;
continue;
}
if ((UINTN) This->Mode->CursorColumn >= mConsoleWidth || String[Index] == '\n') {
if ((UINTN) This->Mode->CursorColumn >= mConsoleWidth) {
This->Mode->CursorColumn = 0;
}
++This->Mode->CursorRow;
mConsoleMaxPosY = MAX (mConsoleMaxPosY, (UINTN) This->Mode->CursorRow);
if (String[Index] == '\n') {
continue;
}
}
if ((UINTN) This->Mode->CursorRow >= mConsoleHeight) {
mGraphicsOutput->Blt (
mGraphicsOutput,
NULL,
EfiBltVideoToVideo,
0,
TGT_CHAR_HEIGHT * 2,
0,
TGT_CHAR_HEIGHT,
mGraphicsOutput->Mode->Info->HorizontalResolution,
TGT_CHAR_HEIGHT * (mConsoleHeight - 1),
0
);
mGraphicsOutput->Blt (
mGraphicsOutput,
&mBackgroundColor.Pixel,
EfiBltVideoFill,
0,
0,
0,
TGT_CHAR_HEIGHT * mConsoleHeight,
mGraphicsOutput->Mode->Info->HorizontalResolution,
TGT_CHAR_HEIGHT,
0
);
This->Mode->CursorColumn = 0;
This->Mode->CursorRow = (INT32) (mConsoleHeight - 1);
}
if (String[Index] < ' ' && String[Index] != '\t') {
continue;
}
RenderChar (String[Index], &mCharacterBuffer[0].Raw);
mGraphicsOutput->Blt (
mGraphicsOutput,
&mCharacterBuffer[0].Pixel,
EfiBltBufferToVideo,
0,
0,
TGT_CHAR_WIDTH + This->Mode->CursorColumn * TGT_CHAR_WIDTH,
TGT_CHAR_HEIGHT + This->Mode->CursorRow * TGT_CHAR_HEIGHT,
TGT_CHAR_WIDTH,
TGT_CHAR_HEIGHT,
0
);
++This->Mode->CursorColumn;
mConsoleMaxPosX = MAX (mConsoleMaxPosX, This->Mode->CursorColumn);
}
RenderCursor (This->Mode->CursorColumn, This->Mode->CursorRow, This->Mode->CursorVisible);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextTestString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextQueryMode (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber,
OUT UINTN *Columns,
OUT UINTN *Rows
)
{
if (ModeNumber != 0) {
return EFI_UNSUPPORTED;
}
*Columns = mConsoleWidth;
*Rows = mConsoleHeight;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextSetMode (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber
)
{
if (ModeNumber != 0) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextSetAttribute (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Attribute
)
{
UINT32 FgColor;
UINT32 BgColor;
if ((Attribute & ~0x7FU) != 0) {
return EFI_UNSUPPORTED;
}
FgColor = BitFieldRead32 (Attribute, 0, 3);
BgColor = BitFieldRead32 (Attribute, 4, 6);
//
// Black foreground means grey.
//
if (FgColor == 0) {
FgColor = ARRAY_SIZE (mGraphicsEfiColors) / 2 - 1;
}
mForegroundColor.Raw = mGraphicsEfiColors[FgColor];
mBackgroundColor.Raw = mGraphicsEfiColors[BgColor];
This->Mode->Attribute = Attribute;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextClearScreen (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
)
{
mCursorOnscreen = FALSE;
This->Mode->CursorColumn = 0;
This->Mode->CursorRow = 0;
if (mConsoleMaxPosX > 0) {
mGraphicsOutput->Blt (
mGraphicsOutput,
&mBackgroundColor.Pixel,
EfiBltVideoFill,
0,
0,
0,
0,
MIN ((mConsoleMaxPosX + 1) * TGT_CHAR_WIDTH, mGraphicsOutput->Mode->Info->HorizontalResolution),
MIN ((mConsoleMaxPosY + 2) * TGT_CHAR_HEIGHT, mGraphicsOutput->Mode->Info->VerticalResolution),
0
);
}
//
// We do not reset max here, as we may still scroll (e.g. in shell via page buttons).
//
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextSetCursorPosition (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Column,
IN UINTN Row
)
{
if (Column >= mConsoleWidth || Row >= mConsoleHeight) {
return EFI_UNSUPPORTED;
}
This->Mode->CursorColumn = (INT32) Column;
This->Mode->CursorRow = (INT32) Row;
RenderCursor (This->Mode->CursorColumn, This->Mode->CursorRow, This->Mode->CursorVisible);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
AsciiTextEnableCursor (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN Visible
)
{
This->Mode->CursorVisible = Visible;
RenderCursor (This->Mode->CursorColumn, This->Mode->CursorRow, This->Mode->CursorVisible);
return EFI_SUCCESS;
}
STATIC
EFI_SIMPLE_TEXT_OUTPUT_MODE
mAsciiTextOutputMode = {
.MaxMode = 1,
.Mode = 0,
.Attribute = 0,
.CursorColumn = 0,
.CursorRow = 0,
.CursorVisible = FALSE,
};
STATIC
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
mAsciiTextOutputProtocol = {
AsciiTextReset,
AsciiTextOutputString,
AsciiTextTestString,
AsciiTextQueryMode,
AsciiTextSetMode,
AsciiTextSetAttribute,
AsciiTextClearScreen,
AsciiTextSetCursorPosition,
AsciiTextEnableCursor,
&mAsciiTextOutputMode
};
VOID
OcInstallCustomConOut (
VOID
)
{
EFI_STATUS Status;
UINTN UiScaleSize;
UiScaleSize = sizeof (mFontScale);
Status = gRT->GetVariable (
APPLE_UI_SCALE_VARIABLE_NAME,
&gAppleVendorVariableGuid,
NULL,
&UiScaleSize,
(VOID *) &mFontScale
);
if (EFI_ERROR (Status) || mFontScale != 2) {
mFontScale = 1;
}
DEBUG ((DEBUG_INFO, "OCC: Using builtin text renderer with %d scale\n", mFontScale));
Status = AsciiTextReset (&mAsciiTextOutputProtocol, TRUE);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCC: Cannot setup ASCII output\n"));
return;
}
gST->ConOut = &mAsciiTextOutputProtocol;
gST->Hdr.CRC32 = 0;
gBS->CalculateCrc32 (
gST,
gST->Hdr.HeaderSize,
&gST->Hdr.CRC32
);
OcConsoleControlSync ();
}