/**
* TerminalSrc.c - Terminal Source Driver for HR650X BIOS
*
* Source: AmiModulePkg\Terminal\Terminal.c, TerminalSetup.c
* Binary: TerminalSrc.efi (0132), 75 functions
*
* Address Range: 0x2C0 - 0x4FC0 (.text), Entry at 0x390
* Protocols: EFI_SERIAL_IO_PROTOCOL, EFI_SIMPLE_TEXT_INPUT_PROTOCOL,
* EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, ACPI SPCR
*
* UEFI Driver Entry Protocol:
* 1. ModuleEntryPoint -> TerminalDriverEntry
* 2. Installs Serial IO + Console In/Out protocols on new handle
* 3. Installs ACPI SPCR table for OS serial console redirection
* 4. Reads/writes "TerminalSerialVar" UEFI variable for persistent config
*
* Terminal Emulation:
* - Serial input parsing: ANSI/VT100 escape sequences, scan codes
* - Output via serial with ANSI escape code generation
* - Unicode input via UTF-8 multi-byte decoding (modes 2-3)
* - 80x25 (Mode 0) and 100x31 (Mode 2) display modes
* - Color support: 8 foreground + 8 background colors (ESC[<attr>m)
*
* Data Flow:
* Serial Port -> RingBuffer -> RingToKeyQueue -> KeyRingBuffer -> SerialToKey
* -> QueueEntry -> ConInProcessSerial -> SimpleTextInput.ReadKeyStroke
*
* SimpleTextOutput.OutputString -> ConOutOutputString -> SerialWrite -> Serial Port
*/
#include "TerminalSrc.h"
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
//=============================================================================
// Global Variables
//=============================================================================
// UEFI system table pointers (set by entry point)
extern EFI_SYSTEM_TABLE *gST;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
extern EFI_HANDLE gImageHandle;
// Terminal device array (2 entries: port 0 and port 1)
extern TERMINAL_DEV *gTerminalDevices[2]; // qword_9768
// Terminal output type array (2 entries)
extern UINT32 gTerminalTypes[2]; // qword_9758 (0=PCANSI, 1=VT100, etc.)
// Terminal serial variable (from TerminalSerialVar NV var)
extern UINT16 gTerminalSerialVar; // word_6F18
// Terminal active port flag
extern UINT8 gTerminalSerialPort; // byte_6F1E
// Debug/assert globals
extern UINT64 gHobList; // qword_6EA0
extern VOID *gDebugMask; // qword_6E98
extern VOID *gPcdDb; // qword_6E90
// Language string
extern UINT16 gEnUs[]; // "en-US"
// Terminal setup config bytes (from Setup NV variable)
extern UINT8 gSetupData[]; // byte_6F20 area
// Screen buffer (100 bytes/row * 31 rows)
extern UINT8 gScreenBuffer[3100]; // qword_72E0
// Attribute buffer (100 words/row * 31 rows)
extern UINT16 gScreenAttr[3100]; // word_7F00
// Escape sequence keymap table
extern ESC_KEYMAP_ENTRY *gEscKeymapTable; // word_6E58
// Key wait list data
extern UINT64 gKeyWaitCount; // qword_9740
extern LIST_ENTRY gKeyWaitListHead; // xmmword_9748
//=============================================================================
// UEFI Entry Point
//=============================================================================
/**
* ModuleEntryPoint - PE/COFF entry point
* @0x390
* Saves ImageHandle, gST, gBS, gRT. Calls HobLibGetHobList()
* then TerminalDriverEntry().
*/
EFI_STATUS
EFIAPI
ModuleEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
//=============================================================================
// Terminal Driver Entry
//=============================================================================
/**
* TerminalDriverEntry - Main driver entry
* @0x44C
*
* Responsibilities:
* 1. Install Serial IO + Console In/Out protocols on new handle
* 2. Allocate 2 terminal device contexts (up to 2 serial ports)
* 3. Register periodic timer callback for key polling (TerminalTimerKeyReset)
* 4. Initialize terminal device state to 0s
* 5. Read "TerminalSerialVar" from NV storage for serial port config
* 6. Write back updated "TerminalSerialVar" as UEFI variable
*
* Returns: EFI_SUCCESS or EFI error code
*/
EFI_STATUS
TerminalDriverEntry(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
//=============================================================================
// Serial Port Detection & Setup
//=============================================================================
/**
* TerminalDetectSerialPorts - Detect available serial ports via FV/HOB
* @0x16B0
*
* Searches the firmware volume file list for a serial terminal device
* matching the terminal GUID (unk_55E0). If found, locates the serial IO
* protocol for the device. Extracts device path info and determines the
* number of serial ports available (up to 2).
*
* Called by TerminalSerialRead() during serial port initialization.
*
* @param Device Terminal device context
* @param FvHandle Firmware volume handle for file list lookup
* @return EFI_STATUS
*/
EFI_STATUS
TerminalDetectSerialPorts(
IN TERMINAL_DEV *Device,
IN EFI_HANDLE FvHandle
);
/**
* TerminalSetupSerialPort - Configure serial port parameters
* @0x18B4
*
* Opens serial IO protocol on the detected serial device, queries
* the device path for ACPI UID, then configures baud rate, line
* control, and terminal settings via the protocol interface.
* Sets the baud rate cache in qword_6ED8.
*
* Called by TerminalSerialRead() after port detection.
*
* @param Device Terminal device context
* @param FvHandle Firmware volume handle
* @return EFI_STATUS
*/
EFI_STATUS
TerminalSetupSerialPort(
IN TERMINAL_DEV *Device,
IN EFI_HANDLE FvHandle
);
//=============================================================================
// EFI_SERIAL_IO_PROTOCOL Implementation
//=============================================================================
/**
* TerminalSerialReset - Reset serial port
* @0x680
*
* Calls EFI_SERIAL_IO_PROTOCOL.Reset() then .SetAttributes()
* on the underlying serial device. Validates device type = 3 (terminal).
*
* Returns: EFI_SUCCESS, EFI_UNSUPPORTED, EFI_DEVICE_ERROR, or EFI_TIMEOUT
*/
EFI_STATUS
TerminalSerialReset(
IN TERMINAL_DEV *This,
IN EFI_HANDLE ControllerHandle,
IN UINT8 *SerialDeviceType
);
/**
* TerminalSerialWrite - Write data to serial port
* @0x800
*
* Converts terminal output to serial data. Handles:
* - Unicode to serial byte conversion
* - Escape sequence generation
* - Scroll/cursor management
* - Reads "Setup" variable for flow control config
* - Flow control: 0=none, 0x4000=hardware, 0x8000=software
* - Calls TerminalSetupReadConfig() for baud/parity/stop/data config
* - Allocates temp buffer for serial data conversion
* - Calls TerminalSerialRead() to check for input while writing
*
* Returns: EFI_STATUS
*/
EFI_STATUS
TerminalSerialWrite(
IN TERMINAL_DEV *This,
IN EFI_HANDLE ControllerHandle,
IN UINT8 *Buffer
);
/**
* TerminalSerialClose - Close serial port
* @0x113C
*
* Disconnects serial IO protocol from controller.
* If CloseData is provided, also cleans up terminal device context
* and unregisters from the key notification system.
*
* Returns: EFI_STATUS
*/
EFI_STATUS
TerminalSerialClose(
IN TERMINAL_DEV *This,
IN EFI_HANDLE ControllerHandle,
IN VOID *CloseData,
IN EFI_HANDLE *ChildHandle
);
/**
* TerminalSerialRead - Read data from serial port (key input)
* @0x1358
*
* Reads serial input and converts to terminal key events.
* Calls TerminalDetectSerialPorts() and TerminalSetupSerialPort()
* for initialization. Parses: type-2 entries (keyboard data),
* type-1 entries (serial data). Handles TerminalSerialVar config.
*
* Returns: EFI_STATUS (EFI_UNSUPPORTED if no key available)
*/
EFI_STATUS
TerminalSerialRead(
IN TERMINAL_DEV *This,
IN EFI_HANDLE ControllerHandle,
OUT UINT8 *KeyChar,
OUT UINT8 *KeyFound
);
/**
* TerminalSerialWriteAll - Write all bytes to serial
* @0x3110
*
* Writes n bytes to serial IO protocol, handling partial writes.
* Continues writing remaining bytes until all are sent or error.
* Handles EFI_TIMEOUT (0x8000000000000012) as non-fatal.
*
* @param SerialIo EFI_SERIAL_IO_PROTOCOL instance
* @param Buffer Data to write
* @param Length Number of bytes to write
* @return EFI_STATUS
*/
EFI_STATUS
TerminalSerialWriteAll(
IN EFI_SERIAL_IO_PROTOCOL *SerialIo,
IN UINT8 *Buffer,
IN UINT64 Length
);
/**
* TerminalSetupReadConfig - Read serial config from Setup NV var
* @0x3F9C
*
* Reads the "Setup" UEFI variable for serial port configuration.
* Extracts flow control, baud rate, parity, stop bits, and data bits
* per port index. Falls back to defaults if variable not found:
* Baud rate: 115200
* Parity: 1 (none? or even?)
* Data bits: 8
* Stop bits: 1
*
* Baud rate lookup via table at qword_5110.
*
* @param PortIndex Serial port index (0 or 1)
* @param Config Output config structure (30+ bytes)
* @return EFI_STATUS
*/
EFI_STATUS
TerminalSetupReadConfig(
IN UINT8 PortIndex,
OUT UINT32 *Config
);
//=============================================================================
// Serial Input Pipeline
//=============================================================================
/**
* TerminalSerialBufferRead - Read bytes from serial device
* @0x2194
*
* Reads bytes from the serial device interface into a memory buffer.
* Called during ring buffer processing to transfer raw serial data
* into the terminal's internal buffer. Checks for error flags (0x100)
* and handles overflow conditions.
*
* @param SerialIo EFI_SERIAL_IO_PROTOCOL instance
* @param Buffer Destination buffer
* @param Remaining Pointer to remaining byte count (updated on return)
*/
VOID
TerminalSerialBufferRead(
IN EFI_SERIAL_IO_PROTOCOL *SerialIo,
OUT UINT8 *Buffer,
IN UINT64 *Remaining
);
/**
* TerminalRingBufferRead - Read one byte from ring buffer
* @0x2204
*
* Reads byte from serial ring buffer at current head index.
* Advances head index (with wrap at 1000).
* Used by TerminalUtf8Decode() and TerminalRingToKeyQueue().
*
* @param Device Terminal device with ring buffer
* @param OutByte Output byte
* @return TRUE if byte was available, FALSE if buffer empty
*/
BOOLEAN
TerminalRingBufferRead(
IN TERMINAL_DEV *Device,
OUT UINT8 *OutByte
);
/**
* TerminalRingWrite - Write Unicode char to key ring buffer
* @0x223C
*
* Enqueues a Unicode character into the circular key ring buffer
* (1000 entries). Checks for overflow against the read head (KeyRingHead).
* Advances KeyRingTail with wrap at 1000.
*
* @param Device Terminal device context
* @param Char Unicode character to enqueue
* @return Updated tail index
*/
UINT16
TerminalRingWrite(
IN TERMINAL_DEV *Device,
IN UINT16 Char
);
/**
* TerminalUtf8Decode - Decode UTF-8 from ring buffer
* @0x22A4
*
* Reads bytes from the ring buffer and decodes a multi-byte UTF-8 sequence:
* 1-byte: 0xxxxxxx (ASCII, returns byte directly)
* 2-byte: 110xxxxx 10xxxxxx (U+0080-U+07FF)
* 3-byte: 1110xxxx 10xxxxxx 10xxxxxx (U+0800-U+FFFF)
*
* Each byte consumed is removed from the ring buffer. The decoded
* Unicode character is written to the output. The n3 parameter
* indicates how many bytes were consumed (1, 2, or 3).
*
* @param Device Terminal device context
* @param OutChar Output decoded Unicode character
* @param NumBytesOut Output: number of bytes consumed (1-3)
* @return TRUE if character decoded successfully
*/
BOOLEAN
TerminalUtf8Decode(
IN TERMINAL_DEV *Device,
OUT UINT16 *OutChar,
OUT UINT8 *NumBytesOut
);
/**
* TerminalRingToKeyQueue - Process ring buffer into key queue
* @0x23B8
*
* Reads bytes from ring buffer and converts them to key events
* in the key ring buffer via TerminalRingWrite().
*
* Handles per output mode:
* Mode 0 (PC-ANSI) / Mode 1 (VT100): Direct byte-to-char mapping
* Mode 2 (VT100+): UTF-8 multi-byte decoding via TerminalUtf8Decode()
* Mode 3 (VT-UTF8): Direct passthrough
*
* Calls TerminalSerialBufferRead() to fetch raw bytes from serial,
* then decodes and writes to key ring buffer.
*/
VOID
TerminalRingToKeyQueue(
IN TERMINAL_DEV *Device
);
/**
* TerminalKeyRingDequeue - Dequeue from key ring buffer
* @0x2598
*
* Reads one Unicode character from the key ring buffer (KeyRingData).
* Checks KeyRingHead != KeyRingTail to determine if data is available.
* Advances KeyRingHead with wrap at 1000.
*
* @param Device Terminal device context
* @param OutChar Output Unicode character
* @return TRUE if character was available
*/
BOOLEAN
TerminalKeyRingDequeue(
IN TERMINAL_DEV *Device,
OUT UINT16 *OutChar
);
/**
* TerminalSerialToKey - Convert serial input to key events
* @0x263C
*
* Core serial-to-key conversion pipeline:
* 1. Calls TerminalRingToKeyQueue() to process raw ring buffer data
* 2. Reads key from TerminalKeyRingDequeue()
* 3. If 0x1B (ESC) received, enters escape sequence mode:
* a. Sets 10-second timer for escape sequence timeout
* b. Reads subsequent bytes into EscKeyBuffer[32]
* c. Matches against keymap table at gEscKeymapTable
* d. Returns converted scan code or 0x17 (ESC) on timeout
* 4. Returns 20-byte SERIAL_QUEUE_ENTRY with scan code + Unicode + flags
*
* If escape sequence does not match, buffered bytes are replayed
* into the key ring buffer by wrapping around KeyRingHead backwards.
*
* Keymap entry format (24 bytes):
* +0x00: WORD KeyChar
* +0x08: QWORD Next (next entry)
* +0x10: WORD ScanCode (output)
* +0x12: WORD Unicode (output)
* +0x14: BYTE ModMask
*
* Returns: EFI_SUCCESS, EFI_NOT_READY (no data)
*/
EFI_STATUS
TerminalSerialToKey(
IN TERMINAL_DEV *Device,
OUT SERIAL_QUEUE_ENTRY *KeyEntry
);
/**
* TerminalKeyboardCheck - Check keyboard state
* @0x25F0
*
* If key notify state is set and serial processing indicates
* a key is available, resets the read timer to stop polling.
*
* @param Device Terminal device context
* @param Context Timer context pointer (pointer to Device pointer)
*/
VOID
TerminalKeyboardCheck(
IN TERMINAL_DEV *Device,
IN VOID **Context
);
//=============================================================================
// EFI_SIMPLE_TEXT_INPUT_PROTOCOL Implementation
//=============================================================================
/**
* TerminalConInReset - Reset console input
* @0x2B98
*
* Resets the console input key queue by zeroing the queue buffer
* and resetting head/tail pointers.
*
* @param This Terminal device
* @param ExtendedVerification Not used
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalConInReset(
IN TERMINAL_DEV *This,
IN BOOLEAN ExtendedVerification
);
/**
* TerminalConInCheckKey - Check if key is available
* @0x2B1C
*
* If SerialInHead != SerialInTail in key queue, key is immediately
* available. Otherwise calls TerminalConInProcessSerial() to read
* more data from serial. If serial data is found, schedules timer.
*
* @param This Terminal device
* @return 0 if no key, non-zero if key state available
*/
UINT8
TerminalConInCheckKey(
IN TERMINAL_DEV *This
);
/**
* TerminalConInProcessSerial - Read and process serial data
* @0x2918
*
* Main serial input processor:
* 1. Reads 20 bytes from serial into temporary SERIAL_QUEUE_ENTRY
* 2. Handles Ctrl-Z (0x1A = 26) -> triggers TerminalScreenRedraw()
* 3. Parses control codes:
* - 0x08 (BS) -> scan code 0x51 (SCAN_LEFT)
* - 0x09 (TAB) -> scan code 0x30 (SCAN_F1?)
* - 0x0D (CR) -> scan code 0x2B (SCAN_ENTER)
* 4. Converts printable ASCII (0x20-0x7E) using attribute table
* (byte_57A0/byte_57A1: 2-byte lookup per char)
* 5. Handles DEL (0x7F) as backspace
* 6. Maps Unicode > 0x7E via ANSI translation table
* 7. Enqueues processed entry into serial output queue
* 8. Calls TerminalQueueDequeue() to dequeue from serial in queue
*
* Scan code lookup table at byte_5862 (3-byte entries per scan code)
* Attribute table at byte_5864 (6-byte entries per scan code)
*
* @param Device Terminal device context
* @return EFI_STATUS
*/
EFI_STATUS
TerminalConInProcessSerial(
IN TERMINAL_DEV *Device
);
/**
* TerminalWaitForKey - Wait for a key press
* @0x2C7C
*
* Processes incoming serial data via TerminalConInProcessSerial()
* and if a key notification is pending, schedules the timer to
* poll for it.
*
* @param This Terminal device
* @return EFI_SUCCESS or EFI_NOT_READY
*/
EFI_STATUS
TerminalWaitForKey(
IN TERMINAL_DEV *This
);
/**
* TerminalNotifyKeyListeners - Notify registered key listeners
* @0x2CC8
*
* Walks the key wait list (gKeyWaitListHead linked list) and for
* each entry, checks if the new key matches the listener's criteria.
* If match found, calls the listener's notification function.
* Uses LIST_ENTRY flink/blink pointers (48-byte KEY_WAIT_ITEM).
*
* @param KeyEntry Key data entry (20 bytes)
* @param Context Notify context
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalNotifyKeyListeners(
IN UINT32 *KeyEntry,
IN VOID *Context
);
/**
* TerminalCreateKeyWait - Create key wait item
* @0x2E6C
*
* Allocates a 48-byte KEY_WAIT_ITEM, initializes with key data
* and notification function, links into global key wait list.
* Schedules timer to check for matching key.
*
* @param This Terminal device (minus 24 bytes from device start)
* @param KeyData Key data to match
* @param NotifyFn Notification callback function
* @param WaitItem Output: pointer to created wait item
* @return EFI_STATUS
*/
EFI_STATUS
TerminalCreateKeyWait(
IN TERMINAL_DEV *This,
IN EFI_KEY_DATA *KeyData,
IN VOID *NotifyFn,
OUT VOID **WaitItem
);
/**
* TerminalRemoveKeyWait - Remove key wait item
* @0x2F88
*
* Unlinks a KEY_WAIT_ITEM from the notification list,
* frees allocated memory, and resets the timer.
*
* @param This Terminal device
* @param WaitItem Wait item to remove
* @return EFI_SUCCESS or EFI_INVALID_PARAMETER
*/
EFI_STATUS
TerminalRemoveKeyWait(
IN TERMINAL_DEV *This,
IN VOID *WaitItem
);
/**
* TerminalKeyFindOrAlloc - Find or allocate key slot
* @0x3F24
*
* Manages the 2-entry key mapping table (gTerminalSerialVar based).
* Searches for key character in existing entries, then looks for
* an active slot to reuse. Returns 0xFF if table full.
*
* @param KeyChar Character to find/allocate
* @return Index (0 or 1) or 0xFF if table full
*/
UINT8
TerminalKeyFindOrAlloc(
IN UINT8 KeyChar
);
/**
* TerminalQueueDequeue - Dequeue entry from circular queue
* @0x304C
*
* Dequeues a 20-byte SERIAL_QUEUE_ENTRY from the 33-entry
* circular FIFO queue at Queue base address. Checks head != tail.
*
* @param Queue Queue base address
* @param OutEntry Output buffer (20 bytes)
* @return EFI_SUCCESS or EFI_NOT_READY (queue empty)
*/
EFI_STATUS
EFIAPI
TerminalQueueDequeue(
IN UINT8 *Queue,
OUT SERIAL_QUEUE_ENTRY *OutEntry
);
//=============================================================================
// EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL Implementation
//=============================================================================
/**
* TerminalConOutReset - Reset console output
* @0x2BF0
*
* Zeroes the output queue buffer and resets head/tail pointers.
*
* @param This Terminal device
* @param ExtendedVerification Not used
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalConOutReset(
IN TERMINAL_DEV *This,
IN BOOLEAN ExtendedVerification
);
/**
* TerminalConOutOutputString - Main text output function (largest function)
* @0x3274 (1602 bytes)
*
* Outputs a Unicode string to the serial terminal:
* 1. Determines current mode (80x25 or 100x31) from ModePtr
* 2. Iterates through Unicode string
* 3. Handles special characters:
* - \b (0x08): Backspace, move cursor left
* - \t (0x09): Tab, expand to column boundary
* - \r (0x0D): Carriage return
* - \n (0x0A): Line feed, scroll if at bottom
* 4. Printable chars written to serial and screen buffer
* 5. Line wrapping at column boundary (80 or 100)
* 6. Scrolling: shift all rows up, clear last row
* 7. Uses gScreenBuffer for character memory
* 8. Uses gScreenAttr for color attributes
* 9. Checks OutputDisabled flag before serial output
* 10. Can suppress output for deferred screen update
*
* @param This Terminal device
* @param WString Unicode string to output
* @param a3 Flag parameter (output mode flags)
* @return EFI_STATUS
*/
EFI_STATUS
TerminalConOutOutputString(
IN TERMINAL_DEV *This,
IN CONST UINT16 *WString,
IN UINT8 a3
);
/**
* TerminalConOutTestString - Test if string can be output
* @0x3A78
*
* Validates Unicode string for output compatibility by terminal type:
* Mode 0 (PC-ANSI): Only chars < 0x80 valid
* Mode 1 (VT100): Validates 0x2100-0x27FF against translation table
* Mode 2 (VT100+): Uses TerminalUniToUtf8 for validation
* Mode 3 (VT-UTF8): Uses TerminalUniToGraphByte for validation
*
* @param This Terminal device
* @param WString Unicode string to test
* @return EFI_SUCCESS if string can be displayed, EFI_UNSUPPORTED otherwise
*/
EFI_STATUS
TerminalConOutTestString(
IN TERMINAL_DEV *This,
IN CONST UINT16 *WString
);
/**
* TerminalConOutSetAttribute - Set text attribute
* @0x3174
*
* Sets foreground/background color attribute. If attribute changes,
* calls TerminalConOutClearScreen() then TerminalConOutSetColor()
* to apply the new color to the entire screen.
*
* @param This Terminal device
* @param Attribute Color attribute (foreground | background << 4)
* @return EFI_STATUS
*/
EFI_STATUS
TerminalConOutSetAttribute(
IN TERMINAL_DEV *This,
IN UINT32 Attribute
);
/**
* TerminalConOutSetAttributeDefault - Set default attribute
* @0x3A70
* Wrapper: TerminalConOutOutputString(This, 1, ...)
* Sets terminal to default attribute (white on black).
*
* @param This Terminal device
* @return EFI_STATUS
*/
EFI_STATUS
TerminalConOutSetAttributeDefault(
IN TERMINAL_DEV *This
);
/**
* TerminalConOutSetAttributeDirect - Set attribute byte directly
* @0x2C4C
*
* Validates and stores an attribute byte at Device->AttributeByte (+3944).
* Attribute must be negative (bit 7 set) with bits 3-5 clear, or
* returns EFI_UNSUPPORTED.
*
* @param Device Terminal device
* @param Attribute Attribute byte to set
* @return EFI_SUCCESS or EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutSetAttributeDirect(
IN TERMINAL_DEV *Device,
IN UINT8 *Attribute
);
/**
* TerminalConOutSetMode - Set display mode
* @0x3BC4
*
* Switches between display modes:
* Mode 0: 80 columns x 25 rows
* Mode 2: 100 columns x 31 rows
* Mode 1 is rejected (returns EFI_UNSUPPORTED).
* Fills screen buffer with 0xFF and clears display.
*
* @param This Terminal device
* @param Mode 0 = 80x25, 2 = 100x31
* @return EFI_SUCCESS or EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutSetMode(
IN TERMINAL_DEV *This,
IN UINT64 Mode
);
/**
* TerminalConOutQueryMode - Query display mode dimensions
* @0x3B7C
*
* Returns columns and rows for requested mode:
* Mode 0: 80 columns, 25 rows
* Mode 2: 100 columns, 31 rows
* Mode 1 and others > MaxMode return EFI_UNSUPPORTED.
*
* @param This Terminal device
* @param Mode Mode number
* @param Columns Output: number of columns
* @param Rows Output: number of rows
* @return EFI_SUCCESS or EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutQueryMode(
IN TERMINAL_DEV *This,
IN UINT64 Mode,
OUT UINT64 *Columns,
OUT UINT64 *Rows
);
/**
* TerminalConOutSetColor - Set foreground/background color
* @0x3C4C
*
* Generates ANSI escape sequence ESC[<attr>m for color change.
* Uses color translation table byte_5080:
* byte_5080[0..7] = foreground color codes (30-37)
* byte_5080[8..15] = background color codes (40-47)
*
* Outputs: ESC[<bright>;<bg>;<fg>m or ESC[<code>m
* Caches attribute to avoid redundant output.
*
* @param This Terminal device
* @param Color Color code (bit 3 = bright, bits 0-2 = fg, bits 4-6 = bg)
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalConOutSetColor(
IN TERMINAL_DEV *This,
IN UINT64 Color
);
/**
* TerminalConOutClearScreen - Clear terminal screen
* @0x3D6C
*
* Sends ESC[2J (clear screen) ANSI sequence, then:
* 1. Fills screen buffer with 0xFF (empty char)
* 2. Fills attribute buffer with 0 (default attr)
* 3. Resets cursor column + row to 0
* 4. Calls TerminalConOutSetCursorPos(0, 0)
*
* @param This Terminal device
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalConOutClearScreen(
IN TERMINAL_DEV *This
);
/**
* TerminalConOutSetCursorPos - Set cursor position
* @0x3E58
*
* Generates ANSI escape: ESC[<row+1>;<col+1>H
* Validates position based on current mode dimensions.
* Caches cursor column + row in ModePtr struct.
*
* @param This Terminal device
* @param Column Column (0-based)
* @param Row Row (0-based)
* @return EFI_SUCCESS or EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutSetCursorPos(
IN TERMINAL_DEV *This,
IN UINT64 Column,
IN UINT64 Row
);
/**
* TerminalConOutEnableCursor - Enable/disable cursor
* @0x3F0C
*
* Always returns EFI_SUCCESS except when ExtendedVerification
* is TRUE, which returns EFI_UNSUPPORTED.
*
* @param This Terminal device
* @param ExtendedVerification Not supported
* @return EFI_SUCCESS or EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutEnableCursor(
IN TERMINAL_DEV *This,
IN BOOLEAN ExtendedVerification
);
/**
* TerminalConOutModeQueryFail - Mode query stub
* @0x410C
* Always returns EFI_UNSUPPORTED
*/
EFI_STATUS
TerminalConOutModeQueryFail(
VOID
);
/**
* TerminalConOutOutputChar - Output a single character
* @0x2870
*
* Outputs a single terminal character to serial via the output queue.
* If serial input data is pending, schedules keyboard check timer.
* For newline (0x0A), inserts carriage return (0x0D) before.
*
* @param This Terminal device
* @param Char Character to output
* @param CharCount Character count parameter (output type variant)
* @return EFI_SUCCESS
*/
EFI_STATUS
TerminalConOutOutputChar(
IN TERMINAL_DEV *This,
IN UINT8 *Char,
IN UINT8 CharCount
);
/**
* TerminalConOutOutputCharType4 - Output char callback (type 4)
* @0x2BD8
*
* Callback variant that outputs char with type=4.
* Wrapper: TerminalConOutOutputChar(a1, a2, 4)
* Registered as SimpleTextOut.OutputString callback.
*/
EFI_STATUS
TerminalConOutOutputCharType4(
IN TERMINAL_DEV *This,
IN UINT8 *Char
);
/**
* TerminalConOutOutputCharType12 - Output char callback (type 0xC)
* @0x2C30
*
* Callback variant that outputs char with type=0xC.
* Adjusts device pointer: arg = device - 24, then
* calls TerminalConOutOutputChar(arg, a2, 0xC).
*/
EFI_STATUS
TerminalConOutOutputCharType12(
IN VOID *ModeStruct,
IN UINT8 *Char
);
/**
* TerminalConOutOutputCharType20 - Output char callback (type 0x14)
* @0x3030
*
* Callback variant that outputs char with type=0x14 (20).
* Adjusts device pointer: arg = device - 72, then
* calls TerminalConOutOutputChar(arg, a2, 0x14).
*/
EFI_STATUS
TerminalConOutOutputCharType20(
IN VOID *ModeStruct,
IN UINT8 *Char
);
//=============================================================================
// Character Encoding / Translation
//=============================================================================
/**
* TerminalUniToGraphByte - Convert Unicode to PC graphics byte
* @0x30BC
*
* Translates Unicode character (0x2100-0x27FF range) to PC graphics
* byte using translation table at word_5920:
* - table[2*v] = Unicode match value
* - table[2*v+1].HIWORD = attribute
* - table[2*v+1].LOWORD = display byte
*
* @param Unicode Unicode character
* @return Graphics byte or 0 if no translation
*/
UINT8
TerminalUniToGraphByte(
IN UINT16 Unicode
);
/**
* TerminalUniToUtf8 - Convert Unicode to UTF-8
* @0x3218
*
* Converts Unicode to 2 or 3 byte UTF-8:
* U+0080-U+07FF: 2 bytes (110xxxxx 10xxxxxx)
* U+0800-U+FFFF: 3 bytes (1110xxxx 10xxxxxx 10xxxxxx)
*
* @param Unicode Unicode character
* @param Utf8Out Output buffer (at least 3 bytes)
* @param NumBytes Output: number of UTF-8 bytes (2 or 3)
* @return Last byte of UTF-8 sequence
*/
UINT8
TerminalUniToUtf8(
IN UINT16 Unicode,
OUT UINT8 *Utf8Out,
OUT UINT8 *NumBytes
);
//=============================================================================
// Screen Management
//=============================================================================
/**
* TerminalScreenRedraw - Redraw entire terminal screen
* @0x38B8
*
* Full screen redraw of both terminal devices (up to 2):
* 1. For each device (iterated from gTerminalDevices array):
* a. Determine mode dimensions (80x25 or 100x31)
* b. Clear screen with ESC[2J
* c. Redraw each character from gScreenBuffer
* d. Apply colors from gScreenAttr
* e. Restore cursor position
* 2. Uses TerminalConOutOutputString() for chars
* 3. Uses TerminalConOutSetColor() for attributes
* 4. Checks OutputDisabled flag per device
*/
VOID
TerminalScreenRedraw(
VOID
);
//=============================================================================
// Timer/Event Infrastructure
//=============================================================================
/**
* TerminalTimerNotify - Timer callback for SPCR refresh
* @0x1C6C
*
* Periodic timer callback. Queries the key wait list and
* calls TerminalInstallSpcrTable() to refresh the SPCR table.
*
* @param Event Timer event
* @param Context Terminal device context
*/
VOID
EFIAPI
TerminalTimerNotify(
IN EFI_EVENT Event,
IN VOID *Context
);
/**
* TerminalTimerKeyReset - Timer to reset key state
* @0x2120
*
* Fires periodically (500ms) to clear key notification state.
* Resets ring buffer and key tracking. Registered via
* gBS->SetTimer() at TIMER_KEY_POLL_US interval.
*
* @param Event Timer event
*/
VOID
EFIAPI
TerminalTimerKeyReset(
IN EFI_EVENT Event
);
//=============================================================================
// Console Output Key Handler (for Setup UI)
//=============================================================================
/**
* TerminalConOutHandleKey - Handle key event on console output
* @0x1CC8 (1110 bytes)
*
* Processes a key event on the console output device for Setup UI:
* 1. Reads "Setup" NV variable for terminal configuration
* 2. Extracts terminal emulation type per serial port
* 3. Locates matching serial IO device handle
* 4. Queries HII database for font data via PcdGetPtr()
* 5. Reads font glyph at X,Y position
* 6. Processes key input for terminal configuration UI
* 7. Routes to correct terminal device by key index
*
* @param KeyIndex Key index (0 or 1)
* @param Context Terminal device context
* @param SerialIoGUID Serial IO protocol GUID
* @return TRUE if key was handled
*/
BOOLEAN
TerminalConOutHandleKey(
IN UINT8 KeyIndex,
IN TERMINAL_DEV *Context,
IN EFI_GUID *SerialIoGUID
);
//=============================================================================
// SPCR Table Installation
//=============================================================================
/**
* TerminalInstallSpcrTable - Install ACPI SPCR table
* @0x1ABC
*
* Constructs and installs the Serial Port Console Redirection (SPCR) table:
* Signature: "SPCR" (0x52435053)
* Length: 80 bytes
* Revision: 2
* OEM ID: "A M I "
* OEM Table ID: 0x56204F49545041 ("APTIO V")
* Creator ID: 0x2E494D41 ("AMI.")
* Creator Rev: 0x0005000E
*
* Data sourced from hardware config bytes:
* byte_6E4B, byte_5C28 (interface type)
* byte_6E51, byte_6E49, byte_6E4A (config)
* byte_6E4D-E (legacy config for < rev 2)
*
* @param AcpiTable ACPI Table Protocol interface
* @param SerialIo Serial IO config pointer (for baud/parity/stop/flow)
* @return EFI_STATUS
*/
EFI_STATUS
TerminalInstallSpcrTable(
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable,
IN TERMINAL_DEV *SerialIo
);
//=============================================================================
// Library Functions (Statically linked)
//=============================================================================
/**
* GuidCompare - Compare two GUIDs
* @0x4118
* Compares two 16-byte GUIDs via two 8-byte uint64 comparisons.
*/
BOOLEAN
GuidCompare(
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
);
/**
* PcdGetPtr - Get PCD database pointer
* @0x4180
* Locates and caches EFI_PCD_PROTOCOL. First call locates via
* gBS->LocateProtocol, subsequent calls return cached pointer.
*/
VOID *
PcdGetPtr(
VOID
);
/**
* ReadUnaligned64 - Read unaligned 64-bit value
* @0x420C
*/
UINT64
ReadUnaligned64(
IN VOID *Buffer
);
/**
* DebugLibGetDebugMask - Get debug mask
* @0x423C
*/
UINT64
DebugLibGetDebugMask(
VOID
);
/**
* DebugPrint - Print debug message
* @0x42BC
*/
UINTN
DebugPrint(
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
);
/**
* AssertReport - Report assertion failure
* @0x4304
*/
VOID
AssertReport(
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Condition
);
/**
* HobLibGetHobList - Get HOB list pointer
* @0x4344
* Finds HOB list from system table configuration table array.
*/
VOID *
HobLibGetHobList(
VOID
);
/**
* PoolAllocate - Allocate memory pool
* @0x4424
*/
VOID *
PoolAllocate(
IN UINTN Size
);
/**
* PoolAllocateZero - Allocate + zero memory pool
* @0x4450
*/
VOID *
PoolAllocateZero(
IN UINTN Size
);
/**
* FvFileListSize - Calculate FV file list size
* @0x4490
*/
UINTN
FvFileListSize(
IN UINT8 *List
);
/**
* FvFileListAppend - Append entry to FV file list
* @0x44E4
*/
UINT8 *
FvFileListAppend(
IN UINT8 *List,
IN UINT8 *Entry
);
/**
* FvFileListFindEnd - Find end marker in FV file list
* @0x45BC
*/
UINT8 *
FvFileListFindEnd(
IN UINT8 *List
);
/**
* FvFileListFindPrev - Find previous entry in FV file list
* @0x460C
*/
UINT8 *
FvFileListFindPrev(
IN UINT8 *List
);
/**
* FvFileListDuplicate - Duplicate FV file list
* @0x463C
*/
UINT8 *
FvFileListDuplicate(
IN UINT8 *List
);
/**
* CompareMem - Compare memory regions
* @0x46B8
*/
INTN
CompareMem(
IN CONST VOID *Dest,
IN CONST VOID *Src,
IN UINTN Length
);
/**
* UnicodeSPrintAsciiFmt - SPrint with ASCII format string
* @0x4940
*/
UINTN
UnicodeSPrintAsciiFmt(
OUT CHAR16 *Buffer,
IN CONST CHAR8 *Format,
...
);
/**
* UnicodeSPrint - Full Unicode SPrint
* @0x4968
*/
UINTN
UnicodeSPrint(
OUT CHAR16 *Buffer,
IN UINTN BufferSize,
IN CONST CHAR8 *Format,
IN VA_LIST Args
);
/**
* DebugPortDetect - Detect debug port via CMOS
* @0x4E00
*/
UINTN
DebugPortDetect(
VOID
);
/**
* SetMem - Fill memory with byte value
* @0x4EA0
*/
VOID *
SetMem(
OUT VOID *Buffer,
IN UINTN Size,
IN UINT8 Value
);
/**
* CopyMem - Copy memory (handles overlap)
* @0x4F00
*/
VOID *
CopyMem(
OUT VOID *Dest,
IN CONST VOID *Src,
IN UINTN Size
);