]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
ArmPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ArmPkg / Library / DebugAgentSymbolsBaseLib / DebugAgentSymbolsBaseLib.c
CommitLineData
65cd89d0 1/** @file\r
2* Main file supporting the SEC Phase for Versatile Express\r
3*\r
6d0ca257 4* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
65cd89d0 5*\r
4059386c 6* SPDX-License-Identifier: BSD-2-Clause-Patent\r
65cd89d0 7*\r
8**/\r
9\r
10#include <Uefi.h>\r
11#include <Library/BaseLib.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/DebugLib.h>\r
14#include <Library/DebugAgentLib.h>\r
15#include <Library/PcdLib.h>\r
16#include <Library/PeCoffExtraActionLib.h>\r
17#include <Library/PeCoffLib.h>\r
18\r
19#include <Pi/PiFirmwareFile.h>\r
20#include <Pi/PiFirmwareVolume.h>\r
21\r
22#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
23 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
24\r
9d6b024d 25\r
26// Vector Table for Sec Phase\r
27VOID\r
28DebugAgentVectorTable (\r
29 VOID\r
30 );\r
31\r
65cd89d0 32/**\r
33 Returns the highest bit set of the State field\r
34\r
35 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY\r
36 in the Attributes field.\r
37 @param FfsHeader Pointer to FFS File Header\r
38\r
39\r
40 @retval the highest bit in the State field\r
41\r
42**/\r
43STATIC\r
44EFI_FFS_FILE_STATE\r
45GetFileState (\r
46 IN UINT8 ErasePolarity,\r
47 IN EFI_FFS_FILE_HEADER *FfsHeader\r
48 )\r
49{\r
50 EFI_FFS_FILE_STATE FileState;\r
51 EFI_FFS_FILE_STATE HighestBit;\r
52\r
53 FileState = FfsHeader->State;\r
54\r
55 if (ErasePolarity != 0) {\r
56 FileState = (EFI_FFS_FILE_STATE)~FileState;\r
57 }\r
58\r
59 HighestBit = 0x80;\r
60 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
61 HighestBit >>= 1;\r
62 }\r
63\r
64 return HighestBit;\r
65}\r
66\r
67/**\r
68 Calculates the checksum of the header of a file.\r
69 The header is a zero byte checksum, so zero means header is good\r
70\r
71 @param FfsHeader Pointer to FFS File Header\r
72\r
73 @retval Checksum of the header\r
74\r
75**/\r
76STATIC\r
77UINT8\r
78CalculateHeaderChecksum (\r
79 IN EFI_FFS_FILE_HEADER *FileHeader\r
80 )\r
81{\r
82 UINT8 Sum;\r
83\r
84 // Calculate the sum of the header\r
85 Sum = CalculateSum8 ((CONST VOID*)FileHeader,sizeof(EFI_FFS_FILE_HEADER));\r
86\r
87 // State field (since this indicates the different state of file).\r
88 Sum = (UINT8)(Sum - FileHeader->State);\r
89\r
90 // Checksum field of the file is not part of the header checksum.\r
91 Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);\r
92\r
93 return Sum;\r
94}\r
95\r
96EFI_STATUS\r
97GetFfsFile (\r
98 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,\r
99 IN EFI_FV_FILETYPE FileType,\r
100 OUT EFI_FFS_FILE_HEADER **FileHeader\r
101 )\r
102{\r
103 UINT64 FvLength;\r
104 UINTN FileOffset;\r
105 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
106 UINT8 ErasePolarity;\r
107 UINT8 FileState;\r
108 UINT32 FileLength;\r
109 UINT32 FileOccupiedSize;\r
110\r
111 ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE);\r
112\r
113 FvLength = FwVolHeader->FvLength;\r
114 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
115 FileOffset = FwVolHeader->HeaderLength;\r
116\r
117 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
118 ErasePolarity = 1;\r
119 } else {\r
120 ErasePolarity = 0;\r
121 }\r
122\r
123 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
124 // Get FileState which is the highest bit of the State\r
125 FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
126\r
127 switch (FileState) {\r
128\r
129 case EFI_FILE_HEADER_INVALID:\r
130 FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
131 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
132 break;\r
133\r
134 case EFI_FILE_DATA_VALID:\r
135 case EFI_FILE_MARKED_FOR_UPDATE:\r
136 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
137 ASSERT (FALSE);\r
138 return EFI_NOT_FOUND;\r
139 }\r
140\r
141 if (FfsFileHeader->Type == FileType) {\r
142 *FileHeader = FfsFileHeader;\r
143 return EFI_SUCCESS;\r
144 }\r
145\r
146 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
147 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
148\r
149 FileOffset += FileOccupiedSize;\r
150 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
151 break;\r
152\r
153 case EFI_FILE_DELETED:\r
154 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
155 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
156 FileOffset += FileOccupiedSize;\r
157 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
158 break;\r
159\r
160 default:\r
161 return EFI_NOT_FOUND;\r
162 }\r
163 }\r
164 return EFI_NOT_FOUND;\r
165}\r
166\r
167EFI_STATUS\r
168GetImageContext (\r
169 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
170 OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
171 )\r
172{\r
173 EFI_STATUS Status;\r
174 UINTN ParsedLength;\r
175 UINTN SectionSize;\r
176 UINTN SectionLength;\r
177 EFI_COMMON_SECTION_HEADER *Section;\r
178 VOID *EfiImage;\r
179 UINTN ImageAddress;\r
180 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
181 VOID *CodeViewEntryPointer;\r
182\r
183 Section = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);\r
184 SectionSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;\r
185 SectionSize -= sizeof (EFI_FFS_FILE_HEADER);\r
186 ParsedLength = 0;\r
187 EfiImage = NULL;\r
188\r
189 while (ParsedLength < SectionSize) {\r
190 if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {\r
191 EfiImage = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(Section + 1);\r
192 break;\r
193 }\r
194\r
195 //\r
196 // Size is 24 bits wide so mask upper 8 bits.\r
197 // SectionLength is adjusted it is 4 byte aligned.\r
198 // Go to the next section\r
199 //\r
200 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
201 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
202 ASSERT (SectionLength != 0);\r
203 ParsedLength += SectionLength;\r
204 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
205 }\r
206\r
207 if (EfiImage == NULL) {\r
208 return EFI_NOT_FOUND;\r
209 }\r
210\r
211 // Initialize the Image Context\r
212 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
213 ImageContext->Handle = EfiImage;\r
214 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;\r
215\r
216 Status = PeCoffLoaderGetImageInfo (ImageContext);\r
c63626b7 217 if (!EFI_ERROR(Status) && ((VOID*)(UINTN)ImageContext->DebugDirectoryEntryRva != NULL)) {\r
65cd89d0 218 ImageAddress = ImageContext->ImageAddress;\r
219 if (ImageContext->IsTeImage) {\r
220 ImageAddress += sizeof (EFI_TE_IMAGE_HEADER) - ((EFI_TE_IMAGE_HEADER*)EfiImage)->StrippedSize;\r
221 }\r
222\r
223 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(ImageAddress + ImageContext->DebugDirectoryEntryRva);\r
224 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
225 CodeViewEntryPointer = (VOID *) (ImageAddress + (UINTN) DebugEntry->RVA);\r
226 switch (* (UINT32 *) CodeViewEntryPointer) {\r
227 case CODEVIEW_SIGNATURE_NB10:\r
228 ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
9201b044 229 break;\r
65cd89d0 230 case CODEVIEW_SIGNATURE_RSDS:\r
231 ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
9201b044 232 break;\r
65cd89d0 233 case CODEVIEW_SIGNATURE_MTOC:\r
234 ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);\r
235 break;\r
236 default:\r
237 break;\r
238 }\r
239 }\r
240 }\r
241\r
242 return Status;\r
243}\r
244\r
245/**\r
246 Initialize debug agent.\r
247\r
248 This function is used to set up debug environment to support source level debugging.\r
249 If certain Debug Agent Library instance has to save some private data in the stack,\r
250 this function must work on the mode that doesn't return to the caller, then\r
251 the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
252 function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
253 responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
254\r
d0d8a17d 255 If the parameter Function is not NULL, Debug Agent Library instance will invoke it by\r
65cd89d0 256 passing in the Context to be its parameter.\r
257\r
258 If Function() is NULL, Debug Agent Library instance will return after setup debug\r
259 environment.\r
260\r
261 @param[in] InitFlag Init flag is used to decide the initialize process.\r
262 @param[in] Context Context needed according to InitFlag; it was optional.\r
263 @param[in] Function Continue function called by debug agent library; it was\r
264 optional.\r
265\r
266**/\r
267VOID\r
268EFIAPI\r
269InitializeDebugAgent (\r
270 IN UINT32 InitFlag,\r
271 IN VOID *Context, OPTIONAL\r
272 IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276 EFI_FFS_FILE_HEADER *FfsHeader;\r
277 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
278\r
d0d8a17d 279 // We use InitFlag to know if DebugAgent has been initialized from\r
65cd89d0 280 // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)\r
281 // modules\r
282 if (InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {\r
283 //\r
cc1e8149 284 // Get the Sec or PrePeiCore module (defined as SEC type module)\r
65cd89d0 285 //\r
bb5420bb 286 Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdSecureFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);\r
65cd89d0 287 if (!EFI_ERROR(Status)) {\r
288 Status = GetImageContext (FfsHeader,&ImageContext);\r
289 if (!EFI_ERROR(Status)) {\r
290 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
291 }\r
292 }\r
293 } else if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {\r
294 //\r
295 // Get the PrePi or PrePeiCore module (defined as SEC type module)\r
296 //\r
bb5420bb 297 Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);\r
65cd89d0 298 if (!EFI_ERROR(Status)) {\r
299 Status = GetImageContext (FfsHeader,&ImageContext);\r
300 if (!EFI_ERROR(Status)) {\r
301 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
302 }\r
303 }\r
304\r
305 //\r
306 // Get the PeiCore module (defined as PEI_CORE type module)\r
307 //\r
bb5420bb 308 Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)PcdGet64 (PcdFvBaseAddress), EFI_FV_FILETYPE_PEI_CORE, &FfsHeader);\r
65cd89d0 309 if (!EFI_ERROR(Status)) {\r
310 Status = GetImageContext (FfsHeader,&ImageContext);\r
311 if (!EFI_ERROR(Status)) {\r
312 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
313 }\r
314 }\r
315 }\r
316}\r
317\r
318/**\r
319 Enable/Disable the interrupt of debug timer and return the interrupt state\r
320 prior to the operation.\r
321\r
322 If EnableStatus is TRUE, enable the interrupt of debug timer.\r
323 If EnableStatus is FALSE, disable the interrupt of debug timer.\r
324\r
325 @param[in] EnableStatus Enable/Disable.\r
326\r
327 @return FALSE always.\r
328\r
329**/\r
330BOOLEAN\r
331EFIAPI\r
332SaveAndSetDebugTimerInterrupt (\r
333 IN BOOLEAN EnableStatus\r
334 )\r
335{\r
336 return FALSE;\r
337}\r
338\r