Configuring Linux Kernel Video Mode for 32-bit and 16-bit Boot Protocols

The Linux kernel has a generic driver for a graphic framebuffer named vesafb on intel boxes. It provides a nice large console for most of modern displays.

Setting VESA modes for Linux kernel with 32-bit and 16-bit boot protocol are different. We introduce both methods here.

Linux kernel with 32-bit boot protocol

For machine with some new BIOS other than legacy BIOS, such as EFI, LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel based on legacy BIOS can not be used, so a 32-bit boot protocol needs to be defined.

– from THE LINUX/x86 BOOT PROTOCOL

The modes can be set by adding ‘video=…’ to the kernel boot parameter.

The syntax is like this (ref: Kernel Mode-setting):

video=<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]

For Grub2, this can be added by 2 steps.

Edit ‘/dev/default/grub’ and edit the line for ‘GRUB_CMDLINE_LINUX’. For example, to set the video mode to 1024×800 with 32-bit color depth:

GRUB_CMDLINE_LINUX="rd.md=0 rd.lvm=0 rd.dm=0 KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 video=1024x800-32"

Then make the new grub.cfg by:

# grub2-mkconfig -o /boot/grub2/grub.cfg

Bonus: Setting Grub2′s video mode also by the Grub2 configuration file as follows.

Add to ‘/dev/default/grub’:

GRUB_GFXMODE=1024x800x32
GRUB_GFXPAYLOAD_LINUX=keep
GRUB_TERMINAL=gfxterm

Then, make the new grub.cfg by

# grub2-mkconfig -o /boot/grub2/grub.cfg

Linux kernel with 16-bit boot protocol

Switching VESA modes of Linux kernel at boot time can be done by using the “vga=… kernel boot parameter. This parameter accept the decimal value of Linux video mode numbers instead of VESA video mode numbers. The Linux video mode number can be easily derived from the VESA number.

The video mode number of the Linux kernel is the VESA mode number plus 0×200.

Linux_kernel_mode_number = VESA_mode_number + 0x200

Here are some of the VESA mode numbers:

    | 640x480  800x600  1024x768 1280x1024
----+-------------------------------------
256 |  0x101    0x103    0x105    0x107
32k |  0x110    0x113    0x116    0x119
64k |  0x111    0x114    0x117    0x11A
16M |  0x112    0x115    0x118    0x11B

So the table for the Kernel mode numbers are:

    | 640x480  800x600  1024x768 1280x1024
----+-------------------------------------
256 |  0x301    0x303    0x305    0x307
32k |  0x310    0x313    0x316    0x319
64k |  0x311    0x314    0x317    0x31A
16M |  0x312    0x315    0x318    0x31B

The decimal value of the Linux kernel video mode number can be passed to the kernel in the form “vga=YYY“, where YYY is the decimal value.

Instead of the YYY decimal value, the “vga” parameter also accept “ask” which will list all the Linux kernel mode numbers and let the user select one. You can used it if you want to be asked every time booting Linux. It can also be used to find the best Linux video mode on your console.

The best way for configuring the “vga=YYY” parameter is following these steps.

First, add “vga=ask” parameter to the Linux kernel entry in grub configuration file /boot/grub/grub.conf. Like this:

kernel /vmlinuz-2.6.32.16-141.fc12.i686 ro root=/dev/mapper/VolGroup-LogVol00 vga=ask 

Second, reboot Linux and hit return when the kernel ask for the vga mode. Then select one mode from the list and remember the Linux mode number which is a hexdecimal value in the format YYY. You can also get more choice by entering “scan“.

Last, calculate the decimal value of the Linux video mode number. This simple python command can be used:

python -c "print 0xYYY"

YYY is the hexdecimal value you got.

Then change “ask” in grub configuration file to the decimal value calculated.

Here is a list of usually used Linux mode number and the decimal value if you like to choose one directly:


320×200640×400640×480800×500800×600896×6721024×6401024×7681280×1024
4 bits 770 (302) 774 (306)
8 bits 768 (300)769 (301)879 (36F)701 (303)815 (32F)874 (36A)773 (305)775 (307)
15 bits781 (30D)801 (321)784 (310)880 (370)787 (313)816 (330)875 (36B)790 (316)793 (319)
16 bits782 (30E)802 (322)785 (311)881 (371)788 (314)817 (331)876 (36C)791 (317)794 (31A)
24 bits783 (30F)803 (323)786 (312)882 (372)789 (315)818 (332)877 (36D)792 (318)795 (31B)
32 bits 804 (324)809 (329)883 (373)814 (32E)819 (333)878 (36E)824 (338)829 (33D)

About Eric Zhiqiang Ma

Eric Zhiqiang Ma is a PhD candidate at Dep. of CSE, HKUST. He is interested in system software for cloud computing, virtualization of large-scale distributed systems and etc. Also find Eric on Facebook, Twitter, LinkedIn and Google+. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties. More Posts - Website

0 thoughts on “Configuring Linux Kernel Video Mode for 32-bit and 16-bit Boot Protocols”

  1. Thanks for the quick response.
    I found where to list vga parameter in /etc/default/drub file in order to pass it to the kernel. Should be added here:
    GRUB_CMDLINE_LINUX=”rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap rhgb quiet vga=789″
    and after generating grub.conf it is listed in the linux section:
    …..
    linux /vmlinuz-3.5.2-1.fc17.i686.PAE root=/dev/mapper/vg_dvr-lv_root ro rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap rhgb quiet vga=789
    …..
    But there is still no effect on the display resolution during splash screen and log in screen. vga=ask option is not available in this kernel version, CPU does not boot with it. Could be vga parameter is ignored by the kernel?

    One remark: vbainfo command from grub menu gave me:
    800x600x24 0×115 + 0×200 = 0×315 ~ 789(d)
    800x600x32 0×124 + 0×200 = 0×324 ~ 804(d)
    In the table above You list 0x32E ~ 814(d) – can it be different?

      1. I am afraid I have no good news. I have been fiddling for 3 days without any result. Final grub file I ended with is:
        GRUB_TIMEOUT=5
        GRUB_DISTRIBUTOR=”Fedora”
        GRUB_DEFAULT=saved
        GRUB_CMDLINE_LINUX=”rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap gfxpayload=true radeon.modeset=1″
        GRUB_GFXMODE=800×600
        GRUB_GFXPAYLOAD_LINUX=keep
        GRUB_PRELOAD_MODULES=”vbe”
        GRUB_VIDEO_BACKEND=vbe
        and the resolution after grub screen is still 1024*768. After switching off graphical boot I noticed that booting starts in 800*600 mode and at some phase switches to 1024*768 mode leaving me headless until automatic user log on is completed.
        I find no way to tell the kernel to boot in my resolution. I will file a bug report and give it up.

        1. What about changing the GRUB_CMDLINE_LINUX to

          GRUB_CMDLINE_LINUX=”rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap gfxpayload=keep gfxmode=800x600  radeon.modeset=1″
        2. Hi Andrew,

          After some searching and testing on my own PC, I finally find out the way. The key is to set the video modes by adding ‘video=…’ to the kernel boot parameters. I have updated the post. Please check and try.

    1. Dear Zhiqiang, I do not know where You dug out this info, but it works! Following Your advice for 32-bit boot protocole I am able to go through the whole boot process with the desired resolution. In the middle of the boot the display is refreshed with the video=….. mode. With me it is 800×600-32
      A couple of glitches:
      - just before autologin for the first user completes for a few seconds the display switches again to shows mouse pointer with 1024*768 resolution.
      - switch user screen between users is shown also with 1024*768 resolution (it should have been 800*600); log out screen resolution is correct.
      I found out that there is /boot/grub/grub.conf besides /boot/grub2/grub.conf with the old content before the last generation. I will update this config file and test a few reboots.
      Thanks for the help!

        1. I cannot tell if it this resolution is for X server or Linux video, sorry, I am more of a user rather than software specialist.
          Trying to set my desired resolution I have made a test file /etc/X11/xorg.conf.d/00-display with the following content:
          Section “Monitor”
          Identifier “Monitor0″
          Modeline “800x600_60.00″ 38.25 800 832 912 1024 600 603 607 624 -hsync +vsync
          Option “PreferredMode” “800x600_60.00″
          EndSection

          Section “Device”
          Identifier “Device0″
          Driver “nouveau”
          EndSection

          Section “Screen”
          Identifier “Screen0″
          Device “Device0″
          Monitor “Monitor0″
          DefaultDepth 24
          SubSection “Display”
          Depth 24
          Modes “1024×768″ “800×600″
          EndSubSection
          EndSection
          Now it is not active. Looking at it, I guess I should change the driver to “radeon”. And this will probably set X server resolution.
          I have also tried adding in /etc/gdm/Init/Default:
          xrandr –output VGA-0 –mode 800×600 –rate 60
          Is this Linux video tuning? When I am logged to the F17 computer (which is installed as a router in the basement at home and which I am using as a testground before I implement anything in the servers at work) with NX machine, the –output default is the correct parameter.

  2. Thanks for the explanation. I find it very useful but I cannot implement vga=YYY on Fedora17 using grub2. grub.conf file is a script, adding vga=YYY to /etc/defaults/grub has no effect (could be expected as such option is not listed in grub2 manual). The Fedora17 install manual http://docs.fedoraproject.org/en-US/Fedora/17/html/Installation_Guide/s2-trouble-ram.html is also irrelevant as 10_linux file contains just script commands and no similar to linux /vmlinuz-(2.6.32.130.el6.i686 ro root=UUID=04a07c13-e6bf-6d5a-b207-002689545705 line where vga=YYY can be added.
    Could You give a tip how to pass the required resolution from grub2 to kernel?
    My problem is that during F17 install I used a display with high resolution and now, after replacing it with an old 800×600 display, the splash screen and user log in/switch user screens have 1024/768 resolution and cannot be viewed properly. Changing display resolution for the users is OK once they log in, but they cannot type name & PW . . .
    For some reason the kernel does not detect and change the correct max resolution of the display and continues to use 1024×768. I need to force it to 800×600 resolution.

      1. Thanks for the quick response.
        I found where to list vga parameter in /etc/default/drub file in order to pass it to the kernel. Should be added here:
        GRUB_CMDLINE_LINUX=”rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap rhgb quiet vga=789″
        and after generating grub.conf it is listed in the linux section:
        …..
        linux /vmlinuz-3.5.2-1.fc17.i686.PAE root=/dev/mapper/vg_dvr-lv_root ro rd.md=0 rd.dm=0 SYSFONT=True rd.lvm.lv=vg_dvr/lv_root KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rd.lvm.lv=vg_dvr/lv_swap rhgb quiet vga=789
        …..
        But there is still no effect on the display resolution during splash screen and log in screen. vga=ask option is not available in this kernel version, CPU does not boot with it. Could be vga parameter is ignored by the kernel?

        One remark: vbainfo command from grub menu gave me:
        800x600x24 0×115 + 0×200 = 0×315 ~ 789(d)
        800x600x32 0×124 + 0×200 = 0×324 ~ 804(d)
        In the table above You list 0x32E ~ 814(d) – can it be different?

Leave a Reply

Your email address will not be published. Required fields are marked *

− 2 = one

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Click to subscribe to Fclose.com Posts by Email if you have not.