Hmm, my code doesn't work.
Code: Select all
.ELFHeader:
mov DWORD [StartAddress], ebx
cmp BYTE [ebx+0], 0x7F
jne .NoELF
cmp BYTE [ebx+1], 'E'
jne .NoELF
cmp BYTE [ebx+2], 'L'
jne .NoELF
cmp BYTE [ebx+3], 'F'
jne .NoELF
cmp BYTE [ebx+4], 1
jne .UnsupportedELF
cmp BYTE [ebx+5], 1
jne .UnsupportedELF
cmp BYTE [ebx+6], 1
jne .UnsupportedELF
cmp WORD [ebx+16], 0x0002
jne .UnsupportedELF
cmp WORD [ebx+18], 0x3
jne .UnsupportedELF
cmp WORD [ebx+20], 1
jne .UnsupportedELF
jmp .ProgramHeadersInfo
Check the ELF header.
Code: Select all
.ProgramHeadersInfo:
xor eax, eax
mov eax, DWORD [ebx+28]
mov DWORD [phOffset], eax
xor eax, eax
mov ax, WORD [ebx+42]
mov WORD [phEntrySize], ax
xor eax, eax
mov ax, WORD [ebx+44]
mov WORD [phAmount], ax
cmp ax, 3
jng .ProgramHeaders
jmp .UnsupportedELF
Get information about the program headers...
Code: Select all
.NoELF:
xor ebx, ebx
mov ebx, msgNoELF
call PrintString
popa
ret
.UnsupportedELF:
xor ebx, ebx
mov ebx, msgUSELF
popa
ret
If the ELF is not an ELF or not for this platform or whatever...
Code: Select all
.ProgramHeaders:
xor ebx, ebx
mov ebx, DWORD [StartAddress]
add ebx, DWORD [phOffset]
xor eax, eax
mov ax, 1
cmp WORD [phAmount], ax
jge .PPH
jmp .PHMELF
Set ebx to the first entry of the program header table and check if there is at least 1 program header.
Code: Select all
.PHMELF
xor ebx, ebx
mov ebx, msgPHMELF
call PrintString
popa
ret
Tell the user that the ELF file has no program headers.
Code: Select all
.PPH:
xor eax, eax
mov eax, DWORD [ebx]
mov DWORD [pType1], eax
xor eax, eax
mov eax, DWORD [ebx+4]
mov DWORD [pOffset1], eax
xor eax, eax
mov eax, DWORD [ebx+8]
mov DWORD [pVirtAddr1], eax
xor eax, eax
mov eax, DWORD [ebx+16]
mov DWORD [pFileSize1], eax
xor eax, eax
mov eax, DWORD [ebx+20]
mov DWORD [pMemSize1], eax
xor eax, eax
mov ax, 2
cmp WORD [phAmount], ax
jge .SPH
jmp .PH1
.SPH:
add ebx, DWORD [phEntrySize]
xor eax, eax
mov eax, DWORD [ebx]
mov DWORD [pType2], eax
xor eax, eax
mov eax, DWORD [ebx+4]
mov DWORD [pOffset2], eax
xor eax, eax
mov eax, DWORD [ebx+8]
mov DWORD [pVirtAddr2], eax
xor eax, eax
mov eax, DWORD [ebx+16]
mov DWORD [pFileSize2], eax
xor eax, eax
mov eax, DWORD [ebx+20]
mov DWORD [pMemSize2], eax
xor eax, eax
mov ax, 3
cmp WORD [phAmount], ax
jge .TPH
jmp .PH1
.TPH:
add ebx, DWORD [phEntrySize]
xor eax, eax
mov eax, DWORD [ebx]
mov DWORD [pType3], eax
xor eax, eax
mov eax, DWORD [ebx+4]
mov DWORD [pOffset3], eax
xor eax, eax
mov eax, DWORD [ebx+8]
mov DWORD [pVirtAddr3], eax
xor eax, eax
mov eax, DWORD [ebx+16]
mov DWORD [pFileSize3], eax
xor eax, eax
mov eax, DWORD [ebx+20]
mov DWORD [pMemSize3], eax
jmp .PH1
Read out the 3 program headers, if there are 3...
Code: Select all
.PH1:
xor ebx, ebx
mov ebx, 1
cmp ebx, DWORD [pType1]
jne .PH2
xor eax, eax
xor ebx, ebx
mov ebx, DWORD [pVirtAddr1]
mov eax, DWORD [StartAddress]
add eax, DWORD [pOffset1]
xor ecx, ecx
mov ecx, DWORD [pFileSize1]
.PH1LOOP1:
xor edx, edx
mov dl, BYTE [eax]
mov BYTE [ebx], dl
inc ebx
inc eax
loop .PH1LOOP1
xor ecx, ecx
mov ecx, DWORD [pMemSize1]
sub ecx, DWORD [pFileSize1]
.PH1LOOP2:
xor edx, edx
mov dl, 0
mov BYTE [ebx], dl
inc ebx
loop .PH1LOOP2
.PH2:
xor ebx, ebx
mov ebx, 1
cmp ebx, DWORD [pType2]
jne .PH3
xor eax, eax
xor ebx, ebx
mov ebx, DWORD [pVirtAddr2]
mov eax, DWORD [StartAddress]
add eax, DWORD [pOffset2]
xor ecx, ecx
mov ecx, DWORD [pFileSize2]
.PH2LOOP1:
xor edx, edx
mov dl, BYTE [eax]
mov BYTE [ebx], dl
inc ebx
inc eax
loop .PH2LOOP1
xor ecx, ecx
mov ecx, DWORD [pMemSize2]
sub ecx, DWORD [pFileSize2]
.PH2LOOP2:
xor edx, edx
mov dl, 0
mov BYTE [ebx], dl
inc ebx
loop .PH2LOOP2
.PH3:
xor ebx, ebx
mov ebx, 1
cmp ebx, DWORD [pType3]
jne .ExecAddr
xor eax, eax
xor ebx, ebx
mov ebx, DWORD [pVirtAddr3]
mov eax, DWORD [StartAddress]
add eax, DWORD [pOffset3]
xor ecx, ecx
mov ecx, DWORD [pFileSize3]
.PH3LOOP1:
xor edx, edx
mov dl, BYTE [eax]
mov BYTE [ebx], dl
inc ebx
inc eax
loop .PH3LOOP1
xor ecx, ecx
mov ecx, DWORD [pMemSize3]
sub ecx, DWORD [pFileSize3]
.PH3LOOP2:
xor edx, edx
mov dl, 0
mov BYTE [ebx], dl
inc ebx
loop .PH3LOOP2
Reallocate the segments and fill out the rest of memory with zeroes (if memsize is greater than the filesize).
Code: Select all
.ExecAddr
xor ebx, ebx
mov ebx, msgELF
call PrintString
xor ebx, ebx
mov ebx, DWORD [StartAddress]
jmp .Parsed
Set ebx back to the startaddress... (Maybe it should be the entry address instead of the start address given)
Parsing complete, return...
Jump to ebx to execute the kernel. (if the kernel is at ebx else it will triple fault or something)
Code: Select all
StartKernel:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 0x90000
call ClearScreen
mov ebx, 0x100000
call ParseKernel
call ExecuteKernel
cli
hlt
This is the code when the second stage went to 32-bit.
Code: Select all
StartAddress DD 0x00000000
phOffset DD 0x00000000
phEntrySize DW 0x0000
phAmount DW 0x0000
phCurrentEntry DW 0x0000
pType1 DD 0x00000000
pType2 DD 0x00000000
pType3 DD 0x00000000
pOffset1 DD 0x00000000
pOffset2 DD 0x00000000
pOffset3 DD 0x00000000
pVirtAddr1 DD 0x00000000
pVirtAddr2 DD 0x00000000
pVirtAddr3 DD 0x00000000
pFileSize1 DD 0x00000000
pFileSize2 DD 0x00000000
pFileSize3 DD 0x00000000
pMemSize1 DD 0x00000000
pMemSize2 DD 0x00000000
pMemSize3 DD 0x00000000
The variables...
The only thing what could be wrong in my eyes is the startaddress moved to ebx when returning if the code is not wrong...
Are there some mistakes?
Sorry for the big code...
Thanks already,
Stephan van Schaik.