13eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
23eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
33e99020dbf0a159e34b84e7ae9125f2e368d5390lgaoCopyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
44ea9375a2d02a43671437e0d3d808d85afb30afahhtianThis program and the accompanying materials
53eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangare licensed and made available under the terms and conditions of the BSD License
63eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangwhich accompanies this distribution.  The full text of the license may be found at
73eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwanghttp://opensource.org/licenses/bsd-license.php
83eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
93eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangModule Name:
133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath.c
153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAbstract:
173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Device Path services. The thing to remember is device paths are built out of
193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  nodes. The device path is terminated by an end node that is length
203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  all over this file.
223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The only place where multi-instance device paths are supported is in
243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  environment varibles. Multi-instance device paths should never be placed
253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  on a Handle.
263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "Tiano.h"
303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "EfiDriverLib.h"
313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include EFI_PROTOCOL_DEFINITION (DevicePath)
323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiDevicePathInstance (
353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,
363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  OUT UINTN                         *Size
373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Function retrieves the next device path instance from a device path data structure.
423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath           - A pointer to a device path data structure.
453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size                 - A pointer to the size of a device path instance in bytes.
473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function returns a pointer to the current device path instance.
513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  In addition, it returns the size in bytes of the current device path instance in Size,
523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  and a pointer to the next device path instance in DevicePath.
533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If there are no more device path instances in DevicePath, then DevicePath will be set to NULL.
543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *ReturnValue;
593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT8                     Temp;
603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (*DevicePath == NULL) {
623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (Size != NULL) {
633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      *Size = 0;
643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return NULL;
673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Find the end of the device path instance
713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevPath = *DevicePath;
733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  while (!IsDevicePathEndType (DevPath)) {
743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevPath = NextDevicePathNode (DevPath);
753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Compute the size of the device path instance
793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (Size != NULL) {
813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Make a copy and return the device path instance
863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Temp              = DevPath->SubType;
883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevPath->SubType  = END_ENTIRE_DEVICE_PATH_SUBTYPE;
893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ReturnValue       = EfiDuplicateDevicePath (*DevicePath);
903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevPath->SubType  = Temp;
913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // If DevPath is the end of an entire device path, then another instance
943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // does not follow, so *DevicePath is set to NULL.
953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    *DevicePath = NULL;
983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else {
993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    *DevicePath = NextDevicePathNode (DevPath);
1003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return ReturnValue;
1033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangBOOLEAN
1063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiIsDevicePathMultiInstance (
1073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
1083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
1103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
1123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Return TRUE is this is a multi instance device path.
1133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
1153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath  - A pointer to a device path data structure.
1163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
1193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
1203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  instance.
1213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
1233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
1243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *Node;
1253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DevicePath == NULL) {
1273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return FALSE;
1283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Node = DevicePath;
1313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  while (!EfiIsDevicePathEnd (Node)) {
1323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (EfiIsDevicePathEndInstance (Node)) {
1333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      return TRUE;
1343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
1353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Node = EfiNextDevicePathNode (Node);
1373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return FALSE;
1403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINTN
1433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiDevicePathSize (
1443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
1453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
1473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
1493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Calculate the space size of a device path.
1513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
1533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath  - A specified device path
1553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
1573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The size.
1593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
1613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
1623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *Start;
1633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DevicePath == NULL) {
1653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return 0;
1663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Search for the end of the device path structure
1703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Start = DevicePath;
1723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  while (!EfiIsDevicePathEnd (DevicePath)) {
1733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevicePath = EfiNextDevicePathNode (DevicePath);
1743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Compute the size and add back in the size of the end device path structure
1783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
1803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
1833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiDevicePathFromHandle (
1843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_HANDLE  Handle
1853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
1873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
1893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Get the device path protocol interface installed on a specified handle.
1913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
1933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Handle  - a specified handle
1953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
1973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The device path protocol interface installed on that handle.
1993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
2013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
2033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath = NULL;
2053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  gBS->HandleProtocol (
2063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        Handle,
2073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        &gEfiDevicePathProtocolGuid,
2083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (VOID *) &DevicePath
2093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        );
2103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return DevicePath;
2113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
2143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiDuplicateDevicePath (
2153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
2163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
2183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
2203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Duplicate a device path structure.
2223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
2243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath  - The device path to duplicated.
2263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
2283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The duplicated device path.
2303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
2323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
2343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     Size;
2353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DevicePath == NULL) {
2373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return NULL;
2383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
2393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Compute the size
2423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size = EfiDevicePathSize (DevicePath);
2443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (Size == 0) {
2453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return NULL;
2463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
2473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Allocate space for duplicate device path
2503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NewDevicePath = EfiLibAllocateCopyPool (Size, DevicePath);
2523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return NewDevicePath;
2543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
2573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiAppendDevicePath (
2583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
2593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Src2
2603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
2623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
2643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Function is used to append a Src1 and Src2 together.
2653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
2673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Src1  - A pointer to a device path data structure.
2683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Src2  - A pointer to a device path data structure.
2703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
2723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  A pointer to the new device path is returned.
2743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NULL is returned if space for the new device path could not be allocated from pool.
2753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
2763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
2783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     Size;
2803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     Size1;
2813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     Size2;
2823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
2833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath;
2843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // If there's only 1 path, just duplicate it
2873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!Src1) {
2893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    ASSERT (!IsDevicePathUnpacked (Src2));
2903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return EfiDuplicateDevicePath (Src2);
2913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
2923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!Src2) {
2943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    ASSERT (!IsDevicePathUnpacked (Src1));
2953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return EfiDuplicateDevicePath (Src1);
2963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
2973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
2993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Allocate space for the combined device path. It only has one end node of
3003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // length EFI_DEVICE_PATH_PROTOCOL
3013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size1         = EfiDevicePathSize (Src1);
3033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size2         = EfiDevicePathSize (Src2);
3043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size          = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);
3053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NewDevicePath = EfiLibAllocateCopyPool (Size, Src1);
3073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (NewDevicePath != NULL) {
3093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Over write Src1 EndNode and do the copy
3123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
3143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    EfiCopyMem (SecondDevicePath, Src2, Size2);
3153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
3163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return NewDevicePath;
3183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
3193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
3213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiAppendDevicePathNode (
3223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
3233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Node
3243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
3253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
3263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
3283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Function is used to append a device path node to the end of another device path.
3293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
3313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Src1  - A pointer to a device path data structure.
3323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Node - A pointer to a device path data structure.
3343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
3363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function returns a pointer to the new device path.
3373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If there is not enough temporary pool memory available to complete this function,
3383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  then NULL is returned.
3393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
3423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
3433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *Temp;
3443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
3453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
3463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     NodeLength;
3473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Build a Node that has a terminator on it
3503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NodeLength  = DevicePathNodeLength (Node);
3523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Temp        = EfiLibAllocateCopyPool (NodeLength + sizeof (EFI_DEVICE_PATH_PROTOCOL), Node);
3543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (Temp == NULL) {
3553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return NULL;
3563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
3573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Add and end device path node to convert Node to device path
3603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NextNode = NextDevicePathNode (Temp);
3623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SetDevicePathEndNode (NextNode);
3633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Append device paths
3663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NewDevicePath = EfiAppendDevicePath (Src1, Temp);
3683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  gBS->FreePool (Temp);
3693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return NewDevicePath;
3703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
3713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
3733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiFileDevicePath (
3743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_HANDLE               Device  OPTIONAL,
3753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN CHAR16                   *FileName
3763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
3773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
3783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
3803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function allocates a device path for a file and appends it to an existiong
3823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  device path.
3833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
3853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Device     - A pointer to a device handle.
3863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FileName   - A pointer to a Null-terminated Unicodestring.
3883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
3903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  A device path contain the file name.
3913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
3933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
3943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     Size;
3953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FILEPATH_DEVICE_PATH      *FilePath;
3963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *Eop;
3973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
3983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  for (Size = 0; FileName[Size] != 0; Size++)
4003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    ;
4013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Size        = (Size + 1) * 2;
4023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FilePath    = EfiLibAllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
4043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DevicePath  = NULL;
4063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (FilePath != NULL) {
4083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Build a file path
4113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    FilePath->Header.Type     = MEDIA_DEVICE_PATH;
4133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    FilePath->Header.SubType  = MEDIA_FILEPATH_DP;
4143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
4153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    EfiCopyMem (FilePath->PathName, FileName, Size);
4163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Eop = NextDevicePathNode (&FilePath->Header);
4173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    SetDevicePathEndNode (Eop);
4183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Append file path to device's device path
4213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
4243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (Device != NULL) {
4253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      DevicePath = EfiAppendDevicePath (
4263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                    EfiDevicePathFromHandle (Device),
4273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                    DevicePath
4283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                    );
4293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      gBS->FreePool (FilePath);
4313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
4323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return DevicePath;
4353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
4363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_DEVICE_PATH_PROTOCOL *
4383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiAppendDevicePathInstance (
4393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Src,
4403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_DEVICE_PATH_PROTOCOL  *Instance
4413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
4423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
4433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
4453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Append a device path instance to another.
4473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
4493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Src       - The device path instance to be appended with.
4513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Instance  - The device path instance appending the other.
4523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
4543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The contaction of these two.
4563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
4583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
4593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT8                     *Ptr;
4603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
4613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     SrcSize;
4623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                     InstanceSize;
4633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (Src == NULL) {
4653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return EfiDuplicateDevicePath (Instance);
4663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SrcSize       = EfiDevicePathSize (Src);
4693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  InstanceSize  = EfiDevicePathSize (Instance);
4703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Ptr           = EfiLibAllocateCopyPool (SrcSize + InstanceSize, Src);
4723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (Ptr != NULL) {
4733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
4753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    while (!IsDevicePathEnd (DevPath)) {
4773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      DevPath = NextDevicePathNode (DevPath);
4783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
4793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Convert the End to an End Instance, since we are
4813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //  appending another instacne after this one its a good
4823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //  idea.
4833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevPath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
4853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    DevPath           = NextDevicePathNode (DevPath);
4873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    EfiCopyMem (DevPath, Instance, InstanceSize);
4883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
4913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
4923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID
4943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
4953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiInitializeFwVolDevicepathNode (
4963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *FvDevicePathNode,
4973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_GUID                               *NameGuid
4983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
4993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
5003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
5023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Initialize a Firmware Volume (FV) Media Device Path node.
5043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
5063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FvDevicePathNode  - Pointer to a FV device path node to initialize
5083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NameGuid          - FV file name to use in FvDevicePathNode
5093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
5113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  None
5133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
5153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
5163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
5173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FvDevicePathNode->Header.SubType  = MEDIA_FV_FILEPATH_DP;
5183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
5193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EfiCopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
5213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
5223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFI_GUID *
5243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
5253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEfiGetNameGuidFromFwVolDevicePathNode (
5263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   *FvDevicePathNode
5273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
5283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
5293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
5313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Check to see if the Firmware Volume (FV) Media Device Path is valid.
5333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
5353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FvDevicePathNode  - Pointer to FV device path to check
5373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
5393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NULL              - FvDevicePathNode is not valid.
5413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Other             - FvDevicePathNode is valid and pointer to NameGuid was returned.
5423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
5443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
5453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
5463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
5473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return &FvDevicePathNode->NameGuid;
5483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
5493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return NULL;
5513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
552