1 /*- 2 * Copyright (c) 2017 Netflix, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* 27 * Taken from MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h 28 */ 29 30 /** @file 31 Definition for Device Path library. 32 33 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> 34 SPDX-License-Identifier: BSD-2-Clause-Patent 35 36 **/ 37 38 #ifndef _UEFI_DEVICE_PATH_LIB_H_ 39 #define _UEFI_DEVICE_PATH_LIB_H_ 40 41 #include <Uefi.h> 42 #include <Protocol/DevicePathUtilities.h> 43 #include <Protocol/DebugPort.h> 44 #include <Protocol/DevicePathToText.h> 45 #include <Protocol/DevicePathFromText.h> 46 #include <Guid/PcAnsi.h> 47 #include <Library/DebugLib.h> 48 #include <Library/PrintLib.h> 49 #include <Library/BaseLib.h> 50 #include <Library/BaseMemoryLib.h> 51 #include <Library/MemoryAllocationLib.h> 52 #include <Library/UefiBootServicesTableLib.h> 53 #include <Library/DevicePathLib.h> 54 #include <Library/PcdLib.h> 55 #include <IndustryStandard/Bluetooth.h> 56 57 #define IS_COMMA(a) ((a) == ',') 58 #define IS_HYPHEN(a) ((a) == '-') 59 #define IS_DOT(a) ((a) == '.') 60 #define IS_LEFT_PARENTH(a) ((a) == '(') 61 #define IS_RIGHT_PARENTH(a) ((a) == ')') 62 #define IS_SLASH(a) ((a) == '/') 63 #define IS_NULL(a) ((a) == '\0') 64 65 // 66 // Private Data structure 67 // 68 typedef struct { 69 char *Str; 70 UINTN Count; 71 UINTN Capacity; 72 } POOL_PRINT; 73 74 typedef 75 EFI_DEVICE_PATH_PROTOCOL * 76 (*DEVICE_PATH_FROM_TEXT) ( 77 IN char *Str 78 ); 79 80 typedef 81 VOID 82 (*DEVICE_PATH_TO_TEXT) ( 83 IN OUT POOL_PRINT *Str, 84 IN VOID *DevicePath, 85 IN BOOLEAN DisplayOnly, 86 IN BOOLEAN AllowShortcuts 87 ); 88 89 typedef struct { 90 UINT8 Type; 91 UINT8 SubType; 92 DEVICE_PATH_TO_TEXT Function; 93 } DEVICE_PATH_TO_TEXT_TABLE; 94 95 typedef struct { 96 UINT8 Type; 97 const char *Text; 98 } DEVICE_PATH_TO_TEXT_GENERIC_TABLE; 99 100 typedef struct { 101 const char *DevicePathNodeText; 102 DEVICE_PATH_FROM_TEXT Function; 103 } DEVICE_PATH_FROM_TEXT_TABLE; 104 105 typedef struct { 106 BOOLEAN ClassExist; 107 UINT8 Class; 108 BOOLEAN SubClassExist; 109 UINT8 SubClass; 110 } USB_CLASS_TEXT; 111 112 #define USB_CLASS_AUDIO 1 113 #define USB_CLASS_CDCCONTROL 2 114 #define USB_CLASS_HID 3 115 #define USB_CLASS_IMAGE 6 116 #define USB_CLASS_PRINTER 7 117 #define USB_CLASS_MASS_STORAGE 8 118 #define USB_CLASS_HUB 9 119 #define USB_CLASS_CDCDATA 10 120 #define USB_CLASS_SMART_CARD 11 121 #define USB_CLASS_VIDEO 14 122 #define USB_CLASS_DIAGNOSTIC 220 123 #define USB_CLASS_WIRELESS 224 124 125 #define USB_CLASS_RESERVE 254 126 #define USB_SUBCLASS_FW_UPDATE 1 127 #define USB_SUBCLASS_IRDA_BRIDGE 2 128 #define USB_SUBCLASS_TEST 3 129 130 #define RFC_1700_UDP_PROTOCOL 17 131 #define RFC_1700_TCP_PROTOCOL 6 132 133 #pragma pack(1) 134 135 typedef struct { 136 EFI_DEVICE_PATH_PROTOCOL Header; 137 EFI_GUID Guid; 138 UINT8 VendorDefinedData[1]; 139 } VENDOR_DEFINED_HARDWARE_DEVICE_PATH; 140 141 typedef struct { 142 EFI_DEVICE_PATH_PROTOCOL Header; 143 EFI_GUID Guid; 144 UINT8 VendorDefinedData[1]; 145 } VENDOR_DEFINED_MESSAGING_DEVICE_PATH; 146 147 typedef struct { 148 EFI_DEVICE_PATH_PROTOCOL Header; 149 EFI_GUID Guid; 150 UINT8 VendorDefinedData[1]; 151 } VENDOR_DEFINED_MEDIA_DEVICE_PATH; 152 153 typedef struct { 154 EFI_DEVICE_PATH_PROTOCOL Header; 155 UINT32 Hid; 156 UINT32 Uid; 157 UINT32 Cid; 158 CHAR8 HidUidCidStr[3]; 159 } ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; 160 161 typedef struct { 162 EFI_DEVICE_PATH_PROTOCOL Header; 163 UINT16 NetworkProtocol; 164 UINT16 LoginOption; 165 UINT64 Lun; 166 UINT16 TargetPortalGroupTag; 167 CHAR8 TargetName[1]; 168 } ISCSI_DEVICE_PATH_WITH_NAME; 169 170 typedef struct { 171 EFI_DEVICE_PATH_PROTOCOL Header; 172 EFI_GUID Guid; 173 UINT8 VendorDefinedData[1]; 174 } VENDOR_DEVICE_PATH_WITH_DATA; 175 176 #pragma pack() 177 178 #ifdef FreeBSD /* Remove these on FreeBSD */ 179 180 /** 181 Returns the size of a device path in bytes. 182 183 This function returns the size, in bytes, of the device path data structure 184 specified by DevicePath including the end of device path node. 185 If DevicePath is NULL or invalid, then 0 is returned. 186 187 @param DevicePath A pointer to a device path data structure. 188 189 @retval 0 If DevicePath is NULL or invalid. 190 @retval Others The size of a device path in bytes. 191 192 **/ 193 UINTN 194 EFIAPI 195 UefiDevicePathLibGetDevicePathSize ( 196 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath 197 ); 198 199 /** 200 Creates a new copy of an existing device path. 201 202 This function allocates space for a new copy of the device path specified by DevicePath. 203 If DevicePath is NULL, then NULL is returned. If the memory is successfully 204 allocated, then the contents of DevicePath are copied to the newly allocated 205 buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. 206 The memory for the new device path is allocated from EFI boot services memory. 207 It is the responsibility of the caller to free the memory allocated. 208 209 @param DevicePath A pointer to a device path data structure. 210 211 @retval NULL DevicePath is NULL or invalid. 212 @retval Others A pointer to the duplicated device path. 213 214 **/ 215 EFI_DEVICE_PATH_PROTOCOL * 216 EFIAPI 217 UefiDevicePathLibDuplicateDevicePath ( 218 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath 219 ); 220 221 /** 222 Creates a new device path by appending a second device path to a first device path. 223 224 This function creates a new device path by appending a copy of SecondDevicePath 225 to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path 226 device node from SecondDevicePath is retained. The newly created device path is 227 returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of 228 SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, 229 and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and 230 SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. 231 232 If there is not enough memory for the newly allocated buffer, then NULL is returned. 233 The memory for the new device path is allocated from EFI boot services memory. 234 It is the responsibility of the caller to free the memory allocated. 235 236 @param FirstDevicePath A pointer to a device path data structure. 237 @param SecondDevicePath A pointer to a device path data structure. 238 239 @retval NULL If there is not enough memory for the newly allocated buffer. 240 @retval NULL If FirstDevicePath or SecondDevicePath is invalid. 241 @retval Others A pointer to the new device path if success. 242 Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. 243 244 **/ 245 EFI_DEVICE_PATH_PROTOCOL * 246 EFIAPI 247 UefiDevicePathLibAppendDevicePath ( 248 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath OPTIONAL, 249 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL 250 ); 251 252 /** 253 Creates a new path by appending the device node to the device path. 254 255 This function creates a new device path by appending a copy of the device node 256 specified by DevicePathNode to a copy of the device path specified by DevicePath 257 in an allocated buffer. The end-of-device-path device node is moved after the 258 end of the appended device node. 259 If DevicePathNode is NULL then a copy of DevicePath is returned. 260 If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device 261 path device node is returned. 262 If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path 263 device node is returned. 264 If there is not enough memory to allocate space for the new device path, then 265 NULL is returned. 266 The memory is allocated from EFI boot services memory. It is the responsibility 267 of the caller to free the memory allocated. 268 269 @param DevicePath A pointer to a device path data structure. 270 @param DevicePathNode A pointer to a single device path node. 271 272 @retval NULL If there is not enough memory for the new device path. 273 @retval Others A pointer to the new device path if success. 274 A copy of DevicePathNode followed by an end-of-device-path node 275 if both FirstDevicePath and SecondDevicePath are NULL. 276 A copy of an end-of-device-path node if both FirstDevicePath 277 and SecondDevicePath are NULL. 278 279 **/ 280 EFI_DEVICE_PATH_PROTOCOL * 281 EFIAPI 282 UefiDevicePathLibAppendDevicePathNode ( 283 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, 284 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL 285 ); 286 287 /** 288 Creates a new device path by appending the specified device path instance to the specified device 289 path. 290 291 This function creates a new device path by appending a copy of the device path 292 instance specified by DevicePathInstance to a copy of the device path specified 293 by DevicePath in a allocated buffer. 294 The end-of-device-path device node is moved after the end of the appended device 295 path instance and a new end-of-device-path-instance node is inserted between. 296 If DevicePath is NULL, then a copy if DevicePathInstance is returned. 297 If DevicePathInstance is NULL, then NULL is returned. 298 If DevicePath or DevicePathInstance is invalid, then NULL is returned. 299 If there is not enough memory to allocate space for the new device path, then 300 NULL is returned. 301 The memory is allocated from EFI boot services memory. It is the responsibility 302 of the caller to free the memory allocated. 303 304 @param DevicePath A pointer to a device path data structure. 305 @param DevicePathInstance A pointer to a device path instance. 306 307 @return A pointer to the new device path. 308 309 **/ 310 EFI_DEVICE_PATH_PROTOCOL * 311 EFIAPI 312 UefiDevicePathLibAppendDevicePathInstance ( 313 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, 314 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL 315 ); 316 317 /** 318 Creates a copy of the current device path instance and returns a pointer to the next device path 319 instance. 320 321 This function creates a copy of the current device path instance. It also updates 322 DevicePath to point to the next device path instance in the device path (or NULL 323 if no more) and updates Size to hold the size of the device path instance copy. 324 If DevicePath is NULL, then NULL is returned. 325 If DevicePath points to a invalid device path, then NULL is returned. 326 If there is not enough memory to allocate space for the new device path, then 327 NULL is returned. 328 The memory is allocated from EFI boot services memory. It is the responsibility 329 of the caller to free the memory allocated. 330 If Size is NULL, then ASSERT(). 331 332 @param DevicePath On input, this holds the pointer to the current 333 device path instance. On output, this holds 334 the pointer to the next device path instance 335 or NULL if there are no more device path 336 instances in the device path pointer to a 337 device path data structure. 338 @param Size On output, this holds the size of the device 339 path instance, in bytes or zero, if DevicePath 340 is NULL. 341 342 @return A pointer to the current device path instance. 343 344 **/ 345 EFI_DEVICE_PATH_PROTOCOL * 346 EFIAPI 347 UefiDevicePathLibGetNextDevicePathInstance ( 348 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, 349 OUT UINTN *Size 350 ); 351 352 /** 353 Creates a device node. 354 355 This function creates a new device node in a newly allocated buffer of size 356 NodeLength and initializes the device path node header with NodeType and NodeSubType. 357 The new device path node is returned. 358 If NodeLength is smaller than a device path header, then NULL is returned. 359 If there is not enough memory to allocate space for the new device path, then 360 NULL is returned. 361 The memory is allocated from EFI boot services memory. It is the responsibility 362 of the caller to free the memory allocated. 363 364 @param NodeType The device node type for the new device node. 365 @param NodeSubType The device node sub-type for the new device node. 366 @param NodeLength The length of the new device node. 367 368 @return The new device path. 369 370 **/ 371 EFI_DEVICE_PATH_PROTOCOL * 372 EFIAPI 373 UefiDevicePathLibCreateDeviceNode ( 374 IN UINT8 NodeType, 375 IN UINT8 NodeSubType, 376 IN UINT16 NodeLength 377 ); 378 379 /** 380 Determines if a device path is single or multi-instance. 381 382 This function returns TRUE if the device path specified by DevicePath is 383 multi-instance. 384 Otherwise, FALSE is returned. 385 If DevicePath is NULL or invalid, then FALSE is returned. 386 387 @param DevicePath A pointer to a device path data structure. 388 389 @retval TRUE DevicePath is multi-instance. 390 @retval FALSE DevicePath is not multi-instance, or DevicePath 391 is NULL or invalid. 392 393 **/ 394 BOOLEAN 395 EFIAPI 396 UefiDevicePathLibIsDevicePathMultiInstance ( 397 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath 398 ); 399 400 /** 401 Converts a device path to its text representation. 402 403 @param DevicePath A Pointer to the device to be converted. 404 @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation 405 of the display node is used, where applicable. If DisplayOnly 406 is FALSE, then the longer text representation of the display node 407 is used. 408 @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text 409 representation for a device node can be used, where applicable. 410 411 @return A pointer to the allocated text representation of the device path or 412 NULL if DeviceNode is NULL or there was insufficient memory. 413 414 **/ 415 CHAR16 * 416 EFIAPI 417 UefiDevicePathLibConvertDevicePathToText ( 418 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, 419 IN BOOLEAN DisplayOnly, 420 IN BOOLEAN AllowShortcuts 421 ); 422 423 /** 424 Converts a device node to its string representation. 425 426 @param DeviceNode A Pointer to the device node to be converted. 427 @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation 428 of the display node is used, where applicable. If DisplayOnly 429 is FALSE, then the longer text representation of the display node 430 is used. 431 @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text 432 representation for a device node can be used, where applicable. 433 434 @return A pointer to the allocated text representation of the device node or NULL if DeviceNode 435 is NULL or there was insufficient memory. 436 437 **/ 438 CHAR16 * 439 EFIAPI 440 UefiDevicePathLibConvertDeviceNodeToText ( 441 IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, 442 IN BOOLEAN DisplayOnly, 443 IN BOOLEAN AllowShortcuts 444 ); 445 446 /** 447 Convert text to the binary representation of a device node. 448 449 @param TextDeviceNode TextDeviceNode points to the text representation of a device 450 node. Conversion starts with the first character and continues 451 until the first non-device node character. 452 453 @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was 454 insufficient memory or text unsupported. 455 456 **/ 457 EFI_DEVICE_PATH_PROTOCOL * 458 EFIAPI 459 UefiDevicePathLibConvertTextToDeviceNode ( 460 IN CONST CHAR16 *TextDeviceNode 461 ); 462 463 /** 464 Convert text to the binary representation of a device path. 465 466 467 @param TextDevicePath TextDevicePath points to the text representation of a device 468 path. Conversion starts with the first character and continues 469 until the first non-device node character. 470 471 @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or 472 there was insufficient memory. 473 474 **/ 475 EFI_DEVICE_PATH_PROTOCOL * 476 EFIAPI 477 UefiDevicePathLibConvertTextToDevicePath ( 478 IN CONST CHAR16 *TextDevicePath 479 ); 480 #else 481 482 /* 483 * Small FreeBSD shim layer. Fast and lose hacks to make this code work with FreeBSD. 484 */ 485 486 #include <ctype.h> 487 488 #define _PCD_GET_MODE_32_PcdMaximumDevicePathNodeCount 1000 489 #define MAX_UINTN UINTPTR_MAX 490 491 #define AllocatePool(x) malloc(x) 492 #define AllocateZeroPool(x) calloc(1,x) 493 #define AsciiStrLen(s) strlen(s) 494 #define CopyGuid(dst, src) memcpy(dst, src, sizeof(uuid_t)) 495 #define CopyMem(d, s, l) memcpy(d, s, l) 496 #define FreePool(x) free(x) 497 #define LShiftU64(x, s) ((x) << s) 498 #define ReadUnaligned64(x) le64dec(x) 499 #define ReallocatePool(old, new, ptr) realloc(ptr, new) 500 /* 501 * Quirky StrCmp returns 0 if equal, 1 if not. This is what the code 502 * expects, though that expectation is likely a bug (it casts the 503 * return value. EDK2's StrCmp returns values just like C's strcmp, 504 * but the parse code casts this to an UINTN, which is bogus. This 505 * definition papers over that bogusness to do the right thing. If 506 * iSCSI protocol string processing is ever fixed, we can remove this 507 * bletcherous kludge. 508 */ 509 #define StrCmp(a, b) (strcmp(a, b) != 0) 510 #define StrCpyS(d, l, s) strcpy(d, s) 511 #define StrHexToUint64(x) strtoll(x, NULL, 16) 512 #define StrHexToUintn(x) strtoll(x, NULL, 16) 513 #define StrLen(x) strlen(x) 514 #define StrSize(x) (strlen(x) + 1) 515 #define StrnCatS(d, l, s, len) strncat(d, s, len) 516 #define StrnCmp(a, b, n) strncmp(a, b, n) 517 #define StrnLenS(str, max) strlen(str) 518 #define Strtoi(x) strtol(x, NULL, 0) 519 #define Strtoi64(x, y) *(long long *)y = strtoll(x, NULL, 0) 520 #define SwapBytes64(u64) bswap64(u64) 521 #define UnicodeStrToAsciiStrS(src, dest, len) strlcpy(dest, src, len) 522 #define ZeroMem(p,l) memset(p, 0, l) 523 524 #undef ASSERT 525 #define ASSERT(x) 526 527 /* 528 * Define AllocateCopyPool and others so that we "forget" about the 529 * previous non-static deifnition since we want these to be static 530 * inlines. 531 */ 532 #define AllocateCopyPool AllocateCopyPoolFreeBSD 533 #define CompareGuid CompareGuidFreeBSD 534 #define StrHexToBytes StrHexToBytesFreeBSD 535 #define StrToGuid StrToGuidFreeBSD 536 #define WriteUnaligned64 WriteUnaligned64FreeBSD 537 538 static inline void * 539 AllocateCopyPool(size_t l, const void *p) 540 { 541 void *rv; 542 543 rv = malloc(l); 544 if (rv == NULL) 545 return NULL; 546 memcpy(rv, p, l); 547 return (rv); 548 } 549 550 static inline BOOLEAN 551 CompareGuid (const EFI_GUID *g1, const EFI_GUID *g2) 552 { 553 uint32_t ignored_status; 554 555 return (uuid_compare((const uuid_t *)g1, (const uuid_t *)g2, 556 &ignored_status) == 0); 557 } 558 559 static inline int 560 StrHexToBytes(const char *str, size_t len, uint8_t *buf, size_t buflen) 561 { 562 size_t i; 563 char hex[3]; 564 565 /* 566 * Sanity check preconditions. 567 */ 568 if (buflen != len / 2 || (len % 2) == 1) 569 return 1; 570 for (i = 0; i < len; i += 2) { 571 if (!isxdigit(str[i]) || !isxdigit(str[i + 1])) 572 return 1; 573 hex[0] = str[i]; 574 hex[1] = str[i + 1]; 575 hex[2] = '\0'; 576 buf[i / 2] = strtol(hex, NULL, 16); 577 } 578 return 0; 579 } 580 581 static inline void 582 StrToGuid(const char *str, EFI_GUID *guid) 583 { 584 uint32_t status; 585 586 uuid_from_string(str, (uuid_t *)guid, &status); 587 } 588 589 static inline void 590 WriteUnaligned64(void *ptr, uint64_t val) 591 { 592 memcpy(ptr, &val, sizeof(val)); 593 } 594 595 /* 596 * Hack to allow converting %g to %s in printfs. Hack because 597 * it's single entry, uses a static buffer, etc. Sufficient for 598 * the day for this file though. IF you ever have to convert 599 * two %g's in one format, punt. Did I mention this was super lame. 600 * Not to mention it's name.... Also, the error GUID is horrific. 601 */ 602 static inline const char * 603 guid_str(const EFI_GUID *g) 604 { 605 static char buf[36 + 1]; 606 char *str = NULL; 607 int32_t ignored_status; 608 609 uuid_to_string((const uuid_t *)g, &str, &ignored_status); 610 if (str != NULL) 611 strlcpy(buf, str, sizeof(buf)); 612 else 613 strlcpy(buf, "groot-cannot-decode-guid-groot-smash", 614 sizeof(buf)); /* ^^^^^^^ 36 characters ^^^^^^^ */ 615 free(str); 616 return buf; 617 } 618 #define G(x) guid_str((const EFI_GUID *)(const void *)x) 619 #endif 620 621 #undef GLOBAL_REMOVE_IF_UNREFERENCED 622 #define GLOBAL_REMOVE_IF_UNREFERENCED static 623 624 #endif 625