alder_lake_bios/Insyde/InsydeModulePkg/Universal/StatusCode/BeepStatusCodeSmm/BeepStatusCodeSmm.c

407 lines
14 KiB
C

/** @file
Beep Status Code Smm implementation.
;******************************************************************************
;* Copyright (c) 2014 - 2021, 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 <BeepStatusCodeSmm.h>
EFI_SMM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
EFI_EVENT mExitBootServicesEvent = NULL;
STATUS_CODE_BEEP_ENTRY *mStatusCodeBeepList;
BEEP_TYPE *mBeepTypeList;
UINT8 *mSmmBscBuffer;
/**
This routine is to return the index number of Beep Type table.
@param BeepTypeId The Id of the Beep Type table.
@retval Index number
- 0xFF : The input Id is not available.
- Other: The index number of the Beep Type table.
**/
UINT8
EFIAPI
GetBeepType (
IN UINT8 BeepTypeId
)
{
BEEP_TYPE *BeepTypeList;
UINT8 Index;
BeepTypeList = (BEEP_TYPE *)mBeepTypeList;
Index = 0;
while (BeepTypeList[Index].Index != 0xFF) {
if (BeepTypeList[Index].Index == BeepTypeId) {
return Index;
}
Index++;
}
//
// Return Index as 0xFF to stand for no matched Beep Type.
//
Index = END_BEEP_TYPE_INDEX;
return Index;
}
/**
This function is to handle Beep Status Code.
@param CodeType Indicates the type of status code being reported.
@param CodeValue Describes the current status of a hardware or
software entity. This includes information about the class and
subclass that is used to classify the entity as well as an operation.
For progress codes, the operation is the current activity.
For error codes, it is the exception.For debug codes,it is not defined at this time.
@param Instance The enumeration of a hardware or software entity within
the system. A system may contain multiple entities that match a class/subclass
pairing. The instance differentiates between them. An instance of 0 indicates
that instance information is unavailable, not meaningful, or not relevant.
Valid instance numbers start with 1.
@param CallerId This optional parameter may be used to identify the caller.
This parameter allows the status code driver to apply different rules to
different callers.
@param Data This optional parameter may be used to pass additional data.
@retval EFI_SUCCESS Function completes successfully.
EFI_UNSUPPORTED Can not find the match beep type.
*/
EFI_STATUS
EFIAPI
BeepStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE CodeValue,
IN UINT32 Instance OPTIONAL,
IN EFI_GUID * CallerId OPTIONAL,
IN EFI_STATUS_CODE_DATA * Data OPTIONAL
)
{
UINTN Index;
STATUS_CODE_BEEP_ENTRY *BeepEntry;
BEEP_TYPE *BeepType;
UINT8 BeepTypeIndex;
if (mStatusCodeBeepList == NULL || mBeepTypeList== NULL) {
return EFI_UNSUPPORTED;
}
Index = 0;
while (mStatusCodeBeepList[Index].CodeType != 0) {
if ((mStatusCodeBeepList[Index].CodeType == CodeType) && (mStatusCodeBeepList[Index].CodeValue == CodeValue)) {
BeepEntry = (STATUS_CODE_BEEP_ENTRY *)&(mStatusCodeBeepList[Index]);
BeepTypeIndex = GetBeepType (BeepEntry->BeepTypeId);
if (BeepTypeIndex == END_BEEP_TYPE_INDEX) {
//
// Can not find the match beep type.
//
return EFI_UNSUPPORTED;
}
BeepType = (BEEP_TYPE *)&(mBeepTypeList[BeepTypeIndex]);
//
// Beep Handler to locate all Speaker Interface protocol instance.
//
BeepHandler (BeepEntry, BeepType);
break;
}
Index++;
}
return EFI_SUCCESS;
}
/**
Beep Handler for Status code.
@param CodeType Indicates the type of status code being reported.
@param CodeValue Describes the current status of a hardware or
software entity. This includes information about the class and
subclass that is used to classify the entity as well as an operation.
For progress codes, the operation is the current activity.
For error codes, it is the exception.For debug codes,it is not defined at this time.
@param Instance The enumeration of a hardware or software entity within
the system. A system may contain multiple entities that match a class/subclass
pairing. The instance differentiates between them. An instance of 0 indicates
that instance information is unavailable, not meaningful, or not relevant.
Valid instance numbers start with 1.
@param CallerId This optional parameter may be used to identify the caller.
This parameter allows the status code driver to apply different rules to
different callers.
@param Data This optional parameter may be used to pass additional data.
@retval EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
BeepHandler (
IN STATUS_CODE_BEEP_ENTRY *BeepEntry,
IN BEEP_TYPE *BeepType
)
{
EFI_STATUS Status;
EFI_SPEAKER_IF_PROTOCOL *SpeakerProtocol;
UINT8 BeepDataCount;
UINT8 BeepLoopIndex;
UINT32 BeepDuration;
UINT32 TimerInterval;
EFI_HANDLE *HandleBuffer;
UINTN NumberOfHandles;
UINTN Index;
//
// Locate Speaker Interface protocol.
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSpeakerInterfaceProtocolGuid,
NULL,
&NumberOfHandles,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
for (Index = 0; Index < NumberOfHandles; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiSpeakerInterfaceProtocolGuid,
(VOID **)&SpeakerProtocol
);
if (EFI_ERROR (Status)) {
continue;
}
for (BeepLoopIndex = 0; BeepLoopIndex < BeepEntry->BeepLoop; BeepLoopIndex++) {
BeepDataCount = 0;
while (BeepType->SoundType[BeepDataCount] != BEEP_NONE) {
BeepDuration = 0;
TimerInterval = 0;
if (BeepType->SoundType[BeepDataCount] == BEEP_LONG) {
BeepDuration = BEEP_LONG_DURATION;
TimerInterval = BEEP_LONG_TIME_INTERVAL;
} else if (BeepType->SoundType[BeepDataCount] == BEEP_SHORT) {
BeepDuration = BEEP_SHORT_DURATION;
TimerInterval = BEEP_SHORT_TIME_INTERVAL;
}
Status = SpeakerProtocol->GenerateBeep (
SpeakerProtocol,
0x1,
BeepDuration,
TimerInterval
);
if (EFI_ERROR (Status)) {
return Status;
}
BeepDataCount++;
}
}
}
return EFI_SUCCESS;
}
/**
Notification function for ReportStatusCode Handler Protocol.
@param[in] Protocol Points to the protocol's unique identifier.
@param[in] Interface Points to the interface instance.
@param[in] Handle The handle on which the interface was installed.
@retval EFI_STATUS
**/
EFI_STATUS
EFIAPI
RscHandlerProtocolCallback (
IN CONST EFI_GUID *Protocol,
IN VOID *Interface,
IN EFI_HANDLE Handle
)
{
EFI_STATUS Status;
Status = gSmst->SmmLocateProtocol (
&gEfiSmmRscHandlerProtocolGuid,
NULL,
(VOID **) &mRscHandlerProtocol
);
ASSERT_EFI_ERROR (Status);
//
// Register the worker function to ReportStatusCodeRouter
//
Status = mRscHandlerProtocol->Register (BeepStatusCode);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
This function is to unregister the Beep Status Code callback function in SMM.
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] Context Points to an optional handler context which was specified when the
handler was registered.
@param[in,out] CommBuffer A pointer to a collection of data in memory that will
be conveyed from a non-SMM environment into an SMM environment.
@param[in,out] CommBufferSize The size of the CommBuffer.
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
should still be called.
**/
EFI_STATUS
EFIAPI
UnregisterBootTimeHandlers (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *RegisterContext,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommBufferSize
)
{
SMM_BEEP_STATUS_CODE_COMMUNICATE *SmmBscCommunicateData;
EFI_STATUS Status = EFI_UNSUPPORTED;
if (CommBuffer == NULL || CommBufferSize == NULL) {
return EFI_SUCCESS;
}
//
// Check buffer size, address, must be the memory which is allocated in DXE part entry point to make sure
// the memory will not overlap SMM RAM.
//
if (*CommBufferSize != SMM_BSC_COMMUNICATION_BUFFER_SIZE - SMM_COMMUNICATE_HEADER_SIZE ||
(UINTN)CommBuffer != (UINTN)mSmmBscBuffer + SMM_COMMUNICATE_HEADER_SIZE) {
return EFI_SUCCESS;
}
SmmBscCommunicateData = (SMM_BEEP_STATUS_CODE_COMMUNICATE *)CommBuffer;
switch (SmmBscCommunicateData->Function) {
case SMM_COMM_UNREGISTER_HANDLER:
if (SmmBscCommunicateData->UnregisterService == FALSE) {
SmmBscCommunicateData->ReturnStatus = EFI_UNSUPPORTED;
break;
}
//
// Unregister Status Code callback function.
//
if (mRscHandlerProtocol != NULL) {
Status = mRscHandlerProtocol->Unregister (BeepStatusCode);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "Unregister BeepStatusCode() in SMM: %r\n", Status));
}
}
SmmBscCommunicateData->ReturnStatus = Status;
break;
default :
SmmBscCommunicateData->ReturnStatus = EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/**
Entry point of Beep Status Code Driver.
The Beep Status Code driver will handle all Beep events during SMM.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI Status
*/
EFI_STATUS
EFIAPI
BeepStatusCodeSmmEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT RscHandlerProtocolEvent;
EFI_HANDLE DispatchHandle;
Status = gSmst->SmmLocateProtocol (
&gEfiSmmRscHandlerProtocolGuid,
NULL,
(VOID **) &mRscHandlerProtocol
);
if (EFI_ERROR (Status)) {
//
// Create callback for registering the Beep Status Code worker function.
//
Status = gSmst->SmmRegisterProtocolNotify (
&gEfiSmmRscHandlerProtocolGuid,
RscHandlerProtocolCallback,
&RscHandlerProtocolEvent
);
} else {
//
// Register the worker function to ReportStatusCodeRouter
//
Status = mRscHandlerProtocol->Register (BeepStatusCode);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Get Beep related tables.
//
mStatusCodeBeepList = NULL;
mBeepTypeList = NULL;
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcUpdateStatusCodeBeep \n"));
Status = OemSvcUpdateStatusCodeBeep (&mStatusCodeBeepList, &mBeepTypeList);
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcUpdateStatusCodeBeep Status: %r\n", Status));
if (Status != EFI_MEDIA_CHANGED) {
//
// Can not get any OEM tables, use default tables.
//
mStatusCodeBeepList = (STATUS_CODE_BEEP_ENTRY *)PcdGetPtr(PcdStatusCodeBeepList);
mBeepTypeList = (BEEP_TYPE *)PcdGetPtr (PcdBeepTypeList);
}
//
// To unregister the Beep Status Code callback function in SMM after exiting Boot Service.
//
Status = gSmst->SmiHandlerRegister (
UnregisterBootTimeHandlers,
&gH2OBeepStatusCodeCommunicationGuid,
&DispatchHandle
);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "Register UnregisterBootTimeHandlers(): %r\n", Status));
}
Status = gBS->LocateProtocol (
&gH2OBeepStatusCodeCommunicationGuid,
NULL,
(VOID **) &mSmmBscBuffer
);
return Status;
}