summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile1
-rw-r--r--lib/date.c6
-rw-r--r--lib/efi_loader/efi_capsule.c66
-rw-r--r--lib/efi_loader/efi_file.c15
-rw-r--r--lib/rtc-lib.c77
-rw-r--r--lib/tpm-common.c5
-rw-r--r--lib/vsprintf.c22
7 files changed, 139 insertions, 53 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 881034f4ae3..d8055d36d6e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -135,6 +135,7 @@ obj-$(CONFIG_SSCANF) += sscanf.o
endif
obj-y += date.o
+obj-y += rtc-lib.o
obj-$(CONFIG_LIB_ELF) += elf.o
#
diff --git a/lib/date.c b/lib/date.c
index 0456de78ab1..c589d9ed3a2 100644
--- a/lib/date.c
+++ b/lib/date.c
@@ -10,8 +10,6 @@
#include <rtc.h>
#include <linux/time.h>
-#if defined(CONFIG_LIB_DATE) || defined(CONFIG_TIMESTAMP)
-
#define FEBRUARY 2
#define STARTOFTIME 1970
#define SECDAY 86400L
@@ -97,9 +95,6 @@ unsigned long rtc_mktime(const struct rtc_time *tm)
return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec;
}
-#endif /* CONFIG_LIB_DATE || CONFIG_TIMESTAMP */
-
-#ifdef CONFIG_LIB_DATE
/* for compatibility with linux code */
time64_t mktime64(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
@@ -116,4 +111,3 @@ time64_t mktime64(const unsigned int year, const unsigned int mon,
return (time64_t)rtc_mktime((const struct rtc_time *)&time);
}
-#endif
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 50bed32bfb3..b878e71438b 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -6,6 +6,8 @@
* Author: AKASHI Takahiro
*/
+#define LOG_CATEGORY LOGC_EFI
+
#include <common.h>
#include <efi_loader.h>
#include <efi_variable.h>
@@ -95,13 +97,25 @@ void set_capsule_result(int index, struct efi_capsule_header *capsule,
else
memset(&result.capsule_processed, 0, sizeof(time));
result.capsule_status = return_status;
- ret = efi_set_variable(variable_name16, &efi_guid_capsule_report,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof(result), &result);
- if (ret)
- log_err("EFI: creating %ls failed\n", variable_name16);
+ ret = efi_set_variable_int(variable_name16, &efi_guid_capsule_report,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(result), &result, false);
+ if (ret != EFI_SUCCESS) {
+ log_err("Setting %ls failed\n", variable_name16);
+ return;
+ }
+
+ /* Variable CapsuleLast must not include terminating 0x0000 */
+ ret = efi_set_variable_int(L"CapsuleLast", &efi_guid_capsule_report,
+ EFI_VARIABLE_READ_ONLY |
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 22, variable_name16, false);
+ if (ret != EFI_SUCCESS)
+ log_err("Setting %ls failed\n", L"CapsuleLast");
}
#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT
@@ -361,7 +375,7 @@ static efi_status_t efi_capsule_update_firmware(
/* sanity check */
if ((capsule->item_offset_list[item] + sizeof(*image)
>= capsule_size)) {
- log_err("EFI: A capsule has not enough data\n");
+ log_err("Capsule does not have enough data\n");
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -379,7 +393,7 @@ static efi_status_t efi_capsule_update_firmware(
image->update_hardware_instance,
handles, no_handles);
if (!fmp) {
- log_err("EFI Capsule: driver not found for firmware type: %pUl, hardware instance: %lld\n",
+ log_err("FMP driver not found for firmware type %pUl, hardware instance %lld\n",
&image->update_image_type_id,
image->update_hardware_instance);
ret = EFI_UNSUPPORTED;
@@ -397,7 +411,7 @@ static efi_status_t efi_capsule_update_firmware(
vendor_code, NULL,
&abort_reason));
if (ret != EFI_SUCCESS) {
- log_err("EFI Capsule: firmware update failed: %ls\n",
+ log_err("Firmware update failed: %ls\n",
abort_reason);
efi_free_pool(abort_reason);
goto out;
@@ -453,7 +467,7 @@ efi_status_t EFIAPI efi_update_capsule(
/* sanity check */
if (capsule->header_size < sizeof(*capsule) ||
capsule->capsule_image_size < sizeof(*capsule)) {
- log_err("EFI: A capsule has not enough data\n");
+ log_err("Capsule does not have enough data\n");
continue;
}
@@ -463,7 +477,7 @@ efi_status_t EFIAPI efi_update_capsule(
&efi_guid_firmware_management_capsule_id)) {
ret = efi_capsule_update_firmware(capsule);
} else {
- log_err("EFI: not support capsule type: %pUl\n",
+ log_err("Unsupported capsule type: %pUl\n",
&capsule->capsule_guid);
ret = EFI_UNSUPPORTED;
}
@@ -476,7 +490,7 @@ efi_status_t EFIAPI efi_update_capsule(
/* Rebuild the ESRT to reflect any updated FW images. */
ret = efi_esrt_populate();
if (ret != EFI_SUCCESS)
- log_warning("EFI Capsule: failed to update ESRT\n");
+ log_warning("ESRT update failed\n");
}
out:
@@ -632,7 +646,7 @@ static efi_status_t find_boot_device(void)
ret = get_dp_device(boot_var16, &boot_dev);
if (ret == EFI_SUCCESS) {
if (device_is_present_and_system_part(boot_dev)) {
- goto out;
+ goto found;
} else {
efi_free_pool(boot_dev);
boot_dev = NULL;
@@ -675,11 +689,12 @@ skip:
efi_free_pool(boot_dev);
boot_dev = NULL;
}
+found:
if (boot_dev) {
u16 *path_str;
path_str = efi_dp_str(boot_dev);
- log_debug("EFI Capsule: bootdev is %ls\n", path_str);
+ log_debug("Boot device %ls\n", path_str);
efi_free_pool(path_str);
volume = efi_fs_from_path(boot_dev);
@@ -720,7 +735,7 @@ static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
ret = find_boot_device();
if (ret == EFI_NOT_FOUND) {
- log_debug("EFI Capsule: bootdev is not set\n");
+ log_debug("Boot device is not set\n");
*num = 0;
return EFI_SUCCESS;
} else if (ret != EFI_SUCCESS) {
@@ -988,7 +1003,6 @@ efi_status_t efi_launch_capsules(void)
struct efi_capsule_header *capsule = NULL;
u16 **files;
unsigned int nfiles, index, i;
- u16 variable_name16[12];
efi_status_t ret;
if (!check_run_capsules())
@@ -1011,19 +1025,19 @@ efi_status_t efi_launch_capsules(void)
/* Launch capsules */
for (i = 0, ++index; i < nfiles; i++, index++) {
- log_debug("capsule from %ls ...\n", files[i]);
+ log_debug("Applying %ls\n", files[i]);
if (index > 0xffff)
index = 0;
ret = efi_capsule_read_file(files[i], &capsule);
if (ret == EFI_SUCCESS) {
ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0));
if (ret != EFI_SUCCESS)
- log_err("EFI Capsule update failed at %ls\n",
+ log_err("Applying capsule %ls failed\n",
files[i]);
free(capsule);
} else {
- log_err("EFI: reading capsule failed: %ls\n", files[i]);
+ log_err("Reading capsule %ls failed\n", files[i]);
}
/* create CapsuleXXXX */
set_capsule_result(index, capsule, ret);
@@ -1031,7 +1045,7 @@ efi_status_t efi_launch_capsules(void)
/* delete a capsule either in case of success or failure */
ret = efi_capsule_delete_file(files[i]);
if (ret != EFI_SUCCESS)
- log_err("EFI: deleting a capsule file failed: %ls\n",
+ log_err("Deleting capsule %ls failed\n",
files[i]);
}
efi_capsule_scan_done();
@@ -1040,16 +1054,6 @@ efi_status_t efi_launch_capsules(void)
free(files[i]);
free(files);
- /* CapsuleLast */
- efi_create_indexed_name(variable_name16, sizeof(variable_name16),
- "Capsule", index - 1);
- efi_set_variable_int(L"CapsuleLast", &efi_guid_capsule_report,
- EFI_VARIABLE_READ_ONLY |
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 22, variable_name16, false);
-
return ret;
}
#endif /* CONFIG_EFI_CAPSULE_ON_DISK */
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 6b3f5962be2..6299fcbbf4e 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -480,6 +480,17 @@ static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
return EFI_SUCCESS;
}
+static void rtc2efi(struct efi_time *time, struct rtc_time *tm)
+{
+ memset(time, 0, sizeof(struct efi_time));
+ time->year = tm->tm_year;
+ time->month = tm->tm_mon;
+ time->day = tm->tm_mday;
+ time->hour = tm->tm_hour;
+ time->minute = tm->tm_min;
+ time->second = tm->tm_sec;
+}
+
static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
void *buffer)
{
@@ -535,6 +546,10 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
info->size = required_size;
info->file_size = dent->size;
info->physical_size = dent->size;
+ info->attribute = dent->attr;
+ rtc2efi(&info->create_time, &dent->create_time);
+ rtc2efi(&info->modification_time, &dent->change_time);
+ rtc2efi(&info->last_access_time, &dent->access_time);
if (dent->type == FS_DT_DIR)
info->attribute |= EFI_FILE_DIRECTORY;
diff --git a/lib/rtc-lib.c b/lib/rtc-lib.c
new file mode 100644
index 00000000000..1f7bdade298
--- /dev/null
+++ b/lib/rtc-lib.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rtc and date/time utility functions
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * U-Boot rtc_time differs from Linux rtc_time:
+ * - The year field takes the actual value, not year - 1900.
+ * - January is month 1.
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <linux/math64.h>
+
+static const unsigned char rtc_days_in_month[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+
+/*
+ * The number of days in the month.
+ */
+int rtc_month_days(unsigned int month, unsigned int year)
+{
+ return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
+}
+
+/*
+ * rtc_to_tm - Converts u64 to rtc_time.
+ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+ *
+ * This function is copied from rtc_time64_to_tm() in the Linux kernel.
+ * But in U-Boot January is month 1 and we do not subtract 1900 from the year.
+ */
+void rtc_to_tm(u64 time, struct rtc_time *tm)
+{
+ unsigned int month, year, secs;
+ int days;
+
+ days = div_u64_rem(time, 86400, &secs);
+
+ /* day of the week, 1970-01-01 was a Thursday */
+ tm->tm_wday = (days + 4) % 7;
+
+ year = 1970 + days / 365;
+ days -= (year - 1970) * 365
+ + LEAPS_THRU_END_OF(year - 1)
+ - LEAPS_THRU_END_OF(1970 - 1);
+ while (days < 0) {
+ year -= 1;
+ days += 365 + is_leap_year(year);
+ }
+ tm->tm_year = year; /* Not year - 1900 */
+ tm->tm_yday = days + 1;
+
+ for (month = 0; month < 11; month++) {
+ int newdays;
+
+ newdays = days - rtc_month_days(month, year);
+ if (newdays < 0)
+ break;
+ days = newdays;
+ }
+ tm->tm_mon = month + 1; /* January = 1 */
+ tm->tm_mday = days + 1;
+
+ tm->tm_hour = secs / 3600;
+ secs -= tm->tm_hour * 3600;
+ tm->tm_min = secs / 60;
+ tm->tm_sec = secs - tm->tm_min * 60;
+
+ /* Zero unused fields */
+ tm->tm_isdst = 0;
+}
diff --git a/lib/tpm-common.c b/lib/tpm-common.c
index 4277846fdd0..82ffdc5341b 100644
--- a/lib/tpm-common.c
+++ b/lib/tpm-common.c
@@ -176,6 +176,11 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
}
size = tpm_command_size(command);
+
+ /* sanity check, which also helps coverity */
+ if (size > COMMAND_BUFFER_SIZE)
+ return log_msg_ret("size", -E2BIG);
+
log_debug("TPM request [size:%d]: ", size);
for (i = 0; i < size; i++)
log_debug("%02x ", ((u8 *)command)[i]);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 9dc96c81c62..c14176dd393 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -434,9 +434,9 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
* - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
* currently the same
*
- * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
- * function pointers are really function descriptors, which contain a
- * pointer to the real address.
+ * Note: IPv6 support is currently if(0)'ed out. If you ever need
+ * %pI6, please add an IPV6 Kconfig knob, make your code select or
+ * depend on that, and change the 0 below to CONFIG_IS_ENABLED(IPV6).
*/
static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
int field_width, int precision, int flags)
@@ -481,7 +481,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
flags |= SPECIAL;
/* Fallthrough */
case 'I':
- if (fmt[1] == '6')
+ /* %pI6 currently unused */
+ if (0 && fmt[1] == '6')
return ip6_addr_string(buf, end, ptr, field_width,
precision, flags);
if (fmt[1] == '4')
@@ -787,22 +788,11 @@ int printf(const char *fmt, ...)
{
va_list args;
uint i;
- char printbuffer[CONFIG_SYS_PBSIZE];
va_start(args, fmt);
-
- /*
- * For this to work, printbuffer must be larger than
- * anything we ever want to print.
- */
- i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+ i = vprintf(fmt, args);
va_end(args);
- /* Handle error */
- if (i <= 0)
- return i;
- /* Print the string */
- puts(printbuffer);
return i;
}