Merge tag 'efi-2019-07-rc5-2' of git://git.denx.de/u-boot-efi
authorTom Rini <trini@konsulko.com>
Sat, 15 Jun 2019 17:03:00 +0000 (13:03 -0400)
committerTom Rini <trini@konsulko.com>
Sat, 15 Jun 2019 17:03:00 +0000 (13:03 -0400)
Pull request for UEFI sub-system for v2019.07-rc5 (2)

This pull request provides bug fixes for the UEFI sub-system. The most
relevant one concerns the allocation of memory at address 0. It is
needed for booting Linux on several boards via bootefi, e.g. the Asus
TinkerBoard.

An undefined reference bug in disk/part.c related to a division is
resolved.

disk/part.c
include/efi_api.h
include/efi_loader.h
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_console.c
lib/efi_loader/efi_memory.c
lib/efi_loader/efi_runtime.c
lib/efi_loader/efi_setup.c
lib/efi_loader/efi_unicode_collation.c
lib/efi_loader/efi_variable.c

index 98cc54db2080b78ed80479dc8c8d3e082f43dcaa..862078f3e7c8a296a1357fa112fe42a119ff2bd5 100644 (file)
@@ -103,17 +103,17 @@ typedef lbaint_t lba512_t;
 #endif
 
 /*
- * Overflowless variant of (block_count * mul_by / div_by)
+ * Overflowless variant of (block_count * mul_by / 2**div_by)
  * when div_by > mul_by
  */
-static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by)
+static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, int div_by)
 {
        lba512_t bc_quot, bc_rem;
 
        /* x * m / d == x / d * m + (x % d) * m / d */
-       bc_quot = block_count / div_by;
-       bc_rem  = block_count - div_by * bc_quot;
-       return bc_quot * mul_by + (bc_rem * mul_by) / div_by;
+       bc_quot = block_count >> div_by;
+       bc_rem  = block_count - (bc_quot << div_by);
+       return bc_quot * mul_by + ((bc_rem * mul_by) >> div_by);
 }
 
 void dev_print (struct blk_desc *dev_desc)
@@ -193,7 +193,7 @@ void dev_print (struct blk_desc *dev_desc)
                lba512 = (lba * (dev_desc->blksz/512));
                /* round to 1 digit */
                /* 2048 = (1024 * 1024) / 512 MB */
-               mb = lba512_muldiv(lba512, 10, 2048);
+               mb = lba512_muldiv(lba512, 10, 11);
 
                mb_quot = mb / 10;
                mb_rem  = mb - (10 * mb_quot);
index 65584dd2d82a235612221b2e3c03f41a1a9f459a..d7d95edd4dfcb0eddded55f269cb65c8b355f82f 100644 (file)
@@ -213,6 +213,21 @@ struct efi_capsule_header {
        u32 capsule_image_size;
 };
 
+#define EFI_RT_SUPPORTED_GET_TIME                      0x0001
+#define EFI_RT_SUPPORTED_SET_TIME                      0x0002
+#define EFI_RT_SUPPORTED_GET_WAKEUP_TIME               0x0004
+#define EFI_RT_SUPPORTED_SET_WAKEUP_TIME               0x0008
+#define EFI_RT_SUPPORTED_GET_VARIABLE                  0x0010
+#define EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME                0x0020
+#define EFI_RT_SUPPORTED_SET_VARIABLE                  0x0040
+#define EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP       0x0080
+#define EFI_RT_SUPPORTED_CONVERT_POINTER               0x0100
+#define EFI_RT_SUPPORTED_GET_NEXT_HIGH_MONOTONIC_COUNT 0x0200
+#define EFI_RT_SUPPORTED_RESET_SYSTEM                  0x0400
+#define EFI_RT_SUPPORTED_UPDATE_CAPSULE                        0x0800
+#define EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES    0x1000
+#define EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO           0x2000
+
 struct efi_runtime_services {
        struct efi_table_hdr hdr;
        efi_status_t (EFIAPI *get_time)(struct efi_time *time,
index f0e1313f9345025b86d74ed7a06cd2f4c4df29d8..b07155cecb7cab8ed91d276cc7381fd55a15cf5c 100644 (file)
@@ -573,6 +573,9 @@ static inline int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2)
 #define __efi_runtime_data __attribute__ ((section (".data.efi_runtime")))
 #define __efi_runtime __attribute__ ((section (".text.efi_runtime")))
 
+/* Indicate supported runtime services */
+efi_status_t efi_init_runtime_supported(void);
+
 /* Update CRC32 in table header */
 void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table);
 
index fa01bbda700b0da243e07c3a0d13d7ec45fe1be3..b26291b919c4729202b104d2a25a543a2b33ba19 100644 (file)
@@ -1779,7 +1779,7 @@ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
        /* Open file */
        f = efi_file_from_path(file_path);
        if (!f)
-               return EFI_DEVICE_ERROR;
+               return EFI_NOT_FOUND;
 
        /* Get file size */
        bs = 0;
@@ -1856,17 +1856,10 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
        EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
                  file_path, source_buffer, source_size, image_handle);
 
-       if (!image_handle || !efi_search_obj(parent_image)) {
-               ret = EFI_INVALID_PARAMETER;
-               goto error;
-       }
-
-       if (!source_buffer && !file_path) {
-               ret = EFI_NOT_FOUND;
-               goto error;
-       }
-       /* The parent image handle must refer to a loaded image */
-       if (!parent_image->type) {
+       if (!image_handle || (!source_buffer && !file_path) ||
+           !efi_search_obj(parent_image) ||
+           /* The parent image handle must refer to a loaded image */
+           !parent_image->type) {
                ret = EFI_INVALID_PARAMETER;
                goto error;
        }
@@ -1940,16 +1933,19 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
                                                  efi_uintn_t map_key)
 {
        struct efi_event *evt;
+       efi_status_t ret = EFI_SUCCESS;
 
        EFI_ENTRY("%p, %zx", image_handle, map_key);
 
        /* Check that the caller has read the current memory map */
-       if (map_key != efi_memory_map_key)
-               return EFI_INVALID_PARAMETER;
+       if (map_key != efi_memory_map_key) {
+               ret = EFI_INVALID_PARAMETER;
+               goto out;
+       }
 
        /* Check if ExitBootServices has already been called */
        if (!systab.boottime)
-               return EFI_EXIT(EFI_SUCCESS);
+               goto out;
 
        /* Stop all timer related activities */
        timers_enabled = false;
@@ -1997,8 +1993,8 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
        /* Give the payload some time to boot */
        efi_set_watchdog(0);
        WATCHDOG_RESET();
-
-       return EFI_EXIT(EFI_SUCCESS);
+out:
+       return EFI_EXIT(ret);
 }
 
 /**
@@ -2870,6 +2866,9 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
        EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
 
        /* Check parameters */
+       if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE)
+               return EFI_EXIT(EFI_INVALID_PARAMETER);
+
        ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
                                         &info, NULL, NULL,
                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL));
index 2fc25e118f2ddb07141b6895326defba89888882..706e6ad31eaee39210cd04b636d53eb9446ace56 100644 (file)
@@ -316,23 +316,6 @@ static efi_status_t EFIAPI efi_cout_query_mode(
        return EFI_EXIT(EFI_SUCCESS);
 }
 
-static efi_status_t EFIAPI efi_cout_set_mode(
-                       struct efi_simple_text_output_protocol *this,
-                       unsigned long mode_number)
-{
-       EFI_ENTRY("%p, %ld", this, mode_number);
-
-
-       if (mode_number > efi_con_mode.max_mode)
-               return EFI_EXIT(EFI_UNSUPPORTED);
-
-       efi_con_mode.mode = mode_number;
-       efi_con_mode.cursor_column = 0;
-       efi_con_mode.cursor_row = 0;
-
-       return EFI_EXIT(EFI_SUCCESS);
-}
-
 static const struct {
        unsigned int fg;
        unsigned int bg;
@@ -358,6 +341,7 @@ static efi_status_t EFIAPI efi_cout_set_attribute(
 
        EFI_ENTRY("%p, %lx", this, attribute);
 
+       efi_con_mode.attribute = attribute;
        if (attribute)
                printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
        else
@@ -378,6 +362,20 @@ static efi_status_t EFIAPI efi_cout_clear_screen(
        return EFI_EXIT(EFI_SUCCESS);
 }
 
+static efi_status_t EFIAPI efi_cout_set_mode(
+                       struct efi_simple_text_output_protocol *this,
+                       unsigned long mode_number)
+{
+       EFI_ENTRY("%p, %ld", this, mode_number);
+
+       if (mode_number >= efi_con_mode.max_mode)
+               return EFI_EXIT(EFI_UNSUPPORTED);
+       efi_con_mode.mode = mode_number;
+       EFI_CALL(efi_cout_clear_screen(this));
+
+       return EFI_EXIT(EFI_SUCCESS);
+}
+
 static efi_status_t EFIAPI efi_cout_reset(
                        struct efi_simple_text_output_protocol *this,
                        char extended_verification)
@@ -387,6 +385,7 @@ static efi_status_t EFIAPI efi_cout_reset(
        /* Clear screen */
        EFI_CALL(efi_cout_clear_screen(this));
        /* Set default colors */
+       efi_con_mode.attribute = 0x07;
        printf(ESC "[0;37;40m");
 
        return EFI_EXIT(EFI_SUCCESS);
index 8d7685123438f05aeffaadc15e7912cfd84f560a..27379381e874c36a671d776b433d05d0c949ae28 100644 (file)
@@ -334,7 +334,6 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
  *
  * Check that the address is within allocated memory:
  *
- * * The address cannot be NULL.
  * * The address must be in a range of the memory map.
  * * The address may not point to EFI_CONVENTIONAL_MEMORY.
  *
@@ -349,8 +348,6 @@ static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated)
 {
        struct efi_mem_list *item;
 
-       if (!addr)
-               return EFI_INVALID_PARAMETER;
        list_for_each_entry(item, &efi_mem, link) {
                u64 start = item->desc.physical_start;
                u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT);
@@ -560,6 +557,9 @@ efi_status_t efi_free_pool(void *buffer)
        efi_status_t ret;
        struct efi_pool_allocation *alloc;
 
+       if (!buffer)
+               return EFI_INVALID_PARAMETER;
+
        ret = efi_check_allocated((uintptr_t)buffer, true);
        if (ret != EFI_SUCCESS)
                return ret;
index 432551d0c8ca6a4ee64984324a0b6f4ffe43377c..40fdc0ea9286945a292d38080dd97a80671bf59d 100644 (file)
@@ -89,6 +89,30 @@ struct elf_rela {
  * handle a good number of runtime callbacks
  */
 
+efi_status_t efi_init_runtime_supported(void)
+{
+       u16 efi_runtime_services_supported = 0;
+
+       /*
+        * This value must be synced with efi_runtime_detach_list
+        * as well as efi_runtime_services.
+        */
+#if CONFIG_IS_ENABLED(ARCH_BCM283X) || \
+    CONFIG_IS_ENABLED(FSL_LAYERSCAPE) || \
+    CONFIG_IS_ENABLED(SYSRESET_X86) || \
+    CONFIG_IS_ENABLED(PSCI_RESET)
+       efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
+#endif
+       efi_runtime_services_supported |=
+                               EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP;
+       return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported",
+                                        &efi_global_variable_guid,
+                                        EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                        EFI_VARIABLE_RUNTIME_ACCESS,
+                                        sizeof(efi_runtime_services_supported),
+                                        &efi_runtime_services_supported));
+}
+
 /**
  * efi_update_table_header_crc32() - Update crc32 in table header
  *
@@ -342,8 +366,7 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
                        struct efi_time *time,
                        struct efi_time_cap *capabilities)
 {
-       /* Nothing we can do */
-       return EFI_DEVICE_ERROR;
+       return EFI_UNSUPPORTED;
 }
 
 /**
index 8691d686d29d02150c50a8ce10c4474498300de8..bfb57836fa9fa22f8183c5330570288abad239f7 100644 (file)
@@ -117,6 +117,11 @@ efi_status_t efi_init_obj_list(void)
        if (ret != EFI_SUCCESS)
                goto out;
 
+       /* Indicate supported runtime services */
+       ret = efi_init_runtime_supported();
+       if (ret != EFI_SUCCESS)
+               goto out;
+
        /* Initialize system table */
        ret = efi_initialize_system_table();
        if (ret != EFI_SUCCESS)
index f293b423975f58f4c67f42c625e56be3ba9d36bd..243c51a8dbe7fffaf87a8f57c0effc8bd5a81b45 100644 (file)
@@ -11,8 +11,8 @@
 #include <cp437.h>
 #include <efi_loader.h>
 
-/* Characters that may not be used in file names */
-static const char illegal[] = "<>:\"/\\|?*\x7f";
+/* Characters that may not be used in FAT 8.3 file names */
+static const char illegal[] = "+,<=>:;\"/\\|?*[]\x7f";
 
 /*
  * EDK2 assumes codepage 1250 when creating FAT 8.3 file names.
@@ -73,11 +73,22 @@ out:
        return ret;
 }
 
+/**
+ * next_lower() - get next codepoint converted to lower case
+ *
+ * @string:    pointer to u16 string, on return advanced by one codepoint
+ * Return:     first codepoint of string converted to lower case
+ */
+static s32 next_lower(const u16 **string)
+{
+       return utf_to_lower(utf16_get(string));
+}
+
 /**
  * metai_match() - compare utf-16 string with a pattern string case-insenitively
  *
- * @s:         string to compare
- * @p:         pattern string
+ * @string:    string to compare
+ * @pattern:   pattern string
  *
  * The pattern string may use these:
  *     - * matches >= 0 characters
@@ -93,61 +104,67 @@ out:
  *
  * Return:     true if the string is matched.
  */
-static bool metai_match(const u16 *s, const u16 *p)
+static bool metai_match(const u16 *string, const u16 *pattern)
 {
-       u16 first;
+       s32 first, s, p;
+
+       for (; *string && *pattern;) {
+               const u16 *string_old = string;
+
+               s = next_lower(&string);
+               p = next_lower(&pattern);
 
-       for (; *s && *p; ++s, ++p) {
-               switch (*p) {
+               switch (p) {
                case '*':
                        /* Match 0 or more characters */
-                       ++p;
-                       for (;; ++s) {
-                               if (metai_match(s, p))
+                       for (;; s = next_lower(&string)) {
+                               if (metai_match(string_old, pattern))
                                        return true;
-                               if (!*s)
+                               if (!s)
                                        return false;
+                               string_old = string;
                        }
                case '?':
                        /* Match any one character */
                        break;
                case '[':
                        /* Match any character in the set */
-                       ++p;
-                       first = *p;
+                       p = next_lower(&pattern);
+                       first = p;
                        if (first == ']')
                                /* Empty set */
                                return false;
-                       ++p;
-                       if (*p == '-') {
+                       p = next_lower(&pattern);
+                       if (p == '-') {
                                /* Range */
-                               ++p;
-                               if (*s < first || *s > *p)
+                               p = next_lower(&pattern);
+                               if (s < first || s > p)
                                        return false;
-                               ++p;
-                               if (*p != ']')
+                               p = next_lower(&pattern);
+                               if (p != ']')
                                        return false;
                        } else {
                                /* Set */
                                bool hit = false;
 
-                               if (*s == first)
+                               if (s == first)
                                        hit = true;
-                               for (; *p && *p != ']'; ++p) {
-                                       if (*p == *s)
+                               for (; p && p != ']';
+                                    p = next_lower(&pattern)) {
+                                       if (p == s)
                                                hit = true;
                                }
-                               if (!hit || *p != ']')
+                               if (!hit || p != ']')
                                        return false;
                        }
                        break;
                default:
                        /* Match one character */
-                       if (*p != *s)
+                       if (p != s)
                                return false;
                }
        }
-       if (!*p && !*s)
+       if (!*pattern && !*string)
                return true;
        return false;
 }
index e56053194daec46642103607904e85ed4f37aa3c..1d1b23b0e550ec2961e6ce31b1e6d446ecbff2d5 100644 (file)
@@ -430,7 +430,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
                  data_size, data);
 
        /* TODO: implement APPEND_WRITE */
-       if (!variable_name || !vendor ||
+       if (!variable_name || !*variable_name || !vendor ||
+           ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
+            !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
            (attributes & EFI_VARIABLE_APPEND_WRITE)) {
                ret = EFI_INVALID_PARAMETER;
                goto out;