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", \
87 static inline ssize_t UNUSED
88 format_hex_helper(char *buf, size_t size, const char *dp_type, char *separator,
89 int stride, const void * const addr, const size_t len)
92 for (size_t i = 0; i < len; i++) {
93 if (i && separator && stride > 0 && i % stride == 0)
94 format(buf, size, off, dp_type, "%s", separator);
95 format(buf, size, off, dp_type, "%02x",
96 *((const unsigned char * const )addr+i));
101 #define format_hex(buf, size, off, dp_type, addr, len) \
102 format_helper(format_hex_helper, buf, size, off, dp_type, "", 0, \
105 #define format_hex_separated(buf, size, off, dp_type, sep, stride, addr, len) \
106 format_helper(format_hex_helper, buf, size, off, dp_type, sep, stride, \
109 static inline ssize_t UNUSED
110 format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
113 ssize_t bytes = efidp_node_size(dp)
114 - sizeof (efidp_header)
115 - sizeof (efi_guid_t);
117 format(buf, size, off, label, "%s(", label);
118 format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid);
120 format(buf, size, off, label, ",");
121 format_hex(buf, size, off, label, dp->hw_vendor.vendor_data,
124 format(buf, size, off, label, ")");
128 #define format_vendor(buf, size, off, label, dp) \
129 format_helper(format_vendor_helper, buf, size, off, label, dp)
131 #define format_ucs2(buf, size, off, dp_type, str, len) ({ \
132 uint16_t *_ucs2buf; \
133 uint32_t _ucs2size = sizeof(uint16_t) * len; \
134 _ucs2buf = alloca(_ucs2size); \
135 if (_ucs2buf == NULL) \
137 memset(_ucs2buf, '\0', _ucs2size); \
138 memcpy(_ucs2buf, str, _ucs2size - sizeof(uint16_t)); \
139 unsigned char *_asciibuf; \
140 _asciibuf = ucs2_to_utf8(_ucs2buf, (len) - 1); \
141 if (_asciibuf == NULL) \
143 _asciibuf = onstack(_asciibuf, (len)); \
144 format(buf, size, off, dp_type, "%s", _asciibuf); \
147 #define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({ \
148 for (size_t _i = 0; _i < len; _i++) { \
150 format(buf, size, off, dp_type, ","); \
151 format(buf, size, off, dp_type, fmt, \
152 ((type *)addr)[_i]); \
157 extern ssize_t _format_hw_dn(char *buf, size_t size, const_efidp dp);
158 extern ssize_t _format_acpi_dn(char *buf, size_t size, const_efidp dp);
159 extern ssize_t _format_message_dn(char *buf, size_t size, const_efidp dp);
160 extern ssize_t _format_media_dn(char *buf, size_t size, const_efidp dp);
161 extern ssize_t _format_bios_boot_dn(char *buf, size_t size, const_efidp dp);
163 #define format_helper_2(name, buf, size, off, dp) ({ \
165 _sz = name(((buf)+(off)), \
166 ((size)?((size)-(off)):0), \
169 efi_error("%s failed", #name); \
175 #define format_hw_dn(buf, size, off, dp) \
176 format_helper_2(_format_hw_dn, buf, size, off, dp)
177 #define format_acpi_dn(buf, size, off, dp) \
178 format_helper_2(_format_acpi_dn, buf, size, off, dp)
179 #define format_message_dn(buf, size, off, dp) \
180 format_helper_2(_format_message_dn, buf, size, off, dp)
181 #define format_media_dn(buf, size, off, dp) \
182 format_helper_2(_format_media_dn, buf, size, off, dp)
183 #define format_bios_boot_dn(buf, size, off, dp) \
184 format_helper_2(_format_bios_boot_dn, buf, size, off, dp)
186 #endif /* _EFIVAR_INTERNAL_DP_H */