⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efivars.c

📁 对于那些带有区码限制的DVD光驱
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 */#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/sched.h>		/* for capable() */#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>#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);/* * efivars_lock protects two things: * 1) efivar_list - adds, removals, reads, writes * 2) efi.[gs]et_variable() calls. * It must not be held when creating sysfs entries or calling kmalloc. * efi.get_next_variable() is only called from efivars_init(), * which is protected by the BKL, so that path is safe. */static DEFINE_SPINLOCK(efivars_lock);static LIST_HEAD(efivar_list);/* * 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 {	struct efi_variable var;	struct list_head list;	struct kobject kobj;};#define get_efivar_entry(n) list_entry(n, struct efivar_entry, list)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);};#define EFI_ATTR(_name, _mode, _show, _store) \struct subsys_attribute efi_attr_##_name = { \	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \	.show = _show, \	.store = _store, \};#define EFIVAR_ATTR(_name, _mode, _show, _store) \struct efivar_attribute efivar_attr_##_name = { \	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \	.show = _show, \	.store = _store, \};#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \struct subsys_attribute var_subsys_attr_##_name = { \	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \	.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 intefivar_create_sysfs_entry(unsigned long variable_name_size,				efi_char16_t *variable_name,				efi_guid_t *vendor_guid);/* Return the number of unicode characters in data */static unsigned longutf8_strlen(efi_char16_t *data, unsigned long maxlength){	unsigned long length = 0;	while (*data++ != 0 && length < maxlength)		length++;	return length;}/* * Return the number of bytes is the length of this string * Note: this is NOT the same as the number of unicode characters */static inline unsigned longutf8_strsize(efi_char16_t *data, unsigned long maxlength){	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);}static efi_status_tget_var_data(struct efi_variable *var){	efi_status_t status;	spin_lock(&efivars_lock);	var->DataSize = 1024;	status = efi.get_variable(var->VariableName,				&var->VendorGuid,				&var->Attributes,				&var->DataSize,				var->Data);	spin_unlock(&efivars_lock);	if (status != EFI_SUCCESS) {		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",			status);	}	return status;}static ssize_tefivar_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_tefivar_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;	status = get_var_data(var);	if (status != EFI_SUCCESS)		return -EIO;	if (var->Attributes & 0x1)		str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");	if (var->Attributes & 0x2)		str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");	if (var->Attributes & 0x4)		str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");	return str - buf;}static ssize_tefivar_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;	status = get_var_data(var);	if (status != EFI_SUCCESS)		return -EIO;	str += sprintf(str, "0x%lx\n", var->DataSize);	return str - buf;}static ssize_tefivar_data_read(struct efivar_entry *entry, char *buf){	struct efi_variable *var = &entry->var;	efi_status_t status;	if (!entry || !buf)		return -EINVAL;	status = get_var_data(var);	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_tefivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count){	struct efi_variable *new_var, *var = &entry->var;	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;	}	spin_lock(&efivars_lock);	status = efi.set_variable(new_var->VariableName,					&new_var->VendorGuid,					new_var->Attributes,					new_var->DataSize,					new_var->Data);	spin_unlock(&efivars_lock);	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_tefivar_show_raw(struct efivar_entry *entry, char *buf){	struct efi_variable *var = &entry->var;	efi_status_t status;	if (!entry || !buf)		return 0;	status = get_var_data(var);	if (status != EFI_SUCCESS)		return -EIO;	memcpy(buf, var, sizeof(*var));	return sizeof(*var);}/* * Generic read/write functions that call the specific functions of * the atttributes... */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);	ssize_t ret = -EIO;	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);	ssize_t ret = -EIO;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (efivar_attr->store)		ret = efivar_attr->store(var, buf, count);	return ret;}static struct sysfs_ops efivar_attr_ops = {	.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);	spin_lock(&efivars_lock);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -