37,12 → 37,9 |
stack_size dd ? |
exe_path dd ? |
command_line dd ? |
environment dd ? |
ends |
|
include 'malloc.inc' |
include 'peloader.inc' |
include 'cmdline.inc' |
|
proc syscall_int40 |
int 0x40 |
49,24 → 46,6 |
ret |
endp |
|
proc syscall_sysenter |
push ebp |
mov ebp, esp |
push @f |
sysenter |
@@: |
pop edx |
pop ecx |
ret |
endp |
|
proc syscall_syscall |
push ecx |
syscall |
pop ecx |
ret |
endp |
|
proc kercall |
jmp FS_SYSCALL_PTR |
endp |
75,52 → 54,27 |
epilogue@proc equ fpo_epilogue |
|
proc start stdcall, dll_base, reason, reserved |
locals |
exe_base dd ? |
exe_path_size dd ? |
endl |
; 1. Do nothing unless called by the kernel for DLL_PROCESS_ATTACH. |
cmp [reason], DLL_PROCESS_ATTACH |
jnz .nothing |
; 2. Initialize process. |
; 2a. Validate version of the init struct. |
; 2. Validate version of the init struct. |
; If not known, say a debug message and die. |
mov ebp, [reserved] |
mov esi, [dll_base] |
cmp [ebp+kernel_init_data.version], 1 |
jnz .version_mismatch |
; 2b. Get the system call code. |
; Note: relocations have not been fixed yet, |
; so we cannot use absolute addresses, only RVAs. |
; 3. Setup common data based on the init struct. |
mov eax, [ebp+kernel_init_data.stack_base] |
mov FS_STACK_MIN, eax |
add eax, [ebp+kernel_init_data.stack_size] |
mov FS_STACK_MAX, eax |
mov eax, [ebp+kernel_init_data.syscall_method] |
cmp eax, 0x10000 |
jae .syscall_absolute |
dec eax |
mov edx, rva syscall_int40 |
cmp eax, num_syscall_methods |
jae @f |
mov edx, [esi+eax*4+rva syscall_methods] |
mov eax, syscall_int40 |
@@: |
lea eax, [edx+esi] |
.syscall_absolute: |
mov FS_SYSCALL_PTR, eax |
; 2c. Fixup relocations so that we can use absolute offsets instead of RVAs |
; in rest of code. |
; Note: this uses syscalls, so this step should be done after |
; configuring FS_SYSCALL_PTR at step 2b. |
push kolibri_dll |
call fixup_pe_relocations |
pop ecx |
jc .die |
; 2d. Allocate process data. |
mov eax, 68 |
mov ebx, 12 |
mov ecx, 0x1000 |
call FS_SYSCALL_PTR |
mov FS_PROCESS_DATA, eax |
; 2e. Initialize process heap. |
; 4. Initialize the process heap. |
mov eax, [ebp+kernel_init_data.exe_base] |
mov [exe_base], eax |
mov edx, [eax+STRIPPED_PE_HEADER.SizeOfHeapReserve] |
cmp word [eax], 'MZ' |
jnz @f |
128,107 → 82,40 |
mov edx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeapReserve] |
@@: |
malloc_init |
; 2f. Copy rest of init struct and free memory. |
; Parse command line to argc/argv here and move arguments to the heap |
; in order to save memory: init struct and heap use different pages, |
; but typically data from init struct are far from the entire page, |
; so moving it to heap does not increase actual physical heap size |
; and allows to free init struct. |
mov eax, [ebp+kernel_init_data.stack_base] |
mov FS_STACK_MIN, eax |
add eax, [ebp+kernel_init_data.stack_size] |
mov FS_STACK_MAX, eax |
mov eax, [ebp+kernel_init_data.exe_path] |
@@: |
inc eax |
cmp byte [eax-1], 0 |
jnz @b |
sub eax, [ebp+kernel_init_data.exe_path] |
mov [exe_path_size], eax |
mov esi, [ebp+kernel_init_data.command_line] |
xor edx, edx |
xor edi, edi |
call parse_cmdline |
inc ebx ; argv[0] = exe path |
.argc equ dll_base |
.argv equ reason |
.envp equ reserved |
mov [.argc], ebx |
sub esi, [ebp+kernel_init_data.command_line] |
lea esi, [esi+(ebx+1)*4] |
add esi, [exe_path_size] |
stdcall malloc, esi |
mov [.argv], eax |
mov edx, eax |
lea edi, [eax+ebx*4] |
mov esi, [ebp+kernel_init_data.exe_path] |
mov [edx], edi |
add edx, 4 |
mov ecx, [exe_path_size] |
rep movsb |
mov esi, [ebp+kernel_init_data.command_line] |
call parse_cmdline |
and dword [edx], 0 ; argv[argc] = NULL |
and [.envp], 0 |
mov eax, 68 |
mov ebx, 13 |
mov ecx, ebp |
call FS_SYSCALL_PTR |
; 3. Configure modules: main EXE and possible statically linked DLLs. |
mov esi, [exe_base] |
mov eax, [.argv] |
pushd [eax] |
call fixup_pe_relocations |
pop ecx |
jc .die |
; 4. Call exe entry point. |
mov edx, [esi+STRIPPED_PE_HEADER.AddressOfEntryPoint] |
cmp word [esi], 'MZ' |
; ...TBD... |
; Call exe entry point. |
mov eax, [ebp+kernel_init_data.exe_base] |
mov edx, [eax+STRIPPED_PE_HEADER.AddressOfEntryPoint] |
cmp word [eax], 'MZ' |
jnz @f |
mov ecx, [esi+IMAGE_DOS_HEADER.e_lfanew] |
add ecx, esi |
mov ecx, [eax+IMAGE_DOS_HEADER.e_lfanew] |
add ecx, eax |
mov edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint] |
@@: |
add edx, esi |
add esp, fpo_localsize+4 |
add edx, eax |
call edx |
; If exe entry point has returned control, die. |
jmp .die |
mov eax, -1 |
call FS_SYSCALL_PTR |
.version_mismatch: |
lea eax, [esi + rva syscall_int40] |
mov FS_SYSCALL_PTR, eax |
add esi, rva msg_version_mismatch |
call sys_msg_board_str |
.die: |
or eax, -1 |
call FS_SYSCALL_PTR |
.nothing: |
ret |
endp |
|
proc sys_msg_board_str |
push eax ebx |
mov esi, version_mismatch_msg |
mov eax, 63 |
mov ebx, 1 |
@@: |
push ecx |
mov cl, [ecx] |
mov cl, [esi] |
test cl, cl |
jz @f |
mov eax, 63 |
mov ebx, 1 |
call FS_SYSCALL_PTR |
pop ecx |
inc ecx |
int 0x40 ; can't use FS_SYSCALL_PTR here, it has not yet been set |
inc esi |
jmp @b |
@@: |
pop ecx ebx eax |
mov eax, -1 |
int 0x40 |
.nothing: |
ret |
endp |
|
align 4 |
syscall_methods dd rva syscall_int40, rva syscall_sysenter, rva syscall_syscall |
num_syscall_methods = ($ - syscall_methods) / 4 |
|
align 4 |
data export |
export 'kolibri.dll' \ |
, kercall, 'kercall' \ |
249,14 → 136,8 |
|
end data |
|
kolibri_dll db 'kolibri.dll',0 |
version_mismatch_msg db 'Version mismatch between kernel and kolibri.dll',13,10,0 |
|
msg_version_mismatch db 'S : Version mismatch between kernel and kolibri.dll',13,10,0 |
msg_bad_relocation1 db 'S : Bad relocation type in ',0 |
msg_newline db 13,10,0 |
msg_relocated1 db 'S : fixups for ',0 |
msg_relocated2 db ' applied',13,10,0 |
|
if FOOTERS |
section '.data' data readable writable |
malloc_magic dd ? |