From d5abc7c1050ab2b9556a4bf21626cd74e83cd086 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 3 Feb 2013 19:53:46 +0000 Subject: efi: move utf16 string functions to efi.h There are currently two implementations of the utf16 string functions. Somewhat confusingly, they've got different names. Centralise the functions in efi.h. Reviewed-by: Tom Gundersen Tested-by: Tom Gundersen Reviewed-by: Mike Waychison Signed-off-by: Matt Fleming --- drivers/firmware/google/gsmi.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers/firmware/google') diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c index 91ddf0f..c409a75 100644 --- a/drivers/firmware/google/gsmi.c +++ b/drivers/firmware/google/gsmi.c @@ -288,17 +288,6 @@ static int gsmi_exec(u8 func, u8 sub) return rc; } -/* Return the number of unicode characters in data */ -static size_t -utf16_strlen(efi_char16_t *data, unsigned long maxlength) -{ - unsigned long length = 0; - - while (*data++ != 0 && length < maxlength) - length++; - return length; -} - static efi_status_t gsmi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr, unsigned long *data_size, @@ -311,7 +300,7 @@ static efi_status_t gsmi_get_variable(efi_char16_t *name, }; efi_status_t ret = EFI_SUCCESS; unsigned long flags; - size_t name_len = utf16_strlen(name, GSMI_BUF_SIZE / 2); + size_t name_len = utf16_strnlen(name, GSMI_BUF_SIZE / 2); int rc; if (name_len >= GSMI_BUF_SIZE / 2) @@ -380,7 +369,7 @@ static efi_status_t gsmi_get_next_variable(unsigned long *name_size, return EFI_BAD_BUFFER_SIZE; /* Let's make sure the thing is at least null-terminated */ - if (utf16_strlen(name, GSMI_BUF_SIZE / 2) == GSMI_BUF_SIZE / 2) + if (utf16_strnlen(name, GSMI_BUF_SIZE / 2) == GSMI_BUF_SIZE / 2) return EFI_INVALID_PARAMETER; spin_lock_irqsave(&gsmi_dev.lock, flags); @@ -408,7 +397,7 @@ static efi_status_t gsmi_get_next_variable(unsigned long *name_size, /* Copy the name back */ memcpy(name, gsmi_dev.name_buf->start, GSMI_BUF_SIZE); - *name_size = utf16_strlen(name, GSMI_BUF_SIZE / 2) * 2; + *name_size = utf16_strnlen(name, GSMI_BUF_SIZE / 2) * 2; /* copy guid to return buffer */ memcpy(vendor, ¶m.guid, sizeof(param.guid)); @@ -434,7 +423,7 @@ static efi_status_t gsmi_set_variable(efi_char16_t *name, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, }; - size_t name_len = utf16_strlen(name, GSMI_BUF_SIZE / 2); + size_t name_len = utf16_strnlen(name, GSMI_BUF_SIZE / 2); efi_status_t ret = EFI_SUCCESS; int rc; unsigned long flags; -- cgit v1.1 From e14ab23dde12b80db4c94b684a2e485b72b16af3 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 3 Feb 2013 20:16:40 +0000 Subject: efivars: efivar_entry API There isn't really a formal interface for dealing with EFI variables or struct efivar_entry. Historically, this has led to various bits of code directly accessing the generic EFI variable ops, which inherently ties it to specific EFI variable operations instead of indirectly using whatever ops were registered with register_efivars(). This lead to the efivarfs code only working with the generic EFI variable ops and not CONFIG_GOOGLE_SMI. Encapsulate everything that needs to access '__efivars' inside an efivar_entry_* API and use the new API in the pstore, sysfs and efivarfs code. Much of the efivars code had to be rewritten to use this new API. For instance, it is now up to the users of the API to build the initial list of EFI variables in their efivar_init() callback function. The variable list needs to be passed to efivar_init() which allows us to keep work arounds for things like implementation bugs in GetNextVariable() in a central location. Allowing users of the API to use a callback function to build the list greatly benefits the efivarfs code which needs to allocate inodes and dentries for every variable. It previously did this in a racy way because the code ran without holding the variable spinlock. Both the sysfs and efivarfs code maintain their own lists which means the two interfaces can be running simultaneously without interference, though it should be noted that because no synchronisation is performed it is very easy to create inconsistencies. efibootmgr doesn't currently use efivarfs and users are likely to also require the old sysfs interface, so it makes sense to allow both to be built. Reviewed-by: Tom Gundersen Tested-by: Tom Gundersen Cc: Seiji Aguchi Cc: Matthew Garrett Cc: Jeremy Kerr Cc: Tony Luck Cc: Mike Waychison Signed-off-by: Matt Fleming --- drivers/firmware/google/gsmi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/firmware/google') diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c index c409a75..757b2d9 100644 --- a/drivers/firmware/google/gsmi.c +++ b/drivers/firmware/google/gsmi.c @@ -882,12 +882,19 @@ static __init int gsmi_init(void) goto out_remove_bin_file; } - ret = register_efivars(&efivars, &efivar_ops, gsmi_kobj); + ret = efivars_register(&efivars, &efivar_ops, gsmi_kobj); if (ret) { printk(KERN_INFO "gsmi: Failed to register efivars\n"); goto out_remove_sysfs_files; } + ret = efivars_sysfs_init(); + if (ret) { + printk(KERN_INFO "gsmi: Failed to create efivars files\n"); + efivars_unregister(&efivars); + goto out_remove_sysfs_files; + } + register_reboot_notifier(&gsmi_reboot_notifier); register_die_notifier(&gsmi_die_notifier); atomic_notifier_chain_register(&panic_notifier_list, @@ -919,7 +926,7 @@ static void __exit gsmi_exit(void) unregister_die_notifier(&gsmi_die_notifier); atomic_notifier_chain_unregister(&panic_notifier_list, &gsmi_panic_notifier); - unregister_efivars(&efivars); + efivars_unregister(&efivars); sysfs_remove_files(gsmi_kobj, gsmi_attrs); sysfs_remove_bin_file(gsmi_kobj, &eventlog_bin_attr); -- cgit v1.1