uboot/lib/efi_selftest/efi_selftest_console.c
<<
>>
Prefs
   1/*
   2 * EFI efi_selftest
   3 *
   4 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <efi_selftest.h>
  10#include <vsprintf.h>
  11
  12struct efi_simple_text_output_protocol *con_out;
  13struct efi_simple_input_interface *con_in;
  14
  15/*
  16 * Print a MAC address to an u16 string
  17 *
  18 * @pointer: mac address
  19 * @buf: pointer to buffer address
  20 * on return position of terminating zero word
  21 */
  22static void mac(void *pointer, u16 **buf)
  23{
  24        int i, j;
  25        u16 c;
  26        u8 *p = (u8 *)pointer;
  27        u8 byte;
  28        u16 *pos = *buf;
  29
  30        for (i = 0; i < ARP_HLEN; ++i) {
  31                if (i)
  32                        *pos++ = ':';
  33                byte = p[i];
  34                for (j = 4; j >= 0; j -= 4) {
  35                        c = (byte >> j) & 0x0f;
  36                        c += '0';
  37                        if (c > '9')
  38                                c += 'a' - '9' - 1;
  39                        *pos++ = c;
  40                }
  41        }
  42        *pos = 0;
  43        *buf = pos;
  44}
  45
  46/*
  47 * Print a pointer to an u16 string
  48 *
  49 * @pointer: pointer
  50 * @buf: pointer to buffer address
  51 * on return position of terminating zero word
  52 */
  53static void pointer(void *pointer, u16 **buf)
  54{
  55        int i;
  56        u16 c;
  57        uintptr_t p = (uintptr_t)pointer;
  58        u16 *pos = *buf;
  59
  60        for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
  61                c = (p >> i) & 0x0f;
  62                c += '0';
  63                if (c > '9')
  64                        c += 'a' - '9' - 1;
  65                *pos++ = c;
  66        }
  67        *pos = 0;
  68        *buf = pos;
  69}
  70
  71/*
  72 * Print an unsigned 32bit value as decimal number to an u16 string
  73 *
  74 * @value: value to be printed
  75 * @buf: pointer to buffer address
  76 * on return position of terminating zero word
  77 */
  78static void uint2dec(u32 value, u16 **buf)
  79{
  80        u16 *pos = *buf;
  81        int i;
  82        u16 c;
  83        u64 f;
  84
  85        /*
  86         * Increment by .5 and multiply with
  87         * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
  88         * to move the first digit to bit 60-63.
  89         */
  90        f = 0x225C17D0;
  91        f += (0x9B5A52DULL * value) >> 28;
  92        f += 0x44B82FA0ULL * value;
  93
  94        for (i = 0; i < 10; ++i) {
  95                /* Write current digit */
  96                c = f >> 60;
  97                if (c || pos != *buf)
  98                        *pos++ = c + '0';
  99                /* Eliminate current digit */
 100                f &= 0xfffffffffffffff;
 101                /* Get next digit */
 102                f *= 0xaULL;
 103        }
 104        if (pos == *buf)
 105                *pos++ = '0';
 106        *pos = 0;
 107        *buf = pos;
 108}
 109
 110/*
 111 * Print a signed 32bit value as decimal number to an u16 string
 112 *
 113 * @value: value to be printed
 114 * @buf: pointer to buffer address
 115 * on return position of terminating zero word
 116 */
 117static void int2dec(s32 value, u16 **buf)
 118{
 119        u32 u;
 120        u16 *pos = *buf;
 121
 122        if (value < 0) {
 123                *pos++ = '-';
 124                u = -value;
 125        } else {
 126                u = value;
 127        }
 128        uint2dec(u, &pos);
 129        *buf = pos;
 130}
 131
 132/*
 133 * Print a formatted string to the EFI console
 134 *
 135 * @fmt: format string
 136 * @...: optional arguments
 137 */
 138void efi_st_printf(const char *fmt, ...)
 139{
 140        va_list args;
 141        u16 buf[160];
 142        const char *c;
 143        u16 *pos = buf;
 144        const char *s;
 145        const u16 *u;
 146
 147        va_start(args, fmt);
 148
 149        c = fmt;
 150        for (; *c; ++c) {
 151                switch (*c) {
 152                case '\\':
 153                        ++c;
 154                        switch (*c) {
 155                        case '\0':
 156                                --c;
 157                                break;
 158                        case 'n':
 159                                *pos++ = '\n';
 160                                break;
 161                        case 'r':
 162                                *pos++ = '\r';
 163                                break;
 164                        case 't':
 165                                *pos++ = '\t';
 166                                break;
 167                        default:
 168                                *pos++ = *c;
 169                        }
 170                        break;
 171                case '%':
 172                        ++c;
 173                        switch (*c) {
 174                        case '\0':
 175                                --c;
 176                                break;
 177                        case 'd':
 178                                int2dec(va_arg(args, s32), &pos);
 179                                break;
 180                        case 'p':
 181                                ++c;
 182                                switch (*c) {
 183                                /* MAC address */
 184                                case 'm':
 185                                        mac(va_arg(args, void*), &pos);
 186                                        break;
 187
 188                                /* u16 string */
 189                                case 's':
 190                                        u = va_arg(args, u16*);
 191                                        /* Ensure string fits into buffer */
 192                                        for (; *u && pos < buf + 120; ++u)
 193                                                *pos++ = *u;
 194                                        break;
 195                                default:
 196                                        --c;
 197                                        pointer(va_arg(args, void*), &pos);
 198                                }
 199                                break;
 200                        case 's':
 201                                s = va_arg(args, const char *);
 202                                for (; *s; ++s)
 203                                        *pos++ = *s;
 204                                break;
 205                        case 'u':
 206                                uint2dec(va_arg(args, u32), &pos);
 207                                break;
 208                        default:
 209                                break;
 210                        }
 211                        break;
 212                default:
 213                        *pos++ = *c;
 214                }
 215        }
 216        va_end(args);
 217        *pos = 0;
 218        con_out->output_string(con_out, buf);
 219}
 220
 221/*
 222 * Reads an Unicode character from the input device.
 223 *
 224 * @return: Unicode character
 225 */
 226u16 efi_st_get_key(void)
 227{
 228        struct efi_input_key input_key;
 229        efi_status_t ret;
 230
 231        /* Wait for next key */
 232        do {
 233                ret = con_in->read_key_stroke(con_in, &input_key);
 234        } while (ret == EFI_NOT_READY);
 235        return input_key.unicode_char;
 236}
 237