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