/** * HELLO console support. */ module hello.console; import uefi; import hello.hello; import core.stdc.stdarg; struct console { /** * Format a hexadecimal value to a string. * * @param s String buffer. * @param v Value to format. * @param ptr If true, always output all 16 digits, and separate the upper and * lower halves with an underscore. */ private static size_t format_hex(CHAR16 * s, ulong v, bool ptr) { string hex_chars = "0123456789ABCDEF"; bool print = ptr; size_t si = 0u; for (size_t i = 0u; i < 16u; i++) { if (ptr && (i == 8u)) { s[si++] = '_'; } ulong n = (v >> (60u - 4u * i)) & 0xFu; if (n != 0u) { print = true; } if (print || (i == 15u)) { s[si++] = hex_chars[n]; } } return si; } /** * Format a decimal value to a string. * * @param s String buffer. * @param v Value to format. */ private static size_t format_dec(CHAR16 * s, ulong v) { string dec_chars = "0123456789"; bool print; char[20] buf; size_t buf_i; while ((buf_i == 0u) || (v != 0u)) { ulong n = v % 10u; buf[buf_i++] = dec_chars[n]; v /= 10u; } for (size_t si = 0u; si < buf_i; si++) { s[si] = buf[buf_i - si - 1u]; } return buf_i; } /** * Write a string to the console. * * @param s Format string. * @param args Variable arguments structure. */ public static void write(string s, va_list args) { __gshared static CHAR16[256] s16; size_t i = 0u; bool escape = false; foreach (char c; s) { if (escape) { if (c == '%') { s16[i++] = '%'; } else if (c == 'x') { ulong v; va_arg(args, v); i += format_hex(&s16[i], v, false); } else if (c == 'p') { ulong v; va_arg(args, v); i += format_hex(&s16[i], v, true); } else if (c == 'S') { const(CHAR16) * s2; va_arg(args, s2); for (size_t s2_i = 0u; s2[s2_i] != 0; s2_i++) { s16[i++] = s2[s2_i]; } } else if (c == 'u') { ulong v; va_arg(args, v); i += format_dec(&s16[i], v); } else { s16[i++] = c; } escape = false; } else if (c == '%') { escape = true; } else { s16[i++] = c; } } s16[i++] = 0u; st.ConOut.OutputString(st.ConOut, &s16[0]); } /** * Write a string to the console. * * @param s Format string. */ public static extern (C) void write(string s, ...) { va_list args; va_start(args, s); write(s, args); va_end(args); } /** * Write a string to the console. * * @param s Format string. */ public static extern (C) void writeln(string s, ...) { va_list args; va_start(args, s); write(s, args); write("\r\n", args); va_end(args); } /** * Write a message to press any key and wait for a key to be pressed. */ public static void wait_key() { writeln("Press any key..."); st.ConIn.Reset(st.ConIn, FALSE); EFI_INPUT_KEY key; while (st.ConIn.ReadKeyStroke(st.ConIn, &key) == EFI_NOT_READY) { } } /** * Clear the console. */ public static void clear() { st.ConOut.ClearScreen(st.ConOut); } }