Home | History | Annotate | Download | only in UefiDevicePathLibDevicePathProtocol
      1 /** @file
      2   Library instance that implement UEFI Device Path Library class based on protocol
      3   gEfiDevicePathUtilitiesProtocolGuid.
      4 
      5   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 
     17 #include <Uefi.h>
     18 
     19 #include <Protocol/DevicePathUtilities.h>
     20 #include <Protocol/DevicePathToText.h>
     21 #include <Protocol/DevicePathFromText.h>
     22 
     23 #include <Library/DevicePathLib.h>
     24 #include <Library/DebugLib.h>
     25 #include <Library/BaseLib.h>
     26 #include <Library/MemoryAllocationLib.h>
     27 #include <Library/BaseMemoryLib.h>
     28 #include <Library/UefiBootServicesTableLib.h>
     29 #include <Library/PcdLib.h>
     30 
     31 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathLibDevicePathUtilities = NULL;
     32 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_TO_TEXT_PROTOCOL   *mDevicePathLibDevicePathToText    = NULL;
     33 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mDevicePathLibDevicePathFromText  = NULL;
     34 
     35 //
     36 // Template for an end-of-device path node.
     37 //
     38 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL  mUefiDevicePathLibEndDevicePath = {
     39   END_DEVICE_PATH_TYPE,
     40   END_ENTIRE_DEVICE_PATH_SUBTYPE,
     41   {
     42     END_DEVICE_PATH_LENGTH,
     43     0
     44   }
     45 };
     46 
     47 /**
     48   The constructor function caches the pointer to DevicePathUtilites protocol.
     49 
     50   The constructor function locates DevicePathUtilities protocol from protocol database.
     51   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
     52 
     53   @param  ImageHandle   The firmware allocated handle for the EFI image.
     54   @param  SystemTable   A pointer to the EFI System Table.
     55 
     56   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
     57 
     58 **/
     59 EFI_STATUS
     60 EFIAPI
     61 DevicePathLibConstructor (
     62   IN      EFI_HANDLE                ImageHandle,
     63   IN      EFI_SYSTEM_TABLE          *SystemTable
     64   )
     65 {
     66   EFI_STATUS                        Status;
     67 
     68   Status = gBS->LocateProtocol (
     69                   &gEfiDevicePathUtilitiesProtocolGuid,
     70                   NULL,
     71                   (VOID**) &mDevicePathLibDevicePathUtilities
     72                   );
     73   ASSERT_EFI_ERROR (Status);
     74   ASSERT (mDevicePathLibDevicePathUtilities != NULL);
     75   return Status;
     76 }
     77 
     78 /**
     79   Determine whether a given device path is valid.
     80   If DevicePath is NULL, then ASSERT().
     81 
     82   @param  DevicePath  A pointer to a device path data structure.
     83   @param  MaxSize     The maximum size of the device path data structure.
     84 
     85   @retval TRUE        DevicePath is valid.
     86   @retval FALSE       The length of any node node in the DevicePath is less
     87                       than sizeof (EFI_DEVICE_PATH_PROTOCOL).
     88   @retval FALSE       If MaxSize is not zero, the size of the DevicePath
     89                       exceeds MaxSize.
     90   @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
     91                       count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
     92 **/
     93 BOOLEAN
     94 EFIAPI
     95 IsDevicePathValid (
     96   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
     97   IN       UINTN                    MaxSize
     98   )
     99 {
    100   UINTN Count;
    101   UINTN Size;
    102   UINTN NodeLength;
    103 
    104   ASSERT (DevicePath != NULL);
    105 
    106   for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
    107     NodeLength = DevicePathNodeLength (DevicePath);
    108     if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
    109       return FALSE;
    110     }
    111 
    112     if (MaxSize > 0) {
    113       Size += NodeLength;
    114       if (Size + END_DEVICE_PATH_LENGTH > MaxSize) {
    115         return FALSE;
    116       }
    117     }
    118 
    119     if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
    120       Count++;
    121       if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
    122         return FALSE;
    123       }
    124     }
    125   }
    126 
    127   //
    128   // Only return TRUE when the End Device Path node is valid.
    129   //
    130   return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
    131 }
    132 
    133 /**
    134   Returns the Type field of a device path node.
    135 
    136   Returns the Type field of the device path node specified by Node.
    137 
    138   If Node is NULL, then ASSERT().
    139 
    140   @param  Node      A pointer to a device path node data structure.
    141 
    142   @return The Type field of the device path node specified by Node.
    143 
    144 **/
    145 UINT8
    146 EFIAPI
    147 DevicePathType (
    148   IN CONST VOID  *Node
    149   )
    150 {
    151   ASSERT (Node != NULL);
    152   return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;
    153 }
    154 
    155 /**
    156   Returns the SubType field of a device path node.
    157 
    158   Returns the SubType field of the device path node specified by Node.
    159 
    160   If Node is NULL, then ASSERT().
    161 
    162   @param  Node      A pointer to a device path node data structure.
    163 
    164   @return The SubType field of the device path node specified by Node.
    165 
    166 **/
    167 UINT8
    168 EFIAPI
    169 DevicePathSubType (
    170   IN CONST VOID  *Node
    171   )
    172 {
    173   ASSERT (Node != NULL);
    174   return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;
    175 }
    176 
    177 /**
    178   Returns the 16-bit Length field of a device path node.
    179 
    180   Returns the 16-bit Length field of the device path node specified by Node.
    181   Node is not required to be aligned on a 16-bit boundary, so it is recommended
    182   that a function such as ReadUnaligned16() be used to extract the contents of
    183   the Length field.
    184 
    185   If Node is NULL, then ASSERT().
    186 
    187   @param  Node      A pointer to a device path node data structure.
    188 
    189   @return The 16-bit Length field of the device path node specified by Node.
    190 
    191 **/
    192 UINTN
    193 EFIAPI
    194 DevicePathNodeLength (
    195   IN CONST VOID  *Node
    196   )
    197 {
    198   ASSERT (Node != NULL);
    199   return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
    200 }
    201 
    202 /**
    203   Returns a pointer to the next node in a device path.
    204 
    205   Returns a pointer to the device path node that follows the device path node
    206   specified by Node.
    207 
    208   If Node is NULL, then ASSERT().
    209 
    210   @param  Node      A pointer to a device path node data structure.
    211 
    212   @return a pointer to the device path node that follows the device path node
    213   specified by Node.
    214 
    215 **/
    216 EFI_DEVICE_PATH_PROTOCOL *
    217 EFIAPI
    218 NextDevicePathNode (
    219   IN CONST VOID  *Node
    220   )
    221 {
    222   ASSERT (Node != NULL);
    223   return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));
    224 }
    225 
    226 /**
    227   Determines if a device path node is an end node of a device path.
    228   This includes nodes that are the end of a device path instance and nodes that
    229   are the end of an entire device path.
    230 
    231   Determines if the device path node specified by Node is an end node of a device path.
    232   This includes nodes that are the end of a device path instance and nodes that are the
    233   end of an entire device path.  If Node represents an end node of a device path,
    234   then TRUE is returned.  Otherwise, FALSE is returned.
    235 
    236   If Node is NULL, then ASSERT().
    237 
    238   @param  Node      A pointer to a device path node data structure.
    239 
    240   @retval TRUE      The device path node specified by Node is an end node of a device path.
    241   @retval FALSE     The device path node specified by Node is not an end node of
    242                     a device path.
    243 
    244 **/
    245 BOOLEAN
    246 EFIAPI
    247 IsDevicePathEndType (
    248   IN CONST VOID  *Node
    249   )
    250 {
    251   ASSERT (Node != NULL);
    252   return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);
    253 }
    254 
    255 /**
    256   Determines if a device path node is an end node of an entire device path.
    257 
    258   Determines if a device path node specified by Node is an end node of an entire
    259   device path.
    260   If Node represents the end of an entire device path, then TRUE is returned.
    261   Otherwise, FALSE is returned.
    262 
    263   If Node is NULL, then ASSERT().
    264 
    265   @param  Node      A pointer to a device path node data structure.
    266 
    267   @retval TRUE      The device path node specified by Node is the end of an entire device path.
    268   @retval FALSE     The device path node specified by Node is not the end of an entire device path.
    269 
    270 **/
    271 BOOLEAN
    272 EFIAPI
    273 IsDevicePathEnd (
    274   IN CONST VOID  *Node
    275   )
    276 {
    277   ASSERT (Node != NULL);
    278   return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
    279 }
    280 
    281 /**
    282   Determines if a device path node is an end node of a device path instance.
    283 
    284   Determines if a device path node specified by Node is an end node of a device
    285   path instance.
    286   If Node represents the end of a device path instance, then TRUE is returned.
    287   Otherwise, FALSE is returned.
    288 
    289   If Node is NULL, then ASSERT().
    290 
    291   @param  Node      A pointer to a device path node data structure.
    292 
    293   @retval TRUE      The device path node specified by Node is the end of a device
    294   path instance.
    295   @retval FALSE     The device path node specified by Node is not the end of a
    296   device path instance.
    297 
    298 **/
    299 BOOLEAN
    300 EFIAPI
    301 IsDevicePathEndInstance (
    302   IN CONST VOID  *Node
    303   )
    304 {
    305   ASSERT (Node != NULL);
    306   return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
    307 }
    308 
    309 /**
    310   Sets the length, in bytes, of a device path node.
    311 
    312   Sets the length of the device path node specified by Node to the value specified
    313   by NodeLength.  NodeLength is returned.  Node is not required to be aligned on
    314   a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16()
    315   be used to set the contents of the Length field.
    316 
    317   If Node is NULL, then ASSERT().
    318   If NodeLength >= SIZE_64KB, then ASSERT().
    319   If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT().
    320 
    321   @param  Node      A pointer to a device path node data structure.
    322   @param  Length    The length, in bytes, of the device path node.
    323 
    324   @return Length
    325 
    326 **/
    327 UINT16
    328 EFIAPI
    329 SetDevicePathNodeLength (
    330   IN OUT VOID  *Node,
    331   IN UINTN     Length
    332   )
    333 {
    334   ASSERT (Node != NULL);
    335   ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB));
    336   return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
    337 }
    338 
    339 /**
    340   Fills in all the fields of a device path node that is the end of an entire device path.
    341 
    342   Fills in all the fields of a device path node specified by Node so Node represents
    343   the end of an entire device path.  The Type field of Node is set to
    344   END_DEVICE_PATH_TYPE, the SubType field of Node is set to
    345   END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to
    346   END_DEVICE_PATH_LENGTH.  Node is not required to be aligned on a 16-bit boundary,
    347   so it is recommended that a function such as WriteUnaligned16() be used to set
    348   the contents of the Length field.
    349 
    350   If Node is NULL, then ASSERT().
    351 
    352   @param  Node      A pointer to a device path node data structure.
    353 
    354 **/
    355 VOID
    356 EFIAPI
    357 SetDevicePathEndNode (
    358   OUT VOID  *Node
    359   )
    360 {
    361   ASSERT (Node != NULL);
    362   CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
    363 }
    364 
    365 /**
    366   Returns the size of a device path in bytes.
    367 
    368   This function returns the size, in bytes, of the device path data structure
    369   specified by DevicePath including the end of device path node.
    370   If DevicePath is NULL or invalid, then 0 is returned.
    371 
    372   @param  DevicePath  A pointer to a device path data structure.
    373 
    374   @retval 0           If DevicePath is NULL or invalid.
    375   @retval Others      The size of a device path in bytes.
    376 
    377 **/
    378 UINTN
    379 EFIAPI
    380 GetDevicePathSize (
    381   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    382   )
    383 {
    384   return mDevicePathLibDevicePathUtilities->GetDevicePathSize (DevicePath);
    385 }
    386 
    387 /**
    388   Creates a new copy of an existing device path.
    389 
    390   This function allocates space for a new copy of the device path specified by
    391   DevicePath.  If DevicePath is NULL, then NULL is returned.
    392   If the memory is successfully allocated, then the
    393   contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer
    394   is returned.  Otherwise, NULL is returned.
    395   The memory for the new device path is allocated from EFI boot services memory.
    396   It is the responsibility of the caller to free the memory allocated.
    397 
    398   @param  DevicePath                 A pointer to a device path data structure.
    399 
    400   @retval NULL    If DevicePath is NULL or invalid.
    401   @retval Others  A pointer to the duplicated device path.
    402 
    403 **/
    404 EFI_DEVICE_PATH_PROTOCOL *
    405 EFIAPI
    406 DuplicateDevicePath (
    407   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    408   )
    409 {
    410   return mDevicePathLibDevicePathUtilities->DuplicateDevicePath (DevicePath);
    411 }
    412 
    413 /**
    414   Creates a new device path by appending a second device path to a first device path.
    415 
    416   This function creates a new device path by appending a copy of SecondDevicePath to a copy of
    417   FirstDevicePath in a newly allocated buffer.  Only the end-of-device-path device node from
    418   SecondDevicePath is retained. The newly created device path is returned.
    419   If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned.
    420   If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned.
    421   If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is
    422   returned.
    423   If there is not enough memory for the newly allocated buffer, then NULL is returned.
    424   The memory for the new device path is allocated from EFI boot services memory. It is the
    425   responsibility of the caller to free the memory allocated.
    426 
    427   @param  FirstDevicePath            A pointer to a device path data structure.
    428   @param  SecondDevicePath           A pointer to a device path data structure.
    429 
    430   @retval NULL      If there is not enough memory for the newly allocated buffer.
    431   @retval NULL      If FirstDevicePath or SecondDevicePath is invalid.
    432   @retval Others    A pointer to the new device path if success.
    433                     Or a copy an end-of-device-path if both FirstDevicePath and
    434                     SecondDevicePath are NULL.
    435 
    436 **/
    437 EFI_DEVICE_PATH_PROTOCOL *
    438 EFIAPI
    439 AppendDevicePath (
    440   IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
    441   IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
    442   )
    443 {
    444   return mDevicePathLibDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath);
    445 }
    446 
    447 /**
    448   Creates a new path by appending the device node to the device path.
    449 
    450   This function creates a new device path by appending a copy of the device node
    451   specified by DevicePathNode to a copy of the device path specified by DevicePath
    452   in an allocated buffer.
    453   The end-of-device-path device node is moved after the end of the appended device node.
    454   If DevicePathNode is NULL then a copy of DevicePath is returned.
    455   If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
    456   path device node is returned.
    457   If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
    458   device node is returned.
    459   If there is not enough memory to allocate space for the new device path, then
    460   NULL is returned.
    461   The memory is allocated from EFI boot services memory. It is the responsibility
    462   of the caller to free the memory allocated.
    463 
    464   @param  DevicePath                 A pointer to a device path data structure.
    465   @param  DevicePathNode             A pointer to a single device path node.
    466 
    467   @retval NULL      If there is not enough memory for the new device path.
    468   @retval Others    A pointer to the new device path if success.
    469                     A copy of DevicePathNode followed by an end-of-device-path node
    470                     if both FirstDevicePath and SecondDevicePath are NULL.
    471                     A copy of an end-of-device-path node if both FirstDevicePath
    472                     and SecondDevicePath are NULL.
    473 
    474 **/
    475 EFI_DEVICE_PATH_PROTOCOL *
    476 EFIAPI
    477 AppendDevicePathNode (
    478   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
    479   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
    480   )
    481 {
    482   return mDevicePathLibDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode);
    483 }
    484 
    485 /**
    486   Creates a new device path by appending the specified device path instance to
    487   the specified device path.
    488 
    489   This function creates a new device path by appending a copy of the device path
    490   instance specified by DevicePathInstance to a copy of the device path specified
    491   by DevicePath in a allocated buffer.
    492   The end-of-device-path device node is moved after the end of the appended device
    493   path instance and a new end-of-device-path-instance node is inserted between.
    494   If DevicePath is NULL, then a copy if DevicePathInstance is returned.
    495   If DevicePathInstance is NULL, then NULL is returned.
    496   If DevicePath or DevicePathInstance is invalid, then NULL is returned.
    497   If there is not enough memory to allocate space for the new device path, then
    498   NULL is returned.
    499   The memory is allocated from EFI boot services memory. It is the responsibility
    500   of the caller to free the memory allocated.
    501 
    502   @param  DevicePath                 A pointer to a device path data structure.
    503   @param  DevicePathInstance         A pointer to a device path instance.
    504 
    505   @return A pointer to the new device path.
    506 
    507 **/
    508 EFI_DEVICE_PATH_PROTOCOL *
    509 EFIAPI
    510 AppendDevicePathInstance (
    511   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
    512   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
    513   )
    514 {
    515   return mDevicePathLibDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance);
    516 }
    517 
    518 /**
    519   Creates a copy of the current device path instance and returns a pointer to the
    520   next device path instance.
    521 
    522   This function creates a copy of the current device path instance. It also updates
    523   DevicePath to point to the next device path instance in the device path (or NULL
    524   if no more) and updates Size to hold the size of the device path instance copy.
    525   If DevicePath is NULL, then NULL is returned.
    526   If there is not enough memory to allocate space for the new device path, then
    527   NULL is returned.
    528   The memory is allocated from EFI boot services memory. It is the responsibility
    529   of the caller to free the memory allocated.
    530   If Size is NULL, then ASSERT().
    531 
    532   @param  DevicePath                 On input, this holds the pointer to the current
    533                                      device path instance. On output, this holds
    534                                      the pointer to the next device path instance
    535                                      or NULL if there are no more device path
    536                                      instances in the device path pointer to a
    537                                      device path data structure.
    538   @param  Size                       On output, this holds the size of the device
    539                                      path instance, in bytes or zero, if DevicePath
    540                                      is NULL.
    541 
    542   @return A pointer to the current device path instance.
    543 
    544 **/
    545 EFI_DEVICE_PATH_PROTOCOL *
    546 EFIAPI
    547 GetNextDevicePathInstance (
    548   IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
    549   OUT UINTN                          *Size
    550   )
    551 {
    552   ASSERT (Size != NULL);
    553   return mDevicePathLibDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size);
    554 }
    555 
    556 /**
    557   Creates a device node.
    558 
    559   This function creates a new device node in a newly allocated buffer of size
    560   NodeLength and initializes the device path node header with NodeType and NodeSubType.
    561   The new device path node is returned.
    562   If NodeLength is smaller than a device path header, then NULL is returned.
    563   If there is not enough memory to allocate space for the new device path, then
    564   NULL is returned.
    565   The memory is allocated from EFI boot services memory. It is the responsibility
    566   of the caller to free the memory allocated.
    567 
    568   @param  NodeType                   The device node type for the new device node.
    569   @param  NodeSubType                The device node sub-type for the new device node.
    570   @param  NodeLength                 The length of the new device node.
    571 
    572   @return The new device path.
    573 
    574 **/
    575 EFI_DEVICE_PATH_PROTOCOL *
    576 EFIAPI
    577 CreateDeviceNode (
    578   IN UINT8                           NodeType,
    579   IN UINT8                           NodeSubType,
    580   IN UINT16                          NodeLength
    581   )
    582 {
    583   return mDevicePathLibDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength);
    584 }
    585 
    586 /**
    587   Determines if a device path is single or multi-instance.
    588 
    589   This function returns TRUE if the device path specified by DevicePath is
    590   multi-instance.
    591   Otherwise, FALSE is returned.
    592   If DevicePath is NULL or invalid, then FALSE is returned.
    593 
    594   @param  DevicePath                 A pointer to a device path data structure.
    595 
    596   @retval  TRUE                      DevicePath is multi-instance.
    597   @retval  FALSE                     DevicePath is not multi-instance, or DevicePath
    598                                      is NULL or invalid.
    599 
    600 **/
    601 BOOLEAN
    602 EFIAPI
    603 IsDevicePathMultiInstance (
    604   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    605   )
    606 {
    607   return mDevicePathLibDevicePathUtilities->IsDevicePathMultiInstance (DevicePath);
    608 }
    609 
    610 /**
    611   Retrieves the device path protocol from a handle.
    612 
    613   This function returns the device path protocol from the handle specified by Handle.
    614   If Handle is NULL or Handle does not contain a device path protocol, then NULL
    615   is returned.
    616 
    617   @param  Handle                     The handle from which to retrieve the device
    618                                      path protocol.
    619 
    620   @return The device path protocol from the handle specified by Handle.
    621 
    622 **/
    623 EFI_DEVICE_PATH_PROTOCOL *
    624 EFIAPI
    625 DevicePathFromHandle (
    626   IN EFI_HANDLE                      Handle
    627   )
    628 {
    629   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    630   EFI_STATUS                Status;
    631 
    632   Status = gBS->HandleProtocol (
    633                   Handle,
    634                   &gEfiDevicePathProtocolGuid,
    635                   (VOID *) &DevicePath
    636                   );
    637   if (EFI_ERROR (Status)) {
    638     DevicePath = NULL;
    639   }
    640   return DevicePath;
    641 }
    642 
    643 /**
    644   Allocates a device path for a file and appends it to an existing device path.
    645 
    646   If Device is a valid device handle that contains a device path protocol, then
    647   a device path for the file specified by FileName  is allocated and appended to
    648   the device path associated with the handle Device.  The allocated device path
    649   is returned.  If Device is NULL or Device is a handle that does not support the
    650   device path protocol, then a device path containing a single device path node
    651   for the file specified by FileName is allocated and returned.
    652   The memory for the new device path is allocated from EFI boot services memory.
    653   It is the responsibility of the caller to free the memory allocated.
    654 
    655   If FileName is NULL, then ASSERT().
    656   If FileName is not aligned on a 16-bit boundary, then ASSERT().
    657 
    658   @param  Device                     A pointer to a device handle.  This parameter
    659                                      is optional and may be NULL.
    660   @param  FileName                   A pointer to a Null-terminated Unicode string.
    661 
    662   @return The allocated device path.
    663 
    664 **/
    665 EFI_DEVICE_PATH_PROTOCOL *
    666 EFIAPI
    667 FileDevicePath (
    668   IN EFI_HANDLE                      Device,     OPTIONAL
    669   IN CONST CHAR16                    *FileName
    670   )
    671 {
    672   UINTN                     Size;
    673   FILEPATH_DEVICE_PATH      *FilePath;
    674   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    675   EFI_DEVICE_PATH_PROTOCOL  *FileDevicePath;
    676 
    677   DevicePath = NULL;
    678 
    679   Size = StrSize (FileName);
    680   FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
    681   if (FileDevicePath != NULL) {
    682     FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
    683     FilePath->Header.Type    = MEDIA_DEVICE_PATH;
    684     FilePath->Header.SubType = MEDIA_FILEPATH_DP;
    685     CopyMem (&FilePath->PathName, FileName, Size);
    686     SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
    687     SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
    688 
    689     if (Device != NULL) {
    690       DevicePath = DevicePathFromHandle (Device);
    691     }
    692 
    693     DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
    694     FreePool (FileDevicePath);
    695   }
    696 
    697   return DevicePath;
    698 }
    699 
    700 /**
    701   Locate and return the protocol instance identified by the ProtocolGuid.
    702 
    703   @param ProtocolGuid     The GUID of the protocol.
    704 
    705   @return A pointer to the protocol instance or NULL when absent.
    706 **/
    707 VOID *
    708 UefiDevicePathLibLocateProtocol (
    709   EFI_GUID                         *ProtocolGuid
    710   )
    711 {
    712   EFI_STATUS Status;
    713   VOID       *Protocol;
    714   Status = gBS->LocateProtocol (
    715                   ProtocolGuid,
    716                   NULL,
    717                   (VOID**) &Protocol
    718                   );
    719   if (EFI_ERROR (Status)) {
    720     return NULL;
    721   } else {
    722     return Protocol;
    723   }
    724 }
    725 
    726 /**
    727   Converts a device node to its string representation.
    728 
    729   @param DeviceNode        A Pointer to the device node to be converted.
    730   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
    731                            of the display node is used, where applicable. If DisplayOnly
    732                            is FALSE, then the longer text representation of the display node
    733                            is used.
    734   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
    735                            representation for a device node can be used, where applicable.
    736 
    737   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
    738           is NULL or there was insufficient memory.
    739 
    740 **/
    741 CHAR16 *
    742 EFIAPI
    743 ConvertDeviceNodeToText (
    744   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
    745   IN BOOLEAN                         DisplayOnly,
    746   IN BOOLEAN                         AllowShortcuts
    747   )
    748 {
    749   if (mDevicePathLibDevicePathToText == NULL) {
    750     mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
    751   }
    752   if (mDevicePathLibDevicePathToText != NULL) {
    753     return mDevicePathLibDevicePathToText->ConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts);
    754   } else {
    755     return NULL;
    756   }
    757 }
    758 
    759 /**
    760   Converts a device path to its text representation.
    761 
    762   @param DevicePath      A Pointer to the device to be converted.
    763   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
    764                          of the display node is used, where applicable. If DisplayOnly
    765                          is FALSE, then the longer text representation of the display node
    766                          is used.
    767   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
    768                          representation for a device node can be used, where applicable.
    769 
    770   @return A pointer to the allocated text representation of the device path or
    771           NULL if DeviceNode is NULL or there was insufficient memory.
    772 
    773 **/
    774 CHAR16 *
    775 EFIAPI
    776 ConvertDevicePathToText (
    777   IN CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
    778   IN BOOLEAN                          DisplayOnly,
    779   IN BOOLEAN                          AllowShortcuts
    780   )
    781 {
    782   if (mDevicePathLibDevicePathToText == NULL) {
    783     mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
    784   }
    785   if (mDevicePathLibDevicePathToText != NULL) {
    786     return mDevicePathLibDevicePathToText->ConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts);
    787   } else {
    788     return NULL;
    789   }
    790 }
    791 
    792 /**
    793   Convert text to the binary representation of a device node.
    794 
    795   @param TextDeviceNode  TextDeviceNode points to the text representation of a device
    796                          node. Conversion starts with the first character and continues
    797                          until the first non-device node character.
    798 
    799   @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
    800           insufficient memory or text unsupported.
    801 
    802 **/
    803 EFI_DEVICE_PATH_PROTOCOL *
    804 EFIAPI
    805 ConvertTextToDeviceNode (
    806   IN CONST CHAR16 *TextDeviceNode
    807   )
    808 {
    809   if (mDevicePathLibDevicePathFromText == NULL) {
    810     mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
    811   }
    812   if (mDevicePathLibDevicePathFromText != NULL) {
    813     return mDevicePathLibDevicePathFromText->ConvertTextToDeviceNode (TextDeviceNode);
    814   } else {
    815     return NULL;
    816   }
    817 }
    818 
    819 /**
    820   Convert text to the binary representation of a device path.
    821 
    822 
    823   @param TextDevicePath  TextDevicePath points to the text representation of a device
    824                          path. Conversion starts with the first character and continues
    825                          until the first non-device node character.
    826 
    827   @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
    828           there was insufficient memory.
    829 
    830 **/
    831 EFI_DEVICE_PATH_PROTOCOL *
    832 EFIAPI
    833 ConvertTextToDevicePath (
    834   IN CONST CHAR16 *TextDevicePath
    835   )
    836 {
    837   if (mDevicePathLibDevicePathFromText == NULL) {
    838     mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
    839   }
    840   if (mDevicePathLibDevicePathFromText != NULL) {
    841     return mDevicePathLibDevicePathFromText->ConvertTextToDevicePath (TextDevicePath);
    842   } else {
    843     return NULL;
    844   }
    845 }
    846 
    847