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