Page 1 of 2
using vesa mode
Posted: Sun May 06, 2012 1:30 pm
by ParaDarkness
I'm trying to access video memory in a vesa mode...
I switch to graphic mode in real mode (before switch to protected mode) with this code :
Code: Select all
[BITS 16]
VesaInfo db 'VBE2'
times 252 db 0
ModeInfo times 256 db 0
FrameBuffer dd 0
;VesaInfo
VesaInfos :
SinV db "VESA"
VE1 db 0
VE2 db 0
PtrFARAscii dd 0
Perf dd 0
PtrFARLst dd 0
NbrChunks dw 0
Buffer times 236 db 0
Mode_Info:
ModeInfo_ModeAttributes dw 1
ModeInfo_WinAAttributes db 1
ModeInfo_WinBAttributes db 1
ModeInfo_WinGranularity dw 1
ModeInfo_WinSize dw 1
ModeInfo_WinASegment dw 1
ModeInfo_WinBSegment dw 1
ModeInfo_WinFuncPtr dd 1
ModeInfo_BytesPerScanLine dw 1
ModeInfo_XResolution dw 1
ModeInfo_YResolution dw 1
ModeInfo_XCharSize db 1
ModeInfo_YCharSize db 1
ModeInfo_NumberOfPlanes db 1
ModeInfo_BitsPerPixel db 1
ModeInfo_NumberOfBanks db 1
ModeInfo_MemoryModel db 1
ModeInfo_BankSize db 1
ModeInfo_NumberOfImagePages db 1
ModeInfo_Reserved_page db 1
ModeInfo_RedMaskSize db 1
ModeInfo_RedMaskPos db 1
ModeInfo_GreenMaskSize db 1
ModeInfo_GreenMaskPos db 1
ModeInfo_BlueMaskSize db 1
ModeInfo_BlueMaskPos db 1
ModeInfo_ReservedMaskSize db 1
ModeInfo_ReservedMaskPos db 1
ModeInfo_DirectColorModeInfo db 1
; VBE 2.0 extensions
ModeInfo_PhysBasePtr dd 1
ModeInfo_OffScreenMemOffset dd 1
ModeInfo_OffScreenMemSize dw 1
mov di, VesaInfos
mov ax, 4F00h
int 10h
mov ax, 4F01h
mov di, Mode_Info
mov cx, 4112h
int 10h
mov ax, 4F02h
mov bx, 4118h
int 10h
I'm not sure that the modeInfo and vesaInfo work and i don't know how can i read the framebuffer address in the mode info block but if I try to write in 0xA0000 in protected mode with this code :
Code: Select all
unsigned long *video;
uDD pix;
long int i = 0;
while (i < 1024*768*4) {
video = (unsigned long *) (0xA0000 + i);
pix = 0x7FDD4C;
*video = pix;
i = i + 3;
}
I have this result :
- result
I would like to know how I can write in all memory (with lfb? how can I activate it?) and hiw can I read the modeInfo block?
Sorry for my English
, (I speak french)
Re: using vesa mode
Posted: Sun May 06, 2012 2:00 pm
by Milan
Try this code:
Code: Select all
mov edi,[ModeInfo_PhysBasePtr]
mov ecx,640*480
mov al,0xff
rep stosb
and there is put_pixel function in c
Code: Select all
void vesa_put_pixel(uint32_t x, uint32_t y, uint32_t cl)
{
register char *ptmp;
if (x < 0 || x > vmi->width || y < 0 || y > vmi->height) return;
x = (x * (vmi->bits_per_pixel >> 3));
y = (y * vmi->bytes_per_scan_line);
char *asd = (char *)vmi->phys_base_ptr;
ptmp = &asd[x+y];
ptmp[0] = cl & 0xff;
ptmp[1] = (cl>>8) & 0xff;
ptmp[2] = (cl>>16) & 0xff;
}
Re: using vesa mode
Posted: Sun May 06, 2012 2:10 pm
by ParaDarkness
What do the first code? :s
It puts 255 in ModeInfo_PhysBasePtr 640*480 Times?
Re: using vesa mode
Posted: Sun May 06, 2012 5:19 pm
by DavidCooper
Have you got the proper documentation on it?
http://www.jnode.org/uploads/vbe3_0.pdf
If so, the answers are in there. On page 31:-
Mandatory information for VBE 2.0 and above
PhysBaseptr dd ? ; physical address for flat memory frame buffer
It's a while since I wrote my VESA code, but I think from memory that that's where you find the linear framebuffer address. Unfortunately the offsets aren't stated, so you need to count it out to find out where this appears in the table - it looks from my code as if it's 40 bytes in (that's a decimal distance), and it's a direct 32-bit physical address.
Re: using vesa mode
Posted: Mon May 07, 2012 9:18 am
by ParaDarkness
There is my problem!
I know that the adress is the 40th byte in the table but i don't know how can I get the adress of the table after switching in protected mode (in C or with "asm()" function in english?
Have you an example code that makes this thing?
Thanks for your link
Re: using vesa mode
Posted: Mon May 07, 2012 11:09 am
by Milan
In protected mode you can't use real mode interruprs...
Only way to do that is to use grub to get address of lfb or you can implement
http://wiki.osdev.org/Virtual_Monitor and then you can use bios interrupts...
Re: using vesa mode
Posted: Mon May 07, 2012 11:33 am
by ParaDarkness
what is the easiest way :
Implement the virtual mode or switch to graphic mode in pmode? (I don't want to use grub)
thanks again
Re: using vesa mode
Posted: Mon May 07, 2012 11:54 am
by Milan
Implement Virtual Monitor if you want to have bios interrupts in protected mode...
With this you can switch to graphic mode and from graphic to text mode, read disk etc.
But implementing the Virtual Monitor can be very hard...
I see you have successfully switched to graphic mode.
You must choose graphic or text mode if you don't have possibility to use interrupts im pm.
Re: using vesa mode
Posted: Mon May 07, 2012 12:44 pm
by ParaDarkness
I did'nt need bios interrupts in protected mode, I don't want to switch between graphic or text mode multiple times.
I just want to find the lfb in pm, I can't believe that it is not possible.
I use this code to change to pm after switching to graphic mode (in asm):
Code: Select all
mov di, VesaInfos
mov ax, 4F00h
int 10h
mov ax, 4F01h
mov di, Mode_Info
mov cx, 4112h
int 10h
mov ax, 4F02h
mov bx, 4118h
int 10h
; pmode
cli
mov eax, cr0
or ax, 1
mov cr0, eax
jmp next
next:
mov ax, 0x10
mov ds, ax
mov fs, ax
mov gs, ax
mov es, ax
mov ss, ax
mov esp, 0x9F000
jmp dword 0x8:_next ; reinitialise le segment de code
[BITS 32]
_next:
and the main kernel in C :
Code: Select all
int main(void)
{
//Kernel content ...
//and the test to put pixels
unsigned long *video;
uDD pix;
long int i = 0;
while (i < 1024*768*4) {
video = (unsigned long *) (0xA0000 + i);
pix = 0x7FDD4C;
*video = pix;
i = i + 3;
}
Isn't it possible to get the address with arguments in main function? or with a descriptor in gdt?
And I have another question : Even if I have activate the lfb, why I still can use 0xA0000 to put pixels to screen? isn't it different address?
Re: using vesa mode
Posted: Mon May 07, 2012 12:46 pm
by Griwes
ParaDarkness wrote:Isn't it possible to get the address with arguments in main function? or with a descriptor in gdt?
You really need to read about calling conventions.
Re: using vesa mode
Posted: Mon May 07, 2012 12:58 pm
by ParaDarkness
can you explain my error? :s
Re: using vesa mode
Posted: Mon May 07, 2012 12:59 pm
by bluemoon
ParaDarkness wrote:Isn't it possible to get the address with arguments in main function?
Yes. At least two usual way:
1. Pass information block with predefined absolute address, then you access it with
Code: Select all
BOOTDATA* boot = (BOOTDATA*)(0x1234); // replace this with your choice of address, make sure it's safe to use
2. Pass on stack/registers, check your ABI reference.
On the other hand, you may query the LFB address in pm with PCI configuration space if that is an PCI card, I assume it's on BAR#0.
ParaDarkness wrote:And I have another question : Even if I have activate the lfb, why I still can use 0xA0000 to put pixels to screen? isn't it different address?
Most card support one mode at a time. when activated LFB, A000 is not used. One exception is qemu(and probably other emu) it will handle both interface at the same time.
Re: using vesa mode
Posted: Mon May 07, 2012 1:41 pm
by DavidCooper
ParaDarkness wrote:I just want to find the lfb in pm, I can't believe that it is not possible.
Why not just collect it the easy way while you're still in real mode? All you need to do is add a little code after calling the Mode Info function:-
mov di, VesaInfos
mov ax, 4F00h
int 10h
mov ax, 4F01h
mov di, Mode_Info
mov cx, 4112h
int 10h
; Add some code in here to read the address in the table and store
; it somewhere where you can find it later once in protected mode.
; (or make sure you don't overwrite the table so that you can read it
; later on while in protected mode)
mov ax, 4F02h
mov bx, 4118h
int 10h
As it stands, you're calling the Mode Info function for nothing - you aren't doing anything with the table which it returns to you at ES:DI, the 40th to 43rd bytes of which you ought to be collecting as it's the linear framebuffer address. It looks as if you've just hacked code out of a tutorial without understanding it, or maybe more than one tutorial, because your next step appears to be to set a different mode from the one you just asked for information about. Your code is also dangerous as you aren't checking to see if the mode is actually available, so it could potentially blow up a monitor which doesn't support it.
Re: using vesa mode
Posted: Tue May 08, 2012 12:46 am
by Combuster
bluemoon wrote:ParaDarkness wrote:And I have another question : Even if I have activate the lfb, why I still can use 0xA0000 to put pixels to screen? isn't it different address?
Most card support one mode at a time. when activated LFB, A000 is not used. One exception is qemu(and probably other emu) it will handle both interface at the same time.
Actually, from most of the live hardware I've seen the LFB can work simultaneously with the legacy window. Specifically, the lfb always works and the legacy addresses can be turned off - something the bios might happen to do or not.
Relying on any of that behaviour for VBE is obviously bad practice, but it's a useful thing when it comes to custom drivers
Re: using vesa mode
Posted: Tue May 08, 2012 10:54 am
by DavidCooper
A few more hints:-
mov di, VesaInfos
mov ax, 4F00h
int 10h
; You've just asked the BIOS for a list of available modes, and by exploring the table at
; ES:DI you can find the address to read them from. Next step should be to call the
; function below for each mode in the list of available modes and to look for the one(s)
; that you want to use. Some of the modes in the list may not actually be valid, so you
; need to check carefully the results you get back from the function below.
mov ax, 4F01h
mov di, Mode_Info
mov cx, 4112h
int 10h
; CX should contain a mode number as found in the list of screen modes returned by the
; previous function - you don't need the 4 in your 4112h at this point as it's only added
; when setting a mode with the function below, its purpose being to set it to use the
; linear framebuffer.
mov ax, 4F02h
mov bx, 4118h
int 10h
Read the VESA documentation carefully and only call functions when you actually understand why you're calling them.