mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 03:03:46 +01:00 
			
		
		
		
	- differnt -> different - Libary -> Library - intialized -> initialized Cc: Leif Lindholm <leif.lindholm@linaro.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gary Lin <glin@suse.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
		
			
				
	
	
		
			352 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			352 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| *  Main file supporting the SEC Phase for Versatile Express
 | |
| *
 | |
| *  Copyright (c) 2011-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 <Uefi.h>
 | |
| #include <Library/ArmLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/DebugAgentLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/PeCoffExtraActionLib.h>
 | |
| #include <Library/PeCoffLib.h>
 | |
| 
 | |
| #include <Pi/PiFirmwareFile.h>
 | |
| #include <Pi/PiFirmwareVolume.h>
 | |
| 
 | |
| #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
 | |
|   (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
 | |
| 
 | |
| 
 | |
| // Vector Table for Sec Phase
 | |
| VOID
 | |
| DebugAgentVectorTable (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Returns the highest bit set of the State field
 | |
| 
 | |
|   @param ErasePolarity   Erase Polarity  as defined by EFI_FVB2_ERASE_POLARITY
 | |
|                          in the Attributes field.
 | |
|   @param FfsHeader       Pointer to FFS File Header
 | |
| 
 | |
| 
 | |
|   @retval the highest bit in the State field
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| EFI_FFS_FILE_STATE
 | |
| GetFileState (
 | |
|   IN UINT8                ErasePolarity,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   EFI_FFS_FILE_STATE  FileState;
 | |
|   EFI_FFS_FILE_STATE  HighestBit;
 | |
| 
 | |
|   FileState = FfsHeader->State;
 | |
| 
 | |
|   if (ErasePolarity != 0) {
 | |
|     FileState = (EFI_FFS_FILE_STATE)~FileState;
 | |
|   }
 | |
| 
 | |
|   HighestBit = 0x80;
 | |
|   while (HighestBit != 0 && (HighestBit & FileState) == 0) {
 | |
|     HighestBit >>= 1;
 | |
|   }
 | |
| 
 | |
|   return HighestBit;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Calculates the checksum of the header of a file.
 | |
|   The header is a zero byte checksum, so zero means header is good
 | |
| 
 | |
|   @param FfsHeader       Pointer to FFS File Header
 | |
| 
 | |
|   @retval Checksum of the header
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| UINT8
 | |
| CalculateHeaderChecksum (
 | |
|   IN EFI_FFS_FILE_HEADER  *FileHeader
 | |
|   )
 | |
| {
 | |
|   UINT8   Sum;
 | |
| 
 | |
|   // Calculate the sum of the header
 | |
|   Sum = CalculateSum8 ((CONST VOID*)FileHeader,sizeof(EFI_FFS_FILE_HEADER));
 | |
| 
 | |
|   // State field (since this indicates the different state of file).
 | |
|   Sum = (UINT8)(Sum - FileHeader->State);
 | |
| 
 | |
|   // Checksum field of the file is not part of the header checksum.
 | |
|   Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
 | |
| 
 | |
|   return Sum;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GetFfsFile (
 | |
|   IN  EFI_FIRMWARE_VOLUME_HEADER           *FwVolHeader,
 | |
|   IN  EFI_FV_FILETYPE                      FileType,
 | |
|   OUT EFI_FFS_FILE_HEADER                  **FileHeader
 | |
|   )
 | |
| {
 | |
|   UINT64                                FvLength;
 | |
|   UINTN                                 FileOffset;
 | |
|   EFI_FFS_FILE_HEADER                   *FfsFileHeader;
 | |
|   UINT8                                 ErasePolarity;
 | |
|   UINT8                                 FileState;
 | |
|   UINT32                                FileLength;
 | |
|   UINT32                                FileOccupiedSize;
 | |
| 
 | |
|   ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE);
 | |
| 
 | |
|   FvLength = FwVolHeader->FvLength;
 | |
|   FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
 | |
|   FileOffset = FwVolHeader->HeaderLength;
 | |
| 
 | |
|   if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
 | |
|     ErasePolarity = 1;
 | |
|   } else {
 | |
|     ErasePolarity = 0;
 | |
|   }
 | |
| 
 | |
|   while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
 | |
|     // Get FileState which is the highest bit of the State
 | |
|     FileState = GetFileState (ErasePolarity, FfsFileHeader);
 | |
| 
 | |
|     switch (FileState) {
 | |
| 
 | |
|     case EFI_FILE_HEADER_INVALID:
 | |
|       FileOffset += sizeof(EFI_FFS_FILE_HEADER);
 | |
|       FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
 | |
|       break;
 | |
| 
 | |
|     case EFI_FILE_DATA_VALID:
 | |
|     case EFI_FILE_MARKED_FOR_UPDATE:
 | |
|       if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
 | |
|         ASSERT (FALSE);
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
| 
 | |
|       if (FfsFileHeader->Type == FileType) {
 | |
|         *FileHeader = FfsFileHeader;
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
 | |
|       FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
 | |
| 
 | |
|       FileOffset += FileOccupiedSize;
 | |
|       FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
 | |
|       break;
 | |
| 
 | |
|     case EFI_FILE_DELETED:
 | |
|       FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
 | |
|       FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
 | |
|       FileOffset += FileOccupiedSize;
 | |
|       FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
|   }
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GetImageContext (
 | |
|   IN  EFI_FFS_FILE_HEADER           *FfsHeader,
 | |
|   OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                              Status;
 | |
|   UINTN                                   ParsedLength;
 | |
|   UINTN                                   SectionSize;
 | |
|   UINTN                                   SectionLength;
 | |
|   EFI_COMMON_SECTION_HEADER               *Section;
 | |
|   VOID                                    *EfiImage;
 | |
|   UINTN                                   ImageAddress;
 | |
|   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY         *DebugEntry;
 | |
|   VOID                                    *CodeViewEntryPointer;
 | |
| 
 | |
|   Section = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
 | |
|   SectionSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
 | |
|   SectionSize -= sizeof (EFI_FFS_FILE_HEADER);
 | |
|   ParsedLength = 0;
 | |
|   EfiImage = NULL;
 | |
| 
 | |
|   while (ParsedLength < SectionSize) {
 | |
|     if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
 | |
|       EfiImage = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(Section + 1);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Size is 24 bits wide so mask upper 8 bits.
 | |
|     // SectionLength is adjusted it is 4 byte aligned.
 | |
|     // Go to the next section
 | |
|     //
 | |
|     SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
 | |
|     SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
 | |
|     ASSERT (SectionLength != 0);
 | |
|     ParsedLength += SectionLength;
 | |
|     Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
 | |
|   }
 | |
| 
 | |
|   if (EfiImage == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   // Initialize the Image Context
 | |
|   ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
 | |
|   ImageContext->Handle    = EfiImage;
 | |
|   ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
 | |
| 
 | |
|   Status =  PeCoffLoaderGetImageInfo (ImageContext);
 | |
|   if (!EFI_ERROR(Status) && ((VOID*)(UINTN)ImageContext->DebugDirectoryEntryRva != NULL)) {
 | |
|     ImageAddress = ImageContext->ImageAddress;
 | |
|     if (ImageContext->IsTeImage) {
 | |
|       ImageAddress += sizeof (EFI_TE_IMAGE_HEADER) - ((EFI_TE_IMAGE_HEADER*)EfiImage)->StrippedSize;
 | |
|     }
 | |
| 
 | |
|     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(ImageAddress + ImageContext->DebugDirectoryEntryRva);
 | |
|     if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
 | |
|       CodeViewEntryPointer = (VOID *) (ImageAddress + (UINTN) DebugEntry->RVA);
 | |
|       switch (* (UINT32 *) CodeViewEntryPointer) {
 | |
|       case CODEVIEW_SIGNATURE_NB10:
 | |
|         ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
 | |
|         break;
 | |
|       case CODEVIEW_SIGNATURE_RSDS:
 | |
|         ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
 | |
|         break;
 | |
|       case CODEVIEW_SIGNATURE_MTOC:
 | |
|         ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
 | |
|         break;
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize debug agent.
 | |
| 
 | |
|   This function is used to set up debug environment to support source level debugging.
 | |
|   If certain Debug Agent Library instance has to save some private data in the stack,
 | |
|   this function must work on the mode that doesn't return to the caller, then
 | |
|   the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
 | |
|   function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
 | |
|   responsible to invoke the passing-in function at the end of InitializeDebugAgent().
 | |
| 
 | |
|   If the parameter Function is not NULL, Debug Agent Library instance will invoke it by
 | |
|   passing in the Context to be its parameter.
 | |
| 
 | |
|   If Function() is NULL, Debug Agent Library instance will return after setup debug
 | |
|   environment.
 | |
| 
 | |
|   @param[in] InitFlag     Init flag is used to decide the initialize process.
 | |
|   @param[in] Context      Context needed according to InitFlag; it was optional.
 | |
|   @param[in] Function     Continue function called by debug agent library; it was
 | |
|                           optional.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| InitializeDebugAgent (
 | |
|   IN UINT32                InitFlag,
 | |
|   IN VOID                  *Context, OPTIONAL
 | |
|   IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   EFI_FFS_FILE_HEADER   *FfsHeader;
 | |
|   PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
 | |
| 
 | |
|   // Now we've got UART, check the Debug Agent Vector Table
 | |
|   // Note: The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure
 | |
|   // 'Align=4K' is defined into your FDF for this module.
 | |
|   ASSERT (((UINTN)DebugAgentVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
 | |
|   ArmWriteVBar ((UINTN)DebugAgentVectorTable);
 | |
| 
 | |
|   // We use InitFlag to know if DebugAgent has been initialized from
 | |
|   // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)
 | |
|   // modules
 | |
|   if (InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {
 | |
|     //
 | |
|     // Get the Sec or PrePeiCore module (defined as SEC type module)
 | |
|     //
 | |
|     Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdSecureFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);
 | |
|     if (!EFI_ERROR(Status)) {
 | |
|       Status = GetImageContext (FfsHeader,&ImageContext);
 | |
|       if (!EFI_ERROR(Status)) {
 | |
|         PeCoffLoaderRelocateImageExtraAction (&ImageContext);
 | |
|       }
 | |
|     }
 | |
|   } else if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
 | |
|     //
 | |
|     // Get the PrePi or PrePeiCore module (defined as SEC type module)
 | |
|     //
 | |
|     Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);
 | |
|     if (!EFI_ERROR(Status)) {
 | |
|       Status = GetImageContext (FfsHeader,&ImageContext);
 | |
|       if (!EFI_ERROR(Status)) {
 | |
|         PeCoffLoaderRelocateImageExtraAction (&ImageContext);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get the PeiCore module (defined as PEI_CORE type module)
 | |
|     //
 | |
|     Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdFvBaseAddress), EFI_FV_FILETYPE_PEI_CORE, &FfsHeader);
 | |
|     if (!EFI_ERROR(Status)) {
 | |
|       Status = GetImageContext (FfsHeader,&ImageContext);
 | |
|       if (!EFI_ERROR(Status)) {
 | |
|         PeCoffLoaderRelocateImageExtraAction (&ImageContext);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Enable/Disable the interrupt of debug timer and return the interrupt state
 | |
|   prior to the operation.
 | |
| 
 | |
|   If EnableStatus is TRUE, enable the interrupt of debug timer.
 | |
|   If EnableStatus is FALSE, disable the interrupt of debug timer.
 | |
| 
 | |
|   @param[in] EnableStatus    Enable/Disable.
 | |
| 
 | |
|   @return FALSE always.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| SaveAndSetDebugTimerInterrupt (
 | |
|   IN BOOLEAN                EnableStatus
 | |
|   )
 | |
| {
 | |
|   return FALSE;
 | |
| }
 | |
| 
 |