2 * Main file supporting the SEC Phase for Versatile Express
4 * Copyright (c) 2011, ARM Limited. All rights reserved.
6 * This program and the accompanying materials
7 * are licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/DebugAgentLib.h>
21 #include <Library/PcdLib.h>
22 #include <Library/PeCoffExtraActionLib.h>
23 #include <Library/PeCoffLib.h>
25 #include <Pi/PiFirmwareFile.h>
26 #include <Pi/PiFirmwareVolume.h>
28 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
29 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
32 Returns the highest bit set of the State field
34 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
35 in the Attributes field.
36 @param FfsHeader Pointer to FFS File Header
39 @retval the highest bit in the State field
45 IN UINT8 ErasePolarity
,
46 IN EFI_FFS_FILE_HEADER
*FfsHeader
49 EFI_FFS_FILE_STATE FileState
;
50 EFI_FFS_FILE_STATE HighestBit
;
52 FileState
= FfsHeader
->State
;
54 if (ErasePolarity
!= 0) {
55 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
59 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
67 Calculates the checksum of the header of a file.
68 The header is a zero byte checksum, so zero means header is good
70 @param FfsHeader Pointer to FFS File Header
72 @retval Checksum of the header
77 CalculateHeaderChecksum (
78 IN EFI_FFS_FILE_HEADER
*FileHeader
83 // Calculate the sum of the header
84 Sum
= CalculateSum8 ((CONST VOID
*)FileHeader
,sizeof(EFI_FFS_FILE_HEADER
));
86 // State field (since this indicates the different state of file).
87 Sum
= (UINT8
)(Sum
- FileHeader
->State
);
89 // Checksum field of the file is not part of the header checksum.
90 Sum
= (UINT8
)(Sum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
97 IN EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
,
98 IN EFI_FV_FILETYPE FileType
,
99 OUT EFI_FFS_FILE_HEADER
**FileHeader
104 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
108 UINT32 FileOccupiedSize
;
110 ASSERT (FwVolHeader
->Signature
== EFI_FVH_SIGNATURE
);
112 FvLength
= FwVolHeader
->FvLength
;
113 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+ FwVolHeader
->HeaderLength
);
114 FileOffset
= FwVolHeader
->HeaderLength
;
116 if (FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
122 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
123 // Get FileState which is the highest bit of the State
124 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
128 case EFI_FILE_HEADER_INVALID
:
129 FileOffset
+= sizeof(EFI_FFS_FILE_HEADER
);
130 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ sizeof(EFI_FFS_FILE_HEADER
));
133 case EFI_FILE_DATA_VALID
:
134 case EFI_FILE_MARKED_FOR_UPDATE
:
135 if (CalculateHeaderChecksum (FfsFileHeader
) != 0) {
137 return EFI_NOT_FOUND
;
140 if (FfsFileHeader
->Type
== FileType
) {
141 *FileHeader
= FfsFileHeader
;
145 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
146 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
148 FileOffset
+= FileOccupiedSize
;
149 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
152 case EFI_FILE_DELETED
:
153 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
154 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
155 FileOffset
+= FileOccupiedSize
;
156 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
160 return EFI_NOT_FOUND
;
163 return EFI_NOT_FOUND
;
168 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
169 OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
176 EFI_COMMON_SECTION_HEADER
*Section
;
179 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
180 VOID
*CodeViewEntryPointer
;
182 Section
= (EFI_COMMON_SECTION_HEADER
*)(FfsHeader
+ 1);
183 SectionSize
= *(UINT32
*)(FfsHeader
->Size
) & 0x00FFFFFF;
184 SectionSize
-= sizeof (EFI_FFS_FILE_HEADER
);
188 while (ParsedLength
< SectionSize
) {
189 if ((Section
->Type
== EFI_SECTION_PE32
) || (Section
->Type
== EFI_SECTION_TE
)) {
190 EfiImage
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Section
+ 1);
195 // Size is 24 bits wide so mask upper 8 bits.
196 // SectionLength is adjusted it is 4 byte aligned.
197 // Go to the next section
199 SectionLength
= *(UINT32
*)Section
->Size
& 0x00FFFFFF;
200 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
201 ASSERT (SectionLength
!= 0);
202 ParsedLength
+= SectionLength
;
203 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
206 if (EfiImage
== NULL
) {
207 return EFI_NOT_FOUND
;
210 // Initialize the Image Context
211 ZeroMem (ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
212 ImageContext
->Handle
= EfiImage
;
213 ImageContext
->ImageRead
= PeCoffLoaderImageReadFromMemory
;
215 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
216 if (!EFI_ERROR(Status
) && ((VOID
*)ImageContext
->DebugDirectoryEntryRva
!= NULL
)) {
217 ImageAddress
= ImageContext
->ImageAddress
;
218 if (ImageContext
->IsTeImage
) {
219 ImageAddress
+= sizeof (EFI_TE_IMAGE_HEADER
) - ((EFI_TE_IMAGE_HEADER
*)EfiImage
)->StrippedSize
;
222 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(ImageAddress
+ ImageContext
->DebugDirectoryEntryRva
);
223 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
224 CodeViewEntryPointer
= (VOID
*) (ImageAddress
+ (UINTN
) DebugEntry
->RVA
);
225 switch (* (UINT32
*) CodeViewEntryPointer
) {
226 case CODEVIEW_SIGNATURE_NB10
:
227 ImageContext
->PdbPointer
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
228 case CODEVIEW_SIGNATURE_RSDS
:
229 ImageContext
->PdbPointer
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
230 case CODEVIEW_SIGNATURE_MTOC
:
231 ImageContext
->PdbPointer
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
);
243 Initialize debug agent.
245 This function is used to set up debug environment to support source level debugging.
246 If certain Debug Agent Library instance has to save some private data in the stack,
247 this function must work on the mode that doesn't return to the caller, then
248 the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
249 function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
250 responsible to invoke the passing-in function at the end of InitializeDebugAgent().
252 If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by
253 passing in the Context to be its parameter.
255 If Function() is NULL, Debug Agent Library instance will return after setup debug
258 @param[in] InitFlag Init flag is used to decide the initialize process.
259 @param[in] Context Context needed according to InitFlag; it was optional.
260 @param[in] Function Continue function called by debug agent library; it was
266 InitializeDebugAgent (
268 IN VOID
*Context
, OPTIONAL
269 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
273 EFI_FFS_FILE_HEADER
*FfsHeader
;
274 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
276 // We use InitFlag to know if DebugAgent has been intialized from
277 // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)
279 if (InitFlag
== DEBUG_AGENT_INIT_PREMEM_SEC
) {
281 // Get the PrePi or PrePeiCore module (defined as SEC type module)
283 Status
= GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER
*)PcdGet32(PcdSecureFdBaseAddress
), EFI_FV_FILETYPE_SECURITY_CORE
, &FfsHeader
);
284 if (!EFI_ERROR(Status
)) {
285 Status
= GetImageContext (FfsHeader
,&ImageContext
);
286 if (!EFI_ERROR(Status
)) {
287 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
290 } else if (InitFlag
== DEBUG_AGENT_INIT_POSTMEM_SEC
) {
292 // Get the PrePi or PrePeiCore module (defined as SEC type module)
294 Status
= GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER
*)PcdGet32(PcdNormalFvBaseAddress
), EFI_FV_FILETYPE_SECURITY_CORE
, &FfsHeader
);
295 if (!EFI_ERROR(Status
)) {
296 Status
= GetImageContext (FfsHeader
,&ImageContext
);
297 if (!EFI_ERROR(Status
)) {
298 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
303 // Get the PeiCore module (defined as PEI_CORE type module)
305 Status
= GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER
*)PcdGet32(PcdNormalFvBaseAddress
), EFI_FV_FILETYPE_PEI_CORE
, &FfsHeader
);
306 if (!EFI_ERROR(Status
)) {
307 Status
= GetImageContext (FfsHeader
,&ImageContext
);
308 if (!EFI_ERROR(Status
)) {
309 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
316 Enable/Disable the interrupt of debug timer and return the interrupt state
317 prior to the operation.
319 If EnableStatus is TRUE, enable the interrupt of debug timer.
320 If EnableStatus is FALSE, disable the interrupt of debug timer.
322 @param[in] EnableStatus Enable/Disable.
324 @return FALSE always.
329 SaveAndSetDebugTimerInterrupt (
330 IN BOOLEAN EnableStatus