UEFI 内存检测失败,蜂鸣器报警

问题描述:内存检测失败,蜂鸣器报警

基本思路

请添加图片描述

内存检测

内存检测在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阶段处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值