/** @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 #include #include #include #include #include #include #include #include #include //#include #include #include #include #include // // 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); }