Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get VESA BIOS Information

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!

like image 346
Ben Gubler Avatar asked Jun 12 '18 17:06

Ben Gubler


1 Answers

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.

like image 52
memo Avatar answered Nov 19 '22 19:11

memo