log: fix log issue which hurt console badly

This commit is contained in:
David Gonzalez Martin 2023-07-14 09:56:05 -06:00
parent 820e60a506
commit 2500b78896
10 changed files with 97 additions and 37 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ bochsout.txt
*.hdd *.hdd
loopback_device loopback_device
tools/OVMF.fd tools/OVMF.fd
logs/*.log

View File

@ -467,6 +467,8 @@ pub fn build(b_arg: *Build) !void {
const user_init = user_module_list.items[0]; const user_init = user_module_list.items[0];
const is_default = architecture == default_configuration.architecture and bootloader == default_configuration.bootloader and boot_protocol == default_configuration.boot_protocol and optimize_mode == default_configuration.optimize_mode and execution_environment == default_configuration.execution_environment and execution_type == default_configuration.execution_type;
const runner_run = try newRunnerRunArtifact(.{ const runner_run = try newRunnerRunArtifact(.{
.configuration = configuration, .configuration = configuration,
.disk_image_path = disk_image_path, .disk_image_path = disk_image_path,
@ -479,7 +481,9 @@ pub fn build(b_arg: *Build) !void {
.is_test = is_test, .is_test = is_test,
}, },
.ovmf_path = ovmf_path, .ovmf_path = ovmf_path,
.is_default = is_default,
}); });
const runner_debug = try newRunnerRunArtifact(.{ const runner_debug = try newRunnerRunArtifact(.{
.configuration = configuration, .configuration = configuration,
.disk_image_path = disk_image_path, .disk_image_path = disk_image_path,
@ -492,13 +496,14 @@ pub fn build(b_arg: *Build) !void {
.is_test = is_test, .is_test = is_test,
}, },
.ovmf_path = ovmf_path, .ovmf_path = ovmf_path,
.is_default = is_default,
}); });
if (is_test) { if (is_test) {
build_steps.test_all.dependOn(&runner_run.step); build_steps.test_all.dependOn(&runner_run.step);
} }
if (architecture == default_configuration.architecture and bootloader == default_configuration.bootloader and boot_protocol == default_configuration.boot_protocol and optimize_mode == default_configuration.optimize_mode and execution_environment == default_configuration.execution_environment and execution_type == default_configuration.execution_type) { if (is_default) {
if (is_test) { if (is_test) {
build_steps.test_run.dependOn(&runner_run.step); build_steps.test_run.dependOn(&runner_run.step);
build_steps.test_debug.dependOn(&runner_debug.step); build_steps.test_debug.dependOn(&runner_debug.step);
@ -592,6 +597,7 @@ fn newRunnerRunArtifact(arguments: struct {
user_init: *CompileStep, user_init: *CompileStep,
qemu_options: QEMUOptions, qemu_options: QEMUOptions,
ovmf_path: FileSource, ovmf_path: FileSource,
is_default: bool,
}) !*RunStep { }) !*RunStep {
const runner = b.addRunArtifact(arguments.runner); const runner = b.addRunArtifact(arguments.runner);
@ -609,6 +615,7 @@ fn newRunnerRunArtifact(arguments: struct {
.debug_user => runner.addArg(if (debug_user) "true" else "false"), .debug_user => runner.addArg(if (debug_user) "true" else "false"),
.debug_loader => runner.addArg(if (debug_loader) "true" else "false"), .debug_loader => runner.addArg(if (debug_loader) "true" else "false"),
.ovmf_path => runner.addFileSourceArg(arguments.ovmf_path), .ovmf_path => runner.addFileSourceArg(arguments.ovmf_path),
.is_default => runner.addArg(if (arguments.is_default) "true" else "false"),
}; };
return runner; return runner;

View File

@ -1,6 +1,6 @@
{ {
"architecture": "x86_64", "architecture": "x86_64",
"bootloader": "birth", "bootloader": "limine",
"boot_protocol": "uefi", "boot_protocol": "uefi",
"execution_environment": "qemu", "execution_environment": "qemu",
"optimize_mode": "Debug", "optimize_mode": "Debug",

View File

@ -8,7 +8,6 @@
"smp": 2, "smp": 2,
"debugcon": "stdio", "debugcon": "stdio",
"log": { "log": {
"file": null,
"guest_errors": true, "guest_errors": true,
"assembly": false, "assembly": false,
"interrupts": true "interrupts": true

0
logs/.gitkeep Normal file
View File

View File

@ -481,6 +481,7 @@ pub const ArgumentParser = struct {
debug_loader, debug_loader,
init, init,
ovmf_path, ovmf_path,
is_default,
}; };
pub const Result = struct { pub const Result = struct {
@ -495,6 +496,7 @@ pub const ArgumentParser = struct {
debug_loader: bool, debug_loader: bool,
init: []const u8, init: []const u8,
ovmf_path: []const u8, ovmf_path: []const u8,
is_default: bool,
}; };
}; };
}; };

View File

@ -57,6 +57,11 @@ pub fn allocateZeroMemory(bytes: u64) ![]align(0x1000) u8 {
pub const ExecutionError = error{failed}; pub const ExecutionError = error{failed};
pub fn spawnProcess(arguments: []const []const u8, allocator: lib.ZigAllocator) !void { pub fn spawnProcess(arguments: []const []const u8, allocator: lib.ZigAllocator) !void {
var process = ChildProcess.init(arguments, allocator); var process = ChildProcess.init(arguments, allocator);
// std.log.err("Spawning process:", .{});
// for (arguments) |arg| {
// std.log.err("Arg: {s}", .{arg});
// }
process.stdout_behavior = .Ignore; process.stdout_behavior = .Ignore;
const execution_result = try process.spawnAndWait(); const execution_result = try process.spawnAndWait();

View File

@ -39,29 +39,29 @@ const MountedPartition = struct {
loopback_device: LoopbackDevice, loopback_device: LoopbackDevice,
fn mkdir(partition: MountedPartition, allocator: lib.ZigAllocator, dir: []const u8) !void { fn mkdir(partition: MountedPartition, allocator: lib.ZigAllocator, dir: []const u8) !void {
try host.spawnProcess(&.{ "sudo", "mkdir", "-p", try partition.join_with_root(allocator, dir) }, allocator); try host.spawnProcess(&.{ "sudo", "mkdir", "-p", try partition.joinWithRoot(allocator, dir) }, allocator);
} }
fn join_with_root(partition: MountedPartition, allocator: lib.ZigAllocator, path: []const u8) ![]const u8 { fn joinWithRoot(partition: MountedPartition, allocator: lib.ZigAllocator, path: []const u8) ![]const u8 {
const mount_dir = partition.get_mount_dir(); const mount_dir = partition.getMountDir();
const slices_to_join: []const []const u8 = if (path[0] == '/') &.{ mount_dir, path } else &.{ mount_dir, "/", path }; const slices_to_join: []const []const u8 = if (path[0] == '/') &.{ mount_dir, path } else &.{ mount_dir, "/", path };
const joint_path = try lib.concat(allocator, u8, slices_to_join); const joint_path = try lib.concat(allocator, u8, slices_to_join);
return joint_path; return joint_path;
} }
pub fn get_mount_dir(partition: MountedPartition) []const u8 { pub fn getMountDir(partition: MountedPartition) []const u8 {
const mount_dir = partition.loopback_device.mount_dir orelse @panic("get_mount_dir"); const mount_dir = partition.loopback_device.mount_dir orelse @panic("getMountDir");
return mount_dir; return mount_dir;
} }
fn copy_file(partition: MountedPartition, allocator: lib.ZigAllocator, file_path: []const u8, file_content: []const u8) !void { fn copyFile(partition: MountedPartition, allocator: lib.ZigAllocator, file_path: []const u8, file_content: []const u8) !void {
// TODO: make this work for Windows? // TODO: make this work for Windows?
const last_slash_index = lib.lastIndexOf(u8, file_path, "/") orelse @panic("fat32: copy file last slash"); const last_slash_index = lib.lastIndexOf(u8, file_path, "/") orelse @panic("fat32: copy file last slash");
const file_name = host.basename(file_path); const file_name = host.basename(file_path);
assert(file_name.len > 0); assert(file_name.len > 0);
try host.cwd().writeFile(file_name, file_content); try host.cwd().writeFile(file_name, file_content);
const dir = file_path[0..if (last_slash_index == 0) 1 else last_slash_index]; const dir = file_path[0..if (last_slash_index == 0) 1 else last_slash_index];
const destination_dir = try partition.join_with_root(allocator, dir); const destination_dir = try partition.joinWithRoot(allocator, dir);
const mkdir_process_args = &.{ "sudo", "mkdir", "-p", destination_dir }; const mkdir_process_args = &.{ "sudo", "mkdir", "-p", destination_dir };
try host.spawnProcess(mkdir_process_args, allocator); try host.spawnProcess(mkdir_process_args, allocator);
const copy_process_args = &.{ "sudo", "cp", "-v", file_name, destination_dir }; const copy_process_args = &.{ "sudo", "cp", "-v", file_name, destination_dir };
@ -167,7 +167,7 @@ test "Limine barebones" {
} }
for (limine_files) |file| { for (limine_files) |file| {
try partition.copy_file(wrapped_allocator.zigUnwrap(), file.path, file.content); try partition.copyFile(wrapped_allocator.zigUnwrap(), file.path, file.content);
} }
try partition.end(wrapped_allocator.zigUnwrap()); try partition.end(wrapped_allocator.zigUnwrap());

View File

@ -22,8 +22,17 @@ const Error = error{
architecture_not_supported, architecture_not_supported,
execution_environment_not_supported, execution_environment_not_supported,
ovmf_path_not_found, ovmf_path_not_found,
is_default_not_found,
}; };
const ParseBoolError = error{
not_found,
};
fn parseBool(argument: []const u8) !bool {
return if (lib.equal(u8, argument, "true")) true else if (lib.equal(u8, argument, "false")) false else ParseBoolError.not_found;
}
pub fn main() anyerror!void { pub fn main() anyerror!void {
const max_file_length = lib.maxInt(usize); const max_file_length = lib.maxInt(usize);
var arena_allocator = host.ArenaAllocator.init(host.page_allocator); var arena_allocator = host.ArenaAllocator.init(host.page_allocator);
@ -46,6 +55,7 @@ pub fn main() anyerror!void {
var argument_init_path: ?[]const u8 = null; var argument_init_path: ?[]const u8 = null;
var argument_index: usize = 0; var argument_index: usize = 0;
var argument_ovmf_path: ?[]const u8 = null; var argument_ovmf_path: ?[]const u8 = null;
var argument_is_default: ?bool = null;
while (argument_parser.next()) |argument_type| switch (argument_type) { while (argument_parser.next()) |argument_type| switch (argument_type) {
.disk_image_path => { .disk_image_path => {
@ -66,7 +76,7 @@ pub fn main() anyerror!void {
argument_qemu_options = undefined; argument_qemu_options = undefined;
inline for (lib.fields(lib.QEMUOptions), 0..) |field, field_index| { inline for (lib.fields(lib.QEMUOptions), 0..) |field, field_index| {
@field(argument_qemu_options.?, field.name) = if (lib.equal(u8, boolean_argument_strings[field_index], "true")) true else if (lib.equal(u8, boolean_argument_strings[field_index], "false")) false else return Error.qemu_options_not_found; @field(argument_qemu_options.?, field.name) = parseBool(boolean_argument_strings[field_index]) catch return Error.qemu_options_not_found;
} }
}, },
.configuration => { .configuration => {
@ -82,15 +92,15 @@ pub fn main() anyerror!void {
argument_index += 1; argument_index += 1;
}, },
.ci => { .ci => {
argument_ci = if (lib.equal(u8, arguments[argument_index], "true")) true else if (lib.equal(u8, arguments[argument_index], "false")) false else return Error.ci_not_found; argument_ci = parseBool(arguments[argument_index]) catch return Error.ci_not_found;
argument_index += 1; argument_index += 1;
}, },
.debug_user => { .debug_user => {
argument_debug_user = if (lib.equal(u8, arguments[argument_index], "true")) true else if (lib.equal(u8, arguments[argument_index], "false")) false else return Error.debug_user_not_found; argument_debug_user = parseBool(arguments[argument_index]) catch return Error.debug_user_not_found;
argument_index += 1; argument_index += 1;
}, },
.debug_loader => { .debug_loader => {
argument_debug_loader = if (lib.equal(u8, arguments[argument_index], "true")) true else if (lib.equal(u8, arguments[argument_index], "false")) false else return Error.debug_loader_not_found; argument_debug_loader = parseBool(arguments[argument_index]) catch return Error.debug_loader_not_found;
argument_index += 1; argument_index += 1;
}, },
.init => { .init => {
@ -101,6 +111,10 @@ pub fn main() anyerror!void {
argument_ovmf_path = arguments[argument_index]; argument_ovmf_path = arguments[argument_index];
argument_index += 1; argument_index += 1;
}, },
.is_default => {
argument_is_default = parseBool(arguments[argument_index]) catch return Error.is_default_not_found;
argument_index += 1;
},
}; };
if (argument_index != arguments.len) return Error.wrong_argument_count; if (argument_index != arguments.len) return Error.wrong_argument_count;
@ -117,6 +131,7 @@ pub fn main() anyerror!void {
.debug_loader = argument_debug_loader orelse return Error.debug_loader_not_found, .debug_loader = argument_debug_loader orelse return Error.debug_loader_not_found,
.init = argument_init_path orelse return Error.init_not_found, .init = argument_init_path orelse return Error.init_not_found,
.ovmf_path = argument_ovmf_path orelse return Error.ovmf_path_not_found, .ovmf_path = argument_ovmf_path orelse return Error.ovmf_path_not_found,
.is_default = argument_is_default orelse return Error.is_default_not_found,
}; };
}; };
@ -124,6 +139,21 @@ pub fn main() anyerror!void {
.qemu => { .qemu => {
const qemu_options = arguments_result.qemu_options; const qemu_options = arguments_result.qemu_options;
const unique_base_name = blk: {
var list = host.ArrayList(u8).init(wrapped_allocator.zigUnwrap());
inline for (lib.fields(Configuration)) |conf_field| {
try list.appendSlice(@tagName(@field(arguments_result.configuration, conf_field.name)));
try list.append('_');
}
break :blk list.items;
};
const debugcon_file = try lib.concat(wrapped_allocator.zigUnwrap(), u8, &.{ "logs/", unique_base_name, "debugcon.log" });
const qemu_debug_file = try lib.concat(wrapped_allocator.zigUnwrap(), u8, &.{ "logs/", unique_base_name, "debug.log" });
var debugcon_file_used = false;
var qemu_debug_file_used = false;
const config_file = try host.cwd().readFileAlloc(wrapped_allocator.zigUnwrap(), "config/qemu.json", max_file_length); const config_file = try host.cwd().readFileAlloc(wrapped_allocator.zigUnwrap(), "config/qemu.json", max_file_length);
const parsed_arguments = try lib.json.parseFromSlice(Arguments, wrapped_allocator.zigUnwrap(), config_file, .{}); const parsed_arguments = try lib.json.parseFromSlice(Arguments, wrapped_allocator.zigUnwrap(), config_file, .{});
const arguments = parsed_arguments.value; const arguments = parsed_arguments.value;
@ -169,7 +199,12 @@ pub fn main() anyerror!void {
if (arguments.debugcon) |debugcon| { if (arguments.debugcon) |debugcon| {
try argument_list.append("-debugcon"); try argument_list.append("-debugcon");
try argument_list.append(@tagName(debugcon)); if (arguments_result.is_default) {
try argument_list.append(@tagName(debugcon));
} else {
debugcon_file_used = true;
try argument_list.append(try lib.concat(wrapped_allocator.zigUnwrap(), u8, &.{ "file:", debugcon_file }));
}
} }
if (arguments.memory) |memory| { if (arguments.memory) |memory| {
@ -213,30 +248,29 @@ pub fn main() anyerror!void {
} }
} }
if (!arguments_result.ci) { if (arguments.log) |log_configuration| {
if (arguments.log) |log_configuration| { var log_what = host.ArrayList(u8).init(wrapped_allocator.zigUnwrap());
var log_what = host.ArrayList(u8).init(wrapped_allocator.zigUnwrap());
if (log_configuration.guest_errors) try log_what.appendSlice("guest_errors,"); if (log_configuration.guest_errors) try log_what.appendSlice("guest_errors,");
if (log_configuration.interrupts) try log_what.appendSlice("int,"); if (log_configuration.interrupts) try log_what.appendSlice("int,");
if (!arguments_result.ci and log_configuration.assembly) try log_what.appendSlice("in_asm,"); if (!arguments_result.ci and log_configuration.assembly) try log_what.appendSlice("in_asm,");
if (log_what.items.len > 0) { if (log_what.items.len > 0) {
// Delete the last comma // Delete the last comma
_ = log_what.pop(); _ = log_what.pop();
try argument_list.append("-d"); try argument_list.append("-d");
try argument_list.append(log_what.items); try argument_list.append(log_what.items);
if (log_configuration.interrupts) { if (log_configuration.interrupts) {
try argument_list.appendSlice(&.{ "-machine", "smm=off" }); try argument_list.appendSlice(&.{ "-machine", "smm=off" });
}
} }
}
if (log_configuration.file) |log_file| { if (!arguments_result.is_default) {
try argument_list.append("-D"); qemu_debug_file_used = true;
try argument_list.append(log_file); try argument_list.append("-D");
} try argument_list.append(qemu_debug_file);
} }
} }
} }
@ -298,6 +332,7 @@ pub fn main() anyerror!void {
} }
var process = host.ChildProcess.init(argument_list.items, wrapped_allocator.zigUnwrap()); var process = host.ChildProcess.init(argument_list.items, wrapped_allocator.zigUnwrap());
//process.stdout_behavior = .I;
const result = try process.spawnAndWait(); const result = try process.spawnAndWait();
if (result == .Exited) { if (result == .Exited) {
@ -310,7 +345,9 @@ pub fn main() anyerror!void {
const qemu_exit_code = @as(lib.QEMU.ExitCode, @enumFromInt(masked_exit_code >> 1)); const qemu_exit_code = @as(lib.QEMU.ExitCode, @enumFromInt(masked_exit_code >> 1));
switch (qemu_exit_code) { switch (qemu_exit_code) {
.success => return log.info("Success!", .{}), .success => {
return;
},
.failure => log.err("QEMU exited with failure code 0x{x}", .{exit_code}), .failure => log.err("QEMU exited with failure code 0x{x}", .{exit_code}),
_ => log.err("Totally unexpected value", .{}), _ => log.err("Totally unexpected value", .{}),
} }
@ -320,6 +357,16 @@ pub fn main() anyerror!void {
log.err("QEMU was {s}", .{@tagName(result)}); log.err("QEMU was {s}", .{@tagName(result)});
} }
if (debugcon_file_used) {
const debugcon_file_content = try host.cwd().readFileAlloc(wrapped_allocator.zigUnwrap(), debugcon_file, lib.maxInt(usize));
@import("std").debug.print("\n{s}\n", .{debugcon_file_content});
}
if (qemu_debug_file_used) {
const debug_file_content = try host.cwd().readFileAlloc(wrapped_allocator.zigUnwrap(), qemu_debug_file, lib.maxInt(usize));
@import("std").debug.print("\n{s}\n", .{debug_file_content});
}
return Error.qemu_error; return Error.qemu_error;
}, },
} }
@ -348,7 +395,6 @@ const Arguments = struct {
stdio, stdio,
}, },
log: ?struct { log: ?struct {
file: ?[]const u8,
guest_errors: bool, guest_errors: bool,
assembly: bool, assembly: bool,
interrupts: bool, interrupts: bool,

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
# $1 Loopback device # $1 Loopback device
set -e set -e
sudo mkfs.fat -F 32 `cat $1`p1 1>2 sudo mkfs.fat -F 32 `cat $1`p1