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