My VGA driver prints garbage on screen

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

My VGA driver prints garbage on screen

Post by mrfrustrationman »

Hello, i'm new at osdev forum, i am following a guide to make my own os, and i've reached the part where i need to write a vga driver, the driver that i've copied from the book displays this at bochs:Image, someone could help me? Thanks in advance!
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: My VGA driver prints garbage on screen

Post by Ethin »

You've provided far too little information. Can you provide your code and the guide your following?
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

I'm using os-dev along with this github repository (the github repository is based on the book) https://github.com/cfenollosa/os-tutorial
EDIT: I realized that when i change the order of the files to link or change the "-Ttext 0x0" or it prints nothing, or it prints different garbage. "ld -o kernel\kernel.out -Ttext 0x0 kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o"
Driver code:

Code: Select all

#include "screen.h"
#include "ports.h"
#include "util.h"

/* Declaration of private functions */
int get_cursor_offset();
void set_cursor_offset(int offset);
int print_char(char c, int col, int row, char attr);
int get_offset(int col, int row);
int get_offset_row(int offset);
int get_offset_col(int offset);

/**********************************************************
 * Public Kernel API functions                            *
 **********************************************************/

/**
 * Print a message on the specified location
 * If col, row, are negative, we will use the current offset
 */
void kprint_at(char *message, int col, int row) {
    /* Set cursor if col/row are negative */
    int offset;
    if (col >= 0 && row >= 0)
        offset = get_offset(col, row);
    else {
        offset = get_cursor_offset();
        row = get_offset_row(offset);
        col = get_offset_col(offset);
    }

    /* Loop through message and print it */
    int i = 0;
    while (message[i] != 0) {
        offset = print_char(message[i++], col, row, WHITE_ON_BLACK);
        /* Compute row/col for next iteration */
        row = get_offset_row(offset);
        col = get_offset_col(offset);
    }
}

void kprint(char *message) {
    kprint_at(message, -1, -1);
}


/**********************************************************
 * Private kernel functions                               *
 **********************************************************/


/**
 * Innermost print function for our kernel, directly accesses the video memory 
 *
 * If 'col' and 'row' are negative, we will print at current cursor location
 * If 'attr' is zero it will use 'white on black' as default
 * Returns the offset of the next character
 * Sets the video cursor to the returned offset
 */
int print_char(char c, int col, int row, char attr) {
    unsigned char *vidmem = (unsigned char*) VIDEO_ADDRESS;
    if (!attr) attr = WHITE_ON_BLACK;

    /* Error control: print a red 'E' if the coords aren't right */
    if (col >= MAX_COLS || row >= MAX_ROWS) {
        vidmem[2*(MAX_COLS)*(MAX_ROWS)-2] = 'E';
        vidmem[2*(MAX_COLS)*(MAX_ROWS)-1] = RED_ON_WHITE;
        return get_offset(col, row);
    }

    int offset;
    if (col >= 0 && row >= 0) offset = get_offset(col, row);
    else offset = get_cursor_offset();

    if (c == '\n') {
        row = get_offset_row(offset);
        offset = get_offset(0, row+1);
    } else {
        vidmem[offset] = c;
        vidmem[offset+1] = attr;
        offset += 2;
    }

    /* Check if the offset is over screen size and scroll */
    if (offset >= MAX_ROWS * MAX_COLS * 2) {
        int i;
        for (i = 1; i < MAX_ROWS; i++) 
            memory_copy(get_offset(0, i) + VIDEO_ADDRESS,
                        get_offset(0, i-1) + VIDEO_ADDRESS,
                        MAX_COLS * 2);

        /* Blank last line */
        char *last_line = get_offset(0, MAX_ROWS-1) + VIDEO_ADDRESS;
        for (i = 0; i < MAX_COLS * 2; i++) last_line[i] = 0;

        offset -= 2 * MAX_COLS;
    }

    set_cursor_offset(offset);
    return offset;
}

int get_cursor_offset() {
    /* Use the VGA ports to get the current cursor position
     * 1. Ask for high byte of the cursor offset (data 14)
     * 2. Ask for low byte (data 15)
     */
    port_byte_out(REG_SCREEN_CTRL, 14);
    int offset = port_byte_in(REG_SCREEN_DATA) << 8; /* High byte: << 8 */
    port_byte_out(REG_SCREEN_CTRL, 15);
    offset += port_byte_in(REG_SCREEN_DATA);
    return offset * 2; /* Position * size of character cell */
}

void set_cursor_offset(int offset) {
    /* Similar to get_cursor_offset, but instead of reading we write data */
    offset /= 2;
    port_byte_out(REG_SCREEN_CTRL, 14);
    port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
    port_byte_out(REG_SCREEN_CTRL, 15);
    port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
}

void clear_screen() {
    int screen_size = MAX_COLS * MAX_ROWS;
    int i;
    char *screen = VIDEO_ADDRESS;

    for (i = 0; i < screen_size; i++) {
        screen[i*2] = ' ';
        screen[i*2+1] = WHITE_ON_BLACK;
    }
    set_cursor_offset(get_offset(0, 0));
}


int get_offset(int col, int row) { return 2 * (row * MAX_COLS + col); }
int get_offset_row(int offset) { return offset / (2 * MAX_COLS); }
int get_offset_col(int offset) { return (offset - (get_offset_row(offset)*2*MAX_COLS))/2; }
kernel code:

Code: Select all

#include "drivers\screen.h"
#include "drivers\util.h"
void _main() {
    clear_screen();
    kprint_at("Tetsing", 5, 0);
}
Octocontrabass
Member
Member
Posts: 5829
Joined: Mon Mar 25, 2013 7:01 pm

Re: My VGA driver prints garbage on screen

Post by Octocontrabass »

mrfrustrationman wrote:"ld -o kernel\kernel.out -Ttext 0x0 kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o"
Where is your kernel's entry point in the files you're linking together? Where is your kernel's entry point when it's loaded in memory by your bootloader?
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

Octocontrabass wrote:
mrfrustrationman wrote:"ld -o kernel\kernel.out -Ttext 0x0 kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o"
Where is your kernel's entry point in the files you're linking together? Where is your kernel's entry point when it's loaded in memory by your bootloader?
bootloader code:

Code: Select all

[org 0x7c00]
KERNEL_OFFSET equ 0x1000

    mov [BOOT_DRIVE], dl
    mov bp, 0x9000
    mov sp, bp

    mov bx, MSG_REAL_MODE 
    call print
    call print_nl

    call load_kernel
    call switch_to_pm 
    jmp $

%include "boot\print_string.asm"
%include "boot\print_string_hex.asm"
%include "boot\read_disk.asm"
%include "boot\gdt.asm"
%include "boot\32bit-print.asm"
%include "boot\32bit-switch.asm"

[bits 16]
load_kernel:
    mov bx, MSG_LOAD_KERNEL
    call print
    call print_nl

    mov bx, KERNEL_OFFSET
    mov dh, 16
    mov dl, [BOOT_DRIVE]
    call disk_load
    ret

[bits 32]
BEGIN_PM:
    mov ebx, MSG_PROT_MODE
    call print_string_pm
    call KERNEL_OFFSET
    jmp $


BOOT_DRIVE db 0
MSG_REAL_MODE db "Starting...", 0
MSG_PROT_MODE db "...", 0
MSG_LOAD_KERNEL db "Loading operating system...", 0

; padding
times 510 - ($-$$) db 0
dw 0xaa55
kernel entry:

Code: Select all

[bits 32]
[extern __main] ; Define calling point. Must have same name as kernel.c 'main' function
call __main ; Calls the C function. The linker will know where it is placed in memory
jmp $
Octocontrabass
Member
Member
Posts: 5829
Joined: Mon Mar 25, 2013 7:01 pm

Re: My VGA driver prints garbage on screen

Post by Octocontrabass »

mrfrustrationman wrote:"ld -o kernel\kernel.out -Ttext 0x0 kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o"
Where is your kernel entry point in the files you're linking together? You can't link source code!

According to your bootloader code, your kernel's entry point in memory is 0x1000. How are you telling the linker about this?
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

Octocontrabass wrote:
mrfrustrationman wrote:"ld -o kernel\kernel.out -Ttext 0x0 kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o"
Where is your kernel entry point in the files you're linking together? You can't link source code!

According to your bootloader code, your kernel's entry point in memory is 0x1000. How are you telling the linker about this?
what do you mean by tell the linker? like "-Ttext 0x1000"? Do you want to see my build.bat file?
Octocontrabass
Member
Member
Posts: 5829
Joined: Mon Mar 25, 2013 7:01 pm

Re: My VGA driver prints garbage on screen

Post by Octocontrabass »

mrfrustrationman wrote:what do you mean by tell the linker? like "-Ttext 0x1000"?
Yes. That tells the linker where your kernel will be loaded in memory.
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

My build.bat

Code: Select all

@echo off
cls
color a
echo Compiling...
gcc -ffreestanding -c  kernel\kernel.c -o kernel\kernel.o
gcc -ffreestanding -c kernel\drivers\ports.c -o kernel\drivers\ports.o
gcc -ffreestanding -c kernel\drivers\screen.c -o kernel\drivers\screen.o
gcc -ffreestanding -c kernel\drivers\util.c -o kernel\util.o
timeout 2 >nul
echo Kernel dump:
objdump -d kernel\kernel.o
timeout 1 >nul
echo nasm:
nasm -f elf boot\kernel_entry.asm -o boot\kernel_entry.o
echo ld:
ld -o kernel\kernel.out -Ttext 0x0  kernel\kernel.o kernel\drivers\screen.o kernel\util.o kernel\drivers\ports.o
echo objcopy:
objcopy -O binary -j .text kernel\kernel.out kernel\kernel.bin
echo nasm:
nasm boot\bootloader.asm -f bin -o boot\bootloader.bin
echo cat:
cat boot\bootloader.bin kernel\kernel.bin > os-image.bin
pause >nul

::qemu-system-x86_64 os-image.bin
call run.bat
Octocontrabass
Member
Member
Posts: 5829
Joined: Mon Mar 25, 2013 7:01 pm

Re: My VGA driver prints garbage on screen

Post by Octocontrabass »

So your kernel entry point is located in kernel_entry.asm, which is assembled to kernel_entry.o and then... not linked? I'm surprised your kernel works at all without the entry point code, it's pretty important.

And in the batch file, you're still telling the linker that your kernel will be loaded at 0x0 when it really will be loaded at 0x1000.
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

Octocontrabass wrote:So your kernel entry point is located in kernel_entry.asm, which is assembled to kernel_entry.o and then... not linked? I'm surprised your kernel works at all without the entry point code, it's pretty important.

And in the batch file, you're still telling the linker that your kernel will be loaded at 0x0 when it really will be loaded at 0x1000.
Omg, i didn't see it! I've already changed the arg, let me test it... Yeah, now it doesn't print anything
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

My updated build.bat:

Code: Select all

@echo off
cls
color a
echo Compiling...
gcc -ffreestanding -c  kernel\kernel.c -o kernel\kernel.o
gcc -ffreestanding -c kernel\drivers\ports.c -o kernel\drivers\ports.o
gcc -ffreestanding -c kernel\drivers\screen.c -o kernel\drivers\screen.o
gcc -ffreestanding -c kernel\drivers\util.c -o kernel\util.o
timeout 2 >nul
echo Kernel dump:
objdump -d kernel\kernel.o
timeout 1 >nul
echo nasm:
nasm -f elf boot\kernel_entry.asm -o boot\kernel_entry.o
echo ld:
ld -o kernel\kernel.out -Ttext 0x1000  kernel\kernel.o boot\kernel_entry.o kernel\drivers\ports.o kernel\drivers\screen.o kernel\util.o
echo objcopy:
objcopy -O binary -j .text kernel\kernel.out kernel\kernel.bin
echo nasm:
nasm boot\bootloader.asm -f bin -o boot\bootloader.bin
echo cat:
cat boot\bootloader.bin kernel\kernel.bin > os-image.bin
pause >nul

::qemu-system-x86_64 os-image.bin
call run.bat
MichaelPetch
Member
Member
Posts: 829
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: My VGA driver prints garbage on screen

Post by MichaelPetch »

As I mentioned in a comment on Stackoverflow you should put your own copy of the project with all your changes (batch files included). However the fact you are using `-Ttext 0x0` is a problem given that the tutorial you are using has a bootloader that loads the kernel to 0x1000. It should be `-Ttext 0x1000` . This could explain why strings print gibberish. Likely your code is reading the string from somewhere in the real mode IVT rather than where your kernel was actually loaded.

I will assume you are using powershell since you are using the `cat` command.
mrfrustrationman
Posts: 13
Joined: Sun Jun 14, 2020 5:15 pm
Libera.chat IRC: mrfrust

Re: My VGA driver prints garbage on screen

Post by mrfrustrationman »

MichaelPetch wrote:As I mentioned in a comment on Stackoverflow you should put your own copy of the project with all your changes (batch files included). However the fact you are using `-Ttext 0x0` is a problem given that the tutorial you are using has a bootloader that loads the kernel to 0x1000. It should be `-Ttext 0x1000` . This could explain why strings print gibberish. Likely your code is reading the string from somewhere in the real mode IVT rather than where your kernel was actually loaded.

I will assume you are using powershell since you are using the `cat` command.
That's a interesting history, I've downloaded GnuWin and used it's cat command
Octocontrabass
Member
Member
Posts: 5829
Joined: Mon Mar 25, 2013 7:01 pm

Re: My VGA driver prints garbage on screen

Post by Octocontrabass »

Code: Select all

objcopy -O binary -j .text kernel\kernel.out kernel\kernel.bin
Strings are usually stored in the .rodata section, but you're discarding everything except the .text section. Any particular reason you use objcopy here instead of passing "--oformat binary" to ld like the tutorial does?
Post Reply