/kernel/branches/Kolibri-acpi/core/memory.inc |
---|
0,0 → 1,1523 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
align 4 |
proc alloc_page |
pushfd |
cli |
push ebx |
;//- |
cmp [pg_data.pages_free], 1 |
jle .out_of_memory |
;//- |
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: |
;//- |
dec [pg_data.pages_free] |
jz .out_of_memory |
;//- |
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 |
;//- |
.out_of_memory: |
mov [pg_data.pages_free], 1 |
xor eax, eax |
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 |
;//- |
mov ebx, [pg_data.pages_free] |
sub ebx, 9 |
js .out_of_memory |
shr ebx, 3 |
cmp eax, ebx |
jg .out_of_memory |
;//- |
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 |
.out_of_memory: |
.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 alloc_pages, (0x280000 / 4096) |
push eax |
call alloc_page |
stdcall map_page_table, LFB_BASE, eax |
pop eax |
or eax, PG_UW |
mov ebx, LFB_BASE |
mov ecx, 0x280000 / 4096 |
call commit_pages |
mov [LFBAddress], dword LFB_BASE |
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, 0x00C00000 |
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_pop |
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 |
push edi |
mov esi, [pg_data.pages_free] |
sub esi, 1 |
shr edi, 12 |
cmp esi, edi |
jle .out_of_memory |
;//- |
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_pop: |
.out_of_memory: |
;//- |
pop edi |
pop esi |
.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 |
; Now it is called from core/sys32::exc_c (see stack frame there) |
proc page_fault_handler |
.err_addr equ ebp-4 |
push ebx ;save exception number (#PF) |
mov ebp, esp |
mov ebx, cr2 |
push ebx ;that is locals: .err_addr = cr2 |
inc [pg_data.pages_faults] |
mov eax, [pf_err_code] |
cmp ebx, OS_BASE ;ebx == .err_addr |
jb .user_space ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ; |
cmp ebx, page_tabs |
jb .kernel_space ;ñòðàíèöà â ïàìÿòè ÿäðà |
cmp ebx, kernel_tabs |
jb .alloc;.app_tabs ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ; |
;ïðîñòî ñîçäàäèì îäíó |
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå |
cmp ebx, LFB_BASE |
jb .core_tabs ;òàáëèöû ñòðàíèö ÿäðà |
;Îøèáêà |
.lfb: |
;îáëàñòü LFB |
;Îøèáêà |
jmp .fail |
end if |
.core_tabs: |
.fail: ;simply return to caller |
mov esp, ebp |
pop ebx ;restore exception number (#PF) |
ret |
; xchg bx, bx |
; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
; restore_ring3_context |
; iretd |
.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,[.err_addr],eax,PG_UW |
mov edi, [.err_addr] |
and edi, 0xFFFFF000 |
mov ecx, 1024 |
xor eax, eax |
;cld ;caller is duty for this |
rep stosd |
.exit: ;iret with repeat fault instruction |
add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller |
restore_ring3_context |
iretd |
.err_access: |
; access denied? this may be a result of copy-on-write protection for DLL |
; check list of HDLLs |
and ebx, not 0xFFF |
mov eax, [CURRENT_TASK] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
test eax, eax |
jz .fail |
mov esi, [eax+HDLL.fd] |
.scan_hdll: |
cmp esi, eax |
jz .fail |
mov edx, ebx |
sub edx, [esi+HDLL.base] |
cmp edx, [esi+HDLL.size] |
jb .fault_in_hdll |
.scan_hdll.next: |
mov esi, [esi+HDLL.fd] |
jmp .scan_hdll |
.fault_in_hdll: |
; allocate new page, map it as rw and copy data |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page,ebx,eax,PG_UW |
mov edi, ebx |
mov ecx, 1024 |
sub ebx, [esi+HDLL.base] |
mov esi, [esi+HDLL.parent] |
mov esi, [esi+DLLDESCR.data] |
add esi, ebx |
rep movsd |
jmp .exit |
.kernel_space: |
test eax, PG_MAP |
jz .fail ;ñòðàíèöà íå ïðèñóòñòâóåò |
test eax,12 ;U/S (+below) |
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,[.err_addr],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 ;caller is duty for this |
rep movsd |
jmp .exit |
endp |
; returns number of mapped bytes |
proc map_mem stdcall, lin_addr:dword,slot:dword,\ |
ofs:dword,buf_size:dword,req_access:dword |
push 0 ; initialize number of mapped bytes |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
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: |
stdcall safe_map_page,[slot],[req_access],[ofs] |
jnc .exit |
add dword [ebp-4], 4096 |
add [ofs], 4096 |
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: |
pop eax |
ret |
endp |
proc map_memEx stdcall, lin_addr:dword,slot:dword,\ |
ofs:dword,buf_size:dword,req_access:dword |
push 0 ; initialize number of mapped bytes |
cmp [buf_size], 0 |
jz .exit |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dir_table] |
and eax, 0xFFFFF000 |
stdcall map_page,[proc_mem_pdir],eax,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,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: |
stdcall safe_map_page,[slot],[req_access],[ofs] |
jnc .exit |
add dword [ebp-4], 0x1000 |
add edi, 0x1000 |
add [ofs], 0x1000 |
inc edx |
dec ecx |
jnz .map |
.exit: |
pop eax |
ret |
endp |
; in: esi+edx*4 = pointer to page table entry |
; in: [slot], [req_access], [ofs] on the stack |
; in: edi = linear address to map |
; out: CF cleared <=> failed |
; destroys: only eax |
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword |
mov eax, [esi+edx*4] |
test al, PG_MAP |
jz .not_present |
test al, PG_WRITE |
jz .resolve_readonly |
; normal case: writable page, just map with requested access |
.map: |
stdcall map_page, edi, eax, [req_access] |
stc |
.fail: |
ret |
.not_present: |
; check for alloc-on-demand page |
test al, 2 |
jz .fail |
; allocate new page, save it to source page table |
push ecx |
call alloc_page |
pop ecx |
test eax, eax |
jz .fail |
or al, PG_UW |
mov [esi+edx*4], eax |
jmp .map |
.resolve_readonly: |
; readonly page, probably copy-on-write |
; check: readonly request of readonly page is ok |
test [req_access], PG_WRITE |
jz .map |
; find control structure for this page |
pushf |
cli |
cld |
push ebx ecx |
mov eax, [slot] |
shl eax, 8 |
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
test eax, eax |
jz .no_hdll |
mov ecx, [eax+HDLL.fd] |
.scan_hdll: |
cmp ecx, eax |
jz .no_hdll |
mov ebx, [ofs] |
and ebx, not 0xFFF |
sub ebx, [ecx+HDLL.base] |
cmp ebx, [ecx+HDLL.size] |
jb .hdll_found |
mov ecx, [ecx+HDLL.fd] |
jmp .scan_hdll |
.no_hdll: |
pop ecx ebx |
popf |
clc |
ret |
.hdll_found: |
; allocate page, save it in page table, map it, copy contents from base |
mov eax, [ecx+HDLL.parent] |
add ebx, [eax+DLLDESCR.data] |
call alloc_page |
test eax, eax |
jz .no_hdll |
or al, PG_UW |
mov [esi+edx*4], eax |
stdcall map_page, edi, eax, [req_access] |
push esi edi |
mov esi, ebx |
mov ecx, 4096/4 |
rep movsd |
pop edi esi |
pop ecx ebx |
popf |
stc |
ret |
endp |
sys_IPC: |
;input: |
; ebx=1 - set ipc buffer area |
; ecx=address of buffer |
; edx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
dec ebx |
jnz @f |
mov eax,[current_slot] |
pushf |
cli |
mov [eax+APPDATA.ipc_start],ecx ;set fields in extended information area |
mov [eax+APPDATA.ipc_size],edx |
add edx, ecx |
add edx, 4095 |
and edx, not 4095 |
.touch: mov eax, [ecx] |
add ecx, 0x1000 |
cmp ecx, edx |
jb .touch |
popf |
mov [esp+32], ebx ;ebx=0 |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;2 |
@@: |
dec ebx |
jnz @f |
stdcall sys_ipc_send, ecx, edx, esi |
mov [esp+32], eax |
ret |
@@: |
or eax,-1 |
mov [esp+32], 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 esi edi |
add esi,0x1000 |
stdcall alloc_kernel_space,esi |
mov ecx, eax |
pop edi esi |
@@: |
mov [used_buf], ecx |
stdcall map_mem, ecx, [dst_slot],\ |
edi, esi, PG_SW |
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 ecx, new_app_base |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [pg_data.pages_count] |
mov [ecx], eax |
shl eax, 12 |
mov [esp+32], eax |
mov eax, [pg_data.pages_free] |
mov [ecx+4], eax |
mov eax, [pg_data.pages_faults] |
mov [ecx+8], eax |
mov eax, [heap_size] |
mov [ecx+12], eax |
mov eax, [heap_free] |
mov [ecx+16], eax |
mov eax, [heap_blocks] |
mov [ecx+20], eax |
mov eax, [free_blocks] |
mov [ecx+24], eax |
ret |
.fail: |
or dword [esp+32], -1 |
ret |
align 4 |
f68: |
cmp ebx,4 |
jbe sys_sheduler |
cmp ebx, 11 |
jb .fail |
cmp ebx, 25 |
ja .fail |
jmp dword [f68call+ebx*4-11*4] |
.11: |
call init_heap |
mov [esp+32], eax |
ret |
.12: |
stdcall user_alloc, ecx |
mov [esp+32], eax |
ret |
.13: |
stdcall user_free, ecx |
mov [esp+32], eax |
ret |
.14: |
cmp ecx, OS_BASE |
jae .fail |
mov edi,ecx |
call get_event_ex |
mov [esp+32], eax |
ret |
.16: |
test ecx, ecx |
jz .fail |
cmp ecx, OS_BASE |
jae .fail |
stdcall get_service, ecx |
mov [esp+32], eax |
ret |
.17: |
call srv_handlerEx ;ecx |
mov [esp+32], eax |
ret |
.19: |
cmp ecx, OS_BASE |
jae .fail |
stdcall load_library, ecx |
mov [esp+32], eax |
ret |
.20: |
mov eax, edx |
mov ebx, ecx |
call user_realloc ;in: eax = pointer, ebx = new size |
mov [esp+32], eax |
ret |
.21: |
cmp ecx, OS_BASE |
jae .fail |
cmp ebx, OS_BASE |
jae .fail |
mov edi, edx |
stdcall load_PE, ecx |
mov esi, eax |
test eax, eax |
jz @F |
push edi |
push DRV_ENTRY |
call eax |
add esp, 8 |
test eax, eax |
jz @F |
mov [eax+SRV.entry], esi |
@@: |
mov [esp+32], eax |
ret |
.22: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_open, ecx, edx, esi |
mov [esp+24], edx |
mov [esp+32], eax |
ret |
.23: |
cmp ecx, OS_BASE |
jae .fail |
stdcall shmem_close, ecx |
mov [esp+32], eax |
ret |
.24: |
mov eax, [current_slot] |
xchg ecx, [eax+APPDATA.exc_handler] |
xchg edx, [eax+APPDATA.except_mask] |
mov [esp+32], ecx ; reg_eax+8 |
mov [esp+20], edx ; reg_ebx+8 |
ret |
.25: |
cmp ecx,32 |
jae .fail |
mov eax, [current_slot] |
btr [eax+APPDATA.except_mask],ecx |
setc byte[esp+32] |
jecxz @f |
bts [eax+APPDATA.except_mask],ecx |
@@: |
ret |
.fail: |
xor eax, eax |
mov [esp+32], eax |
ret |
align 4 |
f68call: ; keep this table closer to main code |
dd f68.11 ; init_heap |
dd f68.12 ; user_alloc |
dd f68.13 ; user_free |
dd f68.14 ; get_event_ex |
dd f68.fail ; moved to f68.24 |
dd f68.16 ; get_service |
dd f68.17 ; call_service |
dd f68.fail ; moved to f68.25 |
dd f68.19 ; load_dll |
dd f68.20 ; user_realloc |
dd f68.21 ; load_driver |
dd f68.22 ; shmem_open |
dd f68.23 ; shmem_close |
dd f68.24 |
dd f68.25 |
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 ; |
; has BIOS already initialized MTRRs? |
test ah, 8 |
jnz .skip_init |
; rarely needed, so mainly placeholder |
; main memory - cached |
push eax |
mov eax, [MEM_AMOUNT] |
; round eax up to next power of 2 |
dec eax |
bsr ecx, eax |
mov ebx, 2 |
shl ebx, cl |
dec ebx |
; base of memory range = 0, type of memory range = MEM_WB |
xor edx, edx |
mov eax, MEM_WB |
mov ecx, 0x200 |
wrmsr |
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1 |
mov eax, 0xFFFFFFFF |
mov edx, 0x0000000F |
sub eax, ebx |
sbb edx, 0 |
or eax, 0x800 |
inc ecx |
wrmsr |
; clear unused MTRRs |
xor eax, eax |
xor edx, edx |
@@: |
wrmsr |
inc ecx |
cmp ecx, 0x210 |
jb @b |
; enable MTRRs |
pop eax |
or ah, 8 |
and al, 0xF0 ; default memtype = UC |
mov ecx, 0x2FF |
wrmsr |
.skip_init: |
stdcall set_mtrr, [LFBAddress],[LFBSize],MEM_WC |
wbinvd ;again invalidate |
mov eax, cr0 |
and eax, not 0x60000000 |
mov cr0, eax ; enable caching |
.exit: |
ret |
endp |
align 4 |
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword |
; find unused register |
mov ecx, 0x201 |
@@: |
rdmsr |
dec ecx |
test ah, 8 |
jz .found |
rdmsr |
mov al, 0 ; clear memory type field |
cmp eax, [base] |
jz .ret |
add ecx, 3 |
cmp ecx, 0x210 |
jb @b |
; no free registers, ignore the call |
.ret: |
ret |
.found: |
; found, write values |
xor edx, edx |
mov eax, [base] |
or eax, [mem_type] |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/heap.inc |
---|
0,0 → 1,1540 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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 |
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, [pg_data.kernel_pages] |
shl ecx, 12 |
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], 4094 |
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 |
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 edi |
pop ebx |
ret |
.err: |
xor eax, eax |
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: |
xor eax, eax |
mov [heap_mutex], eax |
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_alloc_at stdcall, address:dword, alloc_size:dword |
push ebx |
push esi |
push edi |
mov ebx, [current_slot] |
mov edx, [address] |
and edx, not 0xFFF |
mov [address], edx |
sub edx, 0x1000 |
jb .error |
mov esi, [ebx+APPDATA.heap_base] |
mov edi, [ebx+APPDATA.heap_top] |
cmp edx, esi |
jb .error |
.scan: |
cmp esi, edi |
jae .error |
mov ebx, esi |
shr ebx, 12 |
mov eax, [page_tabs+ebx*4] |
mov ecx, eax |
and ecx, 0xFFFFF000 |
add ecx, esi |
cmp edx, ecx |
jb .found |
mov esi, ecx |
jmp .scan |
.error: |
xor eax, eax |
pop edi |
pop esi |
pop ebx |
ret |
.found: |
test al, FREE_BLOCK |
jz .error |
mov eax, ecx |
sub eax, edx |
sub eax, 0x1000 |
cmp eax, [alloc_size] |
jb .error |
; Here we have 1 big free block which includes requested area. |
; In general, 3 other blocks must be created instead: |
; free at [esi, edx); |
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000)); |
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx) |
; First or third block (or both) may be absent. |
mov eax, edx |
sub eax, esi |
jz .nofirst |
or al, FREE_BLOCK |
mov [page_tabs+ebx*4], eax |
.nofirst: |
mov eax, [alloc_size] |
add eax, 0x1FFF |
and eax, not 0xFFF |
mov ebx, edx |
add edx, eax |
shr ebx, 12 |
or al, USED_BLOCK |
mov [page_tabs+ebx*4], eax |
shr eax, 12 |
dec eax |
jz .second_nofill |
inc ebx |
.fill: |
mov dword [page_tabs+ebx*4], 2 |
inc ebx |
dec eax |
jnz .fill |
.second_nofill: |
sub ecx, edx |
jz .nothird |
or cl, FREE_BLOCK |
mov [page_tabs+ebx*4], ecx |
.nothird: |
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 |
mov eax, [address] |
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 ebx, [name] |
test ebx, ebx |
mov edx, E_PARAM |
jz .fail |
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, ebx, 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 .fail |
cmp eax, SHM_CREATE |
mov edx, E_PARAM |
je .create_shm |
cmp eax, SHM_OPEN_ALWAYS |
jne .fail |
.create_shm: |
mov ecx, [size] |
test ecx, ecx |
jz .fail |
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 .fail |
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 .fail |
.create_map: |
mov eax, [access] |
and eax, SHM_ACCESS_MASK |
cmp eax, [esi+SMEM.access] |
mov [access], eax |
mov edx, E_ACCESS |
ja .fail |
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 .fail |
inc [esi+SMEM.refcount] |
mov [edi+SMAP.magic], 'SMAP' |
mov [edi+SMAP.destroy], destroy_smap |
mov [edi+SMAP.parent], esi |
mov [edi+SMAP.base], 0 |
stdcall user_alloc, [esi+SMEM.size] |
test eax, eax |
mov [mapped], eax |
mov edx, E_NOMEM |
jz .cleanup2 |
mov [edi+SMAP.base], eax |
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 .fail |
.exit: |
mov edx, [size] |
.fail: |
mov eax, [mapped] |
popfd |
pop edi |
pop esi |
pop ebx |
ret |
.cleanup: |
mov [size], edx |
mov eax, esi |
call free |
jmp .exit |
.cleanup2: |
mov [size], edx |
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 edi, [edi+SMEM.name] |
stdcall strncmp, [name], edi, 32 |
test eax, eax |
jne .next |
stdcall user_free, [esi+SMAP.base] |
mov eax,esi |
call [esi+APPOBJ.destroy] |
@@: |
popfd |
pop edi |
pop esi |
.fail: |
ret |
endp |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/peload.inc |
---|
0,0 → 1,329 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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 |
alloc_page, 'AllocPage', \ ; gcc ABI |
alloc_pages, 'AllocPages', \ ; stdcall |
commit_pages, 'CommitPages', \ ; eax, ebx, ecx |
\ |
create_event, 'CreateEvent', \ ; ecx, esi |
raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi |
wait_event, 'WaitEvent', \ ; eax, ebx |
get_event_ex, 'GetEvent', \ ; edi |
\ |
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 |
malloc, 'Kmalloc', \ |
free, 'Kfree', \ |
map_io_mem, 'MapIoMem', \ ; stdcall |
get_pg_addr, 'GetPgAddr', \ ; eax |
\ |
mutex_init, 'MutexInit', \ ; gcc fastcall |
mutex_lock, 'MutexLock', \ ; gcc fastcall |
mutex_unlock, 'MutexUnlock', \ ; gcc fastcall |
\ |
get_display, 'GetDisplay', \ |
set_screen, 'SetScreen', \ |
pci_api_drv, '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 |
\ |
get_service, 'GetService', \ ; |
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', \ |
get_timer_ticks, 'GetTimerTicks', \ |
delay_hs, 'Delay', \ ; ebx |
set_mouse_data, 'SetMouseData' |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/exports.inc |
---|
0,0 → 1,161 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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 |
szMutexInit db 'MutexInit',0 |
szMutexLock db 'MutexLock',0 |
szMutexUnlock db 'MutexUnlock',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 |
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 |
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 szMutexInit , mutex_init ;gcc fastcall |
dd szMutexLock , mutex_lock ;gcc fastcall |
dd szMutexUnlock , mutex_unlock ;gcc fastcall |
dd szPciApi , pci_api_drv |
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 ;see EVENT.inc for specification |
dd szRaiseEvent , raise_event ;see EVENT.inc for specification |
dd szWaitEvent , wait_event ;see EVENT.inc for specification |
dd szDestroyEvent , destroy_event ;see EVENT.inc for specification |
dd szClearEvent , clear_event ;see EVENT.inc for specification |
dd szLoadCursor , load_cursor ;stdcall |
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 ;see EVENT.inc for specification |
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 |
exp_lfb: |
dd szLFBAddress , 0 |
dd 0 ;terminator, must be zero |
endg |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/syscall.inc |
---|
0,0 → 1,199 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; 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 |
movzx edi, byte[esp+28 + 4] |
sub edi,53 |
call dword [servetable+edi*4] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 16 |
i40: |
pushad |
cld |
movzx eax, al |
call dword [servetable2 + eax * 4] |
popad |
iretd |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 socket ; 53-Socket interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 |
dd file_system ; 58-Common file system interface |
dd 0 |
dd 0 |
dd 0 |
dd 0 ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; NEW SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable2: |
dd syscall_draw_window ; 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 syscall_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 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 sys_wait_event_timeout ; 23-TimeOutWaitForEvent |
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist |
dd undefined_syscall ; 25-reserved |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd undefined_syscall ; 27-reserved |
dd undefined_syscall ; 28-reserved |
dd sys_date ; 29-GetDate |
dd sys_current_directory ; 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 readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd syscall_getirqowner ; 41-GetIrqOwner |
dd get_irq_data ; 42-ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd sys_programirq ; 44-ProgramIrqs |
dd reserve_free_irq ; 45-ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd syscall_display_settings ; 48-SetRedrawType and SetButtonType |
dd sys_apm ; 49-Advanced Power Management (APM) |
dd syscall_set_window_shape ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd cross_order ; 53-Socket interface |
dd undefined_syscall ; 54-reserved |
dd sound_interface ; 55-Sound interface |
dd undefined_syscall ; 56-reserved |
dd sys_pcibios ; 57-PCI BIOS32 |
dd cross_order ; 58-Common file system interface |
dd undefined_syscall ; 59-reserved |
dd sys_IPC ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd pci_api ;cross_order ; 62-PCI functions |
dd cross_order ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd sys_putimage_palette ; 65-PutImagePalette |
dd sys_process_def ; 66-Process definitions - keyboard |
dd syscall_move_window ; 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_window_settings ; 71-Window settings |
dd sys_sendwindowmsg ; 72-Send window message |
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/dll.inc |
---|
0,0 → 1,1689 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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.sizeof |
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 |
; ecx= io_control |
; |
; retval |
; eax= error code |
align 4 |
srv_handlerEx: |
cmp ecx, OS_BASE |
jae .fail |
mov eax, [ecx+handle] |
cmp [eax+SRV.magic], ' SRV' |
jne .fail |
cmp [eax+SRV.size], SRV.sizeof |
jne .fail |
stdcall [eax+SRV.srv_proc], ecx |
ret |
.fail: |
or eax, -1 |
ret |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc get_service stdcall, sz_name:dword |
mov eax, [sz_name] |
test eax, eax |
jnz @F |
ret |
@@: |
mov edx, [srv.fd] |
@@: |
cmp edx, srv.fd-SRV_FD_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.sizeof |
call malloc |
test eax, eax |
jz .fail |
push esi |
push edi |
mov edi, eax |
mov esi, [name] |
movsd |
movsd |
movsd |
movsd |
pop edi |
pop esi |
mov [eax+SRV.magic], ' SRV' |
mov [eax+SRV.size], SRV.sizeof |
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 eax, [pSym] |
mov eax, [eax+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 |
lea ebx, [cmd] |
call file_system_lfn |
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 |
test eax, eax |
jz .fail |
stdcall read_file, [file_name], eax, dword 0, [file_size] |
cmp ebx, [file_size] |
jne .cleanup |
mov eax, [file] |
cmp dword [eax], 0x4B43504B |
jne .exit |
mov ebx, [eax+4] |
mov [file_size], ebx |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .cleanup |
mov [file2], eax |
pushfd |
cli |
stdcall unpack, [file], eax |
popfd |
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 uses ebx esi, sec:dword, symbols:dword,\ |
sym_count:dword, strings:dword, imports:dword |
locals |
retval dd ? |
endl |
mov edi, [symbols] |
mov [retval], 1 |
.fix: |
movzx ebx, [edi+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 uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
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, [delta] |
add [eax], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
ret |
endp |
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \ |
delta:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
lea esi, [eax+20] |
mov edx, [delta] |
.fix_sec: |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.reloc_loop: |
cmp [edi+CRELOC.Type], 6 |
jne .next_reloc |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
add [eax+edx], edx |
.next_reloc: |
add edi, 10 |
dec ecx |
jnz .reloc_loop |
.next: |
add esi, 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] |
stdcall fix_coff_relocs, ebx, [sym], 0 |
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 |
; in: edx -> COFF_SECTION struct |
; out: eax = alignment as mask for bits to drop |
coff_get_align: |
; Rules: |
; - if alignment is not given, use default = 4K; |
; - if alignment is given and is no more than 4K, use it; |
; - if alignment is more than 4K, revert to 4K. |
push ecx |
mov cl, byte [edx+CFS.Characteristics+2] |
mov eax, 1 |
shr cl, 4 |
dec cl |
js .default |
cmp cl, 12 |
jbe @f |
.default: |
mov cl, 12 |
@@: |
shl eax, cl |
pop ecx |
dec eax |
ret |
align 4 |
proc load_library stdcall, file_name:dword |
locals |
fullname rb 260 |
fileinfo rb 40 |
coff dd ? |
img_base dd ? |
endl |
cli |
; resolve file name |
mov ebx, [file_name] |
lea edi, [fullname+1] |
mov byte [edi-1], '/' |
stdcall get_full_file_name, edi, 259 |
test al, al |
jz .fail |
; scan for required DLL in list of already loaded for this process, |
; ignore timestamp |
mov esi, [CURRENT_TASK] |
shl esi, 8 |
lea edi, [fullname] |
mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] |
test ebx, ebx |
jz .not_in_process |
mov esi, [ebx+HDLL.fd] |
.scan_in_process: |
cmp esi, ebx |
jz .not_in_process |
mov eax, [esi+HDLL.parent] |
add eax, DLLDESCR.name |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .next_in_process |
; simple variant: load DLL which is already loaded in this process |
; just increment reference counters and return address of exports table |
inc [esi+HDLL.refcount] |
mov ecx, [esi+HDLL.parent] |
inc [ecx+DLLDESCR.refcount] |
mov eax, [ecx+DLLDESCR.exports] |
sub eax, [ecx+DLLDESCR.defaultbase] |
add eax, [esi+HDLL.base] |
ret |
.next_in_process: |
mov esi, [esi+HDLL.fd] |
jmp .scan_in_process |
.not_in_process: |
; scan in full list, compare timestamp |
lea eax, [fileinfo] |
stdcall get_fileinfo, edi, eax |
test eax, eax |
jnz .fail |
mov esi, [dll_list.fd] |
.scan_for_dlls: |
cmp esi, dll_list |
jz .load_new |
lea eax, [esi+DLLDESCR.name] |
stdcall strncmp, eax, edi, -1 |
test eax, eax |
jnz .continue_scan |
.test_prev_dll: |
mov eax, dword [fileinfo+24] ; last modified time |
mov edx, dword [fileinfo+28] ; last modified date |
cmp dword [esi+DLLDESCR.timestamp], eax |
jnz .continue_scan |
cmp dword [esi+DLLDESCR.timestamp+4], edx |
jz .dll_already_loaded |
.continue_scan: |
mov esi, [esi+DLLDESCR.fd] |
jmp .scan_for_dlls |
; new DLL |
.load_new: |
; load file |
stdcall load_file, edi |
test eax, eax |
jz .fail |
mov [coff], eax |
mov dword [fileinfo+32], ebx |
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name |
mov esi, edi |
mov ecx, -1 |
xor eax, eax |
repnz scasb |
not ecx |
lea eax, [ecx+DLLDESCR.sizeof] |
push ecx |
call malloc |
pop ecx |
test eax, eax |
jz .fail_and_free_coff |
; save timestamp |
lea edi, [eax+DLLDESCR.name] |
rep movsb |
mov esi, eax |
mov eax, dword [fileinfo+24] |
mov dword [esi+DLLDESCR.timestamp], eax |
mov eax, dword [fileinfo+28] |
mov dword [esi+DLLDESCR.timestamp+4], eax |
; initialize DLLDESCR struct |
and dword [esi+DLLDESCR.refcount], 0 ; no HDLLs yet; later it will be incremented |
mov [esi+DLLDESCR.fd], dll_list |
mov eax, [dll_list.bk] |
mov [dll_list.bk], esi |
mov [esi+DLLDESCR.bk], eax |
mov [eax+DLLDESCR.fd], esi |
; calculate size of loaded DLL |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
xor ebx, ebx |
add edx, 20 |
@@: |
call coff_get_align |
add ebx, eax |
not eax |
and ebx, eax |
add ebx, [edx+CFS.SizeOfRawData] |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
; it must be nonzero and not too big |
mov [esi+DLLDESCR.size], ebx |
test ebx, ebx |
jz .fail_and_free_dll |
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR |
ja .fail_and_free_dll |
; allocate memory for kernel-side image |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .fail_and_free_dll |
mov [esi+DLLDESCR.data], eax |
; calculate preferred base address |
add ebx, 0x1FFF |
and ebx, not 0xFFF |
mov ecx, [dll_cur_addr] |
lea edx, [ecx+ebx] |
cmp edx, MAX_DEFAULT_DLL_ADDR |
jb @f |
mov ecx, MIN_DEFAULT_DLL_ADDR |
lea edx, [ecx+ebx] |
@@: |
mov [esi+DLLDESCR.defaultbase], ecx |
mov [dll_cur_addr], edx |
; copy sections and set correct values for VirtualAddress'es in headers |
push esi |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, eax |
add edx, 20 |
cld |
@@: |
call coff_get_align |
add ecx, eax |
add edi, eax |
not eax |
and ecx, eax |
and edi, eax |
mov [edx+CFS.VirtualAddress], ecx |
add ecx, [edx+CFS.SizeOfRawData] |
mov esi, [edx+CFS.PtrRawData] |
push ecx |
mov ecx, [edx+CFS.SizeOfRawData] |
test esi, esi |
jnz .copy |
xor eax, eax |
rep stosb |
jmp .next |
.copy: |
add esi, [coff] |
rep movsb |
.next: |
pop ecx |
add edx, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
pop esi |
; save some additional data from COFF file |
; later we will use COFF header, headers for sections and symbol table |
; and also relocations table for all sections |
mov edx, [coff] |
mov ebx, [edx+CFH.pSymTable] |
mov edi, dword [fileinfo+32] |
sub edi, ebx |
jc .fail_and_free_data |
mov [esi+DLLDESCR.symbols_lim], edi |
add ebx, edx |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea edi, [edi+ecx*8+20] |
add edx, 20 |
@@: |
movzx eax, [edx+CFS.NumReloc] |
lea eax, [eax*5] |
lea edi, [edi+eax*2] |
add edx, COFF_SECTION_SIZE |
sub ecx, 5 |
jnz @b |
stdcall kernel_alloc, edi |
test eax, eax |
jz .fail_and_free_data |
mov edx, [coff] |
movzx ecx, [edx+CFH.nSections] |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+5] |
mov [esi+DLLDESCR.coff_hdr], eax |
push esi |
mov esi, edx |
mov edi, eax |
rep movsd |
pop esi |
mov [esi+DLLDESCR.symbols_ptr], edi |
push esi |
mov ecx, [edx+CFH.nSymbols] |
mov [esi+DLLDESCR.symbols_num], ecx |
mov ecx, [esi+DLLDESCR.symbols_lim] |
mov esi, ebx |
rep movsb |
pop esi |
mov ebx, [esi+DLLDESCR.coff_hdr] |
push esi |
movzx eax, [edx+CFH.nSections] |
lea edx, [ebx+20] |
@@: |
movzx ecx, [edx+CFS.NumReloc] |
lea ecx, [ecx*5] |
mov esi, [edx+CFS.PtrReloc] |
mov [edx+CFS.PtrReloc], edi |
sub [edx+CFS.PtrReloc], ebx |
add esi, [coff] |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
add edx, COFF_SECTION_SIZE |
dec eax |
jnz @b |
pop esi |
; fixup symbols |
mov edx, ebx |
mov eax, [ebx+CFH.nSymbols] |
add edx, 20 |
mov ecx, [esi+DLLDESCR.symbols_num] |
lea ecx, [ecx*9] |
add ecx, ecx |
add ecx, [esi+DLLDESCR.symbols_ptr] |
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\ |
ecx, 0 |
; test eax, eax |
; jnz @F |
; |
;@@: |
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS |
test eax, eax |
jnz @F |
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS |
@@: |
mov [esi+DLLDESCR.exports], eax |
; fix relocs in the hidden copy in kernel memory to default address |
; it is first fix; usually this will be enough, but second fix |
; can be necessary if real load address will not equal assumption |
mov eax, [esi+DLLDESCR.data] |
sub eax, [esi+DLLDESCR.defaultbase] |
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax |
stdcall kernel_free, [coff] |
.dll_already_loaded: |
inc [esi+DLLDESCR.refcount] |
push esi |
call init_heap |
pop esi |
mov edi, [esi+DLLDESCR.size] |
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi |
test eax, eax |
jnz @f |
stdcall user_alloc, edi |
test eax, eax |
jz .fail_and_dereference |
@@: |
mov [img_base], eax |
mov eax, HDLL.sizeof |
call malloc |
test eax, eax |
jz .fail_and_free_user |
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] |
mov [eax+HDLL.pid], edx |
push eax |
call init_dlls_in_thread |
pop ebx |
test eax, eax |
jz .fail_and_free_user |
mov edx, [eax+HDLL.fd] |
mov [ebx+HDLL.fd], edx |
mov [ebx+HDLL.bk], eax |
mov [eax+HDLL.fd], ebx |
mov [edx+HDLL.bk], ebx |
mov eax, ebx |
mov ebx, [img_base] |
mov [eax+HDLL.base], ebx |
mov [eax+HDLL.size], edi |
mov [eax+HDLL.refcount], 1 |
mov [eax+HDLL.parent], esi |
mov edx, ebx |
shr edx, 12 |
or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK |
; copy entries of page table from kernel-side image to usermode |
; use copy-on-write for user-mode image, so map as readonly |
xor edi, edi |
mov ecx, [esi+DLLDESCR.data] |
shr ecx, 12 |
.map_pages_loop: |
mov eax, [page_tabs+ecx*4] |
and eax, not 0xFFF |
or al, PG_USER |
xchg eax, [page_tabs+edx*4] |
test al, 1 |
jz @f |
call free_page |
@@: |
invlpg [ebx+edi] |
inc ecx |
inc edx |
add edi, 0x1000 |
cmp edi, [esi+DLLDESCR.size] |
jb .map_pages_loop |
; if real user-mode base is not equal to preferred base, relocate image |
sub ebx, [esi+DLLDESCR.defaultbase] |
jz @f |
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx |
@@: |
mov eax, [esi+DLLDESCR.exports] |
sub eax, [esi+DLLDESCR.defaultbase] |
add eax, [img_base] |
ret |
.fail_and_free_data: |
stdcall kernel_free, [esi+DLLDESCR.data] |
.fail_and_free_dll: |
mov eax, esi |
call free |
.fail_and_free_coff: |
stdcall kernel_free, [coff] |
.fail: |
xor eax, eax |
ret |
.fail_and_free_user: |
stdcall user_free, [img_base] |
.fail_and_dereference: |
mov eax, 1 ; delete 1 reference |
call dereference_dll |
xor eax, eax |
ret |
endp |
; initialize [APPDATA.dlls_list_ptr] for given thread |
; DLL is per-process object, so APPDATA.dlls_list_ptr must be |
; kept in sync for all threads of one process. |
; out: eax = APPDATA.dlls_list_ptr if all is OK, |
; NULL if memory allocation failed |
init_dlls_in_thread: |
mov ebx, [current_slot] |
mov eax, [ebx+APPDATA.dlls_list_ptr] |
test eax, eax |
jnz .ret |
push [ebx+APPDATA.dir_table] |
mov eax, 8 |
call malloc |
pop edx |
test eax, eax |
jz .ret |
mov [eax], eax |
mov [eax+4], eax |
mov ecx, [TASK_COUNT] |
mov ebx, SLOT_BASE+256 |
.set: |
cmp [ebx+APPDATA.dir_table], edx |
jnz @f |
mov [ebx+APPDATA.dlls_list_ptr], eax |
@@: |
add ebx, 256 |
dec ecx |
jnz .set |
.ret: |
ret |
; in: eax = number of references to delete, esi -> DLLDESCR struc |
dereference_dll: |
sub [esi+DLLDESCR.refcount], eax |
jnz .ret |
mov eax, [esi+DLLDESCR.fd] |
mov edx, [esi+DLLDESCR.bk] |
mov [eax+DLLDESCR.bk], edx |
mov [edx+DLLDESCR.fd], eax |
stdcall kernel_free, [esi+DLLDESCR.coff_hdr] |
stdcall kernel_free, [esi+DLLDESCR.data] |
mov eax, esi |
call free |
.ret: |
ret |
destroy_hdll: |
push ebx ecx esi edi |
push eax |
mov ebx, [eax+HDLL.base] |
mov esi, [eax+HDLL.parent] |
mov edx, [esi+DLLDESCR.size] |
; The following actions require the context of application where HDLL is mapped. |
; However, destroy_hdll can be called in the context of OS thread when |
; cleaning up objects created by the application which is destroyed. |
; So remember current cr3 and set it to page table of target. |
mov eax, [ecx+APPDATA.dir_table] |
; Because we cheat with cr3, disable interrupts: task switch would restore |
; page table from APPDATA of current thread. |
; Also set [current_slot] because it is used by user_free. |
pushf |
cli |
push [current_slot] |
mov [current_slot], ecx |
mov ecx, cr3 |
push ecx |
mov cr3, eax |
push ebx ; argument for user_free |
mov eax, ebx |
shr ebx, 12 |
push ebx |
mov esi, [esi+DLLDESCR.data] |
shr esi, 12 |
.unmap_loop: |
push eax |
mov eax, 2 |
xchg eax, [page_tabs+ebx*4] |
mov ecx, [page_tabs+esi*4] |
and eax, not 0xFFF |
and ecx, not 0xFFF |
cmp eax, ecx |
jz @f |
call free_page |
@@: |
pop eax |
invlpg [eax] |
add eax, 0x1000 |
inc ebx |
inc esi |
sub edx, 0x1000 |
ja .unmap_loop |
pop ebx |
and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK |
call user_free |
; Restore context. |
pop eax |
mov cr3, eax |
pop [current_slot] |
popf |
; Ok, cheating is done. |
pop eax |
push eax |
mov esi, [eax+HDLL.parent] |
mov eax, [eax+HDLL.refcount] |
call dereference_dll |
pop eax |
mov edx, [eax+HDLL.bk] |
mov ebx, [eax+HDLL.fd] |
mov [ebx+HDLL.bk], edx |
mov [edx+HDLL.fd], ebx |
call free |
pop edi esi ecx ebx |
ret |
; ecx -> APPDATA for slot, esi = dlls_list_ptr |
destroy_all_hdlls: |
test esi, esi |
jz .ret |
.loop: |
mov eax, [esi+HDLL.fd] |
cmp eax, esi |
jz free |
call destroy_hdll |
jmp .loop |
.ret: |
ret |
align 4 |
stop_all_services: |
push ebp |
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.sizeof |
jne .next |
mov ebx, [edx+SRV.entry] |
mov edx, [edx+SRV.fd] |
test ebx, ebx |
jz .next |
push edx |
mov ebp, esp |
push 0 |
push -1 |
call ebx |
mov esp, ebp |
pop edx |
jmp .next |
.done: |
pop ebp |
ret |
; param |
; eax= size |
; ebx= pid |
align 4 |
create_kernel_object: |
push ebx |
call malloc |
pop ebx |
test eax, eax |
jz .fail |
mov ecx,[current_slot] |
add ecx, APP_OBJ_OFFSET |
pushfd |
cli |
mov edx, [ecx+APPOBJ.fd] |
mov [eax+APPOBJ.fd], edx |
mov [eax+APPOBJ.bk], ecx |
mov [eax+APPOBJ.pid], ebx |
mov [ecx+APPOBJ.fd], eax |
mov [edx+APPOBJ.bk], eax |
popfd |
.fail: |
ret |
; param |
; eax= object |
align 4 |
destroy_kernel_object: |
pushfd |
cli |
mov ebx, [eax+APPOBJ.fd] |
mov ecx, [eax+APPOBJ.bk] |
mov [ebx+APPOBJ.bk], ecx |
mov [ecx+APPOBJ.fd], ebx |
popfd |
xor edx, edx ;clear common header |
mov [eax], edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax+16], edx |
call free ;release object memory |
ret |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/v86.inc |
---|
0,0 → 1,935 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; 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 = 0 |
; linear address = OS_BASE |
mov dword [eax], 111b |
mov dword [eax+800h], OS_BASE |
; 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 [OS_BASE + 0x500], 0xCD |
mov byte [OS_BASE + 0x501], 0x13 |
mov byte [OS_BASE + 0x502], 0xF4 |
mov byte [OS_BASE + 0x503], 0xCD |
mov byte [OS_BASE + 0x504], 0x10 |
mov byte [OS_BASE + 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). |
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: |
; Did we all that we have wanted to do? |
cmp bl,1 |
jne @f |
xor eax, eax |
mov dr6, eax |
@@: 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 |
call update_counters |
lea edi, [ebx + 0x100000000 - SLOT_BASE] |
shr edi, 3 |
add edi, TASK_DATA |
call find_next_task.found |
call do_change_task |
popad |
iretd |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/sched.inc |
---|
0,0 → 1,412 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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$ |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
pushad |
Mov ds, ax, app_data |
mov es, ax |
inc [timer_ticks] |
mov eax, [timer_ticks] |
call playNote ; <<<--- Speaker driver |
sub eax,[next_usage_update] |
cmp eax,100 |
jb .nocounter |
add [next_usage_update],100 |
call updatecputimes |
.nocounter: |
mov al,0x20 ; send End Of Interrupt signal |
out 0x20,al |
btr dword[DONT_SWITCH], 0 |
jc .return |
call find_next_task |
jz .return ; if there is only one running process |
call do_change_task |
.return: |
popad |
iretd |
align 4 |
change_task: |
pushfd |
cli |
pushad |
if 0 |
; \begin{Mario79} ; <- must be refractoried, if used... |
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 |
jz .return ; the same task -> skip switch |
@@: mov byte[DONT_SWITCH], 1 |
call do_change_task |
.return: |
popad |
popfd |
ret |
uglobal |
align 4 |
; far_jump: |
; .offs dd ? |
; .sel dw ? |
context_counter dd 0 ;noname & halyavin |
next_usage_update dd 0 |
timer_ticks dd 0 |
; prev_slot dd ? |
; event_sched dd ? |
endg |
align 4 |
update_counters: |
mov edi, [TASK_BASE] |
rdtsc |
sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add |
add [edi+TASKDATA.counter_sum], eax ; counter sum |
ret |
align 4 |
updatecputimes: |
xor eax,eax |
xchg eax,[idleuse] |
mov [idleusesec],eax |
mov ecx, [TASK_COUNT] |
mov edi, TASK_DATA |
.newupdate: |
xor eax,eax |
xchg eax,[edi+TASKDATA.counter_sum] |
mov [edi+TASKDATA.cpu_usage],eax |
add edi,0x20 |
loop .newupdate |
ret |
align 4 |
find_next_task: |
;info: |
; Find next task to execute |
;retval: |
; ebx = address of the APPDATA for the selected task (slot-base) |
; esi = previous slot-base ([current_slot] at the begin) |
; edi = address of the TASKDATA for the selected task |
; ZF = 1 if the task is the same |
;warning: |
; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result |
; [current_slot] is not set to new value (ebx)!!! |
;scratched: eax,ecx |
call update_counters ; edi := [TASK_BASE] |
Mov esi, ebx, [current_slot] |
.loop: |
cmp bh,[TASK_COUNT] |
jb @f |
xor bh, bh |
mov edi,CURRENT_TASK |
@@: inc bh ; ebx += APPDATA.size |
add edi,0x20 ; edi += TASKDATA.size |
mov al, [edi+TASKDATA.state] |
test al, al |
jz .found ; state == 0 |
cmp al, 5 |
jne .loop ; state == 1,2,3,4,9 |
; state == 5 |
pushad ; more freedom for [APPDATA.wait_test] |
call [ebx+APPDATA.wait_test] |
mov [esp+28],eax |
popad |
or eax,eax |
jnz @f |
; testing for timeout |
mov ecx, [timer_ticks] |
sub ecx, [ebx+APPDATA.wait_begin] |
cmp ecx, [ebx+APPDATA.wait_timeout] |
jb .loop |
@@: mov [ebx+APPDATA.wait_param], eax ; retval for wait |
mov [edi+TASKDATA.state], 0 |
.found: |
mov [CURRENT_TASK],bh |
mov [TASK_BASE],edi |
rdtsc ;call _rdtsc |
mov [edi+TASKDATA.counter_add],eax ; for next using update_counters |
cmp ebx, esi ;esi - previous slot-base |
ret |
;TODO: Íàäî áû óáðàòü èñïîëüçîâàíèå do_change_task èç V86... |
; è ïîñëå ýòîãî ïåðåíåñòè îáðàáîòêó TASKDATA.counter_add/sum â do_change_task |
align 4 |
do_change_task: |
;param: |
; ebx = address of the APPDATA for incoming task (new) |
;warning: |
; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) |
; [current_slot] is the outcoming (old), and set here to a new value (ebx) |
;scratched: eax,ecx,esi |
mov esi,ebx |
xchg esi,[current_slot] |
; set new stack after saving old |
mov [esi+APPDATA.saved_esp], esp |
mov esp, [ebx+APPDATA.saved_esp] |
; set new thread io-map |
Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map] |
Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4] |
; set new thread memory-map |
mov ecx, APPDATA.dir_table |
mov eax, [ebx+ecx] ;offset>0x7F |
cmp eax, [esi+ecx] ;offset>0x7F |
je @f |
mov cr3, eax |
@@: |
; set tss.esp0 |
Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] |
mov edx, [ebx+APPDATA.tls_base] |
cmp edx, [esi+APPDATA.tls_base] |
je @f |
mov [tls_data_l+2],dx |
shr edx,16 |
mov [tls_data_l+4],dl |
mov [tls_data_l+7],dh |
mov dx, app_tls |
mov fs, dx |
@@: |
; set gs selector unconditionally |
Mov gs,ax,graph_data |
; set CR0.TS |
cmp bh, byte[fpu_owner] ;bh == incoming task (new) |
clts ;clear a task switch flag |
je @f |
mov eax, cr0 ;and set it again if the owner |
or eax, CR0_TS ;of a fpu has changed |
mov cr0, eax |
@@: ; set context_counter (only for user pleasure ???) |
inc [context_counter] ;noname & halyavin |
; set debug-registers, if it's necessary |
test byte[ebx+APPDATA.dbg_state], 1 |
jz @f |
xor eax, eax |
mov dr6, eax |
lea esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F |
cld |
macro lodsReg [reg] { |
lodsd |
mov reg,eax |
} lodsReg dr0, dr1, dr2, dr3, dr7 |
purge lodsReg |
@@: ret |
;end. |
struc MUTEX_WAITER |
{ |
.next rd 1 |
.prev rd 1 |
.task rd 1 |
.sizeof: |
}; |
virtual at 0 |
MUTEX_WAITER MUTEX_WAITER |
end virtual |
;void __fastcall mutex_init(struct mutex *lock) |
align 4 |
mutex_init: |
lea eax, [ecx+MUTEX.next] |
mov [ecx+MUTEX.count],1 |
mov [ecx+MUTEX.next], eax |
mov [ecx+MUTEX.prev], eax |
ret |
;void __fastcall mutex_lock(struct mutex *lock) |
align 4 |
mutex_lock: |
dec [ecx+MUTEX.count] |
jns .done |
pushfd |
cli |
push esi |
sub esp, MUTEX_WAITER.sizeof |
mov eax, [ecx+MUTEX.prev] |
lea esi, [ecx+MUTEX.next] |
mov [ecx+MUTEX.prev], esp |
mov [esp+MUTEX_WAITER.next], esi |
mov [esp+MUTEX_WAITER.prev], eax |
mov [eax], esp |
mov edx, [TASK_BASE] |
mov [esp+MUTEX_WAITER.task], edx |
.forever: |
mov eax, -1 |
xchg eax, [ecx+MUTEX.count] |
dec eax |
jz @F |
mov [edx+TASKDATA.state], 1 |
call change_task |
jmp .forever |
@@: |
mov edx, [esp+MUTEX_WAITER.next] |
mov eax, [esp+MUTEX_WAITER.prev] |
mov [eax+MUTEX_WAITER.next], edx |
cmp [ecx+MUTEX.next], esi |
mov [edx+MUTEX_WAITER.prev], eax |
jne @F |
mov [ecx+MUTEX.count], 0 |
@@: |
add esp, MUTEX_WAITER.sizeof |
pop esi |
popfd |
.done: |
ret |
;void __fastcall mutex_unlock(struct mutex *lock) |
align 4 |
mutex_unlock: |
pushfd |
cli |
lea eax, [ecx+MUTEX.next] |
cmp eax, [ecx+MUTEX.next] |
mov [ecx+MUTEX.count], 1 |
je @F |
mov eax, [eax+MUTEX_WAITER.task] |
mov [eax+TASKDATA.state], 0 |
@@: |
popfd |
ret |
purge MUTEX_WAITER |
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 |
uglobal |
rdy_head rd 16 |
endg |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/debug.inc |
---|
0,0 → 1,429 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; diamond, 2006 |
sys_debug_services: |
cmp ebx, 9 |
ja @f |
jmp dword [sys_debug_services_table+ebx*4] |
@@: ret |
iglobal |
align 4 |
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 |
endg |
debug_set_event_data: |
; in: ecx = pointer |
; destroys eax |
mov eax, [current_slot] |
mov [eax+APPDATA.dbg_event_mem], ecx |
ret |
get_debuggee_slot: |
; in: ecx=PID |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ecx |
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: ecx=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: ecx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ecx, eax |
shr ecx, 5 |
; push 2 |
; pop ebx |
mov edx,esi |
jmp sysfn_terminate |
debug_suspend: |
; in: ecx=pid |
; destroys eax,ecx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state |
test cl, cl |
jz .1 |
cmp cl, 5 |
jnz .ret |
mov cl, 2 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: |
sti |
ret |
.1: |
inc ecx |
jmp .2 |
do_resume: |
mov cl, [CURRENT_TASK+eax+TASKDATA.state] |
cmp cl, 1 |
jz .1 |
cmp cl, 2 |
jnz .ret |
mov cl, 5 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl |
.ret: ret |
.1: dec ecx |
jmp .2 |
debug_resume: |
; in: ecx=pid |
; destroys eax,ebx |
cli |
mov eax, ecx |
call pid_to_slot |
shl eax, 5 |
jz .ret |
call do_resume |
.ret: sti |
ret |
debug_getcontext: |
; in: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ecx |
; mov ecx, esi |
call check_region |
; pop ecx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
mov edi, esi |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea esi, [eax+RING0_STACK_SIZE] |
.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: |
; ecx=pid |
; edx=sizeof(CONTEXT) |
; esi->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp edx, 28h |
jnz .ret |
; push ebx |
; mov ebx, edx |
call check_region |
; pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
; mov esi, edx |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea edi, [eax+RING0_STACK_SIZE] |
.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 esi, OS_BASE |
jae .errret |
cmp dl, 3 |
ja .errret |
mov ecx, dr7 |
;fix me |
xchg ecx,edx |
shr edx, cl |
shr edx, cl |
xchg ecx,edx |
test ecx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test dh, dh |
jns .new |
; clear breakpoint |
movzx edx, dl |
add edx, edx |
and dword [eax+edx*2], 0 ; clear DR<i> |
btr dword [eax+10h], edx ; 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+32], 0 |
sti |
ret |
.errret: |
sti |
mov dword [esp+32], 1 |
ret |
.errret2: |
sti |
mov dword [esp+32], 2 |
ret |
.new: |
; add new breakpoint |
; dl=index; dh=flags; esi=address |
test dh, 0xF0 |
jnz .errret |
mov cl, dh |
and cl, 3 |
cmp cl, 2 |
jz .errret |
mov cl, dh |
shr cl, 2 |
cmp cl, 2 |
jz .errret |
mov ebx,esi |
test bl, dl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx edx, dh |
movzx ecx, dl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], ebx;esi ; set DR<i> |
shl edx, cl |
mov ebx, 0xF |
shl ebx, cl |
not ebx |
and [eax+10h+2], bx |
or [eax+10h+2], dx ; 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: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=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 ecx, edi |
call read_process_memory |
sti |
mov dword [esp+32], eax |
ret |
.err: |
or dword [esp+32], -1 |
ret |
debug_write_process_memory: |
; in: |
; ecx=pid |
; edx=length |
; edi->buffer in debugger |
; esi=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 ecx, edi |
call write_process_memory |
sti |
mov [esp+32], 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 esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem] |
test esi, esi |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ecx, esp |
mov edx, 8 |
call read_process_memory |
cmp eax, edx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ecx], 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 edx, [ecx+8] |
add edx, [ecx+4] |
cmp edx, [ecx] |
ja .2 |
; advance buffer position |
push edx |
mov edx, 4 |
sub ecx, edx |
mov eax, ebp |
add esi, edx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add esi, edx |
add esi, [ecx+8] |
add ecx, 20 |
pop edx |
pop edx |
pop edx |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/sys32.inc |
---|
0,0 → 1,834 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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$ |
align 4 ;3A08 |
build_interrupt_table: |
mov edi, idts |
mov esi, sys_int |
mov ecx, 0x40 |
mov eax, (10001110b shl 24) + os_code |
@@: movsw ;low word of code-entry |
stosd ;interrupt gate type : os_code selector |
movsw ;high word of code-entry |
loop @b |
movsd ;copy low dword of trap gate for int 0x40 |
movsd ;copy high dword of trap gate for int 0x40 |
lidt [esi] |
ret |
iglobal |
align 4 |
sys_int: |
;exception handlers addresses (for interrupt gate construction) |
dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc |
dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15 |
dd e16, e17,e18, e19 |
times 12 dd unknown_interrupt ;int_20..int_31 |
;interrupt handlers addresses (for interrupt gate construction) |
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 ;int_0x30..int_0x3F |
;int_0x40 gate trap (for directly copied) |
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 |
idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) |
dw 2*($-sys_int-4)-1 |
dd idts ;0x8000B100 |
dw 0 ;ïðîñòî âûðàâíèâàíèå |
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b |
dd msg_exc_c,msg_exc_d,msg_exc_e |
msg_exc_8 db "Double fault", 0 |
msg_exc_u db "Undefined Exception", 0 |
msg_exc_a db "Invalid TSS", 0 |
msg_exc_b db "Segment not present", 0 |
msg_exc_c db "Stack fault", 0 |
msg_exc_d db "General protection fault", 0 |
msg_exc_e db "Page fault", 0 |
msg_sel_ker db "kernel", 0 |
msg_sel_app db "application", 0 |
endg |
macro save_ring3_context { |
pushad |
} |
macro restore_ring3_context { |
popad |
} |
macro exc_wo_code [num] { |
e#num : |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_wo_code 0,1,2,3,4,5,6,15,16,19 |
macro exc_w_code [num] { |
e#num : |
add esp, 4 |
save_ring3_context |
mov bl, num |
jmp exc_c |
} exc_w_code 8,9,10,11,12,13,17,18 |
uglobal |
pf_err_code dd ? |
endg |
page_fault_exc: ; äóðàêîóñòî÷èâîñòü: ñåëåêòîðû èñïîð÷åíû... |
pop [ss:pf_err_code]; äåéñòâèòåëüíî äî ñëåäóþùåãî #PF |
save_ring3_context |
mov bl,14 |
exc_c: ; èñêëþ÷åíèÿ (âñå, êðîìå 7-ãî - #NM) |
; Ôðýéì ñòåêà ïðè èñêëþ÷åíèè/ïðåðûâàíèè èç 3-ãî êîëüöà + pushad (ò.å., èìåííî çäåñü) |
reg_ss equ esp+0x30 |
reg_esp3 equ esp+0x2C |
reg_eflags equ esp+0x28 |
reg_cs3 equ esp+0x24 |
reg_eip equ esp+0x20 |
; ýòî ôðýéì îò pushad |
reg_eax equ esp+0x1C |
reg_ecx equ esp+0x18 |
reg_edx equ esp+0x14 |
reg_ebx equ esp+0x10 |
reg_esp0 equ esp+0x0C |
reg_ebp equ esp+0x08 |
reg_esi equ esp+0x04 |
reg_edi equ esp+0x00 |
Mov ds,ax,app_data ; çàãðóçèì ïðàâèëüíûå çíà÷åíèÿ |
mov es,ax ; â ñåãìåíòíûå ðåãèñòðû |
cld ; è ïðèâîäèì DF ê ñòàíäàðòó |
movzx ebx,bl |
; redirect to V86 manager? (EFLAGS & 0x20000) != 0? |
test byte[reg_eflags+2],2 |
jnz v86_exc_c |
cmp bl,14 ; #PF |
jne @f |
call page_fault_handler ; SEE: core/memory.inc |
@@: mov esi, [current_slot] |
btr [esi+APPDATA.except_mask], ebx |
jnc @f |
mov eax,[esi+APPDATA.exc_handler] |
test eax, eax |
jnz IRetToUserHook |
@@: cli |
mov eax, [esi+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
call show_error_parameters ;; only ONE using, inline ??? |
;mov edx, [TASK_BASE] |
mov [edx + TASKDATA.state], byte 4 ; terminate |
jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
mov ecx,1 ; debug_message code=other_exception |
cmp bl,1 ; #DB |
jne .notify ; notify debugger and suspend ourself |
mov ebx, dr6 ; debug_message data=DR6_image |
xor edx, edx |
mov dr6, edx |
mov edx, dr7 |
mov cl, not 8 |
.l1: shl dl,2 |
jc @f |
and bl, cl |
@@: sar cl,1 |
jc .l1 |
mov cl, 3 ; debug_message code=debug_exception |
.notify: |
push ebx ; debug_message data |
mov ebx, [TASK_BASE] |
push [ebx+TASKDATA.pid] ; PID |
push ecx ; debug_message code ((here: ecx==1/3)) |
mov cl, 12 ; debug_message size |
call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc |
add esp,12 |
mov edx, [TASK_BASE] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task ; SEE: core/shed.inc |
restore_ring3_context |
iretd |
IRetToUserHook: |
xchg eax, [reg_eip] |
sub dword[reg_esp3], 8 |
mov edi, [reg_esp3] |
stosd |
mov [edi], ebx |
restore_ring3_context |
unknown_interrupt: |
iretd |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
show_error_parameters: |
mov edx,[TASK_BASE] ;not scratched below |
DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid] |
cmp bl, 0x08 |
jb .l0 |
cmp bl, 0x0e |
jbe .l1 |
.l0: mov bl, 0x09 |
.l1: mov eax,[msg_fault_sel+ebx*4 - 0x08*4] |
DEBUGF 1, "K : %s\n", eax |
mov eax, [reg_cs3+4] |
mov edi, msg_sel_app |
mov ebx, [reg_esp3+4] |
cmp eax, app_code |
je @f |
mov edi, msg_sel_ker |
mov ebx, [reg_esp0+4] |
@@: DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4] |
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4] |
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx |
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi |
ret |
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
restore reg_ss |
restore reg_esp3 |
restore reg_eflags |
restore reg_cs |
restore reg_eip |
restore reg_eax |
restore reg_ecx |
restore reg_edx |
restore reg_ebx |
restore reg_esp0 |
restore reg_ebp |
restore reg_esi |
restore reg_edi |
; irq1 -> hid/keyboard.inc |
macro irqh [num] { |
p_irq#num : |
mov edi, num |
jmp irqhandler |
} |
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 eax,5 |
mov [check_idle_semaphore],eax |
; mov al, 0x20 |
add eax,(0x20-0x5) |
out 0x20, al |
ret |
;destroy eax |
ready_for_next_irq_1: |
mov eax,5 |
mov [check_idle_semaphore],eax |
; mov al, 0x20 |
add eax,(0x20-0x5) |
out 0xa0,al |
out 0x20, al |
ret |
irqD: |
push eax |
xor eax,eax |
out 0xf0,al |
mov al,0x20 |
out 0xa0,al |
out 0x20,al |
pop eax |
iret |
irqh 2,3,4,5,7,8,9,10,11 |
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 |
xor eax,eax |
mov [application_table_status],eax |
apptsl1: |
pop eax |
ret |
; * eax = 64 - íîìåð ôóíêöèè |
; * ebx = 1 - åäèíñòâåííàÿ ïîäôóíêöèÿ |
; * ecx = íîâûé ðàçìåð ïàìÿòè |
;Âîçâðàùàåìîå çíà÷åíèå: |
; * eax = 0 - óñïåøíî |
; * eax = 1 - íåäîñòàòî÷íî ïàìÿòè |
sys_resize_app_memory: |
; ebx = 1 - resize |
; ecx = new amount of memory |
; cmp eax,1 |
dec ebx |
jnz .no_application_mem_resize |
stdcall new_mem_resize, ecx |
mov [esp+32], eax |
.no_application_mem_resize: |
ret |
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 |
@@: |
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 |
stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr] |
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 [draw_limits.left],eax |
add eax,[esi+WDATA.box.width] |
mov [draw_limits.right],eax |
mov eax,[esi+WDATA.box.top] |
mov [draw_limits.top],eax |
add eax,[esi+WDATA.box.height] |
mov [draw_limits.bottom],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, [SLOT_BASE+256+APPDATA.io_map] |
je @F |
call free_page |
@@: |
mov eax, [edi+APPDATA.io_map+4] |
cmp eax, [SLOT_BASE+256+APPDATA.io_map+4] |
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 |
and [hd1_status], 0 |
@@: |
cmp [cd_status], esi |
jnz @f |
call free_cd_channel |
and [cd_status], 0 |
@@: |
cmp [flp_status], esi |
jnz @f |
and [flp_status], 0 |
@@: |
pop esi |
cmp [bgrlockpid], esi |
jnz @f |
and [bgrlockpid], 0 |
and [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] |
test esi,esi |
jz 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, [draw_limits.left] |
mov ebx, [draw_limits.top] |
mov ecx, [draw_limits.right] |
mov edx, [draw_limits.bottom] |
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 |
and [application_table_status],0 |
;mov esi,process_terminated |
;call sys_msg_board_str |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/taskman.inc |
---|
0,0 → 1,1169 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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 |
.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] |
test eax, eax |
jnz .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 |
xor edx, edx |
cmp word [6], '02' |
jne @f |
not edx |
@@: |
mov [ebx+APPDATA.tls_base],edx |
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' |
je @f |
cmp [eax+6], word '02' |
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], 0 |
@@: |
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, dlls_list:dword |
xor edx,edx |
push 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 |
add ecx,SLOT_BASE |
cmp [ecx+APPDATA.dir_table],ebx ;compare page directory addresses |
jnz @f |
mov [ebp-4],ecx |
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 |
pop ecx |
cmp edx,1 |
jg .ret |
;if there isn't threads then clear memory. |
mov esi, [dlls_list] |
call destroy_all_hdlls |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov eax, [pg_dir] |
and eax, not 0xFFF |
stdcall map_page,[tmp_task_pdir],eax,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,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],0,PG_UNMAP |
stdcall map_page,[tmp_task_pdir],0,PG_UNMAP |
dec [pg_data.pg_mutex] |
.ret: |
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: |
; esi - start of buffer |
; edx - 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 |
; esi - start of buffer |
; edx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test edx,edx |
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 |
; ecx - buffer address |
; edx - buffer size |
; esi - 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], ecx |
and [r_count], 0 |
mov [tmp_r_cnt], edx |
mov [offset], esi |
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 ebx, [offset] |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[slot], ebx, ecx, PG_MAP |
pop ecx |
mov esi, [offset] |
and esi, 0xfff |
sub eax, esi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_r_cnt], eax |
@@: |
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 |
.ret: |
popad |
mov eax, [r_count] |
ret |
endp |
align 4 |
proc write_process_memory |
;Input: |
; eax - process slot |
; ecx - buffer address |
; edx - buffer size |
; esi - 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], ecx |
and [w_count], 0 |
mov [tmp_w_cnt], edx |
mov [offset], esi |
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 ebx, [offset] |
; add ebx, new_app_base |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[slot], ebx, ecx, PG_SW |
pop ecx |
mov edi, [offset] |
and edi, 0xfff |
sub eax, edi |
jbe .ret |
cmp ecx, eax |
jbe @f |
mov ecx, eax |
mov [tmp_w_cnt], eax |
@@: |
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 |
.ret: |
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 ebx,1 |
jne .failed ;other subfunctions |
xor eax,eax |
mov [app_eip], ecx |
mov [app_cmdline], eax |
mov [app_esp], edx |
mov [app_path], eax |
;mov esi,new_process_loading |
;call sys_msg_board_str |
.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] |
test eax, eax |
jnz .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 |
mov eax,[ebx+APPDATA.dlls_list_ptr] |
mov [edx+APPDATA.dlls_list_ptr],eax |
mov eax, [ebx+APPDATA.tls_base] |
test eax, eax |
jz @F |
push edx |
stdcall user_alloc, 4096 |
pop edx |
test eax, eax |
jz .failed1 ;eax=0 |
@@: |
mov [edx+APPDATA.tls_base], eax |
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 |
xor eax,eax |
mov [application_table_status],eax ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
ret |
.failed: |
xor eax,eax |
.failed1: |
mov [application_table_status],eax |
dec eax ;-1 |
ret |
endp |
; param |
; ebx=mutex |
align 4 |
wait_mutex: |
;;Maxis use atomic bts for mutex 4.4.2009 |
push eax |
push ebx |
.do_wait: |
bts dword [ebx],0 |
jnc .locked |
call change_task |
jmp .do_wait |
.locked: |
pop ebx |
pop eax |
ret |
align 4 |
tls_app_entry: |
call init_heap |
stdcall user_alloc, 4096 |
mov edx, [current_slot] |
mov [edx+APPDATA.tls_base], eax |
mov [tls_data_l+2],ax |
shr eax,16 |
mov [tls_data_l+4],al |
mov [tls_data_l+7],ah |
mov dx, app_tls |
mov fs, dx |
popad |
iretd |
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.exc_handler], 0 |
mov [eax+SLOT_BASE+APPDATA.except_mask], 0 |
;set default io permission map |
mov ecx, [SLOT_BASE+256+APPDATA.io_map] |
mov [eax+SLOT_BASE+APPDATA.io_map], ecx |
mov ecx, [SLOT_BASE+256+APPDATA.io_map+4] |
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx |
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 |
mov edx, irq0.return |
cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1 |
jne @F |
mov edx, tls_app_entry |
@@: |
; 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 |
xor eax,eax |
mov [ecx+0],dword eax |
mov [ecx+4],dword eax |
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], edx |
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 |
ret |
endp |
include "debug.inc" |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/malloc.inc |
---|
0,0 → 1,1029 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
; 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 |
; |
align 16 |
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 |
mov [mst.mutex], 0 |
ret |
.small: |
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) |
;;;;;;;;;;; start a change <lrz> |
mov eax,[mst.treemap] |
test eax,eax |
;;;;;;;;;;; end the change <lrz> |
; cmp [mst.treemap], 0 |
jz .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 |
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 |
btr [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 |
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 |
; param |
; esi= chunk |
; ebx= size |
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 |
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 |
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 |
malloc_large: |
.idx equ esp+4 |
.rst equ esp |
push ebp |
push esi |
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 esi |
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 esi |
pop ebp |
ret |
.done: |
add esp, 8 |
pop edi |
pop esi |
pop ebp |
xor eax, eax |
ret |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/test_malloc.asm |
---|
0,0 → 1,223 |
; Tests of malloc()/free() from the kernel heap. |
; This file is not included in the kernel, it is just test application. |
use32 |
db 'MENUET01' |
dd 1, start, i_end, mem, mem, 0, 0 |
start: |
; Zero-initialize uglobals (as in kernel at boot) |
mov ecx, (zeroend - zerostart + 3) / 4 |
xor eax, eax |
mov edi, zerostart |
rep stosd |
; Initialize small heap (as in kernel at boot) |
call init_malloc |
; Run tests |
call run_test1 |
call run_test2 |
call run_test3 |
; All is OK, return |
or eax, -1 |
int 0x40 |
run_test1: |
; basic test |
mov eax, 1 |
call malloc_with_test |
mov byte [eax], 0xDD |
mov esi, eax |
mov eax, 1 |
call malloc_with_test |
cmp byte [esi], 0xDD |
jnz memory_destroyed |
mov byte [eax], 0xEE |
xchg eax, esi |
call free |
cmp byte [esi], 0xEE |
jnz memory_destroyed |
xchg eax, esi |
call free |
ret |
run_test2: |
ret |
run_test3: |
; 1024000 times run random operation. |
; Randomly select malloc(random size from 1 to 1023) |
; or free(random of previously allocated areas) |
mov edi, 0x12345678 |
xor esi, esi ; 0 areas allocated |
mov ebx, 1024000 |
.loop: |
imul edi, 1103515245 |
add edi, 12345 |
mov eax, edi |
shr eax, 16 |
test ebx, 64 |
jz .prefer_free |
.prefer_malloc: |
test eax, 3 |
jz .free |
jmp @f |
.prefer_free: |
test eax, 3 |
jnz .free |
@@: |
shr eax, 2 |
and eax, 1023 |
jz .loop |
push ebx |
push eax |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], eax |
call malloc_with_test |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
pop ecx |
pop ebx |
inc esi |
push ecx eax |
push edi |
mov edi, eax |
mov eax, esi |
rep stosb |
pop edi |
jmp .common |
.free: |
test esi, esi |
jz .loop |
xor edx, edx |
div esi |
sub edx, esi |
neg edx |
dec edx |
mov eax, [esp+edx*8] |
; mov ecx, [saved_state_num] |
; mov [saved_state+ecx*8], -1 |
; mov [saved_state+ecx*8+4], eax |
; inc [saved_state_num] |
mov ecx, [esp+edx*8+4] |
push edi eax |
mov edi, eax |
mov al, [edi] |
repz scasb |
jnz memory_destroyed |
pop eax edi |
push ebx edx |
call free |
pop edx ebx |
dec esi |
pop eax ecx |
push edi |
lea edi, [esp+4] |
@@: |
dec edx |
js @f |
xchg eax, [edi] |
xchg ecx, [edi+4] |
add edi, 8 |
jmp @b |
@@: |
pop edi |
.common: |
dec ebx |
jnz .loop |
@@: |
dec esi |
js @f |
pop eax ecx |
call free |
jmp @b |
@@: |
ret |
malloc_with_test: |
; calls malloc() and checks returned value |
call malloc |
test eax, eax |
jz generic_malloc_fail |
call check_mutex |
call check_range |
ret |
; Stubs for kernel procedures used by heap code |
wait_mutex: |
inc dword [ebx] |
ret |
kernel_alloc: |
cmp dword [esp+4], bufsize |
jnz error1 |
mov eax, buffer |
ret 4 |
macro $Revision [args] |
{ |
} |
; Error handlers |
error1: |
mov eax, 1 |
jmp error_with_code |
generic_malloc_fail: |
mov eax, 2 |
jmp error_with_code |
check_mutex: |
cmp [mst.mutex], 0 |
jnz @f |
ret |
@@: |
mov eax, 3 |
jmp error_with_code |
check_range: |
cmp eax, buffer |
jb @f |
cmp eax, buffer+bufsize |
jae @f |
ret |
@@: |
mov eax, 4 |
jmp error_with_code |
memory_destroyed: |
mov eax, 5 |
jmp error_with_code |
error_with_code: |
mov edx, saved_state_num |
; eax = error code |
; 1 signals error in testing code (wrong bufsize) |
; 2 = malloc() returned NULL |
; 3 = mutex not released |
; 4 = weird returned value from malloc() |
; 5 = memory destroyed by malloc() or free() |
int3 ; simplest way to report error |
jmp $-1 ; just in case |
; Include main heap code |
include '../proc32.inc' |
include '../const.inc' |
include 'malloc.inc' |
i_end: |
align 4 |
zerostart: |
mst MEM_STATE |
align 16 |
bufsize = 0x40000 ; change if malloc.inc changes |
buffer rb bufsize |
zeroend: |
saved_state_num dd ? |
saved_state rd 0x10000 |
align 4 |
rb 0x10000 ; for stack |
mem: |
/kernel/branches/Kolibri-acpi/core/ext_lib.inc |
---|
0,0 → 1,320 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;============================================================================ |
; |
; External kernel dependencies (libraries) loading |
; |
;============================================================================ |
$Revision$ |
if 0 |
; The code currently does not work. Kill "if 0/end if" only after correcting |
; to current kernel (dll.inc). |
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 |
end if |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/conf_lib.inc |
---|
0,0 → 1,297 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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$ |
iglobal |
conf_path_sect: db 'path',0 |
conf_fname db '/sys/sys.conf',0 |
endg |
; 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 |
iglobal |
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 |
endg |
;set up netvork configuration |
proc set_network_conf |
locals |
par db 30 dup(?) |
endl |
pushad |
;[net] |
;active |
lea eax,[par] |
invoke ini.get_int,conf_fname, unet, unet_active, 0 |
or eax,eax |
jz .do_not_set_net |
mov eax, [stack_config] |
and eax, 0xFFFFFF80 |
add eax, 3 |
mov [stack_config], eax |
call ash_eth_enable |
;addr |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_addr, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [stack_ip], eax |
;mask |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_mask, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [subnet_mask], eax |
;gate |
lea eax,[par] |
push eax |
invoke ini.get_str,conf_fname, unet, unet_gate, eax,30, unet_def |
pop eax |
stdcall do_inet_adr,eax |
mov [gateway_ip], eax |
.do_not_set_net: |
popad |
ret |
endp |
iglobal |
unet db 'net',0 |
unet_active db 'active',0 |
unet_addr db 'addr',0 |
unet_mask db 'mask',0 |
unet_gate db 'gate',0 |
unet_def db 0 |
endg |
; 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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/fpu.inc |
---|
0,0 → 1,183 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
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 |
except_7: ;#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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/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$ |
; 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 |
} |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/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$ |
; 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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/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$ |
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 |
Property changes: |
Added: svn:keywords |
+Revision |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/core/. |
---|
Property changes: |
Added: svn:ignore |
+*.mnt |
+lang.inc |
+*.bat |
+out.txt |
+scin* |
+*.obj |