VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c

最後變更 在這個檔案是 99404,由 vboxsync 提交於 2 年 前

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 9.0 KB
 
1/** @file
2 PE/Coff Extra Action library instances.
3
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <PeCoffExtraActionLib.h>
10
11#ifdef VBOX
12#include "VBoxPkg.h"
13#include "../../../../DevEFI.h"
14
15
16
17static void vboxImageEvtU64(uint32_t uCmd, uint64_t uValue)
18{
19 RTUINT64U u; /* 64-bit shift builtins. */
20 u.u = uValue;
21 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[3]));
22 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[2]));
23 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[1]));
24 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[0]));
25}
26
27static void vboxImageEvtString(uint32_t uCmd, const char *pszName)
28{
29 unsigned char uch;
30 while ((uch = *pszName++) != '\0')
31 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, uch));
32}
33
34static void vboxImageEvtEmitOne(PE_COFF_LOADER_IMAGE_CONTEXT const *pImageCtx, uint32_t uEvt)
35{
36 ASMOutU32(EFI_PORT_IMAGE_EVENT, uEvt);
37 if (pImageCtx->DestinationAddress)
38 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, pImageCtx->DestinationAddress);
39 else
40 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, pImageCtx->ImageAddress);
41 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_SIZE0, pImageCtx->ImageSize);
42 if (pImageCtx->PdbPointer)
43 vboxImageEvtString(EFI_IMAGE_EVT_CMD_NAME, pImageCtx->PdbPointer);
44 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_COMPLETE);
45}
46#endif
47
48
49#ifdef VBOX_SOURCE_DEBUG_ENABLE
50/**
51 Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
52
53 It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
54
55
56 @param RegisterIndex Index of Dr register. The value range is from 0 to 3.
57 @param Dr7 Value of Dr7 register.
58
59 @return TRUE The hardware breakpoint specified in the Drx is enabled.
60 @return FALSE The hardware breakpoint specified in the Drx is disabled.
61
62**/
63BOOLEAN
64IsDrxEnabled (
65 IN UINT8 RegisterIndex,
66 IN UINTN Dr7
67 )
68{
69 return (BOOLEAN)(((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
70}
71
72/**
73 Common routine to report the PE/COFF image loading/relocating or unloading event.
74
75 If ImageContext is NULL, then ASSERT().
76
77 @param ImageContext Pointer to the image context structure that describes the
78 PE/COFF image.
79 @param Signature IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.
80
81**/
82VOID
83PeCoffLoaderExtraActionCommon (
84 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
85 IN UINTN Signature
86 )
87{
88 BOOLEAN InterruptState;
89 UINTN Dr0;
90 UINTN Dr1;
91 UINTN Dr2;
92 UINTN Dr3;
93 UINTN Dr7;
94 UINTN Cr4;
95 UINTN NewDr7;
96 UINT8 LoadImageMethod;
97 UINT8 DebugAgentStatus;
98 IA32_DESCRIPTOR IdtDescriptor;
99 IA32_IDT_GATE_DESCRIPTOR OriginalIdtEntry;
100 BOOLEAN IdtEntryHooked;
101 UINT32 RegEdx;
102
103 ASSERT (ImageContext != NULL);
104
105 if (ImageContext->PdbPointer != NULL) {
106 DEBUG ((DEBUG_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
107 }
108
109 //
110 // Disable interrupts and save the current interrupt state
111 //
112 InterruptState = SaveAndDisableInterrupts ();
113
114 IdtEntryHooked = FALSE;
115 LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
116 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
117 //
118 // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)
119 // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3
120 //
121 AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
122 if ((RegEdx & BIT2) == 0) {
123 LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
124 }
125 }
126
127 AsmReadIdtr (&IdtDescriptor);
128 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
129 if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
130 //
131 // Do not trigger INT3 if Debug Agent did not setup IDT entries.
132 //
133 return;
134 }
135 } else {
136 if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {
137 //
138 // Save and update IDT entry for INT1
139 //
140 SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
141 IdtEntryHooked = TRUE;
142 }
143 }
144
145 //
146 // Save Debug Register State
147 //
148 Dr0 = AsmReadDr0 ();
149 Dr1 = AsmReadDr1 ();
150 Dr2 = AsmReadDr2 ();
151 Dr3 = AsmReadDr3 ();
152 Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
153 Cr4 = AsmReadCr4 ();
154
155 //
156 // DR0 = Signature
157 // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
158 // DR2 = The pointer to the ImageContext structure
159 // DR3 = IO_PORT_BREAKPOINT_ADDRESS
160 // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
161 // CR4 = Make sure DE(BIT3) is set
162 //
163 AsmWriteDr7 (BIT10);
164 AsmWriteDr0 (Signature);
165 AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
166 AsmWriteDr2 ((UINTN)ImageContext);
167 AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
168
169 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
170 AsmWriteDr7 (0x20000480);
171 AsmWriteCr4 (Cr4 | BIT3);
172 //
173 // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
174 // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
175 //
176 do {
177 DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
178 } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
179 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
180 //
181 // Generate a software break point.
182 //
183 CpuBreakpoint ();
184 }
185
186 //
187 // Restore Debug Register State only when Host didn't change it inside exception handler.
188 // E.g.: User halts the target and sets the HW breakpoint while target is
189 // in the above exception handler
190 //
191 NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
192 if (!IsDrxEnabled (0, NewDr7) && ((AsmReadDr0 () == 0) || (AsmReadDr0 () == Signature))) {
193 //
194 // If user changed Dr3 (by setting HW bp in the above exception handler,
195 // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
196 //
197 AsmWriteDr0 (Dr0);
198 }
199
200 if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN)ImageContext->PdbPointer)) {
201 AsmWriteDr1 (Dr1);
202 }
203
204 if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN)ImageContext)) {
205 AsmWriteDr2 (Dr2);
206 }
207
208 if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
209 AsmWriteDr3 (Dr3);
210 }
211
212 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
213 if (AsmReadCr4 () == (Cr4 | BIT3)) {
214 AsmWriteCr4 (Cr4);
215 }
216
217 if (NewDr7 == 0x20000480) {
218 AsmWriteDr7 (Dr7);
219 }
220 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
221 if (NewDr7 == BIT10) {
222 AsmWriteDr7 (Dr7);
223 }
224 }
225
226 //
227 // Restore original IDT entry for INT1 if it was hooked.
228 //
229 if (IdtEntryHooked) {
230 RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
231 }
232
233 //
234 // Restore the interrupt state
235 //
236 SetInterruptState (InterruptState);
237}
238#endif
239
240/**
241 Performs additional actions after a PE/COFF image has been loaded and relocated.
242
243 @param ImageContext Pointer to the image context structure that describes the
244 PE/COFF image that has already been loaded and relocated.
245
246**/
247VOID
248EFIAPI
249PeCoffLoaderRelocateImageExtraAction (
250 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
251 )
252{
253#ifdef VBOX_SOURCE_DEBUG_ENABLE
254 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);
255#endif
256
257#ifdef VBOX
258# if ARCH_BITS == 32
259 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_LOAD32);
260# else
261 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_LOAD64);
262# endif
263#endif
264}
265
266/**
267 Performs additional actions just before a PE/COFF image is unloaded. Any resources
268 that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
269
270 @param ImageContext Pointer to the image context structure that describes the
271 PE/COFF image that is being unloaded.
272
273**/
274VOID
275EFIAPI
276PeCoffLoaderUnloadImageExtraAction (
277 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
278 )
279{
280#ifdef VBOX_SOURCE_DEBUG_ENABLE
281 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
282#endif
283
284#ifdef VBOX
285# if ARCH_BITS == 32
286 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_UNLOAD32);
287# else
288 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_UNLOAD64);
289# endif
290#endif
291}
292
293#ifdef VBOX
294VOID
295EFIAPI
296VBoxPeCoffLoaderMoveImageExtraAction(
297 IN PHYSICAL_ADDRESS OldBase,
298 IN PHYSICAL_ADDRESS NewBase
299 )
300{
301#if ARCH_BITS == 32
302 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_START_RELOC32);
303#else
304 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_START_RELOC64);
305#endif
306 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, NewBase);
307 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR1, OldBase);
308 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_COMPLETE);
309}
310#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette