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 <sys/ioctl.h>
29 #include <sys/statfs.h>
33 #include "talloc/talloc.h"
35 void efi_init_mount(struct efi_mount *efi_mount, const char *path,
40 efi_mount->path = path;
41 efi_mount->guid = guid;
43 pb_debug_fn("%s--%s", efi_mount->path, efi_mount->guid);
46 bool efi_check_mount_magic(const struct efi_mount *efi_mount, bool check_magic)
52 if (!efi_mount->guid) {
53 pb_debug_fn("guid not set\n");
57 if (access(efi_mount->path, R_OK | W_OK)) {
58 pb_debug_fn("Can't access %s\n", efi_mount->path);
62 memset(&s, '\0', sizeof(s));
63 if (statfs(efi_mount->path, &s)) {
64 pb_debug_fn("statfs failed: %s: (%d) %s\n", efi_mount->path,
65 errno, strerror(errno));
69 if (check_magic && s.f_type != EFIVARFS_MAGIC) {
70 pb_debug_fn("Bad magic = 0x%lx\n", (unsigned long)s.f_type);
77 static int efi_open(const struct efi_mount *efi_mount, const char *name,
78 int flags, mode_t mode, char **path)
86 if (!efi_mount->path || !efi_mount->guid)
89 *path = talloc_asprintf(NULL, "%s/%s-%s", efi_mount->path, name,
94 flags = flags ? flags : O_RDONLY | O_NONBLOCK;
96 fd = open(*path, flags, mode);
99 pb_log("%s: open failed '%s': (%d) %s\n", __func__, *path,
100 errno, strerror(errno));
109 int efi_del_variable(const struct efi_mount *efi_mount, const char *name)
117 fd = efi_open(efi_mount, name, 0, 0, &path);
121 rc = ioctl(fd, FS_IOC_GETFLAGS, &flag);
122 if (rc == -1 && errno == ENOTTY) {
123 pb_debug_fn("'%s' does not support ioctl_iflags.\n",
126 } else if (rc == -1) {
127 pb_log_fn("FS_IOC_GETFLAGS failed: (%d) %s\n", errno,
132 flag &= ~FS_IMMUTABLE_FL;
133 rc = ioctl(fd, FS_IOC_SETFLAGS, &flag);
135 pb_log_fn("FS_IOC_SETFLAGS failed: (%d) %s\n", errno,
145 pb_log_fn("unlink failed: (%d) %s\n", errno, strerror(errno));
148 pb_debug_fn("Deleted: '%s'\n", name);
155 int efi_get_variable(void *ctx, const struct efi_mount *efi_mount,
156 const char *name, struct efi_data **efi_data)
170 fd = efi_open(efi_mount, name, 0, 0, &path);
174 for (p = buf, total = 0; ; p = buf + count) {
175 count = read(fd, p, sizeof(buf) - total);
177 if (errno == EAGAIN || errno == EWOULDBLOCK)
180 pb_log("%s: read failed %s: (%ld) (%d) %s\n", __func__, path,
181 count, errno, strerror(errno));
184 if (p >= (buf + sizeof(buf))) {
185 pb_log("%s: buffer full %s: (%ld)\n", __func__, path,
194 *efi_data = (void*)talloc_zero_array(ctx, char,
195 sizeof (struct efi_data) + total);
197 (*efi_data)->attributes = *(uint32_t *)buf;
198 (*efi_data)->data_size = total;
199 (*efi_data)->data = (*efi_data)->fill;
200 memcpy((*efi_data)->data, buf + sizeof (uint32_t), total);
201 pb_debug_fn("Found: '%s'='%s'\n", name, (const char *)(*efi_data)->data);
210 int efi_set_variable(const struct efi_mount *efi_mount, const char *name,
211 const struct efi_data *efi_data)
222 efi_del_variable(efi_mount, name);
224 fd = efi_open(efi_mount, name, O_CREAT | O_WRONLY,
225 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &path);
229 bufsize = sizeof(uint32_t) + efi_data->data_size;
230 buf = talloc_size(path, bufsize);
234 *(uint32_t *)buf = efi_data->attributes;
235 memcpy(buf + sizeof(uint32_t), efi_data->data, efi_data->data_size);
237 count = write(fd, buf, bufsize);
238 if ((size_t)count != bufsize) {
239 pb_log("%s: write failed %s: (%ld) (%d) %s\n", __func__, name,
240 count, errno, strerror(errno));
244 pb_debug_fn("Set: '%s'='%s'\n", name, (const char *)efi_data->data);