14

I'm following through the Phil-Opp Tutorials about writing an OS in Rust, and, after playing around with it a little bit, I want to fiddle with displaying real graphics on the screen.

I've figured out that I should probably start out by using the Linear Frame Buffer, with VESA. I found some tutorials on osdev.org here and here, but they keep on talking about "function codes" and es:di. The second link says this:

FUNCTION: Get VESA BIOS information

Function code: 0x4F00

Description: Returns the VESA BIOS information, including manufacturer, supported modes, available video memory, etc... Input: AX = 0x4F00

Input: ES:DI = Segment:Offset pointer to where to store VESA BIOS information structure.

Output: AX = 0x004F on success, other values indicate that VESA BIOS is not supported.

Anyway, the above function returns the following structure and stores it in ES:DI as they were on entry. On entry, ES:DI should contain a pointer to the following structure:

vbe_info_structure: .signature db "VBE2" ; indicate support for VBE 2.0+ .table_data: resb 512-4 ; reserve space for the table below

Though I've looked at some assembly language tutorials, I have no idea what a "function code" is. From what I understand, if I mov ax, 0x4f00, and create a structure like the one above, it will magically overwrite the structure, which I could then pass as a parameter to my Rust Code? How do I, or do I need to, set my es:di? (From researching, I thought that it was just automatically set on modern processors)

Should I do all of this stuff in Inline Assembly instead? Should I just use UEFI and rewrite my kernel? I would love if you could give an example of how to access the vbe_info_structure in Rust code (I'm running in long mode).

Here's my boot.asm file so far, but it doesn't work yet: https://gist.github.com/nebrelbug/5a0042d4de32f942bb72e71fe282bdd2. Thanks!

Ben Gubler
  • 1,393
  • 3
  • 18
  • 32
  • BIOS calls are typically made by putting a value in a register and running `int 0x10` or some other interrupt. e.g. https://en.wikipedia.org/wiki/INT_10H lists the different AH values. These values are "function codes", like system call numbers for Linux system calls where you set `eax=__NR_write` before running `syscall`. – Peter Cordes Jun 12 '18 at 17:46
  • @PeterCordes Oh, I did see some stuff about `int 0x10` in the article. So, if I `mov ax, 0x004f`, run `int 0x10`, then it should work? Do I need to set `ES:DI`? – Ben Gubler Jun 12 '18 at 18:00
  • 1
    Yes. You need to set `ES:DI` to point to a 512 byte variable space starting with the four bytes `VBE2` as defined above before calling `int 10h`. After calling `int 10h` the structure will be filled with the data. – zx485 Jun 12 '18 at 19:31
  • @zx485 Do I put the variable space in `.bss`? – Ben Gubler Jun 12 '18 at 19:39
  • You can use the `.bss` if you manually put the `VBE2` there (and possiblity init to zero!?) before calling `int 10h`. Or use the `.data` segment as defined above. – zx485 Jun 12 '18 at 19:46
  • @zx485 I tried to put my `vbe_info_structure` in my bootcode, but it throws an error: `error: operation size not specified src/arch/x86_64/boot.asm:143: warning: uninitialized space declared in non-BSS section `.rodata': zeroing` – Ben Gubler Jun 12 '18 at 19:57
  • `.rodata` is the wrong section for sure, because the area will be written to. Try putting it in `.data`. – zx485 Jun 12 '18 at 20:06
  • If you are already in long mode, beware. The VBE has a protected mode interface that requires you to create some 16-bit code/data segments. It may be easier to gather all the information and set the mode *before* leaving real mode. Anyway, [here](http://www.petesqbsite.com/sections/tutorials/tuts/vbe3.pdf) you can find the detailed instruction on how to call VBE functions from compatibility mode. – Margaret Bloom Jun 12 '18 at 20:56
  • @MargaretBloom thanks! @zx485, I put the data in a `section.data` section, but it still throws an error. [Here's my code.](https://gist.github.com/nebrelbug/5a0042d4de32f942bb72e71fe282bdd2) What am I doing wrong? – Ben Gubler Jun 13 '18 at 05:09
  • It's the problem @MargaretBloom wrote about. You're using 16-bit code in a 32-bit code segment. The tutorials you mentioned above refer to 16-bit _Real Mode_, but you're in 32-bit _Protected Mode_. I don't know about VESA _Protected Mode_ functions, I've never used them, so I can't help you with that. – zx485 Jun 13 '18 at 12:46
  • @zx485 ok, thanks. I'm probably going to try and remake my kernel with UEFI support and use that for graphics. Any good tutorials for that? :) – Ben Gubler Jun 14 '18 at 19:10
  • 1
    No tutorial, but [fpmurphy is a good blog on UEFI development](https://blog.fpmurphy.com/). – zx485 Jun 14 '18 at 19:19
  • `section.data:` Ithink was meant to be `section .data` – Michael Petch Aug 10 '18 at 19:56

1 Answers1

4

In your boot.asm file, you have:

get_vesa_info:
    mov ax, 0x4f00
    mov [es:di], vbe_info_structure
    int 0x10
    ret

The third line must be replaced by

    mov di, vbe_info_structure

Explanation: as it is now, it attempts to write the constant vbe_info_structure at the address pointed to by es:di (which is undefined in your case). What you want instead, is to load the address vbe_info_structure into di, and thus pass it to the int 0x10 routine.

By the way, int 0x10 performs several functions. In order to tell it which one you want to call, you pass the "function code" in the ax register. Think of the function code as the name of the function (there are no names in assembly, just numbers and addresses).

Also, you need to setup es correctly. Either do

push ds
pop es

assuming that ds already points to section.data, or by using an assembler directive (assume es section.data ? -- not sure about this, it's been a long time since I've used an assembler). Or maybe like this:

mov ax, @section.data
mov es, ax

which should be done before loading 0x4f00 into ax, of course.

memo
  • 1,868
  • 11
  • 19
  • @MichaelPetch Good points. WRT protected mode: he could call get_vesa_info before entering protected mode, to make things easier. – memo Aug 06 '18 at 11:29
  • To inform yourself about the VESA BIOS, you should have a look at RBIL (http://www.ctyme.com/intr/rb-0273.htm) – caylee Aug 06 '18 at 11:31