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