Changes between Version 3 and Version 4 of jazz/jfbterm


Ignore:
Timestamp:
Jan 15, 2009, 10:02:37 AM (15 years ago)
Author:
jazz
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • jazz/jfbterm

    v3 v4  
    298298                die("cannot mmap(mmio)");
    299299}}}
     300
     301== BUGFIX: jfbterm (4) ==
     302
     303 * [wiki:jazz/09-01-4 09-01-14@GMT+8 原紀錄 BUGFIX: jfbterm (3)]
     304
     305 * 在看 fbcommon.c 時,發現在這組出現錯誤的 mmap 前曾跑過另一組 mmap, 因此把參數印出來對照看看。
     306 * gdb debug 程序
     307{{{
     308file jfbterm
     309set args -e ls
     310show args
     311break fbcommon.c:500
     312break fbcommon.c:557
     313break fbcommon.c:566
     314run
     315p fb_fix
     316c
     317p fb_fix
     318c
     319p fb_fix.smem_len
     320p p->soff
     321p p->slen
     322p fb_fix.mmio_len
     323p p->moff
     324p p->mlen
     325}}}
     326{{{
     327root@intrepid:~/jfbterm-0.4.7-dev# gdb
     328GNU gdb 6.8-debian
     329Copyright (C) 2008 Free Software Foundation, Inc.
     330License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
     331This is free software: you are free to change and redistribute it.
     332There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
     333and "show warranty" for details.
     334This GDB was configured as "x86_64-linux-gnu".
     335(gdb) file jfbterm
     336Reading symbols from /root/jfbterm-0.4.7-dev/jfbterm...done.
     337(gdb) set args -e ls
     338(gdb) show args
     339Argument list to give program being debugged when it is started is "-e ls".
     340(gdb) break fbcommon.c:500
     341Breakpoint 1 at 0x40303d: file fbcommon.c, line 500.
     342(gdb) break fbcommon.c:557
     343Breakpoint 2 at 0x40327e: file fbcommon.c, line 557.
     344(gdb) break fbcommon.c:566
     345Breakpoint 3 at 0x403301: file fbcommon.c, line 566.
     346(gdb) run
     347Starting program: /root/jfbterm-0.4.7-dev/jfbterm -e ls
     348...略...
     349Breakpoint 1, tfbm_open (p=0x6146e0) at fbcommon.c:501
     350501             if (fb_var.yres_virtual != fb_var.yres) {
     351(gdb) p fb_fix
     352$1 = {id = "▒\204▒▒Q\177\000\000\006\000\000\000\000\000\000", smem_start = 21037808,
     353  smem_len = 4269392626, type = 32593, type_aux = 0, visual = 0,
     354  xpanstep = 65535, ypanstep = 65535, ywrapstep = 65535, line_length = 1, mmio_start = 15,
     355  mmio_len = 21076240, accel = 0, reserved = {53071, 64, 0}}
     356(gdb) c
     357Continuing.
     358...略...
     359Breakpoint 2, tfbm_open (p=0x6146e0) at fbcommon.c:557
     360557             p->smem = (u_char*)mmap(NULL, p->slen, PROT_READ|PROT_WRITE,
     361(gdb) p fb_fix
     362$2 = {id = "VESA VGA\000\000\000\000\000\000\000", smem_start = 4026531840,
     363  smem_len = 1572864, type = 0, type_aux = 0, visual = 3, xpanstep = 0,
     364  ypanstep = 0, ywrapstep = 0, line_length = 1024, mmio_start = 0,
     365  mmio_len = 0, accel = 0, reserved = {0, 0, 0}}
     366(gdb) c
     367Continuing.
     368
     369Breakpoint 3, tfbm_open (p=0x6146e0) at fbcommon.c:566
     370566             if(p->mlen == 0)
     371(gdb) p fb_fix.smem_len
     372$3 = 1572864
     373(gdb) p p->soff
     374$4 = 0
     375(gdb) p p->slen
     376$5 = 1572864
     377(gdb) p fb_fix.mmio_len
     378$6 = 0
     379(gdb) p p->moff
     380$7 = 0
     381(gdb) p p->mlen
     382$8 = 0
     383}}}
     384|| fb_fix.smem_len = 1572864 || p->soff = 0 || p->slen = 1572864 || mmap 成功 ||
     385|| fb_fix.mmio_len = 0       || p->moff = 0 || p->mlen = 0       || mmap 失敗 (因為 length = 0) ||
     386 * 從數據看起來,無論是從 SSH 登入,或在本機 tty 使用,所得到的 fb_fix.mmio_len = 0 是主要原因。只是 mmio 所代表的意涵,fbcommon.h 程式碼並無註解。
     387 * 繼續往 fb_fix.mmio_len 的源頭追,是 tfbm_get_fix_screen_info 函式去更新 fb_fix 這個結構。資料是透過 ioctl 去詢問核心中對應的 FBIOGET_FSCREENINFO。
     388{{{
     389<fbcommon.c>
     390
     391509         tfbm_get_fix_screen_info(p->fh, &fb_fix);
     392
     393244 static void tfbm_get_fix_screen_info(int fh, struct fb_fix_screeninfo *fix)
     394245 {
     395246         if (ioctl(fh, FBIOGET_FSCREENINFO, fix)) {
     396247                 print_strerror_and_exit("ioctl FBIOGET_FSCREENINFO");
     397248         }
     398249 }
     399}}}
     400 * [http://lxr.linux.no/linux+v2.6.11/drivers/video/fbmem.c#L804 定義在 Kernel 2.6.11/drivers/video/fbmem.c 中 FBIOGET_FSCREENINFO 的 ioctl handler]
     401{{{
     402 804        case FBIOGET_FSCREENINFO:
     403 805                return copy_to_user(argp, &info->fix,
     404 806                                    sizeof(fix)) ? -EFAULT : 0;
     405}}}
     406 * [http://lxr.linux.no/linux+v2.6.27.7/drivers/video/fbmem.c#L1247 定義在 Kernel 2.6.27/drivers/video/fbmem.c 中 FBIOGET_FSCREENINFO 的 ioctl handler]
     407{{{
     4081247        case FBIOGET_FSCREENINFO:
     4091248                ret = fb_get_fscreeninfo(inode, file, cmd, arg);
     4101249                break;
     411}}}
     412   * fb_get_fscreeninfo 會呼叫 fb_ioctl 並以 cmd = FBIOGET_FSCREENINFO 去處理,看起來最後執行的程式碼是跟 2.6.11 一樣。
     413{{{
     4141013 static int
     4151014 fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     4161015          unsigned long arg)
     417
     4181018        struct fb_info *info = registered_fb[fbidx];
     419
     4201046        case FBIOGET_FSCREENINFO:
     4211047                return copy_to_user(argp, &info->fix,
     4221048                                    sizeof(fix)) ? -EFAULT : 0;
     423}}}
     424 * 從 fb.h 的定義,我們可以確定 mmio_len 是從 info (型態為 fb_info) 結構中抓出 fb_fix_screeninfo 型態的 fix 回傳給使用者。
     425{{{
     426<linux-2.6.27.7/include/linux/fb.h>
     427
     428 152 struct fb_fix_screeninfo {
     429
     430 156        __u32 smem_len;                 /* Length of frame buffer mem */
     431
     432 164        unsigned long mmio_start;       /* Start of Memory Mapped I/O   */
     433 165                                        /* (physical address) */
     434 166        __u32 mmio_len;                 /* Length of Memory Mapped I/O  */
     435
     436 808 struct fb_info {
     437
     438 811        struct fb_var_screeninfo var;   /* Current var */
     439 812        struct fb_fix_screeninfo fix;   /* Current fix */
     440}}}
     441 * 目前懷疑是 uvesafb 攔截了 FBIOGET_FSCREENINFO 的 ioctl 並回傳了不正確的 fb_fix_screeninfo 內容。因此先來寫一個測試程式,透過  FBIOGET_FSCREENINFO 的 ioctl 把  fb_fix_screeninfo 內容取出來。
     442   * [參考] http://www.harlan.idv.tw/Computer/EmbeddedLinux/Chapter4.htm