Can i make a slice from u64 length and u64 pointer?

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?

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

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