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