https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			278 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The device path help function.
 | 
						|
 | 
						|
  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "NvmExpressPei.h"
 | 
						|
 | 
						|
//
 | 
						|
// Template for an Nvm Express Device Path node
 | 
						|
//
 | 
						|
NVME_NAMESPACE_DEVICE_PATH  mNvmeDevicePathNodeTemplate = {
 | 
						|
  {        // Header
 | 
						|
    MESSAGING_DEVICE_PATH,
 | 
						|
    MSG_NVME_NAMESPACE_DP,
 | 
						|
    {
 | 
						|
      (UINT8) (sizeof (NVME_NAMESPACE_DEVICE_PATH)),
 | 
						|
      (UINT8) ((sizeof (NVME_NAMESPACE_DEVICE_PATH)) >> 8)
 | 
						|
    }
 | 
						|
  },
 | 
						|
  0x0,     // NamespaceId
 | 
						|
  0x0      // NamespaceUuid
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Template for an End of entire Device Path node
 | 
						|
//
 | 
						|
EFI_DEVICE_PATH_PROTOCOL  mNvmeEndDevicePathNodeTemplate = {
 | 
						|
  END_DEVICE_PATH_TYPE,
 | 
						|
  END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | 
						|
  {
 | 
						|
    (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
 | 
						|
    (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Returns the 16-bit Length field of a device path node.
 | 
						|
 | 
						|
  Returns the 16-bit Length field of the device path node specified by Node.
 | 
						|
  Node is not required to be aligned on a 16-bit boundary, so it is recommended
 | 
						|
  that a function such as ReadUnaligned16() be used to extract the contents of
 | 
						|
  the Length field.
 | 
						|
 | 
						|
  If Node is NULL, then ASSERT().
 | 
						|
 | 
						|
  @param  Node      A pointer to a device path node data structure.
 | 
						|
 | 
						|
  @return The 16-bit Length field of the device path node specified by Node.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
DevicePathNodeLength (
 | 
						|
  IN CONST VOID  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (Node != NULL);
 | 
						|
  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns a pointer to the next node in a device path.
 | 
						|
 | 
						|
  If Node is NULL, then ASSERT().
 | 
						|
 | 
						|
  @param  Node    A pointer to a device path node data structure.
 | 
						|
 | 
						|
  @return a pointer to the device path node that follows the device path node
 | 
						|
  specified by Node.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
NextDevicePathNode (
 | 
						|
  IN CONST VOID  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (Node != NULL);
 | 
						|
  return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the size of the current device path instance.
 | 
						|
 | 
						|
  @param[in]  DevicePath             A pointer to the EFI_DEVICE_PATH_PROTOCOL
 | 
						|
                                     structure.
 | 
						|
  @param[out] InstanceSize           The size of the current device path instance.
 | 
						|
  @param[out] EntireDevicePathEnd    Indicate whether the instance is the last
 | 
						|
                                     one in the device path strucure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    The size of the current device path instance is fetched.
 | 
						|
  @retval Others         Fails to get the size of the current device path instance.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetDevicePathInstanceSize (
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
 | 
						|
  OUT UINTN                       *InstanceSize,
 | 
						|
  OUT BOOLEAN                     *EntireDevicePathEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL    *Walker;
 | 
						|
 | 
						|
  if (DevicePath == NULL || InstanceSize == NULL || EntireDevicePathEnd == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the end of the device path instance
 | 
						|
  //
 | 
						|
  Walker = DevicePath;
 | 
						|
  while (Walker->Type != END_DEVICE_PATH_TYPE) {
 | 
						|
    Walker = NextDevicePathNode (Walker);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if 'Walker' points to the end of an entire device path
 | 
						|
  //
 | 
						|
  if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
 | 
						|
    *EntireDevicePathEnd = TRUE;
 | 
						|
  } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) {
 | 
						|
    *EntireDevicePathEnd = FALSE;
 | 
						|
  } else {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the size of the device path instance
 | 
						|
  //
 | 
						|
  *InstanceSize = ((UINTN) Walker - (UINTN) (DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the validity of the device path of a NVM Express host controller.
 | 
						|
 | 
						|
  @param[in] DevicePath          A pointer to the EFI_DEVICE_PATH_PROTOCOL
 | 
						|
                                 structure.
 | 
						|
  @param[in] DevicePathLength    The length of the device path.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The device path is valid.
 | 
						|
  @retval EFI_INVALID_PARAMETER    The device path is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
NvmeIsHcDevicePathValid (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
 | 
						|
  IN UINTN                       DevicePathLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL    *Start;
 | 
						|
  UINTN                       Size;
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate the DevicePathLength is big enough to touch the first node.
 | 
						|
  //
 | 
						|
  if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Start = DevicePath;
 | 
						|
  while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&
 | 
						|
           DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
 | 
						|
    DevicePath = NextDevicePathNode (DevicePath);
 | 
						|
 | 
						|
    //
 | 
						|
    // Prevent overflow and invalid zero in the 'Length' field of a device path
 | 
						|
    // node.
 | 
						|
    //
 | 
						|
    if ((UINTN) DevicePath <= (UINTN) Start) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Prevent touching memory beyond given DevicePathLength.
 | 
						|
    //
 | 
						|
    if ((UINTN) DevicePath - (UINTN) Start >
 | 
						|
        DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the device path and its size match exactly with each other.
 | 
						|
  //
 | 
						|
  Size = ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
  if (Size != DevicePathLength) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Build the device path for an Nvm Express device with given namespace identifier
 | 
						|
  and namespace extended unique identifier.
 | 
						|
 | 
						|
  @param[in]  Private              A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
 | 
						|
                                   data structure.
 | 
						|
  @param[in]  NamespaceId          The given namespace identifier.
 | 
						|
  @param[in]  NamespaceUuid        The given namespace extended unique identifier.
 | 
						|
  @param[out] DevicePathLength     The length of the device path in bytes specified
 | 
						|
                                   by DevicePath.
 | 
						|
  @param[out] DevicePath           The device path of Nvm Express device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation succeeds.
 | 
						|
  @retval EFI_INVALID_PARAMETER    The parameters are invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of resources.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
NvmeBuildDevicePath (
 | 
						|
  IN  PEI_NVME_CONTROLLER_PRIVATE_DATA    *Private,
 | 
						|
  IN  UINT32                              NamespaceId,
 | 
						|
  IN  UINT64                              NamespaceUuid,
 | 
						|
  OUT UINTN                               *DevicePathLength,
 | 
						|
  OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *DevicePathWalker;
 | 
						|
  NVME_NAMESPACE_DEVICE_PATH    *NvmeDeviceNode;
 | 
						|
 | 
						|
  if (DevicePathLength == NULL || DevicePath == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *DevicePathLength = Private->DevicePathLength + sizeof (NVME_NAMESPACE_DEVICE_PATH);
 | 
						|
  *DevicePath       = AllocatePool (*DevicePathLength);
 | 
						|
  if (*DevicePath == NULL) {
 | 
						|
    *DevicePathLength = 0;
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Construct the host controller part device nodes
 | 
						|
  //
 | 
						|
  DevicePathWalker = *DevicePath;
 | 
						|
  CopyMem (
 | 
						|
    DevicePathWalker,
 | 
						|
    Private->DevicePath,
 | 
						|
    Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Construct the Nvm Express device node
 | 
						|
  //
 | 
						|
  DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker +
 | 
						|
                     (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
 | 
						|
  CopyMem (
 | 
						|
    DevicePathWalker,
 | 
						|
    &mNvmeDevicePathNodeTemplate,
 | 
						|
    sizeof (mNvmeDevicePathNodeTemplate)
 | 
						|
    );
 | 
						|
  NvmeDeviceNode                = (NVME_NAMESPACE_DEVICE_PATH *)DevicePathWalker;
 | 
						|
  NvmeDeviceNode->NamespaceId   = NamespaceId;
 | 
						|
  NvmeDeviceNode->NamespaceUuid = NamespaceUuid;
 | 
						|
 | 
						|
  //
 | 
						|
  // Construct the end device node
 | 
						|
  //
 | 
						|
  DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker +
 | 
						|
                     sizeof (NVME_NAMESPACE_DEVICE_PATH));
 | 
						|
  CopyMem (
 | 
						|
    DevicePathWalker,
 | 
						|
    &mNvmeEndDevicePathNodeTemplate,
 | 
						|
    sizeof (mNvmeEndDevicePathNodeTemplate)
 | 
						|
    );
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |