OSDN Git Service

linux-pci-root: remove an unused assignment
[android-x86/external-efivar.git] / src / lib.c
1 /*
2  * libefivar - library for the manipulation of EFI variables
3  * Copyright 2012-2013 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
21 #include "fix_coverity.h"
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include "efivar.h"
32
33 static int default_probe(void)
34 {
35         return 1;
36 }
37
38 struct efi_var_operations default_ops = {
39                 .name = "default",
40                 .probe = default_probe,
41         };
42
43 struct efi_var_operations *ops = NULL;
44
45 int NONNULL(2, 3) PUBLIC
46 _efi_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
47                   size_t data_size, uint32_t attributes)
48 {
49         int rc;
50         rc = ops->set_variable(guid, name, data, data_size, attributes, 0600);
51         if (rc < 0)
52                 efi_error("ops->set_variable() failed");
53         return rc;
54 }
55 VERSION(_efi_set_variable, _efi_set_variable@libefivar.so.0);
56
57 int NONNULL(2, 3) PUBLIC
58 _efi_set_variable_variadic(efi_guid_t guid, const char *name, uint8_t *data,
59                            size_t data_size, uint32_t attributes, ...)
60 {
61         int rc;
62         rc = ops->set_variable(guid, name, data, data_size, attributes, 0600);
63         if (rc < 0)
64                 efi_error("ops->set_variable() failed");
65         return rc;
66 }
67 VERSION(_efi_set_variable_variadic, efi_set_variable@libefivar.so.0);
68
69 int NONNULL(2, 3) PUBLIC
70 _efi_set_variable_mode(efi_guid_t guid, const char *name, uint8_t *data,
71                        size_t data_size, uint32_t attributes, mode_t mode)
72 {
73         int rc;
74         rc = ops->set_variable(guid, name, data, data_size, attributes, mode);
75         if (rc < 0)
76                 efi_error("ops->set_variable() failed");
77         else
78                 efi_error_clear();
79         return rc;
80 }
81 VERSION(_efi_set_variable_mode,efi_set_variable@@LIBEFIVAR_0.24);
82
83 int NONNULL(2, 3) PUBLIC
84 efi_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
85                  size_t data_size, uint32_t attributes, mode_t mode)
86         ALIAS(_efi_set_variable_mode);
87
88 int NONNULL(2, 3) PUBLIC
89 efi_append_variable(efi_guid_t guid, const char *name, uint8_t *data,
90                         size_t data_size, uint32_t attributes)
91 {
92         int rc;
93         if (!ops->append_variable) {
94                 rc = generic_append_variable(guid, name, data, data_size,
95                                              attributes);
96                 if (rc < 0)
97                         efi_error("generic_append_variable() failed");
98                 else
99                         efi_error_clear();
100                 return rc;
101         }
102         rc = ops->append_variable(guid, name, data, data_size, attributes);
103         if (rc < 0)
104                 efi_error("ops->append_variable() failed");
105         else
106                 efi_error_clear();
107         return rc;
108 }
109
110 int NONNULL(2) PUBLIC
111 efi_del_variable(efi_guid_t guid, const char *name)
112 {
113         int rc;
114         if (!ops->del_variable) {
115                 efi_error("del_variable() is not implemented");
116                 errno = ENOSYS;
117                 return -1;
118         }
119         rc = ops->del_variable(guid, name);
120         if (rc < 0)
121                 efi_error("ops->del_variable() failed");
122         else
123                 efi_error_clear();
124         return rc;
125 }
126
127 int NONNULL(2, 3, 4, 5) PUBLIC
128 efi_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
129                   size_t *data_size, uint32_t *attributes)
130 {
131         int rc;
132         if (!ops->get_variable) {
133                 efi_error("get_variable() is not implemented");
134                 errno = ENOSYS;
135                 return -1;
136         }
137         rc = ops->get_variable(guid, name, data, data_size, attributes);
138         if (rc < 0)
139                 efi_error("ops->get_variable failed");
140         else
141                 efi_error_clear();
142         return rc;
143 }
144
145 int NONNULL(2, 3) PUBLIC
146 efi_get_variable_attributes(efi_guid_t guid, const char *name,
147                             uint32_t *attributes)
148 {
149         int rc;
150         if (!ops->get_variable_attributes) {
151                 efi_error("get_variable_attributes() is not implemented");
152                 errno = ENOSYS;
153                 return -1;
154         }
155         rc = ops->get_variable_attributes(guid, name, attributes);
156         if (rc < 0)
157                 efi_error("ops->get_variable_attributes() failed");
158         else
159                 efi_error_clear();
160         return rc;
161 }
162
163 int NONNULL(2) PUBLIC
164 efi_get_variable_exists(efi_guid_t guid, const char *name)
165 {
166         uint32_t unused_attributes = 0;
167         return efi_get_variable_attributes(guid, name, &unused_attributes);
168 }
169
170 int NONNULL(2, 3) PUBLIC
171 efi_get_variable_size(efi_guid_t guid, const char *name, size_t *size)
172 {
173         int rc;
174         if (!ops->get_variable_size) {
175                 efi_error("get_variable_size() is not implemented");
176                 errno = ENOSYS;
177                 return -1;
178         }
179         rc = ops->get_variable_size(guid, name, size);
180         if (rc < 0)
181                 efi_error("ops->get_variable_size() failed");
182         else
183                 efi_error_clear();
184         return rc;
185 }
186
187 int NONNULL(1, 2) PUBLIC
188 efi_get_next_variable_name(efi_guid_t **guid, char **name)
189 {
190         int rc;
191         if (!ops->get_next_variable_name) {
192                 efi_error("get_next_variable_name() is not implemented");
193                 errno = ENOSYS;
194                 return -1;
195         }
196         rc = ops->get_next_variable_name(guid, name);
197         if (rc < 0)
198                 efi_error("ops->get_next_variable_name() failed");
199         else
200                 efi_error_clear();
201         return rc;
202 }
203
204 int NONNULL(2) PUBLIC
205 efi_chmod_variable(efi_guid_t guid, const char *name, mode_t mode)
206 {
207         int rc;
208         if (!ops->chmod_variable) {
209                 efi_error("chmod_variable() is not implemented");
210                 errno = ENOSYS;
211                 return -1;
212         }
213         rc = ops->chmod_variable(guid, name, mode);
214         if (rc < 0)
215                 efi_error("ops->chmod_variable() failed");
216         else
217                 efi_error_clear();
218         return rc;
219 }
220
221 int PUBLIC
222 efi_variables_supported(void)
223 {
224         if (ops == &default_ops)
225                 return 0;
226         return 1;
227 }
228
229 static void CONSTRUCTOR libefivar_init(void);
230
231 static void CONSTRUCTOR
232 libefivar_init(void)
233 {
234         struct efi_var_operations *ops_list[] = {
235                 &efivarfs_ops,
236                 &vars_ops,
237                 &default_ops,
238                 NULL
239         };
240         char *ops_name = getenv("LIBEFIVAR_OPS");
241         if (ops_name && strcasestr(ops_name, "help")) {
242                 printf("LIBEFIVAR_OPS operations available:\n");
243                 for (int i = 0; ops_list[i] != NULL; i++)
244                         printf("\t%s\n", ops_list[i]->name);
245                 exit(0);
246         }
247
248         for (int i = 0; ops_list[i] != NULL; i++)
249         {
250                 if (ops_name != NULL) {
251                         if (!strcmp(ops_list[i]->name, ops_name) ||
252                                         !strcmp(ops_list[i]->name, "default")) {
253                                 ops = ops_list[i];
254                                 break;
255                         }
256                 } else {
257                         int rc = ops_list[i]->probe();
258                         if (rc <= 0) {
259                                 efi_error("ops_list[%d]->probe() failed", i);
260                         } else {
261                                 efi_error_clear();
262                                 ops = ops_list[i];
263                                 break;
264                         }
265                 }
266         }
267 }