2 * Copyright (C) 2012 Red Hat, Inc.
3 * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/efi.h>
12 #include <linux/ctype.h>
13 #include <linux/slab.h>
17 struct inode
*efivarfs_get_inode(struct super_block
*sb
,
18 const struct inode
*dir
, int mode
, dev_t dev
)
20 struct inode
*inode
= new_inode(sb
);
23 inode
->i_ino
= get_next_ino();
25 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
26 switch (mode
& S_IFMT
) {
28 inode
->i_fop
= &efivarfs_file_operations
;
31 inode
->i_op
= &efivarfs_dir_inode_operations
;
32 inode
->i_fop
= &simple_dir_operations
;
41 * Return true if 'str' is a valid efivarfs filename of the form,
43 * VariableName-12345678-1234-1234-1234-1234567891bc
45 bool efivarfs_valid_name(const char *str
, int len
)
47 static const char dashes
[EFI_VARIABLE_GUID_LEN
] = {
48 [8] = 1, [13] = 1, [18] = 1, [23] = 1
50 const char *s
= str
+ len
- EFI_VARIABLE_GUID_LEN
;
54 * We need a GUID, plus at least one letter for the variable name,
55 * plus the '-' separator
57 if (len
< EFI_VARIABLE_GUID_LEN
+ 2)
60 /* GUID must be preceded by a '-' */
65 * Validate that 's' is of the correct format, e.g.
67 * 12345678-1234-1234-1234-123456789abc
69 for (i
= 0; i
< EFI_VARIABLE_GUID_LEN
; i
++) {
82 static void efivarfs_hex_to_guid(const char *str
, efi_guid_t
*guid
)
84 guid
->b
[0] = hex_to_bin(str
[6]) << 4 | hex_to_bin(str
[7]);
85 guid
->b
[1] = hex_to_bin(str
[4]) << 4 | hex_to_bin(str
[5]);
86 guid
->b
[2] = hex_to_bin(str
[2]) << 4 | hex_to_bin(str
[3]);
87 guid
->b
[3] = hex_to_bin(str
[0]) << 4 | hex_to_bin(str
[1]);
88 guid
->b
[4] = hex_to_bin(str
[11]) << 4 | hex_to_bin(str
[12]);
89 guid
->b
[5] = hex_to_bin(str
[9]) << 4 | hex_to_bin(str
[10]);
90 guid
->b
[6] = hex_to_bin(str
[16]) << 4 | hex_to_bin(str
[17]);
91 guid
->b
[7] = hex_to_bin(str
[14]) << 4 | hex_to_bin(str
[15]);
92 guid
->b
[8] = hex_to_bin(str
[19]) << 4 | hex_to_bin(str
[20]);
93 guid
->b
[9] = hex_to_bin(str
[21]) << 4 | hex_to_bin(str
[22]);
94 guid
->b
[10] = hex_to_bin(str
[24]) << 4 | hex_to_bin(str
[25]);
95 guid
->b
[11] = hex_to_bin(str
[26]) << 4 | hex_to_bin(str
[27]);
96 guid
->b
[12] = hex_to_bin(str
[28]) << 4 | hex_to_bin(str
[29]);
97 guid
->b
[13] = hex_to_bin(str
[30]) << 4 | hex_to_bin(str
[31]);
98 guid
->b
[14] = hex_to_bin(str
[32]) << 4 | hex_to_bin(str
[33]);
99 guid
->b
[15] = hex_to_bin(str
[34]) << 4 | hex_to_bin(str
[35]);
102 static int efivarfs_create(struct inode
*dir
, struct dentry
*dentry
,
103 umode_t mode
, bool excl
)
106 struct efivar_entry
*var
;
107 int namelen
, i
= 0, err
= 0;
109 if (!efivarfs_valid_name(dentry
->d_name
.name
, dentry
->d_name
.len
))
112 inode
= efivarfs_get_inode(dir
->i_sb
, dir
, mode
, 0);
116 var
= kzalloc(sizeof(struct efivar_entry
), GFP_KERNEL
);
122 /* length of the variable name itself: remove GUID and separator */
123 namelen
= dentry
->d_name
.len
- EFI_VARIABLE_GUID_LEN
- 1;
125 efivarfs_hex_to_guid(dentry
->d_name
.name
+ namelen
+ 1,
126 &var
->var
.VendorGuid
);
128 for (i
= 0; i
< namelen
; i
++)
129 var
->var
.VariableName
[i
] = dentry
->d_name
.name
[i
];
131 var
->var
.VariableName
[i
] = '\0';
133 inode
->i_private
= var
;
135 efivar_entry_add(var
, &efivarfs_list
);
136 d_instantiate(dentry
, inode
);
146 static int efivarfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
148 struct efivar_entry
*var
= dentry
->d_inode
->i_private
;
150 if (efivar_entry_delete(var
))
153 drop_nlink(dentry
->d_inode
);
159 * Handle negative dentry.
161 static struct dentry
*efivarfs_lookup(struct inode
*dir
, struct dentry
*dentry
,
164 if (dentry
->d_name
.len
> NAME_MAX
)
165 return ERR_PTR(-ENAMETOOLONG
);
170 const struct inode_operations efivarfs_dir_inode_operations
= {
171 .lookup
= efivarfs_lookup
,
172 .unlink
= efivarfs_unlink
,
173 .create
= efivarfs_create
,