OSDN Git Service

4f48c49f224beb2d6af74dc642b9b64087574328
[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
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)
91 {
92         ssize_t off = 0;
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));
98         }
99         return off;
100 }
101
102 #define format_hex(buf, size, off, dp_type, addr, len)                  \
103         format_helper(format_hex_helper, buf, size, off, dp_type, "", 0, \
104                       addr, len)
105
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, \
108                       addr, len)
109
110 static inline ssize_t
111 __attribute__((__unused__))
112 format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
113 {
114         ssize_t off = 0;
115         ssize_t bytes = efidp_node_size(dp)
116                         - sizeof (efidp_header)
117                         - sizeof (efi_guid_t);
118
119         format(buf, size, off, label, "%s(", label);
120         format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid);
121         if (bytes) {
122                 format(buf, size, off, label, ",");
123                 format_hex(buf, size, off, label, dp->hw_vendor.vendor_data,
124                            bytes);
125         }
126         format(buf, size, off, label, ")");
127         return off;
128 }
129
130 #define format_vendor(buf, size, off, label, dp)                \
131         format_helper(format_vendor_helper, buf, size, off, label, dp)
132
133 #define format_ucs2(buf, size, off, dp_type, str, len) ({               \
134                 uint16_t *_ucs2buf;                                     \
135                 uint32_t _ucs2size = sizeof(uint16_t) * len;            \
136                 _ucs2buf = alloca(_ucs2size);                           \
137                 if (_ucs2buf == NULL)                                   \
138                         return -1;                                      \
139                 memset(_ucs2buf, '\0', _ucs2size);                      \
140                 memcpy(_ucs2buf, str, _ucs2size - sizeof(uint16_t));    \
141                 unsigned char *_asciibuf;                               \
142                 _asciibuf = ucs2_to_utf8(_ucs2buf, (len) - 1);          \
143                 if (_asciibuf == NULL)                                  \
144                         return -1;                                      \
145                 _asciibuf = onstack(_asciibuf, (len));                  \
146                 format(buf, size, off, dp_type, "%s", _asciibuf);       \
147        })
148
149 #define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({  \
150                 for (size_t _i = 0; _i < len; _i++) {                   \
151                         if (_i != 0)                                    \
152                                 format(buf, size, off, dp_type, ",");   \
153                         format(buf, size, off, dp_type, fmt,            \
154                                ((type *)addr)[_i]);                     \
155                 }                                                       \
156                 off;                                                    \
157         })
158
159 extern ssize_t _format_hw_dn(char *buf, size_t size, const_efidp dp);
160 extern ssize_t _format_acpi_dn(char *buf, size_t size, const_efidp dp);
161 extern ssize_t _format_message_dn(char *buf, size_t size, const_efidp dp);
162 extern ssize_t _format_media_dn(char *buf, size_t size, const_efidp dp);
163 extern ssize_t _format_bios_boot_dn(char *buf, size_t size, const_efidp dp);
164
165 #define format_helper_2(name, buf, size, off, dp) ({                    \
166                 ssize_t _sz;                                            \
167                 _sz = name(((buf)+(off)),                               \
168                            ((size)?((size)-(off)):0),                   \
169                            (dp));                                       \
170                 if (_sz < 0) {                                          \
171                         efi_error("%s failed", #name);                  \
172                         return -1;                                      \
173                 }                                                       \
174                 (off) += _sz;                                           \
175         })
176
177 #define format_hw_dn(buf, size, off, dp) \
178         format_helper_2(_format_hw_dn, buf, size, off, dp)
179 #define format_acpi_dn(buf, size, off, dp) \
180         format_helper_2(_format_acpi_dn, buf, size, off, dp)
181 #define format_message_dn(buf, size, off, dp) \
182         format_helper_2(_format_message_dn, buf, size, off, dp)
183 #define format_media_dn(buf, size, off, dp) \
184         format_helper_2(_format_media_dn, buf, size, off, dp)
185 #define format_bios_boot_dn(buf, size, off, dp) \
186         format_helper_2(_format_bios_boot_dn, buf, size, off, dp)
187
188 #endif /* _EFIVAR_INTERNAL_DP_H */