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