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