123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*
- * EFI efi_selftest
- *
- * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <efi_selftest.h>
- #include <vsprintf.h>
- struct efi_simple_text_output_protocol *con_out;
- struct efi_simple_input_interface *con_in;
- /*
- * Print a MAC address to an u16 string
- *
- * @pointer: mac address
- * @buf: pointer to buffer address
- * on return position of terminating zero word
- */
- static void mac(void *pointer, u16 **buf)
- {
- int i, j;
- u16 c;
- u8 *p = (u8 *)pointer;
- u8 byte;
- u16 *pos = *buf;
- for (i = 0; i < ARP_HLEN; ++i) {
- if (i)
- *pos++ = ':';
- byte = p[i];
- for (j = 4; j >= 0; j -= 4) {
- c = (byte >> j) & 0x0f;
- c += '0';
- if (c > '9')
- c += 'a' - '9' - 1;
- *pos++ = c;
- }
- }
- *pos = 0;
- *buf = pos;
- }
- /*
- * Print a pointer to an u16 string
- *
- * @pointer: pointer
- * @buf: pointer to buffer address
- * on return position of terminating zero word
- */
- static void pointer(void *pointer, u16 **buf)
- {
- int i;
- u16 c;
- uintptr_t p = (uintptr_t)pointer;
- u16 *pos = *buf;
- for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
- c = (p >> i) & 0x0f;
- c += '0';
- if (c > '9')
- c += 'a' - '9' - 1;
- *pos++ = c;
- }
- *pos = 0;
- *buf = pos;
- }
- /*
- * Print an unsigned 32bit value as decimal number to an u16 string
- *
- * @value: value to be printed
- * @buf: pointer to buffer address
- * on return position of terminating zero word
- */
- static void uint2dec(u32 value, u16 **buf)
- {
- u16 *pos = *buf;
- int i;
- u16 c;
- u64 f;
- /*
- * Increment by .5 and multiply with
- * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
- * to move the first digit to bit 60-63.
- */
- f = 0x225C17D0;
- f += (0x9B5A52DULL * value) >> 28;
- f += 0x44B82FA0ULL * value;
- for (i = 0; i < 10; ++i) {
- /* Write current digit */
- c = f >> 60;
- if (c || pos != *buf)
- *pos++ = c + '0';
- /* Eliminate current digit */
- f &= 0xfffffffffffffff;
- /* Get next digit */
- f *= 0xaULL;
- }
- if (pos == *buf)
- *pos++ = '0';
- *pos = 0;
- *buf = pos;
- }
- /*
- * Print a signed 32bit value as decimal number to an u16 string
- *
- * @value: value to be printed
- * @buf: pointer to buffer address
- * on return position of terminating zero word
- */
- static void int2dec(s32 value, u16 **buf)
- {
- u32 u;
- u16 *pos = *buf;
- if (value < 0) {
- *pos++ = '-';
- u = -value;
- } else {
- u = value;
- }
- uint2dec(u, &pos);
- *buf = pos;
- }
- /*
- * Print a formatted string to the EFI console
- *
- * @fmt: format string
- * @...: optional arguments
- */
- void efi_st_printf(const char *fmt, ...)
- {
- va_list args;
- u16 buf[160];
- const char *c;
- u16 *pos = buf;
- const char *s;
- const u16 *u;
- va_start(args, fmt);
- c = fmt;
- for (; *c; ++c) {
- switch (*c) {
- case '\\':
- ++c;
- switch (*c) {
- case '\0':
- --c;
- break;
- case 'n':
- *pos++ = '\n';
- break;
- case 'r':
- *pos++ = '\r';
- break;
- case 't':
- *pos++ = '\t';
- break;
- default:
- *pos++ = *c;
- }
- break;
- case '%':
- ++c;
- switch (*c) {
- case '\0':
- --c;
- break;
- case 'd':
- int2dec(va_arg(args, s32), &pos);
- break;
- case 'p':
- ++c;
- switch (*c) {
- /* MAC address */
- case 'm':
- mac(va_arg(args, void*), &pos);
- break;
- /* u16 string */
- case 's':
- u = va_arg(args, u16*);
- /* Ensure string fits into buffer */
- for (; *u && pos < buf + 120; ++u)
- *pos++ = *u;
- break;
- default:
- --c;
- pointer(va_arg(args, void*), &pos);
- }
- break;
- case 's':
- s = va_arg(args, const char *);
- for (; *s; ++s)
- *pos++ = *s;
- break;
- case 'u':
- uint2dec(va_arg(args, u32), &pos);
- break;
- default:
- break;
- }
- break;
- default:
- *pos++ = *c;
- }
- }
- va_end(args);
- *pos = 0;
- con_out->output_string(con_out, buf);
- }
- /*
- * Reads an Unicode character from the input device.
- *
- * @return: Unicode character
- */
- u16 efi_st_get_key(void)
- {
- struct efi_input_key input_key;
- efi_status_t ret;
- /* Wait for next key */
- do {
- ret = con_in->read_key_stroke(con_in, &input_key);
- } while (ret == EFI_NOT_READY);
- return input_key.unicode_char;
- }
|