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