2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 * Copyright (C) 2018 Huaxintong Semiconductor Technology Co.,Ltd. All rights
17 * Author: Ge Song <ge.song@hxt-semitech.com>
27 #include <linux/magic.h>
28 #include <sys/ioctl.h>
30 #include <sys/statfs.h>
34 #include "talloc/talloc.h"
36 #ifndef EFIVARFS_MAGIC
37 #define EFIVARFS_MAGIC 0xde5e81e4
40 void efi_init_mount(struct efi_mount *efi_mount, const char *path,
45 efi_mount->path = path;
46 efi_mount->guid = guid;
48 pb_debug_fn("%s--%s", efi_mount->path, efi_mount->guid);
51 bool efi_check_mount_magic(const struct efi_mount *efi_mount, bool check_magic)
57 if (!efi_mount->guid) {
58 pb_debug_fn("guid not set\n");
62 if (access(efi_mount->path, R_OK | W_OK)) {
63 pb_debug_fn("Can't access %s\n", efi_mount->path);
67 memset(&s, '\0', sizeof(s));
68 if (statfs(efi_mount->path, &s)) {
69 pb_debug_fn("statfs failed: %s: (%d) %s\n", efi_mount->path,
70 errno, strerror(errno));
74 if (check_magic && s.f_type != EFIVARFS_MAGIC) {
75 pb_debug_fn("Bad magic = 0x%lx\n", (unsigned long)s.f_type);
82 static int efi_open(const struct efi_mount *efi_mount, const char *name,
83 int flags, mode_t mode, char **path)
91 if (!efi_mount->path || !efi_mount->guid)
94 *path = talloc_asprintf(NULL, "%s/%s-%s", efi_mount->path, name,
99 flags = flags ? flags : O_RDONLY | O_NONBLOCK;
101 fd = open(*path, flags, mode);
104 pb_log("%s: open failed '%s': (%d) %s\n", __func__, *path,
105 errno, strerror(errno));
114 int efi_del_variable(const struct efi_mount *efi_mount, const char *name)
122 fd = efi_open(efi_mount, name, 0, 0, &path);
126 rc = ioctl(fd, FS_IOC_GETFLAGS, &flag);
127 if (rc == -1 && errno == ENOTTY) {
128 pb_debug_fn("'%s' does not support ioctl_iflags.\n",
131 } else if (rc == -1) {
132 pb_log_fn("FS_IOC_GETFLAGS failed: (%d) %s\n", errno,
137 flag &= ~FS_IMMUTABLE_FL;
138 rc = ioctl(fd, FS_IOC_SETFLAGS, &flag);
140 pb_log_fn("FS_IOC_SETFLAGS failed: (%d) %s\n", errno,
150 pb_log_fn("unlink failed: (%d) %s\n", errno, strerror(errno));
153 pb_debug_fn("Deleted: '%s'\n", name);
160 int efi_get_variable(void *ctx, const struct efi_mount *efi_mount,
161 const char *name, struct efi_data **efi_data)
175 fd = efi_open(efi_mount, name, 0, 0, &path);
179 for (p = buf, total = 0; ; p = buf + count) {
180 count = read(fd, p, sizeof(buf) - total);
182 if (errno == EAGAIN || errno == EWOULDBLOCK)
185 pb_log("%s: read failed %s: (%ld) (%d) %s\n", __func__, path,
186 count, errno, strerror(errno));
189 if (p >= (buf + sizeof(buf))) {
190 pb_log("%s: buffer full %s: (%ld)\n", __func__, path,
199 *efi_data = (void*)talloc_zero_array(ctx, char,
200 sizeof (struct efi_data) + total);
202 (*efi_data)->attributes = *(uint32_t *)buf;
203 (*efi_data)->data_size = total;
204 (*efi_data)->data = (*efi_data)->fill;
205 memcpy((*efi_data)->data, buf + sizeof (uint32_t), total);
206 pb_debug_fn("Found: '%s'='%s'\n", name, (const char *)(*efi_data)->data);
215 int efi_set_variable(const struct efi_mount *efi_mount, const char *name,
216 const struct efi_data *efi_data)
227 efi_del_variable(efi_mount, name);
229 fd = efi_open(efi_mount, name, O_CREAT | O_WRONLY,
230 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &path);
234 bufsize = sizeof(uint32_t) + efi_data->data_size;
235 buf = talloc_size(path, bufsize);
239 *(uint32_t *)buf = efi_data->attributes;
240 memcpy(buf + sizeof(uint32_t), efi_data->data, efi_data->data_size);
242 count = write(fd, buf, bufsize);
243 if ((size_t)count != bufsize) {
244 pb_log("%s: write failed %s: (%ld) (%d) %s\n", __func__, name,
245 count, errno, strerror(errno));
249 pb_debug_fn("Set: '%s'='%s'\n", name, (const char *)efi_data->data);