X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmPlatformPkg%2FFileSystem%2FBootMonFs%2FBootMonFsImages.c;fp=ArmPlatformPkg%2FFileSystem%2FBootMonFs%2FBootMonFsImages.c;h=7d3e9019039fd3796c06d584ad1f01a5fc677f4a;hb=94e0955d3e8a3d949e3f00fe69b2827a637058c3;hp=0000000000000000000000000000000000000000;hpb=33fc8b0fec5fca4a8936348cba2b1beee0bc0ed5;p=mirror_edk2.git diff --git a/ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsImages.c b/ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsImages.c new file mode 100644 index 0000000000..7d3e901903 --- /dev/null +++ b/ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsImages.c @@ -0,0 +1,214 @@ +/** @file +* +* Copyright (c) 2012-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include + +#include + +#include "BootMonFsInternal.h" + +UINT32 +BootMonFsChecksum ( + IN VOID *Data, + IN UINT32 Size + ) +{ + UINT32 *Ptr; + UINT32 Word; + UINT32 Checksum; + + ASSERT (Size % 4 == 0); + + Checksum = 0; + Ptr = (UINT32*)Data; + + while (Size > 0) { + Word = *Ptr++; + Size -= 4; + + if (Word > ~Checksum) { + Checksum++; + } + + Checksum += Word; + } + + return ~Checksum; +} + +EFI_STATUS +BootMonFsComputeFooterChecksum ( + IN OUT HW_IMAGE_DESCRIPTION *Footer + ) +{ + HW_IMAGE_DESCRIPTION *Description; + UINT32 Index; + + Footer->Attributes = 1; + + Description = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION)); + if (Description == NULL) { + DEBUG ((DEBUG_ERROR, "BootMonFsComputeFooterChecksum: Unable to allocate memory.\n")); + return EFI_OUT_OF_RESOURCES; + } + + // Copy over to temporary shim + CopyMem (Description, Footer, sizeof (HW_IMAGE_DESCRIPTION)); + + // BootMon doesn't checksum the previous checksum + Description->FooterChecksum = 0; + + // Blank out regions which aren't being used. + for (Index = Footer->RegionCount; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) { + Description->Region[Index].Checksum = 0; + Description->Region[Index].LoadAddress = 0; + Description->Region[Index].Offset = 0; + Description->Region[Index].Size = 0; + } + + // Compute the checksum + Footer->FooterChecksum = BootMonFsChecksum (Description, sizeof (HW_IMAGE_DESCRIPTION)); + + FreePool (Description); + + return EFI_SUCCESS; +} + +BOOLEAN +BootMonFsImageInThisBlock ( + IN VOID *Buf, + IN UINTN Size, + IN UINT32 Block, + OUT HW_IMAGE_DESCRIPTION *Image + ) +{ + EFI_STATUS Status; + HW_IMAGE_FOOTER *Ptr; + HW_IMAGE_DESCRIPTION *Footer; + UINT32 Checksum; + + // The footer is stored as the last thing in the block + Ptr = (HW_IMAGE_FOOTER *)((UINT8 *)Buf + Size - sizeof (HW_IMAGE_FOOTER)); + + // Check that the verification bytes are present + if ((Ptr->FooterSignature1 != HW_IMAGE_FOOTER_SIGNATURE_1) || (Ptr->FooterSignature2 != HW_IMAGE_FOOTER_SIGNATURE_2)) { + return FALSE; + } + + if (Ptr->Version != HW_IMAGE_FOOTER_VERSION) { + return FALSE; + } + + if (Ptr->Offset != HW_IMAGE_FOOTER_OFFSET) { + return FALSE; + } + + Footer = (HW_IMAGE_DESCRIPTION *)(((UINT8 *)Buf + Size - sizeof (HW_IMAGE_DESCRIPTION))); + Checksum = Footer->FooterChecksum; + Status = BootMonFsComputeFooterChecksum (Footer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: failed to compute checksum for image '%a'\n", Footer->Footer.Filename)); + } + + if (Footer->FooterChecksum != Checksum) { + DEBUG ((DEBUG_ERROR, "Warning: image '%a' checksum mismatch.\n", Footer->Footer.Filename)); + } + + if ((Footer->BlockEnd != Block) || (Footer->BlockStart > Footer->BlockEnd)) { + return FALSE; + } + + // Copy the image out + CopyMem (Image, Footer, sizeof (HW_IMAGE_DESCRIPTION)); + + return TRUE; +} + +EFI_STATUS +BootMonFsDiscoverNextImage ( + IN BOOTMON_FS_INSTANCE *Instance, + IN EFI_LBA *LbaStart, + OUT HW_IMAGE_DESCRIPTION *Image + ) +{ + EFI_BLOCK_IO_PROTOCOL *Blocks; + EFI_LBA CurrentLba; + VOID *Out; + + Blocks = Instance->BlockIo; + + // Allocate an output buffer + Out = AllocatePool (Instance->Media->BlockSize); + if (Out == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Blocks->Reset (Blocks, FALSE); + CurrentLba = *LbaStart; + + // Look for images in the rest of this block + while (CurrentLba <= Instance->Media->LastBlock) { + // Read in the next block + Blocks->ReadBlocks (Blocks, Instance->Media->MediaId, CurrentLba, Instance->Media->BlockSize, Out); + // Check for an image in the current block + if (BootMonFsImageInThisBlock (Out, Instance->Media->BlockSize, (CurrentLba - Instance->Media->LowestAlignedLba), Image)) { + DEBUG ((EFI_D_ERROR, "Found image: %a in block %d.\n", &(Image->Footer.Filename), (UINTN)(CurrentLba - Instance->Media->LowestAlignedLba))); + FreePool (Out); + *LbaStart = Image->BlockEnd + 1; + return EFI_SUCCESS; + } else { + CurrentLba++; + } + } + + *LbaStart = CurrentLba; + FreePool (Out); + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonFsInitialize ( + IN BOOTMON_FS_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + EFI_LBA Lba; + UINT32 ImageCount; + BOOTMON_FS_FILE *NewFile; + + ImageCount = 0; + Lba = 0; + + while (1) { + Status = BootMonFsCreateFile (Instance, &NewFile); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = BootMonFsDiscoverNextImage (Instance, &Lba, &(NewFile->HwDescription)); + if (EFI_ERROR (Status)) { + // Free NewFile allocated by BootMonFsCreateFile () + FreePool (NewFile); + break; + } + InsertTailList (&Instance->RootFile->Link, &NewFile->Link); + ImageCount++; + } + + Instance->Initialized = TRUE; + return EFI_SUCCESS; +}