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