QcomModulePkg: Add support to parse recovery dtbo image
Non-A/B devices need to include the DTBO image within the recovery
partition to be self-sufficient and prevent OTA failures.
Change-Id: Id78d6b82bc798318768d5cc031a852d761572fbf
diff --git a/QcomModulePkg/Library/BootLib/PartitionTableUpdate.c b/QcomModulePkg/Library/BootLib/PartitionTableUpdate.c
old mode 100755
new mode 100644
index 937f4ad..79dafd1
--- a/QcomModulePkg/Library/BootLib/PartitionTableUpdate.c
+++ b/QcomModulePkg/Library/BootLib/PartitionTableUpdate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -1533,27 +1533,107 @@
return Status;
}
+/* This functions should be called only if header revision > 0 */
+STATIC EFI_STATUS GetRecoveryDtboInfo (BootInfo *Info,
+ BootParamlist *BootParamlistPtr,
+ UINT64 *DtboImageSize)
+{
+ UINT32 HeaderVersion = 0;
+ UINT64 RecoveryDtboOffset = 0;
+ UINT32 RecoveryDtboSize = 0;
+ UINT32 ImageHeaderSize = 0;
+ struct boot_img_hdr_v1 *BootImgHdrV1Addr;
+
+ if (Info == NULL ||
+ BootParamlistPtr == NULL ||
+ DtboImageSize == NULL) {
+ DEBUG ((EFI_D_ERROR, "Invalid input parameters\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HeaderVersion = Info->HeaderVersion;
+
+ /* Finds out the location of recovery dtbo size and offset */
+ BootImgHdrV1Addr = (struct boot_img_hdr_v1 *)
+ ((UINT64) BootParamlistPtr->ImageBuffer +
+ BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET);
+
+ if (HeaderVersion == BOOT_HEADER_VERSION_ONE) {
+ ImageHeaderSize = BootImgHdrV1Addr->header_size;
+
+ if ((ImageHeaderSize != (sizeof (struct boot_img_hdr_v1) +
+ BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET)) ||
+ ImageHeaderSize > BootParamlistPtr->PageSize) {
+ DEBUG ((EFI_D_ERROR,
+ "Invalid boot image header: %d\n", ImageHeaderSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+
+ RecoveryDtboOffset = BootImgHdrV1Addr->recovery_dtbo_offset;
+ RecoveryDtboSize = ROUND_TO_PAGE (BootImgHdrV1Addr->recovery_dtbo_size,
+ BootParamlistPtr->PageSize - 1);
+
+ if (CHECK_ADD64 (RecoveryDtboOffset, RecoveryDtboSize)) {
+ DEBUG ((EFI_D_ERROR, "Integer Oveflow: RecoveryDtboOffset=%u "
+ "RecoveryDtboSize=%u\n", RecoveryDtboOffset, RecoveryDtboSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (RecoveryDtboOffset + RecoveryDtboSize >
+ BootParamlistPtr->ImageSize) {
+ DEBUG ((EFI_D_ERROR, "Invalid recovery dtbo: RecoveryDtboOffset=%u,"
+ " RecoveryDtboSize=%u, ImageSize=%u\n",
+ RecoveryDtboOffset, RecoveryDtboSize,
+ BootParamlistPtr->ImageSize));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ BootParamlistPtr->DtboImgBuffer = (VOID *)
+ ((UINT64) BootParamlistPtr->ImageBuffer +
+ RecoveryDtboOffset);
+
+ *DtboImageSize = RecoveryDtboSize;
+
+ DEBUG ((EFI_D_VERBOSE, "Image Header Version: 0x%x\n", HeaderVersion));
+ DEBUG ((EFI_D_VERBOSE, "Recovery Dtbo Offset: 0x%x\n",
+ RecoveryDtboOffset));
+ DEBUG ((EFI_D_VERBOSE, "Recovery Dtbo Size: 0x%x\n", *DtboImageSize));
+
+ return EFI_SUCCESS;
+}
+
/*Function to provide Dtbo Present info
*return: TRUE or FALSE.
*/
BOOLEAN
-LoadAndValidateDtboImg (BootInfo *Info, VOID **DtboImgBuffer)
+LoadAndValidateDtboImg (BootInfo *Info,
+ BootParamlist *BootParamlistPtr)
{
- UINTN DtboImgSize = 0;
+ UINT64 DtboImgSize = 0;
EFI_STATUS Status = EFI_SUCCESS;
struct DtboTableHdr *DtboTableHdr = NULL;
- Status = GetImage (Info, DtboImgBuffer, &DtboImgSize, "dtbo");
+ if (!Info->MultiSlotBoot &&
+ Info->BootIntoRecovery &&
+ Info->HeaderVersion > BOOT_HEADER_VERSION_ZERO) {
+ Status = GetRecoveryDtboInfo (Info, BootParamlistPtr, &DtboImgSize);
+ } else {
+ Status = GetImage (Info, &BootParamlistPtr->DtboImgBuffer,
+ (UINTN *)&DtboImgSize, "dtbo");
+ }
+
if (Status != EFI_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "BootLinux: GetImage dtbo failed!\n"));
+ DEBUG ((EFI_D_ERROR, "BootLinux: failed to get dtbo image\n"));
return FALSE;
}
- if (!*DtboImgBuffer) {
+
+ if (!BootParamlistPtr->DtboImgBuffer) {
DEBUG ((EFI_D_ERROR, "DtboImgBuffer is NULL"));
return FALSE;
}
- DtboTableHdr = *DtboImgBuffer;
+ DtboTableHdr = BootParamlistPtr->DtboImgBuffer;
if (fdt32_to_cpu (DtboTableHdr->Magic) != DTBO_TABLE_MAGIC) {
DEBUG ((EFI_D_ERROR, "Dtbo hdr magic mismatch %x, with %x\n",
DtboTableHdr->Magic, DTBO_TABLE_MAGIC));