ELF Bootloader

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.
Post Reply
teodori
Member
Member
Posts: 103
Joined: Wed Nov 14, 2012 4:55 pm

ELF Bootloader

Post by teodori »

Hello everyone,
I have written a two stage bootloader, 1st stage loads sectors to memory then jumps to it, 2nd stage enables A20 and PMode. They are working very well, but both are in "binary" format and I want now to load an "elf32-i386" and jump to it. I imagine that a far jump won't be enough? Can anyone point me to the right direction? Thank you :)
User avatar
SparrowOS
Member
Member
Posts: 72
Joined: Wed Nov 14, 2012 5:22 pm
Location: Vegas
Contact:

Re: ELF Bootloader

Post by SparrowOS »

When faced with the problem of boot loaders for FAT32, EXT2, EXT3, EXT4, NTFS, Reiser, I had a brilliant idea! I'll write one bootloader that uses a fixed-block address and when I install my operating system, I'll patch the block address and make sure it is contiguous.

I also do a minimum in my bootloaders, pushing work forward to a place without a size limit. Why do work in a boot-loader that has a 512 byte limit?

I wrote my own compiler and made my own binary file format. It sucks the UEFI uses elf. You should see the crap they put into UEFI. Unbelievable.
teodori
Member
Member
Posts: 103
Joined: Wed Nov 14, 2012 4:55 pm

Re: ELF Bootloader

Post by teodori »

Yep,
here is my boot loader which successfully loads a 32 bit executable in binary format :) ,
but now I want to load an elf32-i386 from the second sector and I don't know how to make the entry.

Code: Select all

.section .rodata

bootmsg:
	.asciz "loading..."
bootmsgend:

bootmsglen:
	.word (bootmsgend - bootmsg)

errmsg:
	.asciz "disk error!"
errmsgend:

errmsglen:
	.word (errmsgend - errmsg)

gdt:
	# Null Descriptor at 0x0
	.word 0x0000
	.word 0x0000
	.byte 0x00
	.byte 0x00
	.byte 0x00
	.byte 0x00
	# Code Descriptor at 0x8
	.word 0xffff
	.word 0x0500
	.byte 0x00
	.byte 0x9a
	.byte 0xcf
	.byte 0x00
	# Data Descriptor at 0x10
	.word 0xffff
	.word 0x0500
	.byte 0x00
	.byte 0x92
	.byte 0xcf
	.byte 0x00
gdt_end:

gdtptr:
	.word (gdt_end - gdt - 1)
	.long gdt

.section .text

.globl Start

Start:
	.code16

SaveDriveNumber:
	movb %dl, 0x7bff			# Copy DL to memory 0x7bff

SetVideoMode:
	clrb %ah							# Set Video Mode
	movb $0x03, %al				# 3rd Mode -> 80x25
	int $0x10							# Video Interrupt

ClearScreen:
	movb $0x06, %ah				# Clear Screen
	clrb %al							# Lines to scroll (0 = clear -> CX & DX)
	movb $0x0f, %bh				# Color Black White
	clrw %cx							# Upper Left Corner
	movb $25, %dh					# 25 Lines
	movb $80, %dl					# 80 Columns
	int $0x10							# Video Interrupt

PrintBootMsg:
	clrw %ax							# Set AX to 0x0
	movw %ax, %es					# Set Extra Segment to 0x0
	movw $bootmsg, %bp		# Set base pointer to msg location

	movb $0x13, %ah				# Print String
	movb $0x01, %al				# Char only - Cursor moved
	clrb %bh							# Page Number
	movb $0x09, %bl				# Color Black Blue
	movw bootmsglen, %cx	# Message Length
	movb $1, %dh					# Row 1 
	movb $1, %dl					# Column 1
	int $0x10							# Video Interrupt

SetA20:
	cli										# Disable Interrupts
	inb $0x92, %al				# Enable A20 Gate
	testb	$0x2, %al				# to access to more than
	outb %al, $0x92				# 1 Mega Byte of memory
	sti										# Enable Interrupts

ResetDisk:
	clrb %ah							# Reset Disk
	movb 0x7bff, %dl			# Drive (from Memory Loacation)
	int $0x13							# Disk Interrupt

	jc PrintErrorMsg			# If CF set jump to PrintErrorMsg

LoadFromDisk:
	movw $0x0050, %ax			# Set AX to 0x0050
	movw %ax, %es					# Set Extra Segment to 0x0050

	movb $0x02, %ah				# Read Disk Sectors
	movb $0x01, %al				# Read one sector only (512 bytes per sector)
	clrw %bx							# Offset 0 - Start of Segment
	clrb %ch							# Track 0
	movb $0x02, %cl				# Sector 2
	clrb %dh							#	Head 0
	movb 0x7bff, %dl			# Drive (from Memory Loacation)
	int $0x13							# Disk Interrupt

	jc PrintErrorMsg			# If CF set jump to PrintErrorMsg

	cli										# Disable Interrupts

LoadGDT:
	lgdt gdtptr						# Load Global Descriptor Table

EnterProtectedMode:
	movl %cr0, %eax				# Read from Control Register CR0
	orl $1, %eax					# Set Protected Mode Bit
	movl %eax, %cr0				# Write to Control Register CR

SetupSelectors:
	movw $0x0010, %ax			# Selector 0x0010
	movw %ax, %ds					# Set Data Segment
	movw %ax, %es					# Set Extra Segment
	movw %ax, %fs					# Set Data2 Segment
	movw %ax, %gs					# Set Data3 Segment
	movw %ax, %ss					# Set Stack Segment

	ljmp $0x8, $0x0				# Far Jump

PrintErrorMsg:
	clrw %ax							# Set AX to 0x0
	movw %ax, %es					# Set Extra Segment to 0x0
	movw $errmsg, %bp			# Set base pointer to msg location

	movb $0x13, %ah				# Print String
	movb $0x01, %al				# Char only - Cursor moved
	clrb %bh							# Page Number
	movb $0x04, %bl				# Color Black Red
	movw errmsglen, %cx		# Message Length
	movb $3, %dh					# Row 3
	movb $1, %dl					# Column 1
	int $0x10							# Print Message

	cli										# Disable Interrupts

Hang:
	hlt										# Halt CPU
	jmp Hang							# Infinit loop if Halt does not work
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: ELF Bootloader

Post by bluemoon »

The minimum code to transfer control to a static linked elf-i386 file is getting the program entry field from the program header, this is an 32-bit number that located on fixed file offset.
That number will be in the form of virtual address, as specified by the linker script.
You can use that entry offset to translate to the actual memory location with a bit of calculations by:

Code: Select all

foreach "phdr struct" within ELF {
  if ( "entry point" within the region specified on this phdr ) {
    address = entry(VMA) - phdr(VMA) + phdr(offset) + file offset
  }
}
You may also need to adjust the address depends on where you actually load the elf file.

Grab a copy of the ELF_Format.pdf for detail.


ps. note that this method skipped a lot of things, it does not clear BSS, it assume the memory layout is the same as file layout, it assume BSS is on the end of file, etc - but it usually work as a simple loader, so you can go ahead working on the kernel and come back for a full loader later.
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: ELF Bootloader

Post by Griwes »

SparrowOS wrote:When faced with the problem of boot loaders for FAT32, EXT2, EXT3, EXT4, NTFS, Reiser, I had a brilliant idea! I'll write one bootloader that uses a fixed-block address and when I install my operating system, I'll patch the block address and make sure it is contiguous.

I also do a minimum in my bootloaders, pushing work forward to a place without a size limit. Why do work in a boot-loader that has a 512 byte limit?

I wrote my own compiler and made my own binary file format. It sucks the UEFI uses elf. You should see the crap they put into UEFI. Unbelievable.
Yeah, it's unbelievable, especially since UEFI uses PE+...
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
User avatar
Yoda
Member
Member
Posts: 255
Joined: Tue Mar 09, 2010 8:57 am
Location: Moscow, Russia

Re: ELF Bootloader

Post by Yoda »

SparrowOS wrote:When faced with the problem of boot loaders for FAT32, EXT2, EXT3, EXT4, NTFS, Reiser, I had a brilliant idea! I'll write one bootloader that uses a fixed-block address and when I install my operating system, I'll patch the block address and make sure it is contiguous.
This will work until first disk defragmentation with making free space contiguous or until moving/copying/overwriting the file with bootloader.
SparrowOS wrote:I also do a minimum in my bootloaders, pushing work forward to a place without a size limit. Why do work in a boot-loader that has a 512 byte limit?
Till now the space in boot areas of at least FAT12/16/32/NTFS/Ext2/3 file systems is quite enough in case of PC architecture to boot file placed in root directory and located anywhere in the disk, even beyond 2TB limit.
Yet Other Developer of Architecture.
OS Boot Tools.
Russian national OSDev forum.
Post Reply