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