summaryrefslogtreecommitdiff
path: root/drivers/firmware
diff options
context:
space:
mode:
authorRoy Franz <roy.franz@linaro.org>2013-09-23 02:45:33 +0400
committerMatt Fleming <matt.fleming@intel.com>2013-09-25 15:34:38 +0400
commit5fef3870c572a30f9def07c4ded69dc37a9cf5d9 (patch)
tree08fc883ebc4a51e1dc9ff07ed46d0566d2600f3b /drivers/firmware
parent4a9f3a7c336a6b0ffeef2523bef93e67b0921163 (diff)
downloadlinux-5fef3870c572a30f9def07c4ded69dc37a9cf5d9.tar.xz
efi: Move unicode to ASCII conversion to shared function.
Move the open-coded conversion to a shared function for use by all architectures. Change the allocation to prefer a high address for ARM, as this is required to avoid conflicts with reserved regions in low memory. We don't know the specifics of these regions until after we process the command line and device tree. Signed-off-by: Roy Franz <roy.franz@linaro.org> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/efi-stub-helper.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index 361e24d8d665..96665b730c51 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -554,3 +554,64 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
return status;
}
+
+/*
+ * Convert the unicode UEFI command line to ASCII to pass to kernel.
+ * Size of memory allocated return in *cmd_line_len.
+ * Returns NULL on error.
+ */
+static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg,
+ efi_loaded_image_t *image,
+ int *cmd_line_len)
+{
+ u16 *s2;
+ u8 *s1 = NULL;
+ unsigned long cmdline_addr = 0;
+ int load_options_size = image->load_options_size / 2; /* ASCII */
+ void *options = image->load_options;
+ int options_size = 0;
+ efi_status_t status;
+ int i;
+ u16 zero = 0;
+
+ if (options) {
+ s2 = options;
+ while (*s2 && *s2 != '\n' && options_size < load_options_size) {
+ s2++;
+ options_size++;
+ }
+ }
+
+ if (options_size == 0) {
+ /* No command line options, so return empty string*/
+ options_size = 1;
+ options = &zero;
+ }
+
+ options_size++; /* NUL termination */
+#ifdef CONFIG_ARM
+ /*
+ * For ARM, allocate at a high address to avoid reserved
+ * regions at low addresses that we don't know the specfics of
+ * at the time we are processing the command line.
+ */
+ status = efi_high_alloc(sys_table_arg, options_size, 0,
+ &cmdline_addr, 0xfffff000);
+#else
+ status = efi_low_alloc(sys_table_arg, options_size, 0,
+ &cmdline_addr);
+#endif
+ if (status != EFI_SUCCESS)
+ return NULL;
+
+ s1 = (u8 *)cmdline_addr;
+ s2 = (u16 *)options;
+
+ for (i = 0; i < options_size - 1; i++)
+ *s1++ = *s2++;
+
+ *s1 = '\0';
+
+ *cmd_line_len = options_size;
+ return (char *)cmdline_addr;
+}