Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Matthias Schmidt
    @ms140569
    @CadmiumC4 - yes sure, if i switch to nightly the stuff compiles. But the point here is to make this explicit by providing an override using a rust-toolchain.toml file in the proper directory or mention it in the README. Otherwise a newly checked-out repo won't compile out of the box ...
    Philipp Schuster
    @phip1611

    I'll look into it @ms140569 :)

    @ all : Does anyone know some best practices for coping with nested locking in the logging- and panic infrastructure? In my (very basic!) kernel I have a logging facade that logs to serial and the frame buffer. The facade is behind a Mutex. A panic calls my logging facade (via the log crate). Hence, if inside my logging facade a panic occurs, I have a deadlock/nested locking problem. The system is not functional and I will never output an error message.

    Are there any cool tips here? Anything except "don't use locking"?

    phil-opp
    @phil-opp:matrix.org
    [m]
    I don't think that there is a good solution to this. If your logging facade panics, it might be in an invalid state afterwards. So even if you do an unsafe force-unlock in your panic handler, it might not work. The standard library has the concept of a poisoned mutex for this case.
    You could try to avoid any possible panic in your logging facade of course, and instead return a Result. Then you can cleanly unlock the mutex again. You could even panic afterwards :)
    phil-opp
    @phil-opp:matrix.org
    [m]
    However, panicking inside your panic handler is not a good idea. So maybe set some atomic PANICKING static and simply ignore any logging error if it is set.
    It would be really cool if Rust had some function attribute to forbid panics in that function. I'm only aware of the no_panic crate, but this apparently only works with unwinding.
    Joakim Pettersen
    @sven-eliasen

    Hi guys, im kinda new to os dev and gave myself the project to write a small shell in uefi interface and for that i'm using uefi-rs.
    And I found myself struggling with reading an input, I get that I have to use stdin.read_key() but it sounds like I have to use it with something like:

    let mut events = [ stdin.wait_for_key_event()]; 
    boot_services.wait_for_event(events); // didn't actually tried this bit of code

    Like am I on the right way ? I dont really get how to use it with stdin.read_key(). Could someone show me a little snippet about how I'm suppose to achieve this ?

    Joakim Pettersen
    @sven-eliasen

    Hi, I got my way with my previous question on my own but I have a new one which I really need your help : I'm trying to read a file which is inside the EFI partition, so I look up for the C way of doing it and it seems like I need to get an instance of SimpleFileSystem to call open_volume().

    But in C they instantiate it with a NULL pointer, which is impossible in Rust right ? So how could I call an instanceSimpleFileSystem in Rust ?

    I tried by looking at the source but I dont yet understand everything in this struct :

    pub struct SimpleFileSystem {
        revision: u64,
        open_volume:
            extern "efiapi" fn(this: &mut SimpleFileSystem, root: &mut *mut FileImpl) -> Status,
    }

    I would really appreciate your help please

    Philipp Schuster
    @phip1611
    Hey. If you want to open the volume, it should work like this:
        let fs = uefi_boot_system_table
            .boot_services()
            .locate_protocol::<SimpleFileSystem>()
            .unwrap()
            .unwrap();
        let fs = unsafe { &mut *fs.get() };
        // TODO: not sure what will be inside buf; is there already a type for that in the UEFI crate?
        let mut buf = [0; 4096];
        let mut dir = fs.open_volume().unwrap().unwrap();
        let res = dir.read_entry(&mut buf).unwrap().unwrap().unwrap();
        log::debug!("{:#?}", res);
    Output of the debug-statement:
    [DEBUG]     src/main.rs@82: NamedFileProtocolInfo {
        header: FileInfoHeader {
            size: 88,
            file_size: 8192,
            physical_size: 8192,
            create_time: 2022-01-24 22:46:34.000000000, Timezone=local, Daylight=(empty),
            last_access_time: 2022-01-24 00:00:00.000000000, Timezone=local, Daylight=(empty),
            modification_time: 2022-01-24 22:46:34.000000000, Timezone=local, Daylight=(empty),
            attribute: DIRECTORY,
        },
        name: [
            'E',
            'F',
            'I',
            '\u{0}',
        ],
    }
    I admit that the API is not 100% intuitive. I don't know much about all the UEFI protocols and if there are any plans to improve support for them soon.
    phil-opp
    @phil-opp:matrix.org
    [m]
    This is how I did it in the bootloader crate: https://github.com/rust-osdev/bootloader/blob/9583eafafe7aaa5282d4739006fc7172d8d1552e/src/bin/uefi.rs#L123-L175 . The difference to your example is that I'm also using the LoadedImage and DevicePath protocols. I don't remember why I did it this way though :D
    Joakim Pettersen
    @sven-eliasen

    Hi, sorry I took so long to answer, I hadn't so much time to work on this since last time.

    Anyway, big thanks to both of you, I'm inspired myself from your code to make it work !
    I used @phip1611 's part to open the protocol and @phil-opp:matrix.org to read my file.

    To provide a proper buffer to convert to str after, I used this piece of code which was pretty neat :

    let buf_layout = Layout::array::<u8>(file_size).unwrap();
    let mut buf = allocate_buffer(buf_layout); // Return a 'Box<[u8]>'

    So just so I understand, this is the way instantiate any protocol right ?

    threeoh6000
    @threeoh6000
    hey i'm getting started with this and i keep getting "The bootloader dependency has not the right format: No package.metadata.bootloader.target key found in Cargo.toml of bootloader" and i don't understand how to fix it
    phil-opp
    @phil-opp:matrix.org
    [m]
    @threeoh6000: Sounds like you're trying to use bootimage together with the 0.10 release of bootloader, is that right? The bootimage crate only works on bootloader v0.9 so I recommend to use this older version for now.
    Joakim Pettersen
    @sven-eliasen

    Hi again guys, i'm trying to boot to windows from my uefi application, to achieve this I wrote this :

    let windows_efi = match read_file(&system_table, "EFI\\Microsoft\\Boot\\bootmgfw.old.efi") {
                        Ok(t) => t, // This return an allocated buffer with the content of the file
                        Err(_) => panic!("Windows efi file not found")
    };
    
    let windows_handle = system_table
                        .boot_services()
                        .load_image_from_buffer(*image_handle, windows_efi.deref())
                        .unwrap_success();
    
    match system_table.boot_services().start_image(windows_handle) {
                        Ok(_) => log::info!("OK"),
                        Err(e) => log::info!("KO : {:#?}", e) // I'm getting a INVALID_PARAMETER status here
    }

    I'm getting an INVALID_PARAMETER status and I don't really understand why.

    Am doing this the right way ? I would really appreciate your help as I'm still learning the UEFI specification.

    phil-opp
    @phil-opp:matrix.org
    [m]
    I haven't tried these functions yet, so I don't think that I can help much here. It looks like the error comes directly from the UEFI firmware. I just looked through the UEFI specs (PDF at https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf ): On page 220-221, the StartImage function is described. Apparently an EFI_INVALID_PARAMETER error means that the given handle is invalid or was already initialized, but I think it could be also the exit code of the efi file that you're calling. So I would first try it with a dummy EFI file that always succeeds to pinpoint the problem.
    Joakim Pettersen
    @sven-eliasen

    Yup good idea, so I tried with the basic example from the bootloader crate and it's working well

    Any ideas why the windows boot manager doesn't boot that way ?

    Joakim Pettersen
    @sven-eliasen
    I was looking to boot winload.efi directly but I can't find it, not a good idea anyway
    Joakim Pettersen
    @sven-eliasen
    Could it be that I need to allocate a special amount of memory in order to start windows's efi image ?
    phil-opp
    @phil-opp:matrix.org
    [m]
    I don't know. Is the windows efi image normally started directly by the UEFI firware? If so, it might expecting some initial machine state
    Joakim Pettersen
    @sven-eliasen

    The bootmgfw.efi file is started directly by the firmware yes, it has a dedicated boot entry linking to the image. Doesn't it mean that there aren't any previous initialization ?

    I will try to play with the load options of the image from LoadedImage's protocole, if that doesn't work I will be creating an issue on github.

    Thanks for your help anyway !

    phil-opp
    @phil-opp:matrix.org
    [m]

    Doesn't it mean that there aren't any previous initialization ?

    Yes, probably. But maybe you're changing some state before starting the image, so that the windows efi image is started with an unexpected state? Just guessing, though...

    The Iris System 🏳️‍🌈🏳️‍⚧️
    @iris:smol.systems
    [m]
    bootmgfw.efi happily works when started from other EFI boot managers (rEFInd etc) so I'd have a look at what state things like that leave the system in before launching another EFI executable and see if you can get it to work that way
    Joakim Pettersen
    @sven-eliasen

    bootmgfw.efi happily works when started from other EFI boot managers (rEFInd etc) so I'd have a look at what state things like that leave the system in before launching another EFI executable and see if you can get it to work that way

    You mean like call ExitBootServices before starting the image ? Could try that.

    What's really odd is that it work with with other efi image. I've manage to load it from the EFI Shell so I guess it should be possible.
    I'm not touching any NVRAM variables or anything, I'll try by clearing load options or something.

    No wait I don't think I should exit boot services before starting a bootloader
    jojolepirate
    @jojolepirate
    Hello, I also have an issue loading a specific efi file that works in an EFI shell. I'm using a read_file - load_image - start_image code, it works correctly when loading a simple efi file, windows bootloader even works, efi shell works, but the sedutil payload (which can be found here: https://github.com/Drive-Trust-Alliance/exec/blob/master/UEFI64.img.gz?raw=true) yields a uefi::LOAD_ERROR error on QEMU and on two PCs.
    How could I learn more about the error? Thanks!
    Using uefi version 0.14.0
    ADEOYE ADEFEMI OPEOLUWA
    @opeolluwa
    Hello here, I'm Opeoluwa just breaking into systems engineering. I hope to learn and contribute here
    Chris Drzewiecki
    @cdrzewiecki_gitlab
    Does anyone know if there is some kind of issue with using global pages in QEMU with the -enable-kvm option? I have PGE (bit 7) set in CR4, but when I try to load a page table into CR3 which has pages with the global bit set, I get a triple fault. Only when using -enable-kvm though, if I take that off it works fine.
    Chris Drzewiecki
    @cdrzewiecki_gitlab
    ah... wait, I figured it out. Of course I figure it out when I ask. :) Per the Intel system programming manual, you can only set the global bit in a paging entry which maps a page. So P1 for 4KB pages, P2 for 2MB pages, and P3 for 1GB pages. I was setting the global flag at every level, and apparently qemu's emulation allows that even though it's not correct.
    Js2xxx
    @js2xxx
    Hello there, does anyone know how to get _DYNAMIC's loaded address in a shared library without an interpreter? As far as I've tried, both gcc and ld.lld create a .got entry for that symbol, and whenever I try to get the address of it in Rust code, I always obtain the address of the entry in .got. I have checked the disassembled code generated by both linker and always found mov rax, [rel ..] instead of lea rax, [rel ..] which is what I wanted.
    Jay Jackson
    @TheBotlyNoob
    How could I get the Y and X axis while enumerating the framebuffer?
    Philipp Schuster
    @phip1611

    @js2xxx I'm not sure what you are trying to achieve. Do you want to know the runtime address where a bunch of code was loaded to?
    On x86, you can try something like:

            # Loads the link time address into rcx
                # OFFSET in intel syntax is similar to $ in AT&T syntax
                # This way we get the symbol address as immediate in assembly output
                # https://stackoverflow.com/questions/39355188/
                # This is different to nasm, where the symbol address would be used
                # by default as immediate.
            mov     rcx, OFFSET start
            # Loads the real address of start into rdx
            #  results in "-0x20(%rip)"
            lea     rdx, [rip - start]
            # rdx, the relative runtime offset
            # example: link addr = 8MiB
            #          real addr = 1MiB
            #          offset    = 1MiB - 8MiB = -7MiB
            # => we need to add "-7MiB" (the offset in rdx) to every static/old/invalid address next
            sub     rdx, rcx

    RDX will contain the relative offset between the real address and the link time address. You just need the address of a well-known symbol of your library. In this case, it uses "start".

    Philipp Schuster
    @phip1611

    How could I get the Y and X axis while enumerating the framebuffer?

    Well, usually you have a reference to a continuous memory region and meta information about the buffer, such as height, width, and pixel layout. When you're enumerating all pixels of the continuous memory region (usually pairs of 32-bit, for example (_rgb), you have to iterate over the 32-bit values at first. To get the corresponding index of the pixel on the screen, you calculate:

    y_pos = i / width
    x_pos = i % width

    Does this help you?

    Lorenzo De Marco
    @LorenzoDeMarco
    Greetings everyone. New to this chat but I've been following the rust-osdev related projects for a while...
    Thought it'd have been nice to join here :-)
    phil-opp
    @phil-opp:matrix.org
    [m]
    Welcome!
    madmaxio
    @madmaxio
    This chat works.
    Chris Drzewiecki
    @cdrzewiecki_gitlab

    Wondering if anyone has thoughts on this: I thought it might be nice to update my IDT with new interrupt handlers at runtime, if needed to do so. Right now I have it setup like in blog_os - I have a lazy_static which initializes an immutable static IDT. Obviously I can't mutate that. And I can't easily create a new one on demand (to then load into the CPU), because it needs to be static so it can't accidentally go away on the processor. The way I see it, there are a couple of options: a) have a static mut IDT (probably not a good idea if I want to avoid UB land), or create a new IDT on the heap, leak the memory, and load it (also not great cause now I'm leaking memory even if it is small). Wondering if there is a good way to do this.

    The alternative option is just to have my interrupt handlers contain any branching logic needed so I would never need to write a new function into the IDT for some reason. Probably what I will do in the end, because it's safe and easy. But it did get me thinking about how one would properly go about updating their IDT if they wanted to do so.

    Lorenzo De Marco
    @ledomsw:matrix.org
    [m]

    @cdrzewiecki_gitlab I had to do this too, here's what worked for me.
    I first got an initial IDT up and running using lazy_static:

    
    lazy_static! {
        pub static ref IDT: RwLock<InterruptDescriptorTable> = RwLock::new({
            let mut idt = InterruptDescriptorTable::new();
            idt.breakpoint.set_handler_fn(breakpoint_handler);
            unsafe {
                idt.double_fault.set_handler_fn(double_fault_handler)
                    .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
            }
            idt.non_maskable_interrupt.set_handler_fn(non_maskable_interrupt_handler);
    // ..... lines omitted for brevity
            idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler);
    // ..... lines omitted for brevity
            idt
        });
    }

    then I declared the following function to load the IDT:

    pub fn init_idt() {
        unsafe { IDT.read().load_unsafe(); }
    }

    so when the kernel starts, the first time the BSP will run init_idt().
    Then later, when I need to make changes to the IDT I do this: (example taken from my VMware SVGA module)

    // Set the interrupt handler and enable the IRQ
    let mut idt = crate::interrupts::IDT.write();
    idt[irq.into()].set_handler_fn(svga_interrupt_handler);
    unsafe {
        idt.load_unsafe();
        (*crate::interrupts::PICS.lock()).set_mask(irq, true);
    }

    It may not be the best, cleanest solution but it works for me since I only have to mutate the handlers here. If I have to do that in the future I might consider a different approach but for now the reduced complexity and scope doesn't justify an overhaul. I want to have this be KISS.

    Hope it helps! :)

    For some reason my chat client didn't preserve code indentation... I apologize for that
    Chris Drzewiecki
    @cdrzewiecki_gitlab
    @ledomsw:matrix.org thanks for the suggestion! I was thinking that putting the IDT behind a mutex or something would break the ability to load it, but in hindsight I'm not sure why I was thinking that. (since you call your_idt_instance.load(), not load(your_idt_instance)).
    Lorenzo De Marco
    @ledomsw:matrix.org
    [m]
    Yes, by wrapping it in an RwLock I ensure that I only write to it from one place at a time, and to get to the wrapped InterruptDescriptorTable struct I use either .read() or .write(), depending on the required access. With those methods you get the InterruptDescriptorTable struct directly.
    destiny_hailstorm
    @destiny_hailstorm:matrix.org
    [m]

    This whole project is honestly nuts and pulling my damn brain cells apart XD Awesome stuff!

    Just got Rust up and running for the second time ever (first time was a quick try out to see what the fuss was about), and umm... There is a lot of Rust I still don't understand, but honestly the guide has probably taught me more about how everything works and the general syntax used in more complex programs than anything else.

    Finished the guide after running through it today, I'll be trying to get a game running! I can say for sure it doesn't feel like the OS is quite where I would want it to make a game, but ASCII text and magic keyboard input should let me make a main menu and a game of snake :)

    Really wanting to keep doing more stuff, making my OS in Rust compared to straight NASM is so much easier, especially on Windows, so I just want to make something with more and more features while learning Rust too XD

    What would be some good resources going forward with my OS? I'm more wanting to look into file systems, USB peripherals (assuming BIOS won't be helping me with the keyboard like QEMU), actually installing my OS, and deeper into graphics to allow finer grained control over color and, well, pixels... Maybe OpenGL software rendering or something? (Maybe ordered graphics, USB peripherals, file system, installing)

    Alberto Ruiz
    @aruiz_gitlab
    Hello everyone, I've been working on an OpenFirmware (ieee1275) crate, much like uefi-rs, what's the process to get it included in the rust-osdev group in github?
    Isaac Woods
    @IsaacWoods
    Hi @aruiz_gitlab, great to hear you'd like to get involved! @phil-opp:matrix.org would need to add you to the organisation, so you'll need to wait for him to pick this up
    ADEOYE ADEFEMI OPEOLUWA
    @opeolluwa
    Hello everyone 😊
    I'm just getting started with Rust lang, i intend to venture into embedded systems programming , to build device drivers, OS, bootloader and sort of . But i don't know where to get started
    Alberto Ruiz
    @aruiz_gitlab
    @IsaacWoods thanks, looking forward to it
    @IsaacWoods is there a place where I could file a ticket I can track or is gitter the rigt way?