BIOS VESA扩展:video-modes缓冲指向一个空数组

huangapple go评论68阅读模式
英文:

BIOS VESA-extensions: video-modes buffer pointing to an empty array

问题

我获取了基本的VESA信息块,使用INT 10h / AX=4F00h

    PUSH cs                             ;
    POP es                              ;
    ;- 执行VESA检查               ;
    PUSH es                             ; 一些BIOS在这个调用中破坏ES
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI 缓冲区至少需要256字节(VBE v2.0+需要512字节)
    MOV ax, 04F00H                      ;
    INT 10H                             ;
    POP es                              ;
                                        ;
    ;- 检查错误                 ;
    CALL DRV_VESA_bioscallErrorCheck    ;
                                        ;
    ;-- 检查缓冲区签名          ;
    PUSH CS                             ;
    POP ES                              ;
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI = 缓冲区
    MOV cx, 4                           ;
    MAC_IMMSTRING "VESA"                ; DS:SI = "VESA" 签名需要匹配!
    REPZ CMPSB                          ;
    JZ @@noErrors                       ;
    MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
    DRV_VESA_panic                      ;
                                        ;
    ;-- 检查VESA版本              ;
    MOV ax, CS:[DRV_VESA_infoBlock].version
    CMP ax, 00102H                      ;
    JGE @@noErrors                      ;
    MAC_DPT_PRINTIMM "VESA: version too low"
    DRV_VESA_panic                      ;
@@noErrors:                             ;
...
...
...
                                        ;
    ALIGN DWORD                         ; 一些BIOS可能需要对齐结构体
    DRV_VESA_infoBlock DRV_VESA_VBE_INFO_STRUCT  {}
    ALIGN DWORD                         ;
    DRV_VESA_modeInfo DRV_VESA_VBE_MODE_INFO_STRUCT {}

然后,我获取了视频模式缓冲区的指针。

    ;-- 获取VESA模式缓冲区地址   ;
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesOff
    MOV si, ax
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesSeg
    PUSH ax                             ;
    POP fs                              ;

然后(作为初步步骤),我打印出我拥有的所有视频模式。

@@displayModeLoop:                      ;
    MOV cx, WORD PTR fs:[si]            ;
    CMP cx, 0FFFFH                      ;
    JE @@displayModeEndLoop             ;
    MOV ax, cx                          ;
    CALL DPT_printNum                   ;
    ;--- 获取模式信息           ;
    MOV ax, 04F01H                      ;
    INT 10H                             ;
    CALL DRV_VESA_bioscallErrorCheck    ;

    ADD si, 2                           ;
    JMP @@displayModeLoop               ;
@@displayModeEndLoop:                   ;   
  • DPT_printNum 在这里很可能没有问题(它在许多其他地方都有效)。

  • 我已经尝试过删除BIOS函数调用,它不是导致问题的原因。

  • 我仍然在RMODE中。

  • 我正在使用自己的引导加载程序。

相关文件位于此处:https://github.com/Wittmaxi/maxos/tree/master/kernel/drivers/graphics

当我运行这段代码(无论是在QEMU还是在DOSBox中),会打印出许多空数组索引。一旦打印出第一个非零值,内核就会崩溃。我预期该数组应该(如在http://www.ctyme.com/intr/rb-0273.htm中指定)充满了显示模式代码,并以单词"FFFF"结束。

英文:

I get the basic VESA information block with INT 10h / AX=4F00h.

    PUSH cs                             ;
    POP es                              ;
    ;- perform VESA check               ;
    PUSH es                             ; some BIOSes destroy ES with this call
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI buffer for at least 256 bytes (512 for VBE v2.0+)
    MOV ax, 04F00H                      ;
    INT 10H                             ;
    POP es                              ;
                                        ;
    ;- check for errors                 ;
    CALL DRV_VESA_bioscallErrorCheck    ;
                                        ;
    ;-- check buffer signature          ;
    PUSH CS                             ;
    POP ES                              ;
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI = buffer
    MOV cx, 4                           ;
    MAC_IMMSTRING "VESA"                ; DS:SI = "VESA" signature needs to match!
    REPZ CMPSB                          ;
    JZ @@noErrors                       ;
    MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
    DRV_VESA_panic                      ;
                                        ;
    ;-- check vesa version              ;
    MOV ax, CS:[DRV_VESA_infoBlock].version
    CMP ax, 00102H                      ;
    JGE @@noErrors                      ;
    MAC_DPT_PRINTIMM "VESA: version too low"
    DRV_VESA_panic                      ;
@@noErrors:                             ;
...
...
...
                                        ;
    ALIGN DWORD                         ; some bioses might require the structs to be aligned
    DRV_VESA_infoBlock DRV_VESA_VBE_INFO_STRUCT  {}
    ALIGN DWORD                         ;
    DRV_VESA_modeInfo DRV_VESA_VBE_MODE_INFO_STRUCT {}

I then get the pointer to the video-modes buffer

    ;-- get vesa modes buffer address   ;
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesOff
    MOV si, ax
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesSeg
    PUSH ax                             ;
    POP fs                              ;
                                        ;   

I then (as preliminary step) print out all the video modes I have

@@displayModeLoop:                      ;
    MOV cx, WORD PTR fs:[si]            ;
    CMP cx, 0FFFFH                      ;
    JE @@displayModeEndLoop             ;
    MOV ax, cx                          ;
    CALL DPT_printNum                   ;
    ;--- get mode information           ;
    MOV ax, 04F01H                      ;
    INT 10H                             ;
    CALL DRV_VESA_bioscallErrorCheck    ;

    ADD si, 2                           ;
    JMP @@displayModeLoop               ;
@@displayModeEndLoop:                   ;   
  • DPT_printNum is most certainly not at fault here (it worked in many other places)

  • I already tried removing the BIOS-function-call, it is not what causes the issue

  • I am still in RMODE

  • I am using my own bootloader

The relevant files are here: https://github.com/Wittmaxi/maxos/tree/master/kernel/drivers/graphics

When I run this code (both in QEMU and in DOSBox), a lot of empty array indexes are printed. As soon as the first non-zero value is printed, the kernel panics.
BIOS VESA扩展:video-modes缓冲指向一个空数组
I expect the array to be (as specified <http://www.ctyme.com/intr/rb-0273.htm>) full of display-mode-codes and ended with the word "FFFF"

答案1

得分: 2

>     MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesOff
>     MOV si, ax
>     MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesSeg
>     PUSH ax
>     POP fs

错误地从 DS 相对于 VideoModePtr 检索 VbeInfoBlock,实际上应该相对于 CS,甚至 ES,因为你复制了 CS 到 ES。

;-- 检查缓冲区标识          ;
PUSH CS                    ;
POP ES                     ;
MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI = 缓冲区
MOV cx, 4                  ;
MAC_IMMSTRING "VESA"       ; DS:SI = "VESA" 标识需要匹配!
REPZ CMPSB                 ;
JZ @@sigMatch              ;
MAC_DPT_PRINTIMM "VESA 缓冲区:标识不匹配!"
DRV_VESA_panic            ;

@@sigMatch:                ;
;-- 检查 VESA 版本          ;
MOV ax, ES:[DRV_VESA_infoBlock].version
CMP ax, 00102H             ;
JGE @@versionOk            ;
MAC_DPT_PRINTIMM "VESA: 版本太低"
DRV_VESA_panic            ;

@@versionOk:               ;
;-- 获取 VESA 模式缓冲区地址   ;
MOV si, ES:[DRV_VESA_infoBlock].modesOff
MOV fs, ES:[DRV_VESA_infoBlock].modesSeg

我在 ModeInfoBlock 中找到了一个额外的问题。你没有包括偏移量 29 处的 NumberOfImagePages 字段。

英文:

> MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesOff
> MOV si, ax
> MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesSeg
> PUSH ax
> POP fs

You are erroneously retrieving the VideoModePtr relative to DS where in fact the VbeInfoBlock was placed in the code segment, so relative to CS, or even ES since you copied CS to ES.

;-- check buffer signature          ;
PUSH CS                             ;
POP ES                              ;
MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI = buffer
MOV cx, 4                           ;
MAC_IMMSTRING &quot;VESA&quot;                ; DS:SI = &quot;VESA&quot; signature needs to match!
REPZ CMPSB                          ;
JZ @@sigMatch                       ;
MAC_DPT_PRINTIMM &quot;VESA buffer: signature does not match!&quot;
DRV_VESA_panic                      ;
                                    ;
@@sigMatch:                         ;
;-- check vesa version              ;
MOV ax, ES:[DRV_VESA_infoBlock].version
CMP ax, 00102H                      ;
JGE @@versionOk                     ;
MAC_DPT_PRINTIMM &quot;VESA: version to low&quot;
DRV_VESA_panic                      ;
                                    ;
@@versionOk:                        ;
;-- get vesa modes buffer address   ;
MOV si, ES:[DRV_VESA_infoBlock].modesOff
MOV fs, ES:[DRV_VESA_infoBlock].modesSeg

I have found an additional problem in your ModeInfoBlock. You did not include the NumberOfImagePages field at offset 29.

答案2

得分: 0

在哪里设置BX用于 ;-- 获取VESA模式缓冲区地址
;--- 获取模式信息 需要 ES:DI 指向一个 DRV_VESA_VBE_MODE_INFO_STRUCT

英文:

Where do you set up BX for ;-- get vesa modes buffer address?<br>
;--- get mode information requires ES:DI pointing to a DRV_VESA_VBE_MODE_INFO_STRUCT

huangapple
  • 本文由 发表于 2023年2月8日 19:39:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75385252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定