summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disk/part.c12
-rw-r--r--include/efi_api.h15
-rw-r--r--include/efi_loader.h3
-rw-r--r--lib/efi_loader/efi_boottime.c33
-rw-r--r--lib/efi_loader/efi_console.c33
-rw-r--r--lib/efi_loader/efi_memory.c6
-rw-r--r--lib/efi_loader/efi_runtime.c27
-rw-r--r--lib/efi_loader/efi_setup.c5
-rw-r--r--lib/efi_loader/efi_unicode_collation.c69
-rw-r--r--lib/efi_loader/efi_variable.c4
10 files changed, 135 insertions, 72 deletions
diff --git a/disk/part.c b/disk/part.c
index 98cc54db20..862078f3e7 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -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);
diff --git a/include/efi_api.h b/include/efi_api.h
index 65584dd2d8..d7d95edd4d 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -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,
diff --git a/include/efi_loader.h b/include/efi_loader.h
index f0e1313f93..b07155cecb 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -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);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index fa01bbda70..b26291b919 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -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));
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 2fc25e118f..706e6ad31e 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -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);
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 8d76851234..27379381e8 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -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;
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 432551d0c8..40fdc0ea92 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -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;
}
/**
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 8691d686d2..bfb57836fa 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -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)
diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c
index f293b42397..243c51a8db 100644
--- a/lib/efi_loader/efi_unicode_collation.c
+++ b/lib/efi_loader/efi_unicode_collation.c
@@ -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.
@@ -74,10 +74,21 @@ out:
}
/**
+ * 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;
}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index e56053194d..1d1b23b0e5 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -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;