OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:26 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: BIOS calls for VESA functionalities
PostPosted: Wed Feb 06, 2019 10:56 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
Hi.

I am new in this Forum.
On my way to develop my OS and using VESA for it, I got an issue. It is now in protected mode and I want to call VESA functionalities. I used the source code provided by Napalm at Rohitab (http://www.rohitab.com/discuss/user/3860-napalm/).
Some functionalities work perfectly, but one of them not.

I have a struct called VBE_INFO which holds the vbe info such as vendor, version, etc. Then I supplied reg.ax with 0xF400, regs.es with SEGMENT(&vbe_info) which passes the segment of the pointer and reg.di with OFFSET(&vbe_info) which passes the offset of the 32-bit pointer.

After calling int32 function with 0x10 and &reg as the arguments, I checked the return value in ax and indeed it is 0x00F4. But the vbe_info did not updated by the BIOS. For instance, vbe_info.version is 0. It made me thought perhaps there is a bug in the int32 calling function.

Is there anybody who can help me with that? Maybe others had the same problem before.

Thanks.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Wed Feb 06, 2019 11:10 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
It would probably help to see your actual code.Do you have your OS on Gitlab or Github (or similar service)? Sounds like the memory address of your vbe_info (Segment and Offset) structure that you told Int 10h/04f00h to fill in. Was this a typo?
Quote:
Then I supplied reg.ax with 0xF400,
Did you mean 0x4F00?


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Wed Feb 06, 2019 2:34 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi, and welcome!

You should also initialize the buffer with a magic value. Here's how I do it:
Code:
            xor         ax, ax
            mov         es, ax
            mov         ax, 4f00h
            mov         di, 0A000h
            mov         dword [di], 'VBE2'
            int         10h
            cmp         ax, 004fh
            je          @f
            mov         si, novbe
            jmp         die
@@:

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Wed Feb 06, 2019 3:07 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
iman wrote:
It is now in protected mode and I want to call VESA functionalities.

Does this mean you are executing an INT 10h instruction while in protected mode?

iman wrote:
Then I supplied reg.ax with 0xF400,

As MichaelPetch asked, is this a typo? It should be 0x4F00.

Also as bzt mentioned, you need to give it a signature to tell the BIOS your buffer is big enough to hold the version 2.0 data.

I think your biggest issue is trying to execute an INT 10h instruction while in protected mode. All of this should be done before you move to protected mode.

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 3:12 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
BenLunt wrote:
iman wrote:
It is now in protected mode and I want to call VESA functionalities.

Does this mean you are executing an INT 10h instruction while in protected mode?

iman wrote:
Then I supplied reg.ax with 0xF400,

As MichaelPetch asked, is this a typo? It should be 0x4F00.

Also as bzt mentioned, you need to give it a signature to tell the BIOS your buffer is big enough to hold the version 2.0 data.

I think your biggest issue is trying to execute an INT 10h instruction while in protected mode. All of this should be done before you move to protected mode.

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Sorry it was a typo. I put the value 0x004F in ax and not 0x00F4.
I also put the 'VBE2' signature and reserved 512 bytes for the buffer. To trigger INT 10H in protected mode, I used the same function that Napalm distributed long time ago and as I said for some other calls, it works perfectly. For example, I can supply ax and bx with the needed value and call INT 10H to change the mode for me and it does the job. But for this task that I play with reg.es, although it gives me the success return value, it does not fill up the VBE_INFO buffer.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 3:17 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
MichaelPetch wrote:
It would probably help to see your actual code.Do you have your OS on Gitlab or Github (or similar service)? Sounds like the memory address of your vbe_info (Segment and Offset) structure that you told Int 10h/04f00h to fill in. Was this a typo?
Quote:
Then I supplied reg.ax with 0xF400,
Did you mean 0x4F00?


Dear Michael.
It was a typo during my message writing.
I put the value 0x004F in reg.ax and not 0x00F4.

I will put it public on my Github and send the link here. But, I used exactly the same function that Napalm distributed and my little OS is supposed not to do anything but draw in SVGA. Therefore, I have a kernel file and a loader file which reserve some stack, provides magic numbers for GRUB, and call the kernel. In the kernel file on the other hand, I would like to call INT 10H with the use of int32 function.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 3:19 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
BenLunt wrote:
iman wrote:
It is now in protected mode and I want to call VESA functionalities.

Does this mean you are executing an INT 10h instruction while in protected mode?

iman wrote:
Then I supplied reg.ax with 0xF400,

As MichaelPetch asked, is this a typo? It should be 0x4F00.

Also as bzt mentioned, you need to give it a signature to tell the BIOS your buffer is big enough to hold the version 2.0 data.

I think your biggest issue is trying to execute an INT 10h instruction while in protected mode. All of this should be done before you move to protected mode.

Ben
- http://www.fysnet.net/osdesign_book_series.htm



BenLunt wrote:
Does this mean you are executing an INT 10h instruction while in protected mode?

Yes. This is where I tried to switch back to the real-mode and trigger INT 10H.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 3:37 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
Here is the link to the Github:

https://github.com/ImAbdollahzadeh/OS

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 8:46 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
It is unclear how your OS in github even compiles or works as expected since you define function int32 to take 2 parameters and you only call it with one. Are you sure your github actually is a workable example.Would also help if your project contained something that had the commands used to compile/linker your files, your linker script etc.


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 9:00 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
MichaelPetch wrote:
It is unclear how your OS in github even compiles or works as expected since you define function int32 to take 2 parameters and you only call it with one. Are you sure your github actually is a workable example.Would also help if your project contained something that had the commands used to compile/linker your files, your linker script etc.


Re-updated.
You can find the working code of mine.
Besides all the commands have been given in their orders as well.

Cheers.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 9:59 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Can you look back at my question and answer the one about function int32 defined as taking 2 parameters but you only pass 1 when you call it from kernel.c?


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 10:01 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 06, 2019 10:41 am
Posts: 84
MichaelPetch wrote:
Can you look back at my question and answer the one about function int32 defined as taking 2 parameters but you only pass 1 when you call it from kernel.c?



It gets two arguments. It was a mistake.
In my Github page, I updated everything. Now the status of the code is exactly what I use on both linux and windows machines that I have.

_________________
Iman Abdollahzadeh
Github
Codeberg


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 11:55 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,

I took a look at your code. There are so many things you should fix first before you try VESA.

1. first of all, you should NEVER use a hosted C compiler for a kernel. Use a cross-compiler, or at least specify "-ffreestanding -nostdlib -nostdinc". ANSI C defines two modes, freestanding and hosted for a reason.
2. why do you copy and relocate a lot on every single int32 call? Why don't you place the regs struct somewhere in memory where both the prot mode and real mode codes can access it directly?
3. your stack is very likely corrupted. Maybe I'm mistaken, but where do you push the segment registers on the stack which you pop at line 71?
4. I'm not sure that pusha struct - regs struct are the same, mostly because of the wild stack handling. It would be much faster to use a couple of mov's instead btw, but if you insist on popa / pusha, then you should set the stack at 7C00 and map that area with the regs struct from your linker script. That way you could directly update the real mode stack (which loads the registers from there with a popa) from your C code simply using the regs struct.
5. maybe it would be useful to take a look how Minix does int86(). It also uses a register structure, and it does not relocate anything (although it relies on a real mode monitor, which is implemented in its boot loader).

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 5:20 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Your VBE structure will have to be below 0x100000 to properly work since BIOS interrupts will have difficulty writing above the 1MiB mark. As it is your VBE structure is on the stack where ESP > 0x100000. Pick a memory location in lower memory (like 0x600) that is above the BIOS Data area and the interrupt vector table. This address can be used for both protected mode and realmode. Your OFF and SEG macros assume realmode FAR pointers. Adjust them so they compute to a normalized segment:offset for physical address < 0x100000. The macros could look like:
Code:
#define SEG(FP) ((uint16_t)(((unsigned long)FP)>>4))
#define OFF(FP) ((uint16_t)(((unsigned long)FP)&0xF))
Your VBE function could look like:
Code:
int VBE( VBE_INFO* vbe )
{
        regs16_t regs;
        regs.ax = 0x4F00;
        regs.es = SEG(vbe);
        regs.di = OFF(vbe);
        int32( 0x10, &regs );
        if ( regs.ax == 0x004F )
                return 1;
        return 0;
}
Your main could look like
Code:
int main( void ) {
        VBE_INFO *vbe = (VBE_INFO *)0x600;
  int res;

        vbe->signature[0] = 'V';
  vbe->signature[1] = 'B';
  vbe->signature[2] = 'E';
  vbe->signature[3] = '2';
        res = VBE( vbe );
        if (res == 1)
        {
                if(vbe->version == 0x0000)         // this is what I get always
                        printk('N');
                else if(vbe->version != 0x0000)
                        printk('Y');
        }
        else
    printk('0');
}

Function int32 assumes that the interrupts were already on prior to being called and turns them on when finished. If you don't have a protected mode IDT set up (or you haven't disabled all the IRQs on the PICs) the code will fault in protected mode when int32 is finished. I've amended the code to only re-enable interrupts if they were already enabled when first called:
Code:
[bits 32]
global int32, _int32
struc regs16_t
        .di     resw 1
        .si     resw 1
        .bp     resw 1
        .sp resw 1
        .bx     resw 1
        .dx     resw 1
        .cx     resw 1
        .ax     resw 1
        .gs     resw 1
        .fs     resw 1
        .es     resw 1
        .ds     resw 1
        .ef resw 1
endstruc

%define INT32_BASE                             0x7C00       ; base BIOS address
%define REBASE(x)                              (((x) - reloc) + INT32_BASE)
%define GDTENTRY(x)                            ((x) << 3)
%define CODE32                                 GDTENTRY(1)      ; 0x08
%define DATA32                                 GDTENTRY(2)      ; 0x10
%define CODE16                                 GDTENTRY(3)      ; 0x18
%define DATA16                                 GDTENTRY(4)      ; 0x20
%define STACK16                                (INT32_BASE - regs16_t_size)

section .text
        int32: use32
        _int32:
        pushf
        pop dword [eflags]                     ; Save the current CPU flags (including IF state)

                cli                                    ; disable interrupts
                pusha                                  ; save register state to 32bit stack
                mov  esi, reloc                        ; set source to code below
                mov  edi, INT32_BASE                   ; set destination to new base address
                mov  ecx, (int32_end - reloc)          ; set copy size to our codes size: LOOK AT THE COMMENT TAGGED WITH %*%
                cld                                    ; clear direction flag (so we copy forward)
                rep  movsb                             ; do the actual copy (relocate code to low 16bit space)
                jmp INT32_BASE                         ; jump to new code location

        reloc: use32                                                                                                                              ; %*% From here on gets copy startting from INT32_BASE
                mov  [REBASE(stack32_ptr)], esp        ; save 32bit stack pointer
                sidt [REBASE(idt32_ptr)]               ; save 32bit idt pointer
                sgdt [REBASE(gdt32_ptr)]               ; save 32bit gdt pointer
                lgdt [REBASE(gdt16_ptr)]               ; load 16bit gdt pointer
                lea  esi, [esp+0x24]                   ; set position of intnum on 32bit stack
                lodsd                                  ; read intnum into eax
                mov  [REBASE(ib)], al                  ; set intrrupt immediate byte from our arguments
                mov  esi, [esi]                        ; read regs pointer in esi as source
                mov  edi, STACK16                      ; set destination to 16bit stack
                mov  ecx, regs16_t_size                ; set copy size to our struct size
                mov  esp, edi                          ; save destination to as 16bit stack offset
                rep  movsb                             ; do the actual copy (32bit stack to 16bit stack)
                jmp  word CODE16:REBASE(p_mode16)      ; switch to 16bit selector (16bit protected mode)
        p_mode16: use16
                mov  ax, DATA16                        ; get our 16bit data selector
                mov  ds, ax                            ; set ds to 16bit selector
                mov  es, ax                            ; set es to 16bit selector
                mov  fs, ax                            ; set fs to 16bit selector
                mov  gs, ax                            ; set gs to 16bit selector
                mov  ss, ax                            ; set ss to 16bit selector

                mov  eax, cr0                          ; get cr0 so we can modify it
                and  al,  ~0x01                        ; mask off PE bit to turn off protected mode
                mov  cr0, eax                          ; set cr0 to result
                jmp  word 0x0000:REBASE(r_mode16)      ; finally set cs:ip to enter real-mode
        r_mode16: use16
                xor  ax, ax                            ; set ax to zero
                mov  ds, ax                            ; set ds so we can access idt16
                mov  ss, ax                            ; set ss so they the stack is valid
                lidt [REBASE(idt16_ptr)]               ; load 16bit idt
                popa                                   ; load general purpose registers from 16bit stack
                pop  gs                                ; load gs from 16bit stack
                pop  fs                                ; load fs from 16bit stack
                pop  es                                ; load es from 16bit stack
                pop  ds                                ; load ds from 16bit stack
                sti                                    ; enable interrupts

                db 0xCD                                ; opcode of INT instruction with immediate byte
        ib: db 0x00

                cli                                    ; disable interrupts
                xor  sp, sp                            ; zero sp so we can reuse it
                mov  ss, sp                            ; set ss so the stack is valid
                mov  sp, INT32_BASE                    ; set correct stack position so we can copy back
                pushf                                  ; save eflags to 16bit stack
                push ds                                ; save ds to 16bit stack
                push es                                ; save es to 16bit stack
                push fs                                ; save fs to 16bit stack
                push gs                                ; save gs to 16bit stack
                pusha                                  ; save general purpose registers to 16bit stack
                mov  eax, cr0                          ; get cr0 so we can modify it
                inc  eax                               ; set PE bit to turn on protected mode
                mov  cr0, eax                          ; set cr0 to result
                jmp  dword CODE32:REBASE(p_mode32)     ; switch to 32bit selector (32bit protected mode)
        p_mode32: use32
                mov  ax, DATA32                        ; get our 32bit data selector
                mov  ds, ax                            ; reset ds selector
                mov  es, ax                            ; reset es selector
                mov  fs, ax                            ; reset fs selector
                mov  gs, ax                            ; reset gs selector
                mov  ss, ax                            ; reset ss selector

                lgdt [REBASE(gdt32_ptr)]               ; restore 32bit gdt pointer
                lidt [REBASE(idt32_ptr)]               ; restore 32bit idt pointer
                mov  esp, [REBASE(stack32_ptr)]        ; restore 32bit stack pointer
                mov  esi, STACK16                      ; set copy source to 16bit stack
                lea  edi, [esp+0x28]                   ; set position of regs pointer on 32bit stack
                mov  edi, [edi]                        ; use regs pointer in edi as copy destination
                mov  ecx, regs16_t_size                ; set copy size to our struct size
                cld                                    ; clear direction flag (so we copy forward)
                rep  movsb                             ; do the actual copy (16bit stack to 32bit stack)
                popa                                   ; restore registers

        test dword [eflags], 1<<9               ; If original interrupt state was on, issue STI
        jz int_off                             ;     otherwise keep interrupts off
        sti
int_off:

                ret                                    ; return to caller

        stack32_ptr:                             ; address in 32bit stack after we
                dd 0x00000000                          ;   save all general purpose registers
        idt32_ptr:                               ; IDT table pointer for 32bit access
                dw 0x0000                              ; table limit (size)
                dd 0x00000000                          ; table base address
        gdt32_ptr:                               ; GDT table pointer for 32bit access
                dw 0x0000                              ; table limit (size)
                dd 0x00000000                          ; table base address
        idt16_ptr:                               ; IDT table pointer for 16bit access
                dw 0x03FF                              ; table limit (size)
                dd 0x00000000                          ; table base address
        gdt16_base:                            ; GDT descriptor table
                .null:                               ; 0x00 - null segment descriptor
                        dd 0x00000000                      ; must be left zero'd
                        dd 0x00000000                      ; must be left zero'd
                .code32:                             ; 0x01 - 32bit code segment descriptor 0xFFFFFFFF
                        dw 0xFFFF                          ; limit  0:15
                        dw 0x0000                          ; base   0:15
                        db 0x00                            ; base  16:23
                        db 0x9A                            ; present, iopl/0, code, execute/read
                        db 0xCF                            ; 4Kbyte granularity, 32bit selector; limit 16:19
                        db 0x00                            ; base  24:31
                .data32:                             ; 0x02 - 32bit data segment descriptor 0xFFFFFFFF
                        dw 0xFFFF                          ; limit  0:15
                        dw 0x0000                          ; base   0:15
                        db 0x00                            ; base  16:23
                        db 0x92                            ; present, iopl/0, data, read/write
                        db 0xCF                            ; 4Kbyte granularity, 32bit selector; limit 16:19
                        db 0x00                            ; base  24:31
                .code16:                               ; 0x03 - 16bit code segment descriptor 0x000FFFFF
                        dw 0xFFFF                          ; limit  0:15
                        dw 0x0000                          ; base   0:15
                        db 0x00                            ; base  16:23
                        db 0x9A                            ; present, iopl/0, code, execute/read
                        db 0x0F                            ; 1Byte granularity, 16bit selector; limit 16:19
                        db 0x00                            ; base  24:31
                .data16:                               ; 0x04 - 16bit data segment descriptor 0x000FFFFF
                        dw 0xFFFF                          ; limit  0:15
                        dw 0x0000                          ; base   0:15
                        db 0x00                            ; base  16:23
                        db 0x92                            ; present, iopl/0, data, read/write
                        db 0x0F                            ; 1Byte granularity, 16bit selector; limit 16:19
                        db 0x00                            ; base  24:31
        gdt16_ptr:                                     ; GDT table pointer for 16bit access
                dw gdt16_ptr - gdt16_base - 1          ; table limit (size)
                dd gdt16_base                          ; table base address
    eflags: dd 0                               ; Storage for EFLAGS (including IF)

        int32_end:                               ; end marker (so we can copy the code)


Last edited by MichaelPetch on Fri Feb 08, 2019 9:13 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: BIOS calls for VESA functionalities
PostPosted: Thu Feb 07, 2019 7:27 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
bzt wrote:
3. your stack is very likely corrupted. Maybe I'm mistaken, but where do you push the segment registers on the stack which you pop at line 71?
.They aren't pushed, but they are copied in from the memory address passed as a regs16_t * to the 16-bit real mode stack with these lines:
Code:
                                                   
      mov  esi, [esi]                        ; read regs pointer in esi as source                                                               
      mov  edi, STACK16                      ; set destination to 16bit stack                                                                   
      mov  ecx, regs16_t_size                ; set copy size to our struct size                                                                 
      mov  esp, edi                          ; save destination to as 16bit stack offset                                                         
      rep  movsb                             ; do the actual copy (32bit stack to 16bit stack)
I will admit the code is rather convoluted (better ways to do it) but this part does seem to work.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Amazonbot [bot], Bing [Bot] and 60 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group