]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
ArmPlatformPkg/Sec: Moved Exception Vector Table to ArmPkg/DebugAgentBaseLib
[mirror_edk2.git] / ArmPkg / Library / DebugAgentSymbolsBaseLib / DebugAgentSymbolsBaseLib.c
diff --git a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
new file mode 100644 (file)
index 0000000..5d98677
--- /dev/null
@@ -0,0 +1,351 @@
+/** @file\r
+*  Main file supporting the SEC Phase for Versatile Express\r
+*\r
+*  Copyright (c) 2011-2012, 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 <Uefi.h>\r
+#include <Library/ArmLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeCoffExtraActionLib.h>\r
+#include <Library/PeCoffLib.h>\r
+\r
+#include <Pi/PiFirmwareFile.h>\r
+#include <Pi/PiFirmwareVolume.h>\r
+\r
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
+  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
+\r
+\r
+// Vector Table for Sec Phase\r
+VOID\r
+DebugAgentVectorTable (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Returns the highest bit set of the State field\r
+\r
+  @param ErasePolarity   Erase Polarity  as defined by EFI_FVB2_ERASE_POLARITY\r
+                         in the Attributes field.\r
+  @param FfsHeader       Pointer to FFS File Header\r
+\r
+\r
+  @retval the highest bit in the State field\r
+\r
+**/\r
+STATIC\r
+EFI_FFS_FILE_STATE\r
+GetFileState (\r
+  IN UINT8                ErasePolarity,\r
+  IN EFI_FFS_FILE_HEADER  *FfsHeader\r
+  )\r
+{\r
+  EFI_FFS_FILE_STATE  FileState;\r
+  EFI_FFS_FILE_STATE  HighestBit;\r
+\r
+  FileState = FfsHeader->State;\r
+\r
+  if (ErasePolarity != 0) {\r
+    FileState = (EFI_FFS_FILE_STATE)~FileState;\r
+  }\r
+\r
+  HighestBit = 0x80;\r
+  while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
+    HighestBit >>= 1;\r
+  }\r
+\r
+  return HighestBit;\r
+}\r
+\r
+/**\r
+  Calculates the checksum of the header of a file.\r
+  The header is a zero byte checksum, so zero means header is good\r
+\r
+  @param FfsHeader       Pointer to FFS File Header\r
+\r
+  @retval Checksum of the header\r
+\r
+**/\r
+STATIC\r
+UINT8\r
+CalculateHeaderChecksum (\r
+  IN EFI_FFS_FILE_HEADER  *FileHeader\r
+  )\r
+{\r
+  UINT8   Sum;\r
+\r
+  // Calculate the sum of the header\r
+  Sum = CalculateSum8 ((CONST VOID*)FileHeader,sizeof(EFI_FFS_FILE_HEADER));\r
+\r
+  // State field (since this indicates the different state of file).\r
+  Sum = (UINT8)(Sum - FileHeader->State);\r
+\r
+  // Checksum field of the file is not part of the header checksum.\r
+  Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);\r
+\r
+  return Sum;\r
+}\r
+\r
+EFI_STATUS\r
+GetFfsFile (\r
+  IN  EFI_FIRMWARE_VOLUME_HEADER           *FwVolHeader,\r
+  IN  EFI_FV_FILETYPE                      FileType,\r
+  OUT EFI_FFS_FILE_HEADER                  **FileHeader\r
+  )\r
+{\r
+  UINT64                                FvLength;\r
+  UINTN                                 FileOffset;\r
+  EFI_FFS_FILE_HEADER                   *FfsFileHeader;\r
+  UINT8                                 ErasePolarity;\r
+  UINT8                                 FileState;\r
+  UINT32                                FileLength;\r
+  UINT32                                FileOccupiedSize;\r
+\r
+  ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE);\r
+\r
+  FvLength = FwVolHeader->FvLength;\r
+  FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
+  FileOffset = FwVolHeader->HeaderLength;\r
+\r
+  if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+    ErasePolarity = 1;\r
+  } else {\r
+    ErasePolarity = 0;\r
+  }\r
+\r
+  while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
+    // Get FileState which is the highest bit of the State\r
+    FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
+\r
+    switch (FileState) {\r
+\r
+    case EFI_FILE_HEADER_INVALID:\r
+      FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
+      break;\r
+\r
+    case EFI_FILE_DATA_VALID:\r
+    case EFI_FILE_MARKED_FOR_UPDATE:\r
+      if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
+        ASSERT (FALSE);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      if (FfsFileHeader->Type == FileType) {\r
+        *FileHeader = FfsFileHeader;\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
+\r
+      FileOffset += FileOccupiedSize;\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
+      break;\r
+\r
+    case EFI_FILE_DELETED:\r
+      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
+      FileOffset += FileOccupiedSize;\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
+      break;\r
+\r
+    default:\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+GetImageContext (\r
+  IN  EFI_FFS_FILE_HEADER           *FfsHeader,\r
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+{\r
+  EFI_STATUS                              Status;\r
+  UINTN                                   ParsedLength;\r
+  UINTN                                   SectionSize;\r
+  UINTN                                   SectionLength;\r
+  EFI_COMMON_SECTION_HEADER               *Section;\r
+  VOID                                    *EfiImage;\r
+  UINTN                                   ImageAddress;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY         *DebugEntry;\r
+  VOID                                    *CodeViewEntryPointer;\r
+\r
+  Section = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);\r
+  SectionSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;\r
+  SectionSize -= sizeof (EFI_FFS_FILE_HEADER);\r
+  ParsedLength = 0;\r
+  EfiImage = NULL;\r
+\r
+  while (ParsedLength < SectionSize) {\r
+    if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {\r
+      EfiImage = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(Section + 1);\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Size is 24 bits wide so mask upper 8 bits.\r
+    // SectionLength is adjusted it is 4 byte aligned.\r
+    // Go to the next section\r
+    //\r
+    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
+    SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
+    ASSERT (SectionLength != 0);\r
+    ParsedLength += SectionLength;\r
+    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
+  }\r
+\r
+  if (EfiImage == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  // Initialize the Image Context\r
+  ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
+  ImageContext->Handle    = EfiImage;\r
+  ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+  Status =  PeCoffLoaderGetImageInfo (ImageContext);\r
+  if (!EFI_ERROR(Status) && ((VOID*)ImageContext->DebugDirectoryEntryRva != NULL)) {\r
+    ImageAddress = ImageContext->ImageAddress;\r
+    if (ImageContext->IsTeImage) {\r
+      ImageAddress += sizeof (EFI_TE_IMAGE_HEADER) - ((EFI_TE_IMAGE_HEADER*)EfiImage)->StrippedSize;\r
+    }\r
+\r
+    DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(ImageAddress + ImageContext->DebugDirectoryEntryRva);\r
+    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+      CodeViewEntryPointer = (VOID *) (ImageAddress + (UINTN) DebugEntry->RVA);\r
+      switch (* (UINT32 *) CodeViewEntryPointer) {\r
+      case CODEVIEW_SIGNATURE_NB10:\r
+        ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
+        break;\r
+      case CODEVIEW_SIGNATURE_RSDS:\r
+        ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
+        break;\r
+      case CODEVIEW_SIGNATURE_MTOC:\r
+        ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);\r
+        break;\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Initialize debug agent.\r
+\r
+  This function is used to set up debug environment to support source level debugging.\r
+  If certain Debug Agent Library instance has to save some private data in the stack,\r
+  this function must work on the mode that doesn't return to the caller, then\r
+  the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
+  function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
+  responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
+\r
+  If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by\r
+  passing in the Context to be its parameter.\r
+\r
+  If Function() is NULL, Debug Agent Library instance will return after setup debug\r
+  environment.\r
+\r
+  @param[in] InitFlag     Init flag is used to decide the initialize process.\r
+  @param[in] Context      Context needed according to InitFlag; it was optional.\r
+  @param[in] Function     Continue function called by debug agent library; it was\r
+                          optional.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgent (\r
+  IN UINT32                InitFlag,\r
+  IN VOID                  *Context, OPTIONAL\r
+  IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_FFS_FILE_HEADER   *FfsHeader;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;\r
+\r
+  // Now we've got UART, make the check:\r
+  // - The Vector table must be 32-byte aligned\r
+  //TODO: Define a macro for the ARM Exception Table\r
+  ASSERT(((UINT32)DebugAgentVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);\r
+  ArmWriteVBar (DebugAgentVectorTable);\r
+\r
+  // We use InitFlag to know if DebugAgent has been intialized from\r
+  // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)\r
+  // modules\r
+  if (InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {\r
+    //\r
+    // Get the Sec or PrePeiCore module (defined as SEC type module)\r
+    //\r
+    Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdSecureFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);\r
+    if (!EFI_ERROR(Status)) {\r
+      Status = GetImageContext (FfsHeader,&ImageContext);\r
+      if (!EFI_ERROR(Status)) {\r
+        PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+      }\r
+    }\r
+  } else if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {\r
+    //\r
+    // Get the PrePi or PrePeiCore module (defined as SEC type module)\r
+    //\r
+    Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);\r
+    if (!EFI_ERROR(Status)) {\r
+      Status = GetImageContext (FfsHeader,&ImageContext);\r
+      if (!EFI_ERROR(Status)) {\r
+        PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+      }\r
+    }\r
+\r
+    //\r
+    // Get the PeiCore module (defined as PEI_CORE type module)\r
+    //\r
+    Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdFvBaseAddress), EFI_FV_FILETYPE_PEI_CORE, &FfsHeader);\r
+    if (!EFI_ERROR(Status)) {\r
+      Status = GetImageContext (FfsHeader,&ImageContext);\r
+      if (!EFI_ERROR(Status)) {\r
+        PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Enable/Disable the interrupt of debug timer and return the interrupt state\r
+  prior to the operation.\r
+\r
+  If EnableStatus is TRUE, enable the interrupt of debug timer.\r
+  If EnableStatus is FALSE, disable the interrupt of debug timer.\r
+\r
+  @param[in] EnableStatus    Enable/Disable.\r
+\r
+  @return FALSE always.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SaveAndSetDebugTimerInterrupt (\r
+  IN BOOLEAN                EnableStatus\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
+\r