示例#1
0
/*
 * 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;
}
示例#3
0
/*
 * 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 *)&notification_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;
}
示例#4
0
/*
 * 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;
}
示例#6
0
/**
 * 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;
}
示例#8
0
/*
 * 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;
}
示例#10
0
/*
 * 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;
}
示例#11
0
/*
 * 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;
}
示例#12
0
/*
 * 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;
}
示例#13
0
/*
 * 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;
}
示例#14
0
/*
 * 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;
}
示例#15
0
/*
 * 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;
}
示例#16
0
/*
 * 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;
}
示例#17
0
/*
 * 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;
}