513 lines
18 KiB
C
513 lines
18 KiB
C
/** @file
|
|
This driver is for providing the Int15 callback service routines. It is a
|
|
SMM driver. Operations (HOOKS) are assigned (divided) by different Function
|
|
Numbers. Meanings and definitions of those Function Numbers can be found in
|
|
the VBIOS Spec. Purpose of this driver is trying to provide Programmers the
|
|
template to conduct the INT15 Hook services as they wish.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2014 - 2018, Insyde Software Corporation. 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 <Uefi.h>
|
|
#include <ChipsetAccess.h>
|
|
#include <ChipsetSetupConfig.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/SmmServicesTableLib.h>
|
|
#include <Protocol/SetupUtility.h>
|
|
#include <Protocol/SmmInt15Service.h>
|
|
#include <Protocol/LegacyBios.h>
|
|
#include <Library/SmmOemSvcChipsetLib.h>
|
|
#include <Library/DebugLib.h>
|
|
//#include <Library/EcLib.h>
|
|
#include <Library/BaseOemSvcChipsetLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/VariableLib.h>
|
|
|
|
//
|
|
// INT15 HOOK NUMBER
|
|
//
|
|
#define INT15_GET_UPDATE_SYSTEM_BIOS_STATE 0x5F14
|
|
#define INT15_SET_PANEL_FITTING_HOOK 0x5F34
|
|
#define INT15_BOOT_DISPLAY_DEVICE_HOOK 0x5F35
|
|
#define INT15_BOOT_PANEL_TYPE_HOOK 0x5F40
|
|
#define INT15_HOOK_TO_GET_INVERTER_TYPE_AND_POLARITY_FOR_BACKLIGHT 0x5F49
|
|
#define INT15_HOOK_TO_ENABLE_SQUELCH_REGISTER_FOR_EDP 0x5F50
|
|
#define INT15_HOOK_TO_SELECT_ACTIVE_LFP_CONFIGURATION 0x5F51
|
|
#define INT15_HOOK_TO_GET_PANEL_COLOR_DEPTH_FORM_SETUP 0x5F52
|
|
|
|
#define GET_MISCELLANEOUS_STATUS_HOOK 0x078F
|
|
|
|
#define NO_LVDS 0x00
|
|
#define INT_LVDS 0x01
|
|
#define SDVO_LVDS 0x02
|
|
#define EDP 0x03
|
|
#define NO_HOOK 0xFF
|
|
|
|
//
|
|
// INT15 Service Function HOOK
|
|
// This array stores all the requested INT15 Hook Function Numbers that will
|
|
// be installed (registered) later. Detain meanings of such Function Numbers
|
|
// can be found in VBIOS Spec. Ex: 0x5F14 is "Get/Update System BIOS State"
|
|
//
|
|
#define INT15_VBIOS_FUNCTION_HOOK_LIST \
|
|
INT15_GET_UPDATE_SYSTEM_BIOS_STATE, \
|
|
INT15_SET_PANEL_FITTING_HOOK, \
|
|
INT15_BOOT_DISPLAY_DEVICE_HOOK, \
|
|
INT15_BOOT_PANEL_TYPE_HOOK, \
|
|
INT15_HOOK_TO_GET_INVERTER_TYPE_AND_POLARITY_FOR_BACKLIGHT, \
|
|
INT15_HOOK_TO_ENABLE_SQUELCH_REGISTER_FOR_EDP, \
|
|
INT15_HOOK_TO_SELECT_ACTIVE_LFP_CONFIGURATION, \
|
|
INT15_HOOK_TO_GET_PANEL_COLOR_DEPTH_FORM_SETUP
|
|
|
|
VOID
|
|
VbiosHookCallBack (
|
|
IN OUT EFI_IA32_REGISTER_SET *CpuRegs,
|
|
IN VOID *Context
|
|
);
|
|
|
|
CHIPSET_CONFIGURATION *mSetupVariable;
|
|
UINT16 mIgdBootType;
|
|
UINT8 mLcdPanelType;
|
|
UINT8 mLcdPanelScaling;
|
|
UINT8 mVideoBootType;
|
|
UINT8 mDisplayPipeB;
|
|
UINT8 mBacklightType;
|
|
UINT8 mActiveLFP;
|
|
UINT8 mLfpColorDepth;
|
|
UINT8 mPrimaryDisplay;
|
|
UINT8 mVbiosBrightness;
|
|
|
|
STATIC UINT16 mInt15VbiosFunctionHook[] = {INT15_VBIOS_FUNCTION_HOOK_LIST};
|
|
|
|
/**
|
|
Initializes the SMM Dispatcher for VBIOS INT15 HOOK Services.
|
|
|
|
@param ImageHandle Pointer to the loaded image protocol for this driver.
|
|
@param SystemTable Pointer to the EFI System Table.
|
|
|
|
@return Status EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VbiosHookEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
EFI_SMM_INT15_SERVICE_PROTOCOL *SmmInt15Service;
|
|
UINT16 *OemInt15VbiosFunctionHook;
|
|
UINT16 Size;
|
|
SA_SETUP *SaSetup;
|
|
UINTN SaSetupSize;
|
|
|
|
Size = 0;
|
|
SmmInt15Service = NULL;
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiSmmInt15ServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **)&SmmInt15Service
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SaSetupSize = sizeof (SA_SETUP);
|
|
Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, SaSetupSize, (VOID **) &SaSetup);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Status = gRT->GetVariable (
|
|
SA_SETUP_VARIABLE_NAME,
|
|
&gSaSetupVariableGuid,
|
|
NULL,
|
|
&SaSetupSize,
|
|
SaSetup
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
gSmst->SmmFreePool (SaSetup);
|
|
return Status;
|
|
} else {
|
|
mLcdPanelType = SaSetup->LcdPanelType;
|
|
mLcdPanelScaling = SaSetup->LcdPanelScaling;
|
|
mIgdBootType = SaSetup->IgdBootType;
|
|
mDisplayPipeB = SaSetup->DisplayPipeB;
|
|
mBacklightType = SaSetup->IgdLcdBlc;
|
|
mActiveLFP = SaSetup->ActiveLFP;
|
|
mLfpColorDepth = SaSetup->LfpColorDepth;
|
|
mPrimaryDisplay = SaSetup->PrimaryDisplay;
|
|
mVbiosBrightness = SaSetup->VbiosBrightness;
|
|
gSmst->SmmFreePool (SaSetup);
|
|
}
|
|
|
|
for (Index = 0; Index < sizeof (mInt15VbiosFunctionHook) / sizeof (UINT16); Index++) {
|
|
Status = SmmInt15Service->InstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
mInt15VbiosFunctionHook[Index],
|
|
VbiosHookCallBack,
|
|
NULL
|
|
);
|
|
if (Status == EFI_ALREADY_STARTED) {
|
|
//
|
|
// use new callback function to replace original one
|
|
//
|
|
Status = SmmInt15Service->ReinstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
mInt15VbiosFunctionHook[Index],
|
|
VbiosHookCallBack,
|
|
NULL
|
|
);
|
|
return Status;
|
|
}
|
|
}
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Smm OemChipsetServices Call: OemSvcGetOemInt15VbiosFunctionlist \n"));
|
|
Status = OemSvcGetOemInt15VbiosFunctionlist (&OemInt15VbiosFunctionHook, &Size);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Smm OemChipsetServices OemSvcGetOemInt15VbiosFunctionlist Status: %r\n", Status));
|
|
if (Status == EFI_MEDIA_CHANGED){
|
|
for (Index = 0; Index < Size; Index++) {
|
|
Status = SmmInt15Service->InstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
OemInt15VbiosFunctionHook[Index],
|
|
VbiosHookCallBack,
|
|
NULL
|
|
);
|
|
if (Status == EFI_ALREADY_STARTED) {
|
|
//
|
|
// use new callback function to replace original one
|
|
//
|
|
Status = SmmInt15Service->ReinstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
OemInt15VbiosFunctionHook[Index],
|
|
VbiosHookCallBack,
|
|
NULL
|
|
);
|
|
return Status;
|
|
}
|
|
}
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
INT15 Callback Routine. It contains several INT15 Services corresponding
|
|
to specific Function Number such as 0x5F49 for Backlight Brightness.
|
|
|
|
@param CpuRegs The structure containing CPU Registers (AX, BX, CX, DX etc.).
|
|
@param Context Context.
|
|
|
|
@return None
|
|
|
|
Components of CpuRegs
|
|
CX - For most Settings (Configurations) described in the VBIOS Spec
|
|
BX - In most casess, it is a calling register. It also can be used
|
|
as a return (for Settings/Configurations) register like CX
|
|
AX - Indicate the Status of Function Supported Fail/Success
|
|
|
|
**/
|
|
VOID
|
|
VbiosHookCallBack (
|
|
IN OUT EFI_IA32_REGISTER_SET *CpuRegs,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT32 Int15FunNum;
|
|
UINT32 EdpRegister;
|
|
BOOLEAN LidIsOpen;
|
|
EFI_STATUS Status;
|
|
EFI_STATUS EcGetLidState;
|
|
|
|
LidIsOpen = TRUE;
|
|
Status = EFI_SUCCESS;
|
|
EcGetLidState = EFI_SUCCESS;
|
|
|
|
//
|
|
// GET THE INT15 FUNCTION NUMBER
|
|
//
|
|
Int15FunNum = (CpuRegs->X.AX & 0xFFFF);
|
|
if (!Int15FunNum) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// SWITCH CASE Used For Applying Different HOOK
|
|
// corresponding to the Function Number
|
|
//
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Smm OemChipsetServices Call: OemSvcVbiosHookCallBack \n"));
|
|
Status = OemSvcVbiosHookCallBack(Int15FunNum, CpuRegs, Context);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Smm OemChipsetServices OemSvcVbiosHookCallBack Status: %r\n", Status));
|
|
if (Status == EFI_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
mSetupVariable = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
|
|
if (mSetupVariable == NULL) {
|
|
return;
|
|
}
|
|
|
|
switch (Int15FunNum) {
|
|
case INT15_GET_UPDATE_SYSTEM_BIOS_STATE :
|
|
//
|
|
// VBIOS : Get Miscellaneous Status Hook
|
|
//
|
|
// Calling Registers:
|
|
//
|
|
// AX = 5F14h, System BIOS State Hook
|
|
// BX = 078Fh, Get Miscellaneous Status
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 015Fh, Function supported but failed
|
|
// = 005Fh, Function supported and successful
|
|
// CL = Bit map of dock, lid and AC status:
|
|
// Bits 7 - 3 = Reserved
|
|
// Bit 2 = 0, no AC power
|
|
// = 1, AC power active
|
|
// Bit 1 = 0, lid open
|
|
// = 1, lid closed
|
|
// Bit 0 = 0, not docked
|
|
// = 1, docked
|
|
//
|
|
if (CpuRegs->X.BX == GET_MISCELLANEOUS_STATUS_HOOK) {
|
|
CpuRegs->H.CL &= ~(0xff);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Base OemChipsetServices Call: OemSvcEcGetLidState \n"));
|
|
Status = OemSvcEcGetLidState (&EcGetLidState, &LidIsOpen);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "Base OemChipsetServices OemSvcEcGetLidState Status: %r\n", Status));
|
|
ASSERT (!EFI_ERROR (EcGetLidState));
|
|
|
|
CpuRegs->H.CL |= 0x04;
|
|
if (!EFI_ERROR (EcGetLidState)) {
|
|
if(!LidIsOpen) {
|
|
//
|
|
// If get lid state form EC successfully and lid is closed.
|
|
//
|
|
CpuRegs->H.CL |= BIT1;
|
|
}
|
|
}
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
}
|
|
break;
|
|
|
|
case INT15_SET_PANEL_FITTING_HOOK :
|
|
//
|
|
// VBIOS : Set Panel Fitting Hook
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// CL = Panel fitting flags (1 = Enable, 0 = Disable)
|
|
// = 00h, use video BIOS default
|
|
// Bits 7 - 3 = Reserved
|
|
// Bit 2 = Graphics Stretching
|
|
// Bit 1 = Text Stretching
|
|
// Bit 0 = Centering (Can not be set when Bit1 or Bit2 is set)
|
|
//
|
|
CpuRegs->H.CL &= ~(0xff);
|
|
CpuRegs->H.CL |= mLcdPanelScaling;
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
break;
|
|
|
|
case INT15_BOOT_DISPLAY_DEVICE_HOOK :
|
|
//
|
|
// VBIOS : Boot Display Device Hook
|
|
//
|
|
// Calling Registers:
|
|
//
|
|
// AX = 5F35h, Boot Display Device Hook
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh);
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// CL = Display Device Combination to boot (1 = Enable, 0 = Disable):
|
|
// = 00h, video BIOS Default
|
|
// Bit 7 = LFP2
|
|
// Bit 6 = EFP2
|
|
// Bit 5 = TV2
|
|
// Bit 4 = CRT2
|
|
// Bit 3 = LFP
|
|
// Bit 2 = EFP
|
|
// Bit 1 = TV
|
|
// Bit 0 = CRT
|
|
//
|
|
CpuRegs->H.CL &= ~(0xff);
|
|
CpuRegs->H.CL |= mIgdBootType;
|
|
if (mIgdBootType != 0) {
|
|
if (mIgdBootType == mDisplayPipeB) {
|
|
CpuRegs->H.CH = 0;
|
|
}
|
|
}
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
break;
|
|
|
|
case INT15_BOOT_PANEL_TYPE_HOOK :
|
|
//
|
|
// VBIOS : Boot Panel Type Hook
|
|
//
|
|
// Calling Registers:
|
|
//
|
|
// AX = 5F40h, Boot Panel Type Hook
|
|
// BL = Panel index
|
|
// = 00h, LFP
|
|
// = 01h, LFP2
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// CL = 1 - 16, Panel type (define in VBIOS Panel_#1 ~ Panel_#16)
|
|
//
|
|
CpuRegs->X.CX &= ~(0xffff);
|
|
CpuRegs->X.CX |= mLcdPanelType;
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported but failed
|
|
break;
|
|
|
|
case INT15_HOOK_TO_GET_INVERTER_TYPE_AND_POLARITY_FOR_BACKLIGHT :
|
|
//
|
|
// VBIOS : Hook to get Inverter Type and Polarity for Backlight
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// BX = 0-255, Initial backlight control brightness value
|
|
// CX = Return Parameter
|
|
// = 00h, Enable PWM -- Inverted
|
|
// = 01h, Enable I2C -- Inverted
|
|
// = 02h, Enable PWM -- Normal
|
|
// = 03h, Enable I2C -- Normal
|
|
//
|
|
CpuRegs->X.BX &= ~(0xffff);
|
|
CpuRegs->X.BX |= mVbiosBrightness;
|
|
CpuRegs->X.CX &= ~(0xffff);
|
|
CpuRegs->X.CX |= mBacklightType;
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
break;
|
|
|
|
|
|
case INT15_HOOK_TO_ENABLE_SQUELCH_REGISTER_FOR_EDP :
|
|
//
|
|
// Hook to Enable Squelch Register for eDP
|
|
//
|
|
// Calling Registers:
|
|
//
|
|
// AX = Hook to enable Squelch Register for eDP
|
|
//
|
|
// Return Registers:
|
|
//
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
//
|
|
// - In the 5F50h INT15h hook the SBIOS should program the registers as below
|
|
// - PCIEXBAR + 0x8dfc[1] = 1b
|
|
//
|
|
EdpRegister = McD1PciCfg32 (0xDFC);
|
|
EdpRegister |= BIT1;
|
|
McD1PciCfg32 (0xDFC) = EdpRegister;
|
|
//
|
|
// - PCIEXBAR + 0x8f88[31] = 1b
|
|
// - PCIEXBAR + 0x8f88[26] = 0b
|
|
//
|
|
EdpRegister = McD1PciCfg32 (0xF88);
|
|
EdpRegister |= BIT31;
|
|
EdpRegister &= ~BIT26;
|
|
McD1PciCfg32 (0xF88) = EdpRegister;
|
|
//
|
|
// - PCIEXBAR + 0x8fa8[31] = 1b
|
|
// - PCIEXBAR + 0x8fa8[26] = 0b
|
|
//
|
|
EdpRegister = McD1PciCfg32 (0xFA8);
|
|
EdpRegister |= BIT31;
|
|
EdpRegister &= ~BIT26;
|
|
McD1PciCfg32 (0xFA8) = EdpRegister;
|
|
//
|
|
// - PCIEXBAR + 0x8fc8[31] = 1b
|
|
// - PCIEXBAR + 0x8fc8[26] = 0b
|
|
//
|
|
EdpRegister = McD1PciCfg32 (0xFC8);
|
|
EdpRegister |= BIT31;
|
|
EdpRegister &= ~BIT26;
|
|
McD1PciCfg32 (0xFC8) = EdpRegister;
|
|
//
|
|
// - PCIEXBAR + 0x8fe8[31] = 1b
|
|
// - PCIEXBAR + 0x8fe8[26] = 0b
|
|
//
|
|
EdpRegister = McD1PciCfg32 (0xFE8);
|
|
EdpRegister |= BIT31;
|
|
EdpRegister &= ~BIT26;
|
|
McD1PciCfg32 (0xFE8) = EdpRegister;
|
|
//
|
|
// Return Success
|
|
//
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F;
|
|
break;
|
|
|
|
case INT15_HOOK_TO_SELECT_ACTIVE_LFP_CONFIGURATION :
|
|
//
|
|
// VBIOS : Hook to select Active LFP configuration
|
|
//
|
|
// Return Registers:
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// CX = Active LFP configuration selected in BIOS setup.
|
|
// = 00h, No LVDS, VBIOS does not enable LVDS.
|
|
// = 01h, Int-LVDS, LFP driven by Integrated LVDS encoder.
|
|
// = 02h, SDVO-LVDS, LFP driven by SDVO encoder.
|
|
// = 03h, eDP, LFP Driven by Int-DisplayPort encoder.
|
|
//
|
|
CpuRegs->X.CX &= ~(0xffff);
|
|
CpuRegs->X.CX |= mActiveLFP;
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
break;
|
|
|
|
case INT15_HOOK_TO_GET_PANEL_COLOR_DEPTH_FORM_SETUP :
|
|
//
|
|
// VBIOS : Hook to get Panel Color Depth from Setup
|
|
//
|
|
// Return Registers:
|
|
// AX = Return Status (function not supported if AL != 5Fh):
|
|
// = 005Fh, Function supported and successful
|
|
// = 015Fh, Function supported but failed
|
|
// CX = Return Parameter
|
|
// = 00h, 18 bit
|
|
// = 01h, 24 bit
|
|
//
|
|
CpuRegs->X.CX &= ~(0xffff);
|
|
CpuRegs->X.CX |= mLfpColorDepth;
|
|
CpuRegs->X.AX &= ~(0xffff);
|
|
CpuRegs->X.AX |= 0x005F; // Function supported and successful
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
FreePool (mSetupVariable);
|
|
}
|