You need to sign in or sign up before continuing.
efivars.c 52.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
/*
 * EFI Variables - efivars.c
 *
 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
 *
 * This code takes all variables accessible from EFI runtime and
 *  exports them via sysfs
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Changelog:
 *
 *  17 May 2004 - Matt Domsch <Matt_Domsch@dell.com>
 *   remove check for efi_enabled in exit
 *   add MODULE_VERSION
 *
 *  26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com>
 *   minor bug fixes
 *
 *  21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com)
 *   converted driver to export variable information via sysfs
 *   and moved to drivers/firmware directory
 *   bumped revision number to v0.07 to reflect conversion & move
 *
 *  10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
 *   fix locking per Peter Chubb's findings
 *
 *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
 *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
 *
 *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
 *   use list_for_each_safe when deleting vars.
 *   remove ifdef CONFIG_SMP around include <linux/smp.h>
 *   v0.04 release to linux-ia64@linuxia64.org
 *
 *  20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
 *   Moved vars from /proc/efi to /proc/efi/vars, and made
 *   efi.c own the /proc/efi directory.
 *   v0.03 release to linux-ia64@linuxia64.org
 *
 *  26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
 *   At the request of Stephane, moved ownership of /proc/efi
 *   to efi.c, and now efivars lives under /proc/efi/vars.
 *
 *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
 *   Feedback received from Stephane Eranian incorporated.
 *   efivar_write() checks copy_from_user() return value.
 *   efivar_read/write() returns proper errno.
 *   v0.02 release to linux-ia64@linuxia64.org
 *
 *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
 *   v0.01 release to linux-ia64@linuxia64.org
 */

68
#include <linux/capability.h>
L
Linus Torvalds 已提交
69 70 71 72 73 74 75 76 77 78 79
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/smp.h>
#include <linux/efi.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <linux/device.h>
80
#include <linux/slab.h>
81
#include <linux/pstore.h>
82
#include <linux/ctype.h>
83
#include <linux/ucs2_string.h>
L
Linus Torvalds 已提交
84

85 86 87 88
#include <linux/fs.h>
#include <linux/ramfs.h>
#include <linux/pagemap.h>

L
Linus Torvalds 已提交
89 90 91 92 93 94 95 96 97 98
#include <asm/uaccess.h>

#define EFIVARS_VERSION "0.08"
#define EFIVARS_DATE "2004-May-17"

MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
MODULE_DESCRIPTION("sysfs interface to EFI Variables");
MODULE_LICENSE("GPL");
MODULE_VERSION(EFIVARS_VERSION);

99 100
#define DUMP_NAME_LEN 52

101 102 103 104 105
/*
 * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
 * not including trailing NUL
 */
#define GUID_LEN 36
106

107
static bool efivars_pstore_disable =
108
	IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
109 110 111

module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);

L
Linus Torvalds 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
/*
 * The maximum size of VariableName + Data = 1024
 * Therefore, it's reasonable to save that much
 * space in each part of the structure,
 * and we use a page for reading/writing.
 */

struct efi_variable {
	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
	efi_guid_t    VendorGuid;
	unsigned long DataSize;
	__u8          Data[1024];
	efi_status_t  Status;
	__u32         Attributes;
} __attribute__((packed));

struct efivar_entry {
M
Mike Waychison 已提交
129
	struct efivars *efivars;
L
Linus Torvalds 已提交
130 131 132 133 134 135 136 137 138 139 140
	struct efi_variable var;
	struct list_head list;
	struct kobject kobj;
};

struct efivar_attribute {
	struct attribute attr;
	ssize_t (*show) (struct efivar_entry *entry, char *buf);
	ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
};

141 142 143
static struct efivars __efivars;
static struct efivar_operations ops;

144 145 146 147
#define PSTORE_EFI_ATTRIBUTES \
	(EFI_VARIABLE_NON_VOLATILE | \
	 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
	 EFI_VARIABLE_RUNTIME_ACCESS)
L
Linus Torvalds 已提交
148 149 150

#define EFIVAR_ATTR(_name, _mode, _show, _store) \
struct efivar_attribute efivar_attr_##_name = { \
151
	.attr = {.name = __stringify(_name), .mode = _mode}, \
L
Linus Torvalds 已提交
152 153 154 155 156 157 158 159 160 161 162
	.show = _show, \
	.store = _store, \
};

#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
#define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)

/*
 * Prototype for sysfs creation function
 */
static int
M
Mike Waychison 已提交
163 164 165 166
efivar_create_sysfs_entry(struct efivars *efivars,
			  unsigned long variable_name_size,
			  efi_char16_t *variable_name,
			  efi_guid_t *vendor_guid);
L
Linus Torvalds 已提交
167

168 169 170 171 172 173
/*
 * Prototype for workqueue functions updating sysfs entry
 */

static void efivar_update_sysfs_entries(struct work_struct *);
static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
174
static bool efivar_wq_enabled = true;
175

176
static bool
177 178
validate_device_path(struct efi_variable *var, int match, u8 *buffer,
		     unsigned long len)
179 180 181 182 183 184
{
	struct efi_generic_dev_path *node;
	int offset = 0;

	node = (struct efi_generic_dev_path *)buffer;

185 186
	if (len < sizeof(*node))
		return false;
187

188 189 190 191
	while (offset <= len - sizeof(*node) &&
	       node->length >= sizeof(*node) &&
		node->length <= len - offset) {
		offset += node->length;
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

		if ((node->type == EFI_DEV_END_PATH ||
		     node->type == EFI_DEV_END_PATH2) &&
		    node->sub_type == EFI_DEV_END_ENTIRE)
			return true;

		node = (struct efi_generic_dev_path *)(buffer + offset);
	}

	/*
	 * If we're here then either node->length pointed past the end
	 * of the buffer or we reached the end of the buffer without
	 * finding a device path end node.
	 */
	return false;
}

static bool
210 211
validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
		    unsigned long len)
212 213 214 215 216 217 218 219 220
{
	/* An array of 16-bit integers */
	if ((len % 2) != 0)
		return false;

	return true;
}

static bool
221 222
validate_load_option(struct efi_variable *var, int match, u8 *buffer,
		     unsigned long len)
223 224
{
	u16 filepathlength;
225 226
	int i, desclength = 0, namelen;

227
	namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));
228 229 230

	/* Either "Boot" or "Driver" followed by four digits of hex */
	for (i = match; i < match+4; i++) {
231 232
		if (var->VariableName[i] > 127 ||
		    hex_to_bin(var->VariableName[i] & 0xff) < 0)
233 234 235
			return true;
	}

236 237 238 239 240 241
	/* Reject it if there's 4 digits of hex and then further content */
	if (namelen > match + 4)
		return false;

	/* A valid entry must be at least 8 bytes */
	if (len < 8)
242 243 244 245 246 247 248 249
		return false;

	filepathlength = buffer[4] | buffer[5] << 8;

	/*
	 * There's no stored length for the description, so it has to be
	 * found by hand
	 */
250
	desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

	/* Each boot entry must have a descriptor */
	if (!desclength)
		return false;

	/*
	 * If the sum of the length of the description, the claimed filepath
	 * length and the original header are greater than the length of the
	 * variable, it's malformed
	 */
	if ((desclength + filepathlength + 6) > len)
		return false;

	/*
	 * And, finally, check the filepath
	 */
	return validate_device_path(var, match, buffer + desclength + 6,
				    filepathlength);
}

static bool
272 273
validate_uint16(struct efi_variable *var, int match, u8 *buffer,
		unsigned long len)
274 275 276 277 278 279 280 281 282
{
	/* A single 16-bit integer */
	if (len != 2)
		return false;

	return true;
}

static bool
283 284
validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
		      unsigned long len)
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
{
	int i;

	for (i = 0; i < len; i++) {
		if (buffer[i] > 127)
			return false;

		if (buffer[i] == 0)
			return true;
	}

	return false;
}

struct variable_validate {
	char *name;
	bool (*validate)(struct efi_variable *var, int match, u8 *data,
302
			 unsigned long len);
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
};

static const struct variable_validate variable_validate[] = {
	{ "BootNext", validate_uint16 },
	{ "BootOrder", validate_boot_order },
	{ "DriverOrder", validate_boot_order },
	{ "Boot*", validate_load_option },
	{ "Driver*", validate_load_option },
	{ "ConIn", validate_device_path },
	{ "ConInDev", validate_device_path },
	{ "ConOut", validate_device_path },
	{ "ConOutDev", validate_device_path },
	{ "ErrOut", validate_device_path },
	{ "ErrOutDev", validate_device_path },
	{ "Timeout", validate_uint16 },
	{ "Lang", validate_ascii_string },
	{ "PlatformLang", validate_ascii_string },
	{ "", NULL },
};

static bool
324
validate_var(struct efi_variable *var, u8 *data, unsigned long len)
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
{
	int i;
	u16 *unicode_name = var->VariableName;

	for (i = 0; variable_validate[i].validate != NULL; i++) {
		const char *name = variable_validate[i].name;
		int match;

		for (match = 0; ; match++) {
			char c = name[match];
			u16 u = unicode_name[match];

			/* All special variables are plain ascii */
			if (u > 127)
				return true;

			/* Wildcard in the matching name means we've matched */
			if (c == '*')
				return variable_validate[i].validate(var,
							     match, data, len);

			/* Case sensitive match */
			if (c != u)
				break;

			/* Reached the end of the string while matching */
			if (!c)
				return variable_validate[i].validate(var,
							     match, data, len);
		}
	}

	return true;
}

L
Linus Torvalds 已提交
360
static efi_status_t
361
get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
L
Linus Torvalds 已提交
362 363 364 365
{
	efi_status_t status;

	var->DataSize = 1024;
366 367 368 369 370
	status = efivars->ops->get_variable(var->VariableName,
					    &var->VendorGuid,
					    &var->Attributes,
					    &var->DataSize,
					    var->Data);
371 372 373 374 375 376 377
	return status;
}

static efi_status_t
get_var_data(struct efivars *efivars, struct efi_variable *var)
{
	efi_status_t status;
378
	unsigned long flags;
379

380
	spin_lock_irqsave(&efivars->lock, flags);
381
	status = get_var_data_locked(efivars, var);
382
	spin_unlock_irqrestore(&efivars->lock, flags);
383

L
Linus Torvalds 已提交
384 385 386 387 388 389 390
	if (status != EFI_SUCCESS) {
		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
			status);
	}
	return status;
}

391 392 393 394 395 396
static efi_status_t
check_var_size_locked(struct efivars *efivars, u32 attributes,
			unsigned long size)
{
	const struct efivar_operations *fops = efivars->ops;

397
	if (!efivars->ops->query_variable_store)
398 399
		return EFI_UNSUPPORTED;

400
	return fops->query_variable_store(attributes, size);
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
}


static efi_status_t
check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
{
	efi_status_t status;
	unsigned long flags;

	spin_lock_irqsave(&efivars->lock, flags);
	status = check_var_size_locked(efivars, attributes, size);
	spin_unlock_irqrestore(&efivars->lock, flags);

	return status;
}

L
Linus Torvalds 已提交
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
static ssize_t
efivar_guid_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	char *str = buf;

	if (!entry || !buf)
		return 0;

	efi_guid_unparse(&var->VendorGuid, str);
	str += strlen(str);
	str += sprintf(str, "\n");

	return str - buf;
}

static ssize_t
efivar_attr_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	char *str = buf;
	efi_status_t status;

	if (!entry || !buf)
		return -EINVAL;

M
Mike Waychison 已提交
443
	status = get_var_data(entry->efivars, var);
L
Linus Torvalds 已提交
444 445 446
	if (status != EFI_SUCCESS)
		return -EIO;

447
	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
L
Linus Torvalds 已提交
448
		str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
449
	if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
L
Linus Torvalds 已提交
450
		str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
451
	if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
L
Linus Torvalds 已提交
452
		str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
453 454 455 456 457 458 459 460 461 462 463
	if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
		str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
	if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
		str += sprintf(str,
			"EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
	if (var->Attributes &
			EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
		str += sprintf(str,
			"EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
	if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
		str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
L
Linus Torvalds 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476
	return str - buf;
}

static ssize_t
efivar_size_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	char *str = buf;
	efi_status_t status;

	if (!entry || !buf)
		return -EINVAL;

M
Mike Waychison 已提交
477
	status = get_var_data(entry->efivars, var);
L
Linus Torvalds 已提交
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
	if (status != EFI_SUCCESS)
		return -EIO;

	str += sprintf(str, "0x%lx\n", var->DataSize);
	return str - buf;
}

static ssize_t
efivar_data_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	efi_status_t status;

	if (!entry || !buf)
		return -EINVAL;

M
Mike Waychison 已提交
494
	status = get_var_data(entry->efivars, var);
L
Linus Torvalds 已提交
495 496 497 498 499 500 501 502 503 504 505 506 507 508
	if (status != EFI_SUCCESS)
		return -EIO;

	memcpy(buf, var->Data, var->DataSize);
	return var->DataSize;
}
/*
 * We allow each variable to be edited via rewriting the
 * entire efi variable structure.
 */
static ssize_t
efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
{
	struct efi_variable *new_var, *var = &entry->var;
M
Mike Waychison 已提交
509
	struct efivars *efivars = entry->efivars;
L
Linus Torvalds 已提交
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	efi_status_t status = EFI_NOT_FOUND;

	if (count != sizeof(struct efi_variable))
		return -EINVAL;

	new_var = (struct efi_variable *)buf;
	/*
	 * If only updating the variable data, then the name
	 * and guid should remain the same
	 */
	if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
		efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
		printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
		return -EINVAL;
	}

	if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
		printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
		return -EINVAL;
	}

531 532 533 534 535 536
	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

537
	spin_lock_irq(&efivars->lock);
538 539

	status = check_var_size_locked(efivars, new_var->Attributes,
540
	       new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
541 542 543 544 545 546 547

	if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
		status = efivars->ops->set_variable(new_var->VariableName,
						    &new_var->VendorGuid,
						    new_var->Attributes,
						    new_var->DataSize,
						    new_var->Data);
L
Linus Torvalds 已提交
548

549
	spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

	if (status != EFI_SUCCESS) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
			status);
		return -EIO;
	}

	memcpy(&entry->var, new_var, count);
	return count;
}

static ssize_t
efivar_show_raw(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	efi_status_t status;

	if (!entry || !buf)
		return 0;

M
Mike Waychison 已提交
570
	status = get_var_data(entry->efivars, var);
L
Linus Torvalds 已提交
571 572 573 574 575 576 577 578 579
	if (status != EFI_SUCCESS)
		return -EIO;

	memcpy(buf, var, sizeof(*var));
	return sizeof(*var);
}

/*
 * Generic read/write functions that call the specific functions of
580
 * the attributes...
L
Linus Torvalds 已提交
581 582 583 584 585 586
 */
static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
				char *buf)
{
	struct efivar_entry *var = to_efivar_entry(kobj);
	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
587
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if (efivar_attr->show) {
		ret = efivar_attr->show(var, buf);
	}
	return ret;
}

static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
				const char *buf, size_t count)
{
	struct efivar_entry *var = to_efivar_entry(kobj);
	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
603
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
604 605 606 607 608 609 610 611 612 613

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if (efivar_attr->store)
		ret = efivar_attr->store(var, buf, count);

	return ret;
}

614
static const struct sysfs_ops efivar_attr_ops = {
L
Linus Torvalds 已提交
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
	.show = efivar_attr_show,
	.store = efivar_attr_store,
};

static void efivar_release(struct kobject *kobj)
{
	struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
	kfree(var);
}

static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);

static struct attribute *def_attrs[] = {
	&efivar_attr_guid.attr,
	&efivar_attr_size.attr,
	&efivar_attr_attributes.attr,
	&efivar_attr_data.attr,
	&efivar_attr_raw_var.attr,
	NULL,
};

640
static struct kobj_type efivar_ktype = {
L
Linus Torvalds 已提交
641 642 643 644 645 646 647 648
	.release = efivar_release,
	.sysfs_ops = &efivar_attr_ops,
	.default_attrs = def_attrs,
};

static inline void
efivar_unregister(struct efivar_entry *var)
{
649
	kobject_put(&var->kobj);
L
Linus Torvalds 已提交
650 651
}

652 653 654 655 656 657
static int efivarfs_file_open(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
	return 0;
}

658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
static int efi_status_to_err(efi_status_t status)
{
	int err;

	switch (status) {
	case EFI_INVALID_PARAMETER:
		err = -EINVAL;
		break;
	case EFI_OUT_OF_RESOURCES:
		err = -ENOSPC;
		break;
	case EFI_DEVICE_ERROR:
		err = -EIO;
		break;
	case EFI_WRITE_PROTECTED:
		err = -EROFS;
		break;
	case EFI_SECURITY_VIOLATION:
		err = -EACCES;
		break;
	case EFI_NOT_FOUND:
679
		err = -EIO;
680 681 682 683 684 685 686 687
		break;
	default:
		err = -EINVAL;
	}

	return err;
}

688 689 690 691 692 693 694 695 696
static ssize_t efivarfs_file_write(struct file *file,
		const char __user *userbuf, size_t count, loff_t *ppos)
{
	struct efivar_entry *var = file->private_data;
	struct efivars *efivars;
	efi_status_t status;
	void *data;
	u32 attributes;
	struct inode *inode = file->f_mapping->host;
697
	unsigned long datasize = count - sizeof(attributes);
698
	unsigned long newdatasize, varsize;
699
	ssize_t bytes = 0;
700 701 702 703

	if (count < sizeof(attributes))
		return -EINVAL;

704 705
	if (copy_from_user(&attributes, userbuf, sizeof(attributes)))
		return -EFAULT;
706

707 708
	if (attributes & ~(EFI_VARIABLE_MASK))
		return -EINVAL;
709 710 711

	efivars = var->efivars;

712 713 714 715 716 717
	/*
	 * Ensure that the user can't allocate arbitrarily large
	 * amounts of memory. Pick a default size of 64K if
	 * QueryVariableInfo() isn't supported by the firmware.
	 */

718
	varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
719
	status = check_var_size(efivars, attributes, varsize);
720 721 722 723 724

	if (status != EFI_SUCCESS) {
		if (status != EFI_UNSUPPORTED)
			return efi_status_to_err(status);

725 726
		if (datasize > 65536)
			return -ENOSPC;
727 728
	}

729 730 731 732
	data = kmalloc(datasize, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

733
	if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
734
		bytes = -EFAULT;
735 736 737 738
		goto out;
	}

	if (validate_var(&var->var, data, datasize) == false) {
739
		bytes = -EINVAL;
740 741 742
		goto out;
	}

743 744 745 746 747
	/*
	 * The lock here protects the get_variable call, the conditional
	 * set_variable call, and removal of the variable from the efivars
	 * list (in the case of an authenticated delete).
	 */
748
	spin_lock_irq(&efivars->lock);
749

750 751 752 753 754 755 756 757 758 759 760 761 762
	/*
	 * Ensure that the available space hasn't shrunk below the safe level
	 */

	status = check_var_size_locked(efivars, attributes, varsize);

	if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
		spin_unlock_irq(&efivars->lock);
		kfree(data);

		return efi_status_to_err(status);
	}

763 764 765 766 767
	status = efivars->ops->set_variable(var->var.VariableName,
					    &var->var.VendorGuid,
					    attributes, datasize,
					    data);

768
	if (status != EFI_SUCCESS) {
769
		spin_unlock_irq(&efivars->lock);
770 771
		kfree(data);

772
		return efi_status_to_err(status);
773
	}
774

775 776
	bytes = count;

777 778 779 780 781 782 783 784 785 786 787 788 789
	/*
	 * Writing to the variable may have caused a change in size (which
	 * could either be an append or an overwrite), or the variable to be
	 * deleted. Perform a GetVariable() so we can tell what actually
	 * happened.
	 */
	newdatasize = 0;
	status = efivars->ops->get_variable(var->var.VariableName,
					    &var->var.VendorGuid,
					    NULL, &newdatasize,
					    NULL);

	if (status == EFI_BUFFER_TOO_SMALL) {
790
		spin_unlock_irq(&efivars->lock);
791 792 793 794 795 796
		mutex_lock(&inode->i_mutex);
		i_size_write(inode, newdatasize + sizeof(attributes));
		mutex_unlock(&inode->i_mutex);

	} else if (status == EFI_NOT_FOUND) {
		list_del(&var->list);
797
		spin_unlock_irq(&efivars->lock);
798 799
		efivar_unregister(var);
		drop_nlink(inode);
800
		d_delete(file->f_dentry);
801 802 803
		dput(file->f_dentry);

	} else {
804
		spin_unlock_irq(&efivars->lock);
805 806 807 808
		pr_warn("efivarfs: inconsistent EFI variable implementation? "
				"status = %lx\n", status);
	}

809 810 811
out:
	kfree(data);

812
	return bytes;
813 814 815 816 817 818 819 820 821 822 823
}

static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
		size_t count, loff_t *ppos)
{
	struct efivar_entry *var = file->private_data;
	struct efivars *efivars = var->efivars;
	efi_status_t status;
	unsigned long datasize = 0;
	u32 attributes;
	void *data;
824
	ssize_t size = 0;
825

826
	spin_lock_irq(&efivars->lock);
827 828 829
	status = efivars->ops->get_variable(var->var.VariableName,
					    &var->var.VendorGuid,
					    &attributes, &datasize, NULL);
830
	spin_unlock_irq(&efivars->lock);
831 832

	if (status != EFI_BUFFER_TOO_SMALL)
833
		return efi_status_to_err(status);
834

835
	data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
836 837

	if (!data)
838
		return -ENOMEM;
839

840
	spin_lock_irq(&efivars->lock);
841 842 843
	status = efivars->ops->get_variable(var->var.VariableName,
					    &var->var.VendorGuid,
					    &attributes, &datasize,
844
					    (data + sizeof(attributes)));
845
	spin_unlock_irq(&efivars->lock);
846

847 848
	if (status != EFI_SUCCESS) {
		size = efi_status_to_err(status);
849
		goto out_free;
850
	}
851

852
	memcpy(data, &attributes, sizeof(attributes));
853
	size = simple_read_from_buffer(userbuf, count, ppos,
854
				       data, datasize + sizeof(attributes));
855
out_free:
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
	kfree(data);

	return size;
}

static void efivarfs_evict_inode(struct inode *inode)
{
	clear_inode(inode);
}

static const struct super_operations efivarfs_ops = {
	.statfs = simple_statfs,
	.drop_inode = generic_delete_inode,
	.evict_inode = efivarfs_evict_inode,
	.show_options = generic_show_options,
};

static struct super_block *efivarfs_sb;

static const struct inode_operations efivarfs_dir_inode_operations;

static const struct file_operations efivarfs_file_operations = {
	.open	= efivarfs_file_open,
	.read	= efivarfs_file_read,
	.write	= efivarfs_file_write,
	.llseek	= no_llseek,
};

static struct inode *efivarfs_get_inode(struct super_block *sb,
				const struct inode *dir, int mode, dev_t dev)
{
	struct inode *inode = new_inode(sb);

	if (inode) {
		inode->i_ino = get_next_ino();
		inode->i_mode = mode;
		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
		switch (mode & S_IFMT) {
		case S_IFREG:
			inode->i_fop = &efivarfs_file_operations;
			break;
		case S_IFDIR:
			inode->i_op = &efivarfs_dir_inode_operations;
			inode->i_fop = &simple_dir_operations;
			inc_nlink(inode);
			break;
		}
	}
	return inode;
}

907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
/*
 * Return true if 'str' is a valid efivarfs filename of the form,
 *
 *	VariableName-12345678-1234-1234-1234-1234567891bc
 */
static bool efivarfs_valid_name(const char *str, int len)
{
	static const char dashes[GUID_LEN] = {
		[8] = 1, [13] = 1, [18] = 1, [23] = 1
	};
	const char *s = str + len - GUID_LEN;
	int i;

	/*
	 * We need a GUID, plus at least one letter for the variable name,
	 * plus the '-' separator
	 */
	if (len < GUID_LEN + 2)
		return false;

927 928
	/* GUID must be preceded by a '-' */
	if (*(s - 1) != '-')
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
		return false;

	/*
	 * Validate that 's' is of the correct format, e.g.
	 *
	 *	12345678-1234-1234-1234-123456789abc
	 */
	for (i = 0; i < GUID_LEN; i++) {
		if (dashes[i]) {
			if (*s++ != '-')
				return false;
		} else {
			if (!isxdigit(*s++))
				return false;
		}
	}

	return true;
}

949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
{
	guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
	guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]);
	guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]);
	guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]);
	guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]);
	guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]);
	guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]);
	guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]);
	guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]);
	guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]);
	guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]);
	guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]);
	guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]);
	guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]);
	guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]);
	guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]);
}

static int efivarfs_create(struct inode *dir, struct dentry *dentry,
			  umode_t mode, bool excl)
{
972
	struct inode *inode;
973 974 975 976
	struct efivars *efivars = &__efivars;
	struct efivar_entry *var;
	int namelen, i = 0, err = 0;

977
	if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
978 979
		return -EINVAL;

980
	inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
981
	if (!inode)
982
		return -ENOMEM;
983 984

	var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
985 986 987 988
	if (!var) {
		err = -ENOMEM;
		goto out;
	}
989

990 991
	/* length of the variable name itself: remove GUID and separator */
	namelen = dentry->d_name.len - GUID_LEN - 1;
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010

	efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
			&var->var.VendorGuid);

	for (i = 0; i < namelen; i++)
		var->var.VariableName[i] = dentry->d_name.name[i];

	var->var.VariableName[i] = '\0';

	inode->i_private = var;
	var->efivars = efivars;
	var->kobj.kset = efivars->kset;

	err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s",
			     dentry->d_name.name);
	if (err)
		goto out;

	kobject_uevent(&var->kobj, KOBJ_ADD);
1011
	spin_lock_irq(&efivars->lock);
1012
	list_add(&var->list, &efivars->list);
1013
	spin_unlock_irq(&efivars->lock);
1014 1015 1016
	d_instantiate(dentry, inode);
	dget(dentry);
out:
1017
	if (err) {
1018
		kfree(var);
1019 1020
		iput(inode);
	}
1021 1022 1023 1024 1025 1026 1027 1028 1029
	return err;
}

static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
{
	struct efivar_entry *var = dentry->d_inode->i_private;
	struct efivars *efivars = var->efivars;
	efi_status_t status;

1030
	spin_lock_irq(&efivars->lock);
1031 1032 1033 1034 1035 1036 1037

	status = efivars->ops->set_variable(var->var.VariableName,
					    &var->var.VendorGuid,
					    0, 0, NULL);

	if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
		list_del(&var->list);
1038
		spin_unlock_irq(&efivars->lock);
1039
		efivar_unregister(var);
1040
		drop_nlink(dentry->d_inode);
1041 1042 1043 1044
		dput(dentry);
		return 0;
	}

1045
	spin_unlock_irq(&efivars->lock);
1046 1047 1048
	return -EINVAL;
};

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
/*
 * Compare two efivarfs file names.
 *
 * An efivarfs filename is composed of two parts,
 *
 *	1. A case-sensitive variable name
 *	2. A case-insensitive GUID
 *
 * So we need to perform a case-sensitive match on part 1 and a
 * case-insensitive match on part 2.
 */
static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
			      const struct dentry *dentry, const struct inode *inode,
			      unsigned int len, const char *str,
			      const struct qstr *name)
{
	int guid = len - GUID_LEN;

	if (name->len != len)
		return 1;

	/* Case-sensitive compare for the variable name */
	if (memcmp(str, name->name, guid))
		return 1;

	/* Case-insensitive compare for the GUID */
	return strncasecmp(name->name + guid, str + guid, GUID_LEN);
}

static int efivarfs_d_hash(const struct dentry *dentry,
			   const struct inode *inode, struct qstr *qstr)
{
	unsigned long hash = init_name_hash();
	const unsigned char *s = qstr->name;
	unsigned int len = qstr->len;

	if (!efivarfs_valid_name(s, len))
		return -EINVAL;

	while (len-- > GUID_LEN)
		hash = partial_name_hash(*s++, hash);

	/* GUID is case-insensitive. */
	while (len--)
		hash = partial_name_hash(tolower(*s++), hash);

	qstr->hash = end_name_hash(hash);
	return 0;
}

/*
 * Retaining negative dentries for an in-memory filesystem just wastes
 * memory and lookup time: arrange for them to be deleted immediately.
 */
static int efivarfs_delete_dentry(const struct dentry *dentry)
{
	return 1;
}

static struct dentry_operations efivarfs_d_ops = {
	.d_compare = efivarfs_d_compare,
	.d_hash = efivarfs_d_hash,
	.d_delete = efivarfs_delete_dentry,
};

static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
{
1116
	struct dentry *d;
1117
	struct qstr q;
1118
	int err;
1119 1120 1121 1122

	q.name = name;
	q.len = strlen(name);

1123 1124 1125 1126 1127 1128 1129
	err = efivarfs_d_hash(NULL, NULL, &q);
	if (err)
		return ERR_PTR(err);

	d = d_alloc(parent, &q);
	if (d)
		return d;
1130

1131
	return ERR_PTR(-ENOMEM);
1132 1133
}

1134
static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
1135 1136 1137 1138 1139
{
	struct inode *inode = NULL;
	struct dentry *root;
	struct efivar_entry *entry, *n;
	struct efivars *efivars = &__efivars;
1140
	char *name;
1141
	int err = -ENOMEM;
1142 1143 1144 1145 1146 1147

	efivarfs_sb = sb;

	sb->s_maxbytes          = MAX_LFS_FILESIZE;
	sb->s_blocksize         = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits    = PAGE_CACHE_SHIFT;
M
Matt Fleming 已提交
1148
	sb->s_magic             = EFIVARFS_MAGIC;
1149
	sb->s_op                = &efivarfs_ops;
1150
	sb->s_d_op		= &efivarfs_d_ops;
1151 1152 1153
	sb->s_time_gran         = 1;

	inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
1154 1155
	if (!inode)
		return -ENOMEM;
1156 1157 1158 1159
	inode->i_op = &efivarfs_dir_inode_operations;

	root = d_make_root(inode);
	sb->s_root = root;
1160 1161
	if (!root)
		return -ENOMEM;
1162 1163 1164 1165 1166 1167

	list_for_each_entry_safe(entry, n, &efivars->list, list) {
		struct dentry *dentry, *root = efivarfs_sb->s_root;
		unsigned long size = 0;
		int len, i;

1168 1169
		inode = NULL;

1170
		len = ucs2_strlen(entry->var.VariableName);
1171

1172 1173
		/* name, plus '-', plus GUID, plus NUL*/
		name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
1174 1175
		if (!name)
			goto fail;
1176 1177 1178 1179 1180 1181 1182 1183

		for (i = 0; i < len; i++)
			name[i] = entry->var.VariableName[i] & 0xFF;

		name[len] = '-';

		efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);

1184
		name[len+GUID_LEN+1] = '\0';
1185 1186 1187

		inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
					  S_IFREG | 0644, 0);
1188 1189 1190
		if (!inode)
			goto fail_name;

1191
		dentry = efivarfs_alloc_dentry(root, name);
1192 1193
		if (IS_ERR(dentry)) {
			err = PTR_ERR(dentry);
1194
			goto fail_inode;
1195
		}
1196

1197 1198
		/* copied by the above to local storage in the dentry. */
		kfree(name);
1199

1200
		spin_lock_irq(&efivars->lock);
1201 1202 1203 1204 1205
		efivars->ops->get_variable(entry->var.VariableName,
					   &entry->var.VendorGuid,
					   &entry->var.Attributes,
					   &size,
					   NULL);
1206
		spin_unlock_irq(&efivars->lock);
1207 1208 1209

		mutex_lock(&inode->i_mutex);
		inode->i_private = entry;
1210
		i_size_write(inode, size + sizeof(entry->var.Attributes));
1211 1212 1213 1214 1215
		mutex_unlock(&inode->i_mutex);
		d_add(dentry, inode);
	}

	return 0;
1216 1217 1218 1219 1220 1221

fail_inode:
	iput(inode);
fail_name:
	kfree(name);
fail:
1222
	return err;
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
}

static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
				    int flags, const char *dev_name, void *data)
{
	return mount_single(fs_type, flags, data, efivarfs_fill_super);
}

static void efivarfs_kill_sb(struct super_block *sb)
{
	kill_litter_super(sb);
	efivarfs_sb = NULL;
}

static struct file_system_type efivarfs_type = {
	.name    = "efivarfs",
	.mount   = efivarfs_mount,
	.kill_sb = efivarfs_kill_sb,
};
1242
MODULE_ALIAS_FS("efivarfs");
1243

1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
/*
 * Handle negative dentry.
 */
static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
				      unsigned int flags)
{
	if (dentry->d_name.len > NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);
	d_add(dentry, NULL);
	return NULL;
}

1256
static const struct inode_operations efivarfs_dir_inode_operations = {
1257
	.lookup = efivarfs_lookup,
1258 1259 1260 1261
	.unlink = efivarfs_unlink,
	.create = efivarfs_create,
};

1262
#ifdef CONFIG_EFI_VARS_PSTORE
1263 1264 1265 1266 1267

static int efi_pstore_open(struct pstore_info *psi)
{
	struct efivars *efivars = psi->data;

1268
	spin_lock_irq(&efivars->lock);
1269 1270 1271 1272 1273 1274 1275 1276 1277
	efivars->walk_entry = list_first_entry(&efivars->list,
					       struct efivar_entry, list);
	return 0;
}

static int efi_pstore_close(struct pstore_info *psi)
{
	struct efivars *efivars = psi->data;

1278
	spin_unlock_irq(&efivars->lock);
1279 1280 1281 1282
	return 0;
}

static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
1283
			       int *count, struct timespec *timespec,
1284
			       char **buf, struct pstore_info *psi)
1285 1286 1287 1288 1289
{
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	struct efivars *efivars = psi->data;
	char name[DUMP_NAME_LEN];
	int i;
1290
	int cnt;
1291 1292 1293 1294 1295 1296 1297 1298 1299
	unsigned int part, size;
	unsigned long time;

	while (&efivars->walk_entry->list != &efivars->list) {
		if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
				 vendor)) {
			for (i = 0; i < DUMP_NAME_LEN; i++) {
				name[i] = efivars->walk_entry->var.VariableName[i];
			}
1300 1301
			if (sscanf(name, "dump-type%u-%u-%d-%lu",
				   type, &part, &cnt, &time) == 4) {
1302
				*id = part;
1303
				*count = cnt;
1304 1305
				timespec->tv_sec = time;
				timespec->tv_nsec = 0;
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
			} else if (sscanf(name, "dump-type%u-%u-%lu",
				   type, &part, &time) == 3) {
				/*
				 * Check if an old format,
				 * which doesn't support holding
				 * multiple logs, remains.
				 */
				*id = part;
				*count = 0;
				timespec->tv_sec = time;
				timespec->tv_nsec = 0;
			} else {
				efivars->walk_entry = list_entry(
						efivars->walk_entry->list.next,
						struct efivar_entry, list);
				continue;
1322
			}
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334

			get_var_data_locked(efivars, &efivars->walk_entry->var);
			size = efivars->walk_entry->var.DataSize;
			*buf = kmalloc(size, GFP_KERNEL);
			if (*buf == NULL)
				return -ENOMEM;
			memcpy(*buf, efivars->walk_entry->var.Data,
			       size);
			efivars->walk_entry = list_entry(
					efivars->walk_entry->list.next,
					struct efivar_entry, list);
			return size;
1335 1336 1337 1338 1339 1340 1341
		}
		efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
						 struct efivar_entry, list);
	}
	return 0;
}

1342 1343
static int efi_pstore_write(enum pstore_type_id type,
		enum kmsg_dump_reason reason, u64 *id,
1344 1345
		unsigned int part, int count, size_t size,
		struct pstore_info *psi)
1346 1347 1348 1349 1350
{
	char name[DUMP_NAME_LEN];
	efi_char16_t efi_name[DUMP_NAME_LEN];
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	struct efivars *efivars = psi->data;
1351
	int i, ret = 0;
1352
	efi_status_t status = EFI_NOT_FOUND;
1353
	unsigned long flags;
1354

1355 1356 1357 1358 1359 1360
	if (pstore_cannot_block_path(reason)) {
		/*
		 * If the lock is taken by another cpu in non-blocking path,
		 * this driver returns without entering firmware to avoid
		 * hanging up.
		 */
1361
		if (!spin_trylock_irqsave(&efivars->lock, flags))
1362 1363
			return -EBUSY;
	} else
1364
		spin_lock_irqsave(&efivars->lock, flags);
1365

1366 1367 1368 1369 1370
	/*
	 * Check if there is a space enough to log.
	 * size: a size of logging data
	 * DUMP_NAME_LEN * 2: a maximum size of variable name
	 */
1371 1372 1373 1374 1375

	status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
					 size + DUMP_NAME_LEN * 2);

	if (status) {
1376
		spin_unlock_irqrestore(&efivars->lock, flags);
1377 1378 1379 1380
		*id = part;
		return -ENOSPC;
	}

1381
	sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count,
1382
		get_seconds());
1383 1384 1385 1386

	for (i = 0; i < DUMP_NAME_LEN; i++)
		efi_name[i] = name[i];

1387
	efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
1388 1389
				   size, psi->buf);

1390
	spin_unlock_irqrestore(&efivars->lock, flags);
1391

1392
	if (reason == KMSG_DUMP_OOPS && efivar_wq_enabled)
1393
		schedule_work(&efivar_work);
1394

1395 1396
	*id = part;
	return ret;
1397 1398
};

1399
static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
1400
			    struct timespec time, struct pstore_info *psi)
1401
{
1402
	char name[DUMP_NAME_LEN];
1403
	efi_char16_t efi_name[DUMP_NAME_LEN];
1404 1405
	char name_old[DUMP_NAME_LEN];
	efi_char16_t efi_name_old[DUMP_NAME_LEN];
1406 1407 1408 1409 1410
	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
	struct efivars *efivars = psi->data;
	struct efivar_entry *entry, *found = NULL;
	int i;

1411
	sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
1412
		time.tv_sec);
1413

1414
	spin_lock_irq(&efivars->lock);
1415 1416

	for (i = 0; i < DUMP_NAME_LEN; i++)
1417
		efi_name[i] = name[i];
1418 1419

	/*
1420
	 * Clean up an entry with the same name
1421 1422 1423 1424 1425 1426 1427
	 */

	list_for_each_entry(entry, &efivars->list, list) {
		get_var_data_locked(efivars, &entry->var);

		if (efi_guidcmp(entry->var.VendorGuid, vendor))
			continue;
1428 1429
		if (ucs2_strncmp(entry->var.VariableName, efi_name,
				  ucs2_strlen(efi_name))) {
1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
			/*
			 * Check if an old format,
			 * which doesn't support holding
			 * multiple logs, remains.
			 */
			sprintf(name_old, "dump-type%u-%u-%lu", type,
				(unsigned int)id, time.tv_sec);

			for (i = 0; i < DUMP_NAME_LEN; i++)
				efi_name_old[i] = name_old[i];

1441 1442
			if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
					  ucs2_strlen(efi_name_old)))
1443 1444
				continue;
		}
1445 1446 1447 1448 1449 1450 1451

		/* found */
		found = entry;
		efivars->ops->set_variable(entry->var.VariableName,
					   &entry->var.VendorGuid,
					   PSTORE_EFI_ATTRIBUTES,
					   0, NULL);
1452
		break;
1453 1454 1455 1456 1457
	}

	if (found)
		list_del(&found->list);

1458
	spin_unlock_irq(&efivars->lock);
1459 1460 1461

	if (found)
		efivar_unregister(found);
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474

	return 0;
}

static struct pstore_info efi_pstore_info = {
	.owner		= THIS_MODULE,
	.name		= "efi",
	.open		= efi_pstore_open,
	.close		= efi_pstore_close,
	.read		= efi_pstore_read,
	.write		= efi_pstore_write,
	.erase		= efi_pstore_erase,
};
L
Linus Torvalds 已提交
1475

1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
static void efivar_pstore_register(struct efivars *efivars)
{
	efivars->efi_pstore_info = efi_pstore_info;
	efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
	if (efivars->efi_pstore_info.buf) {
		efivars->efi_pstore_info.bufsize = 1024;
		efivars->efi_pstore_info.data = efivars;
		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
		pstore_register(&efivars->efi_pstore_info);
	}
}
#else
static void efivar_pstore_register(struct efivars *efivars)
{
	return;
}
#endif

1494
static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1495 1496
			     struct bin_attribute *bin_attr,
			     char *buf, loff_t pos, size_t count)
L
Linus Torvalds 已提交
1497 1498
{
	struct efi_variable *new_var = (struct efi_variable *)buf;
M
Mike Waychison 已提交
1499
	struct efivars *efivars = bin_attr->private;
1500
	struct efivar_entry *search_efivar, *n;
L
Linus Torvalds 已提交
1501 1502 1503 1504 1505 1506 1507
	unsigned long strsize1, strsize2;
	efi_status_t status = EFI_NOT_FOUND;
	int found = 0;

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

1508 1509 1510 1511 1512 1513
	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

1514
	spin_lock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1515 1516 1517 1518

	/*
	 * Does this variable already exist?
	 */
1519
	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1520 1521
		strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
		strsize2 = ucs2_strsize(new_var->VariableName, 1024);
L
Linus Torvalds 已提交
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
		if (strsize1 == strsize2 &&
			!memcmp(&(search_efivar->var.VariableName),
				new_var->VariableName, strsize1) &&
			!efi_guidcmp(search_efivar->var.VendorGuid,
				new_var->VendorGuid)) {
			found = 1;
			break;
		}
	}
	if (found) {
1532
		spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1533 1534 1535
		return -EINVAL;
	}

1536
	status = check_var_size_locked(efivars, new_var->Attributes,
1537
	       new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
1538 1539 1540 1541 1542 1543

	if (status && status != EFI_UNSUPPORTED) {
		spin_unlock_irq(&efivars->lock);
		return efi_status_to_err(status);
	}

L
Linus Torvalds 已提交
1544
	/* now *really* create the variable via EFI */
1545 1546 1547 1548 1549
	status = efivars->ops->set_variable(new_var->VariableName,
					    &new_var->VendorGuid,
					    new_var->Attributes,
					    new_var->DataSize,
					    new_var->Data);
L
Linus Torvalds 已提交
1550 1551 1552 1553

	if (status != EFI_SUCCESS) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
			status);
1554
		spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1555 1556
		return -EIO;
	}
1557
	spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1558 1559

	/* Create the entry in sysfs.  Locking is not required here */
M
Mike Waychison 已提交
1560
	status = efivar_create_sysfs_entry(efivars,
1561
					   ucs2_strsize(new_var->VariableName,
M
Mike Waychison 已提交
1562
							 1024),
M
Mike Waychison 已提交
1563 1564
					   new_var->VariableName,
					   &new_var->VendorGuid);
L
Linus Torvalds 已提交
1565 1566 1567 1568 1569 1570
	if (status) {
		printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n");
	}
	return count;
}

1571
static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
1572 1573
			     struct bin_attribute *bin_attr,
			     char *buf, loff_t pos, size_t count)
L
Linus Torvalds 已提交
1574 1575
{
	struct efi_variable *del_var = (struct efi_variable *)buf;
M
Mike Waychison 已提交
1576
	struct efivars *efivars = bin_attr->private;
1577
	struct efivar_entry *search_efivar, *n;
L
Linus Torvalds 已提交
1578 1579 1580 1581 1582 1583 1584
	unsigned long strsize1, strsize2;
	efi_status_t status = EFI_NOT_FOUND;
	int found = 0;

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

1585
	spin_lock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1586 1587 1588 1589

	/*
	 * Does this variable already exist?
	 */
1590
	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1591 1592
		strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
		strsize2 = ucs2_strsize(del_var->VariableName, 1024);
L
Linus Torvalds 已提交
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
		if (strsize1 == strsize2 &&
			!memcmp(&(search_efivar->var.VariableName),
				del_var->VariableName, strsize1) &&
			!efi_guidcmp(search_efivar->var.VendorGuid,
				del_var->VendorGuid)) {
			found = 1;
			break;
		}
	}
	if (!found) {
1603
		spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1604 1605 1606 1607 1608 1609
		return -EINVAL;
	}
	/* force the Attributes/DataSize to 0 to ensure deletion */
	del_var->Attributes = 0;
	del_var->DataSize = 0;

1610 1611 1612 1613 1614
	status = efivars->ops->set_variable(del_var->VariableName,
					    &del_var->VendorGuid,
					    del_var->Attributes,
					    del_var->DataSize,
					    del_var->Data);
L
Linus Torvalds 已提交
1615 1616 1617 1618

	if (status != EFI_SUCCESS) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
			status);
1619
		spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1620 1621
		return -EIO;
	}
1622
	list_del(&search_efivar->list);
L
Linus Torvalds 已提交
1623
	/* We need to release this lock before unregistering. */
1624
	spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1625 1626 1627 1628 1629 1630
	efivar_unregister(search_efivar);

	/* It's dead Jim.... */
	return count;
}

1631 1632 1633 1634 1635 1636 1637
static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
{
	struct efivar_entry *entry, *n;
	struct efivars *efivars = &__efivars;
	unsigned long strsize1, strsize2;
	bool found = false;

1638
	strsize1 = ucs2_strsize(variable_name, 1024);
1639
	list_for_each_entry_safe(entry, n, &efivars->list, list) {
1640
		strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
		if (strsize1 == strsize2 &&
			!memcmp(variable_name, &(entry->var.VariableName),
				strsize2) &&
			!efi_guidcmp(entry->var.VendorGuid,
				*vendor)) {
			found = true;
			break;
		}
	}
	return found;
}

1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
/*
 * Returns the size of variable_name, in bytes, including the
 * terminating NULL character, or variable_name_size if no NULL
 * character is found among the first variable_name_size bytes.
 */
static unsigned long var_name_strnsize(efi_char16_t *variable_name,
				       unsigned long variable_name_size)
{
	unsigned long len;
	efi_char16_t c;

	/*
	 * The variable name is, by definition, a NULL-terminated
	 * string, so make absolutely sure that variable_name_size is
	 * the value we expect it to be. If not, return the real size.
	 */
	for (len = 2; len <= variable_name_size; len += sizeof(c)) {
		c = variable_name[(len / sizeof(c)) - 1];
		if (!c)
			break;
	}

	return min(len, variable_name_size);
}

1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717
static void efivar_update_sysfs_entries(struct work_struct *work)
{
	struct efivars *efivars = &__efivars;
	efi_guid_t vendor;
	efi_char16_t *variable_name;
	unsigned long variable_name_size = 1024;
	efi_status_t status = EFI_NOT_FOUND;
	bool found;

	/* Add new sysfs entries */
	while (1) {
		variable_name = kzalloc(variable_name_size, GFP_KERNEL);
		if (!variable_name) {
			pr_err("efivars: Memory allocation failed.\n");
			return;
		}

		spin_lock_irq(&efivars->lock);
		found = false;
		while (1) {
			variable_name_size = 1024;
			status = efivars->ops->get_next_variable(
							&variable_name_size,
							variable_name,
							&vendor);
			if (status != EFI_SUCCESS) {
				break;
			} else {
				if (!variable_is_present(variable_name,
				    &vendor)) {
					found = true;
					break;
				}
			}
		}
		spin_unlock_irq(&efivars->lock);

		if (!found) {
			kfree(variable_name);
			break;
1718 1719 1720
		} else {
			variable_name_size = var_name_strnsize(variable_name,
							       variable_name_size);
1721 1722 1723
			efivar_create_sysfs_entry(efivars,
						  variable_name_size,
						  variable_name, &vendor);
1724
		}
1725 1726 1727
	}
}

L
Linus Torvalds 已提交
1728 1729 1730 1731
/*
 * Let's not leave out systab information that snuck into
 * the efivars driver
 */
1732 1733
static ssize_t systab_show(struct kobject *kobj,
			   struct kobj_attribute *attr, char *buf)
L
Linus Torvalds 已提交
1734 1735 1736
{
	char *str = buf;

1737
	if (!kobj || !buf)
L
Linus Torvalds 已提交
1738 1739
		return -EINVAL;

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
	if (efi.mps != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "MPS=0x%lx\n", efi.mps);
	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
	if (efi.acpi != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
	if (efi.smbios != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
	if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
	if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
	if (efi.uga != EFI_INVALID_TABLE_ADDR)
		str += sprintf(str, "UGA=0x%lx\n", efi.uga);
L
Linus Torvalds 已提交
1754 1755 1756 1757

	return str - buf;
}

1758 1759
static struct kobj_attribute efi_attr_systab =
			__ATTR(systab, 0400, systab_show, NULL);
L
Linus Torvalds 已提交
1760

1761 1762
static struct attribute *efi_subsys_attrs[] = {
	&efi_attr_systab.attr,
L
Linus Torvalds 已提交
1763 1764 1765
	NULL,	/* maybe more in the future? */
};

1766 1767 1768 1769
static struct attribute_group efi_subsys_attr_group = {
	.attrs = efi_subsys_attrs,
};

1770
static struct kobject *efi_kobj;
L
Linus Torvalds 已提交
1771 1772 1773 1774 1775 1776 1777

/*
 * efivar_create_sysfs_entry()
 * Requires:
 *    variable_name_size = number of bytes required to hold
 *                         variable_name (not counting the NULL
 *                         character at the end.
1778
 *    efivars->lock is not held on entry or exit.
L
Linus Torvalds 已提交
1779 1780 1781
 * Returns 1 on failure, 0 on success
 */
static int
M
Mike Waychison 已提交
1782 1783 1784 1785
efivar_create_sysfs_entry(struct efivars *efivars,
			  unsigned long variable_name_size,
			  efi_char16_t *variable_name,
			  efi_guid_t *vendor_guid)
L
Linus Torvalds 已提交
1786
{
1787
	int i, short_name_size;
L
Linus Torvalds 已提交
1788 1789 1790
	char *short_name;
	struct efivar_entry *new_efivar;

1791 1792 1793 1794 1795 1796 1797 1798
	/*
	 * Length of the variable bytes in ASCII, plus the '-' separator,
	 * plus the GUID, plus trailing NUL
	 */
	short_name_size = variable_name_size / sizeof(efi_char16_t)
				+ 1 + GUID_LEN + 1;

	short_name = kzalloc(short_name_size, GFP_KERNEL);
1799
	new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
L
Linus Torvalds 已提交
1800 1801

	if (!short_name || !new_efivar)  {
1802 1803
		kfree(short_name);
		kfree(new_efivar);
L
Linus Torvalds 已提交
1804 1805 1806
		return 1;
	}

M
Mike Waychison 已提交
1807
	new_efivar->efivars = efivars;
L
Linus Torvalds 已提交
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
	memcpy(new_efivar->var.VariableName, variable_name,
		variable_name_size);
	memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));

	/* Convert Unicode to normal chars (assume top bits are 0),
	   ala UTF-8 */
	for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
		short_name[i] = variable_name[i] & 0xFF;
	}
	/* This is ugly, but necessary to separate one vendor's
	   private variables from another's.         */

	*(short_name + strlen(short_name)) = '-';
	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));

1823
	new_efivar->kobj.kset = efivars->kset;
1824 1825
	i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
				 "%s", short_name);
1826 1827 1828 1829 1830
	if (i) {
		kfree(short_name);
		kfree(new_efivar);
		return 1;
	}
L
Linus Torvalds 已提交
1831

1832
	kobject_uevent(&new_efivar->kobj, KOBJ_ADD);
1833 1834
	kfree(short_name);
	short_name = NULL;
L
Linus Torvalds 已提交
1835

1836
	spin_lock_irq(&efivars->lock);
1837
	list_add(&new_efivar->list, &efivars->list);
1838
	spin_unlock_irq(&efivars->lock);
L
Linus Torvalds 已提交
1839 1840 1841

	return 0;
}
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894

static int
create_efivars_bin_attributes(struct efivars *efivars)
{
	struct bin_attribute *attr;
	int error;

	/* new_var */
	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
	if (!attr)
		return -ENOMEM;

	attr->attr.name = "new_var";
	attr->attr.mode = 0200;
	attr->write = efivar_create;
	attr->private = efivars;
	efivars->new_var = attr;

	/* del_var */
	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
	if (!attr) {
		error = -ENOMEM;
		goto out_free;
	}
	attr->attr.name = "del_var";
	attr->attr.mode = 0200;
	attr->write = efivar_delete;
	attr->private = efivars;
	efivars->del_var = attr;

	sysfs_bin_attr_init(efivars->new_var);
	sysfs_bin_attr_init(efivars->del_var);

	/* Register */
	error = sysfs_create_bin_file(&efivars->kset->kobj,
				      efivars->new_var);
	if (error) {
		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
			" due to error %d\n", error);
		goto out_free;
	}
	error = sysfs_create_bin_file(&efivars->kset->kobj,
				      efivars->del_var);
	if (error) {
		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
			" due to error %d\n", error);
		sysfs_remove_bin_file(&efivars->kset->kobj,
				      efivars->new_var);
		goto out_free;
	}

	return 0;
out_free:
1895 1896
	kfree(efivars->del_var);
	efivars->del_var = NULL;
1897 1898 1899 1900 1901
	kfree(efivars->new_var);
	efivars->new_var = NULL;
	return error;
}

1902
void unregister_efivars(struct efivars *efivars)
1903 1904
{
	struct efivar_entry *entry, *n;
M
Mike Waychison 已提交
1905

1906
	list_for_each_entry_safe(entry, n, &efivars->list, list) {
1907
		spin_lock_irq(&efivars->lock);
1908
		list_del(&entry->list);
1909
		spin_unlock_irq(&efivars->lock);
1910 1911 1912 1913 1914 1915 1916 1917
		efivar_unregister(entry);
	}
	if (efivars->new_var)
		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
	if (efivars->del_var)
		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
	kfree(efivars->new_var);
	kfree(efivars->del_var);
1918
	kobject_put(efivars->kobject);
1919 1920
	kset_unregister(efivars->kset);
}
1921
EXPORT_SYMBOL_GPL(unregister_efivars);
L
Linus Torvalds 已提交
1922

1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951
/*
 * Print a warning when duplicate EFI variables are encountered and
 * disable the sysfs workqueue since the firmware is buggy.
 */
static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
			     unsigned long len16)
{
	size_t i, len8 = len16 / sizeof(efi_char16_t);
	char *s8;

	/*
	 * Disable the workqueue since the algorithm it uses for
	 * detecting new variables won't work with this buggy
	 * implementation of GetNextVariableName().
	 */
	efivar_wq_enabled = false;

	s8 = kzalloc(len8, GFP_KERNEL);
	if (!s8)
		return;

	for (i = 0; i < len8; i++)
		s8[i] = s16[i];

	printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
	       s8, vendor_guid);
	kfree(s8);
}

1952 1953 1954
int register_efivars(struct efivars *efivars,
		     const struct efivar_operations *ops,
		     struct kobject *parent_kobj)
L
Linus Torvalds 已提交
1955 1956 1957 1958 1959
{
	efi_status_t status = EFI_NOT_FOUND;
	efi_guid_t vendor_guid;
	efi_char16_t *variable_name;
	unsigned long variable_name_size = 1024;
1960
	int error = 0;
L
Linus Torvalds 已提交
1961

1962
	variable_name = kzalloc(variable_name_size, GFP_KERNEL);
L
Linus Torvalds 已提交
1963 1964 1965 1966 1967
	if (!variable_name) {
		printk(KERN_ERR "efivars: Memory allocation failed.\n");
		return -ENOMEM;
	}

1968 1969
	spin_lock_init(&efivars->lock);
	INIT_LIST_HEAD(&efivars->list);
1970
	efivars->ops = ops;
1971

1972
	efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
1973
	if (!efivars->kset) {
1974 1975
		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
		error = -ENOMEM;
1976
		goto out;
L
Linus Torvalds 已提交
1977 1978
	}

1979 1980 1981 1982 1983 1984 1985 1986
	efivars->kobject = kobject_create_and_add("efivars", parent_kobj);
	if (!efivars->kobject) {
		pr_err("efivars: Subsystem registration failed.\n");
		error = -ENOMEM;
		kset_unregister(efivars->kset);
		goto out;
	}

L
Linus Torvalds 已提交
1987 1988 1989 1990 1991 1992 1993 1994
	/*
	 * Per EFI spec, the maximum storage allocated for both
	 * the variable name and variable data is 1024 bytes.
	 */

	do {
		variable_name_size = 1024;

1995
		status = ops->get_next_variable(&variable_name_size,
L
Linus Torvalds 已提交
1996 1997 1998 1999
						variable_name,
						&vendor_guid);
		switch (status) {
		case EFI_SUCCESS:
2000 2001
			variable_name_size = var_name_strnsize(variable_name,
							       variable_name_size);
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017

			/*
			 * Some firmware implementations return the
			 * same variable name on multiple calls to
			 * get_next_variable(). Terminate the loop
			 * immediately as there is no guarantee that
			 * we'll ever see a different variable name,
			 * and may end up looping here forever.
			 */
			if (variable_is_present(variable_name, &vendor_guid)) {
				dup_variable_bug(variable_name, &vendor_guid,
						 variable_name_size);
				status = EFI_NOT_FOUND;
				break;
			}

M
Mike Waychison 已提交
2018 2019 2020 2021
			efivar_create_sysfs_entry(efivars,
						  variable_name_size,
						  variable_name,
						  &vendor_guid);
L
Linus Torvalds 已提交
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
			break;
		case EFI_NOT_FOUND:
			break;
		default:
			printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
				status);
			status = EFI_NOT_FOUND;
			break;
		}
	} while (status != EFI_NOT_FOUND);

2033
	error = create_efivars_bin_attributes(efivars);
L
Linus Torvalds 已提交
2034
	if (error)
2035
		unregister_efivars(efivars);
L
Linus Torvalds 已提交
2036

2037 2038
	if (!efivars_pstore_disable)
		efivar_pstore_register(efivars);
2039

2040 2041
	register_filesystem(&efivarfs_type);

2042 2043
out:
	kfree(variable_name);
L
Linus Torvalds 已提交
2044

2045 2046
	return error;
}
2047
EXPORT_SYMBOL_GPL(register_efivars);
L
Linus Torvalds 已提交
2048

2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
/*
 * For now we register the efi subsystem with the firmware subsystem
 * and the vars subsystem with the efi subsystem.  In the future, it
 * might make sense to split off the efi subsystem into its own
 * driver, but for now only efivars will register with it, so just
 * include it here.
 */

static int __init
efivars_init(void)
{
	int error = 0;

	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
	       EFIVARS_DATE);

2065
	if (!efi_enabled(EFI_RUNTIME_SERVICES))
2066
		return 0;
2067 2068 2069 2070 2071 2072 2073 2074

	/* For now we'll register the efi directory at /sys/firmware/efi */
	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
	if (!efi_kobj) {
		printk(KERN_ERR "efivars: Firmware registration failed.\n");
		return -ENOMEM;
	}

2075 2076 2077
	ops.get_variable = efi.get_variable;
	ops.set_variable = efi.set_variable;
	ops.get_next_variable = efi.get_next_variable;
2078
	ops.query_variable_store = efi_query_variable_store;
2079

2080
	error = register_efivars(&__efivars, &ops, efi_kobj);
2081 2082
	if (error)
		goto err_put;
2083 2084 2085 2086 2087 2088 2089

	/* Don't forget the systab entry */
	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
	if (error) {
		printk(KERN_ERR
		       "efivars: Sysfs attribute export failed with error %d.\n",
		       error);
2090
		goto err_unregister;
2091
	}
L
Linus Torvalds 已提交
2092

2093 2094 2095 2096 2097 2098
	return 0;

err_unregister:
	unregister_efivars(&__efivars);
err_put:
	kobject_put(efi_kobj);
L
Linus Torvalds 已提交
2099 2100 2101 2102 2103 2104
	return error;
}

static void __exit
efivars_exit(void)
{
2105 2106
	cancel_work_sync(&efivar_work);

2107
	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
2108 2109 2110
		unregister_efivars(&__efivars);
		kobject_put(efi_kobj);
	}
L
Linus Torvalds 已提交
2111 2112 2113 2114 2115
}

module_init(efivars_init);
module_exit(efivars_exit);