]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c
df25c6d49339dcc65453651f4c4799103db9ee03
[mirror_edk2.git] / IntelFrameworkPkg / Library / DxeSmmDriverEntryPoint / DriverEntryPoint.c
1 /** @file
2 This file implement EfiMain() for library class DxeSmmDriverEntryPoint.
3 EfiMain() is common driver entry point for all SMM driver who uses DxeSmmDriverEntryPoint
4 library class.
5
6 Copyright (c) 2006, Intel Corporation<BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17
18 #include <FrameworkSmm.h>
19
20 #include <Protocol/LoadedImage.h>
21 #include <Protocol/SmmBase.h>
22 #include <Protocol/DevicePath.h>
23
24 #include <Library/DxeSmmDriverEntryPoint.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/DebugLib.h>
27
28
29 EFI_BOOT_SERVICES *mBS;
30
31 /**
32 This function returns the size, in bytes,
33 of the device path data structure specified by DevicePath.
34 If DevicePath is NULL, then 0 is returned.
35
36 @param DevicePath A pointer to a device path data structure.
37
38 @return The size of a device path in bytes.
39
40 **/
41 STATIC
42 UINTN
43 EFIAPI
44 SmmGetDevicePathSize (
45 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
46 )
47 {
48 CONST EFI_DEVICE_PATH_PROTOCOL *Start;
49
50 if (DevicePath == NULL) {
51 return 0;
52 }
53
54 //
55 // Search for the end of the device path structure
56 //
57 Start = DevicePath;
58 while (!EfiIsDevicePathEnd (DevicePath)) {
59 DevicePath = EfiNextDevicePathNode (DevicePath);
60 }
61
62 //
63 // Compute the size and add back in the size of the end device path structure
64 //
65 return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
66 }
67
68 /**
69 This function appends the device path SecondDevicePath
70 to every device path instance in FirstDevicePath.
71
72 @param FirstDevicePath A pointer to a device path data structure.
73
74 @param SecondDevicePath A pointer to a device path data structure.
75
76 @return A pointer to the new device path is returned.
77 NULL is returned if space for the new device path could not be allocated from pool.
78 It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath
79 if they are no longer needed.
80
81 **/
82 EFI_DEVICE_PATH_PROTOCOL *
83 EFIAPI
84 SmmAppendDevicePath (
85 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
86 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
87 )
88 {
89 EFI_STATUS Status;
90 UINTN Size;
91 UINTN Size1;
92 UINTN Size2;
93 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
94 EFI_DEVICE_PATH_PROTOCOL *DevicePath2;
95
96 ASSERT (FirstDevicePath != NULL && SecondDevicePath != NULL);
97
98 //
99 // Allocate space for the combined device path. It only has one end node of
100 // length EFI_DEVICE_PATH_PROTOCOL
101 //
102 Size1 = SmmGetDevicePathSize (FirstDevicePath);
103 Size2 = SmmGetDevicePathSize (SecondDevicePath);
104 Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);
105
106 Status = mBS->AllocatePool (EfiBootServicesData, Size, (VOID **) &NewDevicePath);
107
108 if (EFI_SUCCESS == Status) {
109 mBS->CopyMem ((VOID *) NewDevicePath, (VOID *) FirstDevicePath, Size1);
110 //
111 // Over write Src1 EndNode and do the copy
112 //
113 DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
114 mBS->CopyMem ((VOID *) DevicePath2, (VOID *) SecondDevicePath, Size2);
115 }
116
117 return NewDevicePath;
118 }
119
120 /**
121 Unload function that is registered in the LoadImage protocol. It un-installs
122 protocols produced and deallocates pool used by the driver. Called by the core
123 when unloading the driver.
124
125 @param ImageHandle ImageHandle of the unloaded driver
126
127 @return Status of the ProcessModuleUnloadList.
128
129 **/
130 EFI_STATUS
131 EFIAPI
132 _DriverUnloadHandler (
133 EFI_HANDLE ImageHandle
134 )
135 {
136 EFI_STATUS Status;
137
138 //
139 // Call the unload handlers for all the modules
140 //
141 Status = ProcessModuleUnloadList (ImageHandle);
142
143 //
144 // If the driver specific unload handler does not return an error, then call all of the
145 // library destructors. If the unload handler returned an error, then the driver can not be
146 // unloaded, and the library destructors should not be called
147 //
148 if (!EFI_ERROR (Status)) {
149 ProcessLibraryDestructorList (ImageHandle, gST);
150 }
151
152 //
153 // Return the status from the driver specific unload handler
154 //
155 return Status;
156 }
157
158 /**
159 Enrty point to DXE SMM Driver.
160
161 @param ImageHandle ImageHandle of the loaded driver.
162 @param SystemTable Pointer to the EFI System Table.
163
164 @retval EFI_SUCCESS One or more of the drivers returned a success code.
165 @retval !EFI_SUCESS The return status from the last driver entry point in the list.
166
167 **/
168 EFI_STATUS
169 EFIAPI
170 _ModuleEntryPoint (
171 IN EFI_HANDLE ImageHandle,
172 IN EFI_SYSTEM_TABLE *SystemTable
173 )
174 {
175 EFI_STATUS Status;
176 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
177 EFI_SMM_BASE_PROTOCOL *SmmBase;
178 BOOLEAN InSmm;
179 EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath;
180 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
181 EFI_HANDLE Handle;
182
183 //
184 // Cache a pointer to the Boot Services Table
185 //
186 mBS = SystemTable->BootServices;
187
188 //
189 // Retrieve the Loaded Image Protocol
190 //
191 Status = mBS->HandleProtocol (
192 ImageHandle,
193 &gEfiLoadedImageProtocolGuid,
194 (VOID*)&LoadedImage
195 );
196 ASSERT_EFI_ERROR (Status);
197
198 //
199 // Retrieve SMM Base Protocol
200 //
201 Status = mBS->LocateProtocol (
202 &gEfiSmmBaseProtocolGuid,
203 NULL,
204 (VOID **) &SmmBase
205 );
206 ASSERT_EFI_ERROR (Status);
207
208 //
209 // Check to see if we are already in SMM
210 //
211 SmmBase->InSmm (SmmBase, &InSmm);
212
213 //
214 //
215 //
216 if (!InSmm) {
217 //
218 // Retrieve the Device Path Protocol from the DeviceHandle tha this driver was loaded from
219 //
220 Status = mBS->HandleProtocol (
221 LoadedImage->DeviceHandle,
222 &gEfiDevicePathProtocolGuid,
223 (VOID*)&ImageDevicePath
224 );
225 ASSERT_EFI_ERROR (Status);
226
227 //
228 // Build the full device path to the currently execuing image
229 //
230 CompleteFilePath = SmmAppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
231
232 //
233 // Load the image in memory to SMRAM; it will automatically generate the
234 // SMI.
235 //
236 Status = SmmBase->Register (SmmBase, CompleteFilePath, NULL, 0, &Handle, FALSE);
237 ASSERT_EFI_ERROR (Status);
238 return Status;
239 }
240
241 //
242 // Call constructor for all libraries
243 //
244 ProcessLibraryConstructorList (ImageHandle, SystemTable);
245
246 //
247 // Optionally install the unload handler
248 //
249 if (_gDriverUnloadImageCount > 0) {
250 Status = mBS->HandleProtocol (
251 ImageHandle,
252 &gEfiLoadedImageProtocolGuid,
253 (VOID **)&LoadedImage
254 );
255 ASSERT_EFI_ERROR (Status);
256 LoadedImage->Unload = _DriverUnloadHandler;
257 }
258
259 //
260 // Call the list of driver entry points
261 //
262 Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
263 if (EFI_ERROR (Status)) {
264 ProcessLibraryDestructorList (ImageHandle, SystemTable);
265 }
266
267 return Status;
268 }
269
270 /**
271 Enrty point wrapper of DXE SMM Driver.
272
273 @param ImageHandle ImageHandle of the loaded driver.
274 @param SystemTable Pointer to the EFI System Table.
275
276 @retval EFI_SUCCESS One or more of the drivers returned a success code.
277 @retval !EFI_SUCESS The return status from the last driver entry point in the list.
278
279 **/
280 EFI_STATUS
281 EFIAPI
282 EfiMain (
283 IN EFI_HANDLE ImageHandle,
284 IN EFI_SYSTEM_TABLE *SystemTable
285 )
286 {
287 return _ModuleEntryPoint (ImageHandle, SystemTable);
288 }