3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 PeiNt32PeCoffExtraActionLib.c
12 Provides services to perform additional actions to relocate and unload
13 PE/Coff image for NT32 environment specific purpose such as souce level debug.
14 This version only works for PEI phase
19 // The package level header files this module uses
22 #include <WinNtPeim.h>
25 // The protocols, PPI and GUID defintions for this module
27 #include <Ppi/NtThunk.h>
30 #include <Library/PeCoffLib.h>
31 #include <Library/PeiServicesLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/BaseLib.h>
34 #include <Library/PeCoffExtraActionLib.h>
37 // Cache of WinNtThunk protocol
39 EFI_WIN_NT_THUNK_PROTOCOL
*mWinNt
= NULL
;
42 The function caches the pointer of the WinNT thunk functions
43 It will ASSERT() if NT thunk ppi is not installed.
45 @retval EFI_SUCCESS WinNT thunk protocol is found and cached.
50 Nt32PeCoffGetWinNtThunkStucture (
53 PEI_NT_THUNK_PPI
*NtThunkPpi
;
58 // Locate NtThunkPpi for retrieving standard output handle
60 Status
= PeiServicesLocatePpi (
67 ASSERT_EFI_ERROR (Status
);
69 mWinNt
= (EFI_WIN_NT_THUNK_PROTOCOL
*) NtThunkPpi
->NtThunk ();
75 Convert the passed in Ascii string to Unicode.
77 This function Convert the passed in Ascii string to Unicode.Optionally return
78 the length of the strings..
80 @param AsciiString Pointer to an AscII string
81 @param StrLen Length of string
83 @return Pointer to malloc'ed Unicode version of Ascii
89 IN UINTN
*StrLen OPTIONAL
96 // Allocate a buffer for unicode string
98 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++)
100 Unicode
= mWinNt
->HeapAlloc ( mWinNt
->GetProcessHeap (),
102 ((Index
+ 1) * sizeof (CHAR16
))
104 if (Unicode
== NULL
) {
108 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++) {
109 Unicode
[Index
] = (CHAR16
) Ascii
[Index
];
112 Unicode
[Index
] = '\0';
114 if (StrLen
!= NULL
) {
122 Performs additional actions after a PE/COFF image has been loaded and relocated.
124 For NT32, this function load symbols to support source level debugging.
126 If ImageContext is NULL, then ASSERT().
128 @param ImageContext Pointer to the image context structure that describes the
129 PE/COFF image that has already been loaded and relocated.
134 PeCoffLoaderRelocateImageExtraAction (
135 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
143 ASSERT (ImageContext
!= NULL
);
145 if (mWinNt
== NULL
) {
146 Nt32PeCoffGetWinNtThunkStucture ();
149 // If we load our own PE COFF images the Windows debugger can not source
150 // level debug our code. If a valid PDB pointer exists usw it to load
151 // the *.dll file as a library using Windows* APIs. This allows
152 // source level debug. The image is still loaded and relocated
153 // in the Framework memory space like on a real system (by the code above),
154 // but the entry point points into the DLL loaded by the code bellow.
157 DllEntryPoint
= NULL
;
160 // Load the DLL if it's not an EBC image.
162 if ((ImageContext
->PdbPointer
!= NULL
) &&
163 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
165 // Convert filename from ASCII to Unicode
167 DllFileName
= AsciiToUnicode (ImageContext
->PdbPointer
, &Index
);
170 // Check that we have a valid filename
172 if (Index
< 5 || DllFileName
[Index
- 4] != '.') {
173 mWinNt
->HeapFree (mWinNt
->GetProcessHeap (), 0, DllFileName
);
176 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
177 // The image will run, but we just can't source level debug. If we
178 // return an error the image will not run.
183 // Replace .PDB with .DLL on the filename
185 DllFileName
[Index
- 3] = 'D';
186 DllFileName
[Index
- 2] = 'L';
187 DllFileName
[Index
- 1] = 'L';
190 // Load the .DLL file into the user process's address space for source
193 Library
= mWinNt
->LoadLibraryEx (DllFileName
, NULL
, DONT_RESOLVE_DLL_REFERENCES
);
194 if (Library
!= NULL
) {
196 // InitializeDriver is the entry point we put in all our EFI DLL's. The
197 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the
198 // normal DLL entry point of DllMain, and prevents other modules that are
199 // referenced in side the DllFileName from being loaded. There is no error
200 // checking as the we can point to the PE32 image loaded by Tiano. This
201 // step is only needed for source level debugging
203 DllEntryPoint
= (VOID
*) (UINTN
) mWinNt
->GetProcAddress (Library
, "InitializeDriver");
207 if ((Library
!= NULL
) && (DllEntryPoint
!= NULL
)) {
208 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
209 DEBUG ((EFI_D_INFO
, "LoadLibraryEx (%s,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName
));
211 DEBUG ((EFI_D_ERROR
, "WARNING: No source level debug %s. \n", DllFileName
));
214 mWinNt
->HeapFree (mWinNt
->GetProcessHeap (), 0, DllFileName
);
218 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
219 // The image will run, but we just can't source level debug. If we
220 // return an error the image will not run.
226 Performs additional actions just before a PE/COFF image is unloaded. Any resources
227 that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
229 For NT32, this function unloads symbols for source level debugging.
231 If ImageContext is NULL, then ASSERT().
233 @param ImageContext Pointer to the image context structure that describes the
234 PE/COFF image that is being unloaded.
239 PeCoffLoaderUnloadImageExtraAction (
240 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
243 ASSERT (ImageContext
!= NULL
);