【问题背景】
进行客制化开关机动画设置后,在进行关机充电时,在出现关机充电动画前都会闪现开机logo
【代码分析】
正常来说,最初显示开机logo是在Uefi阶段,而高通原生设计无区分是否关机充电的判断,这样无论是开机还是关机进uefi阶段就都会显示同样的logo图片,具体代码如下:
vendor/boot_images/QcomPkg/Library/MDPLib/DisplayUtils.c
EFI_STATUS
EFIAPI
Display_Utils_RenderSplashScreen(
OUT VOID *BGRTTable OPTIONAL,
RenderLogoParamsType *pRenderLogoParams)
{
EFI_STATUS Status = EFI_SUCCESS;
static EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE *pLocalBGRTTable = NULL;
// Handle cases where the BGRT is not yet loaded or not applicable. 检查BGRT表是否已加载:
if (NULL == BGRTTable)
{
if (NULL == pLocalBGRTTable)
{
// Allocate space for the local cached copy of the BGRT table if it doesn't exit.
if (NULL == (pLocalBGRTTable = (EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE*) AllocateZeroPool(sizeof(EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE))))
{
DEBUG ((EFI_D_ERROR, "Display_Utils_RenderSplashScreen: Unable to allocate memory for local BGRT table\n"));
Status = EFI_OUT_OF_RESOURCES;
}
}
// Load and render the loge file, cache the BGRT information till a valid BGRT is passed in.
//加载和渲染logo文件:
if (EFI_SUCCESS == Status)
{
UINT8 *BGRTAddress = NULL;
CHAR8 *pLogoFileName = NULL;
UINT32 ImageSize = 0;
UINT32 BGRTBufferSize = 0;
UINT32 uFlags = 0;
UINT32 uImageFvSetting = 0;
// Enable display imagefv based on the settings for runtime and compile time.
if (((MDP_STATUS_OK == MDP_Display_GetVariable_Integer(DISPVAR_ENABLE_DISPLAY_IMAGEFV, &uImageFvSetting)) && (1 == uImageFvSetting))
|| ((MDP_STATUS_OK == MDP_GetConfigValue(DISPVAR_ENABLE_DISPLAY_IMAGEFV_ASCII, &uImageFvSetting)) && (1 == uImageFvSetting)))
{
// Set imagefv flag if logo policy is 1, which indicates loading logo from imagefv system.
uFlags = DISP_LOAD_FILE_FLAG_IMAGEFV;
}
// 通过调用Display_Utils_GetLogoConfig函数获取logo文件名,并将其赋值给pLogoFileName
pLogoFileName = Display_Utils_GetLogoConfig(pRenderLogoParams);
// Load logo from FV 再从FV加载logo
Status = Display_Utils_LoadFile(pLogoFileName, &BGRTAddress, &BGRTBufferSize, &ImageSize, uFlags);
//渲染logo文件:
if (EFI_SUCCESS == Status)
{
// Rendor logo file after loading it.
if (EFI_SUCCESS == (Status = Display_Utils_RenderBGRTImage(BGRTAddress, ImageSize, pRenderLogoParams)))
{
BMP_IMAGE_HEADER *ImageHeader = (BMP_IMAGE_HEADER*)BGRTAddress;
UINT32 ImageWidth = ImageHeader->PixelWidth;
UINT32 ImageHeight = ((INT32)ImageHeader->PixelHeight < 0) ? (UINT32)-ImageHeader->PixelHeight : ImageHeader->PixelHeight;
DEBUG ((EFI_D_INFO, "Display_Utils_RenderSplashScreen: OEM Logo Successfully Loaded\n"));
// Update the BGRT position, store it in the cached version of BGRT.
CalculateLogoPosition(ImageWidth, ImageHeight, &pLocalBGRTTable->ImageOffsetX, &pLocalBGRTTable->ImageOffsetY, pRenderLogoParams);
// As logo file is rendered to the panel , set the status field to 1.
pLocalBGRTTable->Status = 0x1 | (pRenderLogoParams->eBGRTRotation << 1);
// Update the BGRT address
pLocalBGRTTable->ImageAddress = (UINT64)BGRTAddress;
}
else
{
DEBUG ((EFI_D_ERROR, "Display_Utils_RenderSplashScreen: Display_Utils_RenderBGRTImage failed %d\n", Status));
}
}
}
}
// 验证并处理有效的BGRT表:
else // Valid BGRT passed in , validate is and process it.
{
// The define of ACPI 6.3 covers version 5.0 to 6.3.
EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE *pBGRTTable = (EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE *)BGRTTable;
if ((EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE != pBGRTTable->Header.Signature) // "BGRT" Signature
|| (EFI_ACPI_6_3_BGRT_VERSION != pBGRTTable->Version) // Valid version 1.0
|| (EFI_ACPI_6_3_BGRT_IMAGE_TYPE_BMP != pBGRTTable->ImageType)) // Valid type BMP
{
DEBUG ((EFI_D_ERROR, "Display_Utils_RenderSplashScreen: BGRT table header corrupt or invalid!\n"));
Status = EFI_LOAD_ERROR;
}
else
{
// Pass information loaded during logo1 back to the caller's BGRT table.
if (NULL != pLocalBGRTTable)
{
pBGRTTable->ImageOffsetX = pLocalBGRTTable->ImageOffsetX;
pBGRTTable->ImageOffsetY = pLocalBGRTTable->ImageOffsetY;
pBGRTTable->Status = pLocalBGRTTable->Status;
pBGRTTable->ImageAddress = pLocalBGRTTable->ImageAddress;
}
else
{
DEBUG ((EFI_D_ERROR, "Display_Utils_RenderSplashScreen: BGRT was not loaded correctly, table cannot be updated!\n"));
}
}
}
return Status;
}
从上面的代码可知如须进行关机充电和开机充电logo的区分,那便在上述逻辑中添加相关判断逻辑(添加判断是否插入充电器)来区分关机充电和正常开机不同场景下的图片显示效果即可
【修改方案】
主要就是两个条件的判断,电池电压和充电模式,所以关键就在于如何获取这两个值了,如下述修改,通过调用
ExtChargerLib_GetBatteryVoltage( )获取电池电压
ChargerExProtocol->IsOffModeCharging(&boffModeCharging) 获取充电模式并传给 boffModeCharging
仅作参考:
#include <Protocol/EFIChargerEx.h>
#include <Library/ExtChargerLib.h>
// 通过调用Display_Utils_GetLogoConfig函数获取logo文件名,并将其赋值给pLogoFileName
pLogoFileName = Display_Utils_GetLogoConfig(pRenderLogoParams);
// Load logo from FV 再从FV加载logo
Status = Display_Utils_LoadFile(pLogoFileName, &BGRTAddress, &BGRTBufferSize, &ImageSize, uFlags);
EFI_CHARGER_EX_PROTOCOL * ChargerExProtocol = NULL;
UINT32 batt_val = 0;
ExtChargerLib_GetBatteryVoltage( &batt_val);
DEBUG ((EFI_D_ERROR, "[POWERON]batt_val = %d\n",batt_val));
// 获取电池电压判断是否达到开机电压
if( batt_val >= START_BOOT_BATT) {
if(EFI_SUCCESS == gBS->LocateProtocol(&gChargerExProtocolGuid, NULL, ((VOID **) &ChargerExProtocol)))
{
// 获取到充电状态,如是关机充电则显示关机充电图片,否则显示正常开机logo
// 此处 直接通过Display_Utils_LoadFile调用图片资源来实现,也可以通过Display_Utils_GetLogoConfig来获取文件名再进行判断等下一步操作
if ((EFI_SUCCESS == ChargerExProtocol->IsOffModeCharging(&boffModeCharging)) && boffModeCharging)
{
Status = Display_Utils_LoadFile("battery_symbol_Charging.bmp", &BGRTAddress, &BGRTBufferSize, &ImageSize);
DEBUG ((EFI_D_ERROR, "[POWERON]Chargeing logo.\n"));
} else {
Status = Display_Utils_LoadFile("logo1.bmp", &BGRTAddress, &BGRTBufferSize, &ImageSize);
}
} else {
Status = Display_Utils_LoadFile("logo1.bmp", &BGRTAddress, &BGRTBufferSize, &ImageSize);
}
}
if (EFI_SUCCESS == Status)
{
// Render logo file after loading it.