Home | History | Annotate | Download | only in UefiDevicePathLib
      1 /** @file
      2   Device Path services. The thing to remember is device paths are built out of
      3   nodes. The device path is terminated by an end node that is length
      4   sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
      5   all over this file.
      6 
      7   The only place where multi-instance device paths are supported is in
      8   environment varibles. Multi-instance device paths should never be placed
      9   on a Handle.
     10 
     11   Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
     12   This program and the accompanying materials
     13   are licensed and made available under the terms and conditions of the BSD License
     14   which accompanies this distribution.  The full text of the license may be found at
     15   http://opensource.org/licenses/bsd-license.php.
     16 
     17   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     19 
     20 **/
     21 
     22 
     23 #include "UefiDevicePathLib.h"
     24 
     25 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathLibDevicePathUtilities = NULL;
     26 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_TO_TEXT_PROTOCOL   *mDevicePathLibDevicePathToText    = NULL;
     27 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mDevicePathLibDevicePathFromText  = NULL;
     28 
     29 /**
     30   The constructor function caches the pointer to DevicePathUtilites protocol,
     31   DevicePathToText protocol and DevicePathFromText protocol.
     32 
     33   The constructor function locates these three protocols from protocol database.
     34   It will caches the pointer to local protocol instance if that operation fails
     35   and it will always return EFI_SUCCESS.
     36 
     37   @param  ImageHandle   The firmware allocated handle for the EFI image.
     38   @param  SystemTable   A pointer to the EFI System Table.
     39 
     40   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
     41 
     42 **/
     43 EFI_STATUS
     44 EFIAPI
     45 UefiDevicePathLibOptionalDevicePathProtocolConstructor (
     46   IN      EFI_HANDLE                ImageHandle,
     47   IN      EFI_SYSTEM_TABLE          *SystemTable
     48   )
     49 {
     50   EFI_STATUS                        Status;
     51 
     52   Status = gBS->LocateProtocol (
     53                   &gEfiDevicePathUtilitiesProtocolGuid,
     54                   NULL,
     55                   (VOID**) &mDevicePathLibDevicePathUtilities
     56                   );
     57   ASSERT_EFI_ERROR (Status);
     58   ASSERT (mDevicePathLibDevicePathUtilities != NULL);
     59   return Status;
     60 }
     61 
     62 /**
     63   Returns the size of a device path in bytes.
     64 
     65   This function returns the size, in bytes, of the device path data structure
     66   specified by DevicePath including the end of device path node.
     67   If DevicePath is NULL or invalid, then 0 is returned.
     68 
     69   @param  DevicePath  A pointer to a device path data structure.
     70 
     71   @retval 0           If DevicePath is NULL or invalid.
     72   @retval Others      The size of a device path in bytes.
     73 
     74 **/
     75 UINTN
     76 EFIAPI
     77 GetDevicePathSize (
     78   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
     79   )
     80 {
     81   if (mDevicePathLibDevicePathUtilities != NULL) {
     82     return mDevicePathLibDevicePathUtilities->GetDevicePathSize (DevicePath);
     83   } else {
     84     return UefiDevicePathLibGetDevicePathSize (DevicePath);
     85   }
     86 }
     87 
     88 /**
     89   Creates a new copy of an existing device path.
     90 
     91   This function allocates space for a new copy of the device path specified by DevicePath.
     92   If DevicePath is NULL, then NULL is returned.  If the memory is successfully
     93   allocated, then the contents of DevicePath are copied to the newly allocated
     94   buffer, and a pointer to that buffer is returned.  Otherwise, NULL is returned.
     95   The memory for the new device path is allocated from EFI boot services memory.
     96   It is the responsibility of the caller to free the memory allocated.
     97 
     98   @param  DevicePath    A pointer to a device path data structure.
     99 
    100   @retval NULL          DevicePath is NULL or invalid.
    101   @retval Others        A pointer to the duplicated device path.
    102 
    103 **/
    104 EFI_DEVICE_PATH_PROTOCOL *
    105 EFIAPI
    106 DuplicateDevicePath (
    107   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    108   )
    109 {
    110   if (mDevicePathLibDevicePathUtilities != NULL) {
    111     return mDevicePathLibDevicePathUtilities->DuplicateDevicePath (DevicePath);
    112   } else {
    113     return UefiDevicePathLibDuplicateDevicePath (DevicePath);
    114   }
    115 }
    116 
    117 /**
    118   Creates a new device path by appending a second device path to a first device path.
    119 
    120   This function creates a new device path by appending a copy of SecondDevicePath
    121   to a copy of FirstDevicePath in a newly allocated buffer.  Only the end-of-device-path
    122   device node from SecondDevicePath is retained. The newly created device path is
    123   returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
    124   SecondDevicePath is returned.  If SecondDevicePath is NULL, then it is ignored,
    125   and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
    126   SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
    127 
    128   If there is not enough memory for the newly allocated buffer, then NULL is returned.
    129   The memory for the new device path is allocated from EFI boot services memory.
    130   It is the responsibility of the caller to free the memory allocated.
    131 
    132   @param  FirstDevicePath            A pointer to a device path data structure.
    133   @param  SecondDevicePath           A pointer to a device path data structure.
    134 
    135   @retval NULL      If there is not enough memory for the newly allocated buffer.
    136   @retval NULL      If FirstDevicePath or SecondDevicePath is invalid.
    137   @retval Others    A pointer to the new device path if success.
    138                     Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
    139 
    140 **/
    141 EFI_DEVICE_PATH_PROTOCOL *
    142 EFIAPI
    143 AppendDevicePath (
    144   IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
    145   IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
    146   )
    147 {
    148   if (mDevicePathLibDevicePathUtilities != NULL) {
    149     return mDevicePathLibDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath);
    150   } else {
    151     return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath);
    152   }
    153 }
    154 
    155 /**
    156   Creates a new path by appending the device node to the device path.
    157 
    158   This function creates a new device path by appending a copy of the device node
    159   specified by DevicePathNode to a copy of the device path specified by DevicePath
    160   in an allocated buffer. The end-of-device-path device node is moved after the
    161   end of the appended device node.
    162   If DevicePathNode is NULL then a copy of DevicePath is returned.
    163   If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
    164   path device node is returned.
    165   If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
    166   device node is returned.
    167   If there is not enough memory to allocate space for the new device path, then
    168   NULL is returned.
    169   The memory is allocated from EFI boot services memory. It is the responsibility
    170   of the caller to free the memory allocated.
    171 
    172   @param  DevicePath                 A pointer to a device path data structure.
    173   @param  DevicePathNode             A pointer to a single device path node.
    174 
    175   @retval NULL      If there is not enough memory for the new device path.
    176   @retval Others    A pointer to the new device path if success.
    177                     A copy of DevicePathNode followed by an end-of-device-path node
    178                     if both FirstDevicePath and SecondDevicePath are NULL.
    179                     A copy of an end-of-device-path node if both FirstDevicePath
    180                     and SecondDevicePath are NULL.
    181 
    182 **/
    183 EFI_DEVICE_PATH_PROTOCOL *
    184 EFIAPI
    185 AppendDevicePathNode (
    186   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
    187   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
    188   )
    189 {
    190   if (mDevicePathLibDevicePathUtilities != NULL) {
    191     return mDevicePathLibDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode);
    192   } else {
    193     return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode);
    194   }
    195 }
    196 
    197 /**
    198   Creates a new device path by appending the specified device path instance to the specified device
    199   path.
    200 
    201   This function creates a new device path by appending a copy of the device path
    202   instance specified by DevicePathInstance to a copy of the device path specified
    203   by DevicePath in a allocated buffer.
    204   The end-of-device-path device node is moved after the end of the appended device
    205   path instance and a new end-of-device-path-instance node is inserted between.
    206   If DevicePath is NULL, then a copy if DevicePathInstance is returned.
    207   If DevicePathInstance is NULL, then NULL is returned.
    208   If DevicePath or DevicePathInstance is invalid, then NULL is returned.
    209   If there is not enough memory to allocate space for the new device path, then
    210   NULL is returned.
    211   The memory is allocated from EFI boot services memory. It is the responsibility
    212   of the caller to free the memory allocated.
    213 
    214   @param  DevicePath                 A pointer to a device path data structure.
    215   @param  DevicePathInstance         A pointer to a device path instance.
    216 
    217   @return A pointer to the new device path.
    218 
    219 **/
    220 EFI_DEVICE_PATH_PROTOCOL *
    221 EFIAPI
    222 AppendDevicePathInstance (
    223   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
    224   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
    225   )
    226 {
    227   if (mDevicePathLibDevicePathUtilities != NULL) {
    228     return mDevicePathLibDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance);
    229   } else {
    230     return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance);
    231   }
    232 }
    233 
    234 /**
    235   Creates a copy of the current device path instance and returns a pointer to the next device path
    236   instance.
    237 
    238   This function creates a copy of the current device path instance. It also updates
    239   DevicePath to point to the next device path instance in the device path (or NULL
    240   if no more) and updates Size to hold the size of the device path instance copy.
    241   If DevicePath is NULL, then NULL is returned.
    242   If DevicePath points to a invalid device path, then NULL is returned.
    243   If there is not enough memory to allocate space for the new device path, then
    244   NULL is returned.
    245   The memory is allocated from EFI boot services memory. It is the responsibility
    246   of the caller to free the memory allocated.
    247   If Size is NULL, then ASSERT().
    248 
    249   @param  DevicePath                 On input, this holds the pointer to the current
    250                                      device path instance. On output, this holds
    251                                      the pointer to the next device path instance
    252                                      or NULL if there are no more device path
    253                                      instances in the device path pointer to a
    254                                      device path data structure.
    255   @param  Size                       On output, this holds the size of the device
    256                                      path instance, in bytes or zero, if DevicePath
    257                                      is NULL.
    258 
    259   @return A pointer to the current device path instance.
    260 
    261 **/
    262 EFI_DEVICE_PATH_PROTOCOL *
    263 EFIAPI
    264 GetNextDevicePathInstance (
    265   IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
    266   OUT UINTN                          *Size
    267   )
    268 {
    269   if (mDevicePathLibDevicePathUtilities != NULL) {
    270     return mDevicePathLibDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size);
    271   } else {
    272     return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size);
    273   }
    274 }
    275 
    276 /**
    277   Creates a device node.
    278 
    279   This function creates a new device node in a newly allocated buffer of size
    280   NodeLength and initializes the device path node header with NodeType and NodeSubType.
    281   The new device path node is returned.
    282   If NodeLength is smaller than a device path header, then NULL is returned.
    283   If there is not enough memory to allocate space for the new device path, then
    284   NULL is returned.
    285   The memory is allocated from EFI boot services memory. It is the responsibility
    286   of the caller to free the memory allocated.
    287 
    288   @param  NodeType                   The device node type for the new device node.
    289   @param  NodeSubType                The device node sub-type for the new device node.
    290   @param  NodeLength                 The length of the new device node.
    291 
    292   @return The new device path.
    293 
    294 **/
    295 EFI_DEVICE_PATH_PROTOCOL *
    296 EFIAPI
    297 CreateDeviceNode (
    298   IN UINT8                           NodeType,
    299   IN UINT8                           NodeSubType,
    300   IN UINT16                          NodeLength
    301   )
    302 {
    303   if (mDevicePathLibDevicePathUtilities != NULL) {
    304     return mDevicePathLibDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength);
    305   } else {
    306     return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength);
    307   }
    308 }
    309 
    310 /**
    311   Determines if a device path is single or multi-instance.
    312 
    313   This function returns TRUE if the device path specified by DevicePath is
    314   multi-instance.
    315   Otherwise, FALSE is returned.
    316   If DevicePath is NULL or invalid, then FALSE is returned.
    317 
    318   @param  DevicePath                 A pointer to a device path data structure.
    319 
    320   @retval  TRUE                      DevicePath is multi-instance.
    321   @retval  FALSE                     DevicePath is not multi-instance, or DevicePath
    322                                      is NULL or invalid.
    323 
    324 **/
    325 BOOLEAN
    326 EFIAPI
    327 IsDevicePathMultiInstance (
    328   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    329   )
    330 {
    331   if (mDevicePathLibDevicePathUtilities != NULL) {
    332     return mDevicePathLibDevicePathUtilities->IsDevicePathMultiInstance (DevicePath);
    333   } else {
    334     return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath);
    335   }
    336 }
    337 
    338 /**
    339   Locate and return the protocol instance identified by the ProtocolGuid.
    340 
    341   @param ProtocolGuid     The GUID of the protocol.
    342 
    343   @return A pointer to the protocol instance or NULL when absent.
    344 **/
    345 VOID *
    346 UefiDevicePathLibLocateProtocol (
    347   EFI_GUID                         *ProtocolGuid
    348   )
    349 {
    350   EFI_STATUS Status;
    351   VOID       *Protocol;
    352   Status = gBS->LocateProtocol (
    353                   ProtocolGuid,
    354                   NULL,
    355                   (VOID**) &Protocol
    356                   );
    357   if (EFI_ERROR (Status)) {
    358     return NULL;
    359   } else {
    360     return Protocol;
    361   }
    362 }
    363 
    364 /**
    365   Converts a device node to its string representation.
    366 
    367   @param DeviceNode        A Pointer to the device node to be converted.
    368   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
    369                            of the display node is used, where applicable. If DisplayOnly
    370                            is FALSE, then the longer text representation of the display node
    371                            is used.
    372   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
    373                            representation for a device node can be used, where applicable.
    374 
    375   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
    376           is NULL or there was insufficient memory.
    377 
    378 **/
    379 CHAR16 *
    380 EFIAPI
    381 ConvertDeviceNodeToText (
    382   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
    383   IN BOOLEAN                         DisplayOnly,
    384   IN BOOLEAN                         AllowShortcuts
    385   )
    386 {
    387   if (mDevicePathLibDevicePathToText == NULL) {
    388     mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
    389   }
    390   if (mDevicePathLibDevicePathToText != NULL) {
    391     return mDevicePathLibDevicePathToText->ConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts);
    392   }
    393 
    394   return UefiDevicePathLibConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts);
    395 }
    396 
    397 /**
    398   Converts a device path to its text representation.
    399 
    400   @param DevicePath      A Pointer to the device to be converted.
    401   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
    402                          of the display node is used, where applicable. If DisplayOnly
    403                          is FALSE, then the longer text representation of the display node
    404                          is used.
    405   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
    406                          representation for a device node can be used, where applicable.
    407 
    408   @return A pointer to the allocated text representation of the device path or
    409           NULL if DeviceNode is NULL or there was insufficient memory.
    410 
    411 **/
    412 CHAR16 *
    413 EFIAPI
    414 ConvertDevicePathToText (
    415   IN CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
    416   IN BOOLEAN                          DisplayOnly,
    417   IN BOOLEAN                          AllowShortcuts
    418   )
    419 {
    420   if (mDevicePathLibDevicePathToText == NULL) {
    421     mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
    422   }
    423   if (mDevicePathLibDevicePathToText != NULL) {
    424     return mDevicePathLibDevicePathToText->ConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts);
    425   }
    426 
    427   return UefiDevicePathLibConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts);
    428 }
    429 
    430 /**
    431   Convert text to the binary representation of a device node.
    432 
    433   @param TextDeviceNode  TextDeviceNode points to the text representation of a device
    434                          node. Conversion starts with the first character and continues
    435                          until the first non-device node character.
    436 
    437   @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
    438           insufficient memory or text unsupported.
    439 
    440 **/
    441 EFI_DEVICE_PATH_PROTOCOL *
    442 EFIAPI
    443 ConvertTextToDeviceNode (
    444   IN CONST CHAR16 *TextDeviceNode
    445   )
    446 {
    447   if (mDevicePathLibDevicePathFromText == NULL) {
    448     mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
    449   }
    450   if (mDevicePathLibDevicePathFromText != NULL) {
    451     return mDevicePathLibDevicePathFromText->ConvertTextToDeviceNode (TextDeviceNode);
    452   }
    453 
    454   return UefiDevicePathLibConvertTextToDeviceNode (TextDeviceNode);
    455 }
    456 
    457 /**
    458   Convert text to the binary representation of a device path.
    459 
    460 
    461   @param TextDevicePath  TextDevicePath points to the text representation of a device
    462                          path. Conversion starts with the first character and continues
    463                          until the first non-device node character.
    464 
    465   @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
    466           there was insufficient memory.
    467 
    468 **/
    469 EFI_DEVICE_PATH_PROTOCOL *
    470 EFIAPI
    471 ConvertTextToDevicePath (
    472   IN CONST CHAR16 *TextDevicePath
    473   )
    474 {
    475   if (mDevicePathLibDevicePathFromText == NULL) {
    476     mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
    477   }
    478   if (mDevicePathLibDevicePathFromText != NULL) {
    479     return mDevicePathLibDevicePathFromText->ConvertTextToDevicePath (TextDevicePath);
    480   }
    481 
    482   return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath);
    483 }
    484 
    485