Search code examples
assemblybootloaderbochsvesa

VESA not working on BOCHS


I have written a simple bootloader which sets the video mode, and puts some pixels. I have tested it on Virtual box, QEMU, Dosbox and real hardware. Works great on them but not on Bochs. Mode sets correctly but pixels are not plotted.

 org 0x7c00

[BITS 16]           ;Tell Assembler to generate 16-bit code

jmp short start         ;Goto start, skip BIOS-Parameter-Block
nop             

;------------BIOS Parameter Block---------------;
;         Needed to recognize the disk      ;
;-----------------------------------------------;
OEMName:        db 'TEST OS '   ;Name of Orignal Equipment Manufacturer
bytesPerSector:     dw 512      ;Number of bytes in each sector
sectPerCluster:     db 1        ;Sectors in one cluster, 1 for FAT12
reservedCluster:    dw 1        ;1 sector is reserved for boot
totalFATs:      db 2        ;There are 2 fats in FAT12 these are copies of each other
rootDirEntries:     dw 224      ;Total entries (files or folders) in root directory
totalSectors:       dw 2880     ;Total Sectors in whole disk
mediaType:      db 0xf0     ;Media type 240 for floppies
sectorsPerFAT:      dw 9        ;Sectors used in on FAT
sectorsPerTrack:    dw 18       ;Sectors in one Track
totalHeads:     dw 2        ;Total sides of disk
hiddenSectors:      dd 0        
hugeSectors:        dd 0
driveNumber:        db 0        ;Drive Number 0 for A:\ floppy
            db 0
signature:      db 41       ;41 for floppies
volumeID:       dd 0        ;Any number
volumeLabel:        db 'TEST OS    ';Any 11-char name
fileSystem:     db 'FAT12   '   ;Type of file system on disk
;------------------------------------------------


;_______________________________________________

gdt:    dd 0x00000000,0x00000000 ;null descriptor
    dd 0x0000ffff,0x00cf9a00 ;code
    dd 0x0000ffff,0x00cf9200

gdtreg: dw 0x17          ;gdt size + 1
    dd 0             ;gdt base (latter filled)

start:
mov ax,0x4f01 ;get vesa mode info
mov cx,0115h ;video mode number
mov di,modeblock
int 0x10
mov esi, [modeblock+0x28] ;save linear frame buffer base = es:di+0x28

mov ax,0x4f02 ;set vesa mode
mov bx,0115h ;video mode number
int 0x10

mov ax,0x2401
int 0x15    ;enable a20 gate

xor eax,eax
mov ax,cs   
shl eax,4
mov [gdt+0x08+2],ax
shr eax,16
mov [gdt+0x20+4],al


xor eax,eax
mov ax,cs
shl eax,4
add eax,gdt
mov [gdtreg+2],eax
lgdt[gdtreg]

mov eax,cr0
or eax,1

cli
mov cr0,eax
jmp 0x08:pstart

[bits 32]
pstart:
mov eax,0x10
mov es,ax
mov ds,ax
mov fs,ax
mov ss,ax
mov gs,ax


cls:
mov eax,0xffffffff
mov edi, esi
mov ecx,1024*768*1/2
cld
rep stosd

;************ THIS PART IS NOT WORKING ON BOCHS. ************
main:
;test code
mov edi,esi 

mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0xff
inc edi
mov byte[edi],0x00
inc edi

mov byte[edi],0x00
inc edi
mov byte[edi],0xff
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi

mov byte[edi],0xff
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi  

mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0xff
inc edi
mov byte[edi],0x00
inc edi

mov byte[edi],0x00
inc edi
mov byte[edi],0xff
inc edi
mov byte[edi],0x00
inc edi
mov byte[edi],0x00
inc edi

jmp $

times 510-($-$$) db 0
dw 0xaa55

modeblock:

Any suggestions? Thanks.


Solution

  • In order to get linear framebuffer, you need to ask for it by setting bit #14 in BX register for the 4F02 function. Bochs seems to be picky about this and silently ignores writes if you haven't enabled the linear framebuffer:

    if (BX_VGA_THIS vbe.lfb_enabled)
    {
    ...
    }
    else
    {
        if (addr < BX_VGA_THIS vbe.base_address) {
          // banked mode write
          offset = (Bit32u)(BX_VGA_THIS vbe.bank*65536 + (addr - 0xA0000));
        }
        else {
          // LFB write while in banked mode -> ignore
          return;
        }
    

    Also note that you should not hardcode mode numbers because they may be different on different systems. It's unclear what mode you want to set, bochs thinks 0x115 is 800x600x24, but your code has 1024*768*1/2 which hints that's not what you expected.