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