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

105 Views Asked by At

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. enter image description here 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"

2

There are 2 best solutions below

0
sinsi On

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

0
Sep Roland On
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 "VESA"                ; DS:SI = "VESA" signature needs to match!
REPZ CMPSB                          ;
JZ @@sigMatch                       ;
MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
DRV_VESA_panic                      ;
                                    ;
@@sigMatch:                         ;
;-- check vesa version              ;
MOV ax, ES:[DRV_VESA_infoBlock].version
CMP ax, 00102H                      ;
JGE @@versionOk                     ;
MAC_DPT_PRINTIMM "VESA: version to low"
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.