QcomModulePkg: Cert fingerprint on diplay in Yellow boot state
Add functinality to VerifiedBootMenu to provide certificate fingerprint
as display output for Yellow boot states.
Change-Id: Id26141d5db87a559f5eb4be1dc47abcf05166e7d
diff --git a/QcomModulePkg/Library/BootLib/VerifiedBootMenu.c b/QcomModulePkg/Library/BootLib/VerifiedBootMenu.c
index 0904446..d948685 100644
--- a/QcomModulePkg/Library/BootLib/VerifiedBootMenu.c
+++ b/QcomModulePkg/Library/BootLib/VerifiedBootMenu.c
@@ -39,6 +39,8 @@
#include <Library/UpdateDeviceTree.h>
#include <Protocol/EFIVerifiedBoot.h>
+#define FINGERPRINT_LINE_LEN 16
+#define FINGERPRINT_FORMATED_LINE_LEN FINGERPRINT_LINE_LEN + 5
#define VERIFIED_BOOT_OPTION_NUM 5
STATIC OPTION_MENU_INFO gMenuInfo;
@@ -131,10 +133,119 @@
};
/**
- Draw the verified boot option menu
- @param[out] OptionMenuInfo The option info
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
+Convert UINT8 array to a CHAR8 hex array.
+The caller of the function should allocate memory properly.
+Size of target should be at least twice than the source size (len).
+
+@param[out] *target Pointer to the output array
+@param[in] *source Pointer to the source array
+@param[in] len Size of the source array
+
+**/
+STATIC VOID GetHexString(CHAR8 *Target, UINT8 *Source, UINTN Len)
+{
+
+ UINTN TargetIndex = 0;
+ UINTN SourceIndex = 0;
+ UINTN TargetLen = Len * 2;
+ CHAR8 HexBuf[3];
+ for (TargetIndex = 0; TargetIndex < TargetLen;
+ TargetIndex = TargetIndex + 2) {
+ AsciiSPrint(HexBuf, sizeof(HexBuf), "%02x",
+ Source[SourceIndex]);
+ CopyMem(Target + TargetIndex, HexBuf, 2);
+ SourceIndex++;
+ }
+}
+
+/**
+
+Construct display output array.
+The caller should allocate the buffer properly before invoking this function.
+The assumption is display output and finger print have larger size than 22 and 16.
+
+The target array starts with string "ID: " following with the fingerprint.
+Each 16 charcaters of fingerprint are shown in one line.
+If fingerprint size is too big, it only copies the number of characters
+that matches the output size.
+
+Eaxmple output:
+
+ID: 3F957EBAD2EE02F2
+ CD23ED905C51913D
+ 4E9AAA2C5A4A1AE8
+ 0F9D6BF727593F14
+
+@param[out] *target Pointer to the output array
+@param[in] target_len Size of output
+@param[in] *source Pointer to the input array
+@param[in] source_len Size of input
+
+**/
+STATIC VOID GetDisplayOutPut(CHAR8 *Target, UINTN TargetLen, CHAR8 *Source,
+ UINTN SourceLen)
+{
+ UINTN LastLineCharsCount = 0;
+ UINTN TargetIndex = 0;
+ UINTN SourceIndex = 0;
+ UINTN LineNum = 0;
+ UINTN FinalLen = 0;
+
+ /* First line starts with 4 characters of "ID: ",
+ other lines start with 4 spaces to make the length of each line 21
+ */
+ CONST CHAR8 ID[4] = "ID: ";
+ CONST CHAR8 StartlineSpace[4] = " ";
+
+ /* Each line contains 21 characters (4 spaces in the beginning),
+ 16 characters from fingerprint, one character for endline */
+ UINTN NumberOfLines = SourceLen / FINGERPRINT_LINE_LEN +
+ ((SourceLen % FINGERPRINT_LINE_LEN== 0 ? 0 :1));
+
+ /* each line contains 4 spaces at the beginning and one endline
+ character at the end */
+ FinalLen = (sizeof(ID) + 1) * (NumberOfLines) + SourceLen;
+
+ /* if final size is bigger that display output size,
+ reduce the numbe of lines,
+ one character is needed for NULL character */
+ while (FinalLen > TargetLen - 1) {
+ NumberOfLines--;
+ FinalLen = FinalLen - FINGERPRINT_FORMATED_LINE_LEN;
+ SourceLen = SourceLen - FINGERPRINT_LINE_LEN;
+ }
+
+ for (LineNum= 0; LineNum < NumberOfLines; LineNum++) {
+ if (LineNum == 0) {
+ CopyMem(Target + TargetIndex, ID, sizeof(ID));
+ } else {
+ CopyMem(Target + TargetIndex, StartlineSpace, sizeof(StartlineSpace));
+ }
+ TargetIndex = TargetIndex + sizeof(ID);
+ if ((SourceLen - SourceIndex) >= FINGERPRINT_LINE_LEN) {
+ CopyMem(Target + TargetIndex,
+ Source + SourceIndex, FINGERPRINT_LINE_LEN);
+ TargetIndex = TargetIndex + FINGERPRINT_LINE_LEN;
+ SourceIndex = SourceIndex + FINGERPRINT_LINE_LEN;
+ } else {
+ LastLineCharsCount = SourceLen % FINGERPRINT_LINE_LEN;
+ CopyMem(Target + TargetIndex, Source + SourceIndex,
+ LastLineCharsCount);
+ TargetIndex = TargetIndex + LastLineCharsCount;
+ SourceIndex = SourceIndex + LastLineCharsCount;
+ }
+ Target[TargetIndex] = '\n';
+ TargetIndex = TargetIndex + 1;
+ }
+ /* NULL terminat the target array */
+ Target[TargetIndex] = '\0';
+}
+
+/**
+Draw the verified boot option menu
+@param[out] OptionMenuInfo The option info
+@retval EFI_SUCCESS The entry point is executed successfully.
+@retval other Some error occurs when executing this entry point.
**/
EFI_STATUS VerifiedBootOptionMenuShowScreen(OPTION_MENU_INFO *OptionMenuInfo)
{
@@ -212,8 +323,49 @@
if (Type == DISPLAY_MENU_YELLOW) {
mCommonMsgInfo[Type].Fingerprint.Location = Location;
- AsciiSPrint(mCommonMsgInfo[Type].Fingerprint.Msg,
- MAX_MSG_SIZE, "ID: %a\n", "unsupported");
+ QCOM_VERIFIEDBOOT_PROTOCOL *VbIntf = NULL;
+ Status = gBS->LocateProtocol(&gEfiQcomVerifiedBootProtocolGuid,
+ NULL, (VOID **) &VbIntf);
+ if (Status != EFI_SUCCESS) {
+ DEBUG((EFI_D_ERROR, "Unable to locate VerifiedBoot Protocol\n"));
+ return Status;
+ }
+
+ if (VbIntf->Revision >=
+ QCOM_VERIFIEDBOOT_PROTOCOL_REVISION) {
+ UINT8 FingerPrint[MAX_MSG_SIZE];
+ UINTN FingerPrintLen = 0;
+ UINTN DisplayStrLen = 0;
+ CHAR8 *DisplayStr = NULL;
+
+ Status = VbIntf->VBGetCertFingerPrint(VbIntf,
+ FingerPrint,
+ MAX_MSG_SIZE,
+ &FingerPrintLen);
+ if (Status != EFI_SUCCESS) {
+ DEBUG((EFI_D_ERROR,
+ "Failed Reading CERT FingerPrint\n"));
+ return Status;
+ }
+ /* Each bytes needs two characters to be shown on display */
+ DisplayStrLen = FingerPrintLen * 2;
+ DisplayStr = AllocatePool(DisplayStrLen);
+ if (DisplayStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ /* Convert the fingerprint to a charcater string */
+ GetHexString(DisplayStr, FingerPrint, FingerPrintLen);
+ /* Save fingerprint in a formated string for display */
+ GetDisplayOutPut(mCommonMsgInfo[Type].Fingerprint.Msg,
+ MAX_MSG_SIZE, DisplayStr,
+ DisplayStrLen);
+ if (DisplayStr) {
+ FreePool(DisplayStr);
+ }
+ }else {
+ AsciiSPrint(mCommonMsgInfo[Type].Fingerprint.Msg,
+ MAX_MSG_SIZE, "ID: %a\n", "unsupported");
+ }
Status = DrawMenu(&mCommonMsgInfo[Type].Fingerprint, &Height);
if (Status != EFI_SUCCESS)
return Status;