歡迎您光臨本站 註冊首頁

linux內核參數"vga="如何影響顯示模式

←手機掃碼閱讀     火星人 @ 2014-03-26 , reply:0

若不指定「vga=」參數,系統則不支持framebuffer設備,為什麼呢?在內核代碼中是如何實現的?
查看系統啟動日誌kern.log發現,指定「vga= 」比不指定多了一下幾行:

Apr 25 17:14:03 nmr107 kernel: vesafb: framebuffer at 0xd0000000, mapped to 0xe0880000, using 6144k, total 65536k
Apr 25 17:14:03 nmr107 kernel: vesafb: mode is 1024x768x32, linelength=4096, pages=1
Apr 25 17:14:03 nmr107 kernel: vesafb: protected mode interface info at c000:f6d0
Apr 25 17:14:03 nmr107 kernel: vesafb: pmi: set display start = c00cf715, set palette = c00cf79a
Apr 25 17:14:03 nmr107 kernel: vesafb: pmi: ports = b4c3 b503 ba03 c003 c103 c403 c503 c603 c703 c803 c903 cc03 ce03 cf03 d003 d103 d203 d303 d403 d503 da03 ff03
Apr 25 17:14:03 nmr107 kernel: vesafb: scrolling: redraw
Apr 25 17:14:03 nmr107 kernel: vesafb: Truecolor: size=8:8:8:8, shift=24:16:8:0
可以看出這裡設置了vesafb模式

搜索的源代碼,發現在/drivers/video/vesafb.c的函數vesafb_probe中,printk輸出了以上信息
那麼,是哪個函數調用vesafb_probe的呢?繼續找。。發現只有這個與vesafb_probe有關
static struct platform_driver vesafb_driver = {
.probe = vesafb_probe,
.driver = {
.name = "vesafb",
},
};
很明顯,必定有哪個地方通過 「->probe」 調用vesafb_probe。搜索關鍵詞「->probe」 ,竟然只有幾個,都不相關。改搜「>probe」,這一次還不少。去掉一些明顯不可能的(如 pci,usb下的),找到最有可能的 driver_probe_device函數(/drivers/base/Dd.c文件中)。照此思路,依次找到__driver_attach(調用driver_probe_device),driver_attach(調用__driver_attach)
bus_add_driver(調用driver_attach),driver_register(調用bus_add_driver),platform_driver_register(調用driver_register),vesafb_init(調用platform_driver_register),最後module_init(vesafb_init)
而通過module_init指定的函數,會在do_initcalls中調用 接著do_basic_setup(調用
do_initcalls),init(調用do_basic_setup)。至此,終於弄明白vesafb_probe的被調用過程。

哪沒有輸出vesafb信息,是在那一步中斷的呢?逐步跟蹤,終於眼前一亮:
if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
return -ENODEV;
據我所知,screen_info是與「vga=」參數有密切關係的!查看VIDEO_TYPE_VLFB定義
#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
正是想要的。

進一步驗證,screen_info的元素orig_video_isVGA位於距起點「0x0f」處。繼續往回找,
有screen_info = SCREEN_INFO;

#define PARAM (boot_params)
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
在/arch/i386/kernel/head.s文件中找到這麼一段
/*
* Copy bootup parameters out of the way.
* Note: %esi still has the pointer to the real-mode data.
* With the kexec as boot loader, parameter segment might be loaded beyond
* kernel image and might not even be addressable by early boot page tables.
* (kexec on panic case). Hence copy out the parameters before initializing
* page tables.
*/
movl $(boot_params - __PAGE_OFFSET),%edi
movl $(PARAM_SIZE/4),%ecx
cld
rep
movsl
註釋意思說,將啟動參數拷貝到boot_params指向的地方。在vedio.s中,有相關代碼處理vesa驅動。
mopar_gr:
leaw modelist+1024, %di
movb $0x23, %fs:(PARAM_HAVE_VGA)
。。。。。。
而PARAM_HAVE_VGA定義為
#define PARAM_HAVE_VGA 0x0f

這裡說明一點,「vga=」參數由grub處理,處理結果放在內核文件vmlinuz的頭部的vidmode處。
linux啟動開始,讀取該值
movw %fs:(0x01fa), %ax # User selected video mode
cmpw $ASK_VGA, %ax # Bring up the menu
jz vid2
call mode_set # Set the mode
這裡%fs:(0x01fa)就是引用內核映像中vidmode處
內核頭部在bootsect.s中能看到
.org 497
setup_sects: .byte SETUPSECTS
root_flags: .word ROOT_RDONLY
syssize: .word SYSSIZE
swap_dev: .word SWAP_DEV
ram_size: .word RAMDISK
vid_mode: .word SVGA_MODE
root_dev: .word ROOT_DEV
boot_flag: .word 0xAA55

總結:寫了這麼多,估計沒幾個人能看懂或看完。不過,我只當是記錄一下讀核的一點艱辛過程。
內核代碼的閱讀,要花費很多的精力,翻看成千上萬行代碼,不停的跟蹤函數調用過程。這時候,
要有一定的技巧,更要有耐心。

[火星人 ] linux內核參數"vga="如何影響顯示模式已經有551次圍觀

http://coctec.com/docs/linux/show-post-188615.html