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