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