Rework HELLO console module to use hulk.writef

This commit is contained in:
Josh Holtrop 2023-09-04 16:17:47 -04:00
parent e25d28ebc7
commit 0781962e9f
3 changed files with 44 additions and 136 deletions

View File

@ -162,6 +162,7 @@ hello_env = env "hello", use: %w[ldc2 x86_64-w64-mingw32-gcc] do |env|
env.add_builder(CheckThreadLocal)
env.add_builder(HulkBinObj)
env["sources"] = glob("src/hello/**/*.d")
env["sources"] += ["src/hulk/writef.d"]
env["sources"] += glob("uefi-d/source/**/*.d")
env.HulkBinObj("^/hulk_bin.S", hulk_env.expand("^/hulk.bin"))
env.Object("^/hulk_bin.o", "^/hulk_bin.S")

View File

@ -6,155 +6,62 @@ module hello.console;
import uefi;
import hello.hello;
import core.stdc.stdarg;
import hulk.writef;
struct console
struct Console
{
/**
* Format a hexadecimal value to a string.
* Write a character to the console.
*
* @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.
* @param ch Character to write.
*/
private static size_t format_hex(CHAR16 * s, ulong v, bool ptr)
public static void write(ubyte ch)
{
string hex_chars = "0123456789ABCDEF";
bool print = ptr;
size_t si = 0u;
for (size_t i = 0u; i < 16u; i++)
if (ch == '\n')
{
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];
}
write('\r');
}
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;
CHAR16[2] s16 = [ch, 0];
st.ConOut.OutputString(st.ConOut, &s16[0]);
}
/**
* Write a string to the console.
* Write a formatted string to the console.
*
* @param s Format string.
* @param args Variable arguments structure.
*/
public static void writef(string s, va_list args)
{
hulk.writef.writef(s, args, function void(ubyte ch) {
Console.write(ch);
});
}
/**
* Write a formatted string to the console.
*
* @param s Format string.
*/
public static extern (C) void write(string s, ...)
public static extern (C) void writef(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
writef(s, args);
va_end(args);
}
/**
* Write a string to the console.
* Write a formatted string and newline to the console.
*
* @param s Format string.
*/
public static extern (C) void writeln(string s, ...)
public static extern (C) void writefln(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
write("\r\n", args);
writef(s, args);
writef("\n", args);
va_end(args);
}
@ -163,7 +70,7 @@ struct console
*/
public static void wait_key()
{
writeln("Press any key...");
writefln("Press any key...");
st.ConIn.Reset(st.ConIn, FALSE);
EFI_INPUT_KEY key;
while (st.ConIn.ReadKeyStroke(st.ConIn, &key) == EFI_NOT_READY)

View File

@ -93,7 +93,7 @@ private bool set_graphics_mode()
&gop_guid, null, &buffer_size, handles);
if (status != EFI_SUCCESS)
{
console.writeln("LocateHandle: error %x", status);
Console.writefln("LocateHandle: error %x", status);
return false;
}
EFI_HANDLE gop_handle = handles[0];
@ -102,12 +102,12 @@ private bool set_graphics_mode()
&gop_guid, &gop_interface);
if (status != EFI_SUCCESS)
{
console.writeln("HandleProtocol: error %x", status);
Console.writefln("HandleProtocol: error %x", status);
return false;
}
if (gop_interface == null)
{
console.writeln("null interface from HandleProtocol");
Console.writefln("null interface from HandleProtocol");
return false;
}
EFI_GRAPHICS_OUTPUT_PROTOCOL * gop = cast(EFI_GRAPHICS_OUTPUT_PROTOCOL *)gop_interface;
@ -129,7 +129,7 @@ private bool set_graphics_mode()
}
if ((status = gop.SetMode(gop, best_mode_number)) != EFI_SUCCESS)
{
console.writeln("SetMode: Error %x\n", status);
Console.writefln("SetMode: Error %x\n", status);
return false;
}
bootinfo().fb.buffer = cast(uint *)gop.Mode.FrameBufferBase;
@ -174,7 +174,7 @@ private void get_memory_map(ulong * physical_address_limit, UINTN * memory_map_k
&descriptor_version);
if (status != EFI_SUCCESS)
{
console.writeln("GetMemoryMap: Error %x", status);
Console.writefln("GetMemoryMap: Error %x", status);
for (;;) {}
}
size_t n_entries = memory_map_size / descriptor_size;
@ -187,7 +187,7 @@ private void get_memory_map(ulong * physical_address_limit, UINTN * memory_map_k
{
if (count > bootinfo().memory_map.length)
{
console.writeln("Memory map too large");
Console.writefln("Memory map too large");
for (;;) {}
}
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
@ -511,21 +511,21 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
{
.st = st;
console.clear();
Console.clear();
console.writeln("Welcome to HELLO, HOS EFI Lightweight LOader, v0.1.0");
console.writeln("Firmware vendor: '%S', version: 0x%x", st.FirmwareVendor, st.FirmwareVendor);
Console.writefln("Welcome to HELLO, HOS EFI Lightweight LOader, v0.1.0");
Console.writefln("Firmware vendor: '%S', version: 0x%x", st.FirmwareVendor, st.FirmwareVendor);
if (!find_acpi_xsdt())
{
console.writeln("Error: Could not locate ACPI XSDT");
console.wait_key();
Console.writefln("Error: Could not locate ACPI XSDT");
Console.wait_key();
return EFI_SUCCESS;
}
if (!set_graphics_mode())
{
console.wait_key();
Console.wait_key();
return EFI_SUCCESS;
}
@ -544,8 +544,8 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
{
break;
}
console.writeln("ExitBootServices: Error %x", status);
console.wait_key();
Console.writefln("ExitBootServices: Error %x", status);
Console.wait_key();
return EFI_SUCCESS;
}