2 * libefivar - library for the manipulation of EFI variables
3 * Copyright 2012-2015 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
20 #ifndef _EFIVAR_INTERNAL_DP_H
21 #define _EFIVAR_INTERNAL_DP_H
30 #define format(buf, size, off, dp_type, fmt, args...) ({ \
31 ssize_t _insize = 0; \
32 void *_inbuf = NULL; \
33 if ((buf) != NULL && (size) > 0) { \
34 _inbuf = (buf) + (off); \
35 _insize = (size) - (off); \
38 ((buf == NULL && _insize == 0) || \
39 (buf != NULL && _insize >= 0))) { \
41 _x = snprintf(_inbuf, _insize, fmt, ## args); \
44 "could not build %s DP string", \
53 #define format_helper(fn, buf, size, off, dp_type, args...) ({ \
55 _x = (fn)(((buf)+(off)), \
56 ((size)?((size)-(off)):0), dp_type, ## args); \
58 efi_error("could not build %s DP string", \
63 #define onstack(buf, len) ({ \
64 char *__newbuf = alloca(len); \
65 memcpy(__newbuf, buf, len); \
70 #define format_guid(buf, size, off, dp_type, guid) ({ \
72 char *_guidstr = NULL; \
74 _rc = efi_guid_to_str(guid, &_guidstr); \
76 efi_error("could not build %s GUID DP string", \
79 _guidstr = onstack(_guidstr, \
80 strlen(_guidstr)+1); \
81 _rc = format(buf, size, off, dp_type, "%s", \
88 __attribute__((__unused__))
89 format_hex_helper(char *buf, size_t size, const char *dp_type, char *separator,
90 int stride, const void * const addr, const size_t len)
93 for (size_t i = 0; i < len; i++) {
94 if (i && separator && stride > 0 && i % stride == 0)
95 format(buf, size, off, dp_type, "%s", separator);
96 format(buf, size, off, dp_type, "%02x",
97 *((const unsigned char * const )addr+i));
102 #define format_hex(buf, size, off, dp_type, addr, len) \
103 format_helper(format_hex_helper, buf, size, off, dp_type, "", 0, \
106 #define format_hex_separated(buf, size, off, dp_type, sep, stride, addr, len) \
107 format_helper(format_hex_helper, buf, size, off, dp_type, sep, stride, \
110 static inline ssize_t
111 __attribute__((__unused__))
112 format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
115 ssize_t bytes = efidp_node_size(dp)
116 - sizeof (efidp_header)
117 - sizeof (efi_guid_t);
119 format(buf, size, off, label, "%s(", label);
120 format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid);
122 format(buf, size, off, label, ",");
123 format_hex(buf, size, off, label, dp->hw_vendor.vendor_data,
126 format(buf, size, off, label, ")");
130 #define format_vendor(buf, size, off, label, dp) \
131 format_helper(format_vendor_helper, buf, size, off, label, dp)
133 #define format_ucs2(buf, size, off, dp_type, str, len) ({ \
134 uint16_t _ucs2buf[(len)]; \
135 memset(_ucs2buf, '\0', sizeof (_ucs2buf)); \
136 memcpy(_ucs2buf, str, sizeof (_ucs2buf) \
137 - sizeof (_ucs2buf[0])); \
138 unsigned char *_asciibuf; \
139 _asciibuf = ucs2_to_utf8(_ucs2buf, (len) - 1); \
140 if (_asciibuf == NULL) \
142 _asciibuf = onstack(_asciibuf, (len)); \
143 format(buf, size, off, dp_type, "%s", _asciibuf); \
146 #define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({ \
147 for (size_t _i = 0; _i < len; _i++) { \
149 format(buf, size, off, dp_type, ","); \
150 format(buf, size, off, dp_type, fmt, \
151 ((type *)addr)[_i]); \
156 extern ssize_t _format_hw_dn(char *buf, size_t size, const_efidp dp);
157 extern ssize_t _format_acpi_dn(char *buf, size_t size, const_efidp dp);
158 extern ssize_t _format_message_dn(char *buf, size_t size, const_efidp dp);
159 extern ssize_t _format_media_dn(char *buf, size_t size, const_efidp dp);
160 extern ssize_t _format_bios_boot_dn(char *buf, size_t size, const_efidp dp);
162 #define format_helper_2(name, buf, size, off, dp) ({ \
164 _sz = name(((buf)+(off)), \
165 ((size)?((size)-(off)):0), \
168 efi_error("%s failed", #name); \
174 #define format_hw_dn(buf, size, off, dp) \
175 format_helper_2(_format_hw_dn, buf, size, off, dp)
176 #define format_acpi_dn(buf, size, off, dp) \
177 format_helper_2(_format_acpi_dn, buf, size, off, dp)
178 #define format_message_dn(buf, size, off, dp) \
179 format_helper_2(_format_message_dn, buf, size, off, dp)
180 #define format_media_dn(buf, size, off, dp) \
181 format_helper_2(_format_media_dn, buf, size, off, dp)
182 #define format_bios_boot_dn(buf, size, off, dp) \
183 format_helper_2(_format_bios_boot_dn, buf, size, off, dp)
185 #endif /* _EFIVAR_INTERNAL_DP_H */