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