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