问题描述:内存检测失败,蜂鸣器报警
基本思路
内存检测
内存检测在PEI阶段,
EFI_STATUS
DramInitWrapper (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN WRAPPER_PARAM *WapperParam
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
DEBUG((EFI_D_ERROR, "miabeep %a,Line:%d,BootMode:%d\n",__FUNCTION__,__LINE__,WapperParam->BootMode));
if (WapperParam->BootMode == BOOT_ON_S3_RESUME) {
Status = (WapperParam->EfiAisaDram)->DramS3Init((EFI_PEI_SERVICES **)PeiServices, (WapperParam->EfiAisaDram));
} else {
Status = (WapperParam->EfiAisaDram)->DramNormalInit((EFI_PEI_SERVICES **)PeiServices, (WapperParam->EfiAisaDram));
if (EFI_ERROR( Status)) {
//ERROR_CODE(PEI_MEMORY_NOT_DETECTED, EFI_ERROR_MAJOR);
DEBUG((EFI_D_ERROR, "miabeep %a,Line:%d\n",__FUNCTION__,__LINE__));
REPORT_STATUS_CODE(EFI_ERROR_CODE, 0x10); //内存检测失败,提交状态码
CpuDeadLoop ();
}
}
return Status;
}
register status code 原理
只有当Report Status Code 协议被安装时,Register Status Code 回调方法。
Status = gBS->LocateProtocol (
&gEfiRscHandlerProtocolGuid,
NULL,
(VOID **) &mBeepRscHandlerProtocol
);
ASSERT_EFI_ERROR (Status);
mBeepRscHandlerProtocol->Register (BeepStatusCodeReportWorker, TPL_HIGH_LEVEL);
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
UnregisterBeepBootTimeHandlers,
NULL,
&gEfiEventExitBootServicesGuid,
&mBeepExitBootServicesEvent
);
mBeepRscHandlerProtocol->Register 先注册BeepStatusCodeReportWorker 回调函数,当内存检测失败,提交错误状态码,BeepStatusCodeReportWorker 回调函数对获得的状态类型及状态码进行处理,匹配Map Table里的内存错误类型,匹配成功触发蜂鸣器报警功能。
gBS->CreateEventEx () :当OS 加载或者OS 内核调用ExitBootServices(),就执行UnregisterBeepBootTimeHandlers,退出注册。
蜂鸣器报警
EFI_STATUS
TurnOnSpeaker (
VOID
)
{
DEBUG((EFI_D_ERROR, "miabeep %a,Line:%d\n",__FUNCTION__,__LINE__));
UINT8 Data;
//
//Write control port
//
Data = IoRead8 (0x61);
Data |= 0x03;
IoWrite8(0x61,Data);
return EFI_SUCCESS;
}
EFI_STATUS
TurnOffSpeaker (
VOID
)
{
DEBUG((EFI_D_ERROR, "miabeep %a,Line:%d\n",__FUNCTION__,__LINE__));
UINT8 Data;
//
//Write control port
//
Data = IoRead8 (0x61);
Data &= 0xFC;
IoWrite8(0x61,Data);
return EFI_SUCCESS;
}
EFI_STATUS
OutputBeep (
IN UINTN NumberOfBeep,
IN UINTN BeepDuration,
IN UINTN TimeInterval
)
{
DEBUG((EFI_D_ERROR, "miabeep %a,Line:%d\n",__FUNCTION__,__LINE__));
UINTN Num;
for (Num = 0; Num < NumberOfBeep; Num++) {
TurnOnSpeaker ();
MicroSecondDelay(BeepDuration);
TurnOffSpeaker ();
MicroSecondDelay(TimeInterval);
}
return EFI_SUCCESS;
}
蜂鸣器的条件是, 0x61寄存器中倒数第二位置1
蜂鸣器不响原因
1.当内存失败的时候REPORT_STATUS XX—这个确保代码有跑到
2. 当REPORT_STATUS XX的时候确保BeepStatusCodeReportWorker同时进来
3. 当BeepStatusCodeReportWorker进来的时候确保map table有对应的entry
4. 测试蜂鸣器功能可用
思考
CRS 注册,提交,接收功能可以处理多种报警事件,如
STATUS_CODE_TO_DATA_MAP mBeepErrorMap[] = {
//
// PEI
//
// Regular boot
{ PEI_MEMORY_NOT_DETECTED, 1 },
{ PEI_MEMORY_INSTALLED_TWICE, 1 },
{ PEI_DXEIPL_NOT_FOUND, 3 },
{ PEI_DXE_CORE_NOT_FOUND, 3 },
{ PEI_RESET_NOT_AVAILABLE, 7 },
// Recovery
{ PEI_RECOVERY_FAILED, 4 },
// S3 Resume
{ PEI_S3_RESUME_FAILED, 4 },
//
// DXE
//
{ DXE_ARCH_PROTOCOL_NOT_AVAILABLE, 4 },
{ DXE_NO_CON_OUT, 5 },
{ DXE_NO_CON_IN, 5 },
{ DXE_INVALID_PASSWORD, 1 },
{ DXE_FLASH_UPDATE_FAILED, 6 },
{ DXE_RESET_NOT_AVAILABLE, 7 },
{0,0}
};
报警功能也可以为setup界面显示,post界面提示,或其它操作。不仅限于PEI阶段的值交给runtime阶段处理。