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!
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
User contributions licensed under CC BY-SA 3.0