287 lines
8.0 KiB
C
287 lines
8.0 KiB
C
/** @file
|
|
Wake On LAN from Dock for L05 Feature
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2020, 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 "WakeOnLanFromDock.h"
|
|
|
|
/**
|
|
Check is HDD security enable.
|
|
|
|
@param HddPasswordDialog A pointer to the EFI_HDD_PASSWORD_DIALOG_PROTOCOL.
|
|
|
|
@retval TRUE HDD security enable.
|
|
@retval FALSE HDD security disable.
|
|
**/
|
|
BOOLEAN
|
|
IsHddSecurityEnable (
|
|
IN EFI_HDD_PASSWORD_DIALOG_PROTOCOL *HddPasswordDialog
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HDD_PASSWORD_SERVICE_PROTOCOL *HddPasswordService;
|
|
HDD_PASSWORD_HDD_INFO *HddInfoArray;
|
|
UINTN NumOfHdd;
|
|
|
|
HddPasswordService = NULL;
|
|
HddInfoArray = NULL;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHddPasswordServiceProtocolGuid,
|
|
NULL,
|
|
&HddPasswordService
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get HDD info
|
|
//
|
|
Status = HddPasswordService->GetHddInfo (
|
|
HddPasswordService,
|
|
&HddInfoArray,
|
|
&NumOfHdd
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (NumOfHdd == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!HddPasswordDialog->CheckHddSecurityEnable (HddPasswordDialog, HddInfoArray, NumOfHdd)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Update Wake On LAN from Dock setting.
|
|
|
|
@param EnableDockWol TRUE - WOL from Dock is enable.
|
|
FALSE - WOL from Dock is disable.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateDsdtWoldNameSpace (
|
|
BOOLEAN EnableDockWol
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
|
|
INTN Index;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Table;
|
|
EFI_ACPI_TABLE_VERSION Version;
|
|
UINTN Handle;
|
|
UINT8 *CurrPtr;
|
|
UINT32 *Signature;
|
|
UINT8 *DsdtPointer;
|
|
CHAR8 *WoldStr;
|
|
|
|
AcpiSupport = NULL;
|
|
Index = 0;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **) &AcpiSupport);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Search for DSDT table
|
|
//
|
|
while (1) {
|
|
Status = AcpiSupport->GetAcpiTable (AcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
|
|
|
|
if (Status == EFI_NOT_FOUND) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Updates once the table found
|
|
//
|
|
if (Table->Signature == EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
|
|
//
|
|
// Point to the beginning of the DSDT table
|
|
//
|
|
CurrPtr = (UINT8 *) Table;
|
|
|
|
if (CurrPtr == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Loop through the ASL looking for values that we must fix up.
|
|
//
|
|
for (DsdtPointer = CurrPtr; DsdtPointer < (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
|
|
//
|
|
// Get a pointer to compare for signature
|
|
//
|
|
Signature = (UINT32 *) DsdtPointer;
|
|
|
|
//
|
|
// Check if this is the signature we are looking for
|
|
//
|
|
if ((*Signature) == SIGNATURE_32 ('W', 'O', 'L', 'D')) { //WOLD
|
|
//
|
|
// Look for Name Encoding
|
|
//
|
|
if (*(DsdtPointer - 1) != AML_NAME_OP || *(DsdtPointer + 4) != AML_STRING_PREFIX) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// [Lenovo Dock BIOS Writer's Guide (BWG) V0.3]
|
|
// 3.2.2 Flowchart
|
|
// WOL from Dock
|
|
// - Enabled: Put Name(WOLD,"_S5WOL_#01EF1700000000#") in ACPI DSDT table
|
|
// - Disabled: Put Name(WOLD,"_S5WOL_#00EF1700000000#") in ACPI DSDT table
|
|
//
|
|
// Update WOLD Name Space string
|
|
//
|
|
if (EnableDockWol) {
|
|
WoldStr = (CHAR8 *) PcdGetPtr (PcdL05WakeOnLanFromDockEnableWold);
|
|
|
|
} else {
|
|
WoldStr = (CHAR8 *) PcdGetPtr (PcdL05WakeOnLanFromDockDisableWold);
|
|
}
|
|
|
|
AsciiStrnCpyS ((DsdtPointer + 5), AsciiStrSize (DsdtPointer + 5), WoldStr, AsciiStrLen (DsdtPointer + 5));
|
|
|
|
//
|
|
// Update DSDT table
|
|
//
|
|
Status = AcpiSupport->SetAcpiTable (AcpiSupport, Table, TRUE, Version, &Handle);
|
|
gBS->FreePool (Table);
|
|
return Status;
|
|
}
|
|
}
|
|
}
|
|
|
|
gBS->FreePool (Table);
|
|
Index++;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Update Wake On LAN from Dock Callback.
|
|
Wake On LAN from Dock function does not work when hard disk password is set.
|
|
|
|
@param Event Event whose notification function is being invoked.
|
|
@param Context Pointer to the notification function's context.
|
|
|
|
@retval None
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
UpdateWakeOnLanFromDockCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HDD_PASSWORD_DIALOG_PROTOCOL *HddPasswordDialog;
|
|
BOOLEAN WakeOnLanEnable;
|
|
BOOLEAN WakeOnLanFromDock;
|
|
UINTN BufferSize;
|
|
SYSTEM_CONFIGURATION SetupNvData;
|
|
|
|
HddPasswordDialog = NULL;
|
|
WakeOnLanEnable = TRUE;
|
|
WakeOnLanFromDock = TRUE;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHddPasswordDialogProtocolGuid,
|
|
NULL,
|
|
(VOID **) &HddPasswordDialog
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
gBS->CloseEvent (Event);
|
|
|
|
BufferSize = sizeof (SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable (
|
|
L"Setup",
|
|
&gSystemConfigurationGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
&SetupNvData
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
WakeOnLanEnable = (SetupNvData.L05WakeOnLan != 0) ? TRUE : FALSE; // 0:Disable, 1:AC only, 2:AC and Battery
|
|
WakeOnLanFromDock = (SetupNvData.L05WakeOnLanFromDock == 1) ? TRUE : FALSE; // 0:Disable, 1:Enable
|
|
}
|
|
|
|
//
|
|
// [Lenovo SMB BIOS Special Requirements V1.1]
|
|
// 2.7 Wake On LAN (WOL)
|
|
// Note: Wake On LAN function does not work when hard disk password is set.
|
|
//
|
|
if (IsHddSecurityEnable (HddPasswordDialog)) {
|
|
WakeOnLanEnable = FALSE;
|
|
}
|
|
|
|
OemSvcNotifyEcEnableWolFromDock (WakeOnLanEnable && WakeOnLanFromDock);
|
|
|
|
//
|
|
// [Lenovo Dock BIOS Writer's Guide (BWG) V0.3]
|
|
// 3.2.2 Flowchart
|
|
// WOL from Dock
|
|
// - Enabled: Put Name(WOLD,"_S5WOL_#01EF1700000000#") in ACPI DSDT table
|
|
// - Disabled: Put Name(WOLD,"_S5WOL_#00EF1700000000#") in ACPI DSDT table
|
|
//
|
|
UpdateDsdtWoldNameSpace (WakeOnLanEnable && WakeOnLanFromDock);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Update Wake On LAN from Dock setting.
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateWakeOnLanFromDockSetting (
|
|
VOID
|
|
)
|
|
{
|
|
VOID *Registration;
|
|
|
|
Registration = NULL;
|
|
|
|
EfiCreateProtocolNotifyEvent (
|
|
&gEfiHddPasswordDialogProtocolGuid,
|
|
TPL_NOTIFY,
|
|
UpdateWakeOnLanFromDockCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|