Why does my OS not boot when I try to access 0xE0000000?

155 Views Asked by At

To implement a linear framebuffer, I wanted to use the pre-registered VBE LFB, at address 0xE0000000. Note that I am using Bochs 2.7, Assembly using NASM, and C using GCC.

I am using a regular char pointer to attempt to point at the address:

char* m = (char*)VIDEO_ADDRESS; //0xE0000000

Though when calling char* m to draw pixels, the OS wouldn't boot - it would be stuck trying in a flashing sequence until it finally gave an error stating

[BXVGA ]
update: select_high_bank != 1

which was when it terminated. This is the code for my display settings in my assembly bootloader (found on a Stack Overflow post):

mov ax, 4F02h ; set vbe mode
mov bx, 118h ; mode 1024*768*24
or bx, 0100000000000000b ; set bit 14th (use LFB)
int 10h

EDIT: I have four files: boot.asm, loader.asm, kernel.asm, and main.c. Here they are, for a complete reproducible example.

boot.asm:

[BITS 16]
[ORG 0x7c00]

start:
    xor ax,ax   
    mov ds,ax
    mov es,ax  
    mov ss,ax
    mov sp,0x7c00

TestDiskExtension:
    mov [DriveId],dl
    mov ah,0x41
    mov bx,0x55aa
    int 0x13
    jc NotSupport
    cmp bx,0xaa55
    jne NotSupport

LoadLoader:
    mov si,ReadPacket
    mov word[si],0x10
    mov word[si+2],5
    mov word[si+4],0x7e00
    mov word[si+6],0
    mov dword[si+8],1
    mov dword[si+0xc],0
    mov dl,[DriveId]
    mov ah,0x42
    int 0x13
    jc  ReadError

    mov dl,[DriveId]
    jmp 0x7e00 

ReadError:
NotSupport:
    mov ah,0x13
    mov al,1
    mov bx,0xa
    xor dx,dx
    mov bp,Message
    mov cx,MessageLen 
    int 0x10

End:
    hlt    
    jmp End
    
DriveId:    db 0
Message:    db "We have an error in boot process"
MessageLen: equ $-Message
ReadPacket: times 16 db 0

times (0x1be-($-$$)) db 0

    db 80h
    db 0,2,0
    db 0f0h
    db 0ffh,0ffh,0ffh
    dd 1
    dd (20*16*63-1)
    
    times (16*3) db 0

    db 0x55
    db 0xaa

loader.asm:

[BITS 16]
[ORG 0x7e00]

start:
    mov [DriveId],dl

    mov eax,0x80000000
    cpuid
    cmp eax,0x80000001
    jb NotSupport

    mov eax,0x80000001
    cpuid
    test edx,(1<<29)
    jz NotSupport
    test edx,(1<<26)
    jz NotSupport

LoadKernel:
    mov si,ReadPacket
    mov word[si],0x10
    mov word[si+2],100
    mov word[si+4],0
    mov word[si+6],0x1000
    mov dword[si+8],6
    mov dword[si+0xc],0
    mov dl,[DriveId]
    mov ah,0x42
    int 0x13
    jc  ReadError

GetMemInfoStart:
    mov eax,0xe820
    mov edx,0x534d4150
    mov ecx,20
    mov edi,0x9000
    xor ebx,ebx
    int 0x15
    jc NotSupport

GetMemInfo:
    add edi,20
    mov eax,0xe820
    mov edx,0x534d4150
    mov ecx,20
    int 0x15
    jc GetMemDone

    test ebx,ebx
    jnz GetMemInfo

GetMemDone:
TestA20:
    mov ax,0xffff
    mov es,ax
    mov word[ds:0x7c00],0xa200
    cmp word[es:0x7c10],0xa200
    jne SetA20LineDone
    mov word[0x7c00],0xb200
    cmp word[es:0x7c10],0xb200
    je End
    

SetA20LineDone:
    xor ax,ax
    mov es,ax

SetVideoMode:
    ;mov ax,4f02h ;set vesa 1.0 screen mode
    ;mov bx,81feh ; FOR 800X600 THIS SHOULD BE "103h", for 1024x768 it should be "105h"
    ;int 10h
    ;mov ax,3
    ;int 0x10
    
    mov ax, 4F02h ; set vbe mode

    mov bx, 118h ; mode 1024*768*24

    or bx, 0100000000000000b ; set bit 14th (use LFB)

    int 10h
    
    ;mov ax, 13h
    ;int 10h
    
    mov ah,2
    mov dl,7
    int 21h
    
    cli
    lgdt [Gdt32Ptr]
    lidt [Idt32Ptr]

    mov eax,cr0
    or eax,1
    mov cr0,eax

    jmp 8:PMEntry

ReadError:
NotSupport:
End:
    hlt
    jmp End


[BITS 32]
PMEntry:
    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov esp,0x7c00

    cld
    mov edi,0x70000
    xor eax,eax
    mov ecx,0x10000/4
    rep stosd
    
    mov dword[0x70000],0x71007
    mov dword[0x71000],10000111b


    lgdt [Gdt64Ptr]

    mov eax,cr4
    or eax,(1<<5)
    mov cr4,eax

    mov eax,0x70000
    mov cr3,eax

    mov ecx,0xc0000080
    rdmsr
    or eax,(1<<8)
    wrmsr

    mov eax,cr0
    or eax,(1<<31)
    mov cr0,eax

    jmp 8:LMEntry

PEnd:
    hlt
    jmp PEnd

[BITS 64]
LMEntry:
    mov rsp,0x7c00

    cld
    mov rdi,0x200000
    mov rsi,0x10000
    mov rcx,51200/8
    rep movsq

    jmp 0x200000
    
LEnd:
    hlt
    jmp LEnd
    
    

DriveId:    db 0
ReadPacket: times 16 db 0

Gdt32:
    dq 0
Code32:
    dw 0xffff
    dw 0
    db 0
    db 0x9a
    db 0xcf
    db 0
Data32:
    dw 0xffff
    dw 0
    db 0
    db 0x92
    db 0xcf
    db 0
    
Gdt32Len: equ $-Gdt32

Gdt32Ptr: dw Gdt32Len-1
          dd Gdt32

Idt32Ptr: dw 0
          dd 0


Gdt64:
    dq 0
    dq 0x0020980000000000

Gdt64Len: equ $-Gdt64


Gdt64Ptr: dw Gdt64Len-1
          dd Gdt64

kernel.asm:

section .data

Gdt64:
    dq 0
    dq 0x0020980000000000
    dq 0x0020f80000000000
    dq 0x0000f20000000000
TssDesc:
    dw TssLen-1
    dw 0
    db 0
    db 0x89
    db 0
    db 0
    dq 0

Gdt64Len: equ $-Gdt64

Gdt64Ptr: dw Gdt64Len-1
          dq Gdt64

Tss:
    dd 0
    dq 0x190000
    times 88 db 0
    dd TssLen

TssLen: equ $-Tss

section .text
extern KMain
global start

start:
    lgdt [Gdt64Ptr]

SetTss:
    mov rax,Tss
    mov [TssDesc+2],ax
    shr rax,16
    mov [TssDesc+4],al
    shr rax,8
    mov [TssDesc+7],al
    shr rax,8
    mov [TssDesc+8],eax
    mov ax,0x20
    ltr ax

InitPIT:
    mov al,(1<<2)|(3<<4)
    out 0x43,al

    mov ax,11931
    out 0x40,al
    mov al,ah
    out 0x40,al

InitPIC:
    mov al,0x11
    out 0x20,al
    out 0xa0,al

    mov al,32
    out 0x21,al
    mov al,40
    out 0xa1,al

    mov al,4
    out 0x21,al
    mov al,2
    out 0xa1,al

    mov al,1
    out 0x21,al
    out 0xa1,al

    mov al,11111110b
    out 0x21,al
    mov al,11111111b
    out 0xa1,al

    push 8
    push KernelEntry
    db 0x48
    retf

KernelEntry:
    mov rsp,0x200000
    call KMain

End:
    hlt
    jmp End

main.c:

#include <string.h>
#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1024
#define VIDEO_ADDRESS 0xe0000000
#define VBE_DISPI_ID5 0xB0C5

void pixel8bit(int x, int y, int color)
{
    long *v = (long*)VIDEO_ADDRESS;
    int offset = ((y * SCREEN_WIDTH) + x);
    v[offset] = color;
}

void pixel(int x, int y, int color)
{
    long *v = (long*)VIDEO_ADDRESS;
    int offset = ((y * SCREEN_WIDTH) + x) * 3;
    v[offset] = color;
}

void line(int x, int y, int length, int color)
{
    for(int i = 0; i < length; i++)
    {
        pixel(x+i, y, color);
    }
}

void vLine(int x, int y, int length, int color)
{
    for(int i = 0; i < length; i++)
    {
        pixel(x, y+i, color);
    }
}

void box(int x, int y, int l, int w, int color)
{
    char* v = (char*)VIDEO_ADDRESS;
    line(x,y,l,color);
    vLine(x,y,w,color);
    line(x,y+w-1,l,color);
    vLine(x+l-1,y,w,color);
}

void fillScreen(int color)
{
    char* v = (char*)VIDEO_ADDRESS;
    for(int i = 0; i < SCREEN_WIDTH*SCREEN_HEIGHT; i++) {
        v[i] = color;
    }
}

void coloredBars()
{
    char* v = (char*)VIDEO_ADDRESS;
    int j = 0;
    for(int i = 0; i < SCREEN_WIDTH*SCREEN_HEIGHT; i++) {
        if (j > 255)
        {   
            j = 0;
            v[i] = j;
        }   
        else
        {
            j++;
            v[i] = j;
        }
    }
}

void text(int x, int y, int size, char* text, int color, int length)
{
    for (int i = 0; i < length; i++)
    {
        
    }
}

void KMain(void)
{
    //coloredBars(); //debug only
    pixel(1,1,0x0f);
}

I also have a build script:

nasm -f bin -o boot.bin boot.asm
nasm -f bin -o loader.bin loader.asm
nasm -f elf64 -o kernel.o kernel.asm
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c main.c 
ld -T link.lds -o kernel kernel.o main.o
objcopy -O binary kernel kernel.bin 
dd if=boot.bin of=boot.img bs=512 count=1 conv=notrunc
dd if=loader.bin of=boot.img bs=512 count=5 seek=1 conv=notrunc
dd if=kernel.bin of=boot.img bs=512 count=100 seek=6 conv=notrunc

My boot.img, which is 10MB, and bochsrc.bxrc:

# configuration file generated by Bochs
plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false
config_interface: win32config
display_library: win32
memory: host=1024, guest=1024
romimage: file="C:\Program Files\Bochs-2.7/BIOS-bochs-latest", address=0x00000000, options=none
vgaromimage: file="C:\Program Files\Bochs-2.7/VGABIOS-lgpl-latest"
boot: disk
floppy_bootsig_check: disabled=0
floppya: type=1_44
# no floppyb
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="C:\Users\{USER}\Desktop\1\boot.img", mode=flat, cylinders=20, heads=16, spt=63, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto
ata0-slave: type=none
ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=false
ata3: enabled=false
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none
vga: extension=vbe, update_freq=60, realtime=1, ddc=builtin
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string="              Intel(R) Pentium(R) 4 CPU        "
cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true
cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, x86_64=true
cpuid: 1g_pages=true, pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true
cpuid: vmx=1
print_timestamps: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none
speaker: enabled=true, mode=sound, volume=15
parport1: enabled=true, file=none
parport2: enabled=false
com1: enabled=true, mode=null
com2: enabled=false
com3: enabled=false
com4: enabled=false

How can I stop this code from crashing with a triple fault when writing to the video memory at 0xe0000000?

0

There are 0 best solutions below