Scripts:
* Update spelling.txt

LMB:
* remove extern keyword in lmb.h
* drop unused lmb_size_bytes()

Test:
* test truncation in snprintf()

Documentation:
* add include/lmb.h to HTML documentation

UEFI:
* reduce non-debug logging output for measured boot
* fix use after free in measured boot
* startup the tpm device when installing the protocol
* implement EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES
* record capsule result only if capsule is read
This commit is contained in:
Tom Rini 2021-11-20 09:36:37 -05:00
commit 2ad8d0cb95
13 changed files with 631 additions and 110 deletions

View file

@ -10,6 +10,7 @@ U-Boot API documentation
efi
getopt
linker_lists
lmb
logging
pinctrl
rng

7
doc/api/lmb.rst Normal file
View file

@ -0,0 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0+
Logical memory blocks
=====================
.. kernel-doc:: include/lmb.h
:internal:

View file

@ -4,7 +4,7 @@
Tracing in U-Boot
=================
U-Boot supports a simple tracing feature which allows a record of excecution
U-Boot supports a simple tracing feature which allows a record of execution
to be collected and sent to a host machine for analysis. At present the
main use for this is to profile boot time.
@ -161,10 +161,10 @@ limit of the trace buffer size you have specified. Once that is exhausted
no more data will be collected.
Collecting trace data has an affect on execution time/performance. You
will notice this particularly with trvial functions - the overhead of
will notice this particularly with trivial functions - the overhead of
recording their execution may even exceed their normal execution time.
In practice this doesn't matter much so long as you are aware of the
effect. Once you have done your optimisations, turn off tracing before
effect. Once you have done your optimizations, turn off tracing before
doing end-to-end timing.
The best time to start tracing is right at the beginning of U-Boot. The
@ -184,7 +184,7 @@ the OS. In practical terms, U-Boot runs the 'fakegocmd' environment
variable at this point. This variable should have a short script which
collects the trace data and writes it somewhere.
Trace data collection relies on a microsecond timer, accesed through
Trace data collection relies on a microsecond timer, accessed through
timer_get_us(). So the first think you should do is make sure that
this produces sensible results for your board. Suitable sources for
this timer include high resolution timers, PWMs or profile timers if
@ -285,7 +285,7 @@ Options
Specify U-Boot map file
-p <trace_file>
Specifiy profile/trace file
Specify profile/trace file
Commands:
@ -315,11 +315,11 @@ time:
2. Build U-Boot with tracing and run it. Note the difference in boot time
(it is common for tracing to add 10% to the time)
3. Collect the trace information as descibed above. Use this to find where
3. Collect the trace information as described above. Use this to find where
all the time is being spent.
4. Take a look at that code and see if you can optimise it. Perhaps it is
possible to speed up the initialisation of a device, or remove an unused
4. Take a look at that code and see if you can optimize it. Perhaps it is
possible to speed up the initialization of a device, or remove an unused
feature.
5. Rebuild, run and collect again. Compare your results.

View file

@ -20,8 +20,8 @@
#include <charset.h>
#include <pe.h>
/* UEFI spec version 2.8 */
#define EFI_SPECIFICATION_VERSION (2 << 16 | 80)
/* UEFI spec version 2.9 */
#define EFI_SPECIFICATION_VERSION (2 << 16 | 90)
/* Types and defines for EFI CreateEvent */
enum efi_timer_delay {
@ -360,10 +360,15 @@ struct efi_runtime_services {
};
/* EFI event group GUID definitions */
#define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \
EFI_GUID(0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, \
0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf)
#define EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES \
EFI_GUID(0x8be0e274, 0x3970, 0x4b44, 0x80, 0xc5, \
0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc)
#define EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE \
EFI_GUID(0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, \
0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96)
@ -376,6 +381,10 @@ struct efi_runtime_services {
EFI_GUID(0x7ce88fb3, 0x4bd7, 0x4679, 0x87, 0xa8, \
0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b)
#define EFI_EVENT_GROUP_AFTER_READY_TO_BOOT \
EFI_GUID(0x3a2a00ad, 0x98b9, 0x4cdf, 0xa4, 0x78, \
0x70, 0x27, 0x77, 0xf1, 0xc1, 0xb)
#define EFI_EVENT_GROUP_RESET_SYSTEM \
EFI_GUID(0x62da6a56, 0x13fb, 0x485a, 0xa8, 0xda, \
0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b)
@ -417,6 +426,15 @@ struct efi_runtime_services {
EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \
0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
/**
* struct efi_configuration_table - EFI Configuration Table
*
* This table contains a set of GUID/pointer pairs.
* The EFI Configuration Table may contain at most one instance of each table type.
*
* @guid: GUID that uniquely identifies the system configuration table
* @table: A pointer to the table associated with guid
*/
struct efi_configuration_table {
efi_guid_t guid;
void *table;
@ -424,6 +442,29 @@ struct efi_configuration_table {
#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
/**
* struct efi_system_table - EFI System Table
*
* EFI System Table contains pointers to the runtime and boot services tables.
*
* @hdr: The table header for the EFI System Table
* @fw_vendor: A pointer to a null terminated string that identifies the vendor
* that produces the system firmware
* @fw_revision: The revision of the system firmware
* @con_in_handle: The handle for the active console input device
* @con_in: A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface
* that is associated with con_in_handle
* @con_out_handle: The handle for the active console output device
* @con_out: A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
* that is associated with con_out_handle
* @stderr_handle: The handle for the active standard error console device
* @std_err: A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
* that is associated with stderr_handle
* @runtime: A pointer to the EFI Runtime Services Table
* @boottime: A pointer to the EFI Boot Services Table
* @nr_tables: The number of system configuration tables
* @tables: A pointer to the system configuration tables
*/
struct efi_system_table {
struct efi_table_hdr hdr;
u16 *fw_vendor; /* physical addr of wchar_t vendor string */
@ -870,8 +911,8 @@ struct efi_hii_package_list_header {
* @fields: 'fields' replaces the bit-fields defined in the EFI
* specification to to avoid possible compiler incompatibilities::
*
* u32 length:24;
* u32 type:8;
* u32 length:24;
* u32 type:8;
*/
struct efi_hii_package_header {
u32 fields;
@ -1809,7 +1850,7 @@ struct efi_system_resource_table {
0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
/**
* win_certificate_uefi_guid - A certificate that encapsulates
* struct win_certificate_uefi_guid - A certificate that encapsulates
* a GUID-specific signature
*
* @hdr: Windows certificate header
@ -1823,7 +1864,7 @@ struct win_certificate_uefi_guid {
} __attribute__((__packed__));
/**
* efi_variable_authentication_2 - A time-based authentication method
* struct efi_variable_authentication_2 - A time-based authentication method
* descriptor
*
* This structure describes an authentication information for
@ -1840,7 +1881,7 @@ struct efi_variable_authentication_2 {
} __attribute__((__packed__));
/**
* efi_firmware_image_authentication - Capsule authentication method
* struct efi_firmware_image_authentication - Capsule authentication method
* descriptor
*
* This structure describes an authentication information for
@ -1858,7 +1899,7 @@ struct efi_firmware_image_authentication {
/**
* efi_signature_data - A format of signature
* struct efi_signature_data - A format of signature
*
* This structure describes a single signature in signature database.
*
@ -1871,7 +1912,7 @@ struct efi_signature_data {
} __attribute__((__packed__));
/**
* efi_signature_list - A format of signature database
* struct efi_signature_list - A format of signature database
*
* This structure describes a list of signatures with the same type.
* An authenticated variable's value is a concatenation of one or more

View file

@ -25,8 +25,9 @@ enum lmb_flags {
/**
* struct lmb_property - Description of one region.
*
* @base: Base address of the region.
* @size: Size of the region
* @base: Base address of the region.
* @size: Size of the region
* @flags: memory region attributes
*/
struct lmb_property {
phys_addr_t base;
@ -73,64 +74,49 @@ struct lmb {
#endif
};
extern void lmb_init(struct lmb *lmb);
extern void lmb_init_and_reserve(struct lmb *lmb, struct bd_info *bd,
void *fdt_blob);
extern void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
phys_size_t size, void *fdt_blob);
extern long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size);
extern long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size);
void lmb_init(struct lmb *lmb);
void lmb_init_and_reserve(struct lmb *lmb, struct bd_info *bd, void *fdt_blob);
void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
phys_size_t size, void *fdt_blob);
long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size);
long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size);
/**
* lmb_reserve_flags - Reserve one region with a specific flags bitfield.
*
* @lmb the logical memory block struct
* @base base address of the memory region
* @size size of the memory region
* @flags flags for the memory region
* @return 0 if OK, > 0 for coalesced region or a negative error code.
* @lmb: the logical memory block struct
* @base: base address of the memory region
* @size: size of the memory region
* @flags: flags for the memory region
* Return: 0 if OK, > 0 for coalesced region or a negative error code.
*/
long lmb_reserve_flags(struct lmb *lmb, phys_addr_t base,
phys_size_t size, enum lmb_flags flags);
extern phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
extern phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
phys_addr_t max_addr);
extern phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
phys_addr_t max_addr);
extern phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base,
phys_size_t size);
extern phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
extern int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
phys_addr_t max_addr);
phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
phys_addr_t max_addr);
phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size);
phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
/**
* lmb_is_reserved_flags - test if tha address is in reserved region with a bitfield flag
*
* @lmb the logical memory block struct
* @addr address to be tested
* @flags flags bitfied to be tested
* @return 0 if not reserved or reserved without the requested flag else 1
* @lmb: the logical memory block struct
* @addr: address to be tested
* @flags: flags bitfied to be tested
* Return: if not reserved or reserved without the requested flag else 1
*/
int lmb_is_reserved_flags(struct lmb *lmb, phys_addr_t addr, int flags);
extern long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size);
long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size);
extern void lmb_dump_all(struct lmb *lmb);
extern void lmb_dump_all_force(struct lmb *lmb);
static inline phys_size_t
lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
{
return type->region[region_nr].size;
}
void lmb_dump_all(struct lmb *lmb);
void lmb_dump_all_force(struct lmb *lmb);
void board_lmb_reserve(struct lmb *lmb);
void arch_lmb_reserve(struct lmb *lmb);
void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong align);
/* Low level functions */
static inline bool lmb_is_nomap(struct lmb_property *m)
{
return m->flags & LMB_NOMAP;
}
#endif /* __KERNEL__ */
#endif /* _LINUX_LMB_H */

View file

@ -793,7 +793,7 @@ config LMB
Support the library logical memory blocks.
config LMB_USE_MAX_REGIONS
bool "Use a commun number of memory and reserved regions in lmb lib"
bool "Use a common number of memory and reserved regions in lmb lib"
depends on LMB
default y
help

View file

@ -71,6 +71,9 @@ const efi_guid_t efi_guid_driver_binding_protocol =
/* event group ExitBootServices() invoked */
const efi_guid_t efi_guid_event_group_exit_boot_services =
EFI_EVENT_GROUP_EXIT_BOOT_SERVICES;
/* event group before ExitBootServices() invoked */
const efi_guid_t efi_guid_event_group_before_exit_boot_services =
EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES;
/* event group SetVirtualAddressMap() invoked */
const efi_guid_t efi_guid_event_group_virtual_address_change =
EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE;
@ -2123,6 +2126,16 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
if (!systab.boottime)
goto out;
/* Notify EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES event group. */
list_for_each_entry(evt, &efi_events, link) {
if (evt->group &&
!guidcmp(evt->group,
&efi_guid_event_group_before_exit_boot_services)) {
efi_signal_event(evt);
break;
}
}
/* Stop all timer related activities */
timers_enabled = false;

View file

@ -1108,13 +1108,13 @@ efi_status_t efi_launch_capsules(void)
log_err("Applying capsule %ls failed\n",
files[i]);
/* create CapsuleXXXX */
set_capsule_result(index, capsule, ret);
free(capsule);
} else {
log_err("Reading capsule %ls failed\n", files[i]);
}
/* create CapsuleXXXX */
set_capsule_result(index, capsule, ret);
/* delete a capsule either in case of success or failure */
ret = efi_capsule_delete_file(files[i]);
if (ret != EFI_SUCCESS)

View file

@ -18,6 +18,7 @@
#include <smbios.h>
#include <version_string.h>
#include <tpm-v2.h>
#include <tpm_api.h>
#include <u-boot/hash-checksum.h>
#include <u-boot/sha1.h>
#include <u-boot/sha256.h>
@ -27,6 +28,17 @@
#include <linux/unaligned/generic.h>
#include <hexdump.h>
/**
* struct event_log_buffer - internal eventlog management structure
*
* @buffer: eventlog buffer
* @final_buffer: finalevent config table buffer
* @pos: current position of 'buffer'
* @final_pos: current position of 'final_buffer'
* @get_event_called: true if GetEventLog has been invoked at least once
* @ebs_called: true if ExitBootServices has been invoked
* @truncated: true if the 'buffer' is truncated
*/
struct event_log_buffer {
void *buffer;
void *final_buffer;
@ -34,6 +46,7 @@ struct event_log_buffer {
size_t final_pos; /* final events config table position */
size_t last_event_size;
bool get_event_called;
bool ebs_called;
bool truncated;
};
@ -186,39 +199,29 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
return EFI_SUCCESS;
}
/* tcg2_agile_log_append - Append an agile event to out eventlog
/* put_event - Append an agile event to an eventlog
*
* @pcr_index: PCR index
* @event_type: type of event added
* @digest_list: list of digest algorithms to add
* @size: size of event
* @event: event to add
* @log: log buffer to append the event
*
* @Return: status code
*/
static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
struct tpml_digest_values *digest_list,
u32 size, u8 event[])
static void put_event(u32 pcr_index, u32 event_type,
struct tpml_digest_values *digest_list, u32 size,
u8 event[], void *log)
{
void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
size_t pos;
size_t i;
u32 event_size;
if (event_log.get_event_called)
log = (void *)((uintptr_t)event_log.final_buffer +
event_log.final_pos);
/*
* size refers to the length of event[] only, we need to check against
* the final tcg_pcr_event2 size
*/
event_size = size + tcg_event_final_size(digest_list);
if (event_log.pos + event_size > TPM2_EVENT_LOG_SIZE ||
event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) {
event_log.truncated = true;
return EFI_VOLUME_FULL;
}
put_unaligned_le32(pcr_index, log);
pos = offsetof(struct tcg_pcr_event2, event_type);
@ -242,25 +245,62 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
memcpy((void *)((uintptr_t)log + pos), event, size);
pos += size;
/* make sure the calculated buffer is what we checked against */
/*
* make sure the calculated buffer is what we checked against
* This check should never fail. It checks the code above is
* calculating the right length for the event we are adding
*/
if (pos != event_size)
return EFI_INVALID_PARAMETER;
log_err("Appending to the EventLog failed\n");
}
/* if GetEventLog hasn't been called update the normal log */
if (!event_log.get_event_called) {
event_log.pos += pos;
event_log.last_event_size = pos;
} else {
/* if GetEventLog has been called update config table log */
struct efi_tcg2_final_events_table *final_event;
/* tcg2_agile_log_append - Append an agile event to an eventlog
*
* @pcr_index: PCR index
* @event_type: type of event added
* @digest_list: list of digest algorithms to add
* @size: size of event
* @event: event to add
* @log: log buffer to append the event
*
* @Return: status code
*/
static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
struct tpml_digest_values *digest_list,
u32 size, u8 event[])
{
void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
u32 event_size = size + tcg_event_final_size(digest_list);
struct efi_tcg2_final_events_table *final_event;
efi_status_t ret = EFI_SUCCESS;
final_event =
(struct efi_tcg2_final_events_table *)(event_log.final_buffer);
final_event->number_of_events++;
event_log.final_pos += pos;
/* if ExitBootServices hasn't been called update the normal log */
if (!event_log.ebs_called) {
if (event_log.truncated ||
event_log.pos + event_size > TPM2_EVENT_LOG_SIZE) {
event_log.truncated = true;
return EFI_VOLUME_FULL;
}
put_event(pcr_index, event_type, digest_list, size, event, log);
event_log.pos += event_size;
event_log.last_event_size = event_size;
}
return EFI_SUCCESS;
if (!event_log.get_event_called)
return ret;
/* if GetEventLog has been called update FinalEventLog as well */
if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE)
return EFI_VOLUME_FULL;
log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
put_event(pcr_index, event_type, digest_list, size, event, log);
final_event = event_log.final_buffer;
final_event->number_of_events++;
event_log.final_pos += event_size;
return ret;
}
/**
@ -1303,6 +1343,7 @@ static efi_status_t efi_init_event_log(void)
event_log.pos = 0;
event_log.last_event_size = 0;
event_log.get_event_called = false;
event_log.ebs_called = false;
event_log.truncated = false;
/*
@ -1472,7 +1513,7 @@ static efi_status_t tcg2_measure_boot_variable(struct udevice *dev)
&var_data_size);
if (!bootvar) {
log_info("%ls not found\n", boot_name);
log_debug("%ls not found\n", boot_name);
continue;
}
@ -1792,6 +1833,7 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
EFI_ENTRY("%p, %p", event, context);
event_log.ebs_called = true;
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS)
goto out;
@ -1902,6 +1944,7 @@ efi_status_t efi_tcg2_register(void)
efi_status_t ret = EFI_SUCCESS;
struct udevice *dev;
struct efi_event *event;
u32 err;
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS) {
@ -1909,6 +1952,13 @@ efi_status_t efi_tcg2_register(void)
return EFI_SUCCESS;
}
/* initialize the TPM as early as possible. */
err = tpm_startup(dev, TPM_ST_CLEAR);
if (err) {
log_err("TPM startup failed\n");
goto fail;
}
ret = efi_init_event_log();
if (ret != EFI_SUCCESS)
goto fail;

View file

@ -10,9 +10,34 @@
#include <efi_selftest.h>
static efi_guid_t guid_before_exit_boot_services =
EFI_GUID(0x8be0e274, 0x3970, 0x4b44, 0x80, 0xc5,
0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc);
#define CAPACITY 4
struct notification_record {
unsigned int count;
unsigned int type[CAPACITY];
};
struct notification_context {
struct notification_record *record;
unsigned int type;
};
static struct efi_boot_services *boottime;
static struct efi_event *event_notify;
static unsigned int notification_count;
struct notification_record record;
struct notification_context context_before = {
.record = &record,
.type = 1,
};
struct notification_context context = {
.record = &record,
.type = 2,
};
/*
* Notification function, increments the notification count.
@ -20,11 +45,15 @@ static unsigned int notification_count;
* @event notified event
* @context pointer to the notification count
*/
static void EFIAPI notify(struct efi_event *event, void *context)
static void EFIAPI ebs_notify(struct efi_event *event, void *context)
{
unsigned int *count = context;
struct notification_context *ctx = context;
++*count;
if (ctx->record->count >= CAPACITY)
return;
ctx->record->type[ctx->record->count] = ctx->type;
ctx->record->count++;
}
/*
@ -43,15 +72,23 @@ static int setup(const efi_handle_t handle,
boottime = systable->boottime;
notification_count = 0;
ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_CALLBACK, notify,
(void *)&notification_count,
TPL_CALLBACK, ebs_notify,
&context,
&event_notify);
if (ret != EFI_SUCCESS) {
efi_st_error("could not create event\n");
return EFI_ST_FAILURE;
}
ret = boottime->create_event_ex(0, TPL_CALLBACK, ebs_notify,
&context_before,
&guid_before_exit_boot_services,
&event_notify);
if (ret != EFI_SUCCESS) {
efi_st_error("could not create event\n");
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;
}
@ -68,13 +105,21 @@ static int setup(const efi_handle_t handle,
*/
static int execute(void)
{
if (notification_count != 1) {
efi_st_error("ExitBootServices was not notified\n");
if (record.count != 2) {
efi_st_error("Incorrect event count %u\n", record.count);
return EFI_ST_FAILURE;
}
if (record.type[0] != 1) {
efi_st_error("EFI_GROUP_BEFORE_EXIT_BOOT_SERVICE not notified\n");
return EFI_ST_FAILURE;
}
if (record.type[1] != 2) {
efi_st_error("EVT_SIGNAL_EXIT_BOOT_SERVICES was not notified\n");
return EFI_ST_FAILURE;
}
efi_st_exit_boot_services();
if (notification_count != 1) {
efi_st_error("ExitBootServices was notified twice\n");
if (record.count != 2) {
efi_st_error("Incorrect event count %u\n", record.count);
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,11 @@
#include <test/test.h>
#include <test/ut.h>
static inline bool lmb_is_nomap(struct lmb_property *m)
{
return m->flags & LMB_NOMAP;
}
static int check_lmb(struct unit_test_state *uts, struct lmb *lmb,
phys_addr_t ram_base, phys_size_t ram_size,
unsigned long num_reserved,

View file

@ -31,6 +31,7 @@ static int print_guid(struct unit_test_state *uts)
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
char str[40];
int ret;
sprintf(str, "%pUb", guid);
ut_assertok(strcmp("01020304-0506-0708-090a-0b0c0d0e0f10", str));
@ -40,6 +41,9 @@ static int print_guid(struct unit_test_state *uts)
ut_assertok(strcmp("04030201-0605-0807-090a-0b0c0d0e0f10", str));
sprintf(str, "%pUL", guid);
ut_assertok(strcmp("04030201-0605-0807-090A-0B0C0D0E0F10", str));
ret = snprintf(str, 4, "%pUL", guid);
ut_asserteq(0, str[3]);
ut_asserteq(36, ret);
return 0;
}
@ -349,6 +353,20 @@ static int print_itoa(struct unit_test_state *uts)
}
PRINT_TEST(print_itoa, 0);
static int snprint(struct unit_test_state *uts)
{
char buf[10] = "xxxxxxxxx";
int ret;
ret = snprintf(buf, 4, "%s:%s", "abc", "def");
ut_asserteq(0, buf[3]);
ut_asserteq(7, ret);
ret = snprintf(buf, 4, "%s:%d", "abc", 9999);
ut_asserteq(8, ret);
return 0;
}
PRINT_TEST(snprint, 0);
static int print_xtoa(struct unit_test_state *uts)
{
ut_asserteq_str("7f", simple_xtoa(127));