Page 1 of 1

grub vbeset : put pixel bad result

Posted: Sat Aug 29, 2009 2:36 pm
by SamyPesse
Hello everybody ;)
when i want to use vesa video mode, i let grub set the mode for me with stage2_eltorino and vbeset :

Code: Select all

default=0
timeout=30
	title=MyOS : free and Open Source OS
	kernel /kernel.bin -disk 0 -part 0 -init C:/sys/bin/shell -b
	vbeset 771
	boot
i get :
http://myos.redby.fr/image/vbe.png

normally with vga12h mode, i get :
http://myos.redby.fr/image/novbe.png

this my code for vesa and grub, :
I dont know where is the probleme !!

Code: Select all


static int lfb_px = 0;

static int lfb_py = 0;



static ULONG lfb_width  = 0;

static ULONG lfb_height = 0;

static ULONG lfb_depth  = 0;

static ULONG lfb_type 	= 0;



void lfb_clear()

{

	memset((char*)lfb,15,lfb_width*lfb_height*lfb_depth);

}




void init_lfb(struct multiboot_info *multiboot )

{

	struct vbe_mode *mode_info;

	void *lfb_ptr;



	lfb_px = 0;

	lfb_py = 0;



	if ( (multiboot->flags & (1<<11)) == 0 )

	{

	    lfb_width  = 0;

	    lfb_height = 0;

	    lfb_depth = 0;

	    lfb_type = 0;

	    lfb_ptr = 0;

		printk("\n Video mode : VGA 12h\n");

	}

	else

	{

		setVideoMode(MODEVBE);

	    mode_info = (struct vbe_mode*) multiboot->vbe_mode_info;

	    lfb_width  = mode_info->x_resolution;

	    lfb_height = mode_info->y_resolution;

	    lfb_depth = mode_info->bits_per_pixel;

	    lfb_type = 0;

	    lfb_ptr = (void*)mode_info->phys_base;

		lfb = (unsigned char*)lfb_ptr;

		printk("\n Video mode : VESA grub\n");

	}

	

//	set_lfb( lfb_width, lfb_height, lfb_depth, lfb_type, lfb_ptr );

}



#define PIXEL_POINTEUR(x,y) ((char*)(lfb+x \

 +((unsigned short int)y*(unsigned short int)lfb_width)))



void putpixel_vbe(ULONG x, ULONG y, ULONG col) {

	*PIXEL_POINTEUR(x,y)=(char)col;

}
and the vbe mode struct :

Code: Select all


/* VBE mode information.  */

struct vbe_mode

{

  unsigned short mode_attributes;

  unsigned char win_a_attributes;

  unsigned char win_b_attributes;

  unsigned short win_granularity;

  unsigned short win_size;

  unsigned short win_a_segment;

  unsigned short win_b_segment;

  unsigned long win_func;

  unsigned short bytes_per_scanline;



  /* >=1.2 */

  unsigned short x_resolution;

  unsigned short y_resolution;

  unsigned char x_char_size;

  unsigned char y_char_size;

  unsigned char number_of_planes;

  unsigned char bits_per_pixel;

  unsigned char number_of_banks;

  unsigned char memory_model;

  unsigned char bank_size;

  unsigned char number_of_image_pages;

  unsigned char reserved0;



  /* direct color */

  unsigned char red_mask_size;

  unsigned char red_field_position;

  unsigned char green_mask_size;

  unsigned char green_field_position;

  unsigned char blue_mask_size;

  unsigned char blue_field_position;

  unsigned char reserved_mask_size;

  unsigned char reserved_field_position;

  unsigned char direct_color_mode_info;



  /* >=2.0 */

  unsigned long phys_base;

  unsigned long reserved1;

  unsigned short reversed2;



  /* >=3.0 */

  unsigned short linear_bytes_per_scanline;

  unsigned char banked_number_of_image_pages;

  unsigned char linear_number_of_image_pages;

  unsigned char linear_red_mask_size;

  unsigned char linear_red_field_position;

  unsigned char linear_green_mask_size;

  unsigned char linear_green_field_position;

  unsigned char linear_blue_mask_size;

  unsigned char linear_blue_field_position;

  unsigned char linear_reserved_mask_size;

  unsigned char linear_reserved_field_position;

  unsigned long max_pixel_clock;



  unsigned char reserved3[189];

} __attribute__ ((packed));


Re: grub vbeset : put pixel bad result

Posted: Sat Aug 29, 2009 4:07 pm
by Combuster
For starters, your code is not taking care of various bit depths.

Also, what is the exact mode you are setting?

Re: grub vbeset : put pixel bad result

Posted: Sun Aug 30, 2009 2:03 am
by SamyPesse
i want to use the mode : 792 (1024x728 and 24 bits per pixel)

Re: grub vbeset : put pixel bad result

Posted: Sun Aug 30, 2009 3:20 am
by xyzzy
The VBE mode number for that mode is 280 (0x118), not 792. I'd guess you got that number from Linux - IIRC its mode numbers are <VESA mode number> + 0x200, which would give what you're using.

Re: grub vbeset : put pixel bad result

Posted: Sun Aug 30, 2009 3:34 am
by SamyPesse
euh the mode 792 give me the correct result with qemu : a windows of 1024x728

Re: grub vbeset : put pixel bad result

Posted: Sun Aug 30, 2009 12:20 pm
by Brendan
Hi,
SamyPesse wrote:i want to use the mode : 792 (1024x728 and 24 bits per pixel)
Some video cards don't support 24 bits per pixel at all, some video cards don't support 1024*768 at all, and some do support "1024*768 * 24-bpp" but don't support VBE. AFAIK in all of these cases, GRUB will fail to set "1024*768 * 24-bpp" and will leave you in text mode.

If the video card does support "1024*768 * 24-bpp", there's no guarantee that the monitor will support it. In this case GRUB will set the video mode but the user won't be able to see anything on the screen after that (and some ancient "VGA only" video cards will blow up).

IMHO there's only 3 sane choices:
  • Use a video mode that every video card and monitor supports (e.g. 640 * 480 * 4 bits per pixel, or text mode)
  • Force the end-user to tell GRUB which video mode to use, so that they can use a video mode that their hardware actually does support. IMHO this idea isn't very user-friendly. For example, if you're using the "mode_type", "width", "height" and "depth" fields in the multi-boot header, then the end user needs to create a customized version of your kernel before using it (which is a pain in the neck for end-users). It also doesn't work in some situations (e.g. a live CD where the person who makes the CD doesn't know which computers it'll be booted on). It also means that the OS has to support every possible video mode (including strange/rare video modes), because it has no control over which video mode the user might select.
  • Switch back to real mode, then create a list of video modes that the video card and OS (and monitor?) do support, then choose a video mode from this list during boot. In this case GRUB's video support isn't used at all (and your OS doesn't require a special patched GRUB, which means people who are already using an unpatched GRUB to boot an existing OS can continue using the version of GRUB they've already installed to dual boot their existing OS and your OS). In this case, the OS could automatically choose any video mode, and could let the user set preferences (e.g. with a pretty menu system or with kernel parameters) where the OS searches the list of usable video modes and finds the video mode that most closely matches the requested resolution and colour depth (and refresh rate?). Unfortunately this is complex and GRUB just makes things worse. For example, you'd need to copy some code below 0x00100000 (as you can't run real mode code above 0x00100000), and you'd need to make sure you don't trash anything that could be the area below 0x00100000 (e.g. the multiboot information data structure).
Mostly, the video support in GRUB (or more correctly, the multi-boot specification) isn't adequate...

It does make me wonder how GRUB 2 will handle video though. Ideally, the multi-boot header should contain a complete description of which video modes the OS does/doesn't support (possibly including ranges - e.g. "this OS supports all video modes from 640 * 480 to 1600 * 1200, but not resolutions that are outside this range, and not any 4-bit per pixel video modes"); so that GRUB 2 can create a list of video modes that the video card and OS (and monitor?) do support and choose a video mode for the OS intelligently (including taking user preferences into account). In addition, the boot loader should display an error message if no suitable video mode is found, rather than using text mode as a fallback (so that an OS that requires graphics mode doesn't have to support text mode). Unfortunately, as far as I can tell GRUB 2 is intending to use the original multi-boot specification, so it won't be any better at mis-handling video... :)


Cheers,

Brendan