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
ELF Bootloader
Re: ELF Bootloader
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.
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.
Re: ELF Bootloader
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.
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
Re: ELF Bootloader
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:
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.
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
}
}
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.
- Griwes
- 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
Yeah, it's unbelievable, especially since UEFI uses PE+...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.
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
<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
Re: ELF Bootloader
This will work until first disk defragmentation with making free space contiguous or until moving/copying/overwriting the file with bootloader.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.
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.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?