/* * Execute unit test. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { char *str; efi_status_t ret; str = get_property(L"compatible"); if (str) { efi_st_printf("compatible: %s\n", str); ret = boottime->free_pool(str); if (ret != EFI_SUCCESS) { efi_st_error("FreePool failed\n"); return EFI_ST_FAILURE; } } else { efi_st_printf("Missing property 'compatible'\n"); return EFI_ST_FAILURE; } str = get_property(L"serial-number"); if (str) { efi_st_printf("serial-number: %s\n", str); ret = boottime->free_pool(str); if (ret != EFI_SUCCESS) { efi_st_error("FreePool failed\n"); return EFI_ST_FAILURE; } } return EFI_ST_SUCCESS; }
/* * Check CRC32 of a table. */ static int check_table(const void *table) { efi_status_t ret; u32 crc32, res; /* Casting from constant to not constant */ struct efi_table_hdr *hdr = (struct efi_table_hdr *)table; crc32 = hdr->crc32; /* * Setting the CRC32 of the 'const' table to zero is easier than * copying */ hdr->crc32 = 0; ret = boottime->calculate_crc32(table, hdr->headersize, &res); /* Reset table CRC32 so it stays constant */ hdr->crc32 = crc32; if (ret != EFI_ST_SUCCESS) { efi_st_error("CalculateCrc32 failed\n"); return EFI_ST_FAILURE; } if (res != crc32) { efi_st_error("Incorrect CRC32\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Setup unit test. * * Create two timer events. * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT. * * @handle: handle of the loaded image * @systable: system table * @return: EFI_ST_SUCCESS for success */ static int setup(const efi_handle_t handle, const struct efi_system_table *systable) { efi_status_t ret; boottime = systable->boottime; notification_context.status = EFI_SUCCESS; notification_context.timer_ticks = 0; ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, notify, (void *)¬ification_context, &event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); return EFI_ST_FAILURE; } ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT, TPL_CALLBACK, notify, NULL, &event_wait); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Tear down unit test. * * Close the events created in setup. * * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { efi_status_t ret; /* Set the watchdog timer to the five minute default value */ ret = boottime->set_watchdog_timer(300, 0, 0, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Setting watchdog timer failed\n"); return EFI_ST_FAILURE; } if (event_notify) { ret = boottime->close_event(event_notify); event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("Could not close event\n"); return EFI_ST_FAILURE; } } if (event_wait) { ret = boottime->close_event(event_wait); event_wait = NULL; if (ret != EFI_SUCCESS) { efi_st_error("Could not close event\n"); return EFI_ST_FAILURE; } } return EFI_ST_SUCCESS; }
/* * Decompress the disk image. * * @image decompressed disk image * @return status code */ static efi_status_t decompress(u8 **image) { u8 *buf; size_t i; size_t addr; size_t len; efi_status_t ret; ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length, (void **)&buf); if (ret != EFI_SUCCESS) { efi_st_error("Out of memory\n"); return ret; } boottime->set_mem(buf, img.length, 0); for (i = 0; ; ++i) { if (!img.lines[i].line) break; addr = img.lines[i].addr; len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE; if (addr + len > img.length) len = img.length - addr; boottime->copy_mem(buf + addr, img.lines[i].line, len); } *image = buf; return ret; }
/** * execute() - execute unit test * * Return: EFI_ST_SUCCESS for success */ static int execute(void) { undefined_instruction(); efi_st_error("An undefined instruction exception was not raised\n"); return EFI_ST_FAILURE; }
/* * Execute unit test. * * Load and start the application image. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { efi_status_t ret; efi_handle_t handle; ret = boottime->load_image(false, image_handle, NULL, image, img.length, &handle); if (ret != EFI_SUCCESS) { efi_st_error("Failed to load image\n"); return EFI_ST_FAILURE; } ret = boottime->start_image(handle, NULL, NULL); if (ret != EFI_UNSUPPORTED) { efi_st_error("Wrong return value from application\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Setup unit test. * * @handle: handle of the loaded image * @systable: system table * @return: EFI_ST_SUCCESS for success */ static int setup(const efi_handle_t img_handle, const struct efi_system_table *systable) { void *acpi; systemtab = systable; boottime = systable->boottime; acpi = efi_st_get_config_table(&acpi_guid); fdt = efi_st_get_config_table(&fdt_guid); if (!fdt) { efi_st_error("Missing device tree\n"); return EFI_ST_FAILURE; } if (acpi) { efi_st_error("Found ACPI table and device tree\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Tear down unit test. * * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { efi_status_t r = EFI_ST_SUCCESS; if (image) { r = efi_free_pool(image); if (r != EFI_SUCCESS) { efi_st_error("Failed to free image\n"); return EFI_ST_FAILURE; } } return r; }
/* * Tear down unit test. * * Close the events created in setup. * * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { efi_status_t ret; if (event_notify) { ret = boottime->close_event(event_notify); event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); return EFI_ST_FAILURE; } } if (event_wait) { ret = boottime->close_event(event_wait); event_wait = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); return EFI_ST_FAILURE; } } return EFI_ST_SUCCESS; }
/* * Setup unit test. * * @handle: handle of the loaded image * @systable: system table * @return: EFI_ST_SUCCESS for success */ static int setup(const efi_handle_t img_handle, const struct efi_system_table *systable) { efi_uintn_t i; boottime = systable->boottime; /* Find configuration tables */ for (i = 0; i < systable->nr_tables; ++i) { if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid, sizeof(efi_guid_t))) fdt = systable->tables[i].table; } if (!fdt) { efi_st_error("Missing device tree\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * Display current time. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { efi_status_t ret; struct efi_time tm; /* Display current time */ ret = runtime->get_time(&tm, NULL); if (ret != EFI_SUCCESS) { #ifdef CONFIG_CMD_DATE efi_st_error(EFI_ST_NO_RTC); return EFI_ST_FAILURE; #else efi_st_todo(EFI_ST_NO_RTC); return EFI_ST_SUCCESS; #endif } else { efi_st_printf("Time according to real time clock: " "%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * Run a 600 ms periodic timer that resets the watchdog to one second * on every timer tick. * * Run a 1350 ms single shot timer and check that the 600ms timer has * been called 2 times. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { size_t index; efi_status_t ret; /* Set the watchdog timeout to one second */ ret = boottime->set_watchdog_timer(1, 0, 0, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Setting watchdog timer failed\n"); return EFI_ST_FAILURE; } if (watchdog_reset) { /* Set 600 ms timer */ ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 6000000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } } /* Set 1350 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 13500000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event\n"); return EFI_ST_FAILURE; } if (notification_context.status != EFI_SUCCESS) { efi_st_error("Setting watchdog timer failed\n"); return EFI_ST_FAILURE; } if (notification_context.timer_ticks != 2) { efi_st_error("The timer was called %u times, expected 2.\n", notification_context.timer_ticks); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * Run a 10 ms periodic timer and check that it is called 10 times * while waiting for 100 ms single shot timer. * * Run a 100 ms single shot timer and check that it is called once * while waiting for 100 ms periodic timer for two periods. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { efi_uintn_t index; efi_status_t ret; /* Set 10 ms timer */ timer_ticks = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } /* Set 100 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } /* Set some arbitrary non-zero value to make change detectable. */ index = 5; ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event\n"); return EFI_ST_FAILURE; } ret = boottime->check_event(event_wait); if (ret != EFI_NOT_READY) { efi_st_error("Signaled state was not cleared.\n"); efi_st_printf("ret = %u\n", (unsigned int)ret); return EFI_ST_FAILURE; } if (index != 0) { efi_st_error("WaitForEvent returned wrong index\n"); return EFI_ST_FAILURE; } if (timer_ticks < 8 || timer_ticks > 12) { efi_st_printf("Notification count periodic: %u\n", timer_ticks); efi_st_error("Incorrect timing of events\n"); return EFI_ST_FAILURE; } ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0); if (index != 0) { efi_st_error("Could not cancel timer\n"); return EFI_ST_FAILURE; } /* Set 10 ms timer */ timer_ticks = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000); if (index != 0) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } /* Set 100 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000); if (index != 0) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event\n"); return EFI_ST_FAILURE; } if (timer_ticks != 1) { efi_st_printf("Notification count single shot: %u\n", timer_ticks); efi_st_error("Single shot timer failed\n"); return EFI_ST_FAILURE; } ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event\n"); return EFI_ST_FAILURE; } if (timer_ticks != 1) { efi_st_printf("Notification count stopped timer: %u\n", timer_ticks); efi_st_error("Stopped timer fired\n"); return EFI_ST_FAILURE; } ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0); if (ret != EFI_SUCCESS) { efi_st_error("Could not cancel timer\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * Create multiple events in an event group. Signal each event once and check * that all events are notified once in each round. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { unsigned int counter[GROUP_SIZE] = {0}; struct efi_event *events[GROUP_SIZE]; size_t i, j; efi_status_t ret; for (i = 0; i < GROUP_SIZE; ++i) { ret = boottime->create_event_ex(0, TPL_NOTIFY, notify, (void *)&counter[i], &event_group, &events[i]); if (ret != EFI_SUCCESS) { efi_st_error("Failed to create event\n"); return EFI_ST_FAILURE; } } for (i = 0; i < GROUP_SIZE; ++i) { ret = boottime->signal_event(events[i]); if (ret != EFI_SUCCESS) { efi_st_error("Failed to signal event\n"); return EFI_ST_FAILURE; } for (j = 0; j < GROUP_SIZE; ++j) { if (counter[j] != i) { efi_st_printf("i %u, j %u, count %u\n", (unsigned int)i, (unsigned int)j, (unsigned int)counter[j]); efi_st_error( "Notification function was called\n"); return EFI_ST_FAILURE; } /* Clear signaled state */ ret = boottime->check_event(events[j]); if (ret != EFI_SUCCESS) { efi_st_error("Event was not signaled\n"); return EFI_ST_FAILURE; } if (counter[j] != i) { efi_st_printf("i %u, j %u, count %u\n", (unsigned int)i, (unsigned int)j, (unsigned int)counter[j]); efi_st_error( "Notification function was called\n"); return EFI_ST_FAILURE; } /* Call notification function */ ret = boottime->check_event(events[j]); if (ret != EFI_NOT_READY) { efi_st_error( "Signaled state not cleared\n"); return EFI_ST_FAILURE; } if (counter[j] != i + 1) { efi_st_printf("i %u, j %u, count %u\n", (unsigned int)i, (unsigned int)j, (unsigned int)counter[j]); efi_st_error( "Notification function not called\n"); return EFI_ST_FAILURE; } } } for (i = 0; i < GROUP_SIZE; ++i) { ret = boottime->close_event(events[i]); if (ret != EFI_SUCCESS) { efi_st_error("Failed to close event\n"); return EFI_ST_FAILURE; } } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * A table is installed, updated, removed. The table entry and the * triggering of events is checked. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { efi_status_t ret; unsigned int counter = 0; struct efi_event *event; void *table; const unsigned int tables[2]; efi_uintn_t i; efi_uintn_t tabcnt; efi_uintn_t table_count = sys_table->nr_tables; ret = boottime->create_event_ex(0, TPL_NOTIFY, notify, (void *)&counter, &table_guid, &event); if (ret != EFI_SUCCESS) { efi_st_error("Failed to create event\n"); return EFI_ST_FAILURE; } /* Try to delete non-existent table */ ret = boottime->install_configuration_table(&table_guid, NULL); if (ret != EFI_NOT_FOUND) { efi_st_error("Failed to detect missing table\n"); return EFI_ST_FAILURE; } if (counter) { efi_st_error("Notification function was called.\n"); return EFI_ST_FAILURE; } /* Check if the event was signaled */ ret = boottime->check_event(event); if (ret == EFI_SUCCESS) { efi_st_error("Event was signaled on EFI_NOT_FOUND\n"); return EFI_ST_FAILURE; } if (counter != 1) { efi_st_error("Notification function was not called.\n"); return EFI_ST_FAILURE; } if (table_count != sys_table->nr_tables) { efi_st_error("Incorrect table count %u, expected %u\n", (unsigned int)sys_table->nr_tables, (unsigned int)table_count); return EFI_ST_FAILURE; } /* Install table */ ret = boottime->install_configuration_table(&table_guid, (void *)&tables[0]); if (ret != EFI_SUCCESS) { efi_st_error("Failed to install table\n"); return EFI_ST_FAILURE; } /* Check signaled state */ ret = boottime->check_event(event); if (ret != EFI_SUCCESS) { efi_st_error("Event was not signaled on insert\n"); return EFI_ST_FAILURE; } if (++table_count != sys_table->nr_tables) { efi_st_error("Incorrect table count %u, expected %u\n", (unsigned int)sys_table->nr_tables, (unsigned int)table_count); return EFI_ST_FAILURE; } table = NULL; for (i = 0; i < sys_table->nr_tables; ++i) { if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, sizeof(efi_guid_t))) table = sys_table->tables[i].table; } if (!table) { efi_st_error("Installed table not found\n"); return EFI_ST_FAILURE; } if (table != &tables[0]) { efi_st_error("Incorrect table address\n"); return EFI_ST_FAILURE; } if (check_table(sys_table) != EFI_ST_SUCCESS) { efi_st_error("Checking system table\n"); return EFI_ST_FAILURE; } /* Update table */ ret = boottime->install_configuration_table(&table_guid, (void *)&tables[1]); if (ret != EFI_SUCCESS) { efi_st_error("Failed to update table\n"); return EFI_ST_FAILURE; } /* Check signaled state */ ret = boottime->check_event(event); if (ret != EFI_SUCCESS) { efi_st_error("Event was not signaled on update\n"); return EFI_ST_FAILURE; } if (table_count != sys_table->nr_tables) { efi_st_error("Incorrect table count %u, expected %u\n", (unsigned int)sys_table->nr_tables, (unsigned int)table_count); return EFI_ST_FAILURE; } table = NULL; tabcnt = 0; for (i = 0; i < sys_table->nr_tables; ++i) { if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, sizeof(efi_guid_t))) { table = sys_table->tables[i].table; ++tabcnt; } } if (!table) { efi_st_error("Installed table not found\n"); return EFI_ST_FAILURE; } if (tabcnt > 1) { efi_st_error("Duplicate table GUID\n"); return EFI_ST_FAILURE; } if (table != &tables[1]) { efi_st_error("Incorrect table address\n"); return EFI_ST_FAILURE; } if (check_table(sys_table) != EFI_ST_SUCCESS) { efi_st_error("Checking system table\n"); return EFI_ST_FAILURE; } /* Delete table */ ret = boottime->install_configuration_table(&table_guid, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Failed to delete table\n"); return EFI_ST_FAILURE; } /* Check signaled state */ ret = boottime->check_event(event); if (ret != EFI_SUCCESS) { efi_st_error("Event was not signaled on delete\n"); return EFI_ST_FAILURE; } if (--table_count != sys_table->nr_tables) { efi_st_error("Incorrect table count %u, expected %u\n", (unsigned int)sys_table->nr_tables, (unsigned int)table_count); return EFI_ST_FAILURE; } table = NULL; for (i = 0; i < sys_table->nr_tables; ++i) { if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, sizeof(efi_guid_t))) { table = sys_table->tables[i].table; } } if (table) { efi_st_error("Wrong table deleted\n"); return EFI_ST_FAILURE; } ret = boottime->close_event(event); if (ret != EFI_SUCCESS) { efi_st_error("Failed to close event\n"); return EFI_ST_FAILURE; } if (check_table(sys_table) != EFI_ST_SUCCESS) { efi_st_error("Checking system table\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; }
/* * Execute unit test. * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { size_t foreground; 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"); for (foreground = 0; foreground < 0x10; ++foreground) { for (background = 0; background < 0x80; background += 0x10) { attrib = foreground | background; con_out->set_attribute(con_out, attrib); efi_st_printf("%p", (void *)attrib); } con_out->set_attribute(con_out, 0); efi_st_printf("\n"); } /* TestString */ ret = con_out->test_string(con_out, L" !\"#$%&'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~\n"); if (ret != EFI_ST_SUCCESS) { 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; }