2, Add DevicePathLib library class to module's INF that use device path utility macros git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@6458 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			278 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  This file implement EfiMain() for library class DxeSmmDriverEntryPoint.
 | 
						|
  EfiMain() is common driver entry point for all SMM driver who uses DxeSmmDriverEntryPoint
 | 
						|
  library class.
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation<BR>
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
 | 
						|
#include <FrameworkSmm.h>
 | 
						|
 | 
						|
#include <Protocol/LoadedImage.h>
 | 
						|
#include <Protocol/SmmBase.h>
 | 
						|
#include <Protocol/DevicePath.h>
 | 
						|
 | 
						|
#include <Library/UefiDriverEntryPoint.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/DevicePathLib.h>
 | 
						|
 | 
						|
/**
 | 
						|
  This function returns the size, in bytes,
 | 
						|
  of the device path data structure specified by DevicePath.
 | 
						|
  If DevicePath is NULL, then 0 is returned.
 | 
						|
 | 
						|
  @param  DevicePath A pointer to a device path data structure.
 | 
						|
 | 
						|
  @return The size of a device path in bytes.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EFIAPI
 | 
						|
SmmGetDevicePathSize (
 | 
						|
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Search for the end of the device path structure
 | 
						|
  //
 | 
						|
  Start = DevicePath;
 | 
						|
  while (!IsDevicePathEnd (DevicePath)) {
 | 
						|
    DevicePath = NextDevicePathNode (DevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the size and add back in the size of the end device path structure
 | 
						|
  //
 | 
						|
  return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function appends the device path SecondDevicePath
 | 
						|
  to every device path instance in FirstDevicePath.
 | 
						|
 | 
						|
  @param  FirstDevicePath A pointer to a device path data structure.
 | 
						|
 | 
						|
  @param  SecondDevicePath A pointer to a device path data structure.
 | 
						|
 | 
						|
  @return A pointer to the new device path is returned.
 | 
						|
          NULL is returned if space for the new device path could not be allocated from pool.
 | 
						|
          It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath
 | 
						|
          if they are no longer needed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
EFIAPI
 | 
						|
SmmAppendDevicePath (
 | 
						|
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,
 | 
						|
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  UINTN                     Size;
 | 
						|
  UINTN                     Size1;
 | 
						|
  UINTN                     Size2;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath2;
 | 
						|
 | 
						|
  ASSERT (FirstDevicePath != NULL && SecondDevicePath != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for the combined device path. It only has one end node of
 | 
						|
  // length EFI_DEVICE_PATH_PROTOCOL
 | 
						|
  //
 | 
						|
  Size1         = SmmGetDevicePathSize (FirstDevicePath);
 | 
						|
  Size2         = SmmGetDevicePathSize (SecondDevicePath);
 | 
						|
  Size          = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
 | 
						|
  Status = gBS->AllocatePool (EfiBootServicesData, Size, (VOID **) &NewDevicePath);
 | 
						|
 | 
						|
  if (EFI_SUCCESS == Status) {
 | 
						|
    //
 | 
						|
    // CopyMem in gBS is used as this service should always be ready. We didn't choose
 | 
						|
    // to use a BaseMemoryLib function as such library instance may have constructor.
 | 
						|
    //
 | 
						|
    gBS->CopyMem ((VOID *) NewDevicePath, (VOID *) FirstDevicePath, Size1);
 | 
						|
    //
 | 
						|
    // Over write Src1 EndNode and do the copy
 | 
						|
    //
 | 
						|
    DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
 | 
						|
    gBS->CopyMem ((VOID *) DevicePath2, (VOID *) SecondDevicePath, Size2);
 | 
						|
  }
 | 
						|
 | 
						|
  return NewDevicePath;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Unload function that is registered in the LoadImage protocol.  It un-installs
 | 
						|
  protocols produced and deallocates pool used by the driver.  Called by the core
 | 
						|
  when unloading the driver.
 | 
						|
 | 
						|
  @param  ImageHandle   ImageHandle of the unloaded driver
 | 
						|
 | 
						|
  @return Status of the ProcessModuleUnloadList.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
_DriverUnloadHandler (
 | 
						|
  EFI_HANDLE ImageHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Call the unload handlers for all the modules.
 | 
						|
  // 
 | 
						|
  // Note: All libraries were constructed in SMM space, 
 | 
						|
  // therefore we can not destruct them in Unload 
 | 
						|
  // handler.
 | 
						|
  //
 | 
						|
  return ProcessModuleUnloadList (ImageHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Enrty point to DXE SMM Driver.
 | 
						|
 | 
						|
  @param  ImageHandle ImageHandle of the loaded driver.
 | 
						|
  @param  SystemTable Pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS One or more of the drivers returned a success code.
 | 
						|
  @retval  !EFI_SUCESS The return status from the last driver entry point in the list.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
_ModuleEntryPoint (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                 Status;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
 | 
						|
  EFI_SMM_BASE_PROTOCOL      *SmmBase;
 | 
						|
  BOOLEAN                    InSmm;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL   *CompleteFilePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL   *ImageDevicePath;
 | 
						|
  EFI_HANDLE                 Handle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Cache a pointer to the Boot Services Table
 | 
						|
  //
 | 
						|
  gBS = SystemTable->BootServices;
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the Loaded Image Protocol
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  ImageHandle,
 | 
						|
                  &gEfiLoadedImageProtocolGuid,
 | 
						|
                  (VOID*)&LoadedImage
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve SMM Base Protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiSmmBaseProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &SmmBase
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check to see if we are already in SMM
 | 
						|
  //
 | 
						|
  SmmBase->InSmm (SmmBase, &InSmm);
 | 
						|
 | 
						|
  //
 | 
						|
  //
 | 
						|
  //
 | 
						|
  if (!InSmm) {
 | 
						|
    //
 | 
						|
    // Retrieve the Device Path Protocol from the DeviceHandle tha this driver was loaded from
 | 
						|
    //
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    LoadedImage->DeviceHandle,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    (VOID*)&ImageDevicePath
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Build the full device path to the currently execuing image
 | 
						|
    //
 | 
						|
    CompleteFilePath = SmmAppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
 | 
						|
 | 
						|
    //
 | 
						|
    // Load the image in memory to SMRAM; it will automatically generate the
 | 
						|
    // SMI.
 | 
						|
    //
 | 
						|
    Status = SmmBase->Register (SmmBase, CompleteFilePath, NULL, 0, &Handle, FALSE);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Call constructor for all libraries
 | 
						|
  //
 | 
						|
  ProcessLibraryConstructorList (ImageHandle, SystemTable);
 | 
						|
 | 
						|
  //
 | 
						|
  // Optionally install the unload handler
 | 
						|
  //
 | 
						|
  if (_gDriverUnloadImageCount > 0) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    ImageHandle,
 | 
						|
                    &gEfiLoadedImageProtocolGuid,
 | 
						|
                    (VOID **)&LoadedImage
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    LoadedImage->Unload = _DriverUnloadHandler;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Call the list of driver entry points
 | 
						|
  //
 | 
						|
  Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ProcessLibraryDestructorList (ImageHandle, SystemTable);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Enrty point wrapper of DXE SMM Driver.
 | 
						|
 | 
						|
  @param  ImageHandle ImageHandle of the loaded driver.
 | 
						|
  @param  SystemTable Pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS One or more of the drivers returned a success code.
 | 
						|
  @retval  !EFI_SUCESS The return status from the last driver entry point in the list.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiMain (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  return _ModuleEntryPoint (ImageHandle, SystemTable);
 | 
						|
}
 |