Turning an EFI varfs filename into its components will be useful for the EFI loader as well, so factor that out. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- common/efi/Makefile | 2 +- common/efi/efivar-filename.c | 116 +++++++++++++++++++++++++++++++++++ fs/efivarfs.c | 76 ----------------------- include/efi/efi-util.h | 4 ++ 4 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 common/efi/efivar-filename.c diff --git a/common/efi/Makefile b/common/efi/Makefile index ed110f5a6899..a7cebde4f1b3 100644 --- a/common/efi/Makefile +++ b/common/efi/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_EFI_BOOTUP) += payload/ obj-$(CONFIG_EFI_GUID) += guid.o obj-$(CONFIG_EFI_DEVICEPATH) += devicepath.o -obj-y += errno.o +obj-y += errno.o efivar-filename.o diff --git a/common/efi/efivar-filename.c b/common/efi/efivar-filename.c new file mode 100644 index 000000000000..51d0130fa774 --- /dev/null +++ b/common/efi/efivar-filename.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/ctype.h> +#include <string.h> +#include <efi/efi-util.h> + +static int char_to_nibble(char c) +{ + int ret = tolower(c); + + return ret <= '9' ? ret - '0' : ret - 'a' + 10; +} + +static int read_byte_str(const char *str, u8 *out) +{ + if (!isxdigit(*str) || !isxdigit(*(str + 1))) + return -EINVAL; + + *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1)); + + return 0; +} + +static int efi_guid_parse(const char *str, efi_guid_t *guid) +{ + int i, ret; + u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; + + for (i = 0; i < 16; i++) { + ret = read_byte_str(str, &guid->b[idx[i]]); + if (ret) + return ret; + str += 2; + + switch (i) { + case 3: + case 5: + case 7: + case 9: + if (*str != '-') + return -EINVAL; + str++; + break; + } + } + + return 0; +} + + +int __efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, + s16 *name, size_t *namelen) +{ + int len, ret; + const char *guidstr; + int i; + + len = strlen(filename); + + if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) + return -EINVAL; + + guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + if (*guidstr != '-' || guidstr == filename) + return -EINVAL; + + guidstr++; + + ret = efi_guid_parse(guidstr, vendor); + if (ret) + return ret; + + if (guidstr - filename > *namelen) + ret = -EFBIG; + + *namelen = guidstr - filename; + + if (ret) + return ret; + + for (i = 0; i < *namelen - 1; i++) + name[i] = filename[i]; + + name[i] = L'\0'; + + return 0; +} + +int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, + s16 **name) +{ + int ret; + s16 *varname; + size_t namelen = 0; + int i; + + if (*filename == '/') + filename++; + + ret = __efivarfs_parse_filename(filename, vendor, NULL, &namelen); + if (ret != -EFBIG) + return ret; + + varname = xzalloc(namelen * sizeof(s16)); + + for (i = 0; i < namelen - 1; i++) + varname[i] = filename[i]; + + varname[i] = L'\0'; + + *name = varname; + + return 0; +} + + diff --git a/fs/efivarfs.c b/fs/efivarfs.c index 01947439ff6c..2e72bb885265 100644 --- a/fs/efivarfs.c +++ b/fs/efivarfs.c @@ -47,82 +47,6 @@ struct efivarfs_priv { struct list_head inodes; }; -static int char_to_nibble(char c) -{ - int ret = tolower(c); - - return ret <= '9' ? ret - '0' : ret - 'a' + 10; -} - -static int read_byte_str(const char *str, u8 *out) -{ - if (!isxdigit(*str) || !isxdigit(*(str + 1))) - return -EINVAL; - - *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1)); - - return 0; -} - -static int efi_guid_parse(const char *str, efi_guid_t *guid) -{ - int i, ret; - u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; - - for (i = 0; i < 16; i++) { - ret = read_byte_str(str, &guid->b[idx[i]]); - if (ret) - return ret; - str += 2; - - switch (i) { - case 3: - case 5: - case 7: - case 9: - if (*str != '-') - return -EINVAL; - str++; - break; - } - } - - return 0; -} - -static int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name) -{ - int len, ret; - const char *guidstr; - s16 *varname; - int i; - - if (*filename == '/') - filename++; - - len = strlen(filename); - - if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) - return -EINVAL; - - guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); - if (*guidstr != '-') - return -EINVAL; - - guidstr++; - - ret = efi_guid_parse(guidstr, vendor); - - varname = xzalloc((guidstr - filename) * sizeof(s16)); - - for (i = 0; i < guidstr - filename - 1; i++) - varname[i] = filename[i]; - - *name = varname; - - return 0; -} - static int efivars_create(struct device_d *dev, const char *pathname, mode_t mode) { struct efivarfs_priv *priv = dev->priv; diff --git a/include/efi/efi-util.h b/include/efi/efi-util.h index 0645af270769..78e352456ad1 100644 --- a/include/efi/efi-util.h +++ b/include/efi/efi-util.h @@ -7,4 +7,8 @@ const char *efi_strerror(efi_status_t err); int efi_errno(efi_status_t err); +int __efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, + s16 *name, size_t *namelen); +int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name); + #endif -- 2.30.2 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox