2 This file implement EfiMain() for library class DxeSmmDriverEntryPoint.
3 EfiMain() is common driver entry point for all SMM driver who uses DxeSmmDriverEntryPoint
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
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.
18 #include <FrameworkSmm.h>
20 #include <Protocol/LoadedImage.h>
21 #include <Protocol/SmmBase.h>
22 #include <Protocol/DevicePath.h>
24 #include <Library/DxeSmmDriverEntryPoint.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/DebugLib.h>
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.
34 @param DevicePath A pointer to a device path data structure.
36 @return The size of a device path in bytes.
42 SmmGetDevicePathSize (
43 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
46 CONST EFI_DEVICE_PATH_PROTOCOL
*Start
;
48 if (DevicePath
== NULL
) {
53 // Search for the end of the device path structure
56 while (!EfiIsDevicePathEnd (DevicePath
)) {
57 DevicePath
= EfiNextDevicePathNode (DevicePath
);
61 // Compute the size and add back in the size of the end device path structure
63 return ((UINTN
) DevicePath
- (UINTN
) Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
67 This function appends the device path SecondDevicePath
68 to every device path instance in FirstDevicePath.
70 @param FirstDevicePath A pointer to a device path data structure.
72 @param SecondDevicePath A pointer to a device path data structure.
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.
80 EFI_DEVICE_PATH_PROTOCOL
*
83 IN CONST EFI_DEVICE_PATH_PROTOCOL
*FirstDevicePath
,
84 IN CONST EFI_DEVICE_PATH_PROTOCOL
*SecondDevicePath
91 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
92 EFI_DEVICE_PATH_PROTOCOL
*DevicePath2
;
94 ASSERT (FirstDevicePath
!= NULL
&& SecondDevicePath
!= NULL
);
97 // Allocate space for the combined device path. It only has one end node of
98 // length EFI_DEVICE_PATH_PROTOCOL
100 Size1
= SmmGetDevicePathSize (FirstDevicePath
);
101 Size2
= SmmGetDevicePathSize (SecondDevicePath
);
102 Size
= Size1
+ Size2
- sizeof (EFI_DEVICE_PATH_PROTOCOL
);
104 Status
= gBS
->AllocatePool (EfiBootServicesData
, Size
, (VOID
**) &NewDevicePath
);
106 if (EFI_SUCCESS
== Status
) {
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.
111 gBS
->CopyMem ((VOID
*) NewDevicePath
, (VOID
*) FirstDevicePath
, Size1
);
113 // Over write Src1 EndNode and do the copy
115 DevicePath2
= (EFI_DEVICE_PATH_PROTOCOL
*) ((CHAR8
*) NewDevicePath
+ (Size1
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
116 gBS
->CopyMem ((VOID
*) DevicePath2
, (VOID
*) SecondDevicePath
, Size2
);
119 return NewDevicePath
;
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.
127 @param ImageHandle ImageHandle of the unloaded driver
129 @return Status of the ProcessModuleUnloadList.
134 _DriverUnloadHandler (
135 EFI_HANDLE ImageHandle
139 // Call the unload handlers for all the modules.
141 // Note: All libraries were constructed in SMM space,
142 // therefore we can not destruct them in Unload
145 return ProcessModuleUnloadList (ImageHandle
);
149 Enrty point to DXE SMM Driver.
151 @param ImageHandle ImageHandle of the loaded driver.
152 @param SystemTable Pointer to the EFI System Table.
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.
161 IN EFI_HANDLE ImageHandle
,
162 IN EFI_SYSTEM_TABLE
*SystemTable
166 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
167 EFI_SMM_BASE_PROTOCOL
*SmmBase
;
169 EFI_DEVICE_PATH_PROTOCOL
*CompleteFilePath
;
170 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
174 // Cache a pointer to the Boot Services Table
176 gBS
= SystemTable
->BootServices
;
179 // Retrieve the Loaded Image Protocol
181 Status
= gBS
->HandleProtocol (
183 &gEfiLoadedImageProtocolGuid
,
186 ASSERT_EFI_ERROR (Status
);
189 // Retrieve SMM Base Protocol
191 Status
= gBS
->LocateProtocol (
192 &gEfiSmmBaseProtocolGuid
,
196 ASSERT_EFI_ERROR (Status
);
199 // Check to see if we are already in SMM
201 SmmBase
->InSmm (SmmBase
, &InSmm
);
208 // Retrieve the Device Path Protocol from the DeviceHandle tha this driver was loaded from
210 Status
= gBS
->HandleProtocol (
211 LoadedImage
->DeviceHandle
,
212 &gEfiDevicePathProtocolGuid
,
213 (VOID
*)&ImageDevicePath
215 ASSERT_EFI_ERROR (Status
);
218 // Build the full device path to the currently execuing image
220 CompleteFilePath
= SmmAppendDevicePath (ImageDevicePath
, LoadedImage
->FilePath
);
223 // Load the image in memory to SMRAM; it will automatically generate the
226 Status
= SmmBase
->Register (SmmBase
, CompleteFilePath
, NULL
, 0, &Handle
, FALSE
);
227 ASSERT_EFI_ERROR (Status
);
232 // Call constructor for all libraries
234 ProcessLibraryConstructorList (ImageHandle
, SystemTable
);
237 // Optionally install the unload handler
239 if (_gDriverUnloadImageCount
> 0) {
240 Status
= gBS
->HandleProtocol (
242 &gEfiLoadedImageProtocolGuid
,
243 (VOID
**)&LoadedImage
245 ASSERT_EFI_ERROR (Status
);
246 LoadedImage
->Unload
= _DriverUnloadHandler
;
250 // Call the list of driver entry points
252 Status
= ProcessModuleEntryPointList (ImageHandle
, SystemTable
);
253 if (EFI_ERROR (Status
)) {
254 ProcessLibraryDestructorList (ImageHandle
, SystemTable
);
261 Enrty point wrapper of DXE SMM Driver.
263 @param ImageHandle ImageHandle of the loaded driver.
264 @param SystemTable Pointer to the EFI System Table.
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.
273 IN EFI_HANDLE ImageHandle
,
274 IN EFI_SYSTEM_TABLE
*SystemTable
277 return _ModuleEntryPoint (ImageHandle
, SystemTable
);