xref: /freebsd/lib/libefivar/uefi-dplib.h (revision 47606b869eb149ebb7135d6594c3b9b9f05b9aed)
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$
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 
37 Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
38 This program and the accompanying materials
39 are licensed and made available under the terms and conditions of the BSD License
40 which accompanies this distribution.  The full text of the license may be found at
41 http://opensource.org/licenses/bsd-license.php
42 
43 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
44 WITHOUT 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 //
78 typedef struct {
79   char  *Str;
80   UINTN   Count;
81   UINTN   Capacity;
82 } POOL_PRINT;
83 
84 typedef
85 EFI_DEVICE_PATH_PROTOCOL  *
86 (*DEVICE_PATH_FROM_TEXT) (
87   IN char *Str
88   );
89 
90 typedef
91 VOID
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 
99 typedef struct {
100   UINT8                Type;
101   UINT8                SubType;
102   DEVICE_PATH_TO_TEXT  Function;
103 } DEVICE_PATH_TO_TEXT_TABLE;
104 
105 typedef struct {
106   UINT8                Type;
107   const char          *Text;
108 } DEVICE_PATH_TO_TEXT_GENERIC_TABLE;
109 
110 typedef struct {
111   const char                *DevicePathNodeText;
112   DEVICE_PATH_FROM_TEXT     Function;
113 } DEVICE_PATH_FROM_TEXT_TABLE;
114 
115 typedef 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 
145 typedef struct {
146   EFI_DEVICE_PATH_PROTOCOL  Header;
147   EFI_GUID                  Guid;
148   UINT8                     VendorDefinedData[1];
149 } VENDOR_DEFINED_HARDWARE_DEVICE_PATH;
150 
151 typedef struct {
152   EFI_DEVICE_PATH_PROTOCOL  Header;
153   EFI_GUID                  Guid;
154   UINT8                     VendorDefinedData[1];
155 } VENDOR_DEFINED_MESSAGING_DEVICE_PATH;
156 
157 typedef struct {
158   EFI_DEVICE_PATH_PROTOCOL  Header;
159   EFI_GUID                  Guid;
160   UINT8                     VendorDefinedData[1];
161 } VENDOR_DEFINED_MEDIA_DEVICE_PATH;
162 
163 typedef 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 
171 typedef 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 
180 typedef 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 **/
203 UINTN
204 EFIAPI
205 UefiDevicePathLibGetDevicePathSize (
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 **/
225 EFI_DEVICE_PATH_PROTOCOL *
226 EFIAPI
227 UefiDevicePathLibDuplicateDevicePath (
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 **/
255 EFI_DEVICE_PATH_PROTOCOL *
256 EFIAPI
257 UefiDevicePathLibAppendDevicePath (
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 **/
290 EFI_DEVICE_PATH_PROTOCOL *
291 EFIAPI
292 UefiDevicePathLibAppendDevicePathNode (
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 **/
320 EFI_DEVICE_PATH_PROTOCOL *
321 EFIAPI
322 UefiDevicePathLibAppendDevicePathInstance (
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 **/
355 EFI_DEVICE_PATH_PROTOCOL *
356 EFIAPI
357 UefiDevicePathLibGetNextDevicePathInstance (
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 **/
381 EFI_DEVICE_PATH_PROTOCOL *
382 EFIAPI
383 UefiDevicePathLibCreateDeviceNode (
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 **/
404 BOOLEAN
405 EFIAPI
406 UefiDevicePathLibIsDevicePathMultiInstance (
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 **/
426 CHAR16 *
427 EFIAPI
428 UefiDevicePathLibConvertDevicePathToText (
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 **/
449 CHAR16 *
450 EFIAPI
451 UefiDevicePathLibConvertDeviceNodeToText (
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 **/
468 EFI_DEVICE_PATH_PROTOCOL *
469 EFIAPI
470 UefiDevicePathLibConvertTextToDeviceNode (
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 **/
486 EFI_DEVICE_PATH_PROTOCOL *
487 EFIAPI
488 UefiDevicePathLibConvertTextToDevicePath (
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 
549 static inline void *
550 AllocateCopyPool(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 
561 static inline BOOLEAN
562 CompareGuid (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 
570 static inline int
571 StrHexToBytes(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 
592 static inline void
593 StrToGuid(const char *str, GUID *guid)
594 {
595 	uint32_t status;
596 
597 	uuid_from_string(str, (uuid_t *)guid, &status);
598 }
599 
600 static inline void
601 WriteUnaligned64(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  */
613 static inline const char *
614 guid_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