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