Hello all,
I recently started writing a somehow basic bootloader. Now, the most things are working, but while reading the kernel file, UEFI greets me with BdsDxe: failed to start Boot0001 'UEFI QEMU HARDDISK QM00004' from PciRoot(0x0)
and Pci(0x1,0x1)/Ata(Secondary,Slave,0x0): Aborted
. After that, it tries to start PXE via IPv4 and after that IPv6 and then it starts the UEFI Interactive Shell.
My current code for the file reading:
const std = @import("std");
const uefi = std.os.uefi;
const puts = @import("./puts.zig").puts;
pub fn usizeToString(value: usize) [20]u8 {
var buffer: [20]u8 = undefined;
var index: u8 = 19;
var value_working = value;
while (value_working > 0) : (index -= 1) {
const digit = @as(u8, @intCast(value_working % 10));
buffer[index] = digit + '0';
value_working /= 10;
}
return buffer;
}
pub fn loadKernel(path: [*:0]const u16, image: *[]const u8) uefi.Status {
// locate file system protocol
const boot_services = uefi.system_table.boot_services.?;
var file_system_protocol: ?*uefi.protocol.SimpleFileSystem = undefined;
var status: uefi.Status = uefi.Status.Success;
puts("DEBUG: Locating file system protocol\r\n");
status = boot_services.locateProtocol(&uefi.protocol.SimpleFileSystem.guid, null, @as(*?*anyopaque, @ptrCast(&file_system_protocol)));
if (status != uefi.Status.Success) {
puts("ERROR: Cannot locate file system protocol\r\n");
return status;
}
// open file system root
puts("DEBUG: Opening file system root\r\n");
var root: *const uefi.protocol.File = undefined;
status = file_system_protocol.?.openVolume(&root);
if (status != uefi.Status.Success) {
puts("ERROR: Cannot open root volume\r\n");
return status;
}
// locate file
puts("DEBUG: Locating file\r\n");
var file: *const uefi.protocol.File = undefined;
status = root.open(&file, path, uefi.protocol.File.efi_file_mode_read, uefi.protocol.File.efi_file_read_only);
if (status != uefi.Status.Success) {
puts("ERROR: Cannot locate file\r\n");
return status;
}
// get file info
puts("DEBUG: Getting file info\r\n");
const file_info_buf_len = @sizeOf(uefi.FileInfo) + 512;
var file_info_size: usize = file_info_buf_len;
var file_info_buf: [file_info_buf_len]u8 align(@alignOf(uefi.FileInfo)) = undefined;
status = file.getInfo(&uefi.FileInfo.guid, &file_info_size, &file_info_buf);
switch (status) {
uefi.Status.Success => {
puts("DEBUG: Getting file info worked\r\n");
},
uefi.Status.BufferTooSmall => {
puts("DEBUG: BufferTooSmall; Handling comes later\r\n");
},
else => {
puts("ERROR: Cannot get file info\r\n");
return status;
}
}
// if (status != uefi.Status.Success) {
// puts("ERROR: Cannot get file info\r\n");
// return status;
// }
const file_info: *uefi.FileInfo = @ptrCast(@alignCast(&file_info_buf));
var image_buffer: [*]u8 = undefined;
// allocate space
puts("DEBUG: Allocating space for file\r\n");
status = boot_services.allocatePool(uefi.tables.MemoryType.LoaderData, @as(u64, @intCast(file_info.file_size)), @as(*[*]align(8) u8, @ptrCast(&image_buffer)));
puts("DEBUG: Allocated ");
puts(&usizeToString(file_info.file_size));
puts(" bytes of RAM for the file\r\n");
if (status != uefi.Status.Success) {
puts("ERROR: Cannot allocate RAM for file\r\n");
return status;
}
// read file
puts("DEBUG: Reading file\r\n");
status = file.read(@as(*usize, @ptrFromInt(@as(usize, @intCast(file_info.file_size)))), image_buffer);
if (status != uefi.Status.Success) {
puts("ERROR: Cannot read file\r\n");
return status;
}
// save in pointers
image.* = image_buffer[0 .. file_info.file_size];
return status;
}
In the main function, the return code of the bootloader function (which starts the loadKernel function) is put out. But somehow, the bootloader does not even get there (it also would not get there if everything would work, but then it would display some other messages). So just while reading the file something strange happens…
What am I doing wrong?
I already wrote about this in a slightly older topic, but I did a new topic to just mark that the old topic is solved.
Looking forwards,
Samuel Fiedler