OSDN Git Service

Update abixml for newer libabigail
[android-x86/external-efivar.git] / src / dp.h
1 /*
2  * libefivar - library for the manipulation of EFI variables
3  * Copyright 2012-2015 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
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/>.
18  *
19  */
20 #ifndef _EFIVAR_INTERNAL_DP_H
21 #define _EFIVAR_INTERNAL_DP_H
22
23 #include <alloca.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "ucs2.h"
29
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);                       \
36                 }                                                       \
37                 if ((off) >= 0 &&                                       \
38                     ((buf == NULL && _insize == 0) ||                   \
39                      (buf != NULL && _insize >= 0))) {                  \
40                         ssize_t _x = 0;                                 \
41                         _x = snprintf(_inbuf, _insize, fmt, ## args);   \
42                         if (_x < 0) {                                   \
43                                 efi_error(                              \
44                                         "could not build %s DP string", \
45                                         (dp_type));                     \
46                                 return _x;                              \
47                         }                                               \
48                         (off) += _x;                                    \
49                 }                                                       \
50                 off;                                                    \
51         })
52
53 #define format_helper(fn, buf, size, off, dp_type, args...) ({          \
54                 ssize_t _x;                                             \
55                 _x = (fn)(((buf)+(off)),                                \
56                           ((size)?((size)-(off)):0), dp_type, ## args); \
57                 if (_x < 0)                                             \
58                         efi_error("could not build %s DP string",       \
59                                   dp_type);                             \
60                 (off) += _x;                                            \
61         })
62
63 #define onstack(buf, len) ({                                            \
64                 char *__newbuf = alloca(len);                           \
65                 memcpy(__newbuf, buf, len);                             \
66                 free(buf);                                              \
67                 (void *)__newbuf;                                       \
68         })
69
70 #define format_guid(buf, size, off, dp_type, guid) ({                   \
71                 int _rc;                                                \
72                 char *_guidstr = NULL;                                  \
73                                                                         \
74                 _rc = efi_guid_to_str(guid, &_guidstr);                 \
75                 if (_rc < 0) {                                          \
76                         efi_error("could not build %s GUID DP string",  \
77                                   dp_type);                             \
78                 } else {                                                \
79                         _guidstr = onstack(_guidstr,                    \
80                                            strlen(_guidstr)+1);         \
81                         _rc = format(buf, size, off, dp_type, "%s",     \
82                                      _guidstr); \
83                 }                                                       \
84                 _rc;                                                    \
85         })
86
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)
90 {
91         ssize_t off = 0;
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));
97         }
98         return off;
99 }
100
101 #define format_hex(buf, size, off, dp_type, addr, len)                  \
102         format_helper(format_hex_helper, buf, size, off, dp_type, "", 0, \
103                       addr, len)
104
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, \
107                       addr, len)
108
109 static inline ssize_t UNUSED
110 format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
111 {
112         ssize_t off = 0;
113         ssize_t bytes = efidp_node_size(dp)
114                         - sizeof (efidp_header)
115                         - sizeof (efi_guid_t);
116
117         format(buf, size, off, label, "%s(", label);
118         format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid);
119         if (bytes) {
120                 format(buf, size, off, label, ",");
121                 format_hex(buf, size, off, label, dp->hw_vendor.vendor_data,
122                            bytes);
123         }
124         format(buf, size, off, label, ")");
125         return off;
126 }
127
128 #define format_vendor(buf, size, off, label, dp)                \
129         format_helper(format_vendor_helper, buf, size, off, label, dp)
130
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)                                   \
136                         return -1;                                      \
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)                                  \
142                         return -1;                                      \
143                 _asciibuf = onstack(_asciibuf, (len));                  \
144                 format(buf, size, off, dp_type, "%s", _asciibuf);       \
145        })
146
147 #define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({  \
148                 for (size_t _i = 0; _i < len; _i++) {                   \
149                         if (_i != 0)                                    \
150                                 format(buf, size, off, dp_type, ",");   \
151                         format(buf, size, off, dp_type, fmt,            \
152                                ((type *)addr)[_i]);                     \
153                 }                                                       \
154                 off;                                                    \
155         })
156
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);
162
163 #define format_helper_2(name, buf, size, off, dp) ({                    \
164                 ssize_t _sz;                                            \
165                 _sz = name(((buf)+(off)),                               \
166                            ((size)?((size)-(off)):0),                   \
167                            (dp));                                       \
168                 if (_sz < 0) {                                          \
169                         efi_error("%s failed", #name);                  \
170                         return -1;                                      \
171                 }                                                       \
172                 (off) += _sz;                                           \
173         })
174
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)
185
186 #endif /* _EFIVAR_INTERNAL_DP_H */