VBE info and putpixel()

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
gumbosoup
Posts: 11
Joined: Tue Aug 26, 2014 5:13 pm

VBE info and putpixel()

Post by gumbosoup »

Hi,
So I booted my OS into text mode using GRUB2 and printed the vbe info it gave me to the screen.
vbe.png
vbe.png (127.64 KiB) Viewed 4027 times
I'm guessing the 80x25 resolution is because I am in text mode, which hopefully would explain why the bpp, pitch, and physbase are 0.

The multiboot header in my bootstrap for this was

Code: Select all

.set ALIGN,    1<<0             # align loaded modules on page boundaries
.set MEMINFO,  1<<1             # provide memory map
.set FLAGS,    ALIGN | MEMINFO  # this is the Multiboot 'flag' field
.set MAGIC,    0x1BADB002       # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot

.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
So I attempted to get the VBE info in graphics mode, but since I don't have the vbe info already, I don't have a way to reliably make pixels appear on the screen.
I made putpixel() that attempts to account for several possible bpps. This would idealy put one whiteish pixel on the screen at x = 0 and y = 0.

The multiboot stuff from the bootstrap this time was

Code: Select all

.set ALIGN,    1<<0             
.set MEMINFO,  1<<1             
.set VIDINFO,  1<<2
.set FLAGS,    ALIGN | MEMINFO | VIDINFO 
.set MAGIC,    0x1BADB002       
.set CHECKSUM, -(MAGIC + FLAGS) 


.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.long 0, 0, 0, 0, 0  # Maybe changing these numbers haphazardly will make it work?
.long 0              # or these?
.long 1024, 768, 32  # Maybe I should add ranch dressing? Ranch makes everything better. This is known.
and my putpixel() was

Code: Select all

void putpixel(uint16_t x, uint16_t y, uint32_t* physbase, uint16_t pitch, uint8_t bpp)
{
	int loc = (x * bpp) + (y * pitch);
	
	if(bpp == 32 || ((bpp/8) == 31) || ((bpp/8 == 32))){
		physbase[loc] = 255;
		physbase[loc + 1] = 255;
		physbase[loc + 2] = 255;
		physbase[loc + 3] = 255;
	}
	else if(bpp == 24 || ((bpp/8) == 24))
	{
		physbase[loc] = 255;
		physbase[loc + 1] = 255;
		physbase[loc + 2] = 255;
	}
	else if(bpp == 16 || ((bpp/8) == 16))
		physbase[loc] = 127 << 8 | 255;
	else if(bpp ==15 || ((bpp/8) == 15))
		physbase[loc] = 255 << 8 | 255;
}
I also tried not checking for bpp/8 but that also ended in a black screen.

I'm hoping the problem is in the multiboot header or the putpixel function.
Am I not accounting for enough cases for bpp?
Do I need to cast the physbase as a certain type before I pass it into putpixel()?
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: VBE info and putpixel()

Post by jnc100 »

If you're in text mode then grub2 doesn't call the various bios functions to get the mode so the rest of the structure will indeed be 0. The contents of the vbe_control_info and vbe_mode_info members of the tag are exact copies of whatever the relevant bios interrupt returns.

If you don't have the ability to write to screen, but still want to return some debugging information about whether you're interpreting the structure correctly, you could always write it to the serial port, or port e9 if using bochs.

Regards,
John.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: VBE info and putpixel()

Post by Brendan »

Hi,

Some notes:
  • BPP stands for "bits per pixel", and is mostly likely to be 1, 2, 4, 8, 15, 16, 24 or 32. It is not "bytes per pixel" (so "if(bpp*8 == 32)" wouldn't make sense) and it's definitely not "eights of a bit per pixel" so "if(bpp/8 == 32)" is even less sane.
  • For C, if you have a pointer to 32-bit value/s (e.g. "uint32_t* physbase") then an expression like "foo = physbase[123]" is equivalent to "foo = (uint32_t *) ( (void *)phybase + 123*sizeof(uint32_t) )". For the 24-bpp and 32-bpp cases, you've written it for "uint8_t* physbase" (and not "uint32_t* physbase" which you're actually using) and for those cases it's incorrect. For the 15-bpp and 16-bpp cases, you've written it for "uint16_t* physbase" (and not "uint32_t* physbase" which you're actually using) and for those cases it's incorrect.
  • For 15-bpp one bit may be reserved, and for 32-bpp 8 bits may be reserved. The reserved bits are often used in a "vendor specific" way to implement non-standard features (e.g. alternative "bits to colour" conversions, overlays, etc). For this reason you should not set these reserved bits and need to ensure they are zeros.
  • Knowing "bits per pixel" is not enough. You also need to know how those bits effect the colour. There are 2 important things in VBE's "mode info" structure that you must also check. The first is the "MemoryMode" field, to determine if it's a planar mode, a mode that uses a lookup table/palette to determine colour, a "direct colour" mode, or if it's a YUV mode (that doesn't use "reg, green and blue" at all). The second (for "direct colour" modes) is the entire set of "redMask", "redPosition", "greenMask", "greenPosition", "blueMask" and "bluePosition" fields. These tell you which bits are used for red, green and blue (e.g. and if it's "RGB" or "BGR", etc).
  • If you ask for (e.g.) a "1024*768, 32-bpp" mode and the computer's VBE doesn't support that mode; then (according to the multi-boot specification) the boot loader is free to do anything it feels like without caring; including giving you text mode, or some strange/unusual graphics mode like "512 * 512, 4-bpp planar"; even if a similar 1024*768, 24-bpp" mode is supported.
  • If you ask for (e.g.) a "1024*768, 32-bpp" mode and the computer's VBE does support that mode, then the boot loader will (should) switch to that mode for you; but there's is no guarantee that the monitor supports the video mode and it may still be entirely unusable.
  • If a tornado is ripping apart your house it'd be a bad idea to ignore it and pretend everything is fine. In the same way, if the boot loader has set a video mode that your OS doesn't support it's a bad idea to ignore it and pretend everything is fine. When video initialisation has failed, there are a variety of ways you could use to inform the user that your OS is unable to boot (e.g. flash keyboard LEDs, make the PC speaker beep, etc). Note: The best option would be to just return a "boot aborted" status (or even better, an ASCIIZ string saying why you can't boot) to the boot loader; but sadly multiboot doesn't support sensible things.
However; despite all of the bugs, it's likely that you would've still got some messed up pixels at the top left of the screen (e.g. maybe a blue pixel, a green pixel then a red pixel, rather than one white pixel). If this didn't happen, then it may also mean that there's an additional problem somewhere (that isn't in the list above).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Peterbjornx
Member
Member
Posts: 116
Joined: Thu May 06, 2010 4:34 am
Libera.chat IRC: peterbjornx
Location: Leiden, The Netherlands
Contact:

Re: VBE info and putpixel()

Post by Peterbjornx »

I would recommend testing in an emulator and using a serial debug console, (QEMU can dump that to stdio using "-serial stdio")
gumbosoup
Posts: 11
Joined: Tue Aug 26, 2014 5:13 pm

Re: VBE info and putpixel()

Post by gumbosoup »

Thanks. I was ignoring some important information with that putpixel(). I got it to work, but only when I boot with BIOS GRUB2.
EFI GRUB2 still just boots into a black screen, which leads me to believe my OS is not compatible with EFI. I guess I have some reading to do on that subject.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VBE info and putpixel()

Post by Combuster »

You can fortunately debug EFI booting with Bochs' integrated debugger. You just need to configure a different bios. After that, you can launch GRUB2 with your OS inside of it and check the response.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
gumbosoup
Posts: 11
Joined: Tue Aug 26, 2014 5:13 pm

Re: VBE info and putpixel()

Post by gumbosoup »

Alrighty, I narrowed down the issue a little bit.
Apparently, good old VBE is just not acceptable in UEFI, and the new thing GOP.
videoinfo gives the following information:

Code: Select all

Adapter 'EFI GOP Driver' :
Legend: mask/position = red/green/blue/reserved
*0x000 1920x1080x32 (7680) Direct color, mask: 8/8/8/8 pos: 16/8/0/24
 0x000 640x480x32 (2560) Direct color, mask: 8/8/8/8 pos: 16/8/0/24
 0x000 1024x768x32 (4096) Direct color, mask: 8/8/8/8 pos: 16/8/0/24
 0x000 1920x1080x32 (3200) Direct color, mask: 8/8/8/8 pos: 16/8/0/24
The "1024x768x32 (4096) Direct color, mask: 8/8/8/8 pos: 16/8/0/24" appeared as one of the many options when I entered
vbeinfo in BIOS GRUB2. Booting with BIOS GRUB2, it works. Booting with EFI GRUB2, it now puts a few weird coloured pixels in odd locations.

Is there a GOP info structure that has the stuff I need to make a working putpixel() like with VBE? If there was, that would make an excellent wiki page.
Post Reply