Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1158 → Rev 1159

/kernel/branches/core/conf_lib.inc
0,0 → 1,242
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;-------------------------------------------------------------------------
;Loading configuration from ini file
; {SPraid.simba}
;-------------------------------------------------------------------------
 
$Revision: 802 $
 
 
conf_path_sect: db 'path',0
 
conf_fname db '/sys/sys.conf',0
 
; set soke kernel configuration
proc set_kernel_conf
locals
par db 30 dup(?)
endl
 
pushad
;[gui]
;mouse_speed
 
lea eax,[par]
push eax
invoke ini.get_str,conf_fname, ugui, ugui_mouse_speed,\
eax,30, ugui_mouse_speed_def
pop eax
stdcall strtoint,eax
mov [mouse_speed_factor], ax
 
;mouse_delay
lea eax,[par]
push eax
invoke ini.get_str,conf_fname, ugui, ugui_mouse_delay,\
eax,30, ugui_mouse_delay_def
pop eax
stdcall strtoint,eax
mov [mouse_delay], eax
 
 
;midibase
lea eax,[par]
push eax
invoke ini.get_str,conf_fname, udev, udev_midibase, eax,30, udev_midibase_def
pop eax
stdcall strtoint,eax
 
cmp eax, 0x100
jb @f
cmp eax, 0x10000
jae @f
mov [midi_base], ax
mov [mididp], eax
inc eax
mov [midisp], eax
@@:
popad
ret
endp
 
ugui db 'gui',0
ugui_mouse_speed db 'mouse_speed',0
ugui_mouse_speed_def db '2',0
ugui_mouse_delay db 'mouse_delay',0
ugui_mouse_delay_def db '0x00A',0
 
udev db 'dev',0
udev_midibase db 'midibase',0
udev_midibase_def db '0x320',0
 
 
; convert string to DWord
proc strtoint stdcall,strs
pushad
 
mov eax,[strs]
inc eax
mov bl,[eax]
cmp bl,'x'
je .hex
cmp bl,'X'
je .hex
jmp .dec
.hex:
inc eax
stdcall strtoint_hex,eax
jmp .exit
.dec:
dec eax
stdcall strtoint_dec,eax
.exit:
mov [esp+28],eax
popad
ret
endp
 
; convert string to DWord for decimal value
proc strtoint_dec stdcall,strs
pushad
xor edx,edx
; ¯®¨áª ª®­æ 
mov esi,[strs]
@@:
lodsb
or al,al
jnz @b
mov ebx,esi
mov esi,[strs]
dec ebx
sub ebx,esi
mov ecx,1
 
@@:
dec ebx
or ebx,ebx
jz @f
imul ecx,ecx,10 ; ¯®à冷ª
jmp @b
@@:
 
xchg ebx,ecx
 
 
xor ecx,ecx
 
 
@@:
xor eax,eax
lodsb
cmp al,0
je .eend
 
sub al,30h
imul ebx
add ecx,eax
push ecx
xchg eax,ebx
mov ecx,10
div ecx
xchg eax,ebx
pop ecx
jmp @b
 
.eend:
mov [esp+28],ecx
popad
ret
endp
 
;convert string to DWord for hex value
proc strtoint_hex stdcall,strs
pushad
xor edx,edx
 
mov esi,[strs]
mov ebx,1
add esi,1
 
@@:
lodsb
or al,al
jz @f
shl ebx,4
jmp @b
@@:
xor ecx,ecx
mov esi,[strs]
 
@@:
xor eax,eax
lodsb
cmp al,0
je .eend
 
cmp al,'a'
jae .bm
cmp al,'A'
jae .bb
jmp .cc
.bm: ; 57h
sub al,57h
jmp .do
 
.bb: ; 37h
sub al,37h
jmp .do
 
.cc: ; 30h
sub al,30h
 
.do:
imul ebx
add ecx,eax
shr ebx,4
 
jmp @b
 
.eend:
mov [esp+28],ecx
popad
ret
endp
 
 
; convert string to DWord for IP addres
proc do_inet_adr stdcall,strs
pushad
 
mov esi,[strs]
mov ebx,0
.next:
push esi
@@:
lodsb
or al,al
jz @f
cmp al,'.'
jz @f
jmp @b
@@:
mov cl, al
mov [esi-1],byte 0
;pop eax
call strtoint_dec
rol eax,24
ror ebx,8
add ebx,eax
or cl,cl
jz @f
jmp .next
@@:
mov [esp+28],ebx
popad
ret
endp
/kernel/branches/core/debug.inc
0,0 → 1,475
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 750 $
 
 
; diamond, 2006
sys_debug_services:
cmp eax, 9
ja @f
jmp dword [sys_debug_services_table+eax*4]
@@: ret
sys_debug_services_table:
dd debug_set_event_data
dd debug_getcontext
dd debug_setcontext
dd debug_detach
dd debug_suspend
dd debug_resume
dd debug_read_process_memory
dd debug_write_process_memory
dd debug_terminate
dd debug_set_drx
 
debug_set_event_data:
; in: ebx = pointer
; destroys eax
mov eax, [current_slot]
mov [eax+APPDATA.dbg_event_mem], ebx
ret
 
get_debuggee_slot:
; in: ebx=PID
; out: CF=1 if error
; CF=0 and eax=slot*0x20 if ok
; out: interrupts disabled
cli
mov eax, ebx
call pid_to_slot
test eax, eax
jz .ret_bad
shl eax, 5
push ebx
mov ebx, [CURRENT_TASK]
cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx
pop ebx
jnz .ret_bad
; clc ; automatically
ret
.ret_bad:
stc
ret
 
debug_detach:
; in: ebx=pid
; destroys eax,ebx
call get_debuggee_slot
jc .ret
and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0
call do_resume
.ret:
sti
ret
 
debug_terminate:
; in: ebx=pid
call get_debuggee_slot
jc debug_detach.ret
mov ecx, eax
shr ecx, 5
push 2
pop ebx
jmp sys_system
 
debug_suspend:
; in: ebx=pid
; destroys eax,ebx
cli
mov eax, ebx
call pid_to_slot
shl eax, 5
jz .ret
mov bl, [CURRENT_TASK+eax+TASKDATA.state] ; process state
test bl, bl
jz .1
cmp bl, 5
jnz .ret
mov bl, 2
.2: mov [CURRENT_TASK+eax+TASKDATA.state], bl
.ret:
sti
ret
.1:
inc ebx
jmp .2
 
do_resume:
mov bl, [CURRENT_TASK+eax+TASKDATA.state]
cmp bl, 1
jz .1
cmp bl, 2
jnz .ret
mov bl, 5
.2: mov [CURRENT_TASK+eax+TASKDATA.state], bl
.ret: ret
.1: dec ebx
jmp .2
 
debug_resume:
; in: ebx=pid
; destroys eax,ebx
cli
mov eax, ebx
call pid_to_slot
shl eax, 5
jz .ret
call do_resume
.ret: sti
ret
 
debug_getcontext:
; in:
; ebx=pid
; ecx=sizeof(CONTEXT)
; edx->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp ecx, 28h
jnz .ret
push ebx
mov ebx, edx
call check_region
pop ebx
dec eax
jnz .ret
call get_debuggee_slot
jc .ret
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack]
lea esi, [eax+RING0_STACK_SIZE]
mov edi, edx
.ring0:
; note that following code assumes that all interrupt/exception handlers
; saves ring-3 context by pushad in this order
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad
sub esi, 8+12+20h
lodsd ;edi
mov [edi+24h], eax
lodsd ;esi
mov [edi+20h], eax
lodsd ; ebp
mov [edi+1Ch], eax
lodsd ;esp
lodsd ;ebx
mov [edi+14h], eax
lodsd ;edx
mov [edi+10h], eax
lodsd ;ecx
mov [edi+0Ch], eax
lodsd ;eax
mov [edi+8], eax
lodsd ;eip
mov [edi], eax
lodsd ;cs
lodsd ;eflags
mov [edi+4], eax
lodsd ;esp
mov [edi+18h], eax
.ret:
sti
ret
 
debug_setcontext:
; in:
; ebx=pid
; ecx=sizeof(CONTEXT)
; edx->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp ecx, 28h
jnz .ret
push ebx
mov ebx, edx
call check_region
pop ebx
dec eax
jnz .ret
call get_debuggee_slot
jc .stiret
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack]
lea edi, [eax+RING0_STACK_SIZE]
mov esi, edx
.ring0:
sub edi, 8+12+20h
mov eax, [esi+24h] ;edi
stosd
mov eax, [esi+20h] ;esi
stosd
mov eax, [esi+1Ch] ;ebp
stosd
scasd
mov eax, [esi+14h] ;ebx
stosd
mov eax, [esi+10h] ;edx
stosd
mov eax, [esi+0Ch] ;ecx
stosd
mov eax, [esi+8] ;eax
stosd
mov eax, [esi] ;eip
stosd
scasd
mov eax, [esi+4] ;eflags
stosd
mov eax, [esi+18h] ;esp
stosd
.stiret:
sti
.ret:
ret
 
debug_set_drx:
call get_debuggee_slot
jc .errret
mov ebp, eax
lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs]
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
; [eax+10]=dr7
cmp edx, OS_BASE
jae .errret
cmp cl, 3
ja .errret
mov ebx, dr7
shr ebx, cl
shr ebx, cl
test ebx, 2 ; bit 1+2*index = G0..G3, global break enable
jnz .errret2
test ch, ch
jns .new
; clear breakpoint
movzx ecx, cl
add ecx, ecx
and dword [eax+ecx*2], 0 ; clear DR<i>
btr dword [eax+10h], ecx ; clear L<i> bit
test byte [eax+10h], 55h
jnz .okret
; imul eax, ebp, tss_step/32
; and byte [eax + tss_data + TSS._trap], not 1
and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1
.okret:
and dword [esp+36], 0
sti
ret
.errret:
sti
mov dword [esp+36], 1
ret
.errret2:
sti
mov dword [esp+36], 2
ret
.new:
; add new breakpoint
; cl=index; ch=flags; edx=address
test ch, 0xF0
jnz .errret
mov bl, ch
and bl, 3
cmp bl, 2
jz .errret
mov bl, ch
shr bl, 2
cmp bl, 2
jz .errret
test dl, bl
jnz .errret
or byte [eax+10h+1], 3 ; set GE and LE flags
movzx ebx, ch
movzx ecx, cl
add ecx, ecx
bts dword [eax+10h], ecx ; set L<i> flag
add ecx, ecx
mov [eax+ecx], edx ; set DR<i>
shl ebx, cl
mov edx, 0xF
shl edx, cl
not edx
and [eax+10h+2], dx
or [eax+10h+2], bx ; set R/W and LEN fields
; imul eax, ebp, tss_step/32
; or byte [eax + tss_data + TSS._trap], 1
or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1
jmp .okret
 
debug_read_process_memory:
; in:
; ebx=pid
; ecx=length
; esi->buffer in debugger
; edx=address in debuggee
; out: [esp+36]=sizeof(read)
; destroys all
push ebx
mov ebx, esi
call check_region
pop ebx
dec eax
jnz .err
call get_debuggee_slot
jc .err
shr eax, 5
mov ebx, esi
call read_process_memory
sti
mov dword [esp+36], eax
ret
.err:
or dword [esp+36], -1
ret
 
debug_write_process_memory:
; in:
; ebx=pid
; ecx=length
; esi->buffer in debugger
; edx=address in debuggee
; out: [esp+36]=sizeof(write)
; destroys all
push ebx
mov ebx, esi
call check_region
pop ebx
dec eax
jnz debug_read_process_memory.err
call get_debuggee_slot
jc debug_read_process_memory.err
shr eax, 5
mov ebx, esi
call write_process_memory
sti
mov [esp+36], eax
ret
 
debugger_notify:
; in: eax=debugger slot
; ecx=size of debug message
; [esp+4]..[esp+4+ecx]=message
; interrupts must be disabled!
; destroys all general registers
; interrupts remain disabled
xchg ebp, eax
mov edi, [timer_ticks]
add edi, 500 ; 5 sec timeout
.1:
mov eax, ebp
shl eax, 8
mov edx, [SLOT_BASE+eax+APPDATA.dbg_event_mem]
test edx, edx
jz .ret
; read buffer header
push ecx
push eax
push eax
mov eax, ebp
mov ebx, esp
mov ecx, 8
call read_process_memory
cmp eax, ecx
jz @f
add esp, 12
jmp .ret
@@:
cmp dword [ebx], 0
jg @f
.2:
pop ecx
pop ecx
pop ecx
cmp dword [CURRENT_TASK], 1
jnz .notos
cmp [timer_ticks], edi
jae .ret
.notos:
sti
call change_task
cli
jmp .1
@@:
mov ecx, [ebx+8]
add ecx, [ebx+4]
cmp ecx, [ebx]
ja .2
; advance buffer position
push ecx
mov ecx, 4
sub ebx, ecx
mov eax, ebp
add edx, ecx
call write_process_memory
pop eax
; write message
mov eax, ebp
add edx, ecx
add edx, [ebx+8]
add ebx, 20
pop ecx
pop ecx
pop ecx
call write_process_memory
; new debug event
mov eax, ebp
shl eax, 8
or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h
.ret:
ret
 
debug_exc:
test byte [esp+8+2], 2
jnz v86_debug_exc
; int 1 = #DB
save_ring3_context
cld
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov eax, dr6
push eax
xor eax, eax
mov dr6, eax
; test if debugging
cli
mov eax, [current_slot]
mov eax, [eax+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
add esp, 0x20+4
mov [error_interrupt], 1
call show_error_parameters
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 4
jmp change_task
.debug:
; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID
pop edx
mov ebx, dr7
mov cl, not 1
.l1:
test bl, 1
jnz @f
and dl, cl
@@:
shr ebx, 2
add cl, cl
inc ecx
cmp cl, not 10h
jnz .l1
push edx ; DR6 image
mov ecx, [TASK_BASE]
push dword [ecx+TASKDATA.pid] ; PID
push 12
pop ecx
push 3 ; 3 = debug exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task
restore_ring3_context
iretd
/kernel/branches/core/dll.inc
0,0 → 1,1229
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 1018 $
 
 
DRV_COMPAT equ 5 ;minimal required drivers version
DRV_CURRENT equ 5 ;current drivers model version
 
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
PID_KERNEL equ 1 ;os_idle thread
 
align 4
proc attach_int_handler stdcall, irq:dword, handler:dword, access_rights:dword
 
push ebx
 
mov ebx, [irq] ;irq num
test ebx, ebx
jz .err
cmp ebx, 15 ; hidnplayr says: we only have 16 IRQ's
ja .err
mov eax, [handler]
test eax, eax
jz .err
cmp [irq_owner + 4 * ebx], 0
je @f
 
mov ecx, [irq_rights + 4 * ebx] ; Rights : 0 - full access, 1 - read only, 2 - forbidden
test ecx, ecx
jnz .err
 
@@:
mov [irq_tab+ebx*4], eax
 
mov eax, [access_rights]
mov [irq_rights + 4 * ebx], eax
 
mov [irq_owner + 4 * ebx], PID_KERNEL ; all handlers belong to a kernel
 
stdcall enable_irq, [irq]
pop ebx
mov eax, 1
ret
.err:
pop ebx
xor eax, eax
ret
endp
 
uglobal
 
irq_rights rd 16
 
endg
 
proc get_int_handler stdcall, irq:dword
 
mov eax, [irq]
 
cmp [irq_rights + 4 * eax], dword 1
ja .err
 
mov eax, [irq_tab + 4 * eax]
ret
 
.err:
xor eax, eax
ret
 
endp
 
align 4
proc detach_int_handler
 
ret
endp
 
align 4
proc enable_irq stdcall, irq_line:dword
mov ebx, [irq_line]
mov edx, 0x21
cmp ebx, 8
jb @F
mov edx, 0xA1
sub ebx,8
@@:
in al,dx
btr eax, ebx
out dx, al
ret
endp
 
align 16
;; proc irq_serv
 
irq_serv:
 
.irq_1:
push 1
jmp .main
align 4
.irq_2:
push 2
jmp .main
align 4
.irq_3:
push 3
jmp .main
align 4
.irq_4:
push 4
jmp .main
align 4
.irq_5:
push 5
jmp .main
; align 4
; .irq_6:
; push 6
; jmp .main
align 4
.irq_7:
push 7
jmp .main
align 4
.irq_8:
push 8
jmp .main
align 4
.irq_9:
push 9
jmp .main
align 4
.irq_10:
push 10
jmp .main
align 4
.irq_11:
push 11
jmp .main
align 4
.irq_12:
push 12
jmp .main
; align 4
; .irq_13:
; push 13
; jmp .main
; align 4
; .irq_14:
; push 14
; jmp .main
; align 4
; .irq_15:
; push 15
; jmp .main
 
align 16
.main:
save_ring3_context
mov eax, [esp + 32]
mov bx, app_data ;os_data
mov ds, bx
mov es, bx
 
cmp [v86_irqhooks+eax*8], 0
jnz v86_irq
 
mov ebx, [irq_tab+eax*4]
test ebx, ebx
jz .exit
 
call ebx
mov [check_idle_semaphore],5
 
.exit:
 
cmp dword [esp + 32], 8
mov al, 0x20
jb @f
out 0xa0, al
@@:
out 0x20, al
 
restore_ring3_context
add esp, 4
 
iret
 
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], SRV_SIZE
jne .fail
 
stdcall [edi+SRV.srv_proc], 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
; ebx= io_control
;
; retval
; eax= error code
 
align 4
srv_handlerEx:
cmp ebx, OS_BASE
jae .fail
 
mov eax, [ebx+handle]
cmp [eax+SRV.magic], ' SRV'
jne .fail
 
cmp [eax+SRV.size], SRV_SIZE
jne .fail
 
stdcall [eax+SRV.srv_proc], ebx
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_OFFSET
je .not_load
 
stdcall strncmp, edx, [sz_name], 16
test eax, eax
je .ok
 
mov edx, [edx+SRV.fd]
jmp @B
.not_load:
pop ebp
jmp load_driver
.ok:
mov eax, edx
ret
endp
 
align 4
proc reg_service stdcall, name:dword, handler:dword
 
push ebx
 
xor eax, eax
 
cmp [name], eax
je .fail
 
cmp [handler], eax
je .fail
 
mov eax, SRV_SIZE
call malloc ;call alloc_service
test eax, eax
jz .fail
 
push esi
push edi
mov edi, eax
mov esi, [name]
mov ecx, 16/4
rep movsd
pop edi
pop esi
 
mov [eax+SRV.magic], ' SRV'
mov [eax+SRV.size], SRV_SIZE
 
mov ebx, srv.fd-SRV_FD_OFFSET
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 ebx, [pSym]
mov eax, [ebx+8]
ret
endp
 
align 4
proc get_curr_task
mov eax,[CURRENT_TASK]
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]
int 0x40
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
push eax
lea eax, [cmd]
call file_system_lfn
pop eax
popad
ret
endp
 
; description
; allocate kernel memory and loads the specified file
;
; param
; file_name= full path to file
;
; retval
; eax= file image in kernel 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 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
 
stdcall read_file, [file_name], eax, dword 0, [file_size]
cmp ebx, [file_size]
jne .cleanup
 
mov eax, [file]
cmp dword [eax], 0x4B43504B
jne .exit
mov ebx, [eax+4]
mov [file_size], ebx
stdcall kernel_alloc, ebx
 
test eax, eax
jz .cleanup
 
mov [file2], eax
stdcall unpack, [file], eax
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
 
align 4
proc get_proc_ex stdcall, proc_name:dword, imports:dword
 
.look_up:
mov edx, [imports]
test edx, edx
jz .end
mov edx, [edx]
test edx, edx
jz .end
.next:
mov eax, [edx]
test eax, eax
jz .next_table
 
push edx
stdcall strncmp, eax, [proc_name], 256
pop edx
test eax, eax
jz .ok
 
add edx,8
jmp .next
.next_table:
add [imports], 4
jmp .look_up
.ok:
mov eax, [edx+4]
ret
.end:
xor eax, eax
ret
endp
 
align 4
proc fix_coff_symbols stdcall, 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+CSYM.SectionNumber]
test ebx, ebx
jnz .internal
mov eax, dword [edi+CSYM.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
 
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+CSYM.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+CFS.VirtualAddress]
add [edi+CSYM.Value], eax
.next:
add edi, CSYM_SIZE
mov [symbols], edi
dec [sym_count]
jnz .fix
mov eax, [retval]
ret
endp
 
align 4
proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword
locals
n_sec dd ?
endl
 
mov eax, [coff]
movzx ebx, [eax+CFH.nSections]
mov [n_sec], ebx
.fix_sec:
mov esi, [sec]
mov edi, [esi+CFS.PtrReloc]
add edi, [coff]
 
movzx ecx, [esi+CFS.NumReloc]
test ecx, ecx
jz .next
.next_reloc:
mov ebx, [edi+CRELOC.SymIndex]
add ebx,ebx
lea ebx,[ebx+ebx*8]
add ebx, [sym]
 
mov edx, [ebx+CSYM.Value]
 
cmp [edi+CRELOC.Type], 6
je .dir_32
 
cmp [edi+CRELOC.Type], 20
jne .next_reloc
.rel_32:
mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress]
sub edx, eax
sub edx, 4
jmp .fix
.dir_32:
mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress]
.fix:
add [eax], edx
add edi, 10
dec ecx
jnz .next_reloc
.next:
add [sec], COFF_SECTION_SIZE
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
 
align 4
proc load_driver stdcall, driver_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
start dd ?
 
exports dd ? ;fake exports table
dd ?
file_name rb 13+16+4+1 ; '/sys/drivers/<up-to-16-chars>.obj'
endl
 
lea edx, [file_name]
mov dword [edx], '/sys'
mov dword [edx+4], '/dri'
mov dword [edx+8], 'vers'
mov byte [edx+12], '/'
mov esi, [driver_name]
.redo:
lea edx, [file_name]
lea edi, [edx+13]
mov ecx, 16
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
mov dword [edi], '.obj'
mov byte [edi+4], 0
stdcall load_file, edx
 
test eax, eax
jz .exit
 
mov [coff], eax
 
movzx ecx, [eax+CFH.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, COFF_SECTION_SIZE
dec ecx
jnz @B
mov [img_size], ebx
 
stdcall kernel_alloc, ebx
test eax, eax
jz .fail
mov [img_base], eax
 
mov edi, eax
xor eax, eax
mov ecx, [img_size]
add ecx, 4095
and ecx, not 4095
shr ecx, 2
cld
rep stosd
 
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx,ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea ebx, [exports]
mov dword [ebx], kernel_export
mov dword [ebx+4], 0
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
[strings], ebx
test eax, eax
jz .link_fail
 
mov ebx, [coff]
add ebx, 20
stdcall fix_coff_relocs, [coff], ebx, [sym]
 
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion
test eax, eax
jz .link_fail
 
mov eax, [eax]
shr eax, 16
cmp eax, DRV_COMPAT
jb .ver_fail
 
cmp eax, DRV_CURRENT
ja .ver_fail
 
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szSTART
mov [start], eax
 
stdcall kernel_free, [coff]
 
mov ebx, [start]
stdcall ebx, DRV_ENTRY
test eax, eax
jnz .ok
 
stdcall kernel_free, [img_base]
cmp dword [file_name+13], 'SOUN'
jnz @f
cmp dword [file_name+17], 'D.ob'
jnz @f
cmp word [file_name+21], 'j'
jnz @f
mov esi, aSis
jmp .redo
@@:
xor eax, eax
ret
.ok:
mov ebx, [img_base]
mov [eax+SRV.base], ebx
mov ecx, [start]
mov [eax+SRV.entry], ecx
ret
 
.ver_fail:
mov esi, msg_CR
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
mov esi, msg_version
call sys_msg_board_str
mov esi, msg_www
call sys_msg_board_str
jmp .cleanup
 
.link_fail:
mov esi, msg_module
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
.cleanup:
stdcall kernel_free,[img_base]
.fail:
stdcall kernel_free, [coff]
.exit:
xor eax, eax
ret
endp
 
align 4
proc load_library stdcall, file_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
exports dd ?
endl
 
cli
 
stdcall load_file, [file_name]
test eax, eax
jz .fail
 
mov [coff], eax
movzx ecx, [eax+CFH.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, COFF_SECTION_SIZE
dec ecx
jnz @B
mov [img_size], ebx
 
call init_heap
stdcall user_alloc, [img_size]
 
test eax, eax
jz .fail
mov [img_base], eax
 
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15 ;-new_app_base
and edi, -16
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx,ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
[strings], dword 0
test eax, eax
jnz @F
 
@@:
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, new_app_base
lea eax, [edx+20]
@@:
add [eax+CFS.VirtualAddress], edi ;patch user space offset
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
add edx, 20
stdcall fix_coff_relocs, [coff], edx, [sym]
 
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS
test eax, eax
jnz @F
 
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],sz_EXPORTS
@@:
mov [exports], eax
stdcall kernel_free, [coff]
mov eax, [exports]
ret
.fail:
xor eax, eax
ret
endp
 
align 4
proc stop_all_services
 
mov edx, [srv.fd]
.next:
cmp edx, srv.fd-SRV_FD_OFFSET
je .done
cmp [edx+SRV.magic], ' SRV'
jne .next
cmp [edx+SRV.size], SRV_SIZE
jne .next
 
mov ebx, [edx+SRV.entry]
mov edx, [edx+SRV.fd]
test ebx, ebx
jz .next
 
push edx
stdcall ebx, dword -1
pop edx
jmp .next
.done:
ret
endp
 
; 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
 
 
 
if 0
 
irq:
 
.irq0:
pusfd
pushad
push IRQ_0
jmp .master
.irq_1:
pusfd
pushad
push IRQ_1
jmp .master
 
.master:
mov ax, app_data
mov ds, eax
mov es, eax
mov ebx, [esp+4] ;IRQ_xx
mov eax, [irq_handlers+ebx+4]
call intr_handler
mov ecx, [esp+4]
cmp [irq_actids+ecx*4], 0
je @F
in al, 0x21
bts eax, ecx
out 0x21, al
mov al, 0x20
out 0x20, al
jmp .restart
 
.slave:
mov ax, app_data
mov ds, eax
mov es, eax
mov ebx, [esp+4] ;IRQ_xx
mov eax, [irq_handlers+ebx+4]
call intr_handler
mov ecx, [esp+4]
sub ecx, 8
cmp [irq_actids+ecx*4], 0
je @F
in al, 0xA1
bts eax, ecx
out 0xA1, al
mov al, 0x20
out 0xA0, al
out 0x20, al
.restart:
mov ebx, [next_slot]
test ebx, ebx
jz @F
mov [next_task],0
mov esi, [prev_slot]
call do_change_task
add esp, 4
iretd
 
end if
 
 
 
 
/kernel/branches/core/export.inc
0,0 → 1,39
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 750 $
 
; Macroinstruction for making export section
 
 
macro export dllname,[label,string]
{ common
local module,addresses,names,ordinal,count
count = 0
forward
count = count+1
common
dd 0,0,0, (module-OS_BASE) , 1
dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE)
addresses:
forward
dd (label-OS_BASE)
common
names:
forward
local name
dd (name-OS_BASE)
common
ordinal: count = 0
forward
dw count
count = count+1
common
module db dllname,0
forward
name db string,0
}
/kernel/branches/core/exports.inc
0,0 → 1,173
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 924 $
 
 
iglobal
szKernel db 'KERNEL', 0
szVersion db 'version',0
 
szRegService db 'RegService',0
szGetService db 'GetService',0
szServiceHandler db 'ServiceHandler',0
szAttachIntHandler db 'AttachIntHandler',0
szGetIntHandler db 'GetIntHandler', 0
szFpuSave db 'FpuSave',0
szFpuRestore db 'FpuRestore',0
szReservePortArea db 'ReservePortArea',0
szBoot_Log db 'Boot_Log',0
 
szPciApi db 'PciApi', 0
szPciRead32 db 'PciRead32', 0
szPciRead16 db 'PciRead16', 0
szPciRead8 db 'PciRead8', 0
szPciWrite8 db 'PciWrite8',0
szPciWrite16 db 'PciWrite16',0
szPciWrite32 db 'PciWrite32',0
 
szAllocPage db 'AllocPage',0
szAllocPages db 'AllocPages',0
szFreePage db 'FreePage',0
szGetPgAddr db 'GetPgAddr',0
szMapPage db 'MapPage',0
szMapSpace db 'MapSpace',0
szMapIoMem db 'MapIoMem',0
szCommitPages db 'CommitPages',0
szReleasePages db 'ReleasePages',0
 
szAllocKernelSpace db 'AllocKernelSpace',0
szFreeKernelSpace db 'FreeKernelSpace',0
szKernelAlloc db 'KernelAlloc',0
szKernelFree db 'KernelFree',0
szUserAlloc db 'UserAlloc',0
szUserFree db 'UserFree',0
szKmalloc db 'Kmalloc',0
szKfree db 'Kfree',0
szCreateRingBuffer db 'CreateRingBuffer',0
 
szGetPid db 'GetPid',0
szCreateObject db 'CreateObject',0
szDestroyObject db 'DestroyObject',0
szCreateEvent db 'CreateEvent',0
szRaiseEvent db 'RaiseEvent',0
szWaitEvent db 'WaitEvent',0
szDestroyEvent db 'DestroyEvent',0
szClearEvent db 'ClearEvent',0
 
szLoadCursor db 'LoadCursor',0
szSelectHwCursor db 'SelectHwCursor',0
szSetHwCursor db 'SetHwCursor',0
szHwCursorRestore db 'HwCursorRestore', 0
szHwCursorCreate db 'HwCursorCreate', 0
 
szSysMsgBoardStr db 'SysMsgBoardStr', 0
szSysMsgBoardChar db 'SysMsgBoardChar', 0
szGetCurrentTask db 'GetCurrentTask',0
szLFBAddress db 'LFBAddress',0
szLoadFile db 'LoadFile',0
szSendEvent db 'SendEvent',0
szSetMouseData db 'SetMouseData',0
szSleep db 'Sleep',0
szGetTimerTicks db 'GetTimerTicks',0
 
szStrncat db 'strncat',0
szStrncpy db 'strncpy',0
szstrncmp db 'strncmp',0
szStrnlen db 'strnlen',0
szStrchr db 'strchr',0
szStrrchr db 'strrchr',0
 
szEthReceiver db 'EthReceiver',0
szEthRegDev db 'EthRegDev',0
szEthUnRegDev db 'EthUnRegDev',0
szEthStruc2Dev db 'EthStruc2Dev',0
 
 
align 16
kernel_export:
dd szRegService , reg_service
dd szGetService , get_service
dd szServiceHandler , srv_handler
dd szAttachIntHandler, attach_int_handler
dd szGetIntHandler , get_int_handler
dd szFpuSave , fpu_save
dd szFpuRestore , fpu_restore
dd szReservePortArea , r_f_port_area
dd szBoot_Log , boot_log
 
dd szPciApi , pci_api
dd szPciRead32 , pci_read32
dd szPciRead16 , pci_read16
dd szPciRead8 , pci_read8
dd szPciWrite8 , pci_write8
dd szPciWrite16 , pci_write16
dd szPciWrite32 , pci_write32
 
dd szAllocPage , alloc_page ;stdcall
dd szAllocPages , alloc_pages ;stdcall
dd szFreePage , free_page
dd szMapPage , map_page ;stdcall
dd szMapSpace , map_space
dd szMapIoMem , map_io_mem ;stdcall
dd szGetPgAddr , get_pg_addr
dd szCommitPages , commit_pages ;not implemented
dd szReleasePages , release_pages
 
dd szAllocKernelSpace, alloc_kernel_space ;stdcall
dd szFreeKernelSpace , free_kernel_space ;stdcall
dd szKernelAlloc , kernel_alloc ;stdcall
dd szKernelFree , kernel_free ;stdcall
dd szUserAlloc , user_alloc ;stdcall
dd szUserFree , user_free ;stdcall
dd szKmalloc , malloc
dd szKfree , free
dd szCreateRingBuffer, create_ring_buffer ;stdcall
 
dd szGetPid , get_pid
dd szCreateObject , create_kernel_object
dd szDestroyObject , destroy_kernel_object
dd szCreateEvent , create_event
dd szRaiseEvent , raise_event
dd szWaitEvent , wait_event
dd szDestroyEvent , destroy_event
dd szClearEvent , clear_event
 
dd szLoadCursor , load_cursor ;stdcall
 
dd szSelectHwCursor , select_hw_cursor ;import stdcall
dd szSetHwCursor , set_hw_cursor ;import stdcall
dd szHwCursorRestore , hw_restore ;import
dd szHwCursorCreate , create_cursor ;import
 
dd szSysMsgBoardStr , sys_msg_board_str
dd szSysMsgBoardChar , sys_msg_board
dd szGetCurrentTask , get_curr_task
dd szLoadFile , load_file ;retval eax, ebx
dd szSendEvent , send_event
dd szSetMouseData , set_mouse_data ;stdcall
dd szSleep , delay_ms
dd szGetTimerTicks , get_timer_ticks
 
dd szStrncat , strncat
dd szStrncpy , strncpy
dd szstrncmp , strncmp
dd szStrnlen , strnlen
dd szStrchr , strchr
dd szStrrchr , strrchr
 
dd szEthReceiver , ETH_Receiver
dd szEthRegDev , ETH_Add_Device
dd szEthUnRegDev , ETH_Remove_Device
dd szEthStruc2Dev , ETH_struc2dev
 
exp_lfb:
dd szLFBAddress , 0
dd 0 ;terminator, must be zero
 
endg
 
/kernel/branches/core/ext_lib.inc
0,0 → 1,317
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;============================================================================
;
; External kernel dependencies (libraries) loading
;
;============================================================================
 
$Revision: 750 $
 
 
macro library [name,fname]
{
forward
dd __#name#_library_table__,__#name#_library_name__
common
dd 0
forward
__#name#_library_name__ db fname,0
}
 
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
name dd __#name#_import_name__
common
dd 0
forward
__#name#_import_name__ db sname,0
}
 
macro export [name,sname]
{
align 4
forward
dd __#name#_export_name__,name
common
dd 0
forward
__#name#_export_name__ db sname,0
}
 
 
 
align 4 ; loading library (use kernel functions)
proc load_k_library stdcall, file_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
exports dd ?
endl
 
cli
 
stdcall load_file, [file_name]
test eax, eax
jz .fail
 
mov [coff], eax
movzx ecx, [eax+CFH.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, COFF_SECTION_SIZE
dec ecx
jnz @B
mov [img_size], ebx
 
stdcall kernel_alloc, [img_size]
 
test eax, eax
jz .fail
mov [img_base], eax
 
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx,ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
[strings], dword 0
test eax, eax
jnz @F
 
@@:
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, 0
lea eax, [edx+20]
@@:
add [eax+CFS.VirtualAddress], edi ;patch user space offset
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
add edx, 20
stdcall fix_coff_relocs, [coff], edx, [sym]
 
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS
mov [exports], eax
 
stdcall kernel_free, [coff]
 
mov eax, [exports]
ret
.fail:
xor eax, eax
ret
endp
 
 
proc dll.Load, import_table:dword
mov esi,[import_table]
.next_lib: mov edx,[esi]
or edx,edx
jz .exit
push esi
 
mov edi,s_libname
 
mov al, '/'
stosb
mov esi,sysdir_path
@@: lodsb
stosb
or al,al
jnz @b
dec edi
mov [edi], dword '/lib'
mov [edi+4],byte '/'
add edi,5
pop esi
push esi
mov esi,[esi+4]
@@: lodsb
stosb
or al,al
jnz @b
 
pushad
stdcall load_k_library,s_libname
mov [esp+28],eax
popad
or eax,eax
jz .fail
stdcall dll.Link,eax,edx
stdcall dll.Init,[eax+4]
pop esi
add esi,8
jmp .next_lib
.exit: xor eax,eax
ret
.fail: add esp,4
xor eax,eax
inc eax
ret
endp
 
proc dll.Link, exp:dword,imp:dword
push eax
mov esi,[imp]
test esi,esi
jz .done
.next: lodsd
test eax,eax
jz .done
stdcall dll.GetProcAddress,[exp],eax
or eax,eax
jz @f
mov [esi-4],eax
jmp .next
@@: mov dword[esp],0
.done: pop eax
ret
endp
 
proc dll.Init, dllentry:dword
pushad
mov eax,mem.Alloc
mov ebx,mem.Free
mov ecx,mem.ReAlloc
mov edx,dll.Load
stdcall [dllentry]
popad
ret
endp
 
proc dll.GetProcAddress, exp:dword,sz_name:dword
mov edx,[exp]
.next: test edx,edx
jz .end
stdcall strncmp,[edx],[sz_name], dword -1
test eax,eax
jz .ok
add edx,8
jmp .next
.ok: mov eax,[edx+4]
.end: ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Alloc size ;/////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx
; mov eax,[size]
; lea ecx,[eax+4+4095]
; and ecx,not 4095
; stdcall kernel_alloc, ecx
; add ecx,-4
; mov [eax],ecx
; add eax,4
 
stdcall kernel_alloc, [size]
 
pop ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx esi edi eax
mov eax,[mptr]
mov ebx,[size]
or eax,eax
jz @f
lea ecx,[ebx+4+4095]
and ecx,not 4095
add ecx,-4
cmp ecx,[eax-4]
je .exit
@@: mov eax,ebx
call mem.Alloc
xchg eax,[esp]
or eax,eax
jz .exit
mov esi,eax
xchg eax,[esp]
mov edi,eax
mov ecx,[esi-4]
cmp ecx,[edi-4]
jbe @f
mov ecx,[edi-4]
@@: add ecx,3
shr ecx,2
cld
rep movsd
xchg eax,[esp]
call mem.Free
.exit:
pop eax edi esi ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Free mptr ;//////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
; mov eax,[mptr]
; or eax,eax
; jz @f
; push ebx ecx
; lea ecx,[eax-4]
; stdcall kernel_free, ecx
; pop ecx ebx
; @@: ret
stdcall kernel_free, [mptr]
ret
endp
 
uglobal
s_libname db 64 dup (0)
endg
/kernel/branches/core/fpu.inc
0,0 → 1,288
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 750 $
 
 
init_fpu:
clts
fninit
 
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
mov ebx, cr4
mov ecx, cr0
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT
mov cr4, ebx
 
and ecx, not (CR0_MP+CR0_EM)
or ecx, CR0_NE
mov cr0, ecx
 
mov dword [esp-4], SSE_INIT
ldmxcsr [esp-4]
 
xorps xmm0, xmm0
xorps xmm1, xmm1
xorps xmm2, xmm2
xorps xmm3, xmm3
xorps xmm4, xmm4
xorps xmm5, xmm5
xorps xmm6, xmm6
xorps xmm7, xmm7
fxsave [fpu_data] ;[eax]
ret
.no_SSE:
mov ecx, cr0
and ecx, not CR0_EM
or ecx, CR0_MP+CR0_NE
mov cr0, ecx
fnsave [fpu_data]
ret
 
; param
; eax= 512 bytes memory area
 
align 4
fpu_save:
push ecx
push esi
push edi
 
pushfd
cli
 
clts
mov edi, eax
 
mov ecx, [fpu_owner]
mov esi, [CURRENT_TASK]
cmp ecx, esi
jne .save
 
call save_context
jmp .exit
.save:
mov [fpu_owner], esi
 
shl ecx, 8
mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state]
 
call save_context
 
shl esi, 8
mov esi, [esi+SLOT_BASE+APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
fninit
.exit:
popfd
pop edi
pop esi
pop ecx
ret
 
align 4
save_context:
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxsave [eax]
ret
.no_SSE:
fnsave [eax]
ret
 
align 4
fpu_restore:
push ecx
push esi
 
mov esi, eax
 
pushfd
cli
 
mov ecx, [fpu_owner]
mov eax, [CURRENT_TASK]
cmp ecx, eax
jne .copy
 
clts
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxrstor [esi]
popfd
pop esi
pop ecx
ret
.no_SSE:
fnclex ;fix possible problems
frstor [esi]
popfd
pop esi
pop ecx
ret
.copy:
shl eax, 8
mov edi, [eax+SLOT_BASE+APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
popfd
pop esi
pop ecx
ret
 
align 4
e7: ;#NM exception handler
save_ring3_context
clts
mov ax, app_data ;
mov ds, ax
mov es, ax
 
mov ebx, [fpu_owner]
cmp ebx, [CURRENT_TASK]
je .exit
 
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxsave [eax]
mov ebx, [CURRENT_TASK]
mov [fpu_owner], ebx
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
fxrstor [eax]
.exit:
restore_ring3_context
iret
 
.no_SSE:
fnsave [eax]
mov ebx, [CURRENT_TASK]
mov [fpu_owner], ebx
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
frstor [eax]
restore_ring3_context
iret
 
iglobal
fpu_owner dd 0
endg
 
reg_eip equ ebp+4
reg_cs equ ebp+8
reg_eflags equ ebp+12
reg_esp equ ebp+16
reg_ss equ ebp+20
 
align 4
except_16: ;fpu native exceptions handler
test byte [esp+8+2], 2
jnz v86_except_16
push ebp
mov ebp, esp
 
push eax
push ebx
push ecx
push edx
 
mov ebx, [CURRENT_TASK]
shl ebx, 8
 
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_handler]
test eax, eax
jz .default
 
mov ecx, [reg_eip]
mov edx, [reg_esp]
sub edx, 4
mov [edx], ecx
mov [reg_esp], edx
mov dword [reg_eip], eax
 
pop edx
pop ecx
pop ebx
pop eax
 
leave
iretd
 
.default:
pop edx
pop ecx
pop ebx
pop eax
leave
 
save_ring3_context ;debugger support
 
mov bl, 16
jmp exc_c
 
align 4
except_19: ;sse exceptions handler
test byte [esp+8+2], 2
jnz v86_except_19
push ebp
mov ebp, esp
 
push eax
push ebx
push ecx
push edx
 
mov ebx, [current_slot]
 
mov eax, [ebx+APPDATA.sse_handler]
test eax, eax
jz .default
 
mov ecx, [reg_eip]
mov edx, [reg_esp]
sub edx, 4
mov [edx], ecx
mov [reg_esp], edx
mov dword [reg_eip], eax
 
pop edx
pop ecx
pop ebx
pop eax
 
leave
iretd
 
.default:
pop edx
pop ecx
pop ebx
pop eax
leave
 
save_ring3_context ;debugger support
 
mov bl, 19
jmp exc_c
 
restore reg_eip
restore reg_cs
restore reg_eflags
restore reg_esp
restore reg_ss
 
 
/kernel/branches/core/heap.inc
0,0 → 1,1443
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 983 $
 
 
struc MEM_BLOCK
{ .next_block dd ?
.prev_block dd ? ;+4
.list_fd dd ? ;+8
.list_bk dd ? ;+12
.base dd ? ;+16
.size dd ? ;+20
.flags dd ? ;+24
.handle dd ? ;+28
}
 
MEM_LIST_OFFSET equ 8
FREE_BLOCK equ 4
USED_BLOCK equ 8
DONT_FREE_BLOCK equ 10h
 
virtual at 0
MEM_BLOCK MEM_BLOCK
end virtual
 
MEM_BLOCK_SIZE equ 8*4
 
block_next equ MEM_BLOCK.next_block
block_prev equ MEM_BLOCK.prev_block
list_fd equ MEM_BLOCK.list_fd
list_bk equ MEM_BLOCK.list_bk
block_base equ MEM_BLOCK.base
block_size equ MEM_BLOCK.size
block_flags equ MEM_BLOCK.flags
 
macro calc_index op
{ shr op, 12
dec op
cmp op, 63
jna @f
mov op, 63
@@:
}
 
macro remove_from_list op
{ mov edx, [op+list_fd]
mov ecx, [op+list_bk]
test edx, edx
jz @f
mov [edx+list_bk], ecx
@@:
test ecx, ecx
jz @f
mov [ecx+list_fd], edx
@@:
mov [op+list_fd],0
mov [op+list_bk],0
}
 
macro remove_from_free op
{
remove_from_list op
 
mov eax, [op+block_size]
calc_index eax
cmp [mem_block_list+eax*4], op
jne @f
mov [mem_block_list+eax*4], edx
@@:
cmp [mem_block_list+eax*4], 0
jne @f
btr [mem_block_mask], eax
@@:
}
 
macro remove_from_used op
{
mov edx, [op+list_fd]
mov ecx, [op+list_bk]
mov [edx+list_bk], ecx
mov [ecx+list_fd], edx
mov [op+list_fd], 0
mov [op+list_bk], 0
}
 
align 4
proc init_kernel_heap
 
mov ecx, 64/4
mov edi, mem_block_list
xor eax, eax
cld
rep stosd
 
mov ecx, 512/4
mov edi, mem_block_map
not eax
rep stosd
 
mov [mem_block_start], mem_block_map
mov [mem_block_end], mem_block_map+512
mov [mem_block_arr], HEAP_BASE
 
mov eax, mem_used.fd-MEM_LIST_OFFSET
mov [mem_used.fd], eax
mov [mem_used.bk], eax
 
stdcall alloc_pages, dword 32
mov ecx, 32
mov edx, eax
mov edi, HEAP_BASE
.l1:
stdcall map_page,edi,edx,PG_SW
add edi, 0x1000
add edx, 0x1000
dec ecx
jnz .l1
 
mov edi, HEAP_BASE
mov ebx, HEAP_BASE+MEM_BLOCK_SIZE
xor eax, eax
mov [edi+block_next], ebx
mov [edi+block_prev], eax
mov [edi+list_fd], eax
mov [edi+list_bk], eax
mov [edi+block_base], HEAP_BASE
mov [edi+block_size], 4096*MEM_BLOCK_SIZE
mov [edi+block_flags], USED_BLOCK
 
mov [ebx+block_next], eax
mov [ebx+block_prev], eax
mov [ebx+list_fd], eax
mov [ebx+list_bk], eax
mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
 
mov ecx, [MEM_AMOUNT]
sub ecx, (HEAP_BASE - OS_BASE + 4096*MEM_BLOCK_SIZE)
mov [heap_size], ecx
mov [heap_free], ecx
mov [ebx+block_size], ecx
mov [ebx+block_flags], FREE_BLOCK
 
mov [mem_block_mask], eax
mov [mem_block_mask+4],0x80000000
 
mov [mem_block_list+63*4], ebx
mov byte [mem_block_map], 0xFC
and [heap_mutex], 0
mov [heap_blocks], 4095
mov [free_blocks], 4095
ret
endp
 
; param
; eax= required size
;
; retval
; edi= memory block descriptor
; ebx= descriptor index
 
align 4
get_small_block:
mov ecx, eax
shr ecx, 12
dec ecx
cmp ecx, 63
jle .get_index
mov ecx, 63
.get_index:
lea esi, [mem_block_mask]
xor ebx, ebx
or edx, -1
 
cmp ecx, 32
jb .bit_test
 
sub ecx, 32
add ebx, 32
add esi, 4
.bit_test:
shl edx, cl
and edx, [esi]
.find:
bsf edi, edx
jz .high_mask
add ebx, edi
mov edi, [mem_block_list+ebx*4]
.check_size:
cmp eax, [edi+block_size]
ja .next
ret
 
.high_mask:
add esi, 4
cmp esi, mem_block_mask+8
jae .err
add ebx, 32
mov edx, [esi]
jmp .find
.next:
mov edi, [edi+list_fd]
test edi, edi
jnz .check_size
.err:
xor edi, edi
ret
 
align 4
alloc_mem_block:
 
mov ebx, [mem_block_start]
mov ecx, [mem_block_end]
.l1:
bsf eax,[ebx];
jnz found
add ebx,4
cmp ebx, ecx
jb .l1
xor eax,eax
ret
 
found:
btr [ebx], eax
mov [mem_block_start],ebx
sub ebx, mem_block_map
lea eax,[eax+ebx*8]
shl eax, 5
add eax, [mem_block_arr]
dec [free_blocks]
ret
align 4
free_mem_block:
mov dword [eax], 0
mov dword [eax+4], 0
mov dword [eax+8], 0
mov dword [eax+12], 0
mov dword [eax+16], 0
; mov dword [eax+20], 0
mov dword [eax+24], 0
mov dword [eax+28], 0
 
sub eax, [mem_block_arr]
shr eax, 5
 
mov ebx, mem_block_map
bts [ebx], eax
inc [free_blocks]
shr eax, 3
and eax, not 3
add eax, ebx
cmp [mem_block_start], eax
ja @f
ret
@@:
mov [mem_block_start], eax
ret
.err:
xor eax, eax
ret
 
align 4
proc alloc_kernel_space stdcall, size:dword
local block_ind:DWORD
 
push ebx
push esi
push edi
 
mov eax, [size]
add eax, 4095
and eax, not 4095
mov [size], eax
 
mov ebx, heap_mutex
call wait_mutex ;ebx
 
cmp eax, [heap_free]
ja .error
 
call get_small_block ; eax
test edi, edi
jz .error
 
cmp [edi+block_flags], FREE_BLOCK
jne .error
 
mov [block_ind], ebx ;index of allocated block
 
mov eax, [edi+block_size]
cmp eax, [size]
je .m_eq_size
 
call alloc_mem_block
and eax, eax
jz .error
 
mov esi, eax ;esi - splitted block
 
mov [esi+block_next], edi
mov eax, [edi+block_prev]
mov [esi+block_prev], eax
mov [edi+block_prev], esi
mov [esi+list_fd], 0
mov [esi+list_bk], 0
and eax, eax
jz @f
mov [eax+block_next], esi
@@:
mov ebx, [edi+block_base]
mov [esi+block_base], ebx
mov edx, [size]
mov [esi+block_size], edx
add [edi+block_base], edx
sub [edi+block_size], edx
 
mov eax, [edi+block_size]
shr eax, 12
sub eax, 1
cmp eax, 63
jna @f
mov eax, 63
@@:
cmp eax, [block_ind]
je .m_eq_ind
 
remove_from_list edi
 
mov ecx, [block_ind]
mov [mem_block_list+ecx*4], edx
 
test edx, edx
jnz @f
btr [mem_block_mask], ecx
@@:
mov edx, [mem_block_list+eax*4]
mov [edi+list_fd], edx
test edx, edx
jz @f
mov [edx+list_bk], edi
@@:
mov [mem_block_list+eax*4], edi
bts [mem_block_mask], eax
.m_eq_ind:
mov ecx, mem_used.fd-MEM_LIST_OFFSET
mov edx, [ecx+list_fd]
mov [esi+list_fd], edx
mov [esi+list_bk], ecx
mov [ecx+list_fd], esi
mov [edx+list_bk], esi
 
mov [esi+block_flags], USED_BLOCK
mov eax, [esi+block_base]
mov ebx, [size]
sub [heap_free], ebx
and [heap_mutex], 0
pop edi
pop esi
pop ebx
ret
.m_eq_size:
remove_from_list edi
mov [mem_block_list+ebx*4], edx
and edx, edx
jnz @f
btr [mem_block_mask], ebx
@@:
mov ecx, mem_used.fd-MEM_LIST_OFFSET
mov edx, [ecx+list_fd]
mov [edi+list_fd], edx
mov [edi+list_bk], ecx
mov [ecx+list_fd], edi
mov [edx+list_bk], edi
 
mov [edi+block_flags], USED_BLOCK
mov eax, [edi+block_base]
mov ebx, [size]
sub [heap_free], ebx
and [heap_mutex], 0
pop edi
pop esi
pop ebx
ret
.error:
xor eax, eax
mov [heap_mutex], eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
push ebx
push esi
push edi
mov ebx, heap_mutex
call wait_mutex ;ebx
 
mov eax, [base]
mov esi, [mem_used.fd]
@@:
cmp esi, mem_used.fd-MEM_LIST_OFFSET
je .fail
 
cmp [esi+block_base], eax
je .found
mov esi, [esi+list_fd]
jmp @b
.found:
cmp [esi+block_flags], USED_BLOCK
jne .fail
 
mov eax, [esi+block_size]
add [heap_free], eax
 
mov edi, [esi+block_next]
test edi, edi
jz .prev
 
cmp [edi+block_flags], FREE_BLOCK
jne .prev
 
remove_from_free edi
 
mov edx, [edi+block_next]
mov [esi+block_next], edx
test edx, edx
jz @f
 
mov [edx+block_prev], esi
@@:
mov ecx, [edi+block_size]
add [esi+block_size], ecx
 
mov eax, edi
call free_mem_block
.prev:
mov edi, [esi+block_prev]
test edi, edi
jz .insert
 
cmp [edi+block_flags], FREE_BLOCK
jne .insert
 
remove_from_used esi
 
mov edx, [esi+block_next]
mov [edi+block_next], edx
test edx, edx
jz @f
mov [edx+block_prev], edi
@@:
mov eax, esi
call free_mem_block
 
mov ecx, [edi+block_size]
mov eax, [esi+block_size]
add eax, ecx
mov [edi+block_size], eax
 
calc_index eax
calc_index ecx
cmp eax, ecx
je .m_eq
 
push ecx
remove_from_list edi
pop ecx
 
cmp [mem_block_list+ecx*4], edi
jne @f
mov [mem_block_list+ecx*4], edx
@@:
cmp [mem_block_list+ecx*4], 0
jne @f
btr [mem_block_mask], ecx
@@:
mov esi, [mem_block_list+eax*4]
mov [mem_block_list+eax*4], edi
mov [edi+list_fd], esi
test esi, esi
jz @f
mov [esi+list_bk], edi
@@:
bts [mem_block_mask], eax
.m_eq:
xor eax, eax
mov [heap_mutex], eax
dec eax
pop edi
pop esi
pop ebx
ret
.insert:
remove_from_used esi
 
mov eax, [esi+block_size]
calc_index eax
 
mov edi, [mem_block_list+eax*4]
mov [mem_block_list+eax*4], esi
mov [esi+list_fd], edi
test edi, edi
jz @f
mov [edi+list_bk], esi
@@:
bts [mem_block_mask], eax
mov [esi+block_flags],FREE_BLOCK
xor eax, eax
mov [heap_mutex], eax
dec eax
pop edi
pop esi
pop ebx
ret
.fail:
xor eax, eax
mov [heap_mutex], eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc kernel_alloc stdcall, size:dword
locals
lin_addr dd ?
pages_count dd ?
endl
 
push ebx
push edi
push edx
 
mov eax, [size]
add eax, 4095
and eax, not 4095;
mov [size], eax
and eax, eax
jz .err
mov ebx, eax
shr ebx, 12
mov [pages_count], ebx
 
stdcall alloc_kernel_space, eax
test eax, eax
jz .err
mov [lin_addr], eax
 
mov ecx, [pages_count]
mov edx, eax
mov ebx, ecx
 
shr ecx, 3
jz .next
 
and ebx, not 7
push ebx
stdcall alloc_pages, ebx
pop ecx ; yes ecx!!!
and eax, eax
jz .err
 
mov edi, eax
mov edx, [lin_addr]
@@:
stdcall map_page,edx,edi,dword PG_SW
add edx, 0x1000
add edi, 0x1000
dec ecx
jnz @B
.next:
mov ecx, [pages_count]
and ecx, 7
jz .end
@@:
push ecx
call alloc_page
pop ecx
test eax, eax
jz .err
 
stdcall map_page,edx,eax,dword PG_SW
add edx, 0x1000
dec ecx
jnz @B
.end:
mov eax, [lin_addr]
pop edx
pop edi
pop ebx
ret
.err:
xor eax, eax
pop edx
pop edi
pop ebx
ret
endp
 
align 4
proc kernel_free stdcall, base:dword
push ebx esi
 
mov ebx, heap_mutex
call wait_mutex ;ebx
 
mov eax, [base]
mov esi, [mem_used.fd]
@@:
cmp esi, mem_used.fd-MEM_LIST_OFFSET
je .fail
 
cmp [esi+block_base], eax
je .found
mov esi, [esi+list_fd]
jmp @b
.found:
cmp [esi+block_flags], USED_BLOCK
jne .fail
 
and [heap_mutex], 0
 
push ecx
mov ecx, [esi+block_size];
shr ecx, 12
call release_pages ;eax, ecx
pop ecx
stdcall free_kernel_space, [base]
pop esi ebx
ret
.fail:
and [heap_mutex], 0
pop esi ebx
ret
endp
 
restore block_next
restore block_prev
restore block_list
restore block_base
restore block_size
restore block_flags
 
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
 
HEAP_TOP equ 0x5FC00000
 
align 4
proc init_heap
 
mov ebx,[current_slot]
mov eax, [ebx+APPDATA.heap_top]
test eax, eax
jz @F
sub eax,[ebx+APPDATA.heap_base]
sub eax, 4096
ret
@@:
mov esi, [ebx+APPDATA.mem_size]
add esi, 4095
and esi, not 4095
mov [ebx+APPDATA.mem_size], esi
mov eax, HEAP_TOP
mov [ebx+APPDATA.heap_base], esi
mov [ebx+APPDATA.heap_top], eax
 
sub eax, esi
shr esi, 10
mov ecx, eax
sub eax, 4096
or ecx, FREE_BLOCK
mov [page_tabs+esi], ecx
ret
endp
 
align 4
proc user_alloc stdcall, alloc_size:dword
 
push ebx
push esi
push edi
 
mov ecx, [alloc_size]
add ecx, (4095+4096)
and ecx, not 4095
 
mov ebx, [current_slot]
mov esi, dword [ebx+APPDATA.heap_base] ; heap_base
mov edi, dword [ebx+APPDATA.heap_top] ; heap_top
l_0:
cmp esi, edi
jae m_exit
 
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
test al, FREE_BLOCK
jz test_used
and eax, 0xFFFFF000
cmp eax, ecx ;alloc_size
jb m_next
jz @f
 
lea edx, [esi+ecx]
sub eax, ecx
or al, FREE_BLOCK
shr edx, 12
mov [page_tabs+edx*4], eax
@@:
or ecx, USED_BLOCK
mov [page_tabs+ebx*4], ecx
shr ecx, 12
inc ebx
dec ecx
jz .no
@@:
mov dword [page_tabs+ebx*4], 2
inc ebx
dec ecx
jnz @B
.no:
 
mov edx, [current_slot]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
 
lea eax, [esi+4096]
 
pop edi
pop esi
pop ebx
ret
test_used:
test al, USED_BLOCK
jz m_exit
 
and eax, 0xFFFFF000
m_next:
add esi, eax
jmp l_0
m_exit:
xor eax, eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc user_free stdcall, base:dword
 
push esi
 
mov esi, [base]
test esi, esi
jz .exit
 
push ebx
 
xor ebx, ebx
shr esi, 12
mov eax, [page_tabs+(esi-1)*4]
test al, USED_BLOCK
jz .cantfree
test al, DONT_FREE_BLOCK
jnz .cantfree
 
and eax, not 4095
mov ecx, eax
or al, FREE_BLOCK
mov [page_tabs+(esi-1)*4], eax
sub ecx, 4096
mov ebx, ecx
shr ecx, 12
jz .released
.release:
xor eax, eax
xchg eax, [page_tabs+esi*4]
test al, 1
jz @F
test eax, PG_SHARED
jnz @F
call free_page
mov eax, esi
shl eax, 12
invlpg [eax]
@@:
inc esi
dec ecx
jnz .release
.released:
push edi
 
mov edx, [current_slot]
mov esi, dword [edx+APPDATA.heap_base]
mov edi, dword [edx+APPDATA.heap_top]
sub ebx, [edx+APPDATA.mem_size]
neg ebx
call update_mem_size
call user_normalize
pop edi
pop ebx
pop esi
ret
.exit:
xor eax, eax
inc eax
pop esi
ret
.cantfree:
xor eax, eax
pop ebx
pop esi
ret
endp
 
user_normalize:
; in: esi=heap_base, edi=heap_top
; out: eax=0 <=> OK
; destroys: ebx,edx,esi,edi
shr esi, 12
shr edi, 12
@@:
mov eax, [page_tabs+esi*4]
test al, USED_BLOCK
jz .test_free
shr eax, 12
add esi, eax
jmp @B
.test_free:
test al, FREE_BLOCK
jz .err
mov edx, eax
shr edx, 12
add edx, esi
cmp edx, edi
jae .exit
 
mov ebx, [page_tabs+edx*4]
test bl, USED_BLOCK
jz .next_free
 
shr ebx, 12
add edx, ebx
mov esi, edx
jmp @B
.next_free:
test bl, FREE_BLOCK
jz .err
and dword [page_tabs+edx*4], 0
add eax, ebx
and eax, not 4095
or eax, FREE_BLOCK
mov [page_tabs+esi*4], eax
jmp @B
.exit:
xor eax, eax
inc eax
ret
.err:
xor eax, eax
ret
 
user_realloc:
; in: eax = pointer, ebx = new size
; out: eax = new pointer or NULL
test eax, eax
jnz @f
; realloc(NULL,sz) - same as malloc(sz)
push ebx
call user_alloc
ret
@@:
push ecx edx
lea ecx, [eax - 0x1000]
shr ecx, 12
mov edx, [page_tabs+ecx*4]
test dl, USED_BLOCK
jnz @f
; attempt to realloc invalid pointer
.ret0:
pop edx ecx
xor eax, eax
ret
@@:
test dl, DONT_FREE_BLOCK
jnz .ret0
add ebx, 0x1FFF
shr edx, 12
shr ebx, 12
; edx = allocated size, ebx = new size
add edx, ecx
add ebx, ecx
cmp edx, ebx
jb .realloc_add
; release part of allocated memory
.loop:
cmp edx, ebx
jz .release_done
dec edx
xor eax, eax
xchg eax, [page_tabs+edx*4]
test al, 1
jz .loop
call free_page
mov eax, edx
shl eax, 12
invlpg [eax]
jmp .loop
.release_done:
sub ebx, ecx
cmp ebx, 1
jnz .nofreeall
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
mov edx, [current_slot]
mov ebx, [APPDATA.mem_size+edx]
sub ebx, eax
add ebx, 0x1000
or al, FREE_BLOCK
mov [page_tabs+ecx*4], eax
push esi edi
mov esi, [APPDATA.heap_base+edx]
mov edi, [APPDATA.heap_top+edx]
call update_mem_size
call user_normalize
pop edi esi
jmp .ret0 ; all freed
.nofreeall:
sub edx, ecx
shl ebx, 12
or ebx, USED_BLOCK
xchg [page_tabs+ecx*4], ebx
shr ebx, 12
sub ebx, edx
push ebx ecx edx
mov edx, [current_slot]
shl ebx, 12
sub ebx, [APPDATA.mem_size+edx]
neg ebx
call update_mem_size
pop edx ecx ebx
lea eax, [ecx+1]
shl eax, 12
push eax
add ecx, edx
lea edx, [ecx+ebx]
shl ebx, 12
jz .ret
push esi
mov esi, [current_slot]
mov esi, [APPDATA.heap_top+esi]
shr esi, 12
@@:
cmp edx, esi
jae .merge_done
mov eax, [page_tabs+edx*4]
test al, USED_BLOCK
jnz .merge_done
and dword [page_tabs+edx*4], 0
shr eax, 12
add edx, eax
shl eax, 12
add ebx, eax
jmp @b
.merge_done:
pop esi
or ebx, FREE_BLOCK
mov [page_tabs+ecx*4], ebx
.ret:
pop eax edx ecx
ret
.realloc_add:
; get some additional memory
mov eax, [current_slot]
mov eax, [APPDATA.heap_top+eax]
shr eax, 12
cmp edx, eax
jae .cant_inplace
mov eax, [page_tabs+edx*4]
test al, FREE_BLOCK
jz .cant_inplace
shr eax, 12
add eax, edx
sub eax, ebx
jb .cant_inplace
jz @f
shl eax, 12
or al, FREE_BLOCK
mov [page_tabs+ebx*4], eax
@@:
mov eax, ebx
sub eax, ecx
shl eax, 12
or al, USED_BLOCK
mov [page_tabs+ecx*4], eax
lea eax, [ecx+1]
shl eax, 12
push eax
push edi
lea edi, [page_tabs+edx*4]
mov eax, 2
sub ebx, edx
mov ecx, ebx
cld
rep stosd
pop edi
mov edx, [current_slot]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
pop eax edx ecx
ret
.cant_inplace:
push esi edi
mov eax, [current_slot]
mov esi, [APPDATA.heap_base+eax]
mov edi, [APPDATA.heap_top+eax]
shr esi, 12
shr edi, 12
sub ebx, ecx
.find_place:
cmp esi, edi
jae .place_not_found
mov eax, [page_tabs+esi*4]
test al, FREE_BLOCK
jz .next_place
shr eax, 12
cmp eax, ebx
jae .place_found
add esi, eax
jmp .find_place
.next_place:
shr eax, 12
add esi, eax
jmp .find_place
.place_not_found:
pop edi esi
jmp .ret0
.place_found:
sub eax, ebx
jz @f
push esi
add esi, ebx
shl eax, 12
or al, FREE_BLOCK
mov [page_tabs+esi*4], eax
pop esi
@@:
mov eax, ebx
shl eax, 12
or al, USED_BLOCK
mov [page_tabs+esi*4], eax
inc esi
mov eax, esi
shl eax, 12
push eax
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
or al, FREE_BLOCK
sub edx, ecx
mov [page_tabs+ecx*4], eax
inc ecx
dec ebx
dec edx
jz .no
@@:
xor eax, eax
xchg eax, [page_tabs+ecx*4]
mov [page_tabs+esi*4], eax
mov eax, ecx
shl eax, 12
invlpg [eax]
inc esi
inc ecx
dec ebx
dec edx
jnz @b
.no:
push ebx
mov edx, [current_slot]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
pop ebx
@@:
mov dword [page_tabs+esi*4], 2
inc esi
dec ebx
jnz @b
pop eax edi esi edx ecx
ret
 
if 0
align 4
proc alloc_dll
pushf
cli
bsf eax, [dll_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [dll_map], eax
popf
shl eax, 5
add eax, dll_tab
ret
endp
 
align 4
proc alloc_service
pushf
cli
bsf eax, [srv_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [srv_map], eax
popf
shl eax,0x02
lea eax,[srv_tab+eax+eax*8] ;srv_tab+eax*36
ret
endp
 
end if
 
 
;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;;
 
 
; param
; eax= shm_map object
 
align 4
destroy_smap:
 
pushfd
cli
 
push esi
push edi
 
mov edi, eax
mov esi, [eax+SMAP.parent]
test esi, esi
jz .done
 
lock dec [esi+SMEM.refcount]
jnz .done
 
mov ecx, [esi+SMEM.bk]
mov edx, [esi+SMEM.fd]
 
mov [ecx+SMEM.fd], edx
mov [edx+SMEM.bk], ecx
 
stdcall kernel_free, [esi+SMEM.base]
mov eax, esi
call free
.done:
mov eax, edi
call destroy_kernel_object
 
pop edi
pop esi
popfd
 
ret
 
E_NOTFOUND equ 5
E_ACCESS equ 10
E_NOMEM equ 30
E_PARAM equ 33
 
SHM_READ equ 0
SHM_WRITE equ 1
 
SHM_ACCESS_MASK equ 3
 
SHM_OPEN equ (0 shl 2)
SHM_OPEN_ALWAYS equ (1 shl 2)
SHM_CREATE equ (2 shl 2)
 
SHM_OPEN_MASK equ (3 shl 2)
 
align 4
proc shmem_open stdcall name:dword, size:dword, access:dword
locals
action dd ?
owner_access dd ?
mapped dd ?
endl
 
push ebx
push esi
push edi
 
mov [mapped], 0
mov [owner_access], 0
 
pushfd ;mutex required
cli
 
mov eax, [access]
and eax, SHM_OPEN_MASK
mov [action], eax
 
mov eax, [name]
test eax, eax
mov edx, E_PARAM
jz .exit
 
mov esi, [shmem_list.fd]
align 4
@@:
cmp esi, shmem_list
je .not_found
 
lea edx, [esi+SMEM.name] ; link , base, size
stdcall strncmp, edx, eax, 32
test eax, eax
je .found
 
mov esi, [esi+SMEM.fd]
jmp @B
 
.not_found:
mov eax, [action]
 
cmp eax, SHM_OPEN
mov edx, E_NOTFOUND
je .exit
 
cmp eax, SHM_CREATE
mov edx, E_PARAM
je .create_shm
 
cmp eax, SHM_OPEN_ALWAYS
jne .exit
 
.create_shm:
 
mov ecx, [size]
test ecx, ecx
jz .exit
 
add ecx, 4095
and ecx, -4096
mov [size], ecx
 
mov eax, SMEM.sizeof
call malloc
test eax, eax
mov esi, eax
mov edx, E_NOMEM
jz .exit
 
stdcall kernel_alloc, [size]
test eax, eax
mov [mapped], eax
mov edx, E_NOMEM
jz .cleanup
 
mov ecx, [size]
mov edx, [access]
and edx, SHM_ACCESS_MASK
 
mov [esi+SMEM.base], eax
mov [esi+SMEM.size], ecx
mov [esi+SMEM.access], edx
mov [esi+SMEM.refcount], 0
mov [esi+SMEM.name+28], 0
 
lea eax, [esi+SMEM.name]
stdcall strncpy, eax, [name], 31
 
mov eax, [shmem_list.fd]
mov [esi+SMEM.bk], shmem_list
mov [esi+SMEM.fd], eax
 
mov [eax+SMEM.bk], esi
mov [shmem_list.fd], esi
 
mov [action], SHM_OPEN
mov [owner_access], SHM_WRITE
 
.found:
mov eax, [action]
 
cmp eax, SHM_CREATE
mov edx, E_ACCESS
je .exit
 
cmp eax, SHM_OPEN
mov edx, E_PARAM
je .create_map
 
cmp eax, SHM_OPEN_ALWAYS
jne .exit
 
.create_map:
 
mov eax, [access]
and eax, SHM_ACCESS_MASK
cmp eax, [esi+SMEM.access]
mov [access], eax
mov edx, E_ACCESS
ja .exit
 
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov ebx, [CURRENT_TASK+ebx+4]
mov eax, SMAP.sizeof
 
call create_kernel_object
test eax, eax
mov edi, eax
mov edx, E_NOMEM
jz .exit
 
mov [edi+SMAP.magic], 'SMAP'
mov [edi+SMAP.destroy], destroy_smap
mov [edi+SMAP.base], 0
mov [edi+SMAP.parent], 0
 
stdcall user_alloc, [esi+SMEM.size]
test eax, eax
mov [mapped], eax
mov edx, E_NOMEM
jz .cleanup2
 
lock inc [esi+SMEM.refcount]
mov [edi+SMAP.base], eax
mov [edi+SMAP.parent], esi
 
mov ecx, [esi+SMEM.size]
mov [size], ecx
 
shr ecx, 12
shr eax, 10
 
mov esi, [esi+SMEM.base]
shr esi, 10
lea edi, [page_tabs+eax]
add esi, page_tabs
 
mov edx, [access]
or edx, [owner_access]
shl edx, 1
or edx, PG_USER+PG_SHARED
@@:
lodsd
and eax, 0xFFFFF000
or eax, edx
stosd
loop @B
 
xor edx, edx
 
cmp [owner_access], 0
jne .exit
 
mov edx, [size]
.exit:
mov eax, [mapped]
 
popfd
pop edi
pop esi
pop ebx
ret
 
.cleanup:
mov eax, esi
call free
jmp .exit
 
.cleanup2:
mov eax, edi
call destroy_smap
jmp .exit
endp
 
align 4
proc shmem_close stdcall, name:dword
 
mov eax, [name]
test eax, eax
jz .fail
 
push esi
push edi
pushfd
cli
 
mov esi, [current_slot]
add esi, APP_OBJ_OFFSET
.next:
mov eax, [esi+APPOBJ.fd]
test eax, eax
jz @F
 
cmp eax, esi
mov esi, eax
je @F
 
cmp [eax+SMAP.magic], 'SMAP'
jne .next
 
mov edi, [eax+SMAP.parent]
test edi, edi
jz .next
 
lea eax, [edi+SMEM.name]
stdcall strncmp, [name], edi, 32
test eax, eax
jne .next
 
stdcall user_free, [esi+SMAP.base]
 
call [esi+APPOBJ.destroy]
@@:
popfd
pop edi
pop esi
.fail:
ret
endp
/kernel/branches/core/malloc.inc
0,0 → 1,1003
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 753 $
 
 
; Small heap based on malloc/free/realloc written by Doug Lea
; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee)
; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c
; License http://creativecommons.org/licenses/publicdomain.
 
 
; eax= size
 
; temp
; esi= nb
; ebx= idx
;
malloc:
push esi
 
; nb = ((size+7)&~7)+8;
 
mov esi, eax ;size
add esi, 7
and esi, -8
add esi, 8
 
mov ebx, mst.mutex
call wait_mutex ;ebx
 
cmp esi, 256
jae .large
 
mov ecx, esi
shr ecx, 3
or eax, -1
shl eax, cl
and eax, [mst.smallmap]
jz .small
 
push ebp
push edi
 
bsf eax, eax
mov ebx, eax
 
; psize= idx<<3;
; B = &ms.smallbins[idx];
; p = B->fd;
; F = p->fd;
; rsize= psize-nb;
 
lea ebp, [eax*8] ;ebp= psize
shl eax, 4
lea edi, [mst.smallbins+eax] ;edi= B
mov edx, [edi+8] ;edx= p
mov eax, [edx+8] ;eax= F
mov ecx, ebp
sub ecx, esi ;ecx= rsize
 
; if (B == F)
cmp edi, eax
jne @F
 
btr [mst.smallmap], ebx
@@:
 
; B->fd = F;
; F->bk = B;
; if(rsize<16)
 
cmp ecx, 16
mov [edi+8], eax
mov [eax+12], edi
jae .split
 
; p->head = psize|PINUSE_BIT|CINUSE_BIT;
; (p + psize)->head |= PINUSE_BIT;
 
lea eax, [edx+8]
or dword [edx+ebp+4], 1
 
or ebp, 3
mov [edx+4], ebp
 
pop edi
pop ebp
.done:
pop esi
mov [mst.mutex], 0
ret
.split:
lea ebx, [edx+8] ;ebx=mem
 
; r = chunk_plus_offset(p, nb);
; p->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
 
lea eax, [edx+esi] ;eax= r
or esi, 3
mov [edx+4], esi
 
mov edx, ecx
or edx, 1
mov [eax+4], edx
 
; (r + rsize)->prev_foot = rsize;
 
mov [eax+ecx], ecx
 
; I = rsize>>3;
 
shr ecx, 3
 
; ms.smallmap |= 1<< I;
bts [mst.smallmap], ecx
 
; B = &ms.smallbins[I];
 
shl ecx, 4
pop edi
pop ebp
add ecx, mst.smallbins ;ecx= B
 
mov edx, [ecx+8] ; F = B->fd;
mov [ecx+8], eax ; B->fd = r;
mov [edx+12], eax ; F->bk = r;
mov [eax+8], edx ; r->fd = F;
mov [eax+12], ecx ; r->bk = B;
mov eax, ebx
pop esi
ret
.small:
 
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0)
 
cmp [mst.treemap], 0
je .from_top
mov eax, esi
call malloc_small
test eax, eax
jz .from_top
pop esi
and [mst.mutex], 0
ret
.large:
 
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0)
 
cmp [mst.treemap], 0
je .from_top
 
call malloc_large ;esi= nb
test eax, eax
jne .done
.from_top:
 
; if (nb < ms.topsize)
 
mov eax, [mst.topsize]
cmp esi, eax
jae .fail
 
; rsize = ms.topsize -= nb;
; p = ms.top;
 
mov ecx, [mst.top]
sub eax, esi
mov [mst.topsize], eax
 
; r = ms.top = chunk_plus_offset(p, nb);
; r->head = rsize | PINUSE_BIT;
; p->head = nb |PINUSE_BIT|CINUSE_BIT;
 
lea edx, [ecx+esi]
or eax, 1
mov [mst.top], edx
or esi, 3
mov [edx+4], eax
mov [ecx+4], esi
lea eax, [ecx+8]
pop esi
and [mst.mutex], 0
ret
.fail:
xor eax, eax
pop esi
and [mst.mutex], 0
ret
 
; param
; eax= mem
 
align 4
free:
push edi
mov edi, eax
add edi, -8
 
; if(p->head & CINUSE_BIT)
 
test byte [edi+4], 2
je .fail
 
mov ebx, mst.mutex
call wait_mutex ;ebx
 
; psize = p->head & (~3);
 
mov eax, [edi+4]
push esi
mov esi, eax
and esi, -4
 
; next = chunk_plus_offset(p, psize);
; if(!(p->head & PINUSE_BIT))
 
test al, 1
lea ebx, [esi+edi]
jne .next
 
; prevsize = p->prev_foot;
; prev=p - prevsize;
; psize += prevsize;
; p = prev;
 
mov ecx, [edi] ;ecx= prevsize
add esi, ecx ;esi= psize
sub edi, ecx ;edi= p
 
; if (prevsize < 256)
 
cmp ecx, 256
jae .unlink_large
 
mov eax, [edi+8] ;F = p->fd;
mov edx, [edi+12] ;B = p->bk;
 
; if (F == B)
; ms.smallmap &= ~(1<< I);
shr ecx, 3
cmp eax, edx
jne @F
and [mst.smallmap], ecx
@@:
mov [eax+12], edx ;F->bk = B;
mov [edx+8], eax ;B->fd = F
jmp .next
.unlink_large:
mov edx, edi
call unlink_large_chunk
.next:
 
; if(next->head & PINUSE_BIT)
 
mov eax, [ebx+4]
test al, 1
jz .fail2
 
; if (! (next->head & CINUSE_BIT))
 
test al, 2
jnz .fix_next
 
; if (next == ms.top)
 
cmp ebx, [mst.top]
jne @F
 
; tsize = ms.topsize += psize;
 
mov eax, [mst.topsize]
add eax, esi
mov [mst.topsize], eax
 
; ms.top = p;
; p->head = tsize | PINUSE_BIT;
 
or eax, 1
mov [mst.top], edi
mov [edi+4], eax
.fail2:
and [mst.mutex], 0
pop esi
.fail:
pop edi
ret
@@:
 
; nsize = next->head & ~INUSE_BITS;
 
and eax, -4
add esi, eax ;psize += nsize;
 
; if (nsize < 256)
 
cmp eax, 256
jae .unl_large
 
mov edx, [ebx+8] ;F = next->fd
mov ebx, [ebx+12] ;B = next->bk
 
; if (F == B)
 
cmp edx, ebx
jne @F
mov ecx, eax
shr ecx, 3
btr [mst.smallmap], ecx
@@:
mov [edx+12], ebx ;F->bk = B
 
; p->head = psize|PINUSE_BIT;
 
mov ecx, esi
mov [ebx+8], edx
or ecx, 1
mov [edi+4], ecx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
 
; insert_chunk(p,psize);
 
mov eax, esi
pop esi
mov ecx, edi
pop edi
jmp insert_chunk
.unl_large:
 
; unlink_large_chunk((tchunkptr)next);
 
mov edx, ebx
call unlink_large_chunk
; p->head = psize|PINUSE_BIT;
 
mov ecx, esi
or ecx, 1
mov [edi+4], ecx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
 
; insert_chunk(p,psize);
 
mov eax, esi
pop esi
mov ecx, edi
pop edi
jmp insert_chunk
.fix_next:
 
; (p+psize)->prev_foot = psize;
; next->head &= ~PINUSE_BIT;
; p->head = psize|PINUSE_BIT;
 
and eax, -2
mov edx, esi
mov [ebx+4], eax
or edx, 1
mov [edi+4], edx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
; insert_chunk(p,psize);
 
mov eax, esi
pop esi
mov ecx, edi
pop edi
jmp insert_chunk
 
; param
; ecx = chunk
; eax = size
 
align 4
insert_chunk:
 
cmp eax, 256
push esi
mov esi, ecx
jae .large
 
; I = S>>3;
; ms.smallmap |= 1<< I;
 
shr eax, 3
bts [mst.smallmap], eax
 
; B = &ms.smallbins[I];
 
shl eax, 4
add eax, mst.smallbins
mov edx, [eax+8] ;F = B->fd
mov [eax+8], esi ;B->fd = P
mov [edx+12], esi ;F->bk = P
mov [esi+8], edx ;P->fd = F
mov [esi+12], eax ;P->bk = B
pop esi
and [mst.mutex], 0
ret
.large:
mov ebx, eax
call insert_large_chunk
pop esi
and [mst.mutex], 0
ret
 
align 4
 
; param
; esi= chunk
; ebx= size
 
align 4
insert_large_chunk:
 
; I = compute_tree_index(S);
 
mov edx, ebx
shr edx, 8
bsr eax, edx
lea ecx, [eax+7]
mov edx, ebx
shr edx, cl
and edx, 1
lea ecx, [edx+eax*2]
 
; X->index = I;
mov dword [esi+28], ecx
 
; X->child[0] = X->child[1] = 0;
and dword [esi+20], 0
and dword [esi+16], 0
 
; H = &ms.treebins[I];
 
mov eax, ecx
lea edx, [mst.treebins+eax*4]
 
; if (!(ms.treemap & 1<<I))
bt [mst.treemap], ecx
jc .tree
 
; ms.treemap |= 1<<I;
bts [mst.treemap], ecx
; *H = X;
mov dword [edx], esi
jmp .done
.tree:
 
; T = *H;
mov edx, [edx]
 
; K = S << leftshift_for_tree_index(I);
mov eax, ecx
shr eax, 1
sub ecx, 31
mov edi, 37
sub edi, eax
neg ecx
sbb ecx, ecx
and ecx, edi
mov eax, ebx
shl eax, cl ;eax= K
 
jmp .loop
 
.not_eq_size:
 
; C = &(T->child[(K >> 31) & 1]);
mov ecx, eax
shr ecx, 31
lea ecx, [edx+ecx*4+16]
 
; K <<= 1;
; if (*C != 0)
mov edi, [ecx]
add eax, eax
test edi, edi
jz .insert_child
 
; T = *C;
mov edx, edi
.loop:
 
; for (;;)
; if ((T->head & ~INUSE_BITS) != S)
 
mov ecx, [edx+4]
and ecx, not 3
cmp ecx, ebx
jne .not_eq_size
 
; F = T->fd;
mov eax, [edx+8]
 
; T->fd = F->bk = X;
mov [eax+12], esi
mov [edx+8], esi
 
; X->fd = F;
; X->bk = T;
; X->parent = 0;
 
and dword [esi+24], 0
mov [esi+8], eax
mov [esi+12], edx
ret
 
.insert_child:
 
; *C = X;
mov [ecx], esi
.done:
 
; X->parent = T;
mov [esi+24], edx
 
; X->fd = X->bk = X;
mov [esi+12], esi
mov [esi+8], esi
ret
 
 
; param
; edx= chunk
 
align 4
unlink_large_chunk:
 
mov eax, [edx+12]
cmp eax, edx
push edi
mov edi, [edx+24]
je @F
 
mov ecx, [edx+8] ;F = X->fd
mov [ecx+12], eax ;F->bk = R;
mov [eax+8], ecx ;R->fd = F
jmp .parent
@@:
mov eax, [edx+20]
test eax, eax
push esi
lea esi, [edx+20]
jne .loop
 
mov eax, [edx+16]
test eax, eax
lea esi, [edx+16]
je .l2
.loop:
cmp dword [eax+20], 0
lea ecx, [eax+20]
jne @F
 
cmp dword [eax+16], 0
lea ecx, [eax+16]
je .l1
@@:
mov eax, [ecx]
mov esi, ecx
jmp .loop
.l1:
mov dword [esi], 0
.l2:
pop esi
.parent:
test edi, edi
je .done
 
mov ecx, [edx+28]
cmp edx, [mst.treebins+ecx*4]
lea ecx, [mst.treebins+ecx*4]
jne .l3
 
test eax, eax
mov [ecx], eax
jne .l5
 
mov ecx, [edx+28]
btr [mst.treemap], ecx
pop edi
ret
.l3:
cmp [edi+16], edx
jne @F
 
mov [edi+16], eax
jmp .l4
@@:
mov [edi+20], eax
.l4:
test eax, eax
je .done
.l5:
mov [eax+24], edi
mov ecx, [edx+16]
test ecx, ecx
je .l6
 
mov [eax+16], ecx
mov [ecx+24], eax
.l6:
mov edx, [edx+20]
test edx, edx
je .done
 
mov [eax+20], edx
mov [edx+24], eax
.done:
pop edi
ret
 
; param
; esi= nb
 
align 4
malloc_small:
push ebp
mov ebp, esi
 
push edi
 
bsf eax,[mst.treemap]
mov ecx, [mst.treebins+eax*4]
 
; rsize = (t->head & ~INUSE_BITS) - nb;
 
mov edi, [ecx+4]
and edi, -4
sub edi, esi
.loop:
mov ebx, ecx
.loop_1:
 
; while ((t = leftmost_child(t)) != 0)
 
mov eax, [ecx+16]
test eax, eax
jz @F
mov ecx, eax
jmp .l1
@@:
mov ecx, [ecx+20]
.l1:
test ecx, ecx
jz .unlink
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov eax, [ecx+4]
and eax, -4
sub eax, ebp
 
; if (trem < rsize)
 
cmp eax, edi
jae .loop_1
 
; rsize = trem;
 
mov edi, eax
jmp .loop
.unlink:
 
 
; r = chunk_plus_offset((mchunkptr)v, nb);
; unlink_large_chunk(v);
 
mov edx, ebx
lea esi, [ebx+ebp]
call unlink_large_chunk
 
; if (rsize < 16)
 
cmp edi, 16
jae .split
 
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
 
lea ecx, [edi+ebp]
 
; (v+rsize + nb)->head |= PINUSE_BIT;
 
add edi, ebx
lea eax, [edi+ebp+4]
pop edi
or ecx, 3
mov [ebx+4], ecx
or dword [eax], 1
pop ebp
 
lea eax, [ebx+8]
ret
.split:
 
; v->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
; (r+rsize)->prev_foot = rsize;
 
or ebp, 3
mov edx, edi
or edx, 1
 
cmp edi, 256
mov [ebx+4], ebp
mov [esi+4], edx
mov [esi+edi], edi
jae .large
 
shr edi, 3
bts [mst.smallmap], edi
 
mov eax, edi
shl eax, 4
add eax, mst.smallbins
 
mov edx, [eax+8]
mov [eax+8], esi
mov [edx+12], esi
pop edi
mov [esi+12], eax
mov [esi+8], edx
pop ebp
lea eax, [ebx+8]
ret
.large:
lea eax, [ebx+8]
push eax
mov ebx, edi
call insert_large_chunk
pop eax
pop edi
pop ebp
ret
 
 
; param
; esi= nb
 
align 4
malloc_large:
.idx equ esp+4
.rst equ esp
 
push ebp
push edi
sub esp, 8
; v = 0;
; rsize = -nb;
 
mov edi, esi
mov ebx, esi
xor ebp, ebp
neg edi
 
; idx = compute_tree_index(nb);
 
mov edx, esi
shr edx, 8
bsr eax, edx
lea ecx, [eax+7]
shr esi, cl
and esi, 1
lea ecx, [esi+eax*2]
mov [.idx], ecx
 
; if ((t = ms.treebins[idx]) != 0)
 
mov eax, [mst.treebins+ecx*4]
test eax, eax
jz .l3
 
; sizebits = nb << leftshift_for_tree_index(idx);
 
cmp ecx, 31
jne @F
xor ecx, ecx
jmp .l1
@@:
mov edx, ecx
shr edx, 1
mov ecx, 37
sub ecx, edx
.l1:
mov edx, ebx
shl edx, cl
 
; rst = 0;
mov [.rst], ebp
.loop:
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov ecx, [eax+4]
and ecx, -4
sub ecx, ebx
 
; if (trem < rsize)
 
cmp ecx, edi
jae @F
; v = t;
; if ((rsize = trem) == 0)
 
test ecx, ecx
mov ebp, eax
mov edi, ecx
je .l2
@@:
 
; rt = t->child[1];
 
mov ecx, [eax+20]
 
; t = t->child[(sizebits >> 31) & 1];
 
mov esi, edx
shr esi, 31
 
; if (rt != 0 && rt != t)
 
test ecx, ecx
mov eax, [eax+esi*4+16]
jz @F
cmp ecx, eax
jz @F
 
; rst = rt;
mov [.rst], ecx
@@:
; if (t == 0)
 
test eax, eax
jz @F
 
; sizebits <<= 1;
 
add edx, edx
jmp .loop
@@:
; t = rst;
mov eax, [.rst]
.l2:
; if (t == 0 && v == 0)
 
test eax, eax
jne .l4
test ebp, ebp
jne .l7
mov ecx, [.idx]
.l3:
 
; leftbits = (-1<<idx) & ms.treemap;
; if (leftbits != 0)
 
or edx, -1
shl edx, cl
and edx, [mst.treemap]
jz @F
 
bsf eax, edx
; t = ms.treebins[i];
mov eax, [mst.treebins+eax*4]
@@:
 
; while (t != 0)
test eax, eax
jz .l5
.l4:
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov ecx, [eax+4]
and ecx, -4
sub ecx, ebx
 
; if (trem < rsize)
 
cmp ecx, edi
jae @F
; rsize = trem;
 
mov edi, ecx
; v = t;
mov ebp, eax
@@:
 
; t = leftmost_child(t);
 
mov ecx, [eax+16]
test ecx, ecx
je @F
mov eax, ecx
jmp .l6
@@:
mov eax, [eax+20]
.l6:
 
; while (t != 0)
 
test eax, eax
jne .l4
.l5:
 
; if (v != 0)
 
test ebp, ebp
jz .done
.l7:
 
; r = chunk_plus_offset((mchunkptr)v, nb);
; unlink_large_chunk(v);
 
mov edx, ebp
lea esi, [ebx+ebp]
call unlink_large_chunk
 
; if (rsize < 16)
 
cmp edi, 16
jae .large
 
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
 
lea ecx, [edi+ebx]
 
; (v+rsize + nb)->head |= PINUSE_BIT;
 
add edi, ebp
lea eax, [edi+ebx+4]
or ecx, 3
mov [ebp+4], ecx
or dword [eax], 1
lea eax, [ebp+8]
add esp, 8
pop edi
pop ebp
ret
.large:
 
; v->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
 
mov edx, edi
or ebx, 3
mov [ebp+4], ebx
or edx, 1
mov [esi+4], edx
 
; (r+rsize)->prev_foot = rsize;
; insert_large_chunk((tchunkptr)r, rsize);
 
mov [esi+edi], edi
mov eax, edi
mov ecx, esi
call insert_chunk
 
lea eax, [ebp+8]
add esp, 8
pop edi
pop ebp
ret
.done:
add esp, 8
pop edi
pop ebp
xor eax, eax
ret
 
align 4
init_malloc:
 
stdcall kernel_alloc, 0x40000
 
mov [mst.top], eax
mov [mst.topsize], 128*1024
mov dword [eax+4], (128*1024) or 1
mov eax, mst.smallbins
@@:
mov [eax+8], eax
mov [eax+12], eax
add eax, 16
cmp eax, mst.smallbins+512
jb @B
 
ret
 
 
 
 
/kernel/branches/core/memory.inc
0,0 → 1,1323
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 983 $
 
 
align 4
proc alloc_page
 
pushfd
cli
push ebx
mov ebx, [page_start]
mov ecx, [page_end]
.l1:
bsf eax,[ebx];
jnz .found
add ebx,4
cmp ebx, ecx
jb .l1
pop ebx
popfd
xor eax,eax
ret
.found:
btr [ebx], eax
mov [page_start],ebx
sub ebx, sys_pgmap
lea eax, [eax+ebx*8]
shl eax, 12
dec [pg_data.pages_free]
pop ebx
popfd
ret
endp
 
align 4
proc alloc_pages stdcall, count:dword
pushfd
push ebx
push edi
cli
mov eax, [count]
add eax, 7
shr eax, 3
mov [count], eax
cmp eax, [pg_data.pages_free]
ja .fail
 
mov ecx, [page_start]
mov ebx, [page_end]
.find:
mov edx, [count]
mov edi, ecx
.match:
cmp byte [ecx], 0xFF
jne .next
dec edx
jz .ok
inc ecx
cmp ecx,ebx
jb .match
.fail:
xor eax, eax
pop edi
pop ebx
popfd
ret
.next:
inc ecx
cmp ecx, ebx
jb .find
pop edi
pop ebx
popfd
xor eax, eax
ret
.ok:
sub ecx, edi
inc ecx
push esi
mov esi, edi
xor eax, eax
rep stosb
sub esi, sys_pgmap
shl esi, 3+12
mov eax, esi
mov ebx, [count]
shl ebx, 3
sub [pg_data.pages_free], ebx
pop esi
pop edi
pop ebx
popfd
ret
endp
 
align 4
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
push ebx
mov eax, [phis_addr]
and eax, not 0xFFF
or eax, [flags]
mov ebx, [lin_addr]
shr ebx, 12
mov [page_tabs+ebx*4], eax
mov eax, [lin_addr]
invlpg [eax]
pop ebx
ret
endp
 
align 4
map_space: ;not implemented
 
 
ret
 
 
align 4
proc free_page
;arg: eax page address
pushfd
cli
shr eax, 12 ;page index
bts dword [sys_pgmap], eax ;that's all!
cmc
adc [pg_data.pages_free], 0
shr eax, 3
and eax, not 3 ;dword offset from page_map
add eax, sys_pgmap
cmp [page_start], eax
ja @f
popfd
ret
@@:
mov [page_start], eax
popfd
ret
endp
 
proc map_io_mem stdcall, base:dword, size:dword, flags:dword
 
push ebx
push edi
mov eax, [size]
add eax, 4095
and eax, -4096
mov [size], eax
stdcall alloc_kernel_space, eax
test eax, eax
jz .fail
push eax
 
mov edi, 0x1000
mov ebx, eax
mov ecx,[size]
mov edx, [base]
shr eax, 12
shr ecx, 12
and edx, -4096
or edx, [flags]
@@:
mov [page_tabs+eax*4], edx
; push eax
; invlpg [ebx]
; pop eax
inc eax
add ebx, edi
add edx, edi
loop @B
 
pop eax
mov edx, [base]
and edx, 4095
add eax, edx
.fail:
pop edi
pop ebx
ret
endp
 
; param
; eax= page base + page flags
; ebx= linear address
; ecx= count
 
align 4
commit_pages:
push edi
test ecx, ecx
jz .fail
 
mov edi, ebx
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
 
mov edx, 0x1000
mov ebx, edi
shr ebx, 12
@@:
mov [page_tabs+ebx*4], eax
; push eax
; invlpg [edi]
; pop eax
add edi, edx
add eax, edx
inc ebx
dec ecx
jnz @B
mov [pg_data.pg_mutex],ecx
.fail:
pop edi
ret
 
 
; param
; eax= base
; ecx= count
 
align 4
release_pages:
 
pushad
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
 
mov esi, eax
mov edi, eax
 
shr esi, 10
add esi, page_tabs
 
mov ebp, [pg_data.pages_free]
mov ebx, [page_start]
mov edx, sys_pgmap
@@:
xor eax, eax
xchg eax, [esi]
push eax
invlpg [edi]
pop eax
 
test eax, 1
jz .next
 
shr eax, 12
bts [edx], eax
cmc
adc ebp, 0
shr eax, 3
and eax, -4
add eax, edx
cmp eax, ebx
jae .next
 
mov ebx, eax
.next:
add edi, 0x1000
add esi, 4
dec ecx
jnz @B
mov [pg_data.pages_free], ebp
and [pg_data.pg_mutex],0
popad
ret
 
; param
; eax= base
; ecx= count
 
align 4
unmap_pages:
 
push edi
 
mov edi, eax
mov edx, eax
 
shr edi, 10
add edi, page_tabs
 
xor eax, eax
@@:
stosd
invlpg [edx]
add edx, 0x1000
loop @b
 
pop edi
ret
 
 
align 4
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
push ebx
mov ebx, [lin_addr]
shr ebx, 22
mov eax, [phis_addr]
and eax, not 0xFFF
or eax, PG_UW ;+PG_NOCACHE
mov dword [master_tab+ebx*4], eax
mov eax, [lin_addr]
shr eax, 10
add eax, page_tabs
invlpg [eax]
pop ebx
ret
endp
 
align 4
proc init_LFB
locals
pg_count dd ?
endl
 
cmp dword [LFBAddress], -1
jne @f
mov [BOOT_VAR+0x901c],byte 2
stdcall kernel_alloc, 0x280000
mov [LFBAddress], eax
ret
@@:
test [SCR_MODE],word 0100000000000000b
jnz @f
mov [BOOT_VAR+0x901c],byte 2
ret
@@:
call init_mtrr
 
mov edx, LFB_BASE
mov esi, [LFBAddress]
mov edi, 0x00800000
mov dword [exp_lfb+4], edx
 
shr edi, 12
mov [pg_count], edi
shr edi, 10
 
bt [cpu_caps], CAPS_PSE
jnc .map_page_tables
or esi, PG_LARGE+PG_UW
mov edx, sys_pgdir+(LFB_BASE shr 20)
@@:
mov [edx], esi
add edx, 4
add esi, 0x00400000
dec edi
jnz @B
 
bt [cpu_caps], CAPS_PGE
jnc @F
or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL
@@:
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
ret
 
.map_page_tables:
 
@@:
call alloc_page
stdcall map_page_table, edx, eax
add edx, 0x00400000
dec edi
jnz @B
 
mov eax, [LFBAddress]
mov edi, page_tabs + (LFB_BASE shr 10)
or eax, PG_UW
mov ecx, [pg_count]
cld
@@:
stosd
add eax, 0x1000
dec ecx
jnz @B
 
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
 
ret
endp
 
align 4
proc new_mem_resize stdcall, new_size:dword
 
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
 
mov edi, [new_size]
add edi,4095
and edi,not 4095
mov [new_size], edi
 
mov edx,[current_slot]
cmp [edx+APPDATA.heap_base],0
jne .exit
 
mov esi, [edx+APPDATA.mem_size]
add esi, 4095
and esi, not 4095
 
cmp edi, esi
jae .expand
 
shr edi, 12
shr esi, 12
@@:
mov eax, [app_page_tabs+edi*4]
test eax, 1
jz .next
mov dword [app_page_tabs+edi*4], 2
mov ebx, edi
shl ebx, 12
push eax
invlpg [ebx]
pop eax
call free_page
 
.next: add edi, 1
cmp edi, esi
jb @B
 
.update_size:
mov ebx, [new_size]
call update_mem_size
 
xor eax, eax
dec [pg_data.pg_mutex]
ret
.expand:
 
push esi
push edi
 
add edi, 0x3FFFFF
and edi, not(0x3FFFFF)
add esi, 0x3FFFFF
and esi, not(0x3FFFFF)
 
cmp esi, edi
jae .grow
 
xchg esi, edi
 
@@:
call alloc_page
test eax, eax
jz .exit
 
stdcall map_page_table, edi, eax
 
push edi
shr edi, 10
add edi, page_tabs
mov ecx, 1024
xor eax, eax
cld
rep stosd
pop edi
 
add edi, 0x00400000
cmp edi, esi
jb @B
.grow:
pop edi
pop esi
@@:
call alloc_page
test eax, eax
jz .exit
stdcall map_page,esi,eax,dword PG_UW
 
push edi
mov edi, esi
xor eax, eax
mov ecx, 1024
cld
rep stosd
pop edi
 
add esi, 0x1000
cmp esi, edi
jb @B
 
jmp .update_size
.exit:
xor eax, eax
inc eax
dec [pg_data.pg_mutex]
ret
endp
 
update_mem_size:
; in: edx = slot base
; ebx = new memory size
; destroys eax,ecx,edx
 
mov [APPDATA.mem_size+edx],ebx
;search threads and update
;application memory size infomation
mov ecx,[APPDATA.dir_table+edx]
mov eax,2
 
.search_threads:
;eax = current slot
;ebx = new memory size
;ecx = page directory
cmp eax,[TASK_COUNT]
jg .search_threads_end
mov edx,eax
shl edx,5
cmp word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty?
jz .search_threads_next
shl edx,3
cmp [SLOT_BASE+edx+APPDATA.dir_table],ecx ;if it is our thread?
jnz .search_threads_next
mov [SLOT_BASE+edx+APPDATA.mem_size],ebx ;update memory size
.search_threads_next:
inc eax
jmp .search_threads
.search_threads_end:
ret
 
; param
; eax= linear address
;
; retval
; eax= phisical page address
 
align 4
get_pg_addr:
shr eax, 12
mov eax, [page_tabs+eax*4]
and eax, 0xFFFFF000
ret
 
 
align 4
proc page_fault_handler
 
test byte [esp+12+2], 2
jnz v86_page_fault
 
.err_code equ ebp+32
.err_addr equ ebp-4
 
pushad
mov ebp, esp
mov eax, cr2
push eax
 
mov ax, app_data
mov ds, ax
mov es, ax
 
inc [pg_data.pages_faults]
 
; push eax
; push edx
; mov edx, 0x400 ;bochs
; mov al,0xff ;bochs
; out dx, al ;bochs
; pop edx
; pop eax
 
mov ebx, [.err_addr]
mov eax, [.err_code]
 
cmp ebx, OS_BASE
jb .user_space ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ;
 
cmp ebx, page_tabs
jb .kernel_space ;ñòðàíèöà â ïàìÿòè ÿäðà
 
cmp ebx, kernel_tabs
jb .alloc;.app_tabs ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ;
;ïðîñòî ñîçäàäèì îäíó
 
cmp ebx, LFB_BASE
jb .core_tabs ;òàáëèöû ñòðàíèö ÿäðà
;Îøèáêà
.lfb:
;îáëàñòü LFB
;Îøèáêà
jmp .fail
 
align 4
.user_space:
test eax, PG_MAP
jnz .err_access ;Ñòðàíèöà ïðèñóòñòâóåò
;Îøèáêà äîñòóïà ?
 
shr ebx, 12
mov ecx, ebx
shr ecx, 10
mov edx, [master_tab+ecx*4]
test edx, PG_MAP
jz .fail ;òàáëèöà ñòðàíèö íå ñîçäàíà
;íåâåðíûé àäðåñ â ïðîãðàììå
 
mov eax, [page_tabs+ebx*4]
test eax, 2
jz .fail ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ;
;èñïîëüçîâàíèÿ. Îøèáêà
.alloc:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page,[ebp-4],eax,dword PG_UW
 
mov edi, [ebp-4]
and edi, 0xFFFFF000
mov ecx, 1024
xor eax, eax
cld
rep stosd
.exit:
mov esp, ebp
popad
add esp, 4
iretd
 
.err_access:
;íèêîãäà íå ïðîèñõîäèò
jmp .fail
 
.kernel_space:
test eax, PG_MAP
jz .fail ;ñòðàíèöà íå ïðèñóòñòâóåò
 
test eax, 4 ;U/S
jnz .fail ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè
;ÿäðà
test eax, 8
jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò
;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon
 
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà
 
cmp ebx, tss._io_map_0
jb .fail
 
cmp ebx, tss._io_map_0+8192
jae .fail
 
; io permission map
; copy-on-write protection
 
call alloc_page
test eax, eax
jz .fail
 
push eax
stdcall map_page,[ebp-4],eax,dword PG_SW
pop eax
mov edi, [.err_addr]
and edi, -4096
lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
 
mov ebx, esi
shr ebx, 12
mov edx, [current_slot]
or eax, PG_SW
mov [edx+APPDATA.io_map+ebx*4], eax
 
add esi, [default_io_map]
mov ecx, 4096/4
cld
rep movsd
jmp .exit
 
 
;íå îáðàáàòûâàåì. Îøèáêà
 
.core_tabs:
.fail:
mov esp, ebp
popad
add esp, 4
 
; iretd
 
save_ring3_context ;debugger support
 
mov bl, 14
jmp exc_c
iretd
endp
 
align 4
proc map_mem stdcall, lin_addr:dword,pdir:dword,\
ofs:dword,buf_size:dword
mov eax, [buf_size]
test eax, eax
jz .exit
 
mov eax, [pdir]
and eax, 0xFFFFF000
 
stdcall map_page,[ipc_pdir],eax,PG_UW
mov ebx, [ofs]
shr ebx, 22
mov esi, [ipc_pdir]
mov edi, [ipc_ptab]
mov eax, [esi+ebx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page,edi,eax,PG_UW
; inc ebx
; add edi, 0x1000
; mov eax, [esi+ebx*4]
; test eax, eax
; jz @f
; and eax, 0xFFFFF000
; stdcall map_page, edi, eax
 
@@: mov edi, [lin_addr]
and edi, 0xFFFFF000
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [ipc_ptab]
 
.map: mov eax, [esi+edx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page,edi,eax,PG_UW
dec ecx
jz .exit
add edi, 0x1000
inc edx
cmp edx, 0x400
jnz .map
inc ebx
mov eax, [ipc_pdir]
mov eax, [eax+ebx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page,esi,eax,PG_UW
xor edx, edx
jmp .map
 
.exit:
ret
endp
 
align 4
proc map_memEx stdcall, lin_addr:dword,pdir:dword,\
ofs:dword,buf_size:dword
mov eax, [buf_size]
test eax, eax
jz .exit
 
mov eax, [pdir]
and eax, 0xFFFFF000
 
stdcall map_page,[proc_mem_pdir],eax,dword PG_UW
mov ebx, [ofs]
shr ebx, 22
mov esi, [proc_mem_pdir]
mov edi, [proc_mem_tab]
mov eax, [esi+ebx*4]
and eax, 0xFFFFF000
test eax, eax
jz .exit
stdcall map_page,edi,eax,dword PG_UW
 
@@: mov edi, [lin_addr]
and edi, 0xFFFFF000
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [proc_mem_tab]
 
.map: mov eax, [esi+edx*4]
; and eax, 0xFFFFF000
; test eax, eax
; jz .exit
stdcall map_page,edi,eax,dword PG_UW
add edi, 0x1000
inc edx
dec ecx
jnz .map
.exit:
ret
endp
 
 
 
 
sys_IPC:
;input:
; eax=1 - set ipc buffer area
; ebx=address of buffer
; ecx=size of buffer
; eax=2 - send message
; ebx=PID
; ecx=address of message
; edx=size of message
 
cmp eax,1
jne @f
call set_ipc_buff
mov [esp+36], eax
ret
@@:
cmp eax, 2
jne @f
stdcall sys_ipc_send, ebx, ecx, edx
mov [esp+36], eax
ret
@@:
xor eax, eax
not eax
mov [esp+36], eax
ret
 
align 4
proc set_ipc_buff
 
mov eax,[current_slot]
pushf
cli
mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area
mov [eax+APPDATA.ipc_size],ecx
 
add ecx, ebx
add ecx, 4095
and ecx, not 4095
 
.touch: mov eax, [ebx]
add ebx, 0x1000
cmp ebx, ecx
jb .touch
 
popf
xor eax, eax
ret
endp
 
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
locals
dst_slot dd ?
dst_offset dd ?
buf_size dd ?
used_buf dd ?
endl
 
pushf
cli
 
mov eax, [PID]
call pid_to_slot
test eax,eax
jz .no_pid
 
mov [dst_slot], eax
shl eax,8
mov edi,[eax+SLOT_BASE+0xa0] ;is ipc area defined?
test edi,edi
jz .no_ipc_area
 
mov ebx, edi
and ebx, 0xFFF
mov [dst_offset], ebx
 
mov esi, [eax+SLOT_BASE+0xa4]
mov [buf_size], esi
 
mov ecx, [ipc_tmp]
cmp esi, 0x40000-0x1000 ; size of [ipc_tmp] minus one page
jbe @f
push eax esi edi
add esi,0x1000
stdcall alloc_kernel_space,esi
mov ecx, eax
pop edi esi eax
@@:
mov [used_buf], ecx
stdcall map_mem, ecx, [SLOT_BASE+eax+0xB8],\
edi, esi
 
mov edi, [dst_offset]
add edi, [used_buf]
cmp dword [edi], 0
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now
 
mov edx, dword [edi+4]
lea ebx, [edx+8]
add ebx, [msg_size]
cmp ebx, [buf_size]
ja .buffer_overflow ;esi<0 - not enough memory in buffer
 
mov dword [edi+4], ebx
mov eax,[TASK_BASE]
mov eax, [eax+0x04] ;eax - our PID
add edi, edx
mov [edi], eax
mov ecx, [msg_size]
 
mov [edi+4], ecx
add edi, 8
mov esi, [msg_addr]
; add esi, new_app_base
cld
rep movsb
 
mov ebx, [ipc_tmp]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov ebx, [ipc_pdir]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov ebx, [ipc_ptab]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov eax, [dst_slot]
shl eax, 8
or [eax+SLOT_BASE+0xA8],dword 0x40
cmp dword [check_idle_semaphore],20
jge .ipc_no_cis
 
mov dword [check_idle_semaphore],5
.ipc_no_cis:
push 0
jmp .ret
.no_pid:
popf
mov eax, 4
ret
.no_ipc_area:
popf
xor eax, eax
inc eax
ret
.ipc_blocked:
push 2
jmp .ret
.buffer_overflow:
push 3
.ret:
mov eax, [used_buf]
cmp eax, [ipc_tmp]
jz @f
stdcall free_kernel_space,eax
@@:
pop eax
popf
ret
endp
 
align 4
sysfn_meminfo:
 
; add ebx, new_app_base
cmp ebx, OS_BASE
jae .fail
 
mov eax, [pg_data.pages_count]
mov [ebx], eax
shl eax, 12
mov [esp+36], eax
mov ecx, [pg_data.pages_free]
mov [ebx+4], ecx
mov edx, [pg_data.pages_faults]
mov [ebx+8], edx
mov esi, [heap_size]
mov [ebx+12], esi
mov edi, [heap_free]
mov [ebx+16], edi
mov eax, [heap_blocks]
mov [ebx+20], eax
mov ecx, [free_blocks]
mov [ebx+24], ecx
ret
.fail:
mov dword [esp+36], -1
ret
 
align 4
f68call:
dd f68.11
dd f68.12
dd f68.13
dd f68.14
dd f68.15
dd f68.16
dd f68.17
dd f68.18
dd f68.19
dd f68.20
dd f68.21
dd f68.22
dd f68.23
 
align 4
f68:
cmp eax,4
jle sys_sheduler
 
cmp eax, 11
jb .fail
 
cmp eax, 23
ja .fail
 
jmp dword [f68call+eax*4-11*4]
.11:
call init_heap
mov [esp+36], eax
ret
.12:
stdcall user_alloc, ebx
mov [esp+36], eax
ret
.13:
stdcall user_free, ebx
mov [esp+36], eax
ret
.14:
cmp ebx, OS_BASE
jae .fail
stdcall get_event_ex, ebx, ecx
mov [esp+36], eax
ret
.15:
mov ecx, [current_slot]
mov eax, [ecx+APPDATA.fpu_handler]
mov [ecx+APPDATA.fpu_handler], ebx
mov [esp+36], eax
ret
.16:
test ebx, ebx
jz .fail
cmp ebx, OS_BASE
jae .fail
stdcall get_service, ebx
mov [esp+36], eax
ret
.17:
call srv_handlerEx ;ebx
mov [esp+36], eax
ret
.18:
mov ecx, [current_slot]
mov eax, [ecx+APPDATA.sse_handler]
mov [ecx+APPDATA.sse_handler], ebx
mov [esp+36], eax
ret
.19:
cmp ebx, OS_BASE
jae .fail
stdcall load_library, ebx
mov [esp+36], eax
ret
.20:
mov eax, ecx
call user_realloc
mov [esp+36], eax
ret
.21:
cmp ebx, OS_BASE
jae .fail
 
stdcall load_PE, ebx
 
test eax, eax
jz @F
 
mov esi, eax
stdcall eax, DRV_ENTRY
 
test eax, eax
jz @F
 
mov [eax+SRV.entry], esi
 
@@:
mov [esp+36], eax
ret
.22:
cmp ebx, OS_BASE
jae .fail
 
stdcall shmem_open, ebx, ecx, edx
mov [esp+28], edx
mov [esp+36], eax
ret
 
.23:
cmp ebx, OS_BASE
jae .fail
 
stdcall shmem_close, ebx
mov [esp+36], eax
ret
 
.fail:
xor eax, eax
mov [esp+36], eax
ret
 
align 4
proc load_pe_driver stdcall, file:dword
 
stdcall load_PE, [file]
test eax, eax
jz .fail
 
mov esi, eax
stdcall eax, DRV_ENTRY
test eax, eax
jz .fail
 
mov [eax+SRV.entry], esi
ret
 
.fail:
xor eax, eax
ret
endp
 
 
align 4
proc init_mtrr
 
cmp [BOOT_VAR+0x901c],byte 2
je .exit
 
bt [cpu_caps], CAPS_MTRR
jnc .exit
 
mov eax, cr0
or eax, 0x60000000 ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
 
mov ecx, 0x2FF
rdmsr ;
push eax
 
xor edx, edx
xor eax, eax
mov ecx, 0x2FF
wrmsr ;disable all MTRR
 
mov eax, [MEM_AMOUNT]
; round eax up to next power of 2
dec eax
bsr ecx, eax
mov eax, 2
shl eax, cl
stdcall set_mtrr, edx,edx,eax,MEM_WB
stdcall set_mtrr, 1,[LFBAddress],[LFBSize],MEM_WC
xor edx, edx
xor eax, eax
mov ecx, 0x204
mov ebx, 6
@@:
wrmsr ;disable unused MTRR
inc ecx
wrmsr
inc ecx
dec ebx
jnz @b
 
wbinvd ;again invalidate
 
pop eax
or eax, 0x800 ;set default memtype to UC
and al, 0xF0
mov ecx, 0x2FF
wrmsr ;and enable MTRR
 
mov eax, cr0
and eax, not 0x60000000
mov cr0, eax ; enable caching
.exit:
ret
endp
 
align 4
proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword
 
xor edx, edx
mov eax, [base]
or eax, [mem_type]
mov ecx, [reg]
lea ecx, [0x200+ecx*2]
wrmsr
 
mov ebx, [size]
dec ebx
mov eax, 0xFFFFFFFF
mov edx, 0x0000000F
sub eax, ebx
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
ret
endp
 
align 4
proc stall stdcall, delay:dword
push ecx
push edx
push ebx
push eax
 
mov eax, [delay]
mul [stall_mcs]
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx,edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
jb @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
align 4
proc create_ring_buffer stdcall, size:dword, flags:dword
locals
buf_ptr dd ?
endl
 
mov eax, [size]
test eax, eax
jz .fail
 
add eax, eax
stdcall alloc_kernel_space, eax
test eax, eax
jz .fail
 
push ebx
 
mov [buf_ptr], eax
 
mov ebx, [size]
shr ebx, 12
push ebx
 
stdcall alloc_pages, ebx
pop ecx
 
test eax, eax
jz .mm_fail
 
push edi
 
or eax, [flags]
mov edi, [buf_ptr]
mov ebx, [buf_ptr]
mov edx, ecx
shl edx, 2
shr edi, 10
@@:
mov [page_tabs+edi], eax
mov [page_tabs+edi+edx], eax
invlpg [ebx]
invlpg [ebx+0x10000]
add eax, 0x1000
add ebx, 0x1000
add edi, 4
dec ecx
jnz @B
 
mov eax, [buf_ptr]
pop edi
pop ebx
ret
.mm_fail:
stdcall free_kernel_space, [buf_ptr]
xor eax, eax
pop ebx
.fail:
ret
endp
 
 
 
/kernel/branches/core/peload.inc
0,0 → 1,320
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 978 $
 
include 'export.inc'
 
align 4
 
proc load_PE stdcall, file_name:dword
locals
image dd ?
entry dd ?
base dd ?
endl
 
stdcall load_file, [file_name]
test eax, eax
jz .fail
 
mov [image], eax
 
mov edx, [eax+60]
 
stdcall kernel_alloc, [eax+80+edx]
test eax, eax
jz .cleanup
 
mov [base], eax
 
stdcall map_PE, eax, [image]
 
mov [entry], eax
test eax, eax
jnz .cleanup
 
stdcall kernel_free, [base]
.cleanup:
stdcall kernel_free, [image]
mov eax, [entry]
ret
.fail:
xor eax, eax
ret
endp
 
DWORD equ dword
PTR equ
 
align 4
map_PE: ;stdcall base:dword, image:dword
cld
push ebp
push edi
push esi
push ebx
sub esp, 60
mov ebx, DWORD PTR [esp+84]
mov ebp, DWORD PTR [esp+80]
mov edx, ebx
mov esi, ebx
add edx, DWORD PTR [ebx+60]
mov edi, ebp
mov DWORD PTR [esp+32], edx
mov ecx, DWORD PTR [edx+84]
 
shr ecx, 2
rep movsd
 
movzx eax, WORD PTR [edx+6]
mov DWORD PTR [esp+36], 0
mov DWORD PTR [esp+16], eax
jmp L2
L3:
mov eax, DWORD PTR [edx+264]
test eax, eax
je L4
mov esi, ebx
mov edi, ebp
add esi, DWORD PTR [edx+268]
mov ecx, eax
add edi, DWORD PTR [edx+260]
 
shr ecx, 2
rep movsd
 
L4:
mov ecx, DWORD PTR [edx+256]
add ecx, 4095
and ecx, -4096
cmp ecx, eax
jbe L6
sub ecx, eax
add eax, DWORD PTR [edx+260]
lea edi, [eax+ebp]
 
xor eax, eax
rep stosb
 
L6:
inc DWORD PTR [esp+36]
add edx, 40
L2:
mov esi, DWORD PTR [esp+16]
cmp DWORD PTR [esp+36], esi
jne L3
mov edi, DWORD PTR [esp+32]
cmp DWORD PTR [edi+164], 0
je L9
mov esi, ebp
mov ecx, ebp
sub esi, DWORD PTR [edi+52]
add ecx, DWORD PTR [edi+160]
mov eax, esi
shr eax, 16
mov DWORD PTR [esp+12], eax
jmp L11
L12:
lea ebx, [eax-8]
xor edi, edi
shr ebx,1
jmp L13
L14:
movzx eax, WORD PTR [ecx+8+edi*2]
mov edx, eax
shr eax, 12
and edx, 4095
add edx, DWORD PTR [ecx]
cmp ax, 2
je L17
cmp ax, 3
je L18
dec ax
jne L15
mov eax, DWORD PTR [esp+12]
add WORD PTR [edx+ebp], ax
L17:
add WORD PTR [edx+ebp], si
L18:
add DWORD PTR [edx+ebp], esi
L15:
inc edi
L13:
cmp edi, ebx
jne L14
add ecx, DWORD PTR [ecx+4]
L11:
mov eax, DWORD PTR [ecx+4]
test eax, eax
jne L12
L9:
mov edx, DWORD PTR [esp+32]
cmp DWORD PTR [edx+132], 0
je L20
mov eax, ebp
add eax, DWORD PTR [edx+128]
mov DWORD PTR [esp+40], 0
add eax, 20
mov DWORD PTR [esp+56], eax
L22:
mov ecx, DWORD PTR [esp+56]
cmp DWORD PTR [ecx-16], 0
jne L23
cmp DWORD PTR [ecx-8], 0
je L25
L23:
mov edi, DWORD PTR [__exports+32]
mov esi, DWORD PTR [__exports+28]
mov eax, DWORD PTR [esp+56]
mov DWORD PTR [esp+20], edi
add edi, OS_BASE
add esi, OS_BASE
mov DWORD PTR [esp+44], esi
mov ecx, DWORD PTR [eax-4]
mov DWORD PTR [esp+48], edi
mov edx, DWORD PTR [eax-20]
mov DWORD PTR [esp+52], 0
add ecx, ebp
add edx, ebp
mov DWORD PTR [esp+24], edx
mov DWORD PTR [esp+28], ecx
L26:
mov esi, DWORD PTR [esp+52]
mov edi, DWORD PTR [esp+24]
mov eax, DWORD PTR [edi+esi*4]
test eax, eax
je L27
test eax, eax
js L27
lea edi, [ebp+eax]
mov eax, DWORD PTR [esp+28]
mov DWORD PTR [eax+esi*4], 0
lea esi, [edi+2]
push eax
push 32
movzx eax, WORD PTR [edi]
mov edx, DWORD PTR [esp+56]
mov eax, DWORD PTR [edx+eax*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop ebx
xor ebx, ebx
test eax, eax
jne L32
jmp L30
L33:
push ecx
push 32
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [ecx+OS_BASE+ebx*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop edx
test eax, eax
jne L34
mov esi, DWORD PTR [esp+44]
mov edx, DWORD PTR [esp+52]
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+ebx*4]
add eax, OS_BASE
mov DWORD PTR [ecx+edx*4], eax
jmp L36
L34:
inc ebx
L32:
cmp ebx, DWORD PTR [__exports+24]
jb L33
L36:
cmp ebx, DWORD PTR [__exports+24]
jne L37
 
mov esi, msg_unresolved
call sys_msg_board_str
lea esi, [edi+2]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
 
mov DWORD PTR [esp+40], 1
jmp L37
L30:
movzx eax, WORD PTR [edi]
mov esi, DWORD PTR [esp+44]
mov edi, DWORD PTR [esp+52]
mov edx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+eax*4]
add eax, OS_BASE
mov DWORD PTR [edx+edi*4], eax
L37:
inc DWORD PTR [esp+52]
jmp L26
L27:
add DWORD PTR [esp+56], 20
jmp L22
L25:
xor eax, eax
cmp DWORD PTR [esp+40], 0
jne L40
L20:
mov ecx, DWORD PTR [esp+32]
mov eax, ebp
add eax, DWORD PTR [ecx+40]
L40:
add esp, 60
pop ebx
pop esi
pop edi
pop ebp
ret 8
 
align 16
__exports:
export 'KERNEL', \
alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall
commit_pages, 'CommitPages', \ ; eax, ebx, ecx
create_kernel_object, 'CreateObject', \
create_ring_buffer, 'CreateRingBuffer', \ ; stdcall
destroy_kernel_object, 'DestroyObject', \
free_kernel_space, 'FreeKernelSpace', \ ; stdcall
kernel_alloc, 'KernelAlloc', \ ; stdcall
kernel_free, 'KernelFree', \ ; stdcall
alloc_pages, 'AllocPages', \ ; stdcall
malloc, 'Kmalloc', \
free, 'Kfree', \
map_io_mem, 'MapIoMem', \ ; stdcall
get_pg_addr, 'GetPgAddr', \ ; eax
\
select_hw_cursor, 'SelectHwCursor', \ ; stdcall
set_hw_cursor, 'SetHwCursor', \ ; stdcall
hw_restore, 'HwCursorRestore', \ ;
create_cursor, 'HwCursorCreate', \ ;
\
set_screen, 'SetScreen', \
pci_api, 'PciApi', \
pci_read8, 'PciRead8', \ ; stdcall
pci_read16, 'PciRead16', \ ; stdcall
pci_read32, 'PciRead32', \ ; stdcall
pci_write8, 'PciWrite8', \ ; stdcall
pci_write16, 'PciWrite16', \ ; stdcall
pci_write32, 'PciWrite32', \ ; stdcall
\
reg_service, 'RegService', \ ; stdcall
attach_int_handler, 'AttachIntHandler', \ ; stdcall
user_alloc, 'UserAlloc', \ ; stdcall
user_free, 'UserFree', \ ; stdcall
unmap_pages, 'UnmapPages', \ ; eax, ecx
sys_msg_board_str, 'SysMsgBoardStr', \
delay_hs, 'Delay', \ ; ebx
set_mouse_data, 'SetMouseData'
 
 
 
/kernel/branches/core/sched.inc
0,0 → 1,388
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 907 $
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IRQ0 HANDLER (TIMER INTERRUPT) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
align 32
irq0:
pushad
mov ax, app_data ;
mov ds, ax
mov es, ax
 
; cmp dword[CURRENT_TASK], 1
; jnz @f
; mov eax, [esp + 32]
; cmp eax, idle_loop + 1
; jz @f
; DEBUGF 1, "K : OOOPS! EAX = 0x%x\n", eax
; @@:
 
inc dword [timer_ticks]
 
mov eax, [timer_ticks]
call playNote ; <<<--- Speaker driver
 
cmp eax,[next_usage_update]
jb .nocounter
add eax,100
mov [next_usage_update],eax
call updatecputimes
.nocounter:
cmp [DONT_SWITCH], byte 1
jne .change_task
 
mov al,0x20 ; send End Of Interrupt signal
mov dx,0x20
out dx,al
 
mov [DONT_SWITCH], byte 0
 
popad
iretd
 
.change_task:
call update_counters
 
call find_next_task
mov ecx, eax
 
mov al,0x20 ; send End Of Interrupt signal
mov dx,0x20
out dx,al
 
test ecx, ecx ; if there is only one running process
jnz .return
 
call do_change_task
 
.return:
popad
; popfd
iretd
 
 
align 4
change_task:
 
pushfd
cli
pushad
 
call update_counters
 
if 0
 
; \begin{Mario79}
cmp [dma_task_switched], 1
jne .find_next_task
mov [dma_task_switched], 0
mov ebx, [dma_process]
cmp [CURRENT_TASK], ebx
je .return
mov edi, [dma_slot_ptr]
mov [CURRENT_TASK], ebx
mov [TASK_BASE], edi
jmp @f
.find_next_task:
; \end{Mario79}
 
end if
 
call find_next_task
test eax, eax ; the same task -> skip switch
jnz .return
@@:
mov [DONT_SWITCH],byte 1
call do_change_task
 
.return:
popad
popfd
ret
 
 
uglobal
align 4
far_jump:
.offs dd ?
.sel dw ?
context_counter dd ? ;noname & halyavin
next_usage_update dd ?
timer_ticks dd ?
prev_slot dd ?
event_sched dd ?
endg
 
 
update_counters:
mov edi, [TASK_BASE]
mov ebx, [edi+TASKDATA.counter_add] ; time stamp counter add
rdtsc
sub eax, ebx
add eax, [edi+TASKDATA.counter_sum] ; counter sum
mov [edi+TASKDATA.counter_sum], eax
ret
 
 
; Find next task to execute
; result: ebx = number of the selected task
; eax = 1 if the task is the same
; edi = address of the data for the task in ebx
; [0x3000] = ebx and [0x3010] = edi
; corrupts other regs
find_next_task:
mov ebx, [CURRENT_TASK]
mov edi, [TASK_BASE]
mov [prev_slot], ebx
 
.waiting_for_termination:
.waiting_for_reuse:
.waiting_for_event:
.suspended:
cmp ebx, [TASK_COUNT]
jb @f
mov edi, CURRENT_TASK
xor ebx, ebx
@@:
 
add edi,0x20
inc ebx
 
mov al, byte [edi+TASKDATA.state]
test al, al
jz .found
cmp al, 1
jz .suspended
cmp al, 2
jz .suspended
cmp al, 3
je .waiting_for_termination
cmp al, 4
je .waiting_for_termination
cmp al, 9
je .waiting_for_reuse
 
mov [CURRENT_TASK],ebx
mov [TASK_BASE],edi
 
cmp al, 5
jne .noevents
call get_event_for_app
test eax, eax
jnz @f
mov eax, ebx
shl eax, 8
mov eax, [SLOT_BASE + APPDATA.wait_timeout + eax]
cmp eax, [timer_ticks]
jae .waiting_for_event
xor eax, eax
@@:
mov [event_sched], eax
mov [edi+TASKDATA.state], byte 0
.noevents:
.found:
mov [CURRENT_TASK],ebx
mov [TASK_BASE],edi
rdtsc ;call _rdtsc
mov [edi+TASKDATA.counter_add],eax
 
mov esi, [prev_slot]
xor eax, eax
cmp ebx, esi
sete al
ret
 
; param
; ebx = incoming task
; esi = outcomig task
 
do_change_task:
 
shl ebx, 8
add ebx, SLOT_BASE
mov [current_slot], ebx
 
shl esi, 8
add esi, SLOT_BASE
 
mov [esi+APPDATA.saved_esp], esp
mov esp, [ebx+APPDATA.saved_esp]
 
; set thread io map
 
mov ecx, [ebx+APPDATA.io_map]
mov edx, [ebx+APPDATA.io_map+4]
mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)], ecx
mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)], edx
 
mov eax, [ebx+APPDATA.dir_table]
cmp eax, [esi+APPDATA.dir_table]
je @F
mov cr3, eax
@@:
mov eax, [ebx+APPDATA.saved_esp0]
mov [tss._esp0], eax
mov ax, graph_data
mov gs, ax
 
mov eax, [CURRENT_TASK]
cmp eax, [fpu_owner]
clts ;clear a task switch flag
je @F
;and set it again if the owner
mov ecx, cr0 ;of a fpu has changed
or ecx, CR0_TS
mov cr0, ecx
@@:
inc [context_counter] ;noname & halyavin
test [ebx+APPDATA.dbg_state], 1
jnz @F
ret
@@:
mov eax, [ebx+APPDATA.dbg_regs.dr0]
mov dr0, eax
mov eax, [ebx+APPDATA.dbg_regs.dr1]
mov dr1, eax
mov eax, [ebx+APPDATA.dbg_regs.dr2]
mov dr2, eax
mov eax, [ebx+APPDATA.dbg_regs.dr3]
mov dr3, eax
xor eax, eax
mov dr6, eax
mov eax, [ebx+APPDATA.dbg_regs.dr7]
mov dr7, eax
ret
 
align 4
updatecputimes:
 
mov eax,[idleuse]
mov [idleusesec],eax
mov [idleuse],dword 0
mov ecx, [TASK_COUNT]
mov edi, TASK_DATA
.newupdate:
mov ebx,[edi+TASKDATA.counter_sum]
mov [edi+TASKDATA.cpu_usage],ebx
mov [edi+TASKDATA.counter_sum],dword 0
add edi,0x20
dec ecx
jnz .newupdate
 
ret
 
if 0
 
 
struc TIMER
{
.next dd ?
.exp_time dd ?
.func dd ?
.arg dd ?
}
 
 
 
 
 
 
 
 
 
MAX_PROIRITY 0 ; highest, used for kernel tasks
MAX_USER_PRIORITY 0 ; highest priority for user processes
USER_PRIORITY 7 ; default (should correspond to nice 0)
MIN_USER_PRIORITY 14 ; minimum priority for user processes
IDLE_PRIORITY 15 ; lowest, only IDLE process goes here
NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1
 
rdy_head rd 16
 
 
align 4
pick_task:
 
xor eax, eax
.pick:
mov ebx, [rdy_head+eax*4]
test ebx, ebx
jz .next
 
mov [next_task], ebx
test [ebx+flags.billable]
jz @F
mov [bill_task], ebx
@@:
ret
.next:
inc eax
jmp .pick
 
 
; param
; eax= task
;
; retval
; eax= task
; ebx= queue
; ecx= front if 1 or back if 0
 
align 4
shed:
cmp [eax+.tics_left], 0 ;signed compare
mov ebx, [eax+.priority]
setg ecx
jg @F
 
mov edx, [eax+.tics_quantum]
mov [eax+.ticks_left], edx
cmp ebx, (IDLE_PRIORITY-1)
je @F
inc ebx
@@:
ret
 
; param
; eax= task
 
align 4
enqueue:
call shed ;eax
cmp [rdy_head+ebx*4],0
jnz @F
 
mov [rdy_head+ebx*4], eax
mov [rdy_tail+ebx*4], eax
mov [eax+.next_ready], 0
jmp .pick
@@:
test ecx, ecx
jz .back
 
mov ecx, [rdy_head+ebx*4]
mov [eax+.next_ready], ecx
mov [rdy_head+ebx*4], eax
jmp .pick
.back:
mov ecx, [rdy_tail+ebx*4]
mov [ecx+.next_ready], eax
mov [rdy_tail+ebx*4], eax
mov [eax+.next_ready], 0
.pick:
call pick_proc ;select next task
ret
 
end if
 
/kernel/branches/core/string.inc
0,0 → 1,188
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Author: Kees J. Bot 1 Jan 1994 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 750 $
 
 
; size_t strncat(char *s1, const char *s2, size_t n)
; Append string s2 to s1.
 
; char *strchr(const char *s, int c)
 
 
; int strncmp(const char *s1, const char *s2, size_t n)
; Compare two strings.
 
; char *strncpy(char *s1, const char *s2, size_t n)
; Copy string s2 to s1.
 
; size_t strnlen(const char *s, size_t n)
; Return the length of a string.
 
; proc strrchr stdcall, s:dword, c:dword
; Look for the last occurrence a character in a string.
 
proc strncat stdcall, s1:dword, s2:dword, n:dword
push esi
push edi
mov edi, [s1] ; String s1
mov edx, [n] ; Maximum length
 
mov ecx, -1
xor al, al ; Null byte
cld
repne scasb ; Look for the zero byte in s1
dec edi ; Back one up (and clear 'Z' flag)
push edi ; Save end of s1
mov edi, [s2] ; edi = string s2
mov ecx, edx ; Maximum count
repne scasb ; Look for the end of s2
jne @F
inc ecx ; Exclude null byte
@@:
sub edx, ecx ; Number of bytes in s2
mov ecx, edx
mov esi, [s2] ; esi = string s2
pop edi ; edi = end of string s1
rep movsb ; Copy bytes
stosb ; Add a terminating null
mov eax, [s1] ; Return s1
pop edi
pop esi
ret
endp
 
align 4
proc strncmp stdcall, s1:dword, s2:dword, n:dword
 
push esi
push edi
mov ecx, [n]
test ecx, ecx ; Max length is zero?
je .done
 
mov esi, [s1] ; esi = string s1
mov edi, [s2] ; edi = string s2
cld
.compare:
cmpsb ; Compare two bytes
jne .done
cmp byte [esi-1], 0 ; End of string?
je .done
dec ecx ; Length limit reached?
jne .compare
.done:
seta al ; al = (s1 > s2)
setb ah ; ah = (s1 < s2)
sub al, ah
movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
pop edi
pop esi
ret
endp
 
align 4
proc strncpy stdcall, s1:dword, s2:dword, n:dword
 
push esi
push edi
 
mov ecx, [n] ; Maximum length
mov edi, [s2] ; edi = string s2
xor al, al ; Look for a zero byte
mov edx, ecx ; Save maximum count
cld
repne scasb ; Look for end of s2
sub edx, ecx ; Number of bytes in s2 including null
xchg ecx, edx
mov esi, [s2] ; esi = string s2
mov edi, [s1] ; edi = string s1
rep movsb ; Copy bytes
 
mov ecx, edx ; Number of bytes not copied
rep stosb ; strncpy always copies n bytes by null padding
mov eax, [s1] ; Return s1
pop edi
pop esi
ret
endp
 
align 4
proc strnlen stdcall, s:dword, n:dword
 
push edi
mov edi, [s] ; edi = string
xor al, al ; Look for a zero byte
mov edx, ecx ; Save maximum count
cmp cl, 1 ; 'Z' bit must be clear if ecx = 0
cld
repne scasb ; Look for zero
jne @F
inc ecx ; Don't count zero byte
@@:
mov eax, edx
sub eax, ecx ; Compute bytes scanned
pop edi
ret
endp
 
align 4
proc strchr stdcall, s:dword, c:dword
push edi
cld
mov edi, [s] ; edi = string
mov edx, 16 ; Look at small chunks of the string
.next:
shl edx, 1 ; Chunks become bigger each time
mov ecx, edx
xor al, al ; Look for the zero at the end
repne scasb
pushf ; Remember the flags
sub ecx, edx
neg ecx ; Some or all of the chunk
sub edi, ecx ; Step back
mov eax, [c] ; The character to look for
repne scasb
je .found
popf ; Did we find the end of string earlier?
jne .next ; No, try again
xor eax, eax ; Return NULL
pop edi
ret
.found:
pop eax ; Get rid of those flags
lea eax, [edi-1] ; Address of byte found
pop edi
ret
 
endp
 
 
proc strrchr stdcall, s:dword, c:dword
push edi
mov edi, [s] ; edi = string
mov ecx, -1
xor al, al
cld
repne scasb ; Look for the end of the string
not ecx ; -1 - ecx = Length of the string + null
dec edi ; Put edi back on the zero byte
mov eax, [c] ; The character to look for
std ; Downwards search
repne scasb
cld ; Direction bit back to default
jne .fail
lea eax, [edi+1] ; Found it
pop edi
ret
.fail:
xor eax, eax ; Not there
pop edi
ret
endp
 
 
/kernel/branches/core/sync.inc
0,0 → 1,119
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Synhronization for MenuetOS. ;;
;; Author: Halyavin Andrey, halyavin@land.ru ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 750 $
 
 
if ~defined sync_inc
sync_inc_fix:
sync_inc fix sync_inc_fix
 
;simplest mutex.
macro SimpleMutex name
{
; iglobal
name dd 0
name#.type = 1
; endg
}
macro WaitSimpleMutex name
{
local start_wait,ok
start_wait=$
cli
cmp [name],dword 0
jz ok
sti
call change_task
jmp start_wait
ok=$
push eax
mov eax,dword [TASK_BASE+second_base_address]
mov eax,[eax+TASKDATA.pid]
mov [name],eax
pop eax
sti
}
macro ReleaseSimpleMutex name
{
mov [name],dword 0
}
macro TryWaitSimpleMutex name ;result in eax and in flags
{
local ok,try_end
cmp [name],dword 0
jz ok
xor eax,eax
jmp try_end
ok=$
xor eax,eax
inc eax
try_end=$
}
macro SimpleCriticalSection name
{
; iglobal
name dd 0
dd 0
name#.type=2
; endg
}
macro WaitSimpleCriticalSection name
{
local start_wait,first_wait,inc_counter,end_wait
push eax
mov eax,[TASK_BASE+second_base_address]
mov eax,[eax+TASKDATA.pid]
start_wait=$
cli
cmp [name],dword 0
jz first_wait
cmp [name],eax
jz inc_counter
sti
call change_task
jmp start_wait
first_wait=$
mov [name],eax
mov [name+4],dword 1
jmp end_wait
inc_counter=$
inc dword [name+4]
end_wait=$
sti
pop eax
}
macro ReleaseSimpleCriticalSection name
{
local release_end
dec dword [name+4]
jnz release_end
mov [name],dword 0
release_end=$
}
macro TryWaitSimpleCriticalSection name ;result in eax and in flags
{
local ok,try_end
mov eax,[CURRENT_TASK+second_base_address]
mov eax,[eax+TASKDATA.pid]
cmp [name],eax
jz ok
cmp [name],0
jz ok
xor eax,eax
jmp try_end
ok=$
xor eax,eax
inc eax
try_end=$
}
_cli equ call MEM_HeapLock
_sti equ call MEM_HeapUnLock
end if
 
/kernel/branches/core/sys32.inc
0,0 → 1,828
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; MenuetOS process management, protected ring3 ;;
;; ;;
;; Distributed under GPL. See file COPYING for details. ;;
;; Copyright 2003 Ville Turjanmaa ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 982 $
 
 
align 4
idtreg:
dw 8*0x41-1
dd idts+8
 
build_interrupt_table:
 
mov edi, idts+8
mov esi, sys_int
mov ecx, 0x40
@@:
lodsd
mov [edi], ax ; lower part of offset
mov [edi+2], word os_code ; segment selector
mov ax, word 10001110b shl 8 ; type: interrupt gate
mov [edi+4], eax
add edi, 8
loop @b
 
;mov edi,8*0x40+idts+8
mov dword [edi], (i40 and 0xFFFF) or (os_code shl 16)
mov dword [edi+4], (11101111b shl 8) or (i40 and 0xFFFF0000)
; type: trap gate
ret
 
iglobal
 
msg_sel_ker db "kernel", 0
msg_sel_app db "application", 0
 
sys_int:
dd e0,debug_exc,e2,e3
dd e4,e5,e6,e7
dd e8,e9,e10,e11
dd e12,e13,page_fault_handler,e15
 
dd except_16, e17,e18, except_19
times 12 dd unknown_interrupt
 
dd irq0, irq_serv.irq_1, irq_serv.irq_2
if USE_COM_IRQ
dd irq_serv.irq_3, irq_serv.irq_4
else
dd p_irq3, p_irq4
end if
dd irq_serv.irq_5, p_irq6, irq_serv.irq_7
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10
dd irq_serv.irq_11, irq_serv.irq_12,irqD ,p_irq14,p_irq15
 
times 16 dd unknown_interrupt
 
dd i40
endg
 
macro save_ring3_context
{
pushad
}
macro restore_ring3_context
{
popad
}
 
; simply return control to interrupted process
unknown_interrupt:
iret
 
macro exc_wo_code [num]
{
forward
e#num :
save_ring3_context
mov bl, num
jmp exc_c
}
 
macro exc_w_code [num]
{
forward
e#num :
add esp, 4
save_ring3_context
mov bl, num
jmp exc_c
}
 
exc_wo_code 0, 2, 3, 4, 5, 6, 9, 15, 18
exc_w_code 8, 10, 11, 12, 13, 14, 17
 
exc_c:
mov ax, app_data ;èñêëþ÷åíèå
mov ds, ax ;çàãðóçèì ïðàâèëüíûå çíà÷åíè
mov es, ax ;â ðåãèñòðû
 
; redirect to V86 manager? (EFLAGS & 0x20000) != 0?
test byte [esp+20h+8+2], 2
jnz v86_exc_c
 
; test if debugging
cli
mov eax, [current_slot]
mov eax, [eax+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
movzx eax, bl
mov [error_interrupt], eax
call show_error_parameters
add esp, 0x20
mov edx, [TASK_BASE]
mov [edx + TASKDATA.state], byte 4
 
jmp change_task
 
.debug:
; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID
cld
movzx ecx, bl
push ecx
mov ecx, [TASK_BASE]
push dword [ecx+TASKDATA.pid] ; PID of current process
push 12
pop ecx
push 1 ; 1=exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task
restore_ring3_context
iretd
 
iglobal
hexletters db '0123456789ABCDEF'
error_interrupt dd -1
endg
 
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
show_error_parameters:
mov eax,[CURRENT_TASK]
shl eax, 5
DEBUGF 1, "K : Process - forced terminate PID: %x\n", [CURRENT_TASK + TASKDATA.pid + eax]
mov eax, [error_interrupt]
cmp al, 0x08
jne @f
DEBUGF 1, "K : Double fault\n"
jmp defined_error
@@:
cmp al, 0x0a
jne @f
DEBUGF 1, "K : Invalid TSS\n"
jmp defined_error
@@:
cmp al, 0x0b
jne @f
DEBUGF 1, "K : Segment not present\n"
jmp defined_error
@@:
cmp al, 0x0c
jne @f
DEBUGF 1, "K : Stack fault\n"
jmp defined_error
@@:
cmp al, 0x0d
jne @f
DEBUGF 1, "K : General protection fault\n"
jmp defined_error
@@:
cmp al, 0x0e
jne @f
DEBUGF 1, "K : Page fault\n"
jmp defined_error
@@:
DEBUGF 1, "K : Undefined Exception\n"
defined_error:
DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [esp + 0x20], [esp - 12 + 0x20], [esp - 4 + 0x20]
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [esp - 8 + 0x20], [esp - 24 + 0x20], [esp - 28 + 0x20]
DEBUGF 1, "K : EBP : %x EIP : %x ", [esp - 20 + 0x20], [esp + 4 + 0x20]
 
mov eax, [esp + 8 + 0x20]
mov edi, msg_sel_app
mov ebx, [esp + 16 + 0x20]
cmp eax, app_code
je @f
mov edi, msg_sel_ker
mov ebx, [esp - 16 + 0x20]
@@:
DEBUGF 1, "ESP : %x\nK : Flags : %x CS : %x (%s)\n", ebx, [esp + 12 + 0x20], eax, edi
ret
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 
; irq1 -> hid/keyboard.inc
macro irqh [num]
{
forward
p_irq#num :
mov edi, num
jmp irqhandler
}
 
irqh 2,3,4,5,7,8,9,10,11
 
 
p_irq6:
save_ring3_context
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov edi, 6
cmp [v86_irqhooks+edi*8], 0
jnz v86_irq2
call fdc_irq
call ready_for_next_irq
restore_ring3_context
iret
 
 
p_irq14:
save_ring3_context
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov edi, 14
cmp [v86_irqhooks+edi*8], 0
jnz v86_irq2
; mov byte [BOOT_VAR + 0x48E], 0xFF
call [irq14_func]
call ready_for_next_irq_1
restore_ring3_context
iret
p_irq15:
save_ring3_context
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov edi, 15
cmp [v86_irqhooks+edi*8], 0
jnz v86_irq2
; mov byte [BOOT_VAR + 0x48E], 0xFF
call [irq15_func]
call ready_for_next_irq_1
restore_ring3_context
iret
 
ready_for_next_irq:
mov [check_idle_semaphore],5
mov al, 0x20
out 0x20, al
ret
 
ready_for_next_irq_1:
mov [check_idle_semaphore],5
mov al, 0x20
out 0xa0,al
out 0x20, al
ret
 
irqD:
save_ring3_context
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
 
mov dx,0xf0
mov al,0
out dx,al
 
mov dx,0xa0
mov al,0x20
out dx,al
mov dx,0x20
out dx,al
 
restore_ring3_context
 
iret
 
 
irqhandler:
 
mov esi,edi ; 1
shl esi,6 ; 1
add esi,irq00read ; 1
shl edi,12 ; 1
add edi,IRQ_SAVE
mov ecx,16
 
irqnewread:
dec ecx
js irqover
 
movzx edx, word [esi] ; 2+
 
test edx, edx ; 1
jz irqover
 
 
mov ebx, [edi] ; address of begin of buffer in edi ; + 0x0 dword - data size
mov eax, 4000 ; + 0x4 dword - data begin offset
cmp ebx, eax
je irqfull
add ebx, [edi + 0x4] ; add data size to data begin offset
cmp ebx, eax ; if end of buffer, begin cycle again
jb @f
 
xor ebx, ebx
 
@@:
add ebx, edi
movzx eax, byte[esi + 3] ; get type of data being received 1 - byte, 2 - word
dec eax
jz irqbyte
dec eax
jnz noirqword
 
in ax,dx
cmp ebx, 3999 ; check for address odd in the end of buffer
jne .odd
mov [ebx + 0x10], ax
jmp .add_size
.odd:
mov [ebx + 0x10], al ; I could make mistake here :)
mov [edi + 0x10], ah
.add_size:
add dword [edi], 2
jmp nextport
 
 
irqbyte:
in al,dx
mov [ebx + 0x10],al
inc dword [edi]
nextport:
add esi,4
jmp irqnewread
 
 
noirqword:
irqfull:
irqover:
 
ret
 
 
 
set_application_table_status:
push eax
 
mov eax,[CURRENT_TASK]
shl eax, 5
add eax,CURRENT_TASK+TASKDATA.pid
mov eax,[eax]
 
mov [application_table_status],eax
 
pop eax
 
ret
 
 
clear_application_table_status:
push eax
 
mov eax,[CURRENT_TASK]
shl eax, 5
add eax,CURRENT_TASK+TASKDATA.pid
mov eax,[eax]
 
cmp eax,[application_table_status]
jne apptsl1
mov [application_table_status],0
apptsl1:
 
pop eax
 
ret
 
sys_resize_app_memory:
; eax = 1 - resize
; ebx = new amount of memory
 
cmp eax,1
jne .no_application_mem_resize
 
stdcall new_mem_resize, ebx
mov [esp+36], eax
ret
 
.no_application_mem_resize:
ret
 
sys_threads:
 
; eax=1 create thread
;
; ebx=thread start
; ecx=thread stack value
;
; on return : eax = pid
jmp new_sys_threads
 
iglobal
process_terminating db 'K : Process - terminating',13,10,0
process_terminated db 'K : Process - done',13,10,0
msg_obj_destroy db 'K : destroy app object',13,10,0
endg
 
; param
; esi= slot
 
terminate: ; terminate application
 
.slot equ esp ;locals
 
push esi ;save .slot
 
shl esi, 8
cmp [SLOT_BASE+esi+APPDATA.dir_table], 0
jne @F
pop esi
shl esi, 5
mov [CURRENT_TASK+esi+TASKDATA.state], 9
ret
@@:
;mov esi,process_terminating
;call sys_msg_board_str
DEBUGF 1,"%s",process_terminating
@@:
cli
cmp [application_table_status],0
je term9
sti
call change_task
jmp @b
term9:
call set_application_table_status
 
; if the process is in V86 mode...
mov eax, [.slot]
shl eax, 8
mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack]
add esi, RING0_STACK_SIZE
cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi
jz .nov86
; ...it has page directory for V86 mode
mov esi, [eax+SLOT_BASE+APPDATA.saved_esp0]
mov ecx, [esi+4]
mov [eax+SLOT_BASE+APPDATA.dir_table], ecx
; ...and I/O permission map for V86 mode
mov ecx, [esi+12]
mov [eax+SLOT_BASE+APPDATA.io_map], ecx
mov ecx, [esi+8]
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx
.nov86:
 
mov esi, [.slot]
shl esi,8
add esi, SLOT_BASE+APP_OBJ_OFFSET
@@:
mov eax, [esi+APPOBJ.fd]
test eax, eax
jz @F
 
cmp eax, esi
je @F
 
push esi
call [eax+APPOBJ.destroy]
DEBUGF 1,"%s",msg_obj_destroy
pop esi
jmp @B
@@:
mov eax, [.slot]
shl eax, 8
mov eax,[SLOT_BASE+eax+APPDATA.dir_table]
stdcall destroy_app_space, eax
 
mov esi, [.slot]
cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1
jne @F
 
mov [fpu_owner],1
mov eax, [256+SLOT_BASE+APPDATA.fpu_state]
clts
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
fxrstor [eax]
jmp @F
.no_SSE:
fnclex
frstor [eax]
@@:
 
mov [KEY_COUNT],byte 0 ; empty keyboard buffer
mov [BTN_COUNT],byte 0 ; empty button buffer
 
 
; remove defined hotkeys
mov eax, hotkey_list
.loop:
cmp [eax+8], esi
jnz .cont
mov ecx, [eax]
jecxz @f
push dword [eax+12]
pop dword [ecx+12]
@@:
mov ecx, [eax+12]
push dword [eax]
pop dword [ecx]
xor ecx, ecx
mov [eax], ecx
mov [eax+4], ecx
mov [eax+8], ecx
mov [eax+12], ecx
.cont:
add eax, 16
cmp eax, hotkey_list+256*16
jb .loop
; remove hotkeys in buffer
mov eax, hotkey_buffer
.loop2:
cmp [eax], esi
jnz .cont2
and dword [eax+4], 0
and dword [eax], 0
.cont2:
add eax, 8
cmp eax, hotkey_buffer+120*8
jb .loop2
 
mov ecx,esi ; remove buttons
bnewba2:
mov edi,[BTN_ADDR]
mov eax,edi
cld
movzx ebx,word [edi]
inc bx
bnewba:
dec bx
jz bnmba
add eax,0x10
cmp cx,[eax]
jnz bnewba
pusha
mov ecx,ebx
inc ecx
shl ecx,4
mov ebx,eax
add eax,0x10
call memmove
dec dword [edi]
popa
jmp bnewba2
bnmba:
 
pusha ; save window coordinates for window restoring
cld
shl esi,5
add esi,window_data
mov eax,[esi+WDATA.box.left]
mov [dlx],eax
add eax,[esi+WDATA.box.width]
mov [dlxe],eax
mov eax,[esi+WDATA.box.top]
mov [dly],eax
add eax,[esi+WDATA.box.height]
mov [dlye],eax
 
xor eax, eax
mov [esi+WDATA.box.left],eax
mov [esi+WDATA.box.width],eax
mov [esi+WDATA.box.top],eax
mov [esi+WDATA.box.height],eax
mov [esi+WDATA.cl_workarea],eax
mov [esi+WDATA.cl_titlebar],eax
mov [esi+WDATA.cl_frames],eax
mov dword [esi+WDATA.reserved],eax ; clear all flags: wstate, redraw, wdrawn
lea edi, [esi-window_data+draw_data]
mov ecx,32/4
rep stosd
popa
 
; debuggee test
pushad
mov edi, esi
shl edi, 5
mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot]
test eax, eax
jz .nodebug
push 8
pop ecx
push dword [CURRENT_TASK+edi+TASKDATA.pid] ; PID
push 2
call debugger_notify
pop ecx
pop ecx
.nodebug:
popad
 
mov ebx, [.slot]
shl ebx, 8
push ebx
mov ebx,[SLOT_BASE+ebx+APPDATA.pl0_stack]
 
stdcall kernel_free, ebx
 
pop ebx
mov ebx,[SLOT_BASE+ebx+APPDATA.cur_dir]
stdcall kernel_free, ebx
 
mov edi, [.slot]
shl edi,8
add edi,SLOT_BASE
 
mov eax, [edi+APPDATA.io_map]
cmp eax, (tss._io_map_0-OS_BASE+PG_MAP)
je @F
call free_page
@@:
mov eax, [edi+APPDATA.io_map+4]
cmp eax, (tss._io_map_1-OS_BASE+PG_MAP)
je @F
call free_page
@@:
mov eax, 0x20202020
stosd
stosd
stosd
mov ecx,244/4
xor eax, eax
rep stosd
 
; activate window
movzx eax, word [WIN_STACK + esi*2]
cmp eax, [TASK_COUNT]
jne .dont_activate
pushad
.check_next_window:
dec eax
cmp eax, 1
jbe .nothing_to_activate
lea esi, [WIN_POS+eax*2]
movzx edi, word [esi] ; edi = process
shl edi, 5
cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots
je .check_next_window
add edi, window_data
; \begin{diamond}[19.09.2006]
; skip minimized windows
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
jnz .check_next_window
; \end{diamond}
call waredraw
.nothing_to_activate:
popad
.dont_activate:
 
push esi ; remove hd1 & cd & flp reservation
shl esi, 5
mov esi, [esi+CURRENT_TASK+TASKDATA.pid]
cmp [hd1_status], esi
jnz @f
call free_hd_channel
mov [hd1_status], 0
@@:
cmp [cd_status], esi
jnz @f
call free_cd_channel
mov [cd_status], 0
@@:
cmp [flp_status], esi
jnz @f
mov [flp_status], 0
@@:
pop esi
cmp [bgrlockpid], esi
jnz @f
and [bgrlockpid], 0
mov [bgrlock], 0
@@:
 
pusha ; remove all irq reservations
mov eax,esi
shl eax, 5
mov eax,[eax+CURRENT_TASK+TASKDATA.pid]
mov edi,irq_owner
xor ebx, ebx
xor edx, edx
newirqfree:
cmp [edi + 4 * ebx], eax
jne nofreeirq
mov [edi + 4 * ebx], edx ; remove irq reservation
mov [irq_tab + 4 * ebx], edx ; remove irq handler
mov [irq_rights + 4 * ebx], edx ; set access rights to full access
nofreeirq:
inc ebx
cmp ebx, 16
jb newirqfree
popa
 
pusha ; remove all port reservations
mov edx,esi
shl edx, 5
add edx,CURRENT_TASK
mov edx,[edx+TASKDATA.pid]
 
rmpr0:
 
mov esi,[RESERVED_PORTS]
 
cmp esi,0
je rmpr9
 
rmpr3:
 
mov edi,esi
shl edi,4
add edi,RESERVED_PORTS
 
cmp edx,[edi]
je rmpr4
 
dec esi
jnz rmpr3
 
jmp rmpr9
 
rmpr4:
 
mov ecx,256
sub ecx,esi
shl ecx,4
 
mov esi,edi
add esi,16
cld
rep movsb
 
dec dword [RESERVED_PORTS]
 
jmp rmpr0
 
rmpr9:
 
popa
mov edi,esi ; do not run this process slot
shl edi, 5
mov [edi+CURRENT_TASK + TASKDATA.state],byte 9
; debugger test - terminate all debuggees
mov eax, 2
mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot
.xd0:
cmp eax, [TASK_COUNT]
ja .xd1
cmp dword [ecx], esi
jnz @f
and dword [ecx], 0
pushad
xchg eax, ecx
mov ebx, 2
call sys_system
popad
@@:
inc eax
add ecx, 0x100
jmp .xd0
.xd1:
; call systest
sti ; .. and life goes on
 
mov eax, [dlx]
mov ebx, [dly]
mov ecx, [dlxe]
mov edx, [dlye]
call calculatescreen
xor eax, eax
xor esi, esi
call redrawscreen
 
mov [MOUSE_BACKGROUND],byte 0 ; no mouse background
mov [DONT_DRAW_MOUSE],byte 0 ; draw mouse
 
mov [application_table_status],0
;mov esi,process_terminated
;call sys_msg_board_str
DEBUGF 1,"%s",process_terminated
add esp, 4
ret
restore .slot
 
iglobal
boot_sched_1 db 'Building gdt tss pointer',0
boot_sched_2 db 'Building IDT table',0
endg
 
 
build_scheduler:
 
mov esi,boot_sched_1
call boot_log
; call build_process_gdt_tss_pointer
 
; mov esi,boot_sched_2
; call boot_log
 
ret
/kernel/branches/core/syscall.inc
0,0 → 1,266
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 940 $
 
; Old style system call converter
align 16
cross_order:
; load all registers in crossed order
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
mov edi, [esp+28 + 4]
and edi,0xff
call dword [servetable+edi*4]
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSTEM CALL ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
align 16
i40:
pushad
cld
movzx eax, al
call dword [servetable2 + eax * 4]
popad
iretd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSENTER ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 32
sysenter_entry:
; Íàñòðàèâàåì ñòåê
mov esp, [ss:tss._esp0]
sti
push ebp ; save app esp + 4
mov ebp, [ebp] ; ebp - original ebp
;------------------
pushad
cld
 
movzx eax, al
call dword [servetable2 + eax * 4]
 
popad
;------------------
xchg ecx, [ss:esp] ; â âåðøèí ñòåêà - app ecx, ecx - app esp + 4
sub ecx, 4
xchg edx, [ecx] ; edx - return point, & save original edx
push edx
mov edx, [ss:esp + 4]
mov [ecx + 4], edx ; save original ecx
pop edx
sysexit
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSCALL ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32
syscall_entry:
; cli syscall clear IF
xchg esp, [ss:tss._esp0]
push ecx
lea ecx, [esp+4]
xchg ecx, [ss:tss._esp0]
sti
push ecx
mov ecx, [ecx]
;------------------
pushad
cld
 
movzx eax, al
call dword [servetable2 + eax * 4]
 
popad
;------------------
mov ecx, [ss:esp+4]
pop esp
sysret
iglobal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
servetable:
 
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd sys_midi ; 20-ResetMidi and OutputMidi
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,.
dd sys_settime ; 22-setting date,time,clock and alarm-clock
dd 0
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist
dd 0 ;
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,.
dd 0
dd 0 ;
dd 0
dd sys_current_directory ; 30-Get/SetCurrentDirectory
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd readmousepos ; 37-GetMousePosition_ScreenRelative,.
dd 0 ; 38-DrawLine
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,.
dd 0
dd 0
dd 0
dd sys_outport ; 43-SendDeviceData
dd 0
dd 0
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea
dd display_number ; 47-WriteNum
dd display_settings ; 48-SetRedrawType and SetButtonType
dd sys_apm ; 49-Advanced Power Management (APM)
dd random_shaped_window ; 50-Window shape & scale
dd syscall_threads ; 51-Threads
dd 0
dd 0
dd 0
dd sound_interface ; 55-Sound interface
dd 0
dd sys_pcibios ; 57-PCI BIOS32
dd file_system ; 58-Common file system interface
dd 0
dd sys_IPC ; 60-Inter Process Communication
dd sys_gs ; 61-Direct graphics access
dd sys_pci ; 62-PCI functions
dd sys_msg_board ; 63-System message board
dd sys_resize_app_memory ; 64-Resize application memory usage
dd syscall_putimage_palette; 65-PutImagePalette
dd sys_process_def ; 66-Process definitions - keyboard
dd sys_window_move ; 67-Window move or resize
dd f68 ; 68-Some internal services
dd sys_debug_services ; 69-Debug
dd file_system_lfn ; 70-Common file system interface, version 2
dd syscall_windowsettings ; 71-Window settings
dd sys_sendwindowmsg ; 72-Send window message
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; NEW SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
servetable2:
 
dd sys_drawwindow ; 0-DrawWindow
dd syscall_setpixel ; 1-SetPixel
dd sys_getkey ; 2-GetKey
dd sys_clock ; 3-GetTime
dd syscall_writetext ; 4-WriteText
dd delay_hs ; 5-DelayHs
dd syscall_openramdiskfile ; 6-OpenRamdiskFile
dd syscall_putimage ; 7-PutImage
dd sys_button ; 8-DefineButton
dd sys_cpuusage ; 9-GetProcessInfo
dd sys_waitforevent ; 10-WaitForEvent
dd sys_getevent ; 11-CheckForEvent
dd sys_redrawstat ; 12-BeginDraw and EndDraw
dd syscall_drawrect ; 13-DrawRect
dd syscall_getscreensize ; 14-GetScreenSize
dd sys_background ; 15-bgr
dd sys_cachetodiskette ; 16-FlushFloppyCache
dd sys_getbutton ; 17-GetButton
dd sys_system ; 18-System Services
dd paleholder ; 19-reserved
dd cross_order ; 20-ResetMidi and OutputMidi
dd cross_order ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,.
dd cross_order ; 22-setting date,time,clock and alarm-clock
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent
dd cross_order ; 24-PlayCdTrack,StopCd and GetCdPlaylist
dd undefined_syscall ; 25-reserved
dd cross_order ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,.
dd undefined_syscall ; 27-reserved
dd undefined_syscall ; 28-reserved
dd sys_date ; 29-GetDate
dd cross_order ; 30-Get/SetCurrentDirectory
dd undefined_syscall ; 31-reserved
dd undefined_syscall ; 32-reserved
dd undefined_syscall ; 33-reserved
dd undefined_syscall ; 34-reserved
dd syscall_getpixel ; 35-GetPixel
dd syscall_getarea ; 36-GetArea
dd cross_order ; 37-GetMousePosition_ScreenRelative,.
dd syscall_drawline ; 38-DrawLine
dd cross_order ; 39-GetBackgroundSize,ReadBgrData,.
dd set_app_param ; 40-WantEvents
dd syscall_getirqowner ; 41-GetIrqOwner
dd get_irq_data ; 42-ReadIrqData
dd cross_order ; 43-SendDeviceData
dd sys_programirq ; 44-ProgramIrqs
dd reserve_free_irq ; 45-ReserveIrq and FreeIrq
dd cross_order ; 46-ReservePortArea and FreePortArea
dd cross_order ; 47-WriteNum
dd cross_order ; 48-SetRedrawType and SetButtonType
dd cross_order ; 49-Advanced Power Management (APM)
dd cross_order ; 50-Window shape & scale
dd cross_order ; 51-Threads
dd cross_order ; 52-Stack driver status
dd cross_order ; 53-Socket interface
dd undefined_syscall ; 54-reserved
dd cross_order ; 55-Sound interface
dd undefined_syscall ; 56-reserved
dd cross_order ; 57-PCI BIOS32
dd cross_order ; 58-Common file system interface
dd undefined_syscall ; 59-reserved
dd cross_order ; 60-Inter Process Communication
dd cross_order ; 61-Direct graphics access
dd cross_order ; 62-PCI functions
dd cross_order ; 63-System message board
dd cross_order ; 64-Resize application memory usage
dd cross_order ; 65-PutImagePalette
dd cross_order ; 66-Process definitions - keyboard
dd cross_order ; 67-Window move or resize
dd cross_order ; 68-Some internal services
dd cross_order ; 69-Debug
dd cross_order ; 70-Common file system interface, version 2
dd cross_order ; 71-Window settings
dd cross_order ; 72-Send window message
dd sys_network ; 73-Network stack
dd sys_socket ; 74-Sockets
dd sys_protocols ; 75-Protocols
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall
dd sys_end ; -1-end application
 
endg
/kernel/branches/core/taskman.inc
0,0 → 1,1111
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 819 $
 
 
GREEDY_KERNEL equ 0
 
struc APP_HEADER_00
{ .banner dq ?
.version dd ? ;+8
.start dd ? ;+12
.i_end dd ? ;+16
.mem_size dd ? ;+20
.i_param dd ? ;+24
}
 
struc APP_HEADER_01
{ .banner dq ?
.version dd ? ;+8
.start dd ? ;+12
.i_end dd ? ;+16
.mem_size dd ? ;+20
.stack_top dd ? ;+24
.i_param dd ? ;+28
.i_icon dd ? ;+32
}
 
 
struc APP_PARAMS
{ .app_cmdline ;0x00
.app_path ;0x04
.app_eip ;0x08
.app_esp ;0x0C
.app_mem ;0x10
}
 
macro _clear_ op
{ mov ecx, op/4
xor eax, eax
cld
rep stosd
}
 
fs_execute_from_sysdir:
xor ebx, ebx
xor edx, edx
mov esi, sysdir_path
 
align 4
proc fs_execute
 
;fn_read:dword, file_size:dword, cluster:dword
 
; ebx - cmdline
; edx - flags
; ebp - full filename
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it
 
locals
cmdline rd 64 ;256/4
filename rd 256 ;1024/4
flags dd ?
 
save_cr3 dd ?
slot dd ?
slot_base dd ?
file_base dd ?
file_size dd ?
;app header data
hdr_cmdline dd ? ;0x00
hdr_path dd ? ;0x04
hdr_eip dd ? ;0x08
hdr_esp dd ? ;0x0C
hdr_mem dd ? ;0x10
hdr_i_end dd ? ;0x14
endl
 
pushad
 
mov [flags], edx
 
; [ebp] pointer to filename
 
lea edi, [filename]
lea ecx, [edi+1024]
mov al, '/'
stosb
@@:
cmp edi, ecx
jae .bigfilename
lodsb
stosb
test al, al
jnz @b
mov esi, [ebp]
test esi, esi
jz .namecopied
mov byte [edi-1], '/'
@@:
cmp edi, ecx
jae .bigfilename
lodsb
stosb
test al, al
jnz @b
jmp .namecopied
.bigfilename:
popad
mov eax, -ERROR_FILE_NOT_FOUND
ret
.namecopied:
 
mov [cmdline], ebx
test ebx, ebx
jz @F
 
lea eax, [cmdline]
mov dword [eax+252], 0
stdcall strncpy, eax, ebx, 255
@@:
lea eax, [filename]
stdcall load_file, eax
mov ecx, -ERROR_FILE_NOT_FOUND
test eax, eax
jz .err_file
 
mov [file_base], eax
mov [file_size], ebx
 
lea ebx, [hdr_cmdline]
call test_app_header
mov ecx, -0x1F
test eax, eax
jz .err_hdr
 
;mov esi, new_process_loading
;call sys_msg_board_str ; write message to message board
DEBUGF 1,"%s",new_process_loading
 
.wait_lock:
cmp [application_table_status],0
je .get_lock
call change_task
jmp .wait_lock
 
.get_lock:
mov eax, 1
xchg eax, [application_table_status]
cmp eax, 0
jne .wait_lock
 
call set_application_table_status
 
call get_new_process_place
test eax, eax
mov ecx, -0x20 ; too many processes
jz .err
 
mov [slot], eax
shl eax, 8
add eax, SLOT_BASE
mov [slot_base], eax
mov edi, eax
_clear_ 256 ;clean extended information about process
 
; write application name
lea eax, [filename]
stdcall strrchr, eax, '/' ; now eax points to name without path
 
lea esi, [eax+1]
test eax, eax
jnz @F
lea esi, [filename]
@@:
mov ecx, 8 ; 8 chars for name
mov edi, [slot_base]
.copy_process_name_loop:
lodsb
cmp al, '.'
jz .copy_process_name_done
test al, al
jz .copy_process_name_done
stosb
loop .copy_process_name_loop
.copy_process_name_done:
 
mov ebx, cr3
mov [save_cr3], ebx
 
stdcall create_app_space,[hdr_mem],[file_base],[file_size]
mov ecx, -30 ; no memory
test eax, eax
jz .failed
 
mov ebx,[slot_base]
mov [ebx+APPDATA.dir_table],eax
mov eax,[hdr_mem]
mov [ebx+APPDATA.mem_size],eax
 
if GREEDY_KERNEL
else
mov ecx, [hdr_mem]
mov edi, [file_size]
add edi, 4095
and edi, not 4095
sub ecx, edi
jna @F
 
xor eax, eax
cld
rep stosb
@@:
end if
 
; release only virtual space, not phisical memory
 
stdcall free_kernel_space, [file_base]
lea eax, [hdr_cmdline]
lea ebx, [cmdline]
lea ecx, [filename]
stdcall set_app_params ,[slot],eax,ebx,ecx,[flags]
 
mov eax, [save_cr3]
call set_cr3
 
xor ebx, ebx
mov [application_table_status],ebx ;unlock application_table_status mutex
mov eax,[process_number] ;set result
ret
.failed:
mov eax, [save_cr3]
call set_cr3
.err:
.err_hdr:
stdcall kernel_free,[file_base]
.err_file:
xor eax, eax
mov [application_table_status],eax
mov eax, ecx
ret
endp
 
align 4
test_app_header:
virtual at eax
APP_HEADER_00 APP_HEADER_00
end virtual
virtual at eax
APP_HEADER_01 APP_HEADER_01
end virtual
 
cmp dword [eax], 'MENU'
jne .fail
cmp word [eax+4],'ET'
jne .fail
 
cmp [eax+6], word '00'
jne .check_01_header
 
mov ecx,[APP_HEADER_00.start]
mov [ebx+0x08], ecx ;app_eip
mov edx,[APP_HEADER_00.mem_size]
mov [ebx+0x10], edx ;app_mem
shr edx,1
sub edx,0x10
mov [ebx+0x0C], edx ;app_esp
mov ecx,[APP_HEADER_00.i_param]
mov [ebx], ecx ;app_cmdline
mov [ebx+4], dword 0 ;app_path
mov edx, [APP_HEADER_00.i_end]
mov [ebx+0x14], edx
ret
 
.check_01_header:
 
cmp [eax+6],word '01'
jne .fail
 
mov ecx,[APP_HEADER_01.start]
mov [ebx+0x08], ecx ;app_eip
mov edx,[APP_HEADER_01.mem_size]
 
; \begin{diamond}[20.08.2006]
; sanity check (functions 19,58 load app_i_end bytes and that must
; fit in allocated memory to prevent kernel faults)
cmp edx,[APP_HEADER_01.i_end]
jb .fail
; \end{diamond}[20.08.2006]
 
mov [ebx+0x10], edx ;app_mem
mov ecx,[APP_HEADER_01.stack_top]
mov [ebx+0x0C], ecx ;app_esp
mov edx,[APP_HEADER_01.i_param]
mov [ebx], edx ;app_cmdline
mov ecx,[APP_HEADER_01.i_icon]
mov [ebx+4], ecx ;app_path
mov edx, [APP_HEADER_01.i_end]
mov [ebx+0x14], edx
ret
.fail:
xor eax, eax
ret
 
align 4
proc get_new_process_place
;input:
; none
;result:
; eax=[new_process_place]<>0 - ok
; 0 - failed.
;This function find least empty slot.
;It doesn't increase [TASK_COUNT]!
mov eax,CURRENT_TASK
mov ebx,[TASK_COUNT]
inc ebx
shl ebx,5
add ebx,eax ;ebx - address of process information for (last+1) slot
.newprocessplace:
;eax = address of process information for current slot
cmp eax,ebx
jz .endnewprocessplace ;empty slot after high boundary
add eax,0x20
cmp word [eax+0xa],9 ;check process state, 9 means that process slot is empty
jnz .newprocessplace
.endnewprocessplace:
mov ebx,eax
sub eax,CURRENT_TASK
shr eax,5 ;calculate slot index
cmp eax,256
jge .failed ;it should be <256
mov word [ebx+0xa],9 ;set process state to 9 (for slot after hight boundary)
ret
.failed:
xor eax,eax
ret
endp
 
align 4
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword
locals
app_pages dd ?
img_pages dd ?
dir_addr dd ?
app_tabs dd ?
endl
 
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
 
xor eax, eax
mov [dir_addr], eax
 
mov eax, [app_size]
add eax, 4095
and eax, NOT(4095)
mov [app_size], eax
mov ebx, eax
shr eax, 12
mov [app_pages], eax
 
add ebx, 0x3FFFFF
and ebx, NOT(0x3FFFFF)
shr ebx, 22
mov [app_tabs], ebx
 
mov ecx, [img_size]
add ecx, 4095
and ecx, NOT(4095)
 
mov [img_size], ecx
shr ecx, 12
mov [img_pages], ecx
 
if GREEDY_KERNEL
lea eax, [ecx+ebx+2] ;only image size
else
lea eax, [eax+ebx+2] ;all requested memory
end if
cmp eax, [pg_data.pages_free]
ja .fail
 
call alloc_page
test eax, eax
jz .fail
mov [dir_addr], eax
stdcall map_page,[tmp_task_pdir],eax,dword PG_SW
 
mov edi, [tmp_task_pdir]
mov ecx, (OS_BASE shr 20)/4
xor eax, eax
cld
rep stosd
 
mov ecx, (OS_BASE shr 20)/4
mov esi, sys_pgdir+(OS_BASE shr 20)
rep movsd
 
mov eax, [dir_addr]
or eax, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
 
and eax, -4096
call set_cr3
 
mov edx, [app_tabs]
mov edi, new_app_base
@@:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page_table, edi, eax
add edi, 0x00400000
dec edx
jnz @B
 
mov edi, new_app_base
shr edi, 10
add edi, page_tabs
 
mov ecx, [app_tabs]
shl ecx, 10
xor eax, eax
rep stosd
 
mov ecx, [img_pages]
mov ebx, PG_UW
mov edx, new_app_base
mov esi, [img_base]
mov edi, new_app_base
shr esi, 10
shr edi, 10
add esi, page_tabs
add edi, page_tabs
.remap:
lodsd
or eax, ebx ; force user level r/w access
stosd
add edx, 0x1000
dec [app_pages]
dec ecx
jnz .remap
 
mov ecx, [app_pages]
test ecx, ecx
jz .done
 
if GREEDY_KERNEL
mov eax, 0x02
rep stosd
else
 
.alloc:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page,edx,eax,dword PG_UW
add edx, 0x1000
dec [app_pages]
jnz .alloc
end if
 
.done:
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP
 
dec [pg_data.pg_mutex]
mov eax, [dir_addr]
ret
.fail:
dec [pg_data.pg_mutex]
cmp [dir_addr], 0
je @f
stdcall destroy_app_space, [dir_addr]
@@:
xor eax, eax
ret
endp
 
align 4
set_cr3:
 
mov ebx, [current_slot]
mov [ebx+APPDATA.dir_table], eax
mov cr3, eax
ret
 
align 4
proc destroy_page_table stdcall, pg_tab:dword
 
push esi
 
mov esi, [pg_tab]
mov ecx, 1024
.free:
mov eax, [esi]
test eax, 1
jz .next
test eax, 1 shl 9
jnz .next ;skip shared pages
call free_page
.next:
add esi, 4
dec ecx
jnz .free
pop esi
ret
endp
 
align 4
proc destroy_app_space stdcall, pg_dir:dword
 
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
 
xor edx,edx
mov eax,0x2
mov ebx, [pg_dir]
.loop:
;eax = current slot of process
mov ecx,eax
shl ecx,5
cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running?
jz @f ;skip empty slots
shl ecx,3
cmp [SLOT_BASE+ecx+0xB8],ebx ;compare page directory addresses
jnz @f
inc edx ;thread found
@@:
inc eax
cmp eax,[TASK_COUNT] ;exit loop if we look through all processes
jle .loop
 
;edx = number of threads
;our process is zombi so it isn't counted
cmp edx,1
jg .exit
;if there isn't threads then clear memory.
 
mov eax, [pg_dir]
and eax, not 0xFFF
stdcall map_page,[tmp_task_pdir],eax,dword PG_SW
mov esi, [tmp_task_pdir]
mov edi, (OS_BASE shr 20)/4
.destroy:
mov eax, [esi]
test eax, 1
jz .next
and eax, not 0xFFF
stdcall map_page,[tmp_task_ptab],eax,dword PG_SW
stdcall destroy_page_table, [tmp_task_ptab]
mov eax, [esi]
call free_page
.next:
add esi, 4
dec edi
jnz .destroy
 
mov eax, [pg_dir]
call free_page
.exit:
stdcall map_page,[tmp_task_ptab],dword 0,dword PG_UNMAP
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP
dec [pg_data.pg_mutex]
ret
endp
 
align 4
get_pid:
mov eax, [TASK_BASE]
mov eax, [eax+TASKDATA.pid]
ret
 
pid_to_slot:
;Input:
; eax - pid of process
;Output:
; eax - slot of process or 0 if process don't exists
;Search process by PID.
push ebx
push ecx
mov ebx,[TASK_COUNT]
shl ebx,5
mov ecx,2*32
 
.loop:
;ecx=offset of current process info entry
;ebx=maximum permitted offset
cmp byte [CURRENT_TASK+ecx+0xa],9
jz .endloop ;skip empty slots
cmp [CURRENT_TASK+ecx+0x4],eax ;check PID
jz .pid_found
.endloop:
add ecx,32
cmp ecx,ebx
jle .loop
 
pop ecx
pop ebx
xor eax,eax
ret
 
.pid_found:
shr ecx,5
mov eax,ecx ;convert offset to index of slot
pop ecx
pop ebx
ret
 
check_region:
;input:
; ebx - start of buffer
; ecx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
mov eax,[CURRENT_TASK]
jmp check_process_region
;-----------------------------------------------------------------------------
check_process_region:
;input:
; eax - slot
; ebx - start of buffer
; ecx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
 
test ecx,ecx
jle .ok
shl eax,5
cmp word [CURRENT_TASK+eax+0xa],0
jnz .failed
shl eax,3
mov eax,[SLOT_BASE+eax+0xb8]
test eax,eax
jz .failed
 
mov eax,1
ret
 
 
; call MEM_Get_Linear_Address
; push ebx
; push ecx
; push edx
; mov edx,ebx
; and edx,not (4096-1)
; sub ebx,edx
; add ecx,ebx
; mov ebx,edx
; add ecx,(4096-1)
; and ecx,not (4096-1)
;.loop:
;;eax - linear address of page directory
;;ebx - current page
;;ecx - current size
; mov edx,ebx
; shr edx,22
; mov edx,[eax+4*edx]
; and edx,not (4096-1)
; test edx,edx
; jz .failed1
; push eax
; mov eax,edx
; call MEM_Get_Linear_Address
; mov edx,ebx
; shr edx,12
; and edx,(1024-1)
; mov eax,[eax+4*edx]
; and eax,not (4096-1)
; test eax,eax
; pop eax
; jz .failed1
; add ebx,4096
; sub ecx,4096
; jg .loop
; pop edx
; pop ecx
; pop ebx
.ok:
mov eax,1
ret
;
;.failed1:
; pop edx
; pop ecx
; pop ebx
.failed:
xor eax,eax
ret
 
align 4
proc read_process_memory
;Input:
; eax - process slot
; ebx - buffer address
; ecx - buffer size
; edx - start address in other process
;Output:
; eax - number of bytes read.
locals
slot dd ?
buff dd ?
r_count dd ?
offset dd ?
tmp_r_cnt dd ?
endl
 
mov [slot], eax
mov [buff], ebx
and [r_count], 0
mov [tmp_r_cnt], ecx
mov [offset], edx
 
pushad
.read_mem:
mov edx, [offset]
mov ebx, [tmp_r_cnt]
 
mov ecx, 0x400000
and edx, 0x3FFFFF
sub ecx, edx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
cmp ecx, 0x8000
jna @F
mov ecx, 0x8000
@@:
mov eax, [slot]
shl eax,8
mov ebx, [offset]
; add ebx, new_app_base
push ecx
stdcall map_memEx, [proc_mem_map],\
[SLOT_BASE+eax+0xB8],\
ebx, ecx
pop ecx
 
mov esi, [offset]
and esi, 0xfff
add esi, [proc_mem_map]
mov edi, [buff]
mov edx, ecx
rep movsb
add [r_count], edx
 
add [offset], edx
sub [tmp_r_cnt], edx
jnz .read_mem
 
popad
mov eax, [r_count]
ret
endp
 
align 4
proc write_process_memory
;Input:
; eax - process slot
; ebx - buffer address
; ecx - buffer size
; edx - start address in other process
;Output:
; eax - number of bytes written
 
locals
slot dd ?
buff dd ?
w_count dd ?
offset dd ?
tmp_w_cnt dd ?
endl
 
mov [slot], eax
mov [buff], ebx
and [w_count], 0
mov [tmp_w_cnt], ecx
mov [offset], edx
 
pushad
.read_mem:
mov edx, [offset]
mov ebx, [tmp_w_cnt]
 
mov ecx, 0x400000
and edx, 0x3FFFFF
sub ecx, edx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
cmp ecx, 0x8000
jna @F
mov ecx, 0x8000
@@:
mov eax, [slot]
shl eax,8
mov ebx, [offset]
; add ebx, new_app_base
push ecx
stdcall map_memEx, [proc_mem_map],\
[SLOT_BASE+eax+0xB8],\
ebx, ecx
pop ecx
 
mov edi, [offset]
and edi, 0xfff
add edi, [proc_mem_map]
mov esi, [buff]
mov edx, ecx
rep movsb
 
add [w_count], edx
add [offset], edx
sub [tmp_w_cnt], edx
jnz .read_mem
 
popad
mov eax, [w_count]
ret
endp
 
align 4
proc new_sys_threads
locals
slot dd ?
app_cmdline dd ? ;0x00
app_path dd ? ;0x04
app_eip dd ? ;0x08
app_esp dd ? ;0x0C
app_mem dd ? ;0x10
endl
 
cmp eax,1
jne .failed ;other subfunctions
 
xor eax,eax
mov [app_cmdline], eax
mov [app_path], eax
mov [app_eip], ebx
mov [app_esp], ecx
 
;mov esi,new_process_loading
;call sys_msg_board_str
DEBUGF 1,"%s",new_process_loading
.wait_lock:
cmp [application_table_status],0
je .get_lock
call change_task
jmp .wait_lock
 
.get_lock:
mov eax, 1
xchg eax, [application_table_status]
cmp eax, 0
jne .wait_lock
 
call set_application_table_status
 
call get_new_process_place
test eax, eax
jz .failed
 
mov [slot], eax
 
mov esi,[current_slot]
mov ebx,esi ;ebx=esi - pointer to extended information about current thread
 
mov edi, eax
shl edi,8
add edi,SLOT_BASE
mov edx,edi ;edx=edi - pointer to extended infomation about new thread
mov ecx,256/4
xor eax, eax
cld
rep stosd ;clean extended information about new thread
mov esi,ebx
mov edi,edx
mov ecx,11
rep movsb ;copy process name
 
mov eax,[ebx+APPDATA.heap_base]
mov [edx+APPDATA.heap_base], eax
 
mov ecx,[ebx+APPDATA.heap_top]
mov [edx+APPDATA.heap_top], ecx
 
mov eax,[ebx+APPDATA.mem_size]
mov [edx+APPDATA.mem_size], eax
 
mov ecx,[ebx+APPDATA.dir_table]
mov [edx+APPDATA.dir_table],ecx ;copy page directory
 
lea eax, [app_cmdline]
stdcall set_app_params ,[slot],eax,dword 0,\
dword 0,dword 0
 
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
DEBUGF 1,"%s",new_process_running
 
mov [application_table_status],0 ;unlock application_table_status mutex
mov eax,[process_number] ;set result
ret
.failed:
mov [application_table_status],0
mov eax,-1
ret
endp
 
; param
; ebx=mutex
 
align 4
wait_mutex:
push eax
push ebx
.do_wait:
cmp dword [ebx],0
je .get_lock
call change_task
jmp .do_wait
.get_lock:
mov eax, 1
xchg eax, [ebx]
test eax, eax
jnz .do_wait
pop ebx
pop eax
ret
 
EFL_IF equ 0x0200
EFL_IOPL1 equ 0x1000
EFL_IOPL2 equ 0x2000
EFL_IOPL3 equ 0x3000
 
 
align 4
proc set_app_params stdcall,slot:dword, params:dword,\
cmd_line:dword, app_path:dword, flags:dword
 
locals
pl0_stack dd ?
endl
 
stdcall kernel_alloc, RING0_STACK_SIZE+512
mov [pl0_stack], eax
 
lea edi, [eax+RING0_STACK_SIZE]
 
mov eax, [slot]
mov ebx, eax
 
shl eax, 8
mov [eax+SLOT_BASE+APPDATA.fpu_state], edi
mov [eax+SLOT_BASE+APPDATA.fpu_handler], 0
mov [eax+SLOT_BASE+APPDATA.sse_handler], 0
 
;set default io permission map
mov [eax+SLOT_BASE+APPDATA.io_map],\
(tss._io_map_0-OS_BASE+PG_MAP)
mov [eax+SLOT_BASE+APPDATA.io_map+4],\
(tss._io_map_1-OS_BASE+PG_MAP)
 
mov esi, fpu_data
mov ecx, 512/4
rep movsd
 
cmp ebx,[TASK_COUNT]
jle .noinc
inc dword [TASK_COUNT] ;update number of processes
.noinc:
shl ebx,8
lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET]
mov [SLOT_BASE+APPDATA.fd_ev+ebx],edx
mov [SLOT_BASE+APPDATA.bk_ev+ebx],edx
 
add edx, APP_OBJ_OFFSET-APP_EV_OFFSET
mov [SLOT_BASE+APPDATA.fd_obj+ebx],edx
mov [SLOT_BASE+APPDATA.bk_obj+ebx],edx
 
mov ecx, [def_cursor]
mov [SLOT_BASE+APPDATA.cursor+ebx],ecx
mov eax, [pl0_stack]
mov [SLOT_BASE+APPDATA.pl0_stack+ebx],eax
add eax, RING0_STACK_SIZE
mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax
 
push ebx
stdcall kernel_alloc, 0x1000
pop ebx
mov esi,[current_slot]
mov esi,[esi+APPDATA.cur_dir]
mov ecx,0x1000/4
mov edi,eax
mov [ebx+SLOT_BASE+APPDATA.cur_dir],eax
rep movsd
 
shr ebx,3
mov eax, new_app_base
mov dword [CURRENT_TASK+ebx+0x10],eax
 
.add_command_line:
mov edx,[params]
mov edx,[edx] ;app_cmdline
test edx,edx
jz @f ;application doesn't need parameters
 
mov eax, edx
add eax, 256
jc @f
 
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
 
mov byte [edx], 0 ;force empty string if no cmdline given
mov eax, [cmd_line]
test eax, eax
jz @f
stdcall strncpy, edx, eax, 256
@@:
mov edx,[params]
mov edx, [edx+4] ;app_path
test edx,edx
jz @F ;application don't need path of file
mov eax, edx
add eax, 1024
jc @f
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
stdcall strncpy, edx, [app_path], 1024
@@:
mov ebx,[slot]
mov eax,ebx
shl ebx,5
lea ecx,[draw_data+ebx] ;ecx - pointer to draw data
 
; set window state to 'normal' (non-minimized/maximized/rolled-up) state
mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL
mov [ebx+window_data+WDATA.fl_redraw], 1
add ebx,CURRENT_TASK ;ebx - pointer to information about process
mov [ebx+TASKDATA.wnd_number],al;set window number on screen = process slot
 
mov [ebx+TASKDATA.event_mask],dword 1+2+4 ;set default event flags (see 40 function)
 
inc dword [process_number]
mov eax,[process_number]
mov [ebx+4],eax ;set PID
 
;set draw data to full screen
 
mov [ecx+0],dword 0
mov [ecx+4],dword 0
mov eax,[Screen_Max_X]
mov [ecx+8],eax
mov eax,[Screen_Max_Y]
mov [ecx+12],eax
 
mov ebx, [pl0_stack]
mov esi,[params]
lea ecx, [ebx+REG_EIP]
xor eax, eax
 
mov [ebx+REG_RET], dword irq0.return
mov [ebx+REG_EDI], eax
mov [ebx+REG_ESI], eax
mov [ebx+REG_EBP], eax
mov [ebx+REG_ESP], ecx ;ebx+REG_EIP
mov [ebx+REG_EBX], eax
mov [ebx+REG_EDX], eax
mov [ebx+REG_ECX], eax
mov [ebx+REG_EAX], eax
 
mov eax, [esi+0x08] ;app_eip
mov [ebx+REG_EIP], eax ;app_entry
mov [ebx+REG_CS], dword app_code
mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF
 
mov eax, [esi+0x0C] ;app_esp
mov [ebx+REG_APP_ESP], eax ;app_stack
mov [ebx+REG_SS], dword app_data
 
lea ecx, [ebx+REG_RET]
mov ebx, [slot]
shl ebx, 5
mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx
 
xor ecx, ecx ; process state - running
; set if debuggee
test byte [flags], 1
jz .no_debug
inc ecx ; process state - suspended
mov eax,[CURRENT_TASK]
mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot],eax
.no_debug:
mov [CURRENT_TASK+ebx+TASKDATA.state], cl
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
DEBUGF 1,"%s",new_process_running
ret
endp
 
include "debug.inc"
/kernel/branches/core/v86.inc
0,0 → 1,956
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 979 $
 
; Virtual-8086 mode manager
; diamond, 2007, 2008
 
DEBUG_SHOW_IO = 0
 
struc V86_machine
{
; page directory
.pagedir dd ?
; translation table: V86 address -> flat linear address
.pages dd ?
; mutex to protect all data from writing by multiple threads at one time
.mutex dd ?
; i/o permission map
.iopm dd ?
.size = $
}
virtual at 0
V86_machine V86_machine
end virtual
 
; Create V86 machine
; in: nothing
; out: eax = handle (pointer to struc V86_machine)
; eax = NULL => failure
; destroys: ebx, ecx, edx (due to malloc)
v86_create:
; allocate V86_machine structure
mov eax, V86_machine.size
call malloc
test eax, eax
jz .fail
; initialize mutex
and dword [eax+V86_machine.mutex], 0
; allocate tables
mov ebx, eax
; We allocate 4 pages.
; First is main page directory for V86 mode.
; Second page:
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
; second half is for V86-to-linear translation.
; Third and fourth are for I/O permission map.
push 8000h ; blocks less than 8 pages are discontinuous
call kernel_alloc
test eax, eax
jz .fail2
mov [ebx+V86_machine.pagedir], eax
push edi eax
mov edi, eax
add eax, 1800h
mov [ebx+V86_machine.pages], eax
; initialize tables
mov ecx, 2000h/4
xor eax, eax
rep stosd
mov [ebx+V86_machine.iopm], edi
dec eax
mov ecx, 2000h/4
rep stosd
pop eax
; page directory: first entry is page table...
mov edi, eax
add eax, 1000h
push eax
call get_pg_addr
or al, PG_UW
stosd
; ...and also copy system page tables
; thx to Serge, system is located at high addresses
add edi, (OS_BASE shr 20) - 4
push esi
mov esi, (OS_BASE shr 20) + sys_pgdir
mov ecx, 0x80000000 shr 22
rep movsd
 
mov eax, [ebx+V86_machine.pagedir] ;root dir also is
call get_pg_addr ;used as page table
or al, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
 
pop esi
; now V86 specific: initialize known addresses in first Mb
pop eax
; first page - BIOS data (shared between all machines!)
; physical address = 0x2f0000
; linear address = BOOT_VAR = OS_BASE + 0x2f0000
mov dword [eax], (BOOT_VAR - OS_BASE) or 111b
mov dword [eax+800h], BOOT_VAR
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
; physical address = 0x9C000
; linear address = 0x8009C000
; (I have seen one computer with EBDA segment = 0x9D80,
; all other computers use less memory)
mov ecx, 4
mov edx, 0x9C000
push eax
lea edi, [eax+0x9C*4]
@@:
lea eax, [edx + OS_BASE]
mov [edi+800h], eax
lea eax, [edx + 111b]
stosd
add edx, 0x1000
loop @b
pop eax
pop edi
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
; physical address = 0xC0000
; linear address = 0x800C0000
mov ecx, 0xC0
@@:
mov edx, ecx
shl edx, 12
push edx
or edx, 111b
mov [eax+ecx*4], edx
pop edx
add edx, OS_BASE
mov [eax+ecx*4+0x800], edx
inc cl
jnz @b
mov eax, ebx
ret
.fail2:
mov eax, ebx
call free
.fail:
xor eax, eax
ret
 
; Destroy V86 machine
; in: eax = handle
; out: nothing
; destroys: eax, ebx, ecx, edx (due to free)
v86_destroy:
push eax
stdcall kernel_free, [eax+V86_machine.pagedir]
pop eax
jmp free
 
; Translate V86-address to linear address
; in: eax=V86 address
; esi=handle
; out: eax=linear address
; destroys: nothing
v86_get_lin_addr:
push ecx edx
mov ecx, eax
mov edx, [esi+V86_machine.pages]
shr ecx, 12
and eax, 0xFFF
add eax, [edx+ecx*4] ; atomic operation, no mutex needed
pop edx ecx
ret
 
; Sets linear address for V86-page
; in: eax=linear address (must be page-aligned)
; ecx=V86 page (NOT address!)
; esi=handle
; out: nothing
; destroys: nothing
v86_set_page:
push eax ebx
mov ebx, [esi+V86_machine.pagedir]
mov [ebx+ecx*4+0x1800], eax
call get_pg_addr
or al, 111b
mov [ebx+ecx*4+0x1000], eax
pop ebx eax
ret
 
; Allocate memory in V86 machine
; in: eax=size (in bytes)
; esi=handle
; out: eax=V86 address, para-aligned (0x10 multiple)
; destroys: nothing
; ­¥¤®¯¨á ­ !!!
;v86_alloc:
; push ebx ecx edx edi
; lea ebx, [esi+V86_machine.mutex]
; call wait_mutex
; add eax, 0x1F
; shr eax, 4
; mov ebx, 0x1000 ; start with address 0x1000 (second page)
; mov edi, [esi+V86_machine.tables]
;.l:
; mov ecx, ebx
; shr ecx, 12
; mov edx, [edi+0x1000+ecx*4] ; get linear address
; test edx, edx ; page allocated?
; jz .unalloc
; mov ecx, ebx
; and ecx, 0xFFF
; add edx, ecx
; cmp dword [edx], 0 ; free block?
; jnz .n
; cmp dword [edx+4],
; and [esi+V86_machine.mutex], 0
; pop edi edx ecx ebx
; ret
 
uglobal
sys_v86_machine dd ?
endg
 
; Called from kernel.asm at first stages of loading
; Initialize system V86 machine (used to simulate BIOS int 13h)
init_sys_v86:
call v86_create
mov [sys_v86_machine], eax
test eax, eax
jz .ret
mov byte [BOOT_VAR + 0x500], 0xCD
mov byte [BOOT_VAR + 0x501], 0x13
mov byte [BOOT_VAR + 0x502], 0xF4
mov byte [BOOT_VAR + 0x503], 0xCD
mov byte [BOOT_VAR + 0x504], 0x10
mov byte [BOOT_VAR + 0x505], 0xF4
mov esi, eax
mov ebx, [eax+V86_machine.pagedir]
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b
mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
if ~DEBUG_SHOW_IO
; allow access to all ports
mov ecx, [esi+V86_machine.iopm]
xor eax, eax
mov edi, ecx
mov ecx, 10000h/8/4
rep stosd
end if
.ret:
ret
 
struc v86_regs
{
; don't change the order, it is important
.edi dd ?
.esi dd ?
.ebp dd ?
dd ? ; ignored
.ebx dd ?
.edx dd ?
.ecx dd ?
.eax dd ?
.eip dd ?
.cs dd ?
.eflags dd ? ; VM flag must be set!
.esp dd ?
.ss dd ?
.es dd ?
.ds dd ?
.fs dd ?
.gs dd ?
.size = $
}
virtual at 0
v86_regs v86_regs
end virtual
 
; Run V86 machine
; in: ebx -> registers for V86 (two structures: in and out)
; esi = handle
; ecx = expected end address (CS:IP)
; edx = IRQ to hook or -1 if not required
; out: structure pointed to by ebx is filled with new values
; eax = 1 - exception has occured, cl contains code
; eax = 2 - access to disabled i/o port, ecx contains port address
; eax = 3 - IRQ is already hooked by another VM
; destroys: nothing
v86_start:
pushad
 
cli
 
mov ecx, [CURRENT_TASK]
shl ecx, 8
add ecx, SLOT_BASE
 
mov eax, [esi+V86_machine.iopm]
call get_pg_addr
inc eax
push dword [ecx+APPDATA.io_map]
push dword [ecx+APPDATA.io_map+4]
mov dword [ecx+APPDATA.io_map], eax
mov dword [page_tabs + (tss._io_map_0 shr 10)], eax
add eax, 0x1000
mov dword [ecx+APPDATA.io_map+4], eax
mov dword [page_tabs + (tss._io_map_1 shr 10)], eax
 
push [ecx+APPDATA.dir_table]
push [ecx+APPDATA.saved_esp0]
mov [ecx+APPDATA.saved_esp0], esp
mov [tss._esp0], esp
 
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov [ecx+APPDATA.dir_table], eax
mov cr3, eax
 
; mov [irq_tab+5*4], my05
 
; We do not enable interrupts, because V86 IRQ redirector assumes that
; machine is running
; They will be enabled by IRET.
; sti
 
mov eax, esi
sub esp, v86_regs.size
mov esi, ebx
mov edi, esp
mov ecx, v86_regs.size/4
rep movsd
 
cmp edx, -1
jz .noirqhook
uglobal
v86_irqhooks rd 16*2
endg
cmp [v86_irqhooks+edx*8], 0
jz @f
cmp [v86_irqhooks+edx*8], eax
jz @f
mov esi, v86_irqerr
call sys_msg_board_str
inc [v86_irqhooks+edx*8+4]
mov eax, 3
jmp v86_exc_c.exit
@@:
mov [v86_irqhooks+edx*8], eax
inc [v86_irqhooks+edx*8+4]
.noirqhook:
 
popad
iretd
 
; It is only possible to leave virtual-8086 mode by faulting to
; a protected-mode interrupt handler (typically the general-protection
; exception handler, which in turn calls the virtual 8086-mode monitor).
 
v86_debug_exc:
pushad
xor eax, eax
mov dr6, eax
mov bl, 1
jmp v86_exc_c
 
v86_page_fault:
add esp, 4
pushad
mov bl, 14
jmp v86_exc_c
 
v86_except_16:
pushad
mov bl, 16
jmp v86_exc_c
v86_except_19:
pushad
mov bl, 19
 
iglobal
v86_exc_str1 db 'V86 : unexpected exception ',0
v86_exc_str2 db ' at ',0
v86_exc_str3 db ':',0
v86_exc_str4 db 13,10,'V86 : faulted code:',0
v86_exc_str5 db ' (unavailable)',0
v86_newline db 13,10,0
v86_io_str1 db 'V86 : access to disabled i/o port ',0
v86_io_byte db ' (byte)',13,10,0
v86_io_word db ' (word)',13,10,0
v86_io_dword db ' (dword)',13,10,0
v86_irqerr db 'V86 : IRQ already hooked',13,10,0
endg
 
v86_exc_c:
mov ax, app_data
mov ds, ax
mov es, ax
; Did we all that we have wanted to do?
mov eax, [esp+v86_regs.size+10h+18h]
cmp word [esp+v86_regs.eip], ax
jnz @f
shr eax, 16
cmp word [esp+v86_regs.cs], ax
jz .done
@@:
; Various system events, which must be handled, result in #GP
cmp bl, 13
jnz .nogp
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
cmp word [esp+v86_regs.eip+2], 0
jnz .nogp
; Otherwise we can safely access byte at CS:IP
; (because it is #GP, not #PF handler)
; …᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î祭¨¥ ⮫쪮 ¨§-§  ç⥭¨ï ¡ ©â®¢ ª®¤ ,
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ­¥ #GP
movzx esi, word [esp+v86_regs.cs]
shl esi, 4
add esi, [esp+v86_regs.eip]
lodsb
cmp al, 0xCD ; int xx command = CD xx
jz .handle_int
cmp al, 0xCF
jz .handle_iret
cmp al, 0xF3
jz .handle_rep
cmp al, 0xEC
jz .handle_in
cmp al, 0xED
jz .handle_in_word
cmp al, 0xEE
jz .handle_out
cmp al, 0xEF
jz .handle_out_word
cmp al, 0xE4
jz .handle_in_imm
cmp al, 0xE6
jz .handle_out_imm
cmp al, 0x9C
jz .handle_pushf
cmp al, 0x9D
jz .handle_popf
cmp al, 0xFA
jz .handle_cli
cmp al, 0xFB
jz .handle_sti
cmp al, 0x66
jz .handle_66
jmp .nogp
.handle_int:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
xor eax, eax
lodsb
; call sys_msg_board_byte
; simulate INT command
; N.B. It is possible that some checks need to be corrected,
; but at least in case of normal execution the code works.
.simulate_int:
cmp word [esp+v86_regs.esp], 6
jae @f
mov bl, 12 ; #SS exception
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
push eax
movzx eax, word [esp+4+v86_regs.esp]
sub eax, 6
add edx, eax
mov eax, edx
mov esi, [esp+4+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
sub word [esp+4+v86_regs.esp], 6
mov eax, [esp+4+v86_regs.eip]
cmp byte [esp+1], 0
jnz @f
inc eax
inc eax
@@:
mov word [edx], ax
mov eax, [esp+4+v86_regs.cs]
mov word [edx+2], ax
mov eax, [esp+4+v86_regs.eflags]
mov word [edx+4], ax
pop eax
mov ah, 0
mov cx, [eax*4]
mov word [esp+v86_regs.eip], cx
mov cx, [eax*4+2]
mov word [esp+v86_regs.cs], cx
; note that interrupts will be disabled globally at IRET
and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
; continue V86 execution
popad
iretd
.handle_iret:
cmp word [esp+v86_regs.esp], 0x10000 - 6
jbe @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov ax, [edx]
mov word [esp+v86_regs.eip], ax
mov ax, [edx+2]
mov word [esp+v86_regs.cs], ax
mov ax, [edx+4]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 6
popad
iretd
.handle_pushf:
cmp word [esp+v86_regs.esp], 1
jnz @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
mov eax, [esp+v86_regs.esp]
sub eax, 2
movzx eax, ax
add edx, eax
mov eax, edx
mov esi, [esp+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+1]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
sub word [esp+v86_regs.esp], 2
mov eax, [esp+v86_regs.eflags]
mov [edx], ax
inc word [esp+v86_regs.eip]
popad
iretd
.handle_pushfd:
cmp word [esp+v86_regs.esp], 4
jae @f
mov bl, 12 ; #SS exception
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
sub eax, 4
add edx, eax
mov eax, edx
mov esi, [esp+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+3]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
sub word [esp+v86_regs.esp], 4
movzx eax, word [esp+v86_regs.eflags]
mov [edx], eax
add word [esp+v86_regs.eip], 2
popad
iretd
.handle_popf:
cmp word [esp+v86_regs.esp], 0xFFFF
jnz @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+1]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov ax, [edx]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_popfd:
cmp word [esp+v86_regs.esp], 0x10000 - 4
jbe @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+v86_regs.size+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
lea eax, [edx+3]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov eax, [edx]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 4
add word [esp+v86_regs.eip], 2
popad
iretd
.handle_cli:
and byte [esp+v86_regs.eflags+1], not 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_sti:
or byte [esp+v86_regs.eflags+1], 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_rep:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
cmp al, 6Eh
jz .handle_rep_outsb
jmp .nogp
.handle_rep_outsb:
.handle_in:
.handle_out:
.invalid_io_byte:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 1
jmp .invalid_io
.handle_in_imm:
.handle_out_imm:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
movzx ebx, al
mov ecx, 1
jmp .invalid_io
.handle_66:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
cmp al, 0x9C
jz .handle_pushfd
cmp al, 0x9D
jz .handle_popfd
cmp al, 0xEF
jz .handle_out_dword
cmp al, 0xED
jz .handle_in_dword
jmp .nogp
.handle_in_word:
.handle_out_word:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 2
jmp .invalid_io
.handle_in_dword:
.handle_out_dword:
.invalid_io_dword:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 4
.invalid_io:
mov esi, v86_io_str1
call sys_msg_board_str
mov eax, ebx
call sys_msg_board_dword
mov esi, v86_io_byte
cmp ecx, 1
jz @f
mov esi, v86_io_word
cmp ecx, 2
jz @f
mov esi, v86_io_dword
@@:
call sys_msg_board_str
if DEBUG_SHOW_IO
mov edx, ebx
mov ebx, 200
call delay_hs
mov esi, [esp+v86_regs.size+10h+4]
mov eax, [esi+V86_machine.iopm]
@@:
btr [eax], edx
inc edx
loop @b
popad
iretd
else
mov eax, 2
jmp .exit
end if
.nogp:
 
mov esi, v86_exc_str1
call sys_msg_board_str
mov al, bl
call sys_msg_board_byte
mov esi, v86_exc_str2
call sys_msg_board_str
mov ax, [esp+32+4]
call sys_msg_board_word
mov esi, v86_exc_str3
call sys_msg_board_str
mov ax, [esp+32]
call sys_msg_board_word
mov esi, v86_exc_str4
call sys_msg_board_str
mov ecx, 8
movzx edx, word [esp+32+4]
shl edx, 4
add edx, [esp+32]
@@:
mov esi, [esp+v86_regs.size+10h+4]
mov eax, edx
call v86_get_lin_addr
cmp eax, 0x1000
jb .nopage
mov esi, v86_exc_str3-2
call sys_msg_board_str
mov al, [edx]
call sys_msg_board_byte
inc edx
loop @b
jmp @f
.nopage:
mov esi, v86_exc_str5
call sys_msg_board_str
@@:
mov esi, v86_newline
call sys_msg_board_str
mov eax, 1
jmp .exit
 
.done:
xor eax, eax
 
.exit:
mov [esp+v86_regs.size+10h+1Ch], eax
mov [esp+v86_regs.size+10h+18h], ebx
 
mov edx, [esp+v86_regs.size+10h+14h]
cmp edx, -1
jz @f
dec [v86_irqhooks+edx*8+4]
jnz @f
and [v86_irqhooks+edx*8], 0
@@:
 
mov esi, esp
mov edi, [esi+v86_regs.size+10h+10h]
add edi, v86_regs.size
mov ecx, v86_regs.size/4
rep movsd
mov esp, esi
 
cli
mov ecx, [CURRENT_TASK]
shl ecx, 8
pop eax
mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
mov [tss._esp0], eax
pop eax
mov [SLOT_BASE+ecx+APPDATA.dir_table], eax
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx
mov cr3, eax
; mov [irq_tab+5*4], 0
sti
 
popad
ret
 
;my05:
; mov dx, 30C2h
; mov cx, 4
;.0:
; in al, dx
; cmp al, 0FFh
; jz @f
; test al, 4
; jnz .1
;@@:
; add dx, 8
; in al, dx
; cmp al, 0FFh
; jz @f
; test al, 4
; jnz .1
;@@:
; loop .0
; ret
;.1:
; or al, 84h
; out dx, al
;.2:
; mov dx, 30F7h
; in al, dx
; mov byte [BOOT_VAR + 48Eh], 0FFh
; ret
 
v86_irq:
; push irq/pushad/jmp v86_irq
; eax = irq
lea esi, [esp+1Ch]
lea edi, [esi+4]
mov ecx, 8
std
rep movsd
cld
mov edi, eax
pop eax
v86_irq2:
mov esi, [v86_irqhooks+edi*8] ; get VM handle
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov ecx, [CURRENT_TASK]
shl ecx, 8
cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax
jnz .notcurrent
lea eax, [edi+8]
cmp al, 10h
mov ah, 1
jb @f
add al, 60h
@@:
jmp v86_exc_c.simulate_int
.notcurrent:
mov ebx, SLOT_BASE + 0x100
mov ecx, [TASK_COUNT]
.scan:
cmp [ebx+APPDATA.dir_table], eax
jnz .cont
push ecx
mov ecx, [ebx+APPDATA.saved_esp0]
cmp word [ecx-v86_regs.size+v86_regs.esp], 6
jb .cont2
movzx edx, word [ecx-v86_regs.size+v86_regs.ss]
shl edx, 4
push eax
movzx eax, word [ecx-v86_regs.size+v86_regs.esp]
sub eax, 6
add edx, eax
mov eax, edx
call v86_get_lin_addr
cmp eax, 0x1000
jb .cont3
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jb .cont3
pop eax
pop ecx
jmp .found
.cont3:
pop eax
.cont2:
pop ecx
.cont:
loop .scan
mov al, 20h
out 20h, al
cmp edi, 8
jb @f
out 0A0h, al
@@:
popad
iretd
.found:
mov cr3, eax
sub word [esi-v86_regs.size+v86_regs.esp], 6
mov ecx, [esi-v86_regs.size+v86_regs.eip]
mov word [edx], cx
mov ecx, [esi-v86_regs.size+v86_regs.cs]
mov word [edx+2], cx
mov ecx, [esi-v86_regs.size+v86_regs.eflags]
mov word [edx+4], cx
lea eax, [edi+8]
cmp al, 10h
jb @f
add al, 60h
@@:
mov cx, [eax*4]
mov word [esi-v86_regs.size+v86_regs.eip], cx
mov cx, [eax*4+2]
mov word [esi-v86_regs.size+v86_regs.cs], cx
and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3
push ebx
call update_counters
pop ebx
sub ebx, SLOT_BASE
shr ebx, 8
mov esi, [CURRENT_TASK]
call do_change_task
popad
iretd