Hi! Thank you for clicking onto my question!
So. I new to programming in general. in the process of making a bare-metal program that writes a cat image onto the framebuffer.
I could do this directly in the UEFI bootloader. but thats boring. So I decided that the part responsible from the write should be the kernel.
currently. i am just trying to clear the buffer from the kernel
snippet for jump part (bootservices exited):
// global
export const fennec_baked = @embedFile("baked/fennec");
// inside main() -> noreturn
asm volatile (
\\
\\ mov %[fb], %rax
:
: [fb] "X" (gop.mode.frame_buffer_base),
);
asm volatile (
\\
\\ mov %[fbl], %rbx
:
: [fbl] "X" (gop.mode.frame_buffer_size),
);
asm volatile ("jmp fennec_baked");
fennec.zig (will be extracted from elf to raw by objdump)
var fb_u64: []volatile u64 = undefined;
export fn _start() callconv(.Naked) noreturn {
const fb: u64 = asm volatile (""
: [fb] "={rax}" (-> u64),
);
const fb_len: u64 = asm volatile (""
: [fb_len] "={rbx}" (-> u64),
);
fb_u64 = .{ .ptr = @ptrFromInt(fb), .len = fb_len }; // invalid
asm volatile ("jmp %[f]"
:
: [f] "X" (&iru),
);
}
fn iru() noreturn {
const koloro: u64 = 0xff000000;
const k: u64 = koloro << 32 | koloro;
for (fb_u64) |*px| {
px.* = k;
}
while (true) {}
}
now. the problem is: i have no idea how to construct a []volatile u64 from a pointer and length. how can i do it?
n0s4
February 9, 2025, 2:04pm
2
I’ve not really looked at your code, but here’s a snippet that reconstructs a slice from two u64s:
const std = @import("std");
pub fn main() !void {
const slice: []const u8 = "Hello, world!";
const pointer: u64 = @intFromPtr(slice.ptr);
const length: u64 = slice.len;
var reconstructed: []const u8 = undefined;
reconstructed.ptr = @ptrFromInt(pointer);
reconstructed.len = length;
std.debug.print("{s}\n", .{reconstructed});
}
3 Likes
ajoino
February 9, 2025, 2:24pm
3
Out of curiosity, Icd reasly love to known what a baked fennec looks like. Would you mind sharing the image?
you can simply do
const ptr: [*]const u8 = @ptrFromInt(intptr);
const slice = ptr[0..length];
8 Likes
unfortunately. fennecs are too cute to be baked. so ill give you intel format x86 assembly
src/baked/fennec: file format binary
Disassembly of section .data:
00000000 <.data>:
0: 90 nop
1: 90 nop
2: 48 c1 eb 03 shr rbx,0x3
6: 48 89 05 33 10 00 00 mov QWORD PTR [rip+0x1033],rax # 0x1040
d: 48 89 1d 34 10 00 00 mov QWORD PTR [rip+0x1034],rbx # 0x1048
14: eb 00 jmp 0x16
16: 48 8b 05 23 10 00 00 mov rax,QWORD PTR [rip+0x1023] # 0x1040
1d: 48 8b 0d 24 10 00 00 mov rcx,QWORD PTR [rip+0x1024] # 0x1048
24: 31 d2 xor edx,edx
26: 48 be ff ff 00 00 ff movabs rsi,0xffff0000ffff
2d: ff 00 00
30: 48 39 d1 cmp rcx,rdx
33: 74 09 je 0x3e
35: 48 89 34 d0 mov QWORD PTR [rax+rdx*8],rsi
39: 48 ff c2 inc rdx
3c: eb f2 jmp 0x30
3e: eb fe jmp 0x3e
made by extracting .text from fennec elf
1 Like
thanks! now i am stuck on low level bullshittery (protection fault thrown when executing nop instuction. or did it even jump to the right place?)
im glad qemu monitor exists. im trying it out soon :3
edit: on secound thought. it might be because of how objdump has formatted the resulting raw binary? still it is the only way that i know of to make a binary jmp’able as i have no idea how to deal with elf executables (entry field and offset of .text is different?)
i’ve just changed the build target. now rather than erroring over QEMU stdout. it seems to do nothing at all after the jmp (or did zig ignore the jump?)
i love low level programming