forked from KolibriOS/kolibrios
Magomed Kostoev (mkostoevr)
eccd8f2198
git-svn-id: svn://kolibrios.org@9048 a494cfbc-eb01-0410-851d-a64ba20cac60
1217 lines
27 KiB
PHP
1217 lines
27 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License. ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision$
|
|
|
|
|
|
DRV_COMPAT = 5 ;minimal required drivers version
|
|
DRV_CURRENT = 6 ;current drivers model version
|
|
|
|
DRV_VERSION = (DRV_COMPAT shl 16) or DRV_CURRENT
|
|
PID_KERNEL = 1 ;os_idle thread
|
|
|
|
|
|
|
|
align 4
|
|
proc get_notify stdcall, p_ev:dword
|
|
|
|
.wait:
|
|
mov ebx, [current_slot]
|
|
test dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
|
|
jz @f
|
|
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
|
|
mov edi, [p_ev]
|
|
mov dword [edi], EV_INTR
|
|
mov eax, [ebx+APPDATA.event]
|
|
mov dword [edi+4], eax
|
|
ret
|
|
@@:
|
|
call change_task
|
|
jmp .wait
|
|
endp
|
|
|
|
align 4
|
|
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 6
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
call pci_read_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 5
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
call pci_read_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 4
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
call pci_read_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 8
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
mov ecx, [val]
|
|
call pci_write_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 9
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
mov ecx, [val]
|
|
call pci_write_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
|
|
push ebx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
mov ah, byte [bus]
|
|
mov al, 10
|
|
mov bh, byte [devfn]
|
|
mov bl, byte [reg]
|
|
mov ecx, [val]
|
|
call pci_write_reg
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
handle equ IOCTL.handle
|
|
io_code equ IOCTL.io_code
|
|
input equ IOCTL.input
|
|
inp_size equ IOCTL.inp_size
|
|
output equ IOCTL.output
|
|
out_size equ IOCTL.out_size
|
|
|
|
|
|
align 4
|
|
proc srv_handler stdcall, ioctl:dword
|
|
mov esi, [ioctl]
|
|
test esi, esi
|
|
jz .err
|
|
|
|
mov edi, [esi+handle]
|
|
cmp [edi+SRV.magic], ' SRV'
|
|
jne .fail
|
|
|
|
cmp [edi+SRV.size], sizeof.SRV
|
|
jne .fail
|
|
|
|
; stdcall [edi+SRV.srv_proc], esi
|
|
mov eax, [edi+SRV.srv_proc]
|
|
test eax, eax
|
|
jz .fail
|
|
stdcall eax, esi
|
|
ret
|
|
.fail:
|
|
xor eax, eax
|
|
not eax
|
|
mov [esi+output], eax
|
|
mov [esi+out_size], 4
|
|
ret
|
|
.err:
|
|
xor eax, eax
|
|
not eax
|
|
ret
|
|
endp
|
|
|
|
; param
|
|
; ecx= io_control
|
|
;
|
|
; retval
|
|
; eax= error code
|
|
|
|
align 4
|
|
srv_handlerEx:
|
|
cmp ecx, OS_BASE
|
|
jae .fail
|
|
|
|
mov eax, [ecx+handle]
|
|
cmp [eax+SRV.magic], ' SRV'
|
|
jne .fail
|
|
|
|
cmp [eax+SRV.size], sizeof.SRV
|
|
jne .fail
|
|
|
|
; stdcall [eax+SRV.srv_proc], ecx
|
|
mov eax, [eax+SRV.srv_proc]
|
|
test eax, eax
|
|
jz .fail
|
|
stdcall eax, ecx
|
|
ret
|
|
.fail:
|
|
or eax, -1
|
|
ret
|
|
|
|
restore handle
|
|
restore io_code
|
|
restore input
|
|
restore inp_size
|
|
restore output
|
|
restore out_size
|
|
|
|
align 4
|
|
proc get_service stdcall, sz_name:dword
|
|
mov eax, [sz_name]
|
|
test eax, eax
|
|
jnz @F
|
|
ret
|
|
@@:
|
|
mov edx, [srv.fd]
|
|
@@:
|
|
cmp edx, srv.fd-SRV.fd
|
|
je .not_load
|
|
|
|
stdcall strncmp, edx, [sz_name], 16
|
|
test eax, eax
|
|
mov eax, edx
|
|
je .nothing
|
|
|
|
mov edx, [edx+SRV.fd]
|
|
jmp @B
|
|
.not_load:
|
|
mov eax, [sz_name]
|
|
push edi
|
|
sub esp, 36
|
|
mov edi, esp
|
|
mov dword [edi], '/sys'
|
|
mov dword [edi+4], '/dri'
|
|
mov dword [edi+8], 'vers'
|
|
mov byte [edi+12], '/'
|
|
@@:
|
|
mov dl, [eax]
|
|
mov [edi+13], dl
|
|
inc eax
|
|
inc edi
|
|
test dl, dl
|
|
jnz @b
|
|
mov dword [edi+12], '.sys'
|
|
mov byte [edi+16], 0
|
|
mov edi, esp
|
|
stdcall load_pe_driver, edi, 0
|
|
add esp, 36
|
|
pop edi
|
|
.nothing:
|
|
ret
|
|
endp
|
|
|
|
reg_service:
|
|
xor eax, eax
|
|
mov ecx, [esp+8]
|
|
jecxz .nothing
|
|
push sizeof.SRV
|
|
push ecx
|
|
pushd [esp+12]
|
|
call reg_service_ex
|
|
.nothing:
|
|
ret 8
|
|
|
|
reg_usb_driver:
|
|
push sizeof.USBSRV
|
|
pushd [esp+12]
|
|
pushd [esp+12]
|
|
call reg_service_ex
|
|
test eax, eax
|
|
jz .nothing
|
|
mov ecx, [esp+12]
|
|
mov [eax+USBSRV.usb_func], ecx
|
|
.nothing:
|
|
ret 12
|
|
|
|
proc reg_service_ex stdcall, name:dword, handler:dword, srvsize:dword
|
|
|
|
push ebx
|
|
|
|
xor eax, eax
|
|
|
|
cmp [name], eax
|
|
je .fail
|
|
|
|
; cmp [handler], eax
|
|
; je .fail
|
|
|
|
mov eax, [srvsize]
|
|
call malloc
|
|
test eax, eax
|
|
jz .fail
|
|
|
|
push esi
|
|
push edi
|
|
mov edi, eax
|
|
mov esi, [name]
|
|
movsd
|
|
movsd
|
|
movsd
|
|
movsd
|
|
pop edi
|
|
pop esi
|
|
|
|
mov [eax+SRV.magic], ' SRV'
|
|
mov [eax+SRV.size], sizeof.SRV
|
|
|
|
mov ebx, srv.fd-SRV.fd
|
|
mov edx, [ebx+SRV.fd]
|
|
mov [eax+SRV.fd], edx
|
|
mov [eax+SRV.bk], ebx
|
|
mov [ebx+SRV.fd], eax
|
|
mov [edx+SRV.bk], eax
|
|
|
|
mov ecx, [handler]
|
|
mov [eax+SRV.srv_proc], ecx
|
|
pop ebx
|
|
ret
|
|
.fail:
|
|
xor eax, eax
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc get_proc stdcall, exp:dword, sz_name:dword
|
|
|
|
mov edx, [exp]
|
|
.next:
|
|
mov eax, [edx]
|
|
test eax, eax
|
|
jz .end
|
|
|
|
push edx
|
|
stdcall strncmp, eax, [sz_name], 16
|
|
pop edx
|
|
test eax, eax
|
|
jz .ok
|
|
|
|
add edx, 8
|
|
jmp .next
|
|
.ok:
|
|
mov eax, [edx+4]
|
|
.end:
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
|
|
|
|
@@:
|
|
stdcall strncmp, [pSym], [sz_sym], 8
|
|
test eax, eax
|
|
jz .ok
|
|
add [pSym], 18
|
|
dec [count]
|
|
jnz @b
|
|
xor eax, eax
|
|
ret
|
|
.ok:
|
|
mov eax, [pSym]
|
|
mov eax, [eax+8]
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc get_curr_task
|
|
mov eax, [current_slot_idx]
|
|
shl eax, 8
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc get_fileinfo stdcall, file_name:dword, info:dword
|
|
locals
|
|
cmd dd ?
|
|
offset dd ?
|
|
dd ?
|
|
count dd ?
|
|
buff dd ?
|
|
db ?
|
|
name dd ?
|
|
endl
|
|
|
|
xor eax, eax
|
|
mov ebx, [file_name]
|
|
mov ecx, [info]
|
|
|
|
mov [cmd], 5
|
|
mov [offset], eax
|
|
mov [offset+4], eax
|
|
mov [count], eax
|
|
mov [buff], ecx
|
|
mov byte [buff+4], al
|
|
mov [name], ebx
|
|
|
|
mov eax, 70
|
|
lea ebx, [cmd]
|
|
pushad
|
|
cld
|
|
call protect_from_terminate
|
|
call file_system_lfn
|
|
call unprotect_from_terminate
|
|
popad
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
|
|
bytes:dword
|
|
locals
|
|
cmd dd ?
|
|
offset dd ?
|
|
dd ?
|
|
count dd ?
|
|
buff dd ?
|
|
db ?
|
|
name dd ?
|
|
endl
|
|
|
|
xor eax, eax
|
|
mov ebx, [file_name]
|
|
mov ecx, [off]
|
|
mov edx, [bytes]
|
|
mov esi, [buffer]
|
|
|
|
mov [cmd], eax
|
|
mov [offset], ecx
|
|
mov [offset+4], eax
|
|
mov [count], edx
|
|
mov [buff], esi
|
|
mov byte [buff+4], al
|
|
mov [name], ebx
|
|
|
|
pushad
|
|
lea ebx, [cmd]
|
|
call file_system_lfn_protected
|
|
popad
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
; @brief Allocate kernel memory and loads the specified file
|
|
;
|
|
; @param file_name Path to file
|
|
;
|
|
; @returns File image in kernel memory in `eax` and size of file in `ebx`
|
|
;
|
|
; @warning You must call kernel_free() to delete each file loaded by the
|
|
; load_file() function
|
|
proc load_file stdcall, file_name:dword
|
|
locals
|
|
attr dd ?
|
|
flags dd ?
|
|
cr_time dd ?
|
|
cr_date dd ?
|
|
acc_time dd ?
|
|
acc_date dd ?
|
|
mod_time dd ?
|
|
mod_date dd ?
|
|
file_size dd ?
|
|
|
|
file dd ?
|
|
file2 dd ?
|
|
endl
|
|
|
|
push esi
|
|
push edi
|
|
|
|
lea eax, [attr]
|
|
stdcall get_fileinfo, [file_name], eax
|
|
test eax, eax
|
|
jnz .fail
|
|
|
|
mov eax, [file_size]
|
|
cmp eax, 1024*1024*16
|
|
ja .fail
|
|
|
|
stdcall kernel_alloc, [file_size]
|
|
mov [file], eax
|
|
test eax, eax
|
|
jz .fail
|
|
|
|
stdcall read_file, [file_name], eax, dword 0, [file_size]
|
|
cmp ebx, [file_size]
|
|
jne .cleanup
|
|
|
|
mov eax, [file]
|
|
cmp dword [eax], 'KPCK'
|
|
jne .exit
|
|
mov ebx, [eax+4]
|
|
mov [file_size], ebx
|
|
stdcall kernel_alloc, ebx
|
|
|
|
test eax, eax
|
|
jz .cleanup
|
|
|
|
mov [file2], eax
|
|
|
|
pushad
|
|
mov ecx, unpack_mutex
|
|
call mutex_lock
|
|
popad
|
|
|
|
stdcall unpack, [file], eax
|
|
|
|
pushad
|
|
mov ecx, unpack_mutex
|
|
call mutex_unlock
|
|
popad
|
|
|
|
stdcall kernel_free, [file]
|
|
mov eax, [file2]
|
|
mov ebx, [file_size]
|
|
.exit:
|
|
push eax
|
|
lea edi, [eax+ebx] ;cleanup remain space
|
|
mov ecx, 4096 ;from file end
|
|
and ebx, 4095
|
|
jz @f
|
|
sub ecx, ebx
|
|
xor eax, eax
|
|
cld
|
|
rep stosb
|
|
@@:
|
|
mov ebx, [file_size]
|
|
pop eax
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
.cleanup:
|
|
stdcall kernel_free, [file]
|
|
.fail:
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
endp
|
|
|
|
; description
|
|
; allocate user memory and loads the specified file
|
|
;
|
|
; param
|
|
; file_name= path to file
|
|
;
|
|
; retval
|
|
; eax= file image in user memory
|
|
; ebx= size of file
|
|
;
|
|
; warging
|
|
; You mast call kernel_free() to delete each file
|
|
; loaded by the load_file() function
|
|
|
|
align 4
|
|
proc load_file_umode stdcall, file_name:dword
|
|
locals
|
|
attr dd ?
|
|
flags dd ?
|
|
cr_time dd ?
|
|
cr_date dd ?
|
|
acc_time dd ?
|
|
acc_date dd ?
|
|
mod_time dd ?
|
|
mod_date dd ?
|
|
file_size dd ?
|
|
|
|
km_file dd ?
|
|
um_file dd ?
|
|
endl
|
|
|
|
push esi
|
|
push edi
|
|
push ebx
|
|
|
|
lea eax, [attr]
|
|
stdcall get_fileinfo, [file_name], eax ;find file and get info
|
|
test eax, eax
|
|
jnz .err_1
|
|
|
|
mov eax, [file_size]
|
|
cmp eax, 1024*1024*16 ;to be enough for anybody (c)
|
|
ja .err_1
|
|
;it is very likely that the file is packed
|
|
stdcall kernel_alloc, [file_size] ;with kpack, so allocate memory from kernel heap
|
|
mov [km_file], eax
|
|
test eax, eax
|
|
jz .err_1
|
|
|
|
stdcall read_file, [file_name], eax, dword 0, [file_size]
|
|
cmp ebx, [file_size]
|
|
|
|
jne .err_2
|
|
|
|
mov eax, [km_file]
|
|
cmp dword [eax], 'KPCK' ; check kpack signature
|
|
jne .raw_file
|
|
|
|
mov ebx, [eax+4] ;get real size of file
|
|
mov [file_size], ebx
|
|
stdcall user_alloc, ebx ;and allocate space from user heap
|
|
mov [um_file], eax
|
|
test eax, eax
|
|
jz .err_2
|
|
|
|
mov edx, [file_size] ;preallocate page memory
|
|
shr eax, 10
|
|
lea edi, [page_tabs+eax]
|
|
add edx, 4095
|
|
shr edx, 12
|
|
@@:
|
|
call alloc_page
|
|
test eax, eax
|
|
jz .err_3
|
|
|
|
or eax, PG_UWR
|
|
stosd
|
|
dec edx
|
|
jnz @B
|
|
|
|
pushad
|
|
mov ecx, unpack_mutex
|
|
call mutex_lock
|
|
|
|
stdcall unpack, [km_file], [um_file]
|
|
|
|
mov ecx, unpack_mutex
|
|
call mutex_unlock
|
|
popad
|
|
|
|
stdcall kernel_free, [km_file] ;we don't need packed file anymore
|
|
.exit:
|
|
|
|
mov edi, [um_file]
|
|
mov esi, [um_file]
|
|
mov eax, [file_size]
|
|
mov edx, eax
|
|
|
|
add edi, eax ;cleanup remain space
|
|
mov ecx, 4096 ;from file end
|
|
and eax, 4095
|
|
jz @f
|
|
sub ecx, eax
|
|
xor eax, eax
|
|
cld
|
|
rep stosb
|
|
@@:
|
|
mov eax, [um_file]
|
|
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
|
|
.raw_file: ; sometimes we load unpacked file
|
|
stdcall user_alloc, ebx ; allocate space from user heap
|
|
mov [um_file], eax
|
|
|
|
test eax, eax
|
|
jz .err_2
|
|
|
|
shr eax, 10 ; and remap pages.
|
|
|
|
mov ecx, [file_size]
|
|
add ecx, 4095
|
|
shr ecx, 12
|
|
|
|
mov esi, [km_file]
|
|
shr esi, 10
|
|
add esi, page_tabs
|
|
|
|
lea edi, [page_tabs+eax]
|
|
|
|
cld
|
|
@@:
|
|
lodsd
|
|
and eax, 0xFFFFF000
|
|
or eax, PG_UWR
|
|
stosd
|
|
loop @B
|
|
|
|
stdcall free_kernel_space, [km_file] ; release allocated kernel space
|
|
jmp .exit ; physical pages still in use
|
|
.err_3:
|
|
stdcall user_free, [um_file]
|
|
.err_2:
|
|
stdcall kernel_free, [km_file]
|
|
.err_1:
|
|
xor eax, eax
|
|
xor edx, edx
|
|
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
endp
|
|
|
|
|
|
uglobal
|
|
align 4
|
|
unpack_mutex MUTEX
|
|
endg
|
|
|
|
align 4
|
|
proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
|
|
mov ebx, [imports]
|
|
test ebx, ebx
|
|
jz .end
|
|
xor esi, esi
|
|
.look_up:
|
|
|
|
mov eax, [ebx+32]
|
|
mov eax, [OS_BASE+eax+esi*4]
|
|
add eax, OS_BASE
|
|
stdcall strncmp, eax, [proc_name], 256
|
|
test eax, eax
|
|
jz .ok
|
|
|
|
inc esi
|
|
cmp esi, [ebx+24]
|
|
jb .look_up
|
|
.end:
|
|
xor eax, eax
|
|
ret
|
|
.ok:
|
|
mov eax, [ebx+28]
|
|
mov eax, [OS_BASE+eax+esi*4]
|
|
add eax, OS_BASE
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
|
|
sym_count:dword, strings:dword, imports:dword
|
|
locals
|
|
retval dd ?
|
|
endl
|
|
|
|
mov edi, [symbols]
|
|
mov [retval], 1
|
|
.fix:
|
|
movzx ebx, [edi+COFF_SYM.SectionNumber]
|
|
test ebx, ebx
|
|
jnz .internal
|
|
mov eax, dword [edi+COFF_SYM.Name]
|
|
test eax, eax
|
|
jnz @F
|
|
|
|
mov edi, [edi+4]
|
|
add edi, [strings]
|
|
@@:
|
|
push edi
|
|
stdcall get_proc_ex, edi, [imports]
|
|
pop edi
|
|
|
|
xor ebx, ebx
|
|
test eax, eax
|
|
jnz @F
|
|
|
|
; disable debug msg
|
|
;mov esi, msg_unresolved
|
|
;call sys_msg_board_str
|
|
;mov esi, edi
|
|
;call sys_msg_board_str
|
|
;mov esi, msg_CR
|
|
;call sys_msg_board_str
|
|
|
|
mov [retval], 0
|
|
@@:
|
|
mov edi, [symbols]
|
|
mov [edi+COFF_SYM.Value], eax
|
|
jmp .next
|
|
.internal:
|
|
cmp bx, -1
|
|
je .next
|
|
cmp bx, -2
|
|
je .next
|
|
|
|
dec ebx
|
|
shl ebx, 3
|
|
lea ebx, [ebx+ebx*4]
|
|
add ebx, [sec]
|
|
|
|
mov eax, [ebx+COFF_SECTION.VirtualAddress]
|
|
add [edi+COFF_SYM.Value], eax
|
|
.next:
|
|
add edi, sizeof.COFF_SYM
|
|
mov [symbols], edi
|
|
dec [sym_count]
|
|
jnz .fix
|
|
mov eax, [retval]
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
|
|
delta:dword
|
|
locals
|
|
n_sec dd ?
|
|
endl
|
|
|
|
mov eax, [coff]
|
|
movzx ebx, [eax+COFF_HEADER.nSections]
|
|
mov [n_sec], ebx
|
|
lea esi, [eax+20]
|
|
.fix_sec:
|
|
mov edi, [esi+COFF_SECTION.PtrReloc]
|
|
add edi, [coff]
|
|
|
|
movzx ecx, [esi+COFF_SECTION.NumReloc]
|
|
test ecx, ecx
|
|
jz .next
|
|
.reloc_loop:
|
|
mov ebx, [edi+COFF_RELOC.SymIndex]
|
|
add ebx, ebx
|
|
lea ebx, [ebx+ebx*8]
|
|
add ebx, [sym]
|
|
|
|
mov edx, [ebx+COFF_SYM.Value]
|
|
|
|
cmp [edi+COFF_RELOC.Type], 6
|
|
je .dir_32
|
|
|
|
cmp [edi+COFF_RELOC.Type], 20
|
|
jne .next_reloc
|
|
.rel_32:
|
|
mov eax, [edi+COFF_RELOC.VirtualAddress]
|
|
add eax, [esi+COFF_SECTION.VirtualAddress]
|
|
sub edx, eax
|
|
sub edx, 4
|
|
jmp .fix
|
|
.dir_32:
|
|
mov eax, [edi+COFF_RELOC.VirtualAddress]
|
|
add eax, [esi+COFF_SECTION.VirtualAddress]
|
|
.fix:
|
|
add eax, [delta]
|
|
add [eax], edx
|
|
.next_reloc:
|
|
add edi, 10
|
|
dec ecx
|
|
jnz .reloc_loop
|
|
.next:
|
|
add esi, sizeof.COFF_SECTION
|
|
dec [n_sec]
|
|
jnz .fix_sec
|
|
.exit:
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
|
|
delta:dword
|
|
locals
|
|
n_sec dd ?
|
|
endl
|
|
|
|
mov eax, [coff]
|
|
movzx ebx, [eax+COFF_HEADER.nSections]
|
|
mov [n_sec], ebx
|
|
lea esi, [eax+20]
|
|
mov edx, [delta]
|
|
.fix_sec:
|
|
mov edi, [esi+COFF_SECTION.PtrReloc]
|
|
add edi, [coff]
|
|
|
|
movzx ecx, [esi+COFF_SECTION.NumReloc]
|
|
test ecx, ecx
|
|
jz .next
|
|
.reloc_loop:
|
|
cmp [edi+COFF_RELOC.Type], 6
|
|
jne .next_reloc
|
|
.dir_32:
|
|
mov eax, [edi+COFF_RELOC.VirtualAddress]
|
|
add eax, [esi+COFF_SECTION.VirtualAddress]
|
|
add [eax+edx], edx
|
|
.next_reloc:
|
|
add edi, 10
|
|
dec ecx
|
|
jnz .reloc_loop
|
|
.next:
|
|
add esi, sizeof.COFF_SECTION
|
|
dec [n_sec]
|
|
jnz .fix_sec
|
|
.exit:
|
|
ret
|
|
endp
|
|
|
|
; in: edx -> COFF_SECTION struct
|
|
; out: eax = alignment as mask for bits to drop
|
|
coff_get_align:
|
|
; Rules:
|
|
; - if alignment is not given, use default = 4K;
|
|
; - if alignment is given and is no more than 4K, use it;
|
|
; - if alignment is more than 4K, revert to 4K.
|
|
push ecx
|
|
mov cl, byte [edx+COFF_SECTION.Characteristics+2]
|
|
mov eax, 1
|
|
shr cl, 4
|
|
dec cl
|
|
js .default
|
|
cmp cl, 12
|
|
jbe @f
|
|
.default:
|
|
mov cl, 12
|
|
@@:
|
|
shl eax, cl
|
|
pop ecx
|
|
dec eax
|
|
ret
|
|
|
|
align 4
|
|
proc load_library stdcall, file_name:dword, encoding:dword
|
|
locals
|
|
fullname dd ?
|
|
filesize dd ?
|
|
coff dd ?
|
|
img_base dd ?
|
|
img_size dd ?
|
|
symbols_ptr dd ?
|
|
symbols_lim dd ?
|
|
exports dd ?
|
|
endl
|
|
|
|
; resolve file name
|
|
stdcall kernel_alloc, maxPathLength
|
|
mov [fullname], eax
|
|
mov edi, eax
|
|
mov esi, [file_name]
|
|
mov eax, [encoding]
|
|
push ebp
|
|
call getFullPath
|
|
pop ebp
|
|
test eax, eax
|
|
jz .fail
|
|
|
|
; load file
|
|
stdcall load_file, [fullname]
|
|
test eax, eax
|
|
jz .fail
|
|
mov [coff], eax
|
|
mov [filesize], ebx
|
|
|
|
; calculate size of loaded DLL
|
|
movzx ecx, [eax+COFF_HEADER.nSections]
|
|
xor ebx, ebx
|
|
|
|
lea edx, [eax+20]
|
|
@@:
|
|
call coff_get_align
|
|
add ebx, eax
|
|
not eax
|
|
and ebx, eax
|
|
add ebx, [edx+COFF_SECTION.SizeOfRawData]
|
|
add edx, sizeof.COFF_SECTION
|
|
dec ecx
|
|
jnz @B
|
|
; it must be nonzero and not too big
|
|
mov [img_size], ebx
|
|
test ebx, ebx
|
|
jz .fail_and_free_coff
|
|
cmp ebx, 0x10000000
|
|
ja .fail_and_free_coff
|
|
; allocate memory
|
|
call init_heap
|
|
stdcall user_alloc, [img_size]
|
|
test eax, eax
|
|
jz .fail_and_free_coff
|
|
mov [img_base], eax
|
|
|
|
; copy sections and set correct values for VirtualAddress'es in headers
|
|
mov edx, [coff]
|
|
movzx ebx, [edx+COFF_HEADER.nSections]
|
|
mov edi, eax
|
|
add edx, 20
|
|
cld
|
|
@@:
|
|
call coff_get_align
|
|
add edi, eax
|
|
not eax
|
|
and edi, eax
|
|
mov [edx+COFF_SECTION.VirtualAddress], edi
|
|
mov esi, [edx+COFF_SECTION.PtrRawData]
|
|
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
|
|
test esi, esi
|
|
jnz .copy
|
|
xor eax, eax
|
|
rep stosb
|
|
jmp .next
|
|
.copy:
|
|
add esi, [coff]
|
|
rep movsb
|
|
.next:
|
|
add edx, sizeof.COFF_SECTION
|
|
dec ebx
|
|
jnz @B
|
|
|
|
mov edx, [coff]
|
|
mov ebx, [edx+COFF_HEADER.pSymTable]
|
|
mov edi, [filesize]
|
|
sub edi, ebx
|
|
jc .fail_and_free_data
|
|
mov [symbols_lim], edi
|
|
add ebx, edx
|
|
; coff_hdr = coff
|
|
; symbols_num = coff.nSymbols
|
|
mov [symbols_ptr], ebx
|
|
mov ebx, edx
|
|
|
|
; fixup symbols
|
|
mov eax, [edx+COFF_HEADER.nSymbols]
|
|
add edx, 20
|
|
lea ecx, [eax*9]
|
|
add ecx, ecx
|
|
add ecx, [symbols_ptr]
|
|
|
|
stdcall fix_coff_symbols, edx, [symbols_ptr], eax, \
|
|
ecx, 0
|
|
; test eax, eax
|
|
; jnz @F
|
|
;
|
|
;@@:
|
|
|
|
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
|
|
test eax, eax
|
|
jnz @F
|
|
|
|
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
|
|
@@:
|
|
mov [exports], eax
|
|
|
|
stdcall fix_coff_relocs, ebx, [symbols_ptr], 0
|
|
|
|
stdcall kernel_free, [coff]
|
|
|
|
stdcall kernel_free, [fullname]
|
|
|
|
mov eax, [exports]
|
|
ret
|
|
|
|
.fail_and_free_data:
|
|
stdcall user_free, [img_base]
|
|
.fail_and_free_coff:
|
|
stdcall kernel_free, [coff]
|
|
.fail:
|
|
stdcall kernel_free, [fullname]
|
|
xor eax, eax
|
|
ret
|
|
endp
|
|
|
|
; in: esi -> PEDESCR struct
|
|
proc dereference_pe
|
|
mov ecx, pe_list_mutex
|
|
call mutex_lock
|
|
dec [esi+PEDESCR.refcount]
|
|
jnz mutex_unlock
|
|
mov eax, [esi+PEDESCR.fd]
|
|
mov edx, [esi+PEDESCR.bk]
|
|
mov [eax+PEDESCR.bk], edx
|
|
mov [edx+PEDESCR.fd], eax
|
|
call mutex_unlock
|
|
mov eax, esi
|
|
call free
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
stop_all_services:
|
|
push ebp
|
|
mov edx, [srv.fd]
|
|
.next:
|
|
cmp edx, srv.fd-SRV.fd
|
|
je .done
|
|
cmp [edx+SRV.magic], ' SRV'
|
|
jne .next
|
|
cmp [edx+SRV.size], sizeof.SRV
|
|
jne .next
|
|
|
|
mov ebx, [edx+SRV.entry]
|
|
mov edx, [edx+SRV.fd]
|
|
test ebx, ebx
|
|
jz .next
|
|
|
|
push edx
|
|
mov ebp, esp
|
|
push 0
|
|
push -1
|
|
call ebx
|
|
mov esp, ebp
|
|
pop edx
|
|
jmp .next
|
|
.done:
|
|
pop ebp
|
|
ret
|
|
|
|
; param
|
|
; eax= size
|
|
; ebx= pid
|
|
|
|
align 4
|
|
create_kernel_object:
|
|
|
|
push ebx
|
|
call malloc
|
|
pop ebx
|
|
test eax, eax
|
|
jz .fail
|
|
|
|
mov ecx, [current_slot]
|
|
add ecx, APP_OBJ_OFFSET
|
|
|
|
pushfd
|
|
cli
|
|
mov edx, [ecx+APPOBJ.fd]
|
|
mov [eax+APPOBJ.fd], edx
|
|
mov [eax+APPOBJ.bk], ecx
|
|
mov [eax+APPOBJ.pid], ebx
|
|
|
|
mov [ecx+APPOBJ.fd], eax
|
|
mov [edx+APPOBJ.bk], eax
|
|
popfd
|
|
.fail:
|
|
ret
|
|
|
|
; param
|
|
; eax= object
|
|
|
|
align 4
|
|
destroy_kernel_object:
|
|
|
|
pushfd
|
|
cli
|
|
mov ebx, [eax+APPOBJ.fd]
|
|
mov ecx, [eax+APPOBJ.bk]
|
|
mov [ebx+APPOBJ.bk], ecx
|
|
mov [ecx+APPOBJ.fd], ebx
|
|
popfd
|
|
|
|
xor edx, edx ;clear common header
|
|
mov [eax], edx
|
|
mov [eax+4], edx
|
|
mov [eax+8], edx
|
|
mov [eax+12], edx
|
|
mov [eax+16], edx
|
|
|
|
call free ;release object memory
|
|
ret
|
|
|
|
|
|
;void* __fastcall create_object(size_t size)
|
|
; param
|
|
; ecx= size
|
|
|
|
align 4
|
|
create_object:
|
|
|
|
push esi
|
|
push edi
|
|
pushfd
|
|
cli
|
|
|
|
mov esi, [current_process]
|
|
mov eax, [esi+PROC.ht_free]
|
|
mov edi, [esi+PROC.ht_next]
|
|
dec eax
|
|
js .err0
|
|
|
|
mov [esi+PROC.ht_free], eax
|
|
mov eax, [esi+PROC.htab+edi*4]
|
|
mov [esi+PROC.ht_next], eax
|
|
popfd
|
|
|
|
mov eax, ecx
|
|
call malloc
|
|
test eax, eax
|
|
jz .err1
|
|
|
|
mov [eax+FUTEX.handle], edi
|
|
mov [esi+PROC.htab+edi*4], eax
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
|
|
.err1:
|
|
pushfd
|
|
cli
|
|
|
|
mov eax, [esi+PROC.ht_next]
|
|
mov [esi+PROC.htab+edi*4], eax
|
|
mov [esi+PROC.ht_next], edi
|
|
inc [esi+PROC.ht_free]
|
|
.err0:
|
|
popfd
|
|
pop edi
|
|
pop esi
|
|
xor eax, eax
|
|
ret
|
|
|
|
|
|
;int __fastcall destroy_object(struct object *obj)
|
|
|
|
align 4
|
|
destroy_object:
|
|
push esi
|
|
mov esi, [current_process]
|
|
mov edx, [ecx+FUTEX.handle]
|
|
|
|
pushfd
|
|
cli
|
|
|
|
mov eax, [esi+PROC.ht_next]
|
|
mov [esi+PROC.htab+edx*4], eax
|
|
mov [esi+PROC.ht_next], edx
|
|
inc [esi+PROC.ht_free]
|
|
|
|
popfd
|
|
pop esi
|
|
|
|
mov eax, ecx
|
|
call free
|
|
xor eax, eax
|
|
ret
|
|
.fail:
|
|
popfd
|
|
pop esi
|
|
mov eax, -1
|
|
ret
|
|
|