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>
26 #include <sys/ioctl.h>
31 #include "talloc/talloc.h"
33 static const char *efivarfs_path;
35 inline void set_efivarfs_path(const char *path)
40 inline const char *get_efivarfs_path(void)
46 static int efi_open(const char *name, const char *guidstr, int flags,
47 mode_t mode, char **path)
53 if (!get_efivarfs_path())
56 *path = talloc_asprintf(NULL, "%s%s-%s", get_efivarfs_path(), name, guidstr);
60 flags = flags ? flags : O_RDONLY | O_NONBLOCK;
62 fd = open(*path, flags, mode);
65 pb_log("%s: open failed %s: %s\n", __func__, *path,
75 int efi_del_variable(const char *guidstr, const char *name)
81 fd = efi_open(name, guidstr, 0, 0, &path);
85 rc = ioctl(fd, FS_IOC_GETFLAGS, &flag);
89 flag &= ~FS_IMMUTABLE_FL;
90 rc = ioctl(fd, FS_IOC_SETFLAGS, &flag);
103 int efi_get_variable(void *ctx, const char *guidstr, const char *name,
104 struct efi_data **efi_data)
116 fd = efi_open(name, guidstr, 0, 0, &path);
120 for (p = buf, total = 0; ; p = buf + count) {
121 count = read(fd, p, sizeof(buf) - total);
123 if (errno == EAGAIN || errno == EWOULDBLOCK)
126 pb_log("%s: read failed %s: (%ld) %s\n", __func__, path,
127 count, strerror(errno));
130 if (p >= (buf + sizeof(buf))) {
131 pb_log("%s: buffer full %s: (%ld)\n", __func__, path,
140 *efi_data = (void*)talloc_zero_array(ctx, char,
141 sizeof (struct efi_data) + total);
143 (*efi_data)->attributes = *(uint32_t *)buf;
144 (*efi_data)->data_size = total;
145 (*efi_data)->data = (*efi_data)->fill;
146 memcpy((*efi_data)->data, buf + sizeof (uint32_t), total);
155 int efi_set_variable(const char *guidstr, const char *name,
156 const struct efi_data *efi_data)
165 efi_del_variable(guidstr, name);
167 fd = efi_open(name, guidstr, O_CREAT | O_WRONLY,
168 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &path);
172 bufsize = sizeof(uint32_t) + efi_data->data_size;
173 buf = talloc_size(path, bufsize);
177 *(uint32_t *)buf = efi_data->attributes;
178 memcpy(buf + sizeof(uint32_t), efi_data->data, efi_data->data_size);
180 count = write(fd, buf, bufsize);
181 if ((size_t)count != bufsize) {
182 pb_log("%s: write failed %s: (%ld) %s\n", __func__, name,
183 count, strerror(errno));