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>
14 #include <linux/uuid.h>
18 struct inode
*efivarfs_get_inode(struct super_block
*sb
,
19 const struct inode
*dir
, int mode
,
20 dev_t dev
, bool is_removable
)
22 struct inode
*inode
= new_inode(sb
);
25 inode
->i_ino
= get_next_ino();
27 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= current_time(inode
);
28 inode
->i_flags
= is_removable
? 0 : S_IMMUTABLE
;
29 switch (mode
& S_IFMT
) {
31 inode
->i_fop
= &efivarfs_file_operations
;
34 inode
->i_op
= &efivarfs_dir_inode_operations
;
35 inode
->i_fop
= &simple_dir_operations
;
44 * Return true if 'str' is a valid efivarfs filename of the form,
46 * VariableName-12345678-1234-1234-1234-1234567891bc
48 bool efivarfs_valid_name(const char *str
, int len
)
50 const char *s
= str
+ len
- EFI_VARIABLE_GUID_LEN
;
53 * We need a GUID, plus at least one letter for the variable name,
54 * plus the '-' separator
56 if (len
< EFI_VARIABLE_GUID_LEN
+ 2)
59 /* GUID must be preceded by a '-' */
64 * Validate that 's' is of the correct format, e.g.
66 * 12345678-1234-1234-1234-123456789abc
68 return uuid_is_valid(s
);
71 static int efivarfs_create(struct inode
*dir
, struct dentry
*dentry
,
72 umode_t mode
, bool excl
)
74 struct inode
*inode
= NULL
;
75 struct efivar_entry
*var
;
76 int namelen
, i
= 0, err
= 0;
77 bool is_removable
= false;
79 if (!efivarfs_valid_name(dentry
->d_name
.name
, dentry
->d_name
.len
))
82 var
= kzalloc(sizeof(struct efivar_entry
), GFP_KERNEL
);
86 /* length of the variable name itself: remove GUID and separator */
87 namelen
= dentry
->d_name
.len
- EFI_VARIABLE_GUID_LEN
- 1;
89 uuid_le_to_bin(dentry
->d_name
.name
+ namelen
+ 1, &var
->var
.VendorGuid
);
91 if (efivar_variable_is_removable(var
->var
.VendorGuid
,
92 dentry
->d_name
.name
, namelen
))
95 inode
= efivarfs_get_inode(dir
->i_sb
, dir
, mode
, 0, is_removable
);
101 for (i
= 0; i
< namelen
; i
++)
102 var
->var
.VariableName
[i
] = dentry
->d_name
.name
[i
];
104 var
->var
.VariableName
[i
] = '\0';
106 inode
->i_private
= var
;
108 err
= efivar_entry_add(var
, &efivarfs_list
);
112 d_instantiate(dentry
, inode
);
123 static int efivarfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
125 struct efivar_entry
*var
= d_inode(dentry
)->i_private
;
127 if (efivar_entry_delete(var
))
130 drop_nlink(d_inode(dentry
));
135 const struct inode_operations efivarfs_dir_inode_operations
= {
136 .lookup
= simple_lookup
,
137 .unlink
= efivarfs_unlink
,
138 .create
= efivarfs_create
,