1199 lines
36 KiB
C
1199 lines
36 KiB
C
/** @file
|
|
CrLegacySupport
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2017, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
#include "CrLegacySupport.h"
|
|
#include "CrBdaMemManager.h"
|
|
#include "CrServiceMisc.h"
|
|
|
|
#include <Library/DxeChipsetSvcLib.h>
|
|
#include <Library/DxeOemSvcKernelLib.h>
|
|
|
|
EFI_CONSOLE_REDIRECTION_SERVICE_PROTOCOL *gCrService = NULL;
|
|
EFI_CONSOLE_REDIRECTION_INFO *gCrInfo = NULL;
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mRootBridgeIo = NULL;
|
|
EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *mLegacyBiosPlatformProtocol = NULL;
|
|
CR_EFI_MEM_MANAGER *mCrEbdaMemManager = NULL;
|
|
EFI_LEGACY_BIOS_PROTOCOL *mLegacyBios = NULL;
|
|
|
|
EFI_EVENT mLegacyBootEvent;
|
|
EFI_LEGACY_BIOS_PLATFORM_HOOKS mPlatformHooks;
|
|
EFI_CONSOLE_REDIRECTION_OPROM_INFO_PROTOCOL mCrOpROMInfo = {0};
|
|
UINT32 mLastEbda = 0;
|
|
UINT8 mUartUid = 0;
|
|
|
|
//
|
|
// Baud Rate Divisor. Baud Rate 1200 Divisor = 115200/1200 = 96
|
|
//
|
|
static UINT16 mBaudRateDivisor [] = {96, 48, 24, 12, 6, 3, 2, 1 };
|
|
//
|
|
// This table use for translate CrInfo terminal type to EBdaCrInfo's TerminalType
|
|
// This table is depend on AdvanceVfr.vfr (vt100=Bit0 vt100P=Bit1 vt-utf8=Bit2 pc-ansi=Bit3)
|
|
//
|
|
static UINT8 gTerminalFlagTable [] = {TP_VT100, TP_VT100P, TP_VTUTF8, TP_PCANSI};
|
|
|
|
BOOLEAN
|
|
IsUartFlowControlNode (
|
|
IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
|
|
)
|
|
{
|
|
return (BOOLEAN) (
|
|
(DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
|
|
(DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
|
|
(CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
|
|
);
|
|
}
|
|
|
|
UINT8
|
|
SupportFlowControl (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
)
|
|
{
|
|
UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
|
|
|
|
while (!IsDevicePathEnd (DevicePath)) {
|
|
if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
|
|
FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *)DevicePath;
|
|
return (UINT8)(ReadUnaligned32 (&FlowControl->FlowControlMap));
|
|
|
|
}
|
|
DevicePath = NextDevicePathNode (DevicePath);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
UINT8
|
|
CrGetUartUid (
|
|
IN EFI_CONSOLE_REDIRECTION_OPROM_INFO_PROTOCOL *This
|
|
)
|
|
{
|
|
return mUartUid++;
|
|
}
|
|
|
|
CR_COMMON_AREA_INFO*
|
|
GetCrCommonArea (
|
|
IN EFI_CONSOLE_REDIRECTION_OPROM_INFO_PROTOCOL *This
|
|
)
|
|
{
|
|
CR_EFI_MEM_MANAGER *CrEfiMemManager;
|
|
UINT32 Ebda;
|
|
UINT8 BiosPhase;
|
|
UINT32 Signature;
|
|
UINT32 EbdaBlock;
|
|
|
|
|
|
if (This->CrOpROMInstalled) {
|
|
Ebda = (UINTN)((*(UINT16*)(UINTN)0x40e) << 4);
|
|
BiosPhase = EBDA_DATA(BIOS_PHASE, UINT8);
|
|
|
|
if (BiosPhase == BIOS_PHASE_DOS_RUNING || BiosPhase == BIOS_PHASE_OPROM_RUNING || BiosPhase == BIOS_PHASE_OPROM) {
|
|
return NULL;
|
|
}
|
|
|
|
if (mLastEbda != Ebda) {
|
|
mCrEbdaMemManager = NULL;
|
|
mLastEbda = Ebda;
|
|
}
|
|
|
|
//
|
|
// Search CROpROM allocated EBDA memory
|
|
//
|
|
if (mCrEbdaMemManager == NULL) {
|
|
for (EbdaBlock = 0; EbdaBlock < (0xA0000 - Ebda); EbdaBlock+=0x400) {
|
|
Signature = EBDA_DATA(EbdaBlock, UINT32);
|
|
if (Signature == CR_MEM_MANAGER_SIGNATURE) {
|
|
mCrEbdaMemManager = (CR_EFI_MEM_MANAGER *)(UINTN)(((*(UINT16*)(UINTN)0x40e) << 4) + (EbdaBlock));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mCrEbdaMemManager != NULL) {
|
|
//
|
|
// Return CR Common Area
|
|
//
|
|
return (CR_COMMON_AREA_INFO *)((UINTN)mCrEbdaMemManager + (UINTN)mCrEbdaMemManager->CommonAreaOffset);
|
|
}
|
|
} else {
|
|
if (mCrMemStart != 0) {
|
|
CrEfiMemManager = (CR_EFI_MEM_MANAGER *)(UINTN)mCrMemStart;
|
|
return (CR_COMMON_AREA_INFO *)(UINTN)(mCrMemStart + CrEfiMemManager->CommonAreaOffset);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Clear UART IER Register to disable UART interrupt
|
|
|
|
**/
|
|
VOID
|
|
ClearUartIer (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
if (gCrInfo == NULL) {
|
|
return;
|
|
}
|
|
for (Index = 0; Index < gCrInfo->DeviceCount; Index++) {
|
|
gCrInfo->CRDevice[Index].Uart16550protocol->RegWrite(
|
|
gCrInfo->CRDevice[Index].Uart16550protocol,
|
|
UART_IER_OFFSET,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Set interrupt of UART device
|
|
|
|
@param EnableIntr Enable or disable UART interrupt
|
|
|
|
**/
|
|
VOID
|
|
SetSerialInterrupt (
|
|
IN UINT8 EnableIntr
|
|
)
|
|
{
|
|
H2O_UART_16550_ACCESS_PROTOCOL *UartProtocol;
|
|
CR_COMMON_AREA_INFO *CrOpromInfo;
|
|
UINT64 PciAddress;
|
|
UINT16 u16;
|
|
UINT8 u8;
|
|
UINTN Index;
|
|
|
|
|
|
if (gCrInfo == NULL) {
|
|
return;
|
|
}
|
|
|
|
u16 = 0;
|
|
u8 = 0;
|
|
CrOpromInfo = NULL;
|
|
for (Index = 0; Index < gCrInfo->DeviceCount; Index++) {
|
|
UartProtocol = gCrInfo->CRDevice[Index].Uart16550protocol;
|
|
|
|
switch (gCrInfo->CRDevice[Index].Type) {
|
|
|
|
case ISA_SERIAL_DEVICE:
|
|
UartProtocol->RegRead (UartProtocol, UART_MCR_OFFSET, &u8);
|
|
if (EnableIntr) {
|
|
u8 = u8 | UART_MCR_OUT2_BIT;
|
|
} else {
|
|
u8 = u8 & ~UART_MCR_OUT2_BIT;
|
|
}
|
|
UartProtocol->RegWrite(UartProtocol, UART_MCR_OFFSET, u8);
|
|
|
|
break;
|
|
|
|
case PCI_SERIAL_DEVICE:
|
|
case PCI_HS_SERIAL_DEVICE:
|
|
u16 = gCrInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->UID;
|
|
PciAddress = EFI_PCI_ADDRESS (GET_BUS(u16), GET_DEV(u16), GET_FUN(u16), PCI_CONFIG_COMMAND_WORD);
|
|
mRootBridgeIo->Pci.Read (mRootBridgeIo, EfiPciWidthUint16, PciAddress, 1, &u16);
|
|
|
|
if (EnableIntr) {
|
|
u16 = u16 & ~PCI_CONFIG_DISABLE_INTERRUPT;
|
|
u16 = u16 | PCI_CONFIG_BUS_MASTER;
|
|
} else {
|
|
u16 = u16 | PCI_CONFIG_DISABLE_INTERRUPT;
|
|
u16 = u16 & ~PCI_CONFIG_BUS_MASTER;
|
|
}
|
|
mRootBridgeIo->Pci.Write (mRootBridgeIo, EfiPciWidthUint16, PciAddress, 1, &u16);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Enable interrupt of UART device
|
|
|
|
**/
|
|
VOID
|
|
EnableSerialInterrupt (
|
|
VOID
|
|
)
|
|
{
|
|
SetSerialInterrupt (1);
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Disable interrupt of UART device
|
|
|
|
**/
|
|
VOID
|
|
DisableSerialInterrupt (
|
|
VOID
|
|
)
|
|
{
|
|
SetSerialInterrupt (0);
|
|
|
|
//
|
|
// Due to some UART device can't be disable interrupt by SetSerialInterrupt (0)
|
|
// So, we need clear IER register setting to ensure UART device interrupt disable
|
|
//
|
|
ClearUartIer ();
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Translate Esc Sequence Code into KeyBoard scan code
|
|
|
|
@param TerminalEscCode Pointer to Terminal ESC Sequence Code protocol
|
|
@param EscTableIndex Index of Terminal ESC Sequence Code
|
|
|
|
@retval return translate result
|
|
|
|
**/
|
|
UINT8
|
|
TranslateEfiScanCode (
|
|
IN EFI_TERMINAL_ESC_CODE_PROTOCOL *TerminalEscCode,
|
|
IN UINTN EscTableIndex
|
|
)
|
|
{
|
|
EFI_TO_KB_SCANCODE_MAP *pScanCodeMap;
|
|
ESC_SEQUENCE_CODE *pEscSeqCode;
|
|
UINT8 DataType;
|
|
UINTN Index;
|
|
|
|
|
|
DataType = TerminalEscCode->EscSequenceCode[EscTableIndex].DataType;
|
|
|
|
if ((DataType == ESC_CODE_SCANCODE) || (DataType == ESC_CODE_EXTENTION)) {
|
|
|
|
pEscSeqCode = TerminalEscCode->EscSequenceCode;
|
|
pScanCodeMap = TerminalEscCode->EfiToKbScanCode;
|
|
|
|
for (Index = 0; pScanCodeMap[Index].EfiScanCode != 0; Index++) {
|
|
if (pScanCodeMap[Index].EfiScanCode == pEscSeqCode[EscTableIndex].Data) {
|
|
return (UINT8) (pScanCodeMap[Index].KbScanCode);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (UINT8)(TerminalEscCode->EscSequenceCode[EscTableIndex].Data);
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Fill Console Redirection supported special commands to CR_EFI_INFO structure
|
|
|
|
@param TerminalEscCode Pointer to Console Redirection EFI Information structure
|
|
|
|
@retval EFI_SUCCESS Special commands fill success
|
|
@retval EFI_UNSUPPORTED Special commands fill fail
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FillCrSpecialCommandTable (
|
|
IN OUT CR_EFI_INFO *CrEfiInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_TERMINAL_ESC_CODE_PROTOCOL *TerminalEscCode;
|
|
CR_EFI_SPECIAL_COMMAND_TABLE *CrSpcTable;
|
|
UINTN Index;
|
|
CHAR8 AsciiStr[128];
|
|
UINTN StringLength;
|
|
CHAR8 *pCrSpcStr;
|
|
|
|
Status = gBS->LocateProtocol (&gTerminalEscCodeProtocolGuid, NULL, (VOID **)&TerminalEscCode);
|
|
if (EFI_ERROR (Status) || (TerminalEscCode->CrSpecialCommandCount == 0)) {
|
|
CrEfiInfo->CrSpecialCommandTableOffset = 0;
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
CrSpcTable = (CR_EFI_SPECIAL_COMMAND_TABLE *) CrEfiMemAlloc ( sizeof(CR_EFI_SPECIAL_COMMAND_TABLE) +
|
|
sizeof (CR_EFI_SPECIAL_COMMAND) *
|
|
(TerminalEscCode->CrSpecialCommandCount - 1));
|
|
if (CrSpcTable == NULL) {
|
|
ASSERT (0);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
CrEfiInfo->CrSpecialCommandTableOffset = (UINT16)((UINTN)CrSpcTable - mCrMemStart);
|
|
|
|
CrSpcTable->Count = TerminalEscCode->CrSpecialCommandCount;
|
|
|
|
for (Index = 0; Index < TerminalEscCode->CrSpecialCommandCount; Index++) {
|
|
CrSpcTable->CrSpecialCommand[Index].Command = TerminalEscCode->CrSpecialCommand[Index].Command;
|
|
CrSpcTable->CrSpecialCommand[Index].CommandType = TerminalEscCode->CrSpecialCommand[Index].CommandType;
|
|
|
|
//[-start-180729-IB08400622-modify]//
|
|
UnicodeStrToAsciiStrS ((CONST CHAR16 *)TerminalEscCode->CrSpecialCommand[Index].CommandStr, AsciiStr, 128);
|
|
//[-end-180729-IB08400622-modify]//
|
|
|
|
StringLength = AsciiStrLen (AsciiStr);
|
|
pCrSpcStr = (CHAR8 *) CrEfiMemAlloc (StringLength + 1);
|
|
if (pCrSpcStr == NULL) {
|
|
ASSERT (0);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
CopyMem (pCrSpcStr ,AsciiStr, StringLength + 1);
|
|
|
|
CrSpcTable->CrSpecialCommand[Index].CommandStrOffset = (UINT16)((UINTN)pCrSpcStr - mCrMemStart);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Fill Console Redirection supported Terminal ESC Sequence Code to CR_EFI_INFO structure
|
|
|
|
@param TerminalEscCode Pointer to Console Redirection EFI Information structure
|
|
|
|
@retval EFI_SUCCESS Terminal ESC Sequence Code fill success
|
|
@retval EFI_UNSUPPORTED Terminal ESC Sequence Code fill fail
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FillTerminalEscCode (
|
|
IN OUT CR_EFI_INFO *CrEfiInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_TERMINAL_ESC_CODE_PROTOCOL *TerminalEscCode;
|
|
CR_EFI_ESC_SEQUENCE_CODE_TABLE *CrEscCodeTable;
|
|
UINTN Index;
|
|
CHAR8 AsciiStr[128];
|
|
UINTN StringLength;
|
|
CHAR8 *pCrEscCode;
|
|
UINT8 Data;
|
|
|
|
Status = gBS->LocateProtocol (&gTerminalEscCodeProtocolGuid, NULL, (VOID **)&TerminalEscCode);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Build ESC sequence code table
|
|
//
|
|
CrEscCodeTable = (CR_EFI_ESC_SEQUENCE_CODE_TABLE *) CrEfiMemAlloc (sizeof(CR_EFI_ESC_SEQUENCE_CODE_TABLE) +
|
|
sizeof(CR_EFI_ESC_SEQUENCE_CODE) *
|
|
(TerminalEscCode->EscCodeCount - 1));
|
|
if (CrEscCodeTable == NULL) {
|
|
ASSERT (0);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
CrEfiInfo->TerminalEscCodeOffset = (UINT16)((UINTN)CrEscCodeTable - mCrMemStart);
|
|
|
|
CrEscCodeTable->Count = TerminalEscCode->EscCodeCount;
|
|
|
|
for (Index = 0; Index < TerminalEscCode->EscCodeCount; Index++) {
|
|
|
|
CrEscCodeTable->CrEscSequenceCode[Index].TerminalType = TerminalEscCode->EscSequenceCode[Index].TerminalType;
|
|
CrEscCodeTable->CrEscSequenceCode[Index].Reserve = TerminalEscCode->EscSequenceCode[Index].Reserve;
|
|
CrEscCodeTable->CrEscSequenceCode[Index].DataType = TerminalEscCode->EscSequenceCode[Index].DataType;
|
|
Data = TranslateEfiScanCode(TerminalEscCode, Index);
|
|
|
|
CrEscCodeTable->CrEscSequenceCode[Index].Data = Data;
|
|
|
|
//
|
|
// Process ESC sequence code string
|
|
//
|
|
//[-start-180729-IB08400622-modify]//
|
|
UnicodeStrToAsciiStrS ((CONST CHAR16 *)TerminalEscCode->EscSequenceCode[Index].EscSequenceCode, AsciiStr, 128);
|
|
//[-end-180729-IB08400622-modify]//
|
|
StringLength = AsciiStrLen(AsciiStr);
|
|
pCrEscCode = (CHAR8 *) CrEfiMemAlloc (StringLength + 1);
|
|
if (pCrEscCode == NULL) {
|
|
ASSERT (0);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
CopyMem (pCrEscCode ,AsciiStr, StringLength + 1);
|
|
|
|
CrEscCodeTable->CrEscSequenceCode[Index].OffsetOfString = (UINT16)((UINTN)pCrEscCode - mCrMemStart);
|
|
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsCrOpROMDevice (
|
|
IN EFI_CONSOLE_REDIRECTION_DEVICE *CrDevice
|
|
)
|
|
{
|
|
return CrDevice->Uart16550protocol->DeviceInfo->LegacySupport;
|
|
}
|
|
|
|
/**
|
|
|
|
Fill Console Redirection Terminal device information to CR_EFI_INFO structure
|
|
|
|
@param CrPolicy Pointer to Console Redirection policy protocol
|
|
@param CRInfo Pointer to Console Redirection information structure
|
|
|
|
@retval EFI_SUCCESS Console Redirection Terminal device information fill success
|
|
@retval EFI_INVALID_PARAMETER Console Redirection Terminal device information fill fail
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FillCRInfo (
|
|
IN EFI_CONSOLE_REDIRECTION_INFO *CRInfo
|
|
)
|
|
{
|
|
CR_EFI_INFO *CrEfiInfo;
|
|
CR_DEVICE *CRDevice;
|
|
UINT8 UartProtocol;
|
|
UINTN CRInfoSize;
|
|
UINTN Index;
|
|
UINTN CrOpromDevNum;
|
|
UINTN DevCount;
|
|
UART_16550_DEVICE_INFO *UartDevInfo;
|
|
|
|
if (CRInfo == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
UartProtocol = 0;
|
|
if (mCrPolicy.GlobalDataBits == CR_DATA_8BIT) {
|
|
UartProtocol = UART_DATA_BITS_8;
|
|
} else {
|
|
UartProtocol = UART_DATA_BITS_7;
|
|
}
|
|
|
|
if (mCrPolicy.GlobalStopBits == CR_STOP_2BIT) {
|
|
UartProtocol |= UART_STOP_BITS_2;
|
|
}
|
|
|
|
switch (mCrPolicy.GlobalParity) {
|
|
case CR_PARITY_EVEN:
|
|
UartProtocol |= UART_PARITY_EVEN;
|
|
break;
|
|
|
|
case CR_PARITY_ODD:
|
|
UartProtocol |= UART_PARITY_ODD;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Count CR legacy support device
|
|
//
|
|
CrOpromDevNum = 0;
|
|
for (Index = 0; Index < CRInfo->DeviceCount; Index++) {
|
|
if ( IsCrOpROMDevice (&(CRInfo->CRDevice[Index])) ) {
|
|
CrOpromDevNum++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Caculate memory size that CRINFO need
|
|
//
|
|
CRInfoSize = sizeof(CR_EFI_INFO) + CrOpromDevNum * sizeof(CR_DEVICE);
|
|
|
|
//
|
|
// Allocate memory from CR Efi Memory Manager
|
|
//
|
|
CrEfiInfo = (CR_EFI_INFO *) CrEfiMemAlloc (CRInfoSize);
|
|
if (CrEfiInfo == NULL) {
|
|
ASSERT (0);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
CrEfiInfo->Signature = SIGNATURE_16 ('C', 'R');
|
|
CrEfiInfo->Revision = CR_INFO_REVISION;
|
|
CrEfiInfo->HLength = sizeof (CR_EFI_INFO);
|
|
CrEfiInfo->DeviceCount = (UINT8)CrOpromDevNum;
|
|
CRDevice = (CR_DEVICE *)((UINT8 *)CrEfiInfo + sizeof(CR_EFI_INFO));
|
|
|
|
for (DevCount = 0, Index = 0; Index < CRInfo->DeviceCount; Index++) {
|
|
if ( !IsCrOpROMDevice (&(CRInfo->CRDevice[Index])) ) {
|
|
continue;
|
|
}
|
|
UartDevInfo = CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo;
|
|
CRDevice[DevCount].Type = UartDevInfo->DeviceType;
|
|
CRDevice[DevCount].BaudRateDivisor = CRInfo->CRDevice[Index].BaudRateDivisor;
|
|
CRDevice[DevCount].BaudRate = (UINT32)(UartDevInfo->SerialClockFreq / UartDevInfo->SampleRate / CRDevice[DevCount].BaudRateDivisor);
|
|
CRDevice[DevCount].UartUid = UartDevInfo->UartUid;
|
|
CRDevice[DevCount].FlowControl = SupportFlowControl(CRInfo->CRDevice[Index].DevicePath);
|
|
|
|
if (CRInfo->CRDevice[Index].Type == ISA_SERIAL_DEVICE) {
|
|
CRDevice[DevCount].Device.IsaSerial.ComPortAddress = (UINT16)CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->BaseAddress;
|
|
CRDevice[DevCount].Device.IsaSerial.ComPortIrq = CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->DevIRQ;
|
|
|
|
} else if (CRInfo->CRDevice[Index].Type == PCI_SERIAL_DEVICE) {
|
|
CRDevice[DevCount].Device.PciSerial.Bus = GET_BUS(CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->UID);
|
|
CRDevice[DevCount].Device.PciSerial.Device = GET_DEV(CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->UID);
|
|
CRDevice[DevCount].Device.PciSerial.Function = GET_FUN(CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo->UID);
|
|
|
|
} else if (CRInfo->CRDevice[Index].Type == PCI_HS_SERIAL_DEVICE) {
|
|
|
|
CRDevice[DevCount].Device.PciHsSerial.Bus = GET_BUS(UartDevInfo->UID);
|
|
CRDevice[DevCount].Device.PciHsSerial.Device = GET_DEV(UartDevInfo->UID);
|
|
CRDevice[DevCount].Device.PciHsSerial.Function = GET_FUN(UartDevInfo->UID);
|
|
CRDevice[DevCount].Device.PciHsSerial.AccessWidth = UartDevInfo->RegisterByteWidth;
|
|
|
|
} else if (CRInfo->CRDevice[Index].Type == PCH_HS_SERIAL_DEVICE) {
|
|
CRDevice[DevCount].Device.PchHsSerial.BaseAddr_Irq = (UINT32)(UartDevInfo->BaseAddress + UartDevInfo->DevIRQ);
|
|
CRDevice[DevCount].Device.PchHsSerial.AccessWidth = UartDevInfo->RegisterByteWidth;
|
|
}
|
|
|
|
DevCount++;
|
|
}
|
|
|
|
CrEfiInfo->BaudRateDivisor = mBaudRateDivisor[mCrPolicy.GlobalBaudRate];
|
|
CrEfiInfo->TerminalType = gTerminalFlagTable[mCrPolicy.GlobalTerminalType];
|
|
CrEfiInfo->Protocol = UartProtocol;
|
|
CrEfiInfo->FIFOLength = mCrPolicy.CRFifoLength;
|
|
CrEfiInfo->InfoWaitTime = mCrPolicy.CRInfoWaitTime;
|
|
CrEfiInfo->CRWriteCharInterval = mCrPolicy.CRWriteCharInterval;
|
|
CrEfiInfo->ShowHelp = mCrPolicy.Feature.Bit.CRShowHelp;
|
|
CrEfiInfo->CRAfterPost = mCrPolicy.Feature.Bit.CRAfterPost;
|
|
CrEfiInfo->CRHeadlessVBuffer = mCrPolicy.Feature.Bit.CRHeadlessVBuffer;
|
|
CrEfiInfo->FeatureFlag = mCrPolicy.Feature.Data16;
|
|
CrEfiInfo->SmiPort = PcdGet16 (PcdSoftwareSmiPort);
|
|
CrEfiInfo->CrsSmi = PcdGet8 (PcdH2OCrSoftwareSmi);
|
|
|
|
//
|
|
// Set Headless flag to notify serial OPROM. (H:Headless V:Vga card)
|
|
//
|
|
if (CRInfo->Headless == TRUE) {
|
|
CrEfiInfo->Headless = 'H';
|
|
} else {
|
|
CrEfiInfo->Headless = 'V';
|
|
}
|
|
|
|
FillTerminalEscCode (CrEfiInfo);
|
|
|
|
FillCrSpecialCommandTable (CrEfiInfo);
|
|
|
|
BDA_DATA(CR_MEM_MANAGER, UINT16) = (UINT16) mCrMemStart;
|
|
|
|
BDA_DATA(CR_CRINFO, UINT16) = (UINT16)((UINTN)CrEfiInfo - mCrMemStart);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Load Console Redirection Option ROM
|
|
|
|
@param CrPolicy Pointer to Console Redirection policy protocol
|
|
|
|
@retval EFI_SUCCESS Console Redirection Option ROM load success
|
|
@retval EFI_UNSUPPORTED Console Redirection Option ROM load fail
|
|
|
|
**/
|
|
EFI_STATUS
|
|
LoadOpRomImage (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *LocalRomImage;
|
|
UINTN LocalRomSize;
|
|
UINTN Flags;
|
|
EFI_IA32_REGISTER_SET RegisterSet;
|
|
VOID *LegacyRegion;
|
|
UINT16 Legacy16CallSegment;
|
|
UINT16 Legacy16CallOffset;
|
|
|
|
LocalRomSize = 0;
|
|
LocalRomImage = NULL;
|
|
Status = GetSectionFromAnyFv (
|
|
PcdGetPtr(PcdH2OCrOpRomFile),
|
|
EFI_SECTION_RAW,
|
|
0,
|
|
&LocalRomImage,
|
|
&LocalRomSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (LocalRomImage != NULL || LocalRomSize != 0) {
|
|
|
|
if (mCrPolicy.Feature.Bit.CROpROMLoadOnESegment == TRUE) {
|
|
|
|
//
|
|
// Get space from E-Seg for CrOpROM
|
|
//
|
|
Status = mLegacyBios->GetLegacyRegion (
|
|
mLegacyBios,
|
|
LocalRomSize,
|
|
0,
|
|
0x200,
|
|
&LegacyRegion
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
ASSERT_EFI_ERROR(Status);
|
|
return Status;
|
|
}
|
|
//
|
|
// Copy CrOpROM to reserved space in E-Seg
|
|
//
|
|
Status = mLegacyBios->CopyLegacyRegion (
|
|
mLegacyBios,
|
|
LocalRomSize,
|
|
LegacyRegion,
|
|
(VOID *)(UINTN)LocalRomImage
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
ASSERT_EFI_ERROR(Status);
|
|
return Status;
|
|
}
|
|
|
|
EBDA_DATA(BIOS_PHASE, UINT8) = BIOS_PHASE_OPROM;
|
|
EnableSerialInterrupt ();
|
|
|
|
ZeroMem (&RegisterSet, sizeof (RegisterSet));
|
|
Legacy16CallSegment = (UINT16) (((UINTN)LegacyRegion) >> 4);
|
|
Legacy16CallOffset = 0x0003;
|
|
Status = mLegacyBios->FarCall86 (
|
|
mLegacyBios,
|
|
Legacy16CallSegment,
|
|
Legacy16CallOffset,
|
|
&RegisterSet,
|
|
NULL,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR(Status);
|
|
|
|
DisableSerialInterrupt ();
|
|
EBDA_DATA(BIOS_PHASE, UINT8) = BIOS_PHASE_INIT;
|
|
} else {
|
|
Status = mLegacyBios->InstallPciRom (
|
|
mLegacyBios,
|
|
NULL,
|
|
&LocalRomImage,
|
|
&Flags,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR(Status);
|
|
}
|
|
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
Set Terminal mode to 80x25 or restore text mode in efi
|
|
|
|
@param SetMode0 TRUE : Set mode0 (80x25)
|
|
FALSE : Restore Termainl mode.
|
|
|
|
**/
|
|
VOID
|
|
SetTerminalModeForLegacy (
|
|
BOOLEAN SetMode0
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH *DPath;
|
|
EFI_HANDLE TerminalHandle;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;
|
|
|
|
for (Index = 0; Index < gCrInfo->DeviceCount; Index++) {
|
|
DPath = gCrInfo->CRDevice[Index].DevicePath;
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
&DPath,
|
|
&TerminalHandle
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (TerminalHandle, &gEfiSimpleTextOutProtocolGuid, &SimpleTextOutput);
|
|
if (EFI_ERROR(Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (SetMode0) {
|
|
gCrInfo->CRDevice[Index].TextMode = SimpleTextOutput->Mode->Mode;
|
|
SimpleTextOutput->SetMode (SimpleTextOutput, 0);
|
|
} else {
|
|
SimpleTextOutput->SetMode (SimpleTextOutput, gCrInfo->CRDevice[Index].TextMode);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
Notify function for LegacyBoot event be invoked
|
|
|
|
@param Event The Event that is being processed
|
|
@param Context The Event Context
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
LegacyBootNotifyFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT16 *BdaEBdaOffset;
|
|
UINT16 EBdaSegment;
|
|
UINT8 *pBiosPhase;
|
|
|
|
//
|
|
// End of POST time for console redirection
|
|
//
|
|
BdaEBdaOffset = (UINT16 *)(UINTN)BDA_EBDA_OFFSET;
|
|
EBdaSegment = *BdaEBdaOffset;
|
|
pBiosPhase = (UINT8 *)(UINTN)(((UINT32)EBdaSegment << SEGMENT_SHIFT) + BIOS_PHASE);
|
|
*pBiosPhase = BIOS_PHASE_OS;
|
|
|
|
SetTerminalModeForLegacy (TRUE);
|
|
|
|
EnableSerialInterrupt ();
|
|
|
|
gBS->CloseEvent (mLegacyBootEvent);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
|
|
Set text mode or restore original video mode.
|
|
|
|
@param DeviceHandle Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
|
|
@param SwitchMode Switch to text mode or restore original mode.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
SwitchVideoMode (
|
|
IN EFI_HANDLE DeviceHandle,
|
|
IN BOOLEAN SwitchMode
|
|
)
|
|
{
|
|
EFI_IA32_REGISTER_SET RegisterSet;
|
|
BOOLEAN ForceSwitchTextMode;
|
|
static UINT16 VideoOriginalMode;
|
|
|
|
if (SwitchMode == SWITCH_TEXT_MODE) {
|
|
|
|
ForceSwitchTextMode = TRUE;
|
|
//
|
|
// Check platform & oem policy for 'ForceSwitchTextMode'.
|
|
//
|
|
DxeCsSvcInstallPciRomSwitchTextMode (DeviceHandle, &ForceSwitchTextMode);
|
|
DEBUG ((DEBUG_INFO, "Cr << %a >> DxeChipsetService() SwitchTextMode:%d\n", __FUNCTION__, ForceSwitchTextMode));
|
|
|
|
//
|
|
// OemServices
|
|
//
|
|
OemSvcInstallPciRomSwitchTextMode (DeviceHandle, &ForceSwitchTextMode);
|
|
DEBUG ((DEBUG_INFO, "Cr << %a >> OemService() SwitchTextMode:%d\n", __FUNCTION__, ForceSwitchTextMode));
|
|
|
|
if (ForceSwitchTextMode) {
|
|
//
|
|
// Save Original VESA Vedio Mode
|
|
//
|
|
VideoOriginalMode = MAX_UINT16;
|
|
RegisterSet.X.AX = VESA_GET_MODE;
|
|
RegisterSet.X.BX = 0;
|
|
mLegacyBios->Int86 (mLegacyBios, INT_10, &RegisterSet);
|
|
|
|
if (RegisterSet.H.AL == VESA_SUPPORTED && RegisterSet.X.BX != VGA_TEXT_MODE) {
|
|
VideoOriginalMode = RegisterSet.X.BX;
|
|
//
|
|
// Set the 80x25 Text VGA Mode before dispatch CRS ROM
|
|
//
|
|
RegisterSet.H.AH = VGA_SET_MODE;
|
|
RegisterSet.H.AL = VGA_TEXT_MODE;
|
|
mLegacyBios->Int86 (mLegacyBios, INT_10, &RegisterSet);
|
|
} else {
|
|
DEBUG ((DEBUG_WARN,
|
|
"\nCr << %a >> Do not save the original video mode. VESA_SUPPORTED:0x%x, Mode:0x%x\n",
|
|
__FUNCTION__,
|
|
RegisterSet.X.AX,
|
|
RegisterSet.X.BX
|
|
));
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
if (VideoOriginalMode != MAX_UINT16) {
|
|
//
|
|
// Restore Original Vedio Mode
|
|
//
|
|
RegisterSet.X.AX = VESA_SET_MODE;
|
|
RegisterSet.X.BX = VideoOriginalMode;
|
|
mLegacyBios->Int86 (mLegacyBios, INT_10, &RegisterSet);
|
|
DEBUG ((DEBUG_INFO, "Cr << %a >> Restore Original Vedio Mode:0x%x\n", __FUNCTION__, VideoOriginalMode));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
|
|
Allows Console Redirection perform specific required action after a LegacyBios operation.
|
|
|
|
@param This The protocol instance pointer
|
|
@param Mode Will bypass to next caller
|
|
@param Type Will bypass to next caller
|
|
@param DeviceHandle Will bypass to next caller
|
|
@param ShadowAddress Will bypass to next caller
|
|
@param Compatibility16Table Will bypass to next caller
|
|
@param AdditionalData Will bypass to next caller
|
|
|
|
@retval EFI_SUCCESS The operation performed successfully.
|
|
@retval EFI_UNSUPPORTED Mode is not supported on the platform.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CrsPlatformHooks (
|
|
IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
|
|
IN EFI_GET_PLATFORM_HOOK_MODE Mode,
|
|
IN UINT16 Type,
|
|
IN EFI_HANDLE DeviceHandle,
|
|
IN OUT UINTN *ShadowAddress,
|
|
IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table,
|
|
IN VOID **AdditionalData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsCrRom;
|
|
|
|
IsCrRom = IS_CRROM(ShadowAddress)? TRUE: FALSE;
|
|
|
|
//
|
|
// If not CROpRom, execute original LegacyBios function for setup legacy environment.
|
|
//
|
|
if (!IsCrRom) {
|
|
Status = mPlatformHooks (This, Mode, Type, DeviceHandle, ShadowAddress, Compatibility16Table, AdditionalData);
|
|
if (EFI_ERROR(Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
switch (Mode) {
|
|
|
|
case EfiPlatformHookPrepareToScanRom:
|
|
|
|
if (IsCrRom) {
|
|
SwitchVideoMode (DeviceHandle, SWITCH_TEXT_MODE);
|
|
}
|
|
|
|
SetTerminalModeForLegacy (TRUE);
|
|
//
|
|
// Set flag for CRS before Oprom runing
|
|
//
|
|
EBDA_DATA(BIOS_PHASE, UINT8) = BIOS_PHASE_OPROM;
|
|
|
|
EnableSerialInterrupt ();
|
|
break;
|
|
|
|
case EfiPlatformHookShadowServiceRoms:
|
|
break;
|
|
|
|
case EfiPlatformHookAfterRomInit:
|
|
|
|
DisableSerialInterrupt ();
|
|
//
|
|
// Set flag for CRS after Oprom runing
|
|
//
|
|
EBDA_DATA(BIOS_PHASE, UINT8) = BIOS_PHASE_INIT;
|
|
SetTerminalModeForLegacy (FALSE);
|
|
|
|
if (IsCrRom) {
|
|
SwitchVideoMode (DeviceHandle, SWITCH_ORIGINAL_MODE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Confirm AB segment can be accessed
|
|
|
|
@retval EFI_SUCCESS AB segment can be accessed.
|
|
@retval EFI_ACCESS_DENIED AB segment can not be accessed.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AbSegAccessConfirm (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 RestoreData;
|
|
UINT8 *pVBuffer;
|
|
UINT8 Data[2];
|
|
UINT8 Index;
|
|
|
|
RestoreData = 0;
|
|
Data[0] = 0x55;
|
|
Data[1] = 0xAA;
|
|
pVBuffer = (UINT8 *)((UINTN)(TEXT_PAGE_0_START));
|
|
|
|
CopyMem (&RestoreData, pVBuffer, sizeof (UINT8));
|
|
|
|
for (Index = 0; Index < 2; Index++) {
|
|
|
|
CopyMem (pVBuffer, &Data[Index], sizeof (UINT8));
|
|
if (CompareMem (pVBuffer, &Data[Index], sizeof (UINT8)) != 0) {
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
CopyMem (pVBuffer, &RestoreData, sizeof (UINT8));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PutDeviceInfoToSmm (
|
|
UINTN DeviceCount,
|
|
UART_16550_DEVICE_INFO *DeviceBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_CONTROL2_PROTOCOL *SmmControl2;
|
|
UINT8 SmiFuncNo;
|
|
UINT8 SmiData;
|
|
|
|
Status = CommonSetVariable (
|
|
CR_UART_DEVICE_INFO_VAR_NAME,
|
|
&gH2OConsoleRedirectionServiceProtocolGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
|
DeviceCount * sizeof(UART_16550_DEVICE_INFO),
|
|
DeviceBuffer
|
|
);
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, &SmmControl2);
|
|
if (EFI_ERROR(Status)) {
|
|
ASSERT (FALSE);
|
|
return Status;
|
|
}
|
|
|
|
SmiFuncNo = PcdGet8 (PcdH2OCrSoftwareSmi);
|
|
|
|
//
|
|
// The SmiData is for pass Wellsburg RC code. It need pass the SmiData and value must be 1
|
|
//
|
|
SmiData = 1;
|
|
|
|
Status = SmmControl2->Trigger (SmmControl2, &SmiFuncNo, &SmiData, FALSE, 0);
|
|
if (EFI_ERROR(Status)) {
|
|
ASSERT (FALSE);
|
|
return Status;
|
|
}
|
|
|
|
//- Status = CommonSetVariable (
|
|
//- CR_UART_DEVICE_INFO_VAR_NAME,
|
|
//- &gH2OConsoleRedirectionServiceProtocolGuid,
|
|
//- 0,
|
|
//- 0,
|
|
//- NULL
|
|
//- );
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CrSmmPutCRInfo (
|
|
EFI_CONSOLE_REDIRECTION_INFO *CRInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BufferSize;
|
|
VOID *Buffer;
|
|
UART_16550_DEVICE_INFO *DeviceInfo;
|
|
UINTN Index;
|
|
|
|
|
|
BufferSize = CRInfo->DeviceCount * sizeof (UART_16550_DEVICE_INFO);
|
|
Status = gBS->AllocatePool ( EfiRuntimeServicesData, BufferSize, &Buffer);
|
|
if (EFI_ERROR(Status)) {
|
|
ASSERT(FALSE);
|
|
return;
|
|
}
|
|
|
|
DeviceInfo = (UART_16550_DEVICE_INFO *) Buffer;
|
|
for (Index =0; Index < CRInfo->DeviceCount; Index++, DeviceInfo++) {
|
|
CopyMem (DeviceInfo, CRInfo->CRDevice[Index].Uart16550protocol->DeviceInfo, sizeof(UART_16550_DEVICE_INFO));
|
|
}
|
|
|
|
PutDeviceInfoToSmm ( CRInfo->DeviceCount, Buffer);
|
|
|
|
gBS->FreePool (Buffer);
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
CrOpRomSupport (
|
|
EFI_CONSOLE_REDIRECTION_INFO *CRInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
|
|
UINT16 *pVgaBuffer;
|
|
UINT16 TextElement;
|
|
UINTN TextCount;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL,(VOID **) &mRootBridgeIo);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR(Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check Console Redirection is Enable or Disable
|
|
//
|
|
Status = gBS->LocateProtocol (&gH2OConsoleRedirectionServiceProtocolGuid, NULL, (VOID **)&gCrService);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR(Status);
|
|
return Status;
|
|
}
|
|
|
|
if (gCrService->CRInfo == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
} else {
|
|
gCrInfo = gCrService->CRInfo;
|
|
}
|
|
|
|
//
|
|
// Get LegacyBiosProtocol for Load Serial Redirect Oprom
|
|
//
|
|
Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **)&mLegacyBios);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Hook in LegacyBiosPlatform to do update BiosPhase Flag
|
|
//
|
|
if (mLegacyBiosPlatformProtocol == NULL) {
|
|
Status = gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, (VOID **)&mLegacyBiosPlatformProtocol);
|
|
ASSERT_EFI_ERROR(Status);
|
|
if (!EFI_ERROR(Status)) {
|
|
mPlatformHooks = mLegacyBiosPlatformProtocol->PlatformHooks;
|
|
mLegacyBiosPlatformProtocol->PlatformHooks = CrsPlatformHooks;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If Headless , Enable AB segment
|
|
//
|
|
if (mHeadless && (mCrPolicy.Feature.Bit.CRHeadlessVBuffer == CR_HEADLESS_USE_VBUFFER)) {
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
Status = SmmAccess->Open (SmmAccess);
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
Status = AbSegAccessConfirm ();
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
//
|
|
// Initialize VGA buffer (B8000 ~ B9000) for Option Rom ,EX: SCSI , PXE ... etc.
|
|
//
|
|
TextElement = CHAR_SPACE | ((COLOR_BG_BLACK | COLOR_FG_WHITE) << 8);
|
|
pVgaBuffer = (UINT16 *)((UINTN)(TEXT_PAGE_0_START));
|
|
TextCount = 0;
|
|
do {
|
|
*pVgaBuffer = TextElement;
|
|
pVgaBuffer++;
|
|
TextCount++;
|
|
} while (TextCount < TEXT_PAGE_SIZE / 2);
|
|
DEBUG ((DEBUG_INFO | DEBUG_ERROR, "\nConsole Redirection : Usb AB Segment as VBuffer in Headless system\n" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If CAN NOT use AB segment(VBuffer) be used, auto change to use EBDA space
|
|
//
|
|
if (EFI_ERROR (Status)) {
|
|
mCrPolicy.Feature.Bit.CRHeadlessVBuffer = CR_HEADLESS_USE_EBDA;
|
|
DEBUG ((DEBUG_INFO | DEBUG_ERROR, "\nConsole Redirection : Usb EBDA as VBuffer in Headless system\n" ) );
|
|
}
|
|
}
|
|
|
|
mCrOpROMInfo.CrOpROMInstalled = FALSE;
|
|
mCrOpROMInfo.CrGetCommonArea = GetCrCommonArea;
|
|
mCrOpROMInfo.CrGetUartUid = CrGetUartUid;
|
|
//
|
|
// Install CROpROMInfo Protocol for Cr Usb terminal reference
|
|
//
|
|
gBS->InstallProtocolInterface (
|
|
&mCrServiceImageHandle,
|
|
&gH2OCrOpRomInfoProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mCrOpROMInfo
|
|
);
|
|
|
|
//
|
|
// Fill CRInfo in CrEfiMemory space. That hand off CRInfo to Option Rom.
|
|
//
|
|
FillCRInfo (gCrInfo);
|
|
|
|
//
|
|
// Legacy ROM need support MMIO, MMIO need Smm driver support. this information is for SMM driver consume.
|
|
//
|
|
CrSmmPutCRInfo ( CRInfo);
|
|
|
|
//
|
|
// Load Console Redirection Option ROM
|
|
//
|
|
Status = LoadOpRomImage ();
|
|
if (Status == EFI_SUCCESS) {
|
|
mCrOpROMInfo.CrOpROMInstalled = TRUE;
|
|
|
|
//
|
|
// When After Post time, we must notify OPRom to work and close SMM AB segment.
|
|
//
|
|
EfiCreateEventLegacyBootEx (TPL_NOTIFY, LegacyBootNotifyFunction, NULL, &mLegacyBootEvent);
|
|
}
|
|
|
|
//
|
|
// Load OpROM complete, free CREfiMemory space
|
|
//
|
|
FreeCrEfiMemorySpace ();
|
|
|
|
return Status;
|
|
}
|
|
|