Page 1 of 1

Trying to get into protected mode, getting relocation error?

Posted: Sun Jun 08, 2014 12:44 am
by mango
I can't use GRUB to make a disk image as I'm developing on OSX, so I've been creating binary kernel images and booting via QEMU. I've wrote an entry asm file that contains a multi boot header and an entry routine that sets up protected mode and a stack before calling into c code. However, while linking everything together I get the following error:

Code: Select all

lib/entry.o: In function `seta20p2':
(.text+0x2c): relocation truncated to fit: R_386_16 against `.text'
lib/entry.o: In function `seta20p2':
(.text+0x39): relocation truncated to fit: R_386_16 against `.text'
collect2: error: ld returned 1 exit status
My code is as follows:

Code: Select all

#include "mmu.h"

.align 4
.text
.global multiboot_header
multiboot_header:
    #define magic 0x1badb002
    #define flags 0
    .long magic
    .long flags
    .long -(magic+flags)

.global _start
_start:
    # start in Real Mode
    .code16
    # Disable interrupts for obvious reasons
    cli
    # Zero out the data segment and stack segment in preparation
    # for a new GDT that will redefine those segments for protected
    # mode
    xorw %ax, %ax
    movw %ax, %ds
    movw %ax, %es
    movw %ax, %ss
    # Set address line 20 high so we can access 1MB and above
    seta20p1:
    inb     $0x64,%al               # Wait for not busy
    testb   $0x2,%al
    jnz     seta20p1

    movb    $0xd1,%al               # 0xd1 -> port 0x64
    outb    %al,$0x64

    seta20p2:
    inb     $0x64,%al               # Wait for not busy
    testb   $0x2,%al
    jnz     seta20p2

    movb    $0xdf,%al               # 0xdf -> port 0x60
    outb    %al,$0x60
    # Switch from real to protected mode, using a GDT that
    # does an identity mapping
    lgdt    gdtdesc
    movl    %cr0, %eax
    orl     $CR0_PE, %eax
    movl    %eax, %cr0
    # Enter protected mode with a long jump,
    # which will reset cs and eip
    ljmp    $KERNEL_CS, $start32
.code32
start32:
    movw $KERNEL_DS, %ax
    movw %ax, %ds
    movw %ax, %es
    movw %ax, %ss
    xorw %ax, %ax

    # set up stack 
    movl $(stack + 4096), %esp

    call main
#The above should never return, but in case it does
spin:
    jmp spin

.align 4
# bootstrap gdt that overlaps code and data and identity maps
gdt:
    SEGMENT_NULL                        # GDT must begin with null descriptor
    SEGMENT(SEG_X|SEG_R, 0, 0xffffffff) # code segment
    SEGMENT(SEG_W, 0, 0xffffffff)       # data segment

# GDT descriptor that is loaded onto gdtr
gdtdesc:
    .word (gdtdesc-gdt-1) #sideof(gdt) - 1
    .long gdt             # pointer to gdt

.comm stack, 4096
I understand most everything above, and I borrowed heavily from xv6, but I don't get what's wrong. Does anyone know what's up?

Re: Trying to get into protected mode, getting relocation er

Posted: Sun Jun 08, 2014 1:06 am
by Combuster
You can use multiboot images directly with QEMU, which means you should not use 16-bit code. You can also roll your entire boot loader, which means you have to write a dedicated bootsector with the relevant boot signature that contains the loading code for a different binary, and no multiboot header.

At the very least, your visible problems are coming from the fact that you told gcc that the bootsector should go in a different place than where it would actually go on a real system. But since your design is fundamentally flawed in the first place, I recommend that you drop this code, decide what you actually want, and then follow the appropriate Tutorials first

Re: Trying to get into protected mode, getting relocation er

Posted: Sun Jun 08, 2014 2:23 pm
by mango
I began writing this OS to get a better understanding of the boot process, so I'm a little lost here. I've never had problems booting from QEMU, I just specify --kernel and boot from the .bin image. I googled around to find more info about the QEMU loader, but I can't seem to find anything useable. I know that GRUB gaurantees protected mode and line A20 up after entering the kernel, but I don't know this about QEMU. What about this is wrong specifically?

Re: Trying to get into protected mode, getting relocation er

Posted: Sun Jun 08, 2014 7:12 pm
by Octocontrabass
mango wrote:I borrowed heavily from xv6
mango wrote:What about this is wrong specifically?
Xv6 boots directly from the BIOS. The BIOS is not Multiboot. Compare this to this.

Re: Trying to get into protected mode, getting relocation er

Posted: Sun Jun 08, 2014 8:35 pm
by mango
Ah, thank you! I changed the code to:

Code: Select all

#include "mmu.h"

.align 4
.text
.global multiboot_header
multiboot_header:
    #define magic 0x1badb002
    #define flags 0
    .long magic
    .long flags
    .long -(magic+flags)

.global _start
_start:
    # Disable interrupts for obvious reasons
    cli
    # does an identity mapping
    lgdt    gdtdesc
    # Enter protected mode with a long jump,
    # which will reset cs and eip
    ljmp    $KERNEL_CS, $gdt_loaded
gdt_loaded:
    movw $KERNEL_DS, %bx
    movw %bx, %ds
    movw %bx, %es
    movw %bx, %ss
    xorw %bx, %ax

    # set up stack 
    movl $(stack + 4096), %esp

    pushl %eax
    call main
#The above should never return, but in case it does
spin:
    jmp spin

.align 4
# bootstrap gdt that overlaps code and data and identity maps
gdt:
    SEGMENT_NULL                        # GDT must begin with null descriptor
    SEGMENT(SEG_X|SEG_R, 0, 0xffffffff) # code segment
    SEGMENT(SEG_W, 0, 0xffffffff)       # data segment

# GDT descriptor that is loaded onto gdtr
gdtdesc:
    .word (gdtdesc-gdt-1) #sideof(gdt) - 1
    .long gdt             # pointer to gdt

.comm stack, 4096
and it boots again, but when I examine the argument to main in the c code, it is != 0x2badb002. What else is wrong? The QEMU docs say that the -kernel flag requires a multi boot kernel, so I assume boot would break, but it doesn't

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 12:26 am
by ScropTheOSAdventurer
You do that XOR with bx and ax. That messes it up.

EDIT: Why are you doing that xor anyways? Curious.

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 4:38 am
by Bender
ScropTheOSAdventurer wrote:You do that XOR with bx and ax. That messes it up.

EDIT: Why are you doing that xor anyways? Curious.
If I'm correct he's probably trying to zero out BX. It's a "shorter" operation (as in size), XOR R32, R32 is only 2-bytes whereas MOV R32, IMM takes 5 bytes. However XOR uses 4 (? idk) NAND gates and it's a complicated operation while AND uses 2. AND R32, 0 can also be used to zero a register. Please note that both XOR and AND thrash (E/R)FLAGS.

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 5:10 am
by Combuster
The propagation delay of one gate of AND or the three of XOR reduced to the three primary ones, is totally irrelevant compared to all the other administration the processor has to perform. The correct answer is that XOR reg, reg (or SUB reg, reg) takes the least possible bytes to encode. AND can't do that, MOV can't do that.
idk
Better not to post in such a situation.

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 8:19 am
by Bender
*Embarrassment*
Yes, Combuster is right. AND R32, IMM takes 4 bytes (x86-32) while XOR R32, R32 takes only 2 bytes which makes XOR a better choice. Heck, even GCC uses XOR R, R with -O2. (Confused AND R32, IMM with AND R32, R32). Though I'd still say on a "hypothetical" machine where instructions are of the same length AND will be faster than XOR. (Even though negligible)

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 10:27 am
by Octocontrabass
Bender wrote:Though I'd still say on a "hypothetical" machine where instructions are of the same length AND will be faster than XOR. (Even though negligible)
Every CPU I know of can do AND, XOR, ADD, and SUB in one cycle each. Your hypothetical CPU's clock speed would have to be very high for the propagation delay of a few transistors to warrant an extra cycle for one ALU operation over another. I'd really like to see your CPU in action!

On a side note, Sandy Bridge skips the ALU entirely if you're using SUB or XOR to zero a register. It's such a small optimization, I have to wonder if it makes a difference anywhere outside of benchmarks.

Re: Trying to get into protected mode, getting relocation er

Posted: Mon Jun 09, 2014 12:24 pm
by Owen
Octocontrabass wrote:
Bender wrote:Though I'd still say on a "hypothetical" machine where instructions are of the same length AND will be faster than XOR. (Even though negligible)
Every CPU I know of can do AND, XOR, ADD, and SUB in one cycle each. Your hypothetical CPU's clock speed would have to be very high for the propagation delay of a few transistors to warrant an extra cycle for one ALU operation over another. I'd really like to see your CPU in action!

On a side note, Sandy Bridge skips the ALU entirely if you're using SUB or XOR to zero a register. It's such a small optimization, I have to wonder if it makes a difference anywhere outside of benchmarks.
It renames out the register to the special zero rename-register and breaks the dependency chain. It's a pretty important one. They've been doing it for years.