Not booting when reaching for function
Page 1 of 1

Author:  R3DC0DE [ Fri Sep 20, 2019 8:31 am ]
Post subject:  Not booting when reaching for function


I am currently in the process of writing a simple screen driver. Unfortunately, QEmu is giving me a "boot failed : couldn't read boot disk" whenever I try accessing print_at function. What is in the function is not the cause of the problem since I tried to change it by a test code and it didn't change the situation.

Edit: I join the git project. The screen driver files are under drivers/.


Thanks for the help.

Author:  iansjack [ Fri Sep 20, 2019 9:09 am ]
Post subject:  Re: Not booting when reaching for function

Without any details of the version of qemu that you are using, your source code, and the commands used to produce the image file it is very difficult to make a sensible guess as to the likely cause of your problem.

Author:  MichaelPetch [ Fri Sep 20, 2019 9:51 am ]
Post subject:  Re: Not booting when reaching for function

Not a lot to go on. If you had a project somewhere like github or similar service it would be easier to look at.

If you are getting "boot failed : could not read boot disk" that sounds like you wrote a custom bootloader and are not using GRUB or QEMU's `-kernel` feature. If that is the case then it could be about how you are building the disk image and/or how you are launching it in QEMU.

One guess may be that the `msg` you are trying to print with the function gets placed in a new section in your kernel's binary file and that has caused a problem with the disk image.

Without any specifics this is pretty much a guessing game.

Author:  MichaelPetch [ Fri Sep 20, 2019 10:45 am ]
Post subject:  Re: Not booting when reaching for function

I see you are on Windows. Native GCC compilers will target Windows, and with it comes many nuances with the default linker script. But there are things that stand out:
objcopy -O binary -j .text  kernel.tmp kernel.bin
The output file will only contain the `.text` and won't include the `.data` or `.rdata*` sections where `msg` likely reside. My guess is that `msg` doesn't appear in the kernel.bin file at all and thus why you are having problems.

Beyond that you appear to have another big issue. You appear to be using a GCC (MinGW? Cygwin?) compiler that by default is generating 64-bit code. In order for you to properly run 64-bit bit code you need to be in 64-bit mode (one of the submodes of long mode). Your bootloader appears to only put the processor in protected mode. Even if you were able to start executing the code, you would likely see certain anomalies right away - like screen output appearing wonky for inexplicable reasons.

I can't stress this enough. If you want to build a 64-bit kernel then you need to get into 64-bit long mode, and on WIndows I highly suggest that you consider a cross compiler so you don't have to deal with all the nuances of the native non-ELF compilers on that platform. If you intend to write a 32-bit OS then I recommend getting a 32-bit (i686-elf or i386-elf) cross compiler.

It is in fact possible to use the native compilers, but the linker script section names are slightly different, and the bit and structure packing rules are different unless you also add the GCC option -mno-ms-bitfields . These are two things that I remember off the top of my head. I've helped people on Stackoverflow build 32-bit OSes using Cygwin and they encounter similar issues.

You will really need to start considering using a linker script as well (you don't use one at all since you link with the -T NUL option).

When using Windows commands to add file together I recommend using COPY instead of type. You can ensure binary files are copied as is. You can do:
copy /b file+file2 outputfile

A somewhat related post of mine (they used GRUB and not a custom bootloader with Cygwin as a compiler) on SO: https://stackoverflow.com/questions/492 ... on-mode-el

And regarding 64-bit code running in 32-bit protected mode these are the type of things you could possibly see early on in OS development:

https://stackoverflow.com/questions/398 ... y/39815993

Author:  MichaelPetch [ Fri Sep 20, 2019 1:36 pm ]
Post subject:  Re: Not booting when reaching for function

These changes are untested since I don't have your environment set up. A new file for a linker script called link.ld:

    . = 0x1000;

    .text :
        *(.text.bootstrap) /* Anything in this section will be first */

    .rodata :
        *(.rdata*)    /* IMPORTANT - Windows uses rdata */

    .data :

    .bss :
A revised Makefile that uses the linker script and passes additional parameters to GCC and compiles and links as 32-bit code:
C_SOURCES = $(wildcard kernel/*.c drivers/*.c)
ASM_SOURCES = $(wildcard kernel/*.asm)
HEADERS = $(wildcard kernel/*.h drivers/*.h)

OBJ = ${C_SOURCES:.c=.o} $(ASM_SOURCES:.asm=.o)

all: os_image.img

run: all
        qemu-system-x86_64 -drive format=raw,file=os_image.img,index=0,if=floppy

os_image.img: boot/boot_sector.bin kernel.bin
        copy /b boot\boot_sector.bin+kernel.bin os_image.img

kernel.bin: ${OBJ}
        ld -mi386pe -T link.ld -o kernel.tmp  $^
        objcopy -O binary kernel.tmp kernel.bin

%.o : %.c ${HEADERS}
        gcc -m32 -ffreestanding -mno-ms-bitfields -c $< -o $@

%.o : %.asm
        nasm $< -f win32 -o $@

%.bin: %.asm
        nasm $< -f bin -i 'boot/' -o $@

        del *.bin
        del *.img
        del drivers\*.o
        del kernel\*.o
        del boot\*.bin
Rather than rely on the objects being in a particular order when linking we use a new section that the linker script places before all others. As well, because Windows 32-bit objects have functions decorated with an additional underscore prefixed to the name the kernel_entry.asm file changes to:
global _start                  ; Prevent a linker warning

[bits 32]
section .text.bootstrap        ; This section is placed before everything
                               ;     else in linker script

[extern ___main]               ; 32-bit Windows objects require extra _
                               ; for name decoration ___main instead of __main
call ___main
jmp $

Author:  R3DC0DE [ Sat Sep 21, 2019 4:59 am ]
Post subject:  Re: Not booting when reaching for function

Thank you for your guidance. If I did understand correctly, the linker script is responsible for putting together the code in the right other at the right memory spot and it is replacing the option I was giving to the ld command.

Author:  MichaelPetch [ Sat Sep 21, 2019 6:41 am ]
Post subject:  Re: Not booting when reaching for function

Yes, the linker script replaces you having to specify -Ttext=0x1000 on the command line, it does away with you needing to place kernel_entry.o as the first object of the command line used by LD (also requires a change to the kernel_entry.asm file to support the linker script change), and it includes all the necessary sections (and no need for objcopy with the -j option).

But the truly big problem fixed in the Makefile is that it now builds a 32-bit kernel and not a 64-bit one. If you want a 64-bit kernel you have to modify your bootloader to put you in 64-bit mode.

Author:  R3DC0DE [ Mon Sep 23, 2019 1:56 am ]
Post subject:  Re: Not booting when reaching for function

Alright. Thank you for your guidance.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group