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