diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 11 | ||||
-rw-r--r-- | lib/Makefile | 5 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 10 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 898 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 131 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 17 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 41 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 55 | ||||
-rw-r--r-- | lib/efi_loader/efi_smbios.c | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 64 | ||||
-rw-r--r-- | lib/efi_selftest/Kconfig | 2 | ||||
-rw-r--r-- | lib/efi_selftest/Makefile | 5 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_controllers.c | 35 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_manageprotocols.c | 2 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_textoutput.c | 78 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_unaligned.c | 66 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_variables.c | 196 | ||||
-rw-r--r-- | lib/fdtdec.c | 1 | ||||
-rw-r--r-- | lib/image-sparse.c | 261 | ||||
-rw-r--r-- | lib/libfdt/fdt_ro.c | 18 | ||||
-rw-r--r-- | lib/tpm-common.c | 197 | ||||
-rw-r--r-- | lib/tpm-utils.h | 101 | ||||
-rw-r--r-- | lib/tpm-v1.c (renamed from lib/tpm.c) | 602 | ||||
-rw-r--r-- | lib/tpm-v2.c | 419 |
25 files changed, 2235 insertions, 990 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 1590f7afa40..15c6a52d4a1 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -61,6 +61,17 @@ config SPL_STRTO config TPL_STRTO bool +config IMAGE_SPARSE + bool + +config IMAGE_SPARSE_FILLBUF_SIZE + hex "Android sparse image CHUNK_TYPE_FILL buffer size" + default 0x80000 + depends on IMAGE_SPARSE + help + Set the size of the fill buffer used when processing CHUNK_TYPE_FILL + chunks. + config USE_PRIVATE_LIBGCC bool "Use private libgcc" depends on HAVE_PRIVATE_LIBGCC diff --git a/lib/Makefile b/lib/Makefile index d531ea54b31..c0511cbff84 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o obj-$(CONFIG_LMB) += lmb.o obj-y += ldiv.o @@ -39,7 +40,9 @@ obj-$(CONFIG_PHYSMEM) += physmem.o obj-y += qsort.o obj-y += rc4.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o -obj-$(CONFIG_TPM) += tpm.o +obj-$(CONFIG_TPM) += tpm-common.o +obj-$(CONFIG_TPM_V1) += tpm-v1.o +obj-$(CONFIG_TPM_V2) += tpm-v2.o obj-$(CONFIG_RBTREE) += rbtree.o obj-$(CONFIG_BITREVERSE) += bitrev.o obj-y += list_sort.o diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index d38780b604e..df58e633d1c 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,6 +1,6 @@ config EFI_LOADER bool "Support running EFI Applications in U-Boot" - depends on (ARM || X86) && OF_LIBFDT + depends on (ARM || X86 || RISCV) && OF_LIBFDT # We do not support bootefi booting ARMv7 in non-secure mode depends on !ARMV7_NONSEC # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB @@ -10,6 +10,7 @@ config EFI_LOADER default y select LIB_UUID select HAVE_BLOCK_DEVICE + imply CFB_CONSOLE_ANSI help Select this option if you want to run EFI applications (like grub2) on top of U-Boot. If this option is enabled, U-Boot will expose EFI diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 153e1737573..853358ab937 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -70,17 +70,17 @@ static void parse_load_option(struct load_option *lo, void *ptr) /* free() the result */ static void *get_var(u16 *name, const efi_guid_t *vendor, - unsigned long *size) + efi_uintn_t *size) { efi_guid_t *v = (efi_guid_t *)vendor; efi_status_t ret; void *buf = NULL; *size = 0; - EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf)); if (ret == EFI_BUFFER_TOO_SMALL) { buf = malloc(*size); - EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf)); } if (ret != EFI_SUCCESS) { @@ -104,7 +104,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, u16 varname[] = L"Boot0000"; u16 hexmap[] = L"0123456789ABCDEF"; void *load_option, *image = NULL; - unsigned long size; + efi_uintn_t size; varname[4] = hexmap[(n & 0xf000) >> 12]; varname[5] = hexmap[(n & 0x0f00) >> 8]; @@ -147,7 +147,7 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, struct efi_device_path **file_path) { uint16_t *bootorder; - unsigned long size; + efi_uintn_t size; void *image = NULL; int i, num; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 5715a8b810e..50d311548e2 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -10,7 +10,6 @@ #include <efi_loader.h> #include <environment.h> #include <malloc.h> -#include <asm/global_data.h> #include <linux/libfdt_env.h> #include <u-boot/crc.h> #include <bootm.h> @@ -130,12 +129,15 @@ void efi_restore_gd(void) #endif } -/* - * Return a string for indenting with two spaces per level. A maximum of ten - * indent levels is supported. Higher indent levels will be truncated. +/** + * indent_string - returns a string for indenting with two spaces per level + * + * A maximum of ten indent levels is supported. Higher indent levels will be + * truncated. * - * @level indent level - * @return indent string + * @level: indent level + * Return Value: A string for indenting with two spaces per level is + * returned. */ static const char *indent_string(int level) { @@ -161,8 +163,8 @@ const char *__efi_nesting_dec(void) return indent_string(--nesting_level); } -/* - * Queue an EFI event. +/** + * efi_queue_event - queue an EFI event * * This function queues the notification function of the event for future * execution. @@ -172,8 +174,8 @@ const char *__efi_nesting_dec(void) * * For the SignalEvent service see efi_signal_event_ext. * - * @event event to signal - * @check_tpl check the TPL level + * @event: event to signal + * @check_tpl: check the TPL level */ static void efi_queue_event(struct efi_event *event, bool check_tpl) { @@ -188,8 +190,8 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) event->is_queued = false; } -/* - * Signal an EFI event. +/** + * efi_signal_event - signal an EFI event * * This function signals an event. If the event belongs to an event group * all events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL @@ -197,8 +199,8 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) * * For the SignalEvent service see efi_signal_event_ext. * - * @event event to signal - * @check_tpl check the TPL level + * @event: event to signal + * @check_tpl: check the TPL level */ void efi_signal_event(struct efi_event *event, bool check_tpl) { @@ -232,15 +234,15 @@ void efi_signal_event(struct efi_event *event, bool check_tpl) } } -/* - * Raise the task priority level. +/** + * efi_raise_tpl - raise the task priority level * * This function implements the RaiseTpl service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @new_tpl new value of the task priority level - * @return old value of the task priority level + * @new_tpl: new value of the task priority level + * Return Value: old value of the task priority level */ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl) { @@ -258,14 +260,14 @@ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl) return old_tpl; } -/* - * Lower the task priority level. +/** + * efi_restore_tpl - lower the task priority level * * This function implements the RestoreTpl service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @old_tpl value of the task priority level to be restored + * @old_tpl: value of the task priority level to be restored */ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl) { @@ -285,18 +287,18 @@ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl) EFI_EXIT(EFI_SUCCESS); } -/* - * Allocate memory pages. +/** + * efi_allocate_pages_ext - allocate memory pages * * This function implements the AllocatePages service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @type type of allocation to be performed - * @memory_type usage type of the allocated memory - * @pages number of pages to be allocated - * @memory allocated memory - * @return status code + * @type: type of allocation to be performed + * @memory_type: usage type of the allocated memory + * @pages: number of pages to be allocated + * @memory: allocated memory + * Return Value: status code */ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, efi_uintn_t pages, @@ -309,16 +311,16 @@ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, return EFI_EXIT(r); } -/* - * Free memory pages. +/** + * efi_free_pages_ext - Free memory pages. * * This function implements the FreePages service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @memory start of the memory area to be freed - * @pages number of pages to be freed - * @return status code + * @memory: start of the memory area to be freed + * @pages: number of pages to be freed + * Return Value: status code */ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, efi_uintn_t pages) @@ -330,20 +332,20 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, return EFI_EXIT(r); } -/* - * Get map describing memory usage. +/** + * efi_get_memory_map_ext - get map describing memory usage * * This function implements the GetMemoryMap service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @memory_map_size on entry the size, in bytes, of the memory map buffer, + * @memory_map_size: on entry the size, in bytes, of the memory map buffer, * on exit the size of the copied memory map - * @memory_map buffer to which the memory map is written - * @map_key key for the memory map - * @descriptor_size size of an individual memory descriptor - * @descriptor_version version number of the memory descriptor structure - * @return status code + * @memory_map: buffer to which the memory map is written + * @map_key: key for the memory map + * @descriptor_size: size of an individual memory descriptor + * @descriptor_version: version number of the memory descriptor structure + * Return Value: status code */ static efi_status_t EFIAPI efi_get_memory_map_ext( efi_uintn_t *memory_map_size, @@ -361,17 +363,17 @@ static efi_status_t EFIAPI efi_get_memory_map_ext( return EFI_EXIT(r); } -/* - * Allocate memory from pool. +/** + * efi_allocate_pool_ext - allocate memory from pool * * This function implements the AllocatePool service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @pool_type type of the pool from which memory is to be allocated - * @size number of bytes to be allocated - * @buffer allocated memory - * @return status code + * @pool_type: type of the pool from which memory is to be allocated + * @size: number of bytes to be allocated + * @buffer: allocated memory + * Return Value: status code */ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, efi_uintn_t size, @@ -384,15 +386,15 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, return EFI_EXIT(r); } -/* - * Free memory from pool. +/** + * efi_free_pool_ext - free memory from pool * * This function implements the FreePool service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @buffer start of memory to be freed - * @return status code + * @buffer: start of memory to be freed + * Return Value: status code */ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) { @@ -403,13 +405,13 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); } -/* - * Add a new object to the object list. +/** + * efi_add_handle - add a new object to the object list * * The protocols list is initialized. * The object handle is set. * - * @obj object to be added + * @obj: object to be added */ void efi_add_handle(struct efi_object *obj) { @@ -420,34 +422,33 @@ void efi_add_handle(struct efi_object *obj) list_add_tail(&obj->link, &efi_obj_list); } -/* - * Create handle. +/** + * efi_create_handle - create handle * - * @handle new handle - * @return status code + * @handle: new handle + * Return Value: status code */ efi_status_t efi_create_handle(efi_handle_t *handle) { struct efi_object *obj; - efi_status_t r; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - sizeof(struct efi_object), - (void **)&obj); - if (r != EFI_SUCCESS) - return r; + obj = calloc(1, sizeof(struct efi_object)); + if (!obj) + return EFI_OUT_OF_RESOURCES; + efi_add_handle(obj); *handle = obj->handle; - return r; + + return EFI_SUCCESS; } -/* - * Find a protocol on a handle. +/** + * efi_search_protocol - find a protocol on a handle. * - * @handle handle - * @protocol_guid GUID of the protocol - * @handler reference to the protocol - * @return status code + * @handle: handle + * @protocol_guid: GUID of the protocol + * @handler: reference to the protocol + * Return Value: status code */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid, @@ -474,13 +475,13 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, return EFI_NOT_FOUND; } -/* - * Delete protocol from a handle. +/** + * efi_remove_protocol - delete protocol from a handle * - * @handle handle from which the protocol shall be deleted - * @protocol GUID of the protocol to be deleted - * @protocol_interface interface of the protocol implementation - * @return status code + * @handle: handle from which the protocol shall be deleted + * @protocol: GUID of the protocol to be deleted + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ efi_status_t efi_remove_protocol(const efi_handle_t handle, const efi_guid_t *protocol, @@ -494,16 +495,18 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, return ret; if (guidcmp(handler->guid, protocol)) return EFI_INVALID_PARAMETER; + if (handler->protocol_interface != protocol_interface) + return EFI_INVALID_PARAMETER; list_del(&handler->link); free(handler); return EFI_SUCCESS; } -/* - * Delete all protocols from a handle. +/** + * efi_remove_all_protocols - delete all protocols from a handle * - * @handle handle from which the protocols shall be deleted - * @return status code + * @handle: handle from which the protocols shall be deleted + * Return Value: status code */ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) { @@ -525,10 +528,10 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) return EFI_SUCCESS; } -/* - * Delete handle. +/** + * efi_delete_handle - delete handle * - * @handle handle to delete + * @obj: handle to delete */ void efi_delete_handle(struct efi_object *obj) { @@ -539,11 +542,11 @@ void efi_delete_handle(struct efi_object *obj) free(obj); } -/* - * Check if a pointer is a valid event. +/** + * efi_is_event - check if a pointer is a valid event * - * @event pointer to check - * @return status code + * @event: pointer to check + * Return Value: status code */ static efi_status_t efi_is_event(const struct efi_event *event) { @@ -558,20 +561,21 @@ static efi_status_t efi_is_event(const struct efi_event *event) return EFI_INVALID_PARAMETER; } -/* - * Create an event. +/** + * efi_create_event - create an event * * This function is used inside U-Boot code to create an event. * * For the API function implementing the CreateEvent service see * efi_create_event_ext. * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @group: event group + * @event: created event + * Return Value: status code */ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( @@ -610,20 +614,19 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, } /* - * Create an event in a group. + * efi_create_event_ex - create an event in a group * * This function implements the CreateEventEx service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. - * TODO: Support event groups * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @event_group event group - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @event: created event + * @event_group: event group + * Return Value: status code */ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( @@ -639,19 +642,19 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl, notify_context, event_group, event)); } -/* - * Create an event. +/** + * efi_create_event_ext - create an event * * This function implements the CreateEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @event: created event + * Return Value: status code */ static efi_status_t EFIAPI efi_create_event_ext( uint32_t type, efi_uintn_t notify_tpl, @@ -666,7 +669,9 @@ static efi_status_t EFIAPI efi_create_event_ext( notify_context, NULL, event)); } -/* +/** + * efi_timer_check - check if a timer event has occurred + * * Check if a timer event has occurred or a queued notification function should * be called. * @@ -699,16 +704,16 @@ void efi_timer_check(void) WATCHDOG_RESET(); } -/* - * Set the trigger time for a timer event or stop the event. +/** + * efi_set_timer - set the trigger time for a timer event or stop the event * * This is the function for internal usage in U-Boot. For the API function * implementing the SetTimer service see efi_set_timer_ext. * - * @event event for which the timer is set - * @type type of the timer - * @trigger_time trigger period in multiples of 100ns - * @return status code + * @event: event for which the timer is set + * @type: type of the timer + * @trigger_time: trigger period in multiples of 100ns + * Return Value: status code */ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time) @@ -740,17 +745,17 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, return EFI_SUCCESS; } -/* - * Set the trigger time for a timer event or stop the event. +/** + * efi_set_timer_ext - Set the trigger time for a timer event or stop the event * * This function implements the SetTimer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @event event for which the timer is set - * @type type of the timer - * @trigger_time trigger period in multiples of 100ns - * @return status code + * @event: event for which the timer is set + * @type: type of the timer + * @trigger_time: trigger period in multiples of 100ns + * Return Value: status code */ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, enum efi_timer_delay type, @@ -760,17 +765,17 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, return EFI_EXIT(efi_set_timer(event, type, trigger_time)); } -/* - * Wait for events to be signaled. +/** + * efi_wait_for_event - wait for events to be signaled * * This function implements the WaitForEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @num_events number of events to be waited for - * @events events to be waited for - * @index index of the event that was signaled - * @return status code + * @num_events: number of events to be waited for + * @event: events to be waited for + * @index: index of the event that was signaled + * Return Value: status code */ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events, struct efi_event **event, @@ -817,8 +822,8 @@ out: return EFI_EXIT(EFI_SUCCESS); } -/* - * Signal an EFI event. +/** + * efi_signal_event_ext - signal an EFI event * * This function implements the SignalEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -827,8 +832,8 @@ out: * This functions sets the signaled state of the event and queues the * notification function for execution. * - * @event event to signal - * @return status code + * @event: event to signal + * Return Value: status code */ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) { @@ -839,15 +844,15 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) return EFI_EXIT(EFI_SUCCESS); } -/* - * Close an EFI event. +/** + * efi_close_event - close an EFI event * * This function implements the CloseEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @event event to close - * @return status code + * @event: event to close + * Return Value: status code */ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) { @@ -859,8 +864,8 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) return EFI_EXIT(EFI_SUCCESS); } -/* - * Check if an event is signaled. +/** + * efi_check_event - check if an event is signaled * * This function implements the CheckEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -869,8 +874,8 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) * If an event is not signaled yet, the notification function is queued. * The signaled state is cleared. * - * @event event to check - * @return status code + * @event: event to check + * Return Value: status code */ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) { @@ -888,11 +893,11 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) return EFI_EXIT(EFI_NOT_READY); } -/* - * Find the internal EFI object for a handle. +/** + * efi_search_obj - find the internal EFI object for a handle * - * @handle handle to find - * @return EFI object + * @handle: handle to find + * Return Value: EFI object */ struct efi_object *efi_search_obj(const efi_handle_t handle) { @@ -906,11 +911,12 @@ struct efi_object *efi_search_obj(const efi_handle_t handle) return NULL; } -/* - * Create open protocol info entry and add it to a protocol. +/** + * efi_open_protocol_info_entry - create open protocol info entry and add it + * to a protocol * - * @handler handler of a protocol - * @return open protocol info entry + * @handler: handler of a protocol + * Return Value: open protocol info entry */ static struct efi_open_protocol_info_entry *efi_create_open_info( struct efi_handler *handler) @@ -926,11 +932,11 @@ static struct efi_open_protocol_info_entry *efi_create_open_info( return &item->info; } -/* - * Remove an open protocol info entry from a protocol. +/** + * efi_delete_open_info - remove an open protocol info entry from a protocol * - * @handler handler of a protocol - * @return status code + * @item: open protocol info entry to delete + * Return Value: status code */ static efi_status_t efi_delete_open_info( struct efi_open_protocol_info_item *item) @@ -940,13 +946,13 @@ static efi_status_t efi_delete_open_info( return EFI_SUCCESS; } -/* - * Install new protocol on a handle. +/** + * efi_add_protocol - install new protocol on a handle * - * @handle handle on which the protocol shall be installed - * @protocol GUID of the protocol to be installed - * @protocol_interface interface of the protocol implementation - * @return status code + * @handle: handle on which the protocol shall be installed + * @protocol: GUID of the protocol to be installed + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, @@ -974,19 +980,19 @@ efi_status_t efi_add_protocol(const efi_handle_t handle, return EFI_SUCCESS; } -/* - * Install protocol interface. +/** + * efi_install_protocol_interface - install protocol interface * * This function implements the InstallProtocolInterface service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol shall be installed - * @protocol GUID of the protocol to be installed - * @protocol_interface_type type of the interface to be installed, + * @handle: handle on which the protocol shall be installed + * @protocol: GUID of the protocol to be installed + * @protocol_interface_type: type of the interface to be installed, * always EFI_NATIVE_INTERFACE - * @protocol_interface interface of the protocol implementation - * @return status code + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ static efi_status_t EFIAPI efi_install_protocol_interface( void **handle, const efi_guid_t *protocol, @@ -1020,38 +1026,16 @@ out: return EFI_EXIT(r); } -/* - * Reinstall protocol interface. - * - * This function implements the ReinstallProtocolInterface service. - * See the Unified Extensible Firmware Interface (UEFI) specification - * for details. +/** + * efi_get_drivers - get all drivers associated to a controller * - * @handle handle on which the protocol shall be - * reinstalled - * @protocol GUID of the protocol to be installed - * @old_interface interface to be removed - * @new_interface interface to be installed - * @return status code - */ -static efi_status_t EFIAPI efi_reinstall_protocol_interface( - efi_handle_t handle, const efi_guid_t *protocol, - void *old_interface, void *new_interface) -{ - EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, - new_interface); - return EFI_EXIT(EFI_ACCESS_DENIED); -} - -/* - * Get all drivers associated to a controller. * The allocated buffer has to be freed with free(). * - * @efiobj handle of the controller - * @protocol protocol guid (optional) - * @number_of_drivers number of child controllers - * @driver_handle_buffer handles of the the drivers - * @return status code + * @efiobj: handle of the controller + * @protocol: protocol guid (optional) + * @number_of_drivers: number of child controllers + * @driver_handle_buffer: handles of the the drivers + * Return Value: status code */ static efi_status_t efi_get_drivers(struct efi_object *efiobj, const efi_guid_t *protocol, @@ -1107,17 +1091,17 @@ static efi_status_t efi_get_drivers(struct efi_object *efiobj, return EFI_SUCCESS; } -/* - * Disconnect all drivers from a controller. +/** + * efi_disconnect_all_drivers - disconnect all drivers from a controller * * This function implements the DisconnectController service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @efiobj handle of the controller - * @protocol protocol guid (optional) - * @child_handle handle of the child to destroy - * @return status code + * @efiobj: handle of the controller + * @protocol: protocol guid (optional) + * @child_handle: handle of the child to destroy + * Return Value: status code */ static efi_status_t efi_disconnect_all_drivers( struct efi_object *efiobj, @@ -1146,17 +1130,17 @@ static efi_status_t efi_disconnect_all_drivers( return ret; } -/* - * Uninstall protocol interface. +/** + * efi_uninstall_protocol_interface - uninstall protocol interface * * This function implements the UninstallProtocolInterface service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle from which the protocol shall be removed - * @protocol GUID of the protocol to be removed - * @protocol_interface interface to be removed - * @return status code + * @handle: handle from which the protocol shall be removed + * @protocol: GUID of the protocol to be removed + * @protocol_interface: interface to be removed + * Return Value: status code */ static efi_status_t EFIAPI efi_uninstall_protocol_interface( efi_handle_t handle, const efi_guid_t *protocol, @@ -1203,18 +1187,19 @@ out: return EFI_EXIT(r); } -/* - * Register an event for notification when a protocol is installed. +/** + * efi_register_protocol_notify - register an event for notification when a + * protocol is installed. * * This function implements the RegisterProtocolNotify service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @protocol GUID of the protocol whose installation shall be + * @protocol: GUID of the protocol whose installation shall be * notified - * @event event to be signaled upon installation of the protocol - * @registration key for retrieving the registration information - * @return status code + * @event: event to be signaled upon installation of the protocol + * @registration: key for retrieving the registration information + * Return Value: status code */ static efi_status_t EFIAPI efi_register_protocol_notify( const efi_guid_t *protocol, @@ -1225,16 +1210,16 @@ static efi_status_t EFIAPI efi_register_protocol_notify( return EFI_EXIT(EFI_OUT_OF_RESOURCES); } -/* - * Determine if an EFI handle implements a protocol. +/** + * efi_search - determine if an EFI handle implements a protocol * * See the documentation of the LocateHandle service in the UEFI specification. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @efiobj handle - * @return 0 if the handle implements the protocol + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @efiobj: handle + * Return Value: 0 if the handle implements the protocol */ static int efi_search(enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, @@ -1257,18 +1242,18 @@ static int efi_search(enum efi_locate_search_type search_type, } } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle - locate handles implementing a protocol * * This function is meant for U-Boot internal calls. For the API implementation * of the LocateHandle service see efi_locate_handle_ext. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @buffer_size size of the buffer to receive the handles in bytes - * @buffer buffer to receive the relevant handles - * @return status code + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @buffer_size: size of the buffer to receive the handles in bytes + * @buffer: buffer to receive the relevant handles + * Return Value: status code */ static efi_status_t efi_locate_handle( enum efi_locate_search_type search_type, @@ -1327,19 +1312,19 @@ static efi_status_t efi_locate_handle( return EFI_SUCCESS; } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle_ext - locate handles implementing a protocol. * * This function implements the LocateHandle service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @buffer_size size of the buffer to receive the handles in bytes - * @buffer buffer to receive the relevant handles - * @return 0 if the handle implements the protocol + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @buffer_size: size of the buffer to receive the handles in bytes + * @buffer: buffer to receive the relevant handles + * Return Value: 0 if the handle implements the protocol */ static efi_status_t EFIAPI efi_locate_handle_ext( enum efi_locate_search_type search_type, @@ -1353,7 +1338,12 @@ static efi_status_t EFIAPI efi_locate_handle_ext( buffer_size, buffer)); } -/* Collapses configuration table entries, removing index i */ +/** + * efi_remove_configuration_table - collapses configuration table entries, + * removing index i + * + * @i: index of the table entry to be removed + */ static void efi_remove_configuration_table(int i) { struct efi_configuration_table *this = &efi_conf_table[i]; @@ -1364,15 +1354,16 @@ static void efi_remove_configuration_table(int i) systab.nr_tables--; } -/* - * Adds, updates, or removes a configuration table. +/** + * efi_install_configuration_table - adds, updates, or removes a configuration + * table * * This function is used for internal calls. For the API implementation of the * InstallConfigurationTable service see efi_install_configuration_table_ext. * - * @guid GUID of the installed table - * @table table to be installed - * @return status code + * @guid: GUID of the installed table + * @table: table to be installed + * Return Value: status code */ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table) @@ -1418,16 +1409,17 @@ out: return EFI_SUCCESS; } -/* - * Adds, updates, or removes a configuration table. +/** + * efi_install_configuration_table_ex - Adds, updates, or removes a + * configuration table. * * This function implements the InstallConfigurationTable service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @guid GUID of the installed table - * @table table to be installed - * @return status code + * @guid: GUID of the installed table + * @table: table to be installed + * Return Value: status code */ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, void *table) @@ -1436,16 +1428,18 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, return EFI_EXIT(efi_install_configuration_table(guid, table)); } -/* - * Initialize a loaded_image_info + loaded_image_info object with correct +/** + * efi_setup_loaded_image - initialize a loaded image + * + * Initialize a loaded_image_info and loaded_image_info object with correct * protocols, boot-device, etc. * - * @info loaded image info to be passed to the entry point of the + * @info: loaded image info to be passed to the entry point of the * image - * @obj internal object associated with the loaded image - * @device_path device path of the loaded image - * @file_path file path of the loaded image - * @return status code + * @obj: internal object associated with the loaded image + * @device_path: device path of the loaded image + * @file_path: file path of the loaded image + * Return Value: status code */ efi_status_t efi_setup_loaded_image( struct efi_loaded_image *info, struct efi_object *obj, @@ -1499,12 +1493,12 @@ failure: return ret; } -/* - * Load an image using a file path. +/** + * efi_load_image_from_path - load an image using a file path * - * @file_path the path of the image to load - * @buffer buffer containing the loaded image - * @return status code + * @file_path: the path of the image to load + * @buffer: buffer containing the loaded image + * Return Value: status code */ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer) @@ -1548,21 +1542,21 @@ error: return ret; } -/* - * Load an EFI image into memory. +/** + * efi_load_image - load an EFI image into memory * * This function implements the LoadImage service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @boot_policy true for request originating from the boot manager - * @parent_image the caller's image handle - * @file_path the path of the image to load - * @source_buffer memory location from which the image is installed - * @source_size size of the memory area from which the image is + * @boot_policy: true for request originating from the boot manager + * @parent_image: the caller's image handle + * @file_path: the path of the image to load + * @source_buffer: memory location from which the image is installed + * @source_size: size of the memory area from which the image is * installed - * @image_handle handle for the newly installed image - * @return status code + * @image_handle: handle for the newly installed image + * Return Value: status code */ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, @@ -1638,17 +1632,17 @@ error: return EFI_EXIT(ret); } -/* - * Call the entry point of an image. +/** + * efi_start_image - dall the entry point of an image * * This function implements the StartImage service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @image_handle handle of the image - * @exit_data_size size of the buffer - * @exit_data buffer to receive the exit data of the called image - * @return status code + * @image_handle: handle of the image + * @exit_data_size: size of the buffer + * @exit_data: buffer to receive the exit data of the called image + * Return Value: status code */ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, @@ -1704,18 +1698,18 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL)); } -/* - * Leave an EFI application or driver. +/** + * efi_exit - leave an EFI application or driver * * This function implements the Exit service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @image_handle handle of the application or driver that is exiting - * @exit_status status code - * @exit_data_size size of the buffer in bytes - * @exit_data buffer with data describing an error - * @return status code + * @image_handle: handle of the application or driver that is exiting + * @exit_status: status code + * @exit_data_size: size of the buffer in bytes + * @exit_data: buffer with data describing an error + * Return Value: status code */ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, efi_status_t exit_status, @@ -1753,15 +1747,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, panic("EFI application exited"); } -/* - * Unload an EFI image. +/** + * efi_unload_image - unload an EFI image * * This function implements the UnloadImage service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @image_handle handle of the image to be unloaded - * @return status code + * @image_handle: handle of the image to be unloaded + * Return Value: status code */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) { @@ -1775,8 +1769,8 @@ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) return EFI_EXIT(EFI_SUCCESS); } -/* - * Fix up caches for EFI payloads if necessary. +/** + * efi_exit_caches - fix up caches for EFI payloads if necessary */ static void efi_exit_caches(void) { @@ -1790,8 +1784,8 @@ static void efi_exit_caches(void) #endif } -/* - * Stop all boot services. +/** + * efi_exit_boot_services - stop all boot services * * This function implements the ExitBootServices service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -1801,9 +1795,9 @@ static void efi_exit_caches(void) * For exit boot services events the notification function is called. * The boot services are disabled in the system table. * - * @image_handle handle of the loaded image - * @map_key key of the memory map - * @return status code + * @image_handle: handle of the loaded image + * @map_key: key of the memory map + * Return Value: status code */ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, unsigned long map_key) @@ -1865,15 +1859,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, return EFI_EXIT(EFI_SUCCESS); } -/* - * Get next value of the counter. +/** + * efi_get_next_monotonic_count - get next value of the counter * * This function implements the NextMonotonicCount service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @count returned value of the counter - * @return status code + * @count: returned value of the counter + * Return Value: status code */ static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count) { @@ -1884,15 +1878,15 @@ static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count) return EFI_EXIT(EFI_SUCCESS); } -/* - * Sleep. +/** + * efi_stall - sleep * * This function implements the Stall sercive. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @microseconds period to sleep in microseconds - * @return status code + * @microseconds: period to sleep in microseconds + * Return Value: status code */ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) { @@ -1901,18 +1895,18 @@ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) return EFI_EXIT(EFI_SUCCESS); } -/* - * Reset the watchdog timer. +/** + * efi_set_watchdog_timer - reset the watchdog timer * * This function implements the SetWatchdogTimer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @timeout seconds before reset by watchdog - * @watchdog_code code to be logged when resetting - * @data_size size of buffer in bytes - * @watchdog_data buffer with data describing the reset reason - * @return status code + * @timeout: seconds before reset by watchdog + * @watchdog_code: code to be logged when resetting + * @data_size: size of buffer in bytes + * @watchdog_data: buffer with data describing the reset reason + * Return Value: status code */ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, uint64_t watchdog_code, @@ -1924,18 +1918,18 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, return EFI_EXIT(efi_set_watchdog(timeout)); } -/* - * Close a protocol. +/** + * efi_close_protocol - close a protocol * * This function implements the CloseProtocol service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol shall be closed - * @protocol GUID of the protocol to close - * @agent_handle handle of the driver - * @controller_handle handle of the controller - * @return status code + * @handle: handle on which the protocol shall be closed + * @protocol: GUID of the protocol to close + * @agent_handle: handle of the driver + * @controller_handle: handle of the controller + * Return Value: status code */ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, const efi_guid_t *protocol, @@ -1971,18 +1965,19 @@ out: return EFI_EXIT(r); } -/* - * Provide information about then open status of a protocol on a handle +/** + * efi_open_protocol_information - provide information about then open status + * of a protocol on a handle * * This function implements the OpenProtocolInformation service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle for which the information shall be retrieved - * @protocol GUID of the protocol - * @entry_buffer buffer to receive the open protocol information - * @entry_count number of entries available in the buffer - * @return status code + * @handle: handle for which the information shall be retrieved + * @protocol: GUID of the protocol + * @entry_buffer: buffer to receive the open protocol information + * @entry_count: number of entries available in the buffer + * Return Value: status code */ static efi_status_t EFIAPI efi_open_protocol_information( efi_handle_t handle, const efi_guid_t *protocol, @@ -2034,17 +2029,17 @@ out: return EFI_EXIT(r); } -/* - * Get protocols installed on a handle. +/** + * efi_protocols_per_handle - get protocols installed on a handle * * This function implements the ProtocolsPerHandleService. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle for which the information is retrieved - * @protocol_buffer buffer with protocol GUIDs - * @protocol_buffer_count number of entries in the buffer - * @return status code + * @handle: handle for which the information is retrieved + * @protocol_buffer: buffer with protocol GUIDs + * @protocol_buffer_count: number of entries in the buffer + * Return Value: status code */ static efi_status_t EFIAPI efi_protocols_per_handle( efi_handle_t handle, efi_guid_t ***protocol_buffer, @@ -2095,19 +2090,19 @@ static efi_status_t EFIAPI efi_protocols_per_handle( return EFI_EXIT(EFI_SUCCESS); } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle_buffer - locate handles implementing a protocol * * This function implements the LocateHandleBuffer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @no_handles number of returned handles - * @buffer buffer with the returned handles - * @return status code + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @no_handles: number of returned handles + * @buffer: buffer with the returned handles + * Return Value: status code */ static efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, @@ -2142,17 +2137,17 @@ out: return EFI_EXIT(r); } -/* - * Find an interface implementing a protocol. +/** + * efi_locate_protocol - find an interface implementing a protocol * * This function implements the LocateProtocol service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @protocol GUID of the protocol - * @registration registration key passed to the notification function - * @protocol_interface interface implementing the protocol - * @return status code + * @protocol: GUID of the protocol + * @registration: registration key passed to the notification function + * @protocol_interface: interface implementing the protocol + * Return Value: status code */ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, void *registration, @@ -2183,17 +2178,18 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, return EFI_EXIT(EFI_NOT_FOUND); } -/* - * Get the device path and handle of an device implementing a protocol. +/** + * efi_locate_device_path - Get the device path and handle of an device + * implementing a protocol * * This function implements the LocateDevicePath service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @protocol GUID of the protocol - * @device_path device path - * @device handle of the device - * @return status code + * @protocol: GUID of the protocol + * @device_path: device path + * @device: handle of the device + * Return Value: status code */ static efi_status_t EFIAPI efi_locate_device_path( const efi_guid_t *protocol, @@ -2259,17 +2255,18 @@ out: return EFI_EXIT(ret); } -/* +/** * Install multiple protocol interfaces. * * This function implements the MultipleProtocolInterfaces service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol interfaces shall be installed - * @... NULL terminated argument list with pairs of protocol GUIDS and - * interfaces - * @return status code + * @handle: handle on which the protocol interfaces shall be + * installed + * @...: NULL terminated argument list with pairs of protocol + * GUIDS and interfaces + * Return Value: status code */ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( void **handle, ...) @@ -2316,17 +2313,19 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( return EFI_EXIT(r); } -/* - * Uninstall multiple protocol interfaces. +/** + * efi_uninstall_multiple_protocol_interfaces - uninstall multiple protocol + * interfaces * * This function implements the UninstallMultipleProtocolInterfaces service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle from which the protocol interfaces shall be removed - * @... NULL terminated argument list with pairs of protocol GUIDS and - * interfaces - * @return status code + * @handle: handle from which the protocol interfaces shall be + * removed + * @...: NULL terminated argument list with pairs of protocol + * GUIDS and interfaces + * Return Value: status code */ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( void *handle, ...) @@ -2373,17 +2372,17 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( return EFI_EXIT(r); } -/* - * Calculate cyclic redundancy code. +/** + * efi_calculate_crc32 - calculate cyclic redundancy code * * This function implements the CalculateCrc32 service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @data buffer with data - * @data_size size of buffer in bytes - * @crc32_p cyclic redundancy code - * @return status code + * @data: buffer with data + * @data_size: size of buffer in bytes + * @crc32_p: cyclic redundancy code + * Return Value: status code */ static efi_status_t EFIAPI efi_calculate_crc32(void *data, unsigned long data_size, @@ -2394,16 +2393,16 @@ static efi_status_t EFIAPI efi_calculate_crc32(void *data, return EFI_EXIT(EFI_SUCCESS); } -/* - * Copy memory. +/** + * efi_copy_mem - copy memory * * This function implements the CopyMem service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @destination destination of the copy operation - * @source source of the copy operation - * @length number of bytes to copy + * @destination: destination of the copy operation + * @source: source of the copy operation + * @length: number of bytes to copy */ static void EFIAPI efi_copy_mem(void *destination, const void *source, size_t length) @@ -2413,16 +2412,16 @@ static void EFIAPI efi_copy_mem(void *destination, const void *source, EFI_EXIT(EFI_SUCCESS); } -/* - * Fill memory with a byte value. +/** + * efi_set_mem - Fill memory with a byte value. * * This function implements the SetMem service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @buffer buffer to fill - * @size size of buffer in bytes - * @value byte to copy to the buffer + * @buffer: buffer to fill + * @size: size of buffer in bytes + * @value: byte to copy to the buffer */ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) { @@ -2431,15 +2430,15 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) EFI_EXIT(EFI_SUCCESS); } -/* - * Open protocol interface on a handle. +/** + * efi_protocol_open - open protocol interface on a handle * - * @handler handler of a protocol - * @protocol_interface interface implementing the protocol - * @agent_handle handle of the driver - * @controller_handle handle of the controller - * @attributes attributes indicating how to open the protocol - * @return status code + * @handler: handler of a protocol + * @protocol_interface: interface implementing the protocol + * @agent_handle: handle of the driver + * @controller_handle: handle of the controller + * @attributes: attributes indicating how to open the protocol + * Return Value: status code */ static efi_status_t efi_protocol_open( struct efi_handler *handler, @@ -2526,20 +2525,20 @@ out: return EFI_SUCCESS; } -/* - * Open protocol interface on a handle. +/** + * efi_open_protocol - open protocol interface on a handle * * This function implements the OpenProtocol interface. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol shall be opened - * @protocol GUID of the protocol - * @protocol_interface interface implementing the protocol - * @agent_handle handle of the driver - * @controller_handle handle of the controller - * @attributes attributes indicating how to open the protocol - * @return status code + * @handle: handle on which the protocol shall be opened + * @protocol: GUID of the protocol + * @protocol_interface: interface implementing the protocol + * @agent_handle: handle of the driver + * @controller_handle: handle of the controller + * @attributes: attributes indicating how to open the protocol + * Return Value: status code */ static efi_status_t EFIAPI efi_open_protocol( void *handle, const efi_guid_t *protocol, @@ -2593,17 +2592,17 @@ out: return EFI_EXIT(r); } -/* - * Get interface of a protocol on a handle. +/** + * efi_handle_protocol - get interface of a protocol on a handle * * This function implements the HandleProtocol service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol shall be opened - * @protocol GUID of the protocol - * @protocol_interface interface implementing the protocol - * @return status code + * @handle: handle on which the protocol shall be opened + * @protocol: GUID of the protocol + * @protocol_interface: interface implementing the protocol + * Return Value: status code */ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, const efi_guid_t *protocol, @@ -2613,6 +2612,14 @@ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); } +/** + * efi_bind_controller - bind a single driver to a controller + * + * @controller_handle: controller handle + * @driver_image_handle: driver handle + * @remain_device_path: remaining path + * Return Value: status code + */ static efi_status_t efi_bind_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, @@ -2641,6 +2648,14 @@ static efi_status_t efi_bind_controller( return r; } +/** + * efi_connect_single_controller - connect a single driver to a controller + * + * @controller_handle: controller + * @driver_image_handle: driver + * @remain_device_path: remainting path + * Return Value: status code + */ static efi_status_t efi_connect_single_controller( efi_handle_t controller_handle, efi_handle_t *driver_image_handle, @@ -2705,8 +2720,8 @@ static efi_status_t efi_connect_single_controller( return EFI_SUCCESS; } -/* - * Connect a controller to a driver. +/** + * efi_connect_controller - connect a controller to a driver * * This function implements the ConnectController service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -2716,11 +2731,11 @@ static efi_status_t efi_connect_single_controller( * Afterwards all handles that have openened a protocol of the controller * with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER are connected to drivers. * - * @controller_handle handle of the controller - * @driver_image_handle handle of the driver - * @remain_device_path device path of a child controller - * @recursive true to connect all child controllers - * @return status code + * @controller_handle: handle of the controller + * @driver_image_handle: handle of the driver + * @remain_device_path: device path of a child controller + * @recursive: true to connect all child controllers + * Return Value: status code */ static efi_status_t EFIAPI efi_connect_controller( efi_handle_t controller_handle, @@ -2773,14 +2788,59 @@ out: return EFI_EXIT(ret); } -/* - * Get all child controllers associated to a driver. +/** + * efi_reinstall_protocol_interface - reinstall protocol interface + * + * This function implements the ReinstallProtocolInterface service. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * The old interface is uninstalled. The new interface is installed. + * Drivers are connected. + * + * @handle: handle on which the protocol shall be + * reinstalled + * @protocol: GUID of the protocol to be installed + * @old_interface: interface to be removed + * @new_interface: interface to be installed + * Return Value: status code + */ +static efi_status_t EFIAPI efi_reinstall_protocol_interface( + efi_handle_t handle, const efi_guid_t *protocol, + void *old_interface, void *new_interface) +{ + efi_status_t ret; + + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, + new_interface); + ret = EFI_CALL(efi_uninstall_protocol_interface(handle, protocol, + old_interface)); + if (ret != EFI_SUCCESS) + goto out; + ret = EFI_CALL(efi_install_protocol_interface(&handle, protocol, + EFI_NATIVE_INTERFACE, + new_interface)); + if (ret != EFI_SUCCESS) + goto out; + /* + * The returned status code has to be ignored. + * Do not create an error if no suitable driver for the handle exists. + */ + EFI_CALL(efi_connect_controller(handle, NULL, NULL, true)); +out: + return EFI_EXIT(ret); +} + +/** + * efi_get_child_controllers - get all child controllers associated to a driver + * * The allocated buffer has to be freed with free(). * - * @efiobj handle of the controller - * @driver_handle handle of the driver - * @number_of_children number of child controllers - * @child_handle_buffer handles of the the child controllers + * @efiobj: handle of the controller + * @driver_handle: handle of the driver + * @number_of_children: number of child controllers + * @child_handle_buffer: handles of the the child controllers + * Return Value: status code */ static efi_status_t efi_get_child_controllers( struct efi_object *efiobj, @@ -2835,17 +2895,17 @@ static efi_status_t efi_get_child_controllers( return EFI_SUCCESS; } -/* - * Disconnect a controller from a driver. +/** + * efi_disconnect_controller - disconnect a controller from a driver * * This function implements the DisconnectController service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @controller_handle handle of the controller - * @driver_image_handle handle of the driver - * @child_handle handle of the child to destroy - * @return status code + * @controller_handle: handle of the controller + * @driver_image_handle: handle of the driver + * @child_handle: handle of the child to destroy + * Return Value: status code */ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index d777db8a3ed..ce66c935ecb 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -12,8 +12,6 @@ #include <stdio_dev.h> #include <video_console.h> -static bool console_size_queried; - #define EFI_COUT_MODE_2 2 #define EFI_MAX_COUT_MODE 3 @@ -62,7 +60,15 @@ static struct simple_text_output_mode efi_con_mode = { .cursor_visible = 1, }; -static int term_read_reply(int *n, int maxnum, char end_char) +/* + * Receive and parse a reply from the terminal. + * + * @n: array of return values + * @num: number of return values expected + * @end_char: character indicating end of terminal message + * @return: non-zero indicates error + */ +static int term_read_reply(int *n, int num, char end_char) { char c; int i = 0; @@ -79,7 +85,7 @@ static int term_read_reply(int *n, int maxnum, char end_char) c = getc(); if (c == ';') { i++; - if (i >= maxnum) + if (i >= num) return -1; n[i] = 0; continue; @@ -93,6 +99,8 @@ static int term_read_reply(int *n, int maxnum, char end_char) n[i] *= 10; n[i] += c - '0'; } + if (i != num - 1) + return -1; return 0; } @@ -116,25 +124,36 @@ static efi_status_t EFIAPI efi_cout_output_string( unsigned int n16 = utf16_strlen(string); char buf[MAX_UTF8_PER_UTF16 * n16 + 1]; - char *p; + u16 *p; *utf16_to_utf8((u8 *)buf, string, n16) = '\0'; fputs(stdout, buf); - for (p = buf; *p; p++) { + /* + * Update the cursor position. + * + * The UEFI spec provides advance rules for U+0000, U+0008, U+000A, + * and U000D. All other characters, including control characters + * U+0007 (bel) and U+0009 (tab), have to increase the column by one. + */ + for (p = string; *p; ++p) { switch (*p) { - case '\r': /* carriage-return */ - con->cursor_column = 0; + case '\b': /* U+0008, backspace */ + con->cursor_column = max(0, con->cursor_column - 1); break; - case '\n': /* newline */ + case '\n': /* U+000A, newline */ con->cursor_column = 0; con->cursor_row++; break; - case '\t': /* tab, assume 8 char align */ + case '\r': /* U+000D, carriage-return */ + con->cursor_column = 0; break; - case '\b': /* backspace */ - con->cursor_column = max(0, con->cursor_column - 1); + case 0xd800 ... 0xdbff: + /* + * Ignore high surrogates, we do not want to count a + * Unicode character twice. + */ break; default: con->cursor_column++; @@ -194,6 +213,51 @@ static int query_console_serial(int *rows, int *cols) return 0; } +/* + * Update the mode table. + * + * By default the only mode available is 80x25. If the console has at least 50 + * lines, enable mode 80x50. If we can query the console size and it is neither + * 80x25 nor 80x50, set it as an additional mode. + */ +static void query_console_size(void) +{ + const char *stdout_name = env_get("stdout"); + int rows = 25, cols = 80; + + if (stdout_name && !strcmp(stdout_name, "vidconsole") && + IS_ENABLED(CONFIG_DM_VIDEO)) { + struct stdio_dev *stdout_dev = + stdio_get_by_name("vidconsole"); + struct udevice *dev = stdout_dev->priv; + struct vidconsole_priv *priv = + dev_get_uclass_priv(dev); + rows = priv->rows; + cols = priv->cols; + } else if (query_console_serial(&rows, &cols)) { + return; + } + + /* Test if we can have Mode 1 */ + if (cols >= 80 && rows >= 50) { + efi_cout_modes[1].present = 1; + efi_con_mode.max_mode = 2; + } + + /* + * Install our mode as mode 2 if it is different + * than mode 0 or 1 and set it as the currently selected mode + */ + if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) && + !cout_mode_matches(&efi_cout_modes[1], rows, cols)) { + efi_cout_modes[EFI_COUT_MODE_2].columns = cols; + efi_cout_modes[EFI_COUT_MODE_2].rows = rows; + efi_cout_modes[EFI_COUT_MODE_2].present = 1; + efi_con_mode.max_mode = EFI_MAX_COUT_MODE; + efi_con_mode.mode = EFI_COUT_MODE_2; + } +} + static efi_status_t EFIAPI efi_cout_query_mode( struct efi_simple_text_output_protocol *this, unsigned long mode_number, unsigned long *columns, @@ -201,52 +265,12 @@ static efi_status_t EFIAPI efi_cout_query_mode( { EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows); - if (!console_size_queried) { - const char *stdout_name = env_get("stdout"); - int rows, cols; - - console_size_queried = true; - - if (stdout_name && !strcmp(stdout_name, "vidconsole") && - IS_ENABLED(CONFIG_DM_VIDEO)) { - struct stdio_dev *stdout_dev = - stdio_get_by_name("vidconsole"); - struct udevice *dev = stdout_dev->priv; - struct vidconsole_priv *priv = - dev_get_uclass_priv(dev); - rows = priv->rows; - cols = priv->cols; - } else if (query_console_serial(&rows, &cols)) { - goto out; - } - - /* Test if we can have Mode 1 */ - if (cols >= 80 && rows >= 50) { - efi_cout_modes[1].present = 1; - efi_con_mode.max_mode = 2; - } - - /* - * Install our mode as mode 2 if it is different - * than mode 0 or 1 and set it as the currently selected mode - */ - if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) && - !cout_mode_matches(&efi_cout_modes[1], rows, cols)) { - efi_cout_modes[EFI_COUT_MODE_2].columns = cols; - efi_cout_modes[EFI_COUT_MODE_2].rows = rows; - efi_cout_modes[EFI_COUT_MODE_2].present = 1; - efi_con_mode.max_mode = EFI_MAX_COUT_MODE; - efi_con_mode.mode = EFI_COUT_MODE_2; - } - } - if (mode_number >= efi_con_mode.max_mode) return EFI_EXIT(EFI_UNSUPPORTED); if (efi_cout_modes[mode_number].present != 1) return EFI_EXIT(EFI_UNSUPPORTED); -out: if (columns) *columns = efi_cout_modes[mode_number].columns; if (rows) @@ -554,6 +578,9 @@ int efi_console_register(void) struct efi_object *efi_console_output_obj; struct efi_object *efi_console_input_obj; + /* Set up mode information */ + query_console_size(); + /* Create handles */ r = efi_create_handle((efi_handle_t *)&efi_console_output_obj); if (r != EFI_SUCCESS) diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index e832cde9016..3cffe9ef461 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -10,7 +10,6 @@ #include <common.h> #include <efi_loader.h> #include <pe.h> -#include <asm/global_data.h> const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; @@ -90,11 +89,16 @@ void efi_print_image_infos(void *pc) } static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, - unsigned long rel_size, void *efi_reloc) + unsigned long rel_size, void *efi_reloc, + unsigned long pref_address) { + unsigned long delta = (unsigned long)efi_reloc - pref_address; const IMAGE_BASE_RELOCATION *end; int i; + if (delta == 0) + return EFI_SUCCESS; + end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size); while (rel < end - 1 && rel->SizeOfBlock) { const uint16_t *relocs = (const uint16_t *)(rel + 1); @@ -103,7 +107,6 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, uint32_t offset = (uint32_t)(*relocs & 0xfff) + rel->VirtualAddress; int type = *relocs >> EFI_PAGE_SHIFT; - unsigned long delta = (unsigned long)efi_reloc; uint64_t *x64 = efi_reloc + offset; uint32_t *x32 = efi_reloc + offset; uint16_t *x16 = efi_reloc + offset; @@ -191,6 +194,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) unsigned long rel_size; int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC; void *entry; + uint64_t image_base; uint64_t image_size; unsigned long virt_size = 0; int supported = 0; @@ -234,6 +238,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { IMAGE_NT_HEADERS64 *nt64 = (void *)nt; IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; + image_base = opt->ImageBase; image_size = opt->SizeOfImage; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); efi_reloc = efi_alloc(virt_size, @@ -249,6 +254,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) virt_size = ALIGN(virt_size, opt->SectionAlignment); } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; + image_base = opt->ImageBase; image_size = opt->SizeOfImage; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); efi_reloc = efi_alloc(virt_size, @@ -279,7 +285,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) } /* Run through relocations */ - if (efi_loader_relocate(rel, rel_size, efi_reloc) != EFI_SUCCESS) { + if (efi_loader_relocate(rel, rel_size, efi_reloc, + (unsigned long)image_base) != EFI_SUCCESS) { efi_free_pages((uintptr_t) efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); return NULL; @@ -287,7 +294,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) /* Flush cache */ flush_cache((ulong)efi_reloc, - ALIGN(virt_size, CONFIG_SYS_CACHELINE_SIZE)); + ALIGN(virt_size, EFI_CACHELINE_SIZE)); invalidate_icache_all(); /* Populate the loaded image interface bits */ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 664c651db56..ec66af98ea8 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -10,7 +10,6 @@ #include <inttypes.h> #include <malloc.h> #include <watchdog.h> -#include <asm/global_data.h> #include <linux/list_sort.h> DECLARE_GLOBAL_DATA_PTR; @@ -69,23 +68,27 @@ static void efi_mem_sort(void) list_sort(NULL, &efi_mem, efi_mem_cmp); } -/* - * Unmaps all memory occupied by the carve_desc region from the - * list entry pointed to by map. +/** efi_mem_carve_out - unmap memory region + * + * @map: memory map + * @carve_desc: memory region to unmap + * @overlap_only_ram: the carved out region may only overlap RAM + * Return Value: the number of overlapping pages which have been + * removed from the map, + * EFI_CARVE_NO_OVERLAP, if the regions don't overlap, + * EFI_CARVE_OVERLAPS_NONRAM, if the carve and map overlap, + * and the map contains anything but free ram + * (only when overlap_only_ram is true), + * EFI_CARVE_LOOP_AGAIN, if the mapping list should be + * traversed again, as it has been altered. * - * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap. - * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap, - * and the map contains anything but free ram. - * (only when overlap_only_ram is true) - * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed - * again, as it has been altered - * Returns the number of overlapping pages. The pages are removed from - * the mapping list. + * Unmaps all memory occupied by the carve_desc region from the list entry + * pointed to by map. * * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility - * to readd the already carved out pages to the mapping. + * to re-add the already carved out pages to the mapping. */ -static int efi_mem_carve_out(struct efi_mem_list *map, +static s64 efi_mem_carve_out(struct efi_mem_list *map, struct efi_mem_desc *carve_desc, bool overlap_only_ram) { @@ -184,7 +187,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, carve_again = false; list_for_each(lhandle, &efi_mem) { struct efi_mem_list *lmem; - int r; + s64 r; lmem = list_entry(lhandle, struct efi_mem_list, link); r = efi_mem_carve_out(lmem, &newlist->desc, @@ -338,7 +341,8 @@ void *efi_alloc(uint64_t len, int memory_type) uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; efi_status_t r; - r = efi_allocate_pages(0, memory_type, pages, &ret); + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages, + &ret); if (r == EFI_SUCCESS) return (void*)(uintptr_t)ret; @@ -385,7 +389,8 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) return EFI_SUCCESS; } - r = efi_allocate_pages(0, pool_type, num_pages, &t); + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages, + &t); if (r == EFI_SUCCESS) { struct efi_pool_allocation *alloc = (void *)(uintptr_t)t; @@ -516,7 +521,7 @@ int efi_memory_init(void) /* Request a 32bit 64MB bounce buffer region */ uint64_t efi_bounce_buffer_addr = 0xffffffff; - if (efi_allocate_pages(1, EFI_LOADER_DATA, + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA, (64 * 1024 * 1024) >> EFI_PAGE_SHIFT, &efi_bounce_buffer_addr) != EFI_SUCCESS) return -1; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 52f1301d75b..65f2bcf1401 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -10,7 +10,6 @@ #include <dm.h> #include <efi_loader.h> #include <rtc.h> -#include <asm/global_data.h> /* For manual relocation support */ DECLARE_GLOBAL_DATA_PTR; @@ -29,13 +28,6 @@ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void); static efi_status_t __efi_runtime EFIAPI efi_device_error(void); static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); -#ifdef CONFIG_SYS_CACHELINE_SIZE -#define EFI_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE -#else -/* Just use the greatest cache flush alignment requirement I'm aware of */ -#define EFI_CACHELINE_SIZE 128 -#endif - #if defined(CONFIG_ARM64) #define R_RELATIVE 1027 #define R_MASK 0xffffffffULL @@ -47,6 +39,25 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); #include <asm/elf.h> #define R_RELATIVE R_386_RELATIVE #define R_MASK 0xffULL +#elif defined(CONFIG_RISCV) +#include <elf.h> +#define R_RELATIVE R_RISCV_RELATIVE +#define R_MASK 0xffULL +#define IS_RELA 1 + +struct dyn_sym { + ulong foo1; + ulong addr; + u32 foo2; + u32 foo3; +}; +#ifdef CONFIG_CPU_RISCV_32 +#define R_ABSOLUTE R_RISCV_32 +#define SYM_INDEX 8 +#else +#define R_ABSOLUTE R_RISCV_64 +#define SYM_INDEX 32 +#endif #else #error Need to add relocation awareness #endif @@ -201,7 +212,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { .ptr = &efi_runtime_services.get_variable, .patchto = &efi_device_error, }, { - .ptr = &efi_runtime_services.get_next_variable, + .ptr = &efi_runtime_services.get_next_variable_name, .patchto = &efi_device_error, }, { .ptr = &efi_runtime_services.set_variable, @@ -253,15 +264,27 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) p = (void*)((ulong)rel->offset - base) + gd->relocaddr; - if ((rel->info & R_MASK) != R_RELATIVE) { - continue; - } + debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__, rel->info, *p, rel->offset); + switch (rel->info & R_MASK) { + case R_RELATIVE: #ifdef IS_RELA newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE; #else newaddr = *p - lastoff + offset; #endif + break; +#ifdef R_ABSOLUTE + case R_ABSOLUTE: { + ulong symidx = rel->info >> SYM_INDEX; + extern struct dyn_sym __dyn_sym_start[]; + newaddr = __dyn_sym_start[symidx].addr + offset; + break; + } +#endif + default: + continue; + } /* Check if the relocation is inside bounds */ if (map && ((newaddr < map->virtual_start) || @@ -421,9 +444,9 @@ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( efi_status_t __efi_runtime EFIAPI efi_query_variable_info( u32 attributes, - u64 maximum_variable_storage_size, - u64 remaining_variable_storage_size, - u64 maximum_variable_size) + u64 *maximum_variable_storage_size, + u64 *remaining_variable_storage_size, + u64 *maximum_variable_size) { return EFI_UNSUPPORTED; } @@ -441,7 +464,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_virtual_address_map = &efi_set_virtual_address_map, .convert_pointer = (void *)&efi_invalid_parameter, .get_variable = efi_get_variable, - .get_next_variable = efi_get_next_variable, + .get_next_variable_name = efi_get_next_variable_name, .set_variable = efi_set_variable, .get_next_high_mono_count = (void *)&efi_device_error, .reset_system = &efi_reset_system_boottime, diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 482436e2adb..7c3fc8af0b2 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -29,7 +29,12 @@ efi_status_t efi_smbios_register(void) if (ret != EFI_SUCCESS) return ret; - /* Generate SMBIOS tables */ + /* + * Generate SMBIOS tables - we know that efi_allocate_pages() returns + * a 4k-aligned address, so it is safe to assume that + * write_smbios_table() will write the table at that address. + */ + assert(!(dmi & 0xf)); write_smbios_table(dmi); /* And expose them to our EFI payload */ diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 7e0e7f020ee..90b637215e4 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -49,7 +49,7 @@ (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \ (MAX_VAR_NAME * MAX_UTF8_PER_UTF16)) -static int hex(unsigned char ch) +static int hex(int ch) { if (ch >= 'a' && ch <= 'f') return ch-'a'+10; @@ -60,44 +60,32 @@ static int hex(unsigned char ch) return -1; } -static const char *hex2mem(u8 *mem, const char *hexstr, int count) +static int hex2mem(u8 *mem, const char *hexstr, int size) { - memset(mem, 0, count/2); + int nibble; + int i; - do { - int nibble; - - *mem = 0; - - if (!count || !*hexstr) + for (i = 0; i < size; i++) { + if (*hexstr == '\0') break; nibble = hex(*hexstr); if (nibble < 0) - break; + return -1; *mem = nibble; - count--; hexstr++; - if (!count || !*hexstr) - break; - nibble = hex(*hexstr); if (nibble < 0) - break; + return -1; *mem = (*mem << 4) | nibble; - count--; hexstr++; mem++; + } - } while (1); - - if (*hexstr) - return hexstr; - - return NULL; + return i; } static char *mem2hex(char *hexstr, const u8 *mem, int count) @@ -113,8 +101,8 @@ static char *mem2hex(char *hexstr, const u8 *mem, int count) return hexstr; } -static efi_status_t efi_to_native(char *native, s16 *variable_name, - efi_guid_t *vendor) +static efi_status_t efi_to_native(char *native, u16 *variable_name, + efi_guid_t *vendor) { size_t len; @@ -176,9 +164,9 @@ static const char *parse_attr(const char *str, u32 *attrp) } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */ -efi_status_t EFIAPI efi_get_variable(s16 *variable_name, - efi_guid_t *vendor, u32 *attributes, - unsigned long *data_size, void *data) +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, + u32 *attributes, efi_uintn_t *data_size, + void *data) { char native_name[MAX_NATIVE_VAR_NAME + 1]; efi_status_t ret; @@ -209,8 +197,12 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name, if ((s = prefix(val, "(blob)"))) { unsigned len = strlen(s); + /* number of hexadecimal digits must be even */ + if (len & 1) + return EFI_EXIT(EFI_DEVICE_ERROR); + /* two characters per byte: */ - len = DIV_ROUND_UP(len, 2); + len /= 2; *data_size = len; if (in_size < len) @@ -219,7 +211,7 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name, if (!data) return EFI_EXIT(EFI_INVALID_PARAMETER); - if (hex2mem(data, s, len * 2)) + if (hex2mem(data, s, len) != len) return EFI_EXIT(EFI_DEVICE_ERROR); debug("%s: got value: \"%s\"\n", __func__, s); @@ -250,9 +242,9 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name, } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */ -efi_status_t EFIAPI efi_get_next_variable( - unsigned long *variable_name_size, - s16 *variable_name, efi_guid_t *vendor) +efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, + u16 *variable_name, + efi_guid_t *vendor) { EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor); @@ -260,16 +252,16 @@ efi_status_t EFIAPI efi_get_next_variable( } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ -efi_status_t EFIAPI efi_set_variable(s16 *variable_name, - efi_guid_t *vendor, u32 attributes, - unsigned long data_size, void *data) +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, + u32 attributes, efi_uintn_t data_size, + void *data) { char native_name[MAX_NATIVE_VAR_NAME + 1]; efi_status_t ret = EFI_SUCCESS; char *val, *s; u32 attr; - EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes, + EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes, data_size, data); if (!variable_name || !vendor) diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig index 3b5f3a1230b..59f9f36801c 100644 --- a/lib/efi_selftest/Kconfig +++ b/lib/efi_selftest/Kconfig @@ -1,6 +1,8 @@ config CMD_BOOTEFI_SELFTEST bool "Allow booting an EFI efi_selftest" depends on CMD_BOOTEFI + imply FAT + imply FAT_WRITE help This adds an EFI test application to U-Boot that can be executed with the 'bootefi selftest' command. It provides extended tests of diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 80c43026458..4fe404d88d8 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -28,8 +28,13 @@ efi_selftest_textinput.o \ efi_selftest_textoutput.o \ efi_selftest_tpl.o \ efi_selftest_util.o \ +efi_selftest_variables.o \ efi_selftest_watchdog.o +ifeq ($(CONFIG_CMD_BOOTEFI_SELFTEST),y) +obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o +endif + ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o endif diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index e30c11b1e45..ceefa03444f 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -6,7 +6,7 @@ * * This unit test checks the following protocol services: * ConnectController, DisconnectController, - * InstallProtocol, UninstallProtocol, + * InstallProtocol, ReinstallProtocol, UninstallProtocol, * OpenProtocol, CloseProtcol, OpenProtocolInformation */ @@ -14,6 +14,8 @@ #define NUMBER_OF_CHILD_CONTROLLERS 4 +static int interface1 = 1; +static int interface2 = 2; static struct efi_boot_services *boottime; const efi_guid_t guid_driver_binding_protocol = EFI_DRIVER_BINDING_PROTOCOL_GUID; @@ -271,7 +273,7 @@ static int setup(const efi_handle_t img_handle, /* Create controller handle */ ret = boottime->install_protocol_interface( &handle_controller, &guid_controller, - EFI_NATIVE_INTERFACE, NULL); + EFI_NATIVE_INTERFACE, &interface1); if (ret != EFI_SUCCESS) { efi_st_error("InstallProtocolInterface failed\n"); return EFI_ST_FAILURE; @@ -299,6 +301,7 @@ static int setup(const efi_handle_t img_handle, * Disconnect and destroy the remaining child controllers. * * Connect a controller to a driver. + * Reinstall the driver protocol on the controller. * Uninstall the driver protocol from the controller. */ static int execute(void) @@ -361,9 +364,35 @@ static int execute(void) efi_st_error("Number of children %u != %u\n", (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); } + /* Try to uninstall controller protocol using the wrong interface */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface2); + if (ret == EFI_SUCCESS) { + efi_st_error( + "Interface not checked when uninstalling protocol\n"); + return EFI_ST_FAILURE; + } + /* Reinstall controller protocol */ + ret = boottime->reinstall_protocol_interface(handle_controller, + &guid_controller, + &interface1, + &interface2); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to reinstall protocols\n"); + return EFI_ST_FAILURE; + } + /* Check number of child controllers */ + ret = count_child_controllers(handle_controller, &guid_controller, + &count); + if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) { + efi_st_error("Number of children %u != %u\n", + (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); + } /* Uninstall controller protocol */ ret = boottime->uninstall_protocol_interface(handle_controller, - &guid_controller, NULL); + &guid_controller, + &interface2); if (ret != EFI_SUCCESS) { efi_st_error("Failed to uninstall protocols\n"); return EFI_ST_FAILURE; diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c index 3e4755c25e9..44b8da3ba5d 100644 --- a/lib/efi_selftest/efi_selftest_manageprotocols.c +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -335,7 +335,7 @@ static int execute(void) return EFI_ST_FAILURE; } ret = boottime->uninstall_protocol_interface(handle1, &guid3, - &interface1); + &interface3); if (ret != EFI_SUCCESS) { efi_st_error("UninstallProtocolInterface failed\n"); return EFI_ST_FAILURE; diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 3533647fd49..a87f65e197f 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -23,6 +23,13 @@ static int execute(void) size_t background; size_t attrib; efi_status_t ret; + s16 col; + u16 cr[] = { 0x0d, 0x00 }; + u16 lf[] = { 0x0a, 0x00 }; + u16 brahmi[] = { /* 2 Brahmi letters */ + 0xD804, 0xDC05, + 0xD804, 0xDC22, + 0}; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -42,6 +49,77 @@ static int execute(void) efi_st_error("TestString failed for ANSI characters\n"); return EFI_ST_FAILURE; } + /* OutputString */ + ret = con_out->output_string(con_out, + L"Testing cursor column update\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for ANSI characters"); + return EFI_ST_FAILURE; + } + col = con_out->mode->cursor_column; + ret = con_out->output_string(con_out, lf); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for line feed\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != col) { + efi_st_error("Cursor column changed by line feed\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, cr); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for carriage return\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column not 0 at beginning of line\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"123"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for ANSI characters\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != 3) { + efi_st_error("Cursor column not incremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != 2) { + efi_st_error("Cursor column not decremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column not decremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column decremented past zero\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, brahmi); + if (ret != EFI_ST_SUCCESS) { + efi_st_todo("Unicode output not fully supported\n"); + } else if (con_out->mode->cursor_column != 2) { + efi_st_printf("Unicode not handled properly\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); + return EFI_ST_SUCCESS; } diff --git a/lib/efi_selftest/efi_selftest_unaligned.c b/lib/efi_selftest/efi_selftest_unaligned.c new file mode 100644 index 00000000000..1802948e675 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_unaligned.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_unaligned + * + * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * Test unaligned memory access on ARMv7. + */ + +#include <efi_selftest.h> + +struct aligned_buffer { + char a[8] __aligned(8); +}; + +/* + * Return an u32 at a give address. + * If the address is not four byte aligned, an unaligned memory access + * occurs. + * + * @addr: address to read + * @return: value at the address + */ +static inline u32 deref(u32 *addr) +{ + int ret; + + asm( + "ldr %[out], [%[in]]\n\t" + : [out] "=r" (ret) + : [in] "r" (addr) + ); + return ret; +} + +/* + * Execute unit test. + * An unaligned memory access is executed. The result is checked. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + struct aligned_buffer buf = { + {0, 1, 2, 3, 4, 5, 6, 7}, + }; + void *v = &buf; + u32 r = 0; + + /* Read an unaligned address */ + r = deref(v + 1); + + /* UEFI only supports low endian systems */ + if (r != 0x04030201) { + efi_st_error("Unaligned access failed"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(unaligned) = { + .name = "unaligned memory access", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .execute = execute, +}; diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c new file mode 100644 index 00000000000..146378fb9a2 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_variables + * + * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * This unit test checks the following protocol services: + * ConnectController, DisconnectController, + * InstallProtocol, ReinstallProtocol, UninstallProtocol, + * OpenProtocol, CloseProtcol, OpenProtocolInformation + */ + +#include <efi_selftest.h> + +#define EFI_ST_MAX_DATA_SIZE 16 +#define EFI_ST_MAX_VARNAME_SIZE 40 + +static struct efi_boot_services *boottime; +static struct efi_runtime_services *runtime; +static efi_guid_t guid_vendor0 = + EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1, + 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6); +static efi_guid_t guid_vendor1 = + EFI_GUID(0xff629290, 0x1fc1, 0xd73f, + 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); + +/* + * Setup unit test. + * + * @handle handle of the loaded image + * @systable system table + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + boottime = systable->boottime; + runtime = systable->runtime; + + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + */ +static int execute(void) +{ + efi_status_t ret; + efi_uintn_t len; + u32 attr; + u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c, + 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,}; + u8 data[EFI_ST_MAX_DATA_SIZE]; + u16 varname[EFI_ST_MAX_VARNAME_SIZE]; + int flag; + efi_guid_t guid; + u64 max_storage, rem_storage, max_size; + + ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_SUCCESS) { + efi_st_todo("QueryVariableInfo failed\n"); + } else if (!max_storage || !rem_storage || !max_size) { + efi_st_error("QueryVariableInfo: wrong info\n"); + return EFI_ST_FAILURE; + } + /* Set variable 0 */ + ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 3, v + 4); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + data[3] = 0xff; + len = 3; + ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(data, v + 4, 3)) { + efi_st_error("GetVariable returned wrong value\n"); + return EFI_ST_FAILURE; + } + if (data[3] != 0xff) { + efi_st_error("GetVariable wrote past the end of the buffer\n"); + return EFI_ST_FAILURE; + } + /* Set variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 8, v); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (len != 8) { + efi_st_error("GetVariable returned wrong length %u\n", + (unsigned int)len); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(data, v, 8)) { + efi_st_error("GetVariable returned wrong value\n"); + return EFI_ST_FAILURE; + } + /* Append variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_APPEND_WRITE, + 7, v + 8); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (len != 15) + efi_st_todo("GetVariable returned wrong length %u\n", + (unsigned int)len); + if (efi_st_memcmp(data, v, len)) + efi_st_todo("GetVariable returned wrong value\n"); + /* Enumerate variables */ + boottime->set_mem(&guid, 16, 0); + *varname = 0; + flag = 0; + for (;;) { + len = EFI_ST_MAX_VARNAME_SIZE; + ret = runtime->get_next_variable_name(&len, varname, &guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret != EFI_SUCCESS) { + efi_st_todo("GetNextVariableName failed\n"); + break; + } + if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) && + !efi_st_strcmp_16_8(varname, "efi_st_var0")) + flag |= 2; + if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) && + !efi_st_strcmp_16_8(varname, "efi_st_var1")) + flag |= 2; + } + if (flag != 3) + efi_st_todo( + "GetNextVariableName did not return all variables\n"); + /* Delete variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Variable was not deleted\n"); + return EFI_ST_FAILURE; + } + /* Delete variable 0 */ + ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, + 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, + &attr, &len, data); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Variable was not deleted\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(variables) = { + .name = "variables", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, +}; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 69bf12623e0..f4e8dbf699a 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -72,6 +72,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"), COMPAT(ALTERA_SOCFPGA_FPGA0, "altr,socfpga-a10-fpga-mgr"), COMPAT(ALTERA_SOCFPGA_NOC, "altr,socfpga-a10-noc"), + COMPAT(ALTERA_SOCFPGA_CLK_INIT, "altr,socfpga-a10-clk-init") }; const char *fdtdec_get_compatible(enum fdt_compat_id id) diff --git a/lib/image-sparse.c b/lib/image-sparse.c new file mode 100644 index 00000000000..036062139bb --- /dev/null +++ b/lib/image-sparse.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2009, Google Inc. + * All rights reserved. + * + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. + * Portions Copyright 2014 Broadcom Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * NOTE: + * Although it is very similar, this license text is not identical + * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT! + */ + +#include <config.h> +#include <common.h> +#include <image-sparse.h> +#include <div64.h> +#include <malloc.h> +#include <part.h> +#include <sparse_format.h> + +#include <linux/math64.h> + +static void default_log(const char *ignored, char *response) {} + +int write_sparse_image(struct sparse_storage *info, + const char *part_name, void *data, char *response) +{ + lbaint_t blk; + lbaint_t blkcnt; + lbaint_t blks; + uint32_t bytes_written = 0; + unsigned int chunk; + unsigned int offset; + unsigned int chunk_data_sz; + uint32_t *fill_buf = NULL; + uint32_t fill_val; + sparse_header_t *sparse_header; + chunk_header_t *chunk_header; + uint32_t total_blocks = 0; + int fill_buf_num_blks; + int i; + int j; + + fill_buf_num_blks = CONFIG_IMAGE_SPARSE_FILLBUF_SIZE / info->blksz; + + /* Read and skip over sparse image header */ + sparse_header = (sparse_header_t *)data; + + data += sparse_header->file_hdr_sz; + if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) { + /* + * Skip the remaining bytes in a header that is longer than + * we expected. + */ + data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t)); + } + + if (!info->mssg) + info->mssg = default_log; + + debug("=== Sparse Image Header ===\n"); + debug("magic: 0x%x\n", sparse_header->magic); + debug("major_version: 0x%x\n", sparse_header->major_version); + debug("minor_version: 0x%x\n", sparse_header->minor_version); + debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz); + debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz); + debug("blk_sz: %d\n", sparse_header->blk_sz); + debug("total_blks: %d\n", sparse_header->total_blks); + debug("total_chunks: %d\n", sparse_header->total_chunks); + + /* + * Verify that the sparse block size is a multiple of our + * storage backend block size + */ + div_u64_rem(sparse_header->blk_sz, info->blksz, &offset); + if (offset) { + printf("%s: Sparse image block size issue [%u]\n", + __func__, sparse_header->blk_sz); + info->mssg("sparse image block size issue", response); + return -1; + } + + puts("Flashing Sparse Image\n"); + + /* Start processing chunks */ + blk = info->start; + for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) { + /* Read and skip over chunk header */ + chunk_header = (chunk_header_t *)data; + data += sizeof(chunk_header_t); + + if (chunk_header->chunk_type != CHUNK_TYPE_RAW) { + debug("=== Chunk Header ===\n"); + debug("chunk_type: 0x%x\n", chunk_header->chunk_type); + debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz); + debug("total_size: 0x%x\n", chunk_header->total_sz); + } + + if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) { + /* + * Skip the remaining bytes in a header that is longer + * than we expected. + */ + data += (sparse_header->chunk_hdr_sz - + sizeof(chunk_header_t)); + } + + chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz; + blkcnt = chunk_data_sz / info->blksz; + switch (chunk_header->chunk_type) { + case CHUNK_TYPE_RAW: + if (chunk_header->total_sz != + (sparse_header->chunk_hdr_sz + chunk_data_sz)) { + info->mssg("Bogus chunk size for chunk type Raw", + response); + return -1; + } + + if (blk + blkcnt > info->start + info->size) { + printf( + "%s: Request would exceed partition size!\n", + __func__); + info->mssg("Request would exceed partition size!", + response); + return -1; + } + + blks = info->write(info, blk, blkcnt, data); + /* blks might be > blkcnt (eg. NAND bad-blocks) */ + if (blks < blkcnt) { + printf("%s: %s" LBAFU " [" LBAFU "]\n", + __func__, "Write failed, block #", + blk, blks); + info->mssg("flash write failure", response); + return -1; + } + blk += blks; + bytes_written += blkcnt * info->blksz; + total_blocks += chunk_header->chunk_sz; + data += chunk_data_sz; + break; + + case CHUNK_TYPE_FILL: + if (chunk_header->total_sz != + (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) { + info->mssg("Bogus chunk size for chunk type FILL", response); + return -1; + } + + fill_buf = (uint32_t *) + memalign(ARCH_DMA_MINALIGN, + ROUNDUP( + info->blksz * fill_buf_num_blks, + ARCH_DMA_MINALIGN)); + if (!fill_buf) { + info->mssg("Malloc failed for: CHUNK_TYPE_FILL", + response); + return -1; + } + + fill_val = *(uint32_t *)data; + data = (char *)data + sizeof(uint32_t); + + for (i = 0; + i < (info->blksz * fill_buf_num_blks / + sizeof(fill_val)); + i++) + fill_buf[i] = fill_val; + + if (blk + blkcnt > info->start + info->size) { + printf( + "%s: Request would exceed partition size!\n", + __func__); + info->mssg("Request would exceed partition size!", + response); + return -1; + } + + for (i = 0; i < blkcnt;) { + j = blkcnt - i; + if (j > fill_buf_num_blks) + j = fill_buf_num_blks; + blks = info->write(info, blk, j, fill_buf); + /* blks might be > j (eg. NAND bad-blocks) */ + if (blks < j) { + printf("%s: %s " LBAFU " [%d]\n", + __func__, + "Write failed, block #", + blk, j); + info->mssg("flash write failure", + response); + free(fill_buf); + return -1; + } + blk += blks; + i += j; + } + bytes_written += blkcnt * info->blksz; + total_blocks += chunk_data_sz / sparse_header->blk_sz; + free(fill_buf); + break; + + case CHUNK_TYPE_DONT_CARE: + blk += info->reserve(info, blk, blkcnt); + total_blocks += chunk_header->chunk_sz; + break; + + case CHUNK_TYPE_CRC32: + if (chunk_header->total_sz != + sparse_header->chunk_hdr_sz) { + info->mssg("Bogus chunk size for chunk type Dont Care", + response); + return -1; + } + total_blocks += chunk_header->chunk_sz; + data += chunk_data_sz; + break; + + default: + printf("%s: Unknown chunk type: %x\n", __func__, + chunk_header->chunk_type); + info->mssg("Unknown chunk type", response); + return -1; + } + } + + debug("Wrote %d blocks, expected to write %d blocks\n", + total_blocks, sparse_header->total_blks); + printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name); + + if (total_blocks != sparse_header->total_blks) { + info->mssg("sparse image write failure", response); + return -1; + } + + return 0; +} diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 4b7008d88fe..b6ca4e0b0c3 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -76,8 +76,8 @@ uint32_t fdt_get_max_phandle(const void *fdt) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); + *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); return 0; } @@ -85,7 +85,7 @@ int fdt_num_mem_rsv(const void *fdt) { int i = 0; - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) i++; return i; } @@ -211,11 +211,11 @@ int fdt_path_offset(const void *fdt, const char *path) const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); int err; if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; if (len) @@ -233,7 +233,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset) { int offset; - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; return _nextprop(fdt, offset); @@ -241,7 +241,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset) int fdt_next_property_offset(const void *fdt, int offset) { - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) return offset; return _nextprop(fdt, offset); @@ -254,13 +254,13 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int err; const struct fdt_property *prop; - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } - prop = _fdt_offset_ptr(fdt, offset); + prop = fdt_offset_ptr_(fdt, offset); if (lenp) *lenp = fdt32_to_cpu(prop->len); diff --git a/lib/tpm-common.c b/lib/tpm-common.c new file mode 100644 index 00000000000..43b530865a0 --- /dev/null +++ b/lib/tpm-common.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * Coypright (c) 2013 Guntermann & Drunck GmbH + */ + +#include <common.h> +#include <dm.h> +#include <asm/unaligned.h> +#include <tpm-common.h> +#include "tpm-utils.h" + +int pack_byte_string(u8 *str, size_t size, const char *format, ...) +{ + va_list args; + size_t offset = 0, length = 0; + u8 *data = NULL; + u32 value = 0; + + va_start(args, format); + for (; *format; format++) { + switch (*format) { + case 'b': + offset = va_arg(args, size_t); + value = va_arg(args, int); + length = 1; + break; + case 'w': + offset = va_arg(args, size_t); + value = va_arg(args, int); + length = 2; + break; + case 'd': + offset = va_arg(args, size_t); + value = va_arg(args, u32); + length = 4; + break; + case 's': + offset = va_arg(args, size_t); + data = va_arg(args, u8 *); + length = va_arg(args, u32); + break; + default: + debug("Couldn't recognize format string\n"); + va_end(args); + return -1; + } + + if (offset + length > size) { + va_end(args); + return -1; + } + + switch (*format) { + case 'b': + str[offset] = value; + break; + case 'w': + put_unaligned_be16(value, str + offset); + break; + case 'd': + put_unaligned_be32(value, str + offset); + break; + case 's': + memcpy(str + offset, data, length); + break; + } + } + va_end(args); + + return 0; +} + +int unpack_byte_string(const u8 *str, size_t size, const char *format, ...) +{ + va_list args; + size_t offset = 0, length = 0; + u8 *ptr8 = NULL; + u16 *ptr16 = NULL; + u32 *ptr32 = NULL; + + va_start(args, format); + for (; *format; format++) { + switch (*format) { + case 'b': + offset = va_arg(args, size_t); + ptr8 = va_arg(args, u8 *); + length = 1; + break; + case 'w': + offset = va_arg(args, size_t); + ptr16 = va_arg(args, u16 *); + length = 2; + break; + case 'd': + offset = va_arg(args, size_t); + ptr32 = va_arg(args, u32 *); + length = 4; + break; + case 's': + offset = va_arg(args, size_t); + ptr8 = va_arg(args, u8 *); + length = va_arg(args, u32); + break; + default: + va_end(args); + debug("Couldn't recognize format string\n"); + return -1; + } + + if (offset + length > size) { + va_end(args); + return -1; + } + + switch (*format) { + case 'b': + *ptr8 = str[offset]; + break; + case 'w': + *ptr16 = get_unaligned_be16(str + offset); + break; + case 'd': + *ptr32 = get_unaligned_be32(str + offset); + break; + case 's': + memcpy(ptr8, str + offset, length); + break; + } + } + va_end(args); + + return 0; +} + +u32 tpm_command_size(const void *command) +{ + const size_t command_size_offset = 2; + + return get_unaligned_be32(command + command_size_offset); +} + +u32 tpm_return_code(const void *response) +{ + const size_t return_code_offset = 6; + + return get_unaligned_be32(response + return_code_offset); +} + +u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr) +{ + struct udevice *dev; + int err, ret; + u8 response_buffer[COMMAND_BUFFER_SIZE]; + size_t response_length; + int i; + + if (response) { + response_length = *size_ptr; + } else { + response = response_buffer; + response_length = sizeof(response_buffer); + } + + ret = uclass_first_device_err(UCLASS_TPM, &dev); + if (ret) + return ret; + err = tpm_xfer(dev, command, tpm_command_size(command), + response, &response_length); + + if (err < 0) + return err; + + if (size_ptr) + *size_ptr = response_length; + + ret = tpm_return_code(response); + + log(LOGC_NONE, LOGL_DEBUG, "TPM response [ret:%d]: ", ret); + for (i = 0; i < response_length; i++) + log(LOGC_NONE, LOGL_DEBUG, "%02x ", ((u8 *)response)[i]); + log(LOGC_NONE, LOGL_DEBUG, "\n"); + + return ret; +} + +int tpm_init(void) +{ + struct udevice *dev; + int err; + + err = uclass_first_device_err(UCLASS_TPM, &dev); + if (err) + return err; + + return tpm_open(dev); +} diff --git a/lib/tpm-utils.h b/lib/tpm-utils.h new file mode 100644 index 00000000000..a9cb7dc7ee5 --- /dev/null +++ b/lib/tpm-utils.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * Coypright (c) 2013 Guntermann & Drunck GmbH + */ + +#ifndef __TPM_UTILS_H +#define __TPM_UTILS_H + +#define COMMAND_BUFFER_SIZE 256 + +/* Internal error of TPM command library */ +#define TPM_LIB_ERROR ((u32)~0u) + +/* To make strings of commands more easily */ +#define __MSB(x) ((x) >> 8) +#define __LSB(x) ((x) & 0xFF) +#define tpm_u16(x) __MSB(x), __LSB(x) +#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF) + +/** + * tpm_open() - Request access to locality 0 for the caller + * + * After all commands have been completed the caller is supposed to + * call tpm_close(). + * + * Returns 0 on success, -ve on failure. + */ +int tpm_open(struct udevice *dev); + +/** + * tpm_close() - Close the current session + * + * Releasing the locked locality. Returns 0 on success, -ve 1 on + * failure (in case lock removal did not succeed). + */ +int tpm_close(struct udevice *dev); + +/** + * Pack data into a byte string. The data types are specified in + * the format string: 'b' means unsigned byte, 'w' unsigned word, + * 'd' unsigned double word, and 's' byte string. The data are a + * series of offsets and values (for type byte string there are also + * lengths). The data values are packed into the byte string + * sequentially, and so a latter value could over-write a former + * value. + * + * @param str output string + * @param size size of output string + * @param format format string + * @param ... data points + * @return 0 on success, non-0 on error + */ +int pack_byte_string(u8 *str, size_t size, const char *format, ...); + +/** + * Unpack data from a byte string. The data types are specified in + * the format string: 'b' means unsigned byte, 'w' unsigned word, + * 'd' unsigned double word, and 's' byte string. The data are a + * series of offsets and pointers (for type byte string there are also + * lengths). + * + * @param str output string + * @param size size of output string + * @param format format string + * @param ... data points + * @return 0 on success, non-0 on error + */ +int unpack_byte_string(const u8 *str, size_t size, const char *format, ...); + +/** + * Get TPM command size. + * + * @param command byte string of TPM command + * @return command size of the TPM command + */ +u32 tpm_command_size(const void *command); + +/** + * Get TPM response return code, which is one of TPM_RESULT values. + * + * @param response byte string of TPM response + * @return return code of the TPM response + */ +u32 tpm_return_code(const void *response); + +/** + * Send a TPM command and return response's return code, and optionally + * return response to caller. + * + * @param command byte string of TPM command + * @param response output buffer for TPM response, or NULL if the + * caller does not care about it + * @param size_ptr output buffer size (input parameter) and TPM + * response length (output parameter); this parameter + * is a bidirectional + * @return return code of the TPM response + */ +u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr); + +#endif /* __TPM_UTILS_H */ diff --git a/lib/tpm.c b/lib/tpm-v1.c index bc9652d8e4e..7aecb24f921 100644 --- a/lib/tpm.c +++ b/lib/tpm-v1.c @@ -6,26 +6,11 @@ #include <common.h> #include <dm.h> -#include <tpm.h> #include <asm/unaligned.h> #include <u-boot/sha1.h> - -/* Internal error of TPM command library */ -#define TPM_LIB_ERROR ((uint32_t)~0u) - -/* Useful constants */ -enum { - COMMAND_BUFFER_SIZE = 256, - TPM_REQUEST_HEADER_LENGTH = 10, - TPM_RESPONSE_HEADER_LENGTH = 10, - PCR_DIGEST_LENGTH = 20, - DIGEST_LENGTH = 20, - TPM_REQUEST_AUTH_LENGTH = 45, - TPM_RESPONSE_AUTH_LENGTH = 41, - /* some max lengths, valid for RSA keys <= 2048 bits */ - TPM_KEY12_MAX_LENGTH = 618, - TPM_PUBKEY_MAX_LENGTH = 288, -}; +#include <tpm-common.h> +#include <tpm-v1.h> +#include "tpm-utils.h" #ifdef CONFIG_TPM_AUTH_SESSIONS @@ -35,277 +20,50 @@ enum { struct session_data { int valid; - uint32_t handle; - uint8_t nonce_even[DIGEST_LENGTH]; - uint8_t nonce_odd[DIGEST_LENGTH]; + u32 handle; + u8 nonce_even[DIGEST_LENGTH]; + u8 nonce_odd[DIGEST_LENGTH]; }; static struct session_data oiap_session = {0, }; #endif /* CONFIG_TPM_AUTH_SESSIONS */ -/** - * Pack data into a byte string. The data types are specified in - * the format string: 'b' means unsigned byte, 'w' unsigned word, - * 'd' unsigned double word, and 's' byte string. The data are a - * series of offsets and values (for type byte string there are also - * lengths). The data values are packed into the byte string - * sequentially, and so a latter value could over-write a former - * value. - * - * @param str output string - * @param size size of output string - * @param format format string - * @param ... data points - * @return 0 on success, non-0 on error - */ -int pack_byte_string(uint8_t *str, size_t size, const char *format, ...) -{ - va_list args; - size_t offset = 0, length = 0; - uint8_t *data = NULL; - uint32_t value = 0; - - va_start(args, format); - for (; *format; format++) { - switch (*format) { - case 'b': - offset = va_arg(args, size_t); - value = va_arg(args, int); - length = 1; - break; - case 'w': - offset = va_arg(args, size_t); - value = va_arg(args, int); - length = 2; - break; - case 'd': - offset = va_arg(args, size_t); - value = va_arg(args, uint32_t); - length = 4; - break; - case 's': - offset = va_arg(args, size_t); - data = va_arg(args, uint8_t *); - length = va_arg(args, uint32_t); - break; - default: - debug("Couldn't recognize format string\n"); - va_end(args); - return -1; - } - - if (offset + length > size) { - va_end(args); - return -1; - } - - switch (*format) { - case 'b': - str[offset] = value; - break; - case 'w': - put_unaligned_be16(value, str + offset); - break; - case 'd': - put_unaligned_be32(value, str + offset); - break; - case 's': - memcpy(str + offset, data, length); - break; - } - } - va_end(args); - - return 0; -} - -/** - * Unpack data from a byte string. The data types are specified in - * the format string: 'b' means unsigned byte, 'w' unsigned word, - * 'd' unsigned double word, and 's' byte string. The data are a - * series of offsets and pointers (for type byte string there are also - * lengths). - * - * @param str output string - * @param size size of output string - * @param format format string - * @param ... data points - * @return 0 on success, non-0 on error - */ -int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...) -{ - va_list args; - size_t offset = 0, length = 0; - uint8_t *ptr8 = NULL; - uint16_t *ptr16 = NULL; - uint32_t *ptr32 = NULL; - - va_start(args, format); - for (; *format; format++) { - switch (*format) { - case 'b': - offset = va_arg(args, size_t); - ptr8 = va_arg(args, uint8_t *); - length = 1; - break; - case 'w': - offset = va_arg(args, size_t); - ptr16 = va_arg(args, uint16_t *); - length = 2; - break; - case 'd': - offset = va_arg(args, size_t); - ptr32 = va_arg(args, uint32_t *); - length = 4; - break; - case 's': - offset = va_arg(args, size_t); - ptr8 = va_arg(args, uint8_t *); - length = va_arg(args, uint32_t); - break; - default: - va_end(args); - debug("Couldn't recognize format string\n"); - return -1; - } - - if (offset + length > size) { - va_end(args); - return -1; - } - - switch (*format) { - case 'b': - *ptr8 = str[offset]; - break; - case 'w': - *ptr16 = get_unaligned_be16(str + offset); - break; - case 'd': - *ptr32 = get_unaligned_be32(str + offset); - break; - case 's': - memcpy(ptr8, str + offset, length); - break; - } - } - va_end(args); - - return 0; -} - -/** - * Get TPM command size. - * - * @param command byte string of TPM command - * @return command size of the TPM command - */ -static uint32_t tpm_command_size(const void *command) +u32 tpm_startup(enum tpm_startup_type mode) { - const size_t command_size_offset = 2; - return get_unaligned_be32(command + command_size_offset); -} - -/** - * Get TPM response return code, which is one of TPM_RESULT values. - * - * @param response byte string of TPM response - * @return return code of the TPM response - */ -static uint32_t tpm_return_code(const void *response) -{ - const size_t return_code_offset = 6; - return get_unaligned_be32(response + return_code_offset); -} - -/** - * Send a TPM command and return response's return code, and optionally - * return response to caller. - * - * @param command byte string of TPM command - * @param response output buffer for TPM response, or NULL if the - * caller does not care about it - * @param size_ptr output buffer size (input parameter) and TPM - * response length (output parameter); this parameter - * is a bidirectional - * @return return code of the TPM response - */ -static uint32_t tpm_sendrecv_command(const void *command, - void *response, size_t *size_ptr) -{ - struct udevice *dev; - int err, ret; - uint8_t response_buffer[COMMAND_BUFFER_SIZE]; - size_t response_length; - - if (response) { - response_length = *size_ptr; - } else { - response = response_buffer; - response_length = sizeof(response_buffer); - } - - ret = uclass_first_device_err(UCLASS_TPM, &dev); - if (ret) - return ret; - err = tpm_xfer(dev, command, tpm_command_size(command), - response, &response_length); - - if (err < 0) - return TPM_LIB_ERROR; - if (size_ptr) - *size_ptr = response_length; - - return tpm_return_code(response); -} - -int tpm_init(void) -{ - int err; - struct udevice *dev; - - err = uclass_first_device_err(UCLASS_TPM, &dev); - if (err) - return err; - return tpm_open(dev); -} - -uint32_t tpm_startup(enum tpm_startup_type mode) -{ - const uint8_t command[12] = { + const u8 command[12] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0, }; const size_t mode_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE]; if (pack_byte_string(buf, sizeof(buf), "sw", - 0, command, sizeof(command), - mode_offset, mode)) + 0, command, sizeof(command), + mode_offset, mode)) return TPM_LIB_ERROR; return tpm_sendrecv_command(buf, NULL, NULL); } -uint32_t tpm_self_test_full(void) +u32 tpm_self_test_full(void) { - const uint8_t command[10] = { + const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }; return tpm_sendrecv_command(command, NULL, NULL); } -uint32_t tpm_continue_self_test(void) +u32 tpm_continue_self_test(void) { - const uint8_t command[10] = { + const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }; return tpm_sendrecv_command(command, NULL, NULL); } -uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size) +u32 tpm_nv_define_space(u32 index, u32 perm, u32 size) { - const uint8_t command[101] = { + const u8 command[101] = { 0x0, 0xc1, /* TPM_TAG */ 0x0, 0x0, 0x0, 0x65, /* parameter size */ 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */ @@ -334,55 +92,55 @@ uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size) const size_t index_offset = 12; const size_t perm_offset = 70; const size_t size_offset = 77; - uint8_t buf[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE]; if (pack_byte_string(buf, sizeof(buf), "sddd", - 0, command, sizeof(command), - index_offset, index, - perm_offset, perm, - size_offset, size)) + 0, command, sizeof(command), + index_offset, index, + perm_offset, perm, + size_offset, size)) return TPM_LIB_ERROR; return tpm_sendrecv_command(buf, NULL, NULL); } -uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count) +u32 tpm_nv_read_value(u32 index, void *data, u32 count) { - const uint8_t command[22] = { + const u8 command[22] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }; const size_t index_offset = 10; const size_t length_offset = 18; const size_t data_size_offset = 10; const size_t data_offset = 14; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t data_size; - uint32_t err; + u32 data_size; + u32 err; if (pack_byte_string(buf, sizeof(buf), "sdd", - 0, command, sizeof(command), - index_offset, index, - length_offset, count)) + 0, command, sizeof(command), + index_offset, index, + length_offset, count)) return TPM_LIB_ERROR; err = tpm_sendrecv_command(buf, response, &response_length); if (err) return err; if (unpack_byte_string(response, response_length, "d", - data_size_offset, &data_size)) + data_size_offset, &data_size)) return TPM_LIB_ERROR; if (data_size > count) return TPM_LIB_ERROR; if (unpack_byte_string(response, response_length, "s", - data_offset, data, data_size)) + data_offset, data, data_size)) return TPM_LIB_ERROR; return 0; } -uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length) +u32 tpm_nv_write_value(u32 index, const void *data, u32 length) { - const uint8_t command[256] = { + const u8 command[256] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }; const size_t command_size_offset = 2; @@ -390,18 +148,18 @@ uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length) const size_t length_offset = 18; const size_t data_offset = 22; const size_t write_info_size = 12; - const uint32_t total_length = + const u32 total_length = TPM_REQUEST_HEADER_LENGTH + write_info_size + length; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (pack_byte_string(buf, sizeof(buf), "sddds", - 0, command, sizeof(command), - command_size_offset, total_length, - index_offset, index, - length_offset, length, - data_offset, data, length)) + 0, command, sizeof(command), + command_size_offset, total_length, + index_offset, index, + length_offset, length, + data_offset, data, length)) return TPM_LIB_ERROR; err = tpm_sendrecv_command(buf, response, &response_length); if (err) @@ -410,99 +168,99 @@ uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length) return 0; } -uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest) +u32 tpm_extend(u32 index, const void *in_digest, void *out_digest) { - const uint8_t command[34] = { + const u8 command[34] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }; const size_t index_offset = 10; const size_t in_digest_offset = 14; const size_t out_digest_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE]; - uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH]; + u8 buf[COMMAND_BUFFER_SIZE]; + u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (pack_byte_string(buf, sizeof(buf), "sds", - 0, command, sizeof(command), - index_offset, index, - in_digest_offset, in_digest, - PCR_DIGEST_LENGTH)) + 0, command, sizeof(command), + index_offset, index, + in_digest_offset, in_digest, + PCR_DIGEST_LENGTH)) return TPM_LIB_ERROR; err = tpm_sendrecv_command(buf, response, &response_length); if (err) return err; if (unpack_byte_string(response, response_length, "s", - out_digest_offset, out_digest, - PCR_DIGEST_LENGTH)) + out_digest_offset, out_digest, + PCR_DIGEST_LENGTH)) return TPM_LIB_ERROR; return 0; } -uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count) +u32 tpm_pcr_read(u32 index, void *data, size_t count) { - const uint8_t command[14] = { + const u8 command[14] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }; const size_t index_offset = 10; const size_t out_digest_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (count < PCR_DIGEST_LENGTH) return TPM_LIB_ERROR; if (pack_byte_string(buf, sizeof(buf), "sd", - 0, command, sizeof(command), - index_offset, index)) + 0, command, sizeof(command), + index_offset, index)) return TPM_LIB_ERROR; err = tpm_sendrecv_command(buf, response, &response_length); if (err) return err; if (unpack_byte_string(response, response_length, "s", - out_digest_offset, data, PCR_DIGEST_LENGTH)) + out_digest_offset, data, PCR_DIGEST_LENGTH)) return TPM_LIB_ERROR; return 0; } -uint32_t tpm_tsc_physical_presence(uint16_t presence) +u32 tpm_tsc_physical_presence(u16 presence) { - const uint8_t command[12] = { + const u8 command[12] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0, }; const size_t presence_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE]; if (pack_byte_string(buf, sizeof(buf), "sw", - 0, command, sizeof(command), - presence_offset, presence)) + 0, command, sizeof(command), + presence_offset, presence)) return TPM_LIB_ERROR; return tpm_sendrecv_command(buf, NULL, NULL); } -uint32_t tpm_read_pubek(void *data, size_t count) +u32 tpm_read_pubek(void *data, size_t count) { - const uint8_t command[30] = { + const u8 command[30] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }; const size_t response_size_offset = 2; const size_t data_offset = 10; const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20; - uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE]; + u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE]; size_t response_length = sizeof(response); - uint32_t data_size; - uint32_t err; + u32 data_size; + u32 err; err = tpm_sendrecv_command(command, response, &response_length); if (err) return err; if (unpack_byte_string(response, response_length, "d", - response_size_offset, &data_size)) + response_size_offset, &data_size)) return TPM_LIB_ERROR; if (data_size < header_and_checksum_size) return TPM_LIB_ERROR; @@ -510,59 +268,58 @@ uint32_t tpm_read_pubek(void *data, size_t count) if (data_size > count) return TPM_LIB_ERROR; if (unpack_byte_string(response, response_length, "s", - data_offset, data, data_size)) + data_offset, data, data_size)) return TPM_LIB_ERROR; return 0; } -uint32_t tpm_force_clear(void) +u32 tpm_force_clear(void) { - const uint8_t command[10] = { + const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }; return tpm_sendrecv_command(command, NULL, NULL); } -uint32_t tpm_physical_enable(void) +u32 tpm_physical_enable(void) { - const uint8_t command[10] = { + const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }; return tpm_sendrecv_command(command, NULL, NULL); } -uint32_t tpm_physical_disable(void) +u32 tpm_physical_disable(void) { - const uint8_t command[10] = { + const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }; return tpm_sendrecv_command(command, NULL, NULL); } -uint32_t tpm_physical_set_deactivated(uint8_t state) +u32 tpm_physical_set_deactivated(u8 state) { - const uint8_t command[11] = { + const u8 command[11] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }; const size_t state_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE]; if (pack_byte_string(buf, sizeof(buf), "sb", - 0, command, sizeof(command), - state_offset, state)) + 0, command, sizeof(command), + state_offset, state)) return TPM_LIB_ERROR; return tpm_sendrecv_command(buf, NULL, NULL); } -uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, - void *cap, size_t count) +u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count) { - const uint8_t command[22] = { + const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ 0x0, 0x0, 0x0, 0x16, /* parameter size */ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ @@ -574,34 +331,34 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, const size_t sub_cap_offset = 18; const size_t cap_offset = 14; const size_t cap_size_offset = 10; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t cap_size; - uint32_t err; + u32 cap_size; + u32 err; if (pack_byte_string(buf, sizeof(buf), "sdd", - 0, command, sizeof(command), - cap_area_offset, cap_area, - sub_cap_offset, sub_cap)) + 0, command, sizeof(command), + cap_area_offset, cap_area, + sub_cap_offset, sub_cap)) return TPM_LIB_ERROR; err = tpm_sendrecv_command(buf, response, &response_length); if (err) return err; if (unpack_byte_string(response, response_length, "d", - cap_size_offset, &cap_size)) + cap_size_offset, &cap_size)) return TPM_LIB_ERROR; if (cap_size > response_length || cap_size > count) return TPM_LIB_ERROR; if (unpack_byte_string(response, response_length, "s", - cap_offset, cap, cap_size)) + cap_offset, cap, cap_size)) return TPM_LIB_ERROR; return 0; } -uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) +u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) { - const uint8_t command[22] = { + const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ 0x0, 0x0, 0x0, 0x16, /* parameter size */ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ @@ -610,11 +367,11 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) 0x0, 0x0, 0x1, 0x8, /* subcap value */ }; const size_t data_size_offset = TPM_HEADER_SIZE; - const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t); - uint8_t response[COMMAND_BUFFER_SIZE]; + const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32); + u8 response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; - uint32_t data_size; + u32 err; + u32 data_size; err = tpm_sendrecv_command(command, response, &response_length); if (err) @@ -631,9 +388,9 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) return 0; } -uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) +u32 tpm_get_permissions(u32 index, u32 *perm) { - const uint8_t command[22] = { + const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ 0x0, 0x0, 0x0, 0x16, /* parameter size */ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ @@ -642,9 +399,9 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) }; const size_t index_offset = 18; const size_t perm_offset = 60; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command), index_offset, index)) @@ -660,9 +417,9 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) } #ifdef CONFIG_TPM_FLUSH_RESOURCES -uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type) +u32 tpm_flush_specific(u32 key_handle, u32 resource_type) { - const uint8_t command[18] = { + const u8 command[18] = { 0x00, 0xc1, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x12, /* parameter size */ 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */ @@ -671,9 +428,9 @@ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type) }; const size_t key_handle_offset = 10; const size_t resource_type_offset = 14; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (pack_byte_string(buf, sizeof(buf), "sdd", 0, command, sizeof(command), @@ -702,12 +459,12 @@ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type) * @param request_auth pointer to the auth block of the request to be filled * @param auth authentication data (HMAC key) */ -static uint32_t create_request_auth(const void *request, size_t request_len0, - size_t handles_len, - struct session_data *auth_session, - void *request_auth, const void *auth) +static u32 create_request_auth(const void *request, size_t request_len0, + size_t handles_len, + struct session_data *auth_session, + void *request_auth, const void *auth) { - uint8_t hmac_data[DIGEST_LENGTH * 3 + 1]; + u8 hmac_data[DIGEST_LENGTH * 3 + 1]; sha1_context hash_ctx; const size_t command_code_offset = 6; const size_t auth_nonce_odd_offset = 4; @@ -765,19 +522,18 @@ static uint32_t create_request_auth(const void *request, size_t request_len0, * @param response_auth pointer to the auth block of the response to be verified * @param auth authentication data (HMAC key) */ -static uint32_t verify_response_auth(uint32_t command_code, - const void *response, size_t response_len0, - size_t handles_len, - struct session_data *auth_session, - const void *response_auth, const void *auth) +static u32 verify_response_auth(u32 command_code, const void *response, + size_t response_len0, size_t handles_len, + struct session_data *auth_session, + const void *response_auth, const void *auth) { - uint8_t hmac_data[DIGEST_LENGTH * 3 + 1]; - uint8_t computed_auth[DIGEST_LENGTH]; + u8 hmac_data[DIGEST_LENGTH * 3 + 1]; + u8 computed_auth[DIGEST_LENGTH]; sha1_context hash_ctx; const size_t return_code_offset = 6; const size_t auth_continue_offset = 20; const size_t auth_auth_offset = 21; - uint8_t auth_continue; + u8 auth_continue; if (!auth_session || !auth_session->valid) return TPM_AUTHFAIL; @@ -798,7 +554,7 @@ static uint32_t verify_response_auth(uint32_t command_code, sha1_finish(&hash_ctx, hmac_data); memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH); - auth_continue = ((uint8_t *)response_auth)[auth_continue_offset]; + auth_continue = ((u8 *)response_auth)[auth_continue_offset]; if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb", DIGEST_LENGTH, response_auth, @@ -820,18 +576,17 @@ static uint32_t verify_response_auth(uint32_t command_code, return TPM_SUCCESS; } - -uint32_t tpm_terminate_auth_session(uint32_t auth_handle) +u32 tpm_terminate_auth_session(u32 auth_handle) { - const uint8_t command[18] = { + const u8 command[18] = { 0x00, 0xc1, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x00, /* parameter size */ 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */ 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */ - 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */ + 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */ }; const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH; - uint8_t request[COMMAND_BUFFER_SIZE]; + u8 request[COMMAND_BUFFER_SIZE]; if (pack_byte_string(request, sizeof(request), "sd", 0, command, sizeof(command), @@ -843,26 +598,27 @@ uint32_t tpm_terminate_auth_session(uint32_t auth_handle) return tpm_sendrecv_command(request, NULL, NULL); } -uint32_t tpm_end_oiap(void) +u32 tpm_end_oiap(void) { - uint32_t err = TPM_SUCCESS; + u32 err = TPM_SUCCESS; + if (oiap_session.valid) err = tpm_terminate_auth_session(oiap_session.handle); return err; } -uint32_t tpm_oiap(uint32_t *auth_handle) +u32 tpm_oiap(u32 *auth_handle) { - const uint8_t command[10] = { + const u8 command[10] = { 0x00, 0xc1, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x0a, /* parameter size */ 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */ }; const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH; const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4; - uint8_t response[COMMAND_BUFFER_SIZE]; + u8 response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (oiap_session.valid) tpm_terminate_auth_session(oiap_session.handle); @@ -873,7 +629,7 @@ uint32_t tpm_oiap(uint32_t *auth_handle) if (unpack_byte_string(response, response_length, "ds", res_auth_handle_offset, &oiap_session.handle, res_nonce_even_offset, &oiap_session.nonce_even, - (uint32_t)DIGEST_LENGTH)) + (u32)DIGEST_LENGTH)) return TPM_LIB_ERROR; oiap_session.valid = 1; if (auth_handle) @@ -881,12 +637,10 @@ uint32_t tpm_oiap(uint32_t *auth_handle) return 0; } -uint32_t tpm_load_key2_oiap(uint32_t parent_handle, - const void *key, size_t key_length, - const void *parent_key_usage_auth, - uint32_t *key_handle) +u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length, + const void *parent_key_usage_auth, u32 *key_handle) { - const uint8_t command[14] = { + const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x00, /* parameter size */ 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */ @@ -896,11 +650,11 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH; const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4; const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH; - uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH - + TPM_REQUEST_AUTH_LENGTH]; - uint8_t response[COMMAND_BUFFER_SIZE]; + u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH + + TPM_REQUEST_AUTH_LENGTH]; + u8 response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (!oiap_session.valid) { err = tpm_oiap(NULL); @@ -918,9 +672,9 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, return TPM_LIB_ERROR; err = create_request_auth(request, sizeof(command) + key_length, 4, - &oiap_session, - request + sizeof(command) + key_length, - parent_key_usage_auth); + &oiap_session, + request + sizeof(command) + key_length, + parent_key_usage_auth); if (err) return err; err = tpm_sendrecv_command(request, response, &response_length); @@ -931,10 +685,11 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, } err = verify_response_auth(0x00000041, response, - response_length - TPM_RESPONSE_AUTH_LENGTH, - 4, &oiap_session, - response + response_length - TPM_RESPONSE_AUTH_LENGTH, - parent_key_usage_auth); + response_length - TPM_RESPONSE_AUTH_LENGTH, + 4, &oiap_session, + response + response_length - + TPM_RESPONSE_AUTH_LENGTH, + parent_key_usage_auth); if (err) return err; @@ -947,10 +702,10 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, return 0; } -uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, - void *pubkey, size_t *pubkey_len) +u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey, + size_t *pubkey_len) { - const uint8_t command[14] = { + const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x00, /* parameter size */ 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */ @@ -959,11 +714,11 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, const size_t req_size_offset = 2; const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH; const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH; - uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH]; - uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH - + TPM_RESPONSE_AUTH_LENGTH]; + u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH]; + u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH + + TPM_RESPONSE_AUTH_LENGTH]; size_t response_length = sizeof(response); - uint32_t err; + u32 err; if (!oiap_session.valid) { err = tpm_oiap(NULL); @@ -973,13 +728,13 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, if (pack_byte_string(request, sizeof(request), "sdd", 0, command, sizeof(command), req_size_offset, - (uint32_t)(sizeof(command) + (u32)(sizeof(command) + TPM_REQUEST_AUTH_LENGTH), req_key_handle_offset, key_handle )) return TPM_LIB_ERROR; err = create_request_auth(request, sizeof(command), 4, &oiap_session, - request + sizeof(command), usage_auth); + request + sizeof(command), usage_auth); if (err) return err; err = tpm_sendrecv_command(request, response, &response_length); @@ -989,16 +744,17 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, return err; } err = verify_response_auth(0x00000021, response, - response_length - TPM_RESPONSE_AUTH_LENGTH, - 0, &oiap_session, - response + response_length - TPM_RESPONSE_AUTH_LENGTH, - usage_auth); + response_length - TPM_RESPONSE_AUTH_LENGTH, + 0, &oiap_session, + response + response_length - + TPM_RESPONSE_AUTH_LENGTH, + usage_auth); if (err) return err; if (pubkey) { if ((response_length - TPM_RESPONSE_HEADER_LENGTH - - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len) + - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len) return TPM_LIB_ERROR; *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH - TPM_RESPONSE_AUTH_LENGTH; @@ -1011,15 +767,15 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, } #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 -uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t - pubkey_digest[20], uint32_t *handle) -{ - uint16_t key_count; - uint32_t key_handles[10]; - uint8_t buf[288]; - uint8_t *ptr; - uint32_t err; - uint8_t digest[20]; +u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20], + u32 *handle) +{ + u16 key_count; + u32 key_handles[10]; + u8 buf[288]; + u8 *ptr; + u32 err; + u8 digest[20]; size_t buf_len; unsigned int i; @@ -1052,9 +808,9 @@ uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t #endif /* CONFIG_TPM_AUTH_SESSIONS */ -uint32_t tpm_get_random(void *data, uint32_t count) +u32 tpm_get_random(void *data, u32 count) { - const uint8_t command[14] = { + const u8 command[14] = { 0x0, 0xc1, /* TPM_TAG */ 0x0, 0x0, 0x0, 0xe, /* parameter size */ 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */ @@ -1062,15 +818,15 @@ uint32_t tpm_get_random(void *data, uint32_t count) const size_t length_offset = 10; const size_t data_size_offset = 10; const size_t data_offset = 14; - uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); - uint32_t data_size; - uint8_t *out = data; + u32 data_size; + u8 *out = data; while (count > 0) { - uint32_t this_bytes = min((size_t)count, - sizeof (response) - data_offset); - uint32_t err; + u32 this_bytes = min((size_t)count, + sizeof(response) - data_offset); + u32 err; if (pack_byte_string(buf, sizeof(buf), "sd", 0, command, sizeof(command), diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c new file mode 100644 index 00000000000..f1bbca8e7aa --- /dev/null +++ b/lib/tpm-v2.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 Bootlin + * Author: Miquel Raynal <miquel.raynal@bootlin.com> + */ + +#include <common.h> +#include <dm.h> +#include <tpm-common.h> +#include <tpm-v2.h> +#include "tpm-utils.h" + +u32 tpm2_startup(enum tpm2_startup_types mode) +{ + const u8 command_v2[12] = { + tpm_u16(TPM2_ST_NO_SESSIONS), + tpm_u32(12), + tpm_u32(TPM2_CC_STARTUP), + tpm_u16(mode), + }; + int ret; + + /* + * Note TPM2_Startup command will return RC_SUCCESS the first time, + * but will return RC_INITIALIZE otherwise. + */ + ret = tpm_sendrecv_command(command_v2, NULL, NULL); + if (ret && ret != TPM2_RC_INITIALIZE) + return ret; + + return 0; +} + +u32 tpm2_self_test(enum tpm2_yes_no full_test) +{ + const u8 command_v2[12] = { + tpm_u16(TPM2_ST_NO_SESSIONS), + tpm_u32(11), + tpm_u32(TPM2_CC_SELF_TEST), + full_test, + }; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_clear(u32 handle, const char *pw, const ssize_t pw_sz) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(27 + pw_sz), /* Length */ + tpm_u32(TPM2_CC_CLEAR), /* Command code */ + + /* HANDLE */ + tpm_u32(handle), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz), /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + }; + unsigned int offset = 27; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "s", + offset, pw, pw_sz); + offset += pw_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_pcr_extend(u32 index, const uint8_t *digest) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(33 + TPM2_DIGEST_LEN), /* Length */ + tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */ + + /* HANDLE */ + tpm_u32(index), /* Handle (PCR Index) */ + + /* AUTH_SESSION */ + tpm_u32(9), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(0), /* Size of <hmac/password> */ + /* <hmac/password> (if any) */ + tpm_u32(1), /* Count (number of hashes) */ + tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */ + /* STRING(digest) Digest */ + }; + unsigned int offset = 33; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the digest + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "s", + offset, digest, TPM2_DIGEST_LEN); + offset += TPM2_DIGEST_LEN; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_pcr_read(u32 idx, unsigned int idx_min_sz, void *data, + unsigned int *updates) +{ + u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8)); + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */ + tpm_u32(17 + idx_array_sz), /* Length */ + tpm_u32(TPM2_CC_PCR_READ), /* Command code */ + + /* TPML_PCR_SELECTION */ + tpm_u32(1), /* Number of selections */ + tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */ + idx_array_sz, /* Array size for selection */ + /* bitmap(idx) Selected PCR bitmap */ + }; + size_t response_len = COMMAND_BUFFER_SIZE; + u8 response[COMMAND_BUFFER_SIZE]; + unsigned int pcr_sel_idx = idx / 8; + u8 pcr_sel_bit = BIT(idx % 8); + unsigned int counter = 0; + int ret; + + if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b", + 17 + pcr_sel_idx, pcr_sel_bit)) + return TPM_LIB_ERROR; + + ret = tpm_sendrecv_command(command_v2, response, &response_len); + if (ret) + return ret; + + if (unpack_byte_string(response, response_len, "ds", + 10, &counter, + response_len - TPM2_DIGEST_LEN, data, + TPM2_DIGEST_LEN)) + return TPM_LIB_ERROR; + + if (updates) + *updates = counter; + + return 0; +} + +u32 tpm2_get_capability(u32 capability, u32 property, void *buf, + size_t prop_count) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */ + tpm_u32(22), /* Length */ + tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */ + + tpm_u32(capability), /* Capability */ + tpm_u32(property), /* Property */ + tpm_u32(prop_count), /* Property count */ + }; + u8 response[COMMAND_BUFFER_SIZE]; + size_t response_len = COMMAND_BUFFER_SIZE; + unsigned int properties_off; + int ret; + + ret = tpm_sendrecv_command(command_v2, response, &response_len); + if (ret) + return ret; + + /* + * In the response buffer, the properties are located after the: + * tag (u16), response size (u32), response code (u32), + * YES/NO flag (u8), TPM_CAP (u32) and TPMU_CAPABILITIES (u32). + */ + properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) + + sizeof(u8) + sizeof(u32) + sizeof(u32); + memcpy(buf, &response[properties_off], response_len - properties_off); + + return 0; +} + +u32 tpm2_dam_reset(const char *pw, const ssize_t pw_sz) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(27 + pw_sz), /* Length */ + tpm_u32(TPM2_CC_DAM_RESET), /* Command code */ + + /* HANDLE */ + tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz), /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + }; + unsigned int offset = 27; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "s", + offset, pw, pw_sz); + offset += pw_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz, + unsigned int max_tries, unsigned int recovery_time, + unsigned int lockout_recovery) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(27 + pw_sz + 12), /* Length */ + tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */ + + /* HANDLE */ + tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz), /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + + /* LOCKOUT PARAMETERS */ + /* tpm_u32(max_tries) Max tries (0, always lock) */ + /* tpm_u32(recovery_time) Recovery time (0, no lock) */ + /* tpm_u32(lockout_recovery) Lockout recovery */ + }; + unsigned int offset = 27; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + * - max tries + * - recovery time + * - lockout recovery + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd", + offset, pw, pw_sz, + offset + pw_sz, max_tries, + offset + pw_sz + 4, recovery_time, + offset + pw_sz + 8, lockout_recovery); + offset += pw_sz + 12; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz, + const char *oldpw, const ssize_t oldpw_sz) +{ + unsigned int offset = 27; + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */ + tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */ + + /* HANDLE */ + tpm_u32(handle), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + oldpw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(oldpw_sz) /* Size of <hmac/password> */ + /* STRING(oldpw) <hmac/password> (if any) */ + + /* TPM2B_AUTH (TPM2B_DIGEST) */ + /* tpm_u16(newpw_sz) Digest size, new pw length */ + /* STRING(newpw) Digest buffer, new pw */ + }; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the old password (if any) + * - size of the new password + * - new password + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "sws", + offset, oldpw, oldpw_sz, + offset + oldpw_sz, newpw_sz, + offset + oldpw_sz + 2, newpw, newpw_sz); + offset += oldpw_sz + 2 + newpw_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index, + const char *key) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */ + tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */ + + /* HANDLE */ + tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz) /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + + /* TPM2B_AUTH (TPM2B_DIGEST) */ + /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */ + /* STRING(key) Digest buffer (PCR key) */ + + /* TPMI_ALG_HASH */ + /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */ + + /* TPMI_DH_PCR */ + /* tpm_u32(index), PCR Index */ + }; + unsigned int offset = 27; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + * - the PCR key length + * - the PCR key + * - the hash algorithm + * - the PCR index + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd", + offset, pw, pw_sz, + offset + pw_sz, TPM2_DIGEST_LEN, + offset + pw_sz + 2, key, TPM2_DIGEST_LEN, + offset + pw_sz + 2 + TPM2_DIGEST_LEN, + TPM2_ALG_SHA256, + offset + pw_sz + 4 + TPM2_DIGEST_LEN, index); + offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +u32 tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index, + const char *key, const ssize_t key_sz) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */ + tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */ + + /* HANDLE */ + tpm_u32(index), /* Handle (PCR Index) */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz), /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + + /* TPM2B_DIGEST */ + /* tpm_u16(key_sz) Key length */ + /* STRING(key) Key */ + }; + unsigned int offset = 27; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + * - the number of digests, 1 in our case + * - the algorithm, sha256 in our case + * - the digest (64 bytes) + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "sws", + offset, pw, pw_sz, + offset + pw_sz, key_sz, + offset + pw_sz + 2, key, key_sz); + offset += pw_sz + 2 + key_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} |