git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11094 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			650 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			650 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
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.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  RtDevicePath.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Device Path services. The thing to remember is device paths are built out of
 | 
						|
  nodes. The device path is terminated by an end node that is length
 | 
						|
  sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
 | 
						|
  all over this file.
 | 
						|
 | 
						|
  The only place where multi-instance device paths are supported is in
 | 
						|
  environment varibles. Multi-instance device paths should never be placed
 | 
						|
  on a Handle.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "Tiano.h"
 | 
						|
#include "EfiRuntimeLib.h"
 | 
						|
#include "RtDevicePath.h"
 | 
						|
#include EFI_GUID_DEFINITION (FrameworkDevicePath)
 | 
						|
#include EFI_PROTOCOL_DEFINITION (DevicePath)
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID *
 | 
						|
InternalAllocatePool (
 | 
						|
  IN  UINTN   AllocationSize
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Allocate BootServicesData pool.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  AllocationSize  - The size to allocate
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Pointer of the buffer allocated.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  VOID  *Memory;
 | 
						|
 | 
						|
  Memory = NULL;
 | 
						|
  gBS->AllocatePool (EfiBootServicesData, AllocationSize, &Memory);
 | 
						|
  return Memory;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID *
 | 
						|
InternalAllocateCopyPool (
 | 
						|
  IN  UINTN   AllocationSize,
 | 
						|
  IN  VOID    *Buffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Allocate BootServicesData pool and use a buffer provided by 
 | 
						|
  caller to fill it.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  AllocationSize  - The size to allocate
 | 
						|
  
 | 
						|
  Buffer          - Buffer that will be filled into the buffer allocated
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Pointer of the buffer allocated.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  VOID  *Memory;
 | 
						|
 | 
						|
  Memory = NULL;
 | 
						|
  gBS->AllocatePool (EfiBootServicesData, AllocationSize, &Memory);
 | 
						|
  if (Memory != NULL) {
 | 
						|
    gBS->CopyMem (Memory, Buffer, AllocationSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return Memory;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID *
 | 
						|
InternalAllocateZeroPool (
 | 
						|
  IN  UINTN   AllocationSize
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Allocate BootServicesData pool and zero it.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  AllocationSize  - The size to allocate
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Pointer of the buffer allocated.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  VOID  *Memory;
 | 
						|
 | 
						|
  Memory = InternalAllocatePool (AllocationSize);
 | 
						|
  if (Memory != NULL) {
 | 
						|
    gBS->SetMem (Memory, AllocationSize, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  return Memory;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiDevicePathInstance (
 | 
						|
  IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,
 | 
						|
  OUT UINTN                         *Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Function retrieves the next device path instance from a device path data structure.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  DevicePath           - A pointer to a device path data structure.
 | 
						|
 | 
						|
  Size                 - A pointer to the size of a device path instance in bytes.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  This function returns a pointer to the current device path instance.
 | 
						|
  In addition, it returns the size in bytes of the current device path instance in Size,
 | 
						|
  and a pointer to the next device path instance in DevicePath.
 | 
						|
  If there are no more device path instances in DevicePath, then DevicePath will be set to NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *ReturnValue;
 | 
						|
  UINT8                     Temp;
 | 
						|
 | 
						|
  if (*DevicePath == NULL) {
 | 
						|
    if (Size != NULL) {
 | 
						|
      *Size = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the end of the device path instance
 | 
						|
  //
 | 
						|
  DevPath = *DevicePath;
 | 
						|
  while (!IsDevicePathEndType (DevPath)) {
 | 
						|
    DevPath = NextDevicePathNode (DevPath);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the size of the device path instance
 | 
						|
  //
 | 
						|
  if (Size != NULL) {
 | 
						|
    *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Make a copy and return the device path instance
 | 
						|
  //
 | 
						|
  Temp              = DevPath->SubType;
 | 
						|
  DevPath->SubType  = END_ENTIRE_DEVICE_PATH_SUBTYPE;
 | 
						|
  ReturnValue       = RtEfiDuplicateDevicePath (*DevicePath);
 | 
						|
  DevPath->SubType  = Temp;
 | 
						|
 | 
						|
  //
 | 
						|
  // If DevPath is the end of an entire device path, then another instance
 | 
						|
  // does not follow, so *DevicePath is set to NULL.
 | 
						|
  //
 | 
						|
  if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
 | 
						|
    *DevicePath = NULL;
 | 
						|
  } else {
 | 
						|
    *DevicePath = NextDevicePathNode (DevPath);
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnValue;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
RtEfiIsDevicePathMultiInstance (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Return TRUE is this is a multi instance device path.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  DevicePath  - A pointer to a device path data structure.
 | 
						|
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
 | 
						|
  instance.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Node;
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Node = DevicePath;
 | 
						|
  while (!EfiIsDevicePathEnd (Node)) {
 | 
						|
    if (EfiIsDevicePathEndInstance (Node)) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    Node = EfiNextDevicePathNode (Node);
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
RtEfiDevicePathSize (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Calculate the space size of a device path.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  DevicePath  - A specified device path
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The size.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Start;
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Search for the end of the device path structure
 | 
						|
  //
 | 
						|
  Start = DevicePath;
 | 
						|
  while (!EfiIsDevicePathEnd (DevicePath)) {
 | 
						|
    DevicePath = EfiNextDevicePathNode (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);
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiDevicePathFromHandle (
 | 
						|
  IN EFI_HANDLE  Handle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Get the device path protocol interface installed on a specified handle.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Handle  - a specified handle
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The device path protocol interface installed on that handle.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
 | 
						|
  DevicePath = NULL;
 | 
						|
  gBS->HandleProtocol (
 | 
						|
        Handle,
 | 
						|
        &gEfiDevicePathProtocolGuid,
 | 
						|
        (VOID *) &DevicePath
 | 
						|
        );
 | 
						|
  return DevicePath;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiDuplicateDevicePath (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Duplicate a device path structure.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  DevicePath  - The device path to duplicated.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The duplicated device path.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
 | 
						|
  UINTN                     Size;
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the size
 | 
						|
  //
 | 
						|
  Size = RtEfiDevicePathSize (DevicePath);
 | 
						|
  if (Size == 0) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for duplicate device path
 | 
						|
  //
 | 
						|
  NewDevicePath = InternalAllocateCopyPool (Size, DevicePath);
 | 
						|
 | 
						|
  return NewDevicePath;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiAppendDevicePath (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Src2
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Function is used to append a Src1 and Src2 together.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Src1  - A pointer to a device path data structure.
 | 
						|
 | 
						|
  Src2  - A pointer to a device path data structure.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  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 Src1 and Src2 if they are no longer needed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                     Size;
 | 
						|
  UINTN                     Size1;
 | 
						|
  UINTN                     Size2;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath;
 | 
						|
 | 
						|
  //
 | 
						|
  // If there's only 1 path, just duplicate it
 | 
						|
  //
 | 
						|
  if (!Src1) {
 | 
						|
    ASSERT (!IsDevicePathUnpacked (Src2));
 | 
						|
    return RtEfiDuplicateDevicePath (Src2);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Src2) {
 | 
						|
    ASSERT (!IsDevicePathUnpacked (Src1));
 | 
						|
    return RtEfiDuplicateDevicePath (Src1);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for the combined device path. It only has one end node of
 | 
						|
  // length EFI_DEVICE_PATH_PROTOCOL
 | 
						|
  //
 | 
						|
  Size1         = RtEfiDevicePathSize (Src1);
 | 
						|
  Size2         = RtEfiDevicePathSize (Src2);
 | 
						|
  Size          = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
 | 
						|
  NewDevicePath = InternalAllocateCopyPool (Size, Src1);
 | 
						|
 | 
						|
  if (NewDevicePath != NULL) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Over write Src1 EndNode and do the copy
 | 
						|
    //
 | 
						|
    SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
 | 
						|
    EfiCopyMem (SecondDevicePath, Src2, Size2);
 | 
						|
  }
 | 
						|
 | 
						|
  return NewDevicePath;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiAppendDevicePathNode (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Node
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Function is used to append a device path node to the end of another device path.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Src1  - A pointer to a device path data structure.
 | 
						|
 | 
						|
  Node - A pointer to a device path data structure.
 | 
						|
 | 
						|
Returns:
 | 
						|
  This function returns a pointer to the new device path.
 | 
						|
  If there is not enough temporary pool memory available to complete this function,
 | 
						|
  then NULL is returned.
 | 
						|
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Temp;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
 | 
						|
  UINTN                     NodeLength;
 | 
						|
 | 
						|
  //
 | 
						|
  // Build a Node that has a terminator on it
 | 
						|
  //
 | 
						|
  NodeLength  = DevicePathNodeLength (Node);
 | 
						|
 | 
						|
  Temp        = InternalAllocateCopyPool (NodeLength + sizeof (EFI_DEVICE_PATH_PROTOCOL), Node);
 | 
						|
  if (Temp == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add and end device path node to convert Node to device path
 | 
						|
  //
 | 
						|
  NextNode = NextDevicePathNode (Temp);
 | 
						|
  SetDevicePathEndNode (NextNode);
 | 
						|
 | 
						|
  //
 | 
						|
  // Append device paths
 | 
						|
  //
 | 
						|
  NewDevicePath = RtEfiAppendDevicePath (Src1, Temp);
 | 
						|
  gBS->FreePool (Temp);
 | 
						|
  return NewDevicePath;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiFileDevicePath (
 | 
						|
  IN EFI_HANDLE               Device  OPTIONAL,
 | 
						|
  IN CHAR16                   *FileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function allocates a device path for a file and appends it to an existiong
 | 
						|
  device path.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Device     - A pointer to a device handle.
 | 
						|
 | 
						|
  FileName   - A pointer to a Null-terminated Unicodestring.
 | 
						|
 | 
						|
Returns:
 | 
						|
  A device path contain the file name.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                     Size;
 | 
						|
  FILEPATH_DEVICE_PATH      *FilePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Eop;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
 | 
						|
  for (Size = 0; FileName[Size] != 0; Size++)
 | 
						|
    ;
 | 
						|
  Size        = (Size + 1) * 2;
 | 
						|
 | 
						|
  FilePath    = InternalAllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
 | 
						|
 | 
						|
  DevicePath  = NULL;
 | 
						|
 | 
						|
  if (FilePath != NULL) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Build a file path
 | 
						|
    //
 | 
						|
    FilePath->Header.Type     = MEDIA_DEVICE_PATH;
 | 
						|
    FilePath->Header.SubType  = MEDIA_FILEPATH_DP;
 | 
						|
    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
 | 
						|
    EfiCopyMem (FilePath->PathName, FileName, Size);
 | 
						|
    Eop = NextDevicePathNode (&FilePath->Header);
 | 
						|
    SetDevicePathEndNode (Eop);
 | 
						|
 | 
						|
    //
 | 
						|
    // Append file path to device's device path
 | 
						|
    //
 | 
						|
 | 
						|
    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
 | 
						|
    if (Device != NULL) {
 | 
						|
      DevicePath = RtEfiAppendDevicePath (
 | 
						|
                    RtEfiDevicePathFromHandle (Device),
 | 
						|
                    DevicePath
 | 
						|
                    );
 | 
						|
 | 
						|
      gBS->FreePool (FilePath);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return DevicePath;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
RtEfiAppendDevicePathInstance (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Src,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *Instance
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Append a device path instance to another.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Src       - The device path instance to be appended with.
 | 
						|
  Instance  - The device path instance appending the other.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The contaction of these two.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT8                     *Ptr;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
 | 
						|
  UINTN                     SrcSize;
 | 
						|
  UINTN                     InstanceSize;
 | 
						|
 | 
						|
  if (Src == NULL) {
 | 
						|
    return RtEfiDuplicateDevicePath (Instance);
 | 
						|
  }
 | 
						|
 | 
						|
  SrcSize       = RtEfiDevicePathSize (Src);
 | 
						|
  InstanceSize  = RtEfiDevicePathSize (Instance);
 | 
						|
 | 
						|
  Ptr           = InternalAllocateCopyPool (SrcSize + InstanceSize, Src);
 | 
						|
  if (Ptr != NULL) {
 | 
						|
 | 
						|
    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
 | 
						|
 | 
						|
    while (!IsDevicePathEnd (DevPath)) {
 | 
						|
      DevPath = NextDevicePathNode (DevPath);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Convert the End to an End Instance, since we are
 | 
						|
    //  appending another instacne after this one its a good
 | 
						|
    //  idea.
 | 
						|
    //
 | 
						|
    DevPath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
 | 
						|
 | 
						|
    DevPath           = NextDevicePathNode (DevPath);
 | 
						|
    EfiCopyMem (DevPath, Instance, InstanceSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
RtEfiInitializeFwVolDevicepathNode (
 | 
						|
  IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *FvDevicePathNode,
 | 
						|
  IN EFI_GUID                               *NameGuid
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initialize a Firmware Volume (FV) Media Device Path node.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvDevicePathNode  - Pointer to a FV device path node to initialize
 | 
						|
  NameGuid          - FV file name to use in FvDevicePathNode
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
 | 
						|
  FvDevicePathNode->Header.SubType  = MEDIA_FV_FILEPATH_DP;
 | 
						|
  SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
 | 
						|
 | 
						|
  EfiCopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
 | 
						|
}
 | 
						|
 | 
						|
EFI_GUID *
 | 
						|
EFIAPI
 | 
						|
RtEfiGetNameGuidFromFwVolDevicePathNode (
 | 
						|
  IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   *FvDevicePathNode
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Check to see if the Firmware Volume (FV) Media Device Path is valid.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvDevicePathNode  - Pointer to FV device path to check
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  NULL              - FvDevicePathNode is not valid.
 | 
						|
  Other             - FvDevicePathNode is valid and pointer to NameGuid was returned.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
 | 
						|
      DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
 | 
						|
    return &FvDevicePathNode->NameGuid;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 |