Unable to get QEMU to boot my bootloader after linking a C file

1

I am trying to link some C code into a bootloader that I have made, However after doing that, I'm not able to get QEMU to boot my raw file attached are the relevant parts of the bootloader, the makefile and linker scripts.

EDIT: QEMU gives a "not a bootable disk" when it tries to boot from the hard drive and a "could not read the boot disk" when it tries to boot from the floppy.

I am assuming that there's something wrong with my linker script that prevents code from loading into 0x7c00, but I have included all of the other code just to be doubly sure.

[bits 16]

mmap_entries equ 0x8000

[extern mainKernel]
[extern code]
[extern bss]
[extern end]

global start   ;start is global and is our entry point

start:
jmp ZeroSeg                 ;try jmp 0x0000:ZeroSeg
dw 0x00                     ;padding

OEMname:            db      "MYBOOT  "
    bytesPerSector:     dw       512
    sectPerCluster:     db       1
    reservedSectors:    dw       1
    numFAT:             db       2
    numRootDirEntries:  dw       240
    numSectors:         dw       5760
    mediaType:          db       0xf0
    numFATsectors:      dw       9
    sectorsPerTrack:    dw       36
    numHeads:           dw       2
    numHiddenSectors:   dd       0
    numSectorsHuge:     dd       0
    driveNum:           db       0
    reserved:           db       0x00
    signature:          db       0x29
    volumeID:           dd       0x54428E71
    volumeLabel:        db      "NO NAME    "
    fileSysType:        db      "FAT12   "


ZeroSeg:

    cli         ;clear interrupts 
    xor ax,ax   ; clear ax

    mov ds,ax   ;clear the seg registers, to prevent any offset buffer
    mov es,ax 
    mov fs,ax
    mov gs,ax
    mov ss,ax   ;even after cli, apparently some processors don't like any code after mov ss...
                ;but before mov sp...

    mov sp, 0x7c00      ;0x7c00 = Start address
    cld         ; clear the direction flag, which controlls the order of reading
                ; string
    sti         ; set interrupt


    ;extended read ah=42h

    mov ax,0x07e0
    mov es,ax
    xor di,di


    mov ax, 0x0002  ; number of sectors read
    mov cx, 0x0001  ;absolute number (not addr of start sector (sector 0 is bootloader here))

    call readDisk

    call loadE820

    ;mov dx,ax      
    ;call printh

    ;TODO Configure Proper video modes

    jmp sect2       ; works if sect2 is read

Here is the code for sector 2:

sect2:
    call EnableA20

    mov si, MESSAGE
    call printf

    ;call checklm
    jmp enterProtected


And the code for the enter protected method

enterProtected:

    cli

    xor ax,ax
    mov ds,ax


    lgdt [GDT_DESC]

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



    jmp 08h:clear_pipe ;fix CS and clear all garbage instructions

    [BITS 32]
    clear_pipe:
        ;clear all garbage instructions
        mov ax, 10h  ;data segment, not codeseg 
        mov ds, ax
        mov ss, ax

        ;segment part set 
        ;set offset part

        mov esp, 090000h        ;safe offset for stack to exist 
        mov byte [0B8000h], 'P'
        mov byte [0B8001h], 1Bh


        call mainKernel
        jmp $

mainKernel is an external C function that's just returning a value

int mainKernel()
{
    return 0xDEADBEEF;
}

I'm building the whole thing in a makefile as follows, by using an i686-elf-gcc cross-compiler

BOOTLOADER=bootloader.asm
KERNEL=mainKernel.c


clean:
    rm *.bin
rq:
    qemu-system-x86_64 bootloader.bin 

rb:
    bochs

compile:
    nasm -felf $(BOOTLOADER) -o boot.o
    i686-elf-gcc -c self_kernel/$(KERNEL) -o mainKernel.o -ffreestanding -O2 -Wall -Wextra -std=gnu99
    i686-elf-gcc -T linker.ld -o bootloader.bin -ffreestanding -O2 -nostdlib boot.o mainKernel.o -lgcc

and here's the script for linker.ld

ENTRY(start)
SECTIONS
{
    . = 0x7c00;
    .text 0x7c00:
    {

        boot.o(.text);
        *(.text);
        . = ALIGN(4096);
    }

    .data :
    {

        *(.data);
        *(.rodata);
        . = ALIGN(4096);
    }

    .bss :
    {

        *(.bss);
        . = ALIGN(4096);
    }

}

EDIT: here's the readelf output for the binary output.

readelf -a bootloader.bin
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x7c00
  Start of program headers:          52 (bytes into file)
  Start of section headers:          14860 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         9
  Section header string table index: 8

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00007c00 000c00 001400 00  AX  0   0 16
  [ 2] .eh_frame         PROGBITS        00009000 002000 00002c 00   A  0   0  4
  [ 3] .data             PROGBITS        0000902c 00202c 000fd4 00  WA  0   0  1
  [ 4] .bss              NOBITS          0000a000 003000 000000 00  WA  0   0  1
  [ 5] .comment          PROGBITS        00000000 003000 000011 01  MS  0   0  1
  [ 6] .symtab           SYMTAB          00000000 003014 000610 10      7  95  4
  [ 7] .strtab           STRTAB          00000000 003624 0003a9 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 0039cd 00003f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00007000 0x00007000 0x03000 0x03000 RWE 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text .eh_frame .data 

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Intel 80386 is not currently supported.

Symbol table '.symtab' contains 97 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00007c00     0 SECTION LOCAL  DEFAULT    1 
     2: 00009000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000902c     0 SECTION LOCAL  DEFAULT    3 
     4: 0000a000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 FILE    LOCAL  DEFAULT  ABS bootloader.asm
     7: 00008000     0 NOTYPE  LOCAL  DEFAULT  ABS mmap_entries
     8: 00007c04     0 NOTYPE  LOCAL  DEFAULT    1 OEMname
     9: 00007c0c     0 NOTYPE  LOCAL  DEFAULT    1 bytesPerSector
    10: 00007c0e     0 NOTYPE  LOCAL  DEFAULT    1 sectPerCluster
    11: 00007c0f     0 NOTYPE  LOCAL  DEFAULT    1 reservedSectors
    12: 00007c11     0 NOTYPE  LOCAL  DEFAULT    1 numFAT
    13: 00007c12     0 NOTYPE  LOCAL  DEFAULT    1 numRootDirEntries
    14: 00007c14     0 NOTYPE  LOCAL  DEFAULT    1 numSectors
    15: 00007c16     0 NOTYPE  LOCAL  DEFAULT    1 mediaType
    16: 00007c17     0 NOTYPE  LOCAL  DEFAULT    1 numFATsectors
    17: 00007c19     0 NOTYPE  LOCAL  DEFAULT    1 sectorsPerTrack
    18: 00007c1b     0 NOTYPE  LOCAL  DEFAULT    1 numHeads
    19: 00007c1d     0 NOTYPE  LOCAL  DEFAULT    1 numHiddenSectors
    20: 00007c21     0 NOTYPE  LOCAL  DEFAULT    1 numSectorsHuge
    21: 00007c25     0 NOTYPE  LOCAL  DEFAULT    1 driveNum
    22: 00007c26     0 NOTYPE  LOCAL  DEFAULT    1 reserved
    23: 00007c27     0 NOTYPE  LOCAL  DEFAULT    1 signature
    24: 00007c28     0 NOTYPE  LOCAL  DEFAULT    1 volumeID
    25: 00007c2c     0 NOTYPE  LOCAL  DEFAULT    1 volumeLabel
    26: 00007c37     0 NOTYPE  LOCAL  DEFAULT    1 fileSysType
    27: 00007c3f     0 NOTYPE  LOCAL  DEFAULT    1 ZeroSeg
    28: 00007c67     0 NOTYPE  LOCAL  DEFAULT    1 printf
    29: 00007c68     0 NOTYPE  LOCAL  DEFAULT    1 strLoop
    30: 00007c73     0 NOTYPE  LOCAL  DEFAULT    1 end__
    31: 00007c75     0 NOTYPE  LOCAL  DEFAULT    1 readDisk
    32: 00007ca4     0 NOTYPE  LOCAL  DEFAULT    1 DAP
    33: 00007ca4     0 NOTYPE  LOCAL  DEFAULT    1 DAP_SIZE
    34: 00007ca5     0 NOTYPE  LOCAL  DEFAULT    1 DAP_UNUSED
    35: 00007ca6     0 NOTYPE  LOCAL  DEFAULT    1 DAP_NUM_SECTORS
    36: 00007ca8     0 NOTYPE  LOCAL  DEFAULT    1 DAP_PTR_TO_SECTOR
    37: 00007ca8     0 NOTYPE  LOCAL  DEFAULT    1 DAP_OFFSET
    38: 00007caa     0 NOTYPE  LOCAL  DEFAULT    1 DAP_SEGMENT
    39: 00007cac     0 NOTYPE  LOCAL  DEFAULT    1 DAP_START_SECTOR
    40: 00007cb4     0 NOTYPE  LOCAL  DEFAULT    1 fail
    41: 00007cbc     0 NOTYPE  LOCAL  DEFAULT    1 printh
    42: 00007cc4     0 NOTYPE  LOCAL  DEFAULT    1 subp
    43: 00007ce8     0 NOTYPE  LOCAL  DEFAULT    1 loadE820
    44: 00007d22     0 NOTYPE  LOCAL  DEFAULT    1 e820Load
    45: 00007d41     0 NOTYPE  LOCAL  DEFAULT    1 loadMap
    46: 00007d4f     0 NOTYPE  LOCAL  DEFAULT    1 noText
    47: 00007d5f     0 NOTYPE  LOCAL  DEFAULT    1 skipEnt
    48: 00007d64     0 NOTYPE  LOCAL  DEFAULT    1 e820Done
    49: 00007d6e     0 NOTYPE  LOCAL  DEFAULT    1 noE820
    50: 00007d6e     0 NOTYPE  LOCAL  DEFAULT    1 e820Fail
    51: 00007d77     0 NOTYPE  LOCAL  DEFAULT    1 DISKFAILMSG
    52: 00007d88     0 NOTYPE  LOCAL  DEFAULT    1 drive_number
    53: 00007d89     0 NOTYPE  LOCAL  DEFAULT    1 HEX_PATTERN
    54: 00007d92     0 NOTYPE  LOCAL  DEFAULT    1 HEX_TABLE
    55: 00007da2     0 NOTYPE  LOCAL  DEFAULT    1 E820_ERR_MESSAGE
    56: 00007e00     0 NOTYPE  LOCAL  DEFAULT    1 sect2
    57: 00007e0c     0 NOTYPE  LOCAL  DEFAULT    1 TestA20
    58: 00007e12     0 NOTYPE  LOCAL  DEFAULT    1 SegTest
    59: 00007e25     0 NOTYPE  LOCAL  DEFAULT    1 EnableA20
    60: 00007e38     0 NOTYPE  LOCAL  DEFAULT    1 BIOS
    61: 00007e7a     0 NOTYPE  LOCAL  DEFAULT    1 Wait_8042_command
    62: 00007e81     0 NOTYPE  LOCAL  DEFAULT    1 Wait_8042_data
    63: 00007e88     0 NOTYPE  LOCAL  DEFAULT    1 FAILURE
    64: 00007e90     0 NOTYPE  LOCAL  DEFAULT    1 EndA20
    65: 00007e97     0 NOTYPE  LOCAL  DEFAULT    1 checklm
    66: 00007e97     0 NOTYPE  LOCAL  DEFAULT    1 cpudetect
    67: 00007eb2     0 NOTYPE  LOCAL  DEFAULT    1 long_mode
    68: 00007edb     0 NOTYPE  LOCAL  DEFAULT    1 NoID
    69: 00007ee2     0 NOTYPE  LOCAL  DEFAULT    1 NoExFunc
    70: 00007ee9     0 NOTYPE  LOCAL  DEFAULT    1 NoLM
    71: 00007ef0     0 NOTYPE  LOCAL  DEFAULT    1 YesLM
    72: 00007ef7     0 NOTYPE  LOCAL  DEFAULT    1 enterProtected
    73: 00007f10     0 NOTYPE  LOCAL  DEFAULT    1 clear_pipe
    74: 00007f32     0 NOTYPE  LOCAL  DEFAULT    1 MESSAGE
    75: 00007f40     0 NOTYPE  LOCAL  DEFAULT    1 FAILA20
    76: 00007f5e     0 NOTYPE  LOCAL  DEFAULT    1 SUCCESSA20
    77: 00007f6c     0 NOTYPE  LOCAL  DEFAULT    1 LM_SUCCESS
    78: 00007f85     0 NOTYPE  LOCAL  DEFAULT    1 ID_FAIL
    79: 00007f98     0 NOTYPE  LOCAL  DEFAULT    1 EXFUNC_FAIL
    80: 00007fb8     0 NOTYPE  LOCAL  DEFAULT    1 LM_FAIL
    81: 00008000     0 NOTYPE  LOCAL  DEFAULT    1 sect3
    82: 00008000     0 NOTYPE  LOCAL  DEFAULT    1 keyb
    83: 0000800a     0 NOTYPE  LOCAL  DEFAULT    1 GDT
    84: 0000800a     0 NOTYPE  LOCAL  DEFAULT    1 GDT_NULL
    85: 00008012     0 NOTYPE  LOCAL  DEFAULT    1 GDT_CODE
    86: 00008012     0 NOTYPE  LOCAL  DEFAULT    1 GDT_FIRST_DD
    87: 00008016     0 NOTYPE  LOCAL  DEFAULT    1 GDT_CONT_BASE_ADDR
    88: 00008017     0 NOTYPE  LOCAL  DEFAULT    1 GDT_SEGMENT_DESC
    89: 00008018     0 NOTYPE  LOCAL  DEFAULT    1 GDT_LIMIT_DESC
    90: 00008019     0 NOTYPE  LOCAL  DEFAULT    1 GDT_REM_BASE_ADDR
    91: 0000801a     0 NOTYPE  LOCAL  DEFAULT    1 GDT_DATA
    92: 00008022     0 NOTYPE  LOCAL  DEFAULT    1 GDT_END
    93: 00008022     0 NOTYPE  LOCAL  DEFAULT    1 GDT_DESC
    94: 00000000     0 FILE    LOCAL  DEFAULT  ABS mainKernel.c
    95: 00008200     6 FUNC    GLOBAL DEFAULT    1 mainKernel
    96: 00007c00     0 NOTYPE  GLOBAL DEFAULT    1 start

No version information found in this file.

What could be the reason for this? Thanks!

assembly
operating-system
x86-16
bootloader
asked on Stack Overflow Apr 30, 2020 by AetherPrior • edited Apr 30, 2020 by AetherPrior

1 Answer

2

Figured it out. All I had to do was an object copy:

objcopy -O binary bootloader.bin output_file

I was trying to load an elf instead of a flat executable Thanks to @Jester for pointing it out

answered on Stack Overflow May 1, 2020 by AetherPrior

User contributions licensed under CC BY-SA 3.0