Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 128 → Rev 129

/kernel/branches/gfx_kernel/core/debug.inc
0,0 → 1,499
; diamond, 2006
sys_debug_services:
cmp eax, 9
ja @f
jmp dword [sys_debug_services_table+eax*4]
@@: ret
sys_debug_services_table:
dd debug_set_event_data
dd debug_getcontext
dd debug_setcontext
dd debug_detach
dd debug_suspend
dd debug_resume
dd debug_read_process_memory
dd debug_write_process_memory
dd debug_terminate
dd debug_set_drx
 
debug_set_event_data:
; in: ebx = pointer
; destroys eax
mov eax, [0x3000]
shl eax, 8
mov [eax+0x80000+APPDATA.dbg_event_mem], ebx
ret
 
get_debuggee_slot:
; in: ebx=PID
; out: CF=1 if error
; CF=0 and eax=slot*0x20 if ok
; out: interrupts disabled
cli
mov eax, ebx
call pid_to_slot
test eax, eax
jz .ret_bad
shl eax, 5
push ebx
mov ebx, [0x3000]
cmp [0x80000+eax*8+APPDATA.debugger_slot], ebx
pop ebx
jnz .ret_bad
; clc ; automatically
ret
.ret_bad:
stc
ret
 
debug_detach:
; in: ebx=pid
; destroys eax,ebx
call get_debuggee_slot
jc .ret
and dword [eax*8+0x80000+APPDATA.debugger_slot], 0
call do_resume
.ret:
sti
ret
 
debug_terminate:
; in: ebx=pid
call get_debuggee_slot
jc debug_detach.ret
mov ebx, eax
shr ebx, 5
push 2
pop eax
jmp sys_system
 
debug_suspend:
; in: ebx=pid
; destroys eax,ebx
call get_debuggee_slot
jc .ret
mov bl, [0x3000+eax+TASKDATA.state] ; process state
test bl, bl
jz .1
cmp bl, 5
jnz .ret
mov bl, 2
.2: mov [0x3000+eax+TASKDATA.state], bl
.ret:
sti
ret
.1:
inc ebx
jmp .2
 
do_resume:
mov bl, [0x3000+eax+TASKDATA.state]
cmp bl, 1
jz .1
cmp bl, 2
jnz .ret
mov bl, 5
.2: mov [0x3000+eax+TASKDATA.state], bl
.ret: ret
.1: dec ebx
jmp .2
 
debug_resume:
; in: ebx=pid
; destroys eax,ebx
call get_debuggee_slot
jc .ret
call do_resume
.ret: sti
ret
 
debug_getcontext:
; in:
; ebx=pid
; ecx=sizeof(CONTEXT)
; edx->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp ecx, 28h
jnz .ret
add edx, std_application_base_address
push ebx
mov ebx, edx
call check_region
pop ebx
dec eax
jnz .ret
call get_debuggee_slot
jc .ret
imul eax, tss_step/32
add eax, tss_data
mov edi, edx
cmp [l.cs - tss_sceleton + eax], app_code
jnz .ring0
lea esi, [l.eip - tss_sceleton + eax]
shr ecx, 2
rep movsd
jmp .ret
.ring0:
; note that following code assumes that all interrupt/exception handlers
; saves ring-3 context by push ds es, pushad in this order
mov esi, [l.esp0 - tss_sceleton + eax]
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), ds, es, pushad
sub esi, 8+12+8+20h
lodsd
mov [edi+24h], eax
lodsd
mov [edi+20h], eax
lodsd
mov [edi+1Ch], eax
lodsd
lodsd
mov [edi+14h], eax
lodsd
mov [edi+10h], eax
lodsd
mov [edi+0Ch], eax
lodsd
mov [edi+8], eax
add esi, 8
lodsd
mov [edi], eax
lodsd
lodsd
mov [edi+4], eax
lodsd
mov [edi+18h], eax
.ret:
sti
ret
 
debug_setcontext:
; in:
; ebx=pid
; ecx=sizeof(CONTEXT)
; edx->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp ecx, 28h
jnz .ret
add edx, std_application_base_address
push ebx
mov ebx, edx
call check_region
pop ebx
dec eax
jnz .ret
call get_debuggee_slot
jc .stiret
imul eax, tss_step/32
add eax, tss_data
mov esi, edx
cmp [l.cs - tss_sceleton + eax], app_code
jnz .ring0
lea edi, [l.eip - tss_sceleton + eax]
shr ecx, 2
rep movsd
jmp .stiret
.ring0:
mov edi, [l.esp0 - tss_sceleton + eax]
sub edi, 8+12+8+20h
mov eax, [esi+24h]
stosd
mov eax, [esi+20h]
stosd
mov eax, [esi+1Ch]
stosd
scasd
mov eax, [esi+14h]
stosd
mov eax, [esi+10h]
stosd
mov eax, [esi+0Ch]
stosd
mov eax, [esi+8]
stosd
add edi, 8
mov eax, [esi]
stosd
scasd
mov eax, [esi+4]
stosd
mov eax, [esi+18h]
stosd
.stiret:
sti
.ret:
ret
 
debug_set_drx:
call get_debuggee_slot
jc .errret
mov ebp, eax
lea eax, [eax*8+0x80000+APPDATA.dbg_regs]
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
; [eax+10]=dr7
add edx, std_application_base_address
jc .errret
cmp cl, 3
ja .errret
mov ebx, dr7
shr ebx, cl
shr ebx, cl
test ebx, 2 ; bit 1+2*index = G0..G3, global break enable
jnz .errret2
test ch, ch
jns .new
; clear breakpoint
movzx ecx, cl
add ecx, ecx
and dword [eax+ecx*2], 0 ; clear DR<i>
btr dword [eax+10h], ecx ; clear L<i> bit
test byte [eax+10h], 55h
jnz .okret
imul eax, ebp, tss_step/32
and byte [eax + tss_data + l.trap - tss_sceleton], not 1
.okret:
and dword [esp+36], 0
sti
ret
.errret:
sti
mov dword [esp+36], 1
ret
.errret2:
sti
mov dword [esp+36], 2
ret
.new:
; add new breakpoint
; cl=index; ch=flags; edx=address
test ch, 0xF0
jnz .errret
mov bl, ch
and bl, 3
cmp bl, 2
jz .errret
mov bl, ch
shr bl, 2
cmp bl, 2
jz .errret
test dl, bl
jnz .errret
or byte [eax+10h+1], 3 ; set GE and LE flags
movzx ebx, ch
movzx ecx, cl
add ecx, ecx
bts dword [eax+10h], ecx ; set L<i> flag
add ecx, ecx
mov [eax+ecx], edx ; set DR<i>
shl ebx, cl
mov edx, 0xF
shl edx, cl
not edx
and [eax+10h+2], dx
or [eax+10h+2], bx ; set R/W and LEN fields
imul eax, ebp, tss_step/32
or byte [eax + tss_data + l.trap - tss_sceleton], 1
jmp .okret
 
debug_read_process_memory:
; in:
; ebx=pid
; ecx=length
; esi->buffer in debugger
; edx=address in debuggee
; out: [esp+36]=sizeof(read)
; destroys all
add esi, std_application_base_address
push ebx
mov ebx, esi
call check_region
pop ebx
dec eax
jnz .err
call get_debuggee_slot
jc .err
shr eax, 5
mov ebx, esi
call read_process_memory
sti
mov dword [esp+36], eax
ret
.err:
or dword [esp+36], -1
ret
 
debug_write_process_memory:
; in:
; ebx=pid
; ecx=length
; esi->buffer in debugger
; edx=address in debuggee
; out: [esp+36]=sizeof(write)
; destroys all
add esi, std_application_base_address
push ebx
mov ebx, esi
call check_region
pop ebx
dec eax
jnz debug_read_process_memory.err
call get_debuggee_slot
jc debug_read_process_memory.err
shr eax, 5
mov ebx, esi
call write_process_memory
sti
mov [esp+36], eax
ret
 
debugger_notify:
; in: eax=debugger slot
; ecx=size of debug message
; [esp+4]..[esp+4+ecx]=message
; interrupts must be disabled!
; destroys all general registers
; interrupts remain disabled
xchg ebp, eax
mov edi, [timer_ticks]
add edi, 500 ; 5 sec timeout
.1:
mov eax, ebp
shl eax, 8
mov edx, [0x80000+eax+APPDATA.dbg_event_mem]
test edx, edx
jz .ret
; read buffer header
push ecx
push eax
push eax
mov eax, ebp
mov ebx, esp
mov ecx, 8
call read_process_memory
cmp eax, ecx
jz @f
add esp, 12
jmp .ret
@@:
cmp dword [ebx], 0
jg @f
.2:
pop ecx
pop ecx
pop ecx
cmp dword [0x3000], 1
jnz .notos
cmp [timer_ticks], edi
jae .ret
.notos:
sti
call change_task
cli
jmp .1
@@:
mov ecx, [ebx+8]
add ecx, [ebx+4]
cmp ecx, [ebx]
ja .2
; advance buffer position
push ecx
mov ecx, 4
sub ebx, ecx
mov eax, ebp
add edx, ecx
call write_process_memory
pop eax
; write message
mov eax, ebp
add edx, ecx
add edx, [ebx+8]
add ebx, 20
pop ecx
pop ecx
pop ecx
call write_process_memory
; new debug event
mov eax, ebp
shl eax, 8
or byte [0x80000+eax+APPDATA.event_mask+1], 1 ; set flag 100h
.ret:
ret
 
debug_exc:
; int 1 = #DB
save_ring3_context
cld
mov ax, os_data
mov ds, ax
mov es, ax
mov eax, dr6
test ax, ax
jns @f
; this is exception from task switch
; set DRx registers for task and continue
mov eax, [0x3000]
shl eax, 8
add eax, 0x80000+APPDATA.dbg_regs
mov ecx, [eax+0]
mov dr0, ecx
mov ecx, [eax+4]
mov dr1, ecx
mov ecx, [eax+8]
mov dr2, ecx
mov ecx, [eax+0Ch]
mov dr3, ecx
xor ecx, ecx
mov dr6, ecx
mov ecx, [eax+10h]
mov dr7, ecx
restore_ring3_context
iretd
@@:
push eax
xor eax, eax
mov dr6, eax
; test if debugging
cli
mov eax, [0x3000]
shl eax, 8
mov eax, [0x80000+eax+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
add esp, 28h+4
mov [error_interrupt], 1
call show_error_parameters
mov edx, [0x3010]
mov byte [edx+TASKDATA.state], 4
jmp change_task
.debug:
; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID
pop edx
mov ebx, dr7
mov cl, not 1
.l1:
test bl, 1
jnz @f
and dl, cl
@@:
shr ebx, 2
add cl, cl
inc ecx
cmp cl, not 10h
jnz .l1
push edx ; DR6 image
mov ecx, [0x3010]
push dword [ecx+TASKDATA.pid] ; PID
push 12
pop ecx
push 3 ; 3 = debug exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [0x3010]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task
restore_ring3_context
iretd
/kernel/branches/gfx_kernel/core/mem.inc
0,0 → 1,469
if ~defined mem_inc
mem_inc_fix:
mem_inc fix mem_inc_fix
;include "memmanag.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;High-level memory management in MenuetOS.
;;It uses memory manager in memmanager.inc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
second_base_address=0xC0000000
std_application_base_address=0x10000000
general_page_table_ dd 0
general_page_table=general_page_table_+second_base_address
;-----------------------------------------------------------------------------
create_general_page_table:
;input
; none
;output
; none
;Procedure create general page directory and write
;it address to [general_page_table].
pushad
mov eax,1 ;alloc 1 page
mov ebx,general_page_table ;write address to [general_page_table]
call MEM_Alloc_Pages ;allocate page directory
mov eax,[general_page_table]
call MEM_Get_Linear_Address ;eax - linear address of page directory
mov edi,eax
mov ebx,eax ;copy address of page directory to safe place
xor eax,eax
mov ecx,4096/4
cld
rep stosd ;clear page directory
mov eax,4
mov edx,eax
call MEM_Alloc_Pages ;alloc page tables for 0x0-0x1000000 region
cmp eax,edx
jnz $ ;hang if not enough memory
;fill page tables
xor esi,esi
mov ebp,7
.loop:
;esi - number of page in page directory
;ebp - current page address
;ebx - linear address of page directory
mov eax,[ebx+4*esi]
add dword [ebx+4*esi],7 ;add flags to address of page table
call MEM_Get_Linear_Address
;eax - linear address of page table
mov ecx,4096/4
;ecx (counter) - number of pages in page table
;current address=4Mb*esi
.loop1:
mov [eax],ebp ;write page address (with flags) in page table
add eax,4
add ebp,4096 ;size of page=4096 bytes
loop .loop1
inc esi ;next page directory entry
cmp esi,edx
jnz .loop
;map region 0x80000000-0x807fffff to LFB
mov eax,2 ;size of the region is 4Mb so only 1 page table needed
mov edx,ebx ;ebx still contains linear address of the page directory
add ebx,0x800
call MEM_Alloc_Pages ;alloc page table for the region
mov eax,[ebx]
add dword [ebx],7 ;add flags
call MEM_Get_Linear_Address ;get linear address of the page table
mov ecx,4096/4 ;number of pages in page table
mov edi,[0xfe80]
add edi,7
.loop3:
;eax - linear address of page table
;edi - current linear address with flags
mov [eax],edi
add eax,4
add edi,4096
loop .loop3
mov eax,[ebx+4]
call MEM_Get_Linear_Address
add dword [ebx+4],7
mov ecx,4096/4
.loop31:
mov [eax],edi
add eax,4
add edi,4096
loop .loop31
;map region 0xC0000000-* to 0x0-*
mov esi,edx ;esi=linear address of the page directory
lea edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00)
mov ecx,4
rep movsd ;first 16Mb of the region mapped as 0x0-0x1000000 block
mov eax,[0xfe8c] ;eax=memory size
add eax,0x3fffff
shr eax,22
mov esi,eax ;calculate number of entries in page directory
sub esi,4 ;subtract entries for first 16Mb.
mov ebp,0x1000000+7 ;start physical address with flags
;mapping memory higher than 16Mb
.loop4:
;esi (counter) - number of entries in page directory
;edi - address of entry
test esi,esi
jle .loop4end
call MEM_Alloc_Page ;alloc page table for entry in page directory
mov [edi],eax
add dword [edi],7 ;write physical address of page table in page directory
add edi,4 ;move entry pointer
call MEM_Get_Linear_Address
mov ecx,eax
xor edx,edx
.loop5:
;ecx - linear address of page table
;edx - index of page in page table
;ebp - current mapped physical address with flags
mov [ecx+4*edx],ebp ;write address of page in page table
add ebp,0x1000 ;move to next page
inc edx
cmp edx,4096/4
jl .loop5
dec esi
jmp .loop4
.loop4end:
.set_cr3:
;set value of cr3 register to the address of page directory
mov eax,[general_page_table]
add eax,8+16 ;add flags
mov cr3,eax ;now we have full access paging
popad
ret
;-----------------------------------------------------------------------------
simple_clone_cr3_table:
;Parameters:
; eax - physical address of cr3 table (page directory)
;result:
; eax - physical address of clone of cr3 table.
;Function copy only page directory.
push ecx
push edx
push esi
push edi
call MEM_Get_Linear_Address
;eax - linear address of cr3 table
mov esi,eax
call MEM_Alloc_Page
test eax,eax
jz .failed
;eax - physical address of new page diretory
mov edx,eax
call MEM_Get_Linear_Address
mov edi,eax
mov ecx,4096/4
cld
;esi - address of old page directory
;edi - address of new page directory
rep movsd ;copy page directory
mov eax,edx
.failed:
pop edi
pop esi
pop edx
pop ecx
ret
;-----------------------------------------------------------------------------
create_app_cr3_table:
;Parameters:
; eax - slot of process (index in 0x3000 table)
;result:
; eax - physical address of table.
;This function create page directory for new process and
;write it physical address to offset 0xB8 of extended
;process information.
push ebx
 
mov ebx,eax
mov eax,[general_page_table]
call simple_clone_cr3_table ;clone general page table
shl ebx,8
mov [second_base_address+0x80000+ebx+APPDATA.dir_table],eax ;save address of page directory
pop ebx
ret
;-----------------------------------------------------------------------------
get_cr3_table:
;Input:
; eax - slot of process
;result:
; eax - physical address of page directory
shl eax,8 ;size of process extended information=256 bytes
mov eax,[second_base_address+0x80000+eax+APPDATA.dir_table]
ret
;-----------------------------------------------------------------------------
dispose_app_cr3_table:
;Input:
; eax - slot of process
;result:
; none
;This procedure frees page directory,
;page tables and all memory of process.
pushad
mov ebp,eax
;ebp = process slot in the procedure.
shl eax,8
mov eax,[second_base_address+0x80000+eax+APPDATA.dir_table]
mov ebx,eax
;ebx = physical address of page directory
call MEM_Get_Linear_Address
mov edi,eax
;edi = linear address of page directory
mov eax,[edi+(std_application_base_address shr 20)]
and eax,not (4096-1)
call MEM_Get_Linear_Address
mov esi,eax
;esi = linear address of first page table
 
;search threads
; mov ecx,0x200
xor edx,edx
mov eax,0x2
.loop:
;eax = current slot of process
mov ecx,eax
shl ecx,5
cmp byte [second_base_address+0x3000+ecx+TASKDATA.state],9 ;if process running?
jz .next ;skip empty slots
shl ecx,3
cmp [second_base_address+0x80000+ecx+APPDATA.dir_table],ebx ;compare page directory addresses
jnz .next
inc edx ;thread found
.next:
inc eax
cmp eax,[0x3004] ;exit loop if we look through all processes
jle .loop
;edx = number of threads
;our process is zombi so it isn't counted
cmp edx,1
jg .threadsexists
;if there isn't threads then clear memory.
add edi,std_application_base_address shr 20
.loop1:
;edi = linear address of current directory entry
;esi = linear address of current page table
test esi,esi
jz .loop1end
xor ecx,ecx
.loop2:
;ecx = index of page
mov eax,[esi+4*ecx]
test eax,eax
jz .loopend ;skip empty entries
and eax,not (4096-1) ;clear flags
push ecx
call MEM_Free_Page ;free page
pop ecx
.loopend:
inc ecx
cmp ecx,1024 ;there are 1024 pages in page table
jl .loop2
mov eax,esi
call MEM_Free_Page_Linear ;free page table
.loop1end:
add edi,4 ;move to next directory entry
mov eax,[edi]
and eax,not (4096-1)
call MEM_Get_Linear_Address
mov esi,eax ;calculate linear address of new page table
test edi,0x800
jz .loop1 ;test if we at 0x80000000 address?
and edi,not (4096-1) ;clear offset of page directory entry
mov eax,edi
call MEM_Free_Page_Linear ;free page directory
popad
ret
.threadsexists: ;do nothing
popad ;last thread will free memory
ret
;-----------------------------------------------------------------------------
mem_alloc_specified_region:
;eax - linear directory address
;ebx - start address (aligned to 4096 bytes)
;ecx - size in pages
;result:
; eax=1 - ok
; eax=0 - failed
;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval.
pushad
mov ebp,ebx ;save start address for recoil
mov esi,eax
.gen_loop:
;esi = linear directory address
;ebx = current address
;ecx = remaining size in pages
mov edx,ebx
shr edx,22
mov edi,[esi+4*edx] ;find directory entry for current address
test edi,edi
jnz .table_exists ;check if page table allocated
call MEM_Alloc_Page ;alloc page table
test eax,eax
jz .failed
mov [esi+4*edx],eax
add dword [esi+4*edx],7 ;write it address with flags
call MEM_Get_Linear_Address
call mem_fill_page ;clear page table
jmp .table_linear
.table_exists:
;calculate linear address of page table
mov eax,edi
and eax,not (4096-1) ;clear flags
call MEM_Get_Linear_Address
.table_linear:
;eax = linear address of page table
mov edx,ebx
shr edx,12
and edx,(1024-1) ;calculate index in page table
mov edi,eax
.loop:
;edi = linear address of page table
;edx = current page table index
;ecx = remaining size in pages
;ebx = current address
test ecx,ecx
jle .endloop1 ;all requested pages allocated
call MEM_Alloc_Page ;alloc new page
test eax,eax
jz .failed
mov [edi+4*edx],eax
add dword [edi+4*edx],7 ;write it address with flags
call MEM_Get_Linear_Address
call mem_fill_page ;clear new page
;go to next page table entry
dec ecx
add ebx,4096
inc edx
test edx,(1024-1)
jnz .loop
jmp .gen_loop
.endloop1:
popad
mov eax,1 ;ok
ret
.failed:
;calculate data for recoil
sub ebx,ebp
shr ebx,12
mov ecx,ebx ;calculate number of allocated pages
mov eax,esi ;restore linear address of page directory
mov ebx,ebp ;restore initial address
call mem_free_specified_region ;free all allocated pages
popad
xor eax,eax ;fail
ret
;-----------------------------------------------------------------------------
mem_fill_page:
;Input:
; eax - address
;result:
; none
;set to zero 4096 bytes at eax address.
push ecx
push edi
mov edi,eax
mov ecx,4096/4
xor eax,eax
rep stosd
lea eax,[edi-4096]
pop edi
pop ecx
ret
;-----------------------------------------------------------------------------
mem_free_specified_region:
;eax - linear page directory address
;ebx - start address (aligned to 4096 bytes)
;ecx - size in pages
;result - none
;Free pages in [ebx;ebx+4096*ecx) region.
pushad
mov esi,eax
xor ebp,ebp
.gen_loop:
;esi = linear page directory address
;ebx = current address
;ecx = remaining pages
;ebp = 0 for first page table
; 1 otherwise
mov edx,ebx
shr edx,22
mov eax,[esi+4*edx] ;find directory entry for current address
and eax,not (4096-1)
test eax,eax
jnz .table_exists
;skip absent page tables
mov edx,ebx
shr edx,12
and edx,(1024-1) ;edx - index of current page
add ebx,1 shl 22
add ecx,edx
and ebx,not ((1 shl 22)-1)
mov ebp,1 ;set flag
sub ecx,1024 ;ecx=ecx-(1024-edx)
jg .gen_loop
popad
ret
.table_exists:
call MEM_Get_Linear_Address
;eax - linear address of table
mov edx,ebx
shr edx,12
and edx,(1024-1) ;edx - index of current page
mov edi,eax
.loop:
;edi = linear address of page table entry
;edx = index of page table entry
;ecx = remaining pages
test ecx,ecx
jle .endloop1
mov eax,[edi+4*edx]
and eax,not (4096-1)
call MEM_Free_Page ;free page
mov dword [edi+4*edx],0 ;and clear page table entry
dec ecx
inc edx
cmp edx,1024
jl .loop
test ebp,ebp
jz .first_page
mov eax,edi
call MEM_Free_Page_Linear ;free page table
mov edx,ebx
shr edx,22
mov dword [esi+4*edx],0 ;and clear page directory entry
.first_page:
add ebx,1 shl 22
and ebx,not ((1 shl 22)-1) ;calculate new current address
mov ebp,1 ;set flag
jmp .gen_loop
.endloop1:
popad
ret
end if
/kernel/branches/gfx_kernel/core/memmanag.inc
0,0 → 1,833
if ~defined memmanager_inc
memmanager_inc_fix:
memmanager_inc fix memmanager_inc_fix
;for testing in applications
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Memory allocator for MenuetOS kernel
;; Andrey Halyavin, halyavin@land.ru 2005
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; heap block structure -
;; you can handle several ranges of
;; pages simultaneosly.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.heap_linear_address equ 0
.heap_block_size equ 4
.heap_physical_address equ 8
.heap_reserved equ 12
.heap_block_info equ 16
max_heaps equ 8
.range_info equ 36
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; memory manager data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
uglobal
MEM_heap_block rd .heap_block_info*max_heaps/4
MEM_heap_count rd 1
MEM_cli_count rd 1
MEM_cli_prev rd 1
MEM_FreeSpace rd 1
; MEM_AllSpace rd 1
endg
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Init
;;Initialize memory manager structures.
;;Must be called first.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEM_Init:
push eax
xor eax,eax
mov [MEM_cli_prev],eax ;init value = 0
dec eax
mov [MEM_cli_count],eax ;init value = -1
pop eax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Heap_Lock
;;Wait until all operations with heap will be finished.
;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations
;;with heap are forbidden.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEM_Heap_Lock:
pushfd
cli
inc dword [MEM_cli_count]
jz MEM_Heap_First_Lock
add esp,4
ret
MEM_Heap_First_Lock: ;save interrupt flag
shr dword [esp],9
and dword [esp],1
pop dword [MEM_cli_prev]
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Heap_UnLock
;;After this routine operations with heap are allowed.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEM_Heap_UnLock:
dec dword [MEM_cli_count]
js MEM_Heap_UnLock_last
ret
MEM_Heap_UnLock_last:
cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag
jz MEM_Heap_UnLock_No_sti
sti
MEM_Heap_UnLock_No_sti:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Add_Heap
;;Add new range to memory manager.
;;eax - linear address
;;ebx - size in pages
;;ecx - physical address
;;Result:
;; eax=1 - success
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEM_Add_Heap:
push edx
call MEM_Heap_Lock
mov edx,[MEM_heap_count]
cmp edx,max_heaps
jz MEM_Add_Heap_Error
inc dword [MEM_heap_count]
shl edx,4
mov [MEM_heap_block+edx+.heap_linear_address],eax
mov [MEM_heap_block+edx+.heap_block_size],ebx
shl dword [MEM_heap_block+edx+.heap_block_size],12
mov [MEM_heap_block+edx+.heap_physical_address],ecx
lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table
and edx,0xFFFFF000
 
push edi
mov edi,edx
shr edi,12
sub edi,ebx ;edi=-free space
sub [MEM_FreeSpace],edi
; sub [MEM_AllSpace],edi
 
mov [eax],eax
add [eax],edx ;first 4 bytes - pointer to first free page
;clean page info area
lea edi,[eax+4]
mov ecx,edx
shr ecx,2
push eax
xor eax,eax
rep stosd
pop eax
pop edi
;create free pages list.
mov ecx,[eax]
shl ebx,12
add eax,ebx ;eax - address after block
MEM_Add_Heap_loop:
add ecx,4096
mov [ecx-4096],ecx ;set forward pointer
cmp ecx,eax
jnz MEM_Add_Heap_loop
mov dword [ecx-4096],0 ;set end of list
MEM_Add_Heap_ret:
call MEM_Heap_UnLock
pop edx
ret
MEM_Add_Heap_Error:
xor eax,eax
jmp MEM_Add_Heap_ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Get_Physical_Address
;;Translate linear address to physical address
;;Parameters:
;; eax - linear address
;;Result:
;; eax - physical address
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Get_Physical_Address
MEM_Get_Physical_Address:
push ecx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Get_Physical_Address_loop:
sub eax,[MEM_heap_block+ecx+.heap_linear_address]
jl MEM_Get_Physical_Address_next
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jge MEM_Get_Physical_Address_next
add eax,[MEM_heap_block+ecx+.heap_physical_address]
jmp MEM_Get_Physical_Address_loopend
MEM_Get_Physical_Address_next:
add eax,[MEM_heap_block+ecx+.heap_linear_address]
sub ecx,16
jns MEM_Get_Physical_Address_loop
xor eax,eax ;address not found
MEM_Get_Physical_Address_loopend:
call MEM_Heap_UnLock
pop ecx
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Get_Linear_Address
;;Translate physical address to linear address.
;;Parameters:
;; eax - physical address
;;Result:
;; eax - linear address
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Get_Linear_Address
MEM_Get_Linear_Address:
push ecx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Get_Linear_Address_loop:
sub eax,[MEM_heap_block+ecx+.heap_physical_address]
jl MEM_Get_Linear_Address_Next
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jge MEM_Get_Linear_Address_Next
add eax,[MEM_heap_block+ecx+.heap_linear_address]
call MEM_Heap_UnLock
pop ecx
ret
MEM_Get_Linear_Address_Next:
add eax,[MEM_heap_block+ecx+.heap_physical_address]
sub ecx,16
jns MEM_Get_Linear_Address_loop
call MEM_Heap_UnLock
pop ecx
xor eax,eax ;address not found
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Alloc_Page
;;Allocate and add reference to page
;;Result:
;; eax<>0 - physical address of page
;; eax=0 - not enough memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Alloc_Page
MEM_Alloc_Page:
push ecx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Alloc_Page_loop:
push ecx
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
cmp dword [ecx],0
jz MEM_Alloc_Page_loopend
mov eax,[ecx]
push dword [eax]
pop dword [ecx]
sub eax,ecx
push eax
shr eax,10
mov word [ecx+.range_info+eax],1
pop eax
pop ecx
add eax,[MEM_heap_block+ecx+.heap_physical_address]
dec [MEM_FreeSpace]
jmp MEM_Alloc_Page_ret
MEM_Alloc_Page_loopend:
pop ecx
sub ecx,16
jns MEM_Alloc_Page_loop
xor eax,eax
MEM_Alloc_Page_ret:
call MEM_Heap_UnLock
pop ecx
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Alloc_Page_Linear
;;Allocate and add reference to page
;;Result:
;; eax<>0 - linear address of page
;; eax=0 - not enough memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Alloc_Page_Linear
MEM_Alloc_Page_Linear:
push ecx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Alloc_Page_Linear_loop:
push ecx
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
cmp dword [ecx],0
jz MEM_Alloc_Page_Linear_loopend
mov eax,[ecx]
push dword [eax]
pop dword [ecx]
push eax
sub eax,ecx
shr eax,10
mov word [ecx+.range_info+eax],1
pop eax
pop ecx
dec [MEM_FreeSpace]
jmp MEM_Alloc_Page_Linear_ret
MEM_Alloc_Page_Linear_loopend:
pop ecx
sub ecx,16
jns MEM_Alloc_Page_Linear_loop
xor eax,eax
MEM_Alloc_Page_Linear_ret:
call MEM_Heap_UnLock
pop ecx
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Free_Page
;;Remove reference and free page if number of
;;references is equal to 0
;;Parameters:
;; eax - physical address of page
;;Result:
;; eax - 1 success
;; eax - 0 failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if (used MEM_Free_Page) | (used MEM_Free_Page_Linear)
MEM_Free_Page:
test eax,eax
jz MEM_Free_Page_Zero
test eax,0xFFF
jnz MEM_Free_Page_Not_Aligned
push ebx
push ecx
push edx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Free_Page_Heap_loop:
sub eax,[MEM_heap_block+ecx+.heap_physical_address]
js MEM_Free_Page_Heap_loopnext
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jl MEM_Free_Page_Heap_loopend
MEM_Free_Page_Heap_loopnext:
add eax,[MEM_heap_block+ecx+.heap_physical_address]
sub ecx,16
jns MEM_Free_Page_Heap_loop
xor eax,eax
inc eax
jmp MEM_Free_Page_ret
MEM_Free_Page_Heap_loopend:
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
mov ebx,eax
add eax,ecx
shr ebx,10
mov edx,[ecx+.range_info+ebx]
test edx,0x80000000
jnz MEM_Free_Page_Bucket
test dx,dx
jz MEM_Free_Page_Error
dec word [ecx+.range_info+ebx]
jnz MEM_Free_Page_OK
MEM_Free_Page_Bucket:
push dword [ecx]
mov [ecx],eax
pop dword [eax]
mov dword [ecx+.range_info+ebx],0
inc [MEM_FreeSpace]
MEM_Free_Page_OK:
mov eax,1
MEM_Free_Page_ret:
call MEM_Heap_UnLock
pop edx
pop ecx
pop ebx
ret
MEM_Free_Page_Error:
xor eax,eax
jmp MEM_Free_Page_ret
MEM_Free_Page_Zero:
inc eax
ret
MEM_Free_Page_Not_Aligned:
xor eax,eax
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Free_Page_Linear
;;Remove reference and free page if number of
;;references is equal to 0
;;Parameters:
;; eax - linear address of page
;;Result:
;; eax - 1 success
;; eax - 0 failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Free_Page_Linear
MEM_Free_Page_Linear:
test eax,eax
jz MEM_Free_Page_Zero
test eax,0xFFF
jnz MEM_Free_Page_Not_Aligned
push ebx
push ecx
push edx
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Free_Page_Linear_Heap_loop:
sub eax,[MEM_heap_block+ecx+.heap_linear_address]
js MEM_Free_Page_Linear_Heap_loopnext
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jl MEM_Free_Page_Heap_loopend
MEM_Free_Page_Linear_Heap_loopnext:
add eax,[MEM_heap_block+ecx+.heap_linear_address]
sub ecx,16
jns MEM_Free_Page_Linear_Heap_loop
xor eax,eax
inc eax
jmp MEM_Free_Page_ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Alloc_Pages
;;Allocates set of pages.
;;Parameters:
;; eax - number of pages
;; ebx - buffer for physical addresses
;;Result:
;; eax - number of allocated pages
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Alloc_Pages
MEM_Alloc_Pages:
push eax
push ebx
push ecx
mov ecx,eax
test ecx,ecx
jz MEM_Alloc_Pages_ret
MEM_Alloc_Pages_loop:
call MEM_Alloc_Page
test eax,eax
jz MEM_Alloc_Pages_ret
mov [ebx],eax
add ebx,4
dec ecx
jnz MEM_Alloc_Pages_loop
MEM_Alloc_Pages_ret:
sub [esp+8],ecx
pop ecx
pop ebx
pop eax
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Alloc_Pages_Linear
;;Allocates set of pages.
;;Parameters:
;; eax - number of pages
;; ebx - buffer for linear addresses
;;Result:
;; eax - number of allocated pages
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Alloc_Pages_Linear
MEM_Alloc_Pages_Linear:
push eax
push ebx
push ecx
mov ecx,eax
test ecx,ecx
jz MEM_Alloc_Pages_Linear_ret
MEM_Alloc_Pages_Linear_loop:
call MEM_Alloc_Page_Linear
test eax,eax
jz MEM_Alloc_Pages_Linear_ret
mov [ebx],eax
add ebx,4
dec ecx
jnz MEM_Alloc_Pages_Linear_loop
MEM_Alloc_Pages_Linear_ret:
sub [esp+8],ecx
pop ecx
pop ebx
pop eax
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Free_Pages
;;Parameters:
;; eax - number of pages
;; ebx - array of addresses
;;Result:
;; eax=1 - succcess
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Free_Pages
MEM_Free_Pages:
push ebx
push ecx
mov ecx,eax
test ecx,ecx
jz MEM_Free_Pages_ret
MEM_Free_Pages_loop:
mov eax,[ebx]
call MEM_Free_Page
add ebx,4
test eax,eax
jz MEM_Free_Pages_ret
dec ecx
jnz MEM_Free_Pages_loop
MEM_Free_Pages_ret:
pop ecx
pop ebx
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Free_Pages_Linear
;;Parameters:
;; eax - number of pages
;; ebx - array of addresses
;;Result:
;; eax=1 - succcess
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Free_Pages_Linear
MEM_Free_Pages_Linear:
push ebx
push ecx
mov ecx,eax
test ecx,ecx
jz MEM_Free_Pages_Linear_ret
MEM_Free_Pages_Linear_loop:
mov eax,[ebx]
call MEM_Free_Page_Linear
add ebx,4
test eax,eax
jz MEM_Free_Pages_Linear_ret
dec ecx
jnz MEM_Free_Pages_Linear_loop
MEM_Free_Pages_Linear_ret:
pop ecx
pop ebx
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Get_Heap_Number
;;Calculate number of heap which pointer belongs to.
;;Parameter:
;; eax - address
;;Result:
;; ecx - number of heap*16.
;; eax=0 if address not found.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Get_Heap_Number
MEM_Get_Heap_Number:
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Get_Heap_loop:
sub eax,[MEM_heap_block+ecx+.heap_physical_address]
jl MEM_Get_Heap_loopnext
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jl MEM_Get_Heap_loopend
MEM_Get_Heap_loopnext:
add eax,[MEM_heap_block+ecx+.heap_physical_address]
sub ecx,16
jns MEM_Get_Heap_loop
call MEM_Heap_UnLock
xor eax,eax
ret
MEM_Get_Heap_loopend:
add eax,[MEM_heap_block+ecx+.heap_physical_address]
call MEM_Heap_UnLock
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Get_Heap_Number_Linear
;;Calculate number of heap which pointer belongs to.
;;Parameter:
;; eax - address
;;Result:
;; ecx - number of heap*16.
;; eax=0 if address not found.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Get_Heap_Number_Linear
MEM_Get_Heap_Number_Linear:
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Get_Heap_Linear_loop:
sub eax,[MEM_heap_block+ecx+.heap_linear_address]
jl MEM_Get_Heap_Linear_loopnext
cmp eax,[MEM_heap_block+ecx+.heap_block_size]
jl MEM_Get_Heap_Linear_loopend
MEM_Get_Heap_Linear_loopnext:
add eax,[MEM_heap_block+ecx+.heap_linear_address]
sub ecx,16
jns MEM_Get_Heap_Linear_loop
call MEM_Heap_UnLock
xor eax,eax
ret
MEM_Get_Heap_Linear_loopend:
add eax,[MEM_heap_block+ecx+.heap_linear_address]
call MEM_Heap_UnLock
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Alloc
;;Allocate small region.
;;Parameters:
;; eax - size (0<eax<=4096)
;;Result:
;; eax - linear address
;; eax=0 - not enough memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Alloc
MEM_Alloc:
;find chain
test eax,eax
jng MEM_Alloc_Wrong_Size
cmp eax,4096
jg MEM_Alloc_Wrong_Size
push ebx
push ecx
push edx
push esi
dec eax
shr eax,4
xor edx,edx
MEM_Alloc_Find_Size:
add edx,4
shr eax,1
jnz MEM_Alloc_Find_Size
MEM_Alloc_Size_Found:
mov ecx,edx
shr ecx,2
add ecx,4
mov eax,1
shl eax,cl
mov esi,eax
;esi - block size
;edx - offset
call MEM_Heap_Lock
mov ecx,[MEM_heap_count]
dec ecx
shl ecx,4
MEM_Alloc_Find_Heap:
mov eax,[MEM_heap_block+ecx+.heap_linear_address]
cmp dword [eax+edx],0
jnz MEM_Alloc_Use_Existing
sub ecx,16
jns MEM_Alloc_Find_Heap
;create new bucket page
call MEM_Alloc_Page_Linear
call MEM_Get_Heap_Number_Linear
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
mov [ecx+edx],eax
lea ebx,[eax+4096]
MEM_Alloc_List_loop:
mov [eax],eax
mov [eax+4],eax
add [eax],esi
sub [eax+4],esi
add eax,esi
cmp eax,ebx
jnz MEM_Alloc_List_loop
sub ebx,esi
mov dword [ebx],0
sub eax,4096
mov dword [eax+4],0
mov eax,ecx
MEM_Alloc_Use_Existing:
mov ebx,eax
mov eax,[eax+edx]
mov ecx,[eax]
mov [ebx+edx],ecx
test ecx,ecx
jz MEM_Alloc_Became_Empty
mov dword [ecx+4],0
MEM_Alloc_Became_Empty:
mov ecx,eax
sub ecx,ebx
shr ecx,10
and ecx,0xFFFFFFFC
inc byte [ebx+.range_info+ecx+2]
shr edx,2
add edx,128
dec edx
mov [ebx+.range_info+ecx+3],dl
MEM_Alloc_ret:
call MEM_Heap_UnLock
pop esi
pop edx
pop ecx
pop ebx
ret
MEM_Alloc_Wrong_Size:
xor eax,eax
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Free
;;Parameters:
;; eax - linear address
;;Result:
;; eax=1 - success
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Free
MEM_Free:
test eax,eax
jz MEM_Free_Zero
push ebx
push ecx
push edx
push esi
push edi
push ebp
call MEM_Heap_Lock
call MEM_Get_Heap_Number_Linear
test eax,eax
jz MEM_Free_ret
mov edx,eax
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
sub edx,ecx
shr edx,10
and edx,0xFFFFFFFC
mov ebx,[ecx+.range_info+edx]
mov esi,ebx
shr esi,24
sub esi,128
mov edi,[ecx+4+4*esi]
mov [eax],edi
mov dword [eax+4],0
test edi,edi
jz MEM_Free_Empty_List
mov [edi+4],eax
MEM_Free_Empty_List:
mov [ecx+4+4*esi],eax
sub ebx,0x10000
mov [ecx+.range_info+edx],ebx
test ebx,0xFF0000
jnz MEM_Free_ret
;delete empty blocks on the page
lea edx,[esi+5]
and eax,0xFFFFF000
mov edi,eax
mov eax,1
xchg ecx,edx
shl eax,cl
mov ecx,edx
mov edx,eax
;edx - size of block
;edi - start of page
mov eax,edi
lea ebx,[eax+4096]
MEM_Free_Block_loop:
cmp dword [eax+4],0
jnz MEM_Free_Block_Not_First
mov ebp,dword [eax]
mov [ecx+4+4*esi],ebp
test ebp,ebp
jz MEM_Free_Block_Last
mov dword [ebp+4],0
MEM_Free_Block_Last:
jmp MEM_Free_Block_loop_end
MEM_Free_Block_Not_First:
mov ebp,dword [eax]
push ebp
mov ebp,dword [eax+4]
pop dword [ebp]
mov ebp,dword [eax]
test ebp,ebp
jz MEM_Free_Block_loop_end
push dword [eax+4]
pop dword [ebp+4]
; jmp MEM_Free_Block_loop_end
MEM_Free_Block_loop_end:
add eax,edx
cmp eax,ebx
jnz MEM_Free_Block_loop
mov eax,edi
call MEM_Free_Page_Linear
MEM_Free_ret:
call MEM_Heap_UnLock
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
MEM_Free_Zero:
inc eax
ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Add_Reference
;; eax - physical address of page
;;Result:
;; eax=1 - success
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Add_Reference
MEM_Add_Reference:
push ebx
push ecx
call MEM_Heap_Lock
call MEM_Get_Heap_Number
test eax,eax
jz MEM_Add_Reference_ret
sub eax,[MEM_heap_block+ecx+.heap_physical_address]
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
shr eax,10
and eax,0xFFFFFFFC
test dword [ecx+eax+.range_info],0x80000000
jnz MEM_Add_Reference_failed
inc dword [ecx+eax+.range_info]
MEM_Add_Reference_ret:
call MEM_Heap_UnLock
pop ecx
pop ebx
ret
MEM_Add_Reference_failed:
xor eax,eax
jmp MEM_Add_Reference_ret
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;MEM_Add_Reference_Linear
;; eax - linear address of page
;;Result:
;; eax=1 - success
;; eax=0 - failed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if used MEM_Add_Reference_Linear
MEM_Add_Reference_Linear:
push ebx
push ecx
call MEM_Heap_Lock
call MEM_Get_Heap_Number_Linear
test eax,eax
jz MEM_Add_Reference_Linear_ret
mov ecx,[MEM_heap_block+ecx+.heap_linear_address]
sub eax,ecx
shr eax,10
and eax,0xFFFFFFFC
test dword [ecx+eax+.range_info],0x80000000
jnz MEM_Add_Reference_Linear_failed
inc dword [ecx+eax+.range_info]
mov eax,1
MEM_Add_Reference_Linear_ret:
call MEM_Heap_UnLock
pop ecx
pop ebx
ret
MEM_Add_Reference_Linear_failed:
xor eax,eax
jmp MEM_Add_Reference_Linear_ret
end if
end if ;memmanager.inc
/kernel/branches/gfx_kernel/core/newproce.inc
0,0 → 1,1615
if ~defined newprocess_inc
newprocess_inc_fix:
newprocess_inc fix newprocess_inc_fix
include "mem.inc"
include "memmanag.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Working with new types of processes.
;;Author: Khalyavin Andrey halyavin@land.ru
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iglobal
new_process_loading db 'K : New Process - loading',13,10,0
new_process_running db 'K : New Process - done',13,10,0
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0
endg
;-----------------------------------------------------------------------------
find_new_process_place:
;input:
; none
;result:
; eax=[new_process_place]<>0 - ok
; 0 - failed.
;This function find least empty slot.
;It doesn't increase [0x3004]!
mov eax,0x3000+second_base_address
push ebx
mov ebx,[0x3004]
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+TASKDATA.state],9 ;check process state, 9 means that process slot is empty
jnz .newprocessplace
.endnewprocessplace:
mov ebx,eax
sub eax,0x3000+second_base_address
shr eax,5 ;calculate slot index
cmp eax,256
jge .failed ;it should be <256
mov word [ebx+TASKDATA.state],9 ;set process state to 9 (for slot after hight boundary)
mov [new_process_place],eax ;save process slot
pop ebx
ret
.failed:
xor eax,eax
pop ebx
ret
;-----------------------------------------------------------------------------
safe_sti:
cmp byte [0xe000], 1
jne @f
sti
@@:ret
new_start_application_floppy:
;input:
; eax - pointer to filename
; ebx - parameters to pass
; edx - flags
;result:
; eax - pid of new process
; or 0 if call fails.
mov [appl_path],edi
pushad
mov esi,new_process_loading
call sys_msg_board_str ;write to debug board
;wait application_table_status mutex
.table_status:
cli
cmp [application_table_status],0
jz .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
;we can change system tables now
push edi
push ebx
push eax
call find_new_process_place ;find empty process slot
sti
test eax,eax
mov ecx, -0x20 ; too many processes
jz .failed
 
mov edi,eax
shl edi,8
add edi,0x80000
mov ecx,256/4
xor eax,eax
cld
rep stosd ;clean extended information about process
;set new process name
mov [appl_path_size],eax
pop eax
push eax
.find_last_byte:
cmp byte [eax],0
jz .find_last_byte_end
inc eax
inc [appl_path_size]
jmp .find_last_byte
.find_last_byte_end:
add [appl_path_size],24
sub eax,11 ;last 11 bytes = application name
; mov eax,[esp] ;eax - pointer to file name
mov ebx,[new_process_place]
shl ebx,8
add ebx,0x80000 + APPDATA.app_name
mov ecx,11
call memmove
;read header of file
mov eax,[esp]
mov ebx,1 ;index of first block
mov ecx,2 ;number of blocks
mov edx,0x90000 ;temp area
mov esi,12 ;file name length
mov edi,[esp+8]
; cli
call floppy_fileread ;read file from FD
; sti
mov ecx, eax
neg ecx
jnz .cleanfailed
;check MENUET signature
mov ecx, -0x1F ; not Menuet/Kolibri executable
cmp [0x90000],dword 'MENU'
jnz .cleanfailed
cmp [0x90004],word 'ET'
jnz .cleanfailed
call get_app_params ;parse header fields
test esi, esi
jz .cleanfailed
mov eax,[new_process_place]
inc ecx ; -0x1E = no memory
call create_app_cr3_table ;create page directory for new process
test eax,eax
jz .cleanfailed_mem
call MEM_Get_Linear_Address ;calculate linear address of it
mov ebx,std_application_base_address
mov ecx,[app_mem]
add ecx,4095
shr ecx,12
mov edx,eax
call mem_alloc_specified_region ;allocate memory for application
test eax,eax
mov ecx, -0x1E
jz .cleanfailed_mem1
mov eax,[edx+(std_application_base_address shr 20)]
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table
call MEM_Get_Linear_Address
mov edx,eax
;read file
mov ebx,1
mov esi,12 ;length of file name
.loop1:
;edx = linear address of current page table entry
;ebx = index of current block in file
push edx
mov eax,[edx]
and eax,not (4096-1)
call MEM_Get_Linear_Address
mov edx,eax ;read file block to current page
mov eax,[esp+4] ;restore pointer to file name
mov ecx,8 ;number of blocks read
push ebx
mov edi,[esp+16]
; cli
call floppy_fileread
;ebx=file size
; sti
pop ecx
shr ebx,9
cmp ecx,ebx
jg .endloop1 ;if end of file?
mov ebx,ecx
test eax,eax
jnz .endloop1 ;check io errors
pop edx
add ebx,8 ;go to next page
add edx,4
jmp .loop1
.endloop1:
add esp,8+4 ;pop linear address of page table entry and pointer to file name
call new_start_application_fl.add_app_parameters
mov [esp+28],eax
popad
ret
.cleanfailed_mem1:
;there is mem for directory entry, but there is no mem for pages
;so free directory entry
mov eax,[new_process_place]
shl eax,8
mov eax,[0x80000+eax+APPDATA.dir_table]
call MEM_Free_Page
.cleanfailed_mem:
;there is no mem for directory entry, display message.
mov esi,start_not_enough_memory
call sys_msg_board_str
.cleanfailed: ;clean process name
push ecx ; save error code
;can't read file, clean process name.
;this avoid problems with panel application.
mov edi,[new_process_place]
shl edi,8
add edi,0x80000 + APPDATA.app_name
mov ecx,11
mov eax,' '
cld
rep stosb
pop eax
.failed:
;no more slots
add esp,8+4
mov [application_table_status],0
mov [esp+1Ch], eax
popad
sti
ret
 
;-----------------------------------------------------------------------------
new_start_application_fl:
;input:
; eax - pointer to filename
; ebx - parameters to pass
; edx - flags
;result:
; eax - pid of new process
; or 0 if call fails.
mov [appl_path],edi
mov [appl_path_size],36
pushad
mov esi,new_process_loading
call sys_msg_board_str ;write to debug board
;wait application_table_status mutex
.table_status:
cli
cmp [application_table_status],0
jz .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
;we can change system tables now
push ebx
push eax
call find_new_process_place ;find empty process slot
call safe_sti
test eax,eax
mov ecx, -0x20 ; too many processes
jz .failed
 
mov edi,eax
shl edi,8
add edi,0x80000
mov ecx,256/4
xor eax,eax
cld
rep stosd ;clean extended information about process
;set new process name
mov eax,[esp] ;eax - pointer to file name
mov ebx,[new_process_place]
shl ebx,8
add ebx,0x80000 + APPDATA.app_name
mov ecx,11
call memmove
;read header of file
mov ebx,1 ;index of first block
mov ecx,2 ;number of blocks
mov edx,0x90000 ;temp area
mov esi,12 ;file name length
cli
call fileread ;read file from RD
call safe_sti
mov ecx, eax
neg ecx
jnz .cleanfailed
;check MENUET signature
mov ecx, -0x1F ; not Menuet/Kolibri executable
cmp [0x90000],dword 'MENU'
jnz .cleanfailed
cmp [0x90004],word 'ET'
jnz .cleanfailed
call get_app_params ;parse header fields
test esi,esi
jz .cleanfailed
mov eax,[new_process_place]
inc ecx ; -0x1E = no memory
call create_app_cr3_table ;create page directory for new process
test eax,eax
jz .cleanfailed_mem
call MEM_Get_Linear_Address ;calculate linear address of it
mov ebx,std_application_base_address
mov ecx,[app_mem]
add ecx,4095
shr ecx,12
mov edx,eax
call mem_alloc_specified_region ;allocate memory for application
test eax,eax
mov ecx, -0x1E
jz .cleanfailed_mem1
mov eax,[edx+(std_application_base_address shr 20)]
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table
call MEM_Get_Linear_Address
mov edx,eax
;read file
mov ebx,1
mov esi,12 ;length of file name
.loop1:
;edx = linear address of current page table entry
;ebx = index of current block in file
push edx
mov eax,[edx]
and eax,not (4096-1)
call MEM_Get_Linear_Address
mov edx,eax ;read file block to current page
mov eax,[esp+4] ;restore pointer to file name
mov ecx,8 ;number of blocks read
push ebx
cli
call fileread
;ebx=file size
call safe_sti
pop ecx
shr ebx,9
cmp ecx,ebx
jg .endloop1 ;if end of file?
mov ebx,ecx
test eax,eax
jnz .endloop1 ;check io errors
pop edx
add ebx,8 ;go to next page
add edx,4
jmp .loop1
.endloop1:
add esp,8 ;pop linear address of page table entry and pointer to file name
call .add_app_parameters
mov [esp+28],eax
popad
ret
.cleanfailed_mem1:
;there is mem for directory entry, but there is no mem for pages
;so free directory entry
mov eax,[new_process_place]
shl eax,8
mov eax,[0x80000+eax+APPDATA.dir_table]
call MEM_Free_Page
.cleanfailed_mem:
;there is no mem for directory entry, display message.
mov esi,start_not_enough_memory
call sys_msg_board_str
.cleanfailed: ;clean process name
push ecx ; save error code
;can't read file, clean process name.
;this avoid problems with panel application.
mov edi,[new_process_place]
shl edi,8
add edi,0x80000+APPDATA.app_name
mov ecx,11
mov eax,' '
cld
rep stosb
pop eax
.failed:
;no more slots
add esp,8
mov [application_table_status],0
mov [esp+1Ch], eax
popad
call safe_sti
ret
.add_app_parameters:
;input:
; [esp] - pointer to parameters
; [esp+4]-[esp+36] pushad registers.
;result
; eax - pid of new process
; or zero if failed
cli
mov ebx,[new_process_place]
cmp ebx,[0x3004]
jle .noinc
inc dword [0x3004] ;update number of processes
.noinc:
 
; mov ebx,[new_process_place]
;set 0x8c field of extended information about process
;(size of application memory)
shl ebx,8
mov eax,[app_mem]
mov [second_base_address+0x80000+APPDATA.mem_size+ebx],eax
;set 0x10 field of information about process
;(application base address)
; mov ebx,[new_process_place]
; shl ebx,5
shr ebx,3
mov dword [second_base_address+0x3000+ebx+TASKDATA.mem_start],std_application_base_address
 
;add command line parameters
.add_command_line:
mov edx,[app_i_param]
test edx,edx
jz .no_command_line ;application don't need parameters
mov eax,[esp+4]
test eax,eax
jz .no_command_line ;no parameters specified
;calculate parameter length
mov esi,eax
xor ecx,ecx
.command_line_len:
cmp byte [esi],0
jz .command_line_len_end
inc esi
inc ecx
cmp ecx,256
jl .command_line_len
.command_line_len_end:
;ecx - parameter length
;edx - address of parameters in new process address space
mov ebx,eax ;ebx - address of parameters in our address space
mov eax,[new_process_place]
call write_process_memory ;copy parameters to new process address space
.no_command_line:
;******************************************************************
mov edx,[app_i_icon]
test edx,edx
jz .no_command_line_1 ;application don't need path of file
mov ebx,[appl_path]
mov ecx,[appl_path_size]
mov eax,[new_process_place]
call write_process_memory ;copy path of file to new process address space
.no_command_line_1:
;******************************************************************
mov ebx,[new_process_place]
mov eax,ebx
shl ebx,5
add ebx,0x3000 ;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+TASKDATA.pid],eax ;set PID
mov ecx,ebx
add ecx,draw_data-0x3000 ;ecx - pointer to draw data
;set draw data to full screen
mov [ecx+RECT.left],dword 0
mov [ecx+RECT.top],dword 0
mov eax,[0xfe00]
mov [ecx+RECT.right],eax
mov eax,[0xfe04]
mov [ecx+RECT.bottom],eax
;set window state to 'normal' (non-minimized/maximized/rolled-up) state
mov [ecx+WDATA.fl_wstate],WSTATE_NORMAL
;set cr3 register in TSS of application
mov ecx,[new_process_place]
shl ecx,8
mov eax,[0x80000+APPDATA.dir_table+ecx]
add eax,8+16 ;add flags
mov [l.cr3],eax
mov eax,[app_start]
mov [l.eip],eax ;set eip in TSS
mov eax,[app_esp]
mov [l.esp],eax ;set stack in TSS
;gdt
;mov ebx,[new_process_place]
;shl ebx,3
mov ax,app_code ;ax - selector of code segment
;add ax,bx
mov [l.cs],ax
mov ax,app_data
;add ax,bx ;ax - selector of data segment
mov [l.ss],ax
mov [l.ds],ax
mov [l.es],ax
mov [l.fs],ax
mov ax,graph_data ;ax - selector of graphic segment
mov [l.gs],ax
mov [l.io],word 128
mov [l.eflags],dword 0x11202
mov [l.ss0],os_data
mov ebx,[new_process_place]
shl ebx,12
add ebx,sysint_stack_data+4096
mov [l.esp0],ebx
 
;copy tss to it place
mov eax,tss_sceleton
mov ebx,[new_process_place]
imul ebx,tss_step
add ebx,tss_data ;ebx - address of application TSS
mov ecx,120
call memmove
;Add IO access table - bit array of permitted ports
or eax,-1
mov edi,[new_process_place]
imul edi,tss_step
add edi,tss_data+128
mov ecx,2048
cld
rep stosd ;full access to 2048*8=16384 ports
mov ecx,ebx ;ecx - address of application TSS
mov edi,[new_process_place]
shl edi,3
;set TSS descriptor
mov [edi+gdts+tss0+0],word tss_step ;limit (size)
mov [edi+gdts+tss0+2],cx ;part of offset
mov eax,ecx
shr eax,16
mov [edi+gdts+tss0+4],al ;part of offset
mov [edi+gdts+tss0+7],ah ;part of offset
mov [edi+gdts+tss0+5],word 01010000b*256+11101001b ;system flags
 
;flush keyboard and buttons queue
mov [0xf400],byte 0
mov [0xf500],byte 0
 
mov edi,[new_process_place]
shl edi,5
add edi,window_data
mov ebx,[new_process_place]
movzx esi,word [0xC000+ebx*2]
lea esi,[0xC400+esi*2]
call windowactivate ;gui initialization
 
mov ebx,[new_process_place]
shl ebx,5
; set if debuggee
test byte [esp+28], 1
jz .no_debug
mov [0x3000+ebx+TASKDATA.state], 1 ; set process state - suspended
mov eax, [0x3000]
mov [0x80000+ebx*8+APPDATA.debugger_slot], eax ;set debugger PID - current
jmp .debug
.no_debug:
mov [0x3000+ebx+TASKDATA.state], 0 ; set process state - running
.debug:
mov esi,new_process_running
call sys_msg_board_str ;output information about succefull startup
; add esp,4 ;pop pointer to parameters
; popad
mov eax,[process_number] ;set result
mov [application_table_status],0 ;unlock application_table_status mutex
call safe_sti
ret 4
;-----------------------------------------------------------------------------
new_sys_threads:
;eax=1 - create thread
; ebx=thread start
; ecx=thread stack value
;result:
; eax=pid
xor edx,edx ; flags=0
pushad
cmp eax,1
jnz .ret ;other subfunctions
mov esi,new_process_loading
call sys_msg_board_str
;lock application_table_status mutex
.table_status:
cli
cmp [application_table_status],0
je .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
;find free process slot
 
call find_new_process_place
test eax,eax
jz .failed
;set parameters for thread
xor eax,eax
mov [app_i_param],eax
mov [app_i_icon],eax
mov [app_start],ebx
mov [app_esp],ecx
 
mov esi,[0x3000]
shl esi,8
add esi,0x80000+APPDATA.app_name
mov ebx,esi ;ebx=esi - pointer to extended information about current thread
mov edi,[new_process_place]
shl edi,8
add edi,0x80000
lea edx, [edi+APPDATA.app_name] ;edx=edi - pointer to extended infomation about new thread
mov ecx,256/4
rep stosd ;clean extended information about new thread
mov edi,edx
mov ecx,11
rep movsb ;copy process name
mov eax,[ebx+APPDATA.mem_size]
mov [app_mem],eax ;set memory size
mov eax,[ebx+APPDATA.dir_table]
mov dword [edx-APPDATA.app_name+APPDATA.dir_table],eax ;copy page directory
; mov eax,[new_process_place]
; mov ebx,[0x3000]
; call addreference_app_cr3_table
 
push 0 ;no parameters
call new_start_application_fl.add_app_parameters ;start thread
mov [esp+28],eax
popad
ret
.failed:
sti
popad
mov eax,-1
ret
.ret:
popad
ret
;-----------------------------------------------------------------------------
new_mem_resize:
;input:
; ebx - new size
;result:
; [esp+36]:=0 - normal
; [esp+36]:=1 - error
;This function set new application memory size.
mov esi,ebx ;save new size
add ebx,4095
and ebx,not (4096-1) ;round up size
mov ecx,[0x3000]
shl ecx,8
mov edx,[0x80000 + APPDATA.mem_size +ecx]
add edx,4095
and edx,not (4096-1) ;old size
mov eax,[0x80000 + APPDATA.dir_table+ecx]
call MEM_Get_Linear_Address
;eax - linear address of page directory
call MEM_Heap_Lock ;guarantee that two threads willn't
;change memory size simultaneously
cmp ebx,edx
; mov esi,ebx ;save new size
jg .expand
.free:
sub edx,ebx
jz .unlock ;do nothing
mov ecx,edx
shr ecx,12
add ebx,std_application_base_address
call mem_free_specified_region ;free unnecessary pages
jmp .unlock
 
.expand:
sub ebx,edx
mov ecx,ebx
shr ecx,12
mov ebx,edx
add ebx,std_application_base_address
call mem_alloc_specified_region ;alloc necessary pages
test eax,eax
jz .failed ;not enough memory
.unlock:
mov ebx,esi
mov eax,[0x3000]
shl eax,8
mov [eax+0x80000 + APPDATA.mem_size],ebx ;write new memory size
;search threads and update
;application memory size infomation
mov ecx,[eax+0x80000 + APPDATA.dir_table]
mov eax,2
.search_threads:
;eax = current slot
;ebx = new memory size
;ecx = page directory
cmp eax,[0x3004]
jg .search_threads_end
mov edx,eax
shl edx,5
cmp word [0x3000+edx+TASKDATA.state],9 ;if slot empty?
jz .search_threads_next
shl edx,3
cmp [edx+0x80000+APPDATA.dir_table],ecx ;if it is our thread?
jnz .search_threads_next
mov [edx+0x80000+APPDATA.mem_size],ebx ;update memory size
.search_threads_next:
inc eax
jmp .search_threads
.search_threads_end:
 
call MEM_Heap_UnLock
mov dword [esp+36],0
ret
.failed:
call MEM_Heap_UnLock
mov dword [esp+36],1
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,[0x3004]
shl ebx,5
mov ecx,2*32
.loop:
;ecx=offset of current process info entry
;ebx=maximum permitted offset
cmp byte [second_base_address+0x3000+ecx+TASKDATA.state],9
jz .endloop ;skip empty slots
cmp [second_base_address+0x3000+ecx+TASKDATA.pid],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
;-----------------------------------------------------------------------------
is_new_process:
;Input:
; eax - process slot
;Output:
; eax=1 - it is new process
; eax=0 - it is old process
; shl eax,5
; mov eax,[second_base_address+0x3000+eax+0x10]
; cmp eax,std_application_base_address ;check base address of application
; jz .new_process
; xor eax,eax
; ret
;.new_process:
mov eax,1
ret
;-----------------------------------------------------------------------------
write_process_memory:
;Input:
; eax - process slot
; ebx - buffer address
; ecx - buffer size
; edx - start address in other process
;Output:
; eax - number of bytes written
pushad
shl eax,8
mov eax,[0x80000+eax+APPDATA.dir_table]
call MEM_Get_Linear_Address
mov ebp,eax
;ebp=linear address of page directory of other process.
add edx,std_application_base_address ;convert to linear address
test ecx,ecx
jle .ret
.write_loop:
;ebx = current buffer address
;ecx>0 = current size
;edx = current address in other process
;ebp = linear address of page directory
 
call MEM_Heap_Lock ;cli
mov esi,edx
shr esi,22
mov eax,[ebp+4*esi] ;find page directory entry
and eax,not (4096-1) ;clear flags
test eax,eax
jz .page_not_found
call MEM_Get_Linear_Address ;calculate linear address of page table
test eax,eax
jz .page_not_found
mov esi,edx
shr esi,12
and esi,1023
mov eax,[eax+4*esi] ;find page table entry
and eax,not (4096-1)
test eax,eax
jz .page_not_found
call MEM_Get_Linear_Address ;calculate linear address of page
test eax,eax
jz .page_not_found
mov edi,eax
call MEM_Add_Reference_Linear;guarantee that page willn't disappear
call MEM_Heap_UnLock ;sti
mov esi,edx
and esi,4095
add edi,esi ;add offset in page
;edi = linear address corresponding edx in other process
sub esi,4096
neg esi ;esi - number of remaining bytes in page
cmp esi,ecx
jl .min_ecx
mov esi,ecx
.min_ecx: ;esi=min(ecx,esi) - number of bytes to write
sub ecx,esi
push ecx
mov ecx,esi ;ecx - number of bytes to write
mov esi,ebx ;esi - source, edi - destination
add edx,ecx ;move pointer in address space of other process
push edi
;move ecx bytes
test ecx,3
jnz .not_aligned
shr ecx,2
rep movsd
jmp .next_iter
.not_aligned:
rep movsb
.next_iter:
 
pop eax
and eax,not (4096-1) ;eax - linear address of current page
call MEM_Free_Page_Linear ;free reference
mov ebx,esi ;new pointer to buffer - movsb automaticaly advance it.
pop ecx ;restore number of remaining bytes
test ecx,ecx
jnz .write_loop
.ret:
popad
mov eax,ecx
ret
.page_not_found:
call MEM_Heap_UnLock ;error has appeared in critical region
sub ecx,[esp+24] ;[esp+24]<-->ecx
neg ecx ;ecx=number_of_written_bytes
mov [esp+28],ecx ;[esp+28]<-->eax
popad
ret
;-----------------------------------------------------------------------------
syscall_test:
;for testing memory manager from applications.
mov edx,ecx
mov ecx,ebx
call trans_address
mov ebx,eax
mov eax,[0x3000]
call read_process_memory
ret
;-----------------------------------------------------------------------------
read_process_memory:
;Input:
; eax - process slot
; ebx - buffer address
; ecx - buffer size
; edx - start address in other process
;Output:
; eax - number of bytes read.
pushad
shl eax,8
mov eax,[0x80000+eax+APPDATA.dir_table]
call MEM_Get_Linear_Address
mov ebp,eax
add edx,std_application_base_address
.read_loop:
;ebx = current buffer address
;ecx>0 = current size
;edx = current address in other process
;ebp = linear address of page directory
 
call MEM_Heap_Lock ;cli
mov esi,edx
shr esi,22
mov eax,[ebp+4*esi] ;find page directory entry
and eax,not (4096-1)
test eax,eax
jz .page_not_found
call MEM_Get_Linear_Address
test eax,eax
jz .page_not_found
mov esi,edx
shr esi,12
and esi,1023
mov eax,[eax+4*esi] ;find page table entry
and eax,not (4096-1)
test eax,eax
jz .page_not_found
call MEM_Get_Linear_Address ;calculate linear address of page
test eax,eax
jz .page_not_found
mov esi,eax
call MEM_Add_Reference_Linear;guarantee that page willn't disappear
call MEM_Heap_UnLock ;sti
mov edi,edx
and edi,4095
add esi,edi ;add offset in page
;esi = linear address corresponding edx in other process
sub edi,4096
neg edi
;edi=min(edi,ecx) - number of bytes to copy
cmp edi,ecx
jl .min_ecx
mov edi,ecx
.min_ecx:
 
sub ecx,edi ;update size of remaining bytes
add edx,edi ;update current pointer in other address space.
push ecx
mov ecx,edi ;ecx - number of bytes to read
mov edi,ebx ;esi - source, edi - destination
push esi
;move ecx bytes
test ecx,3
jnz .not_aligned
shr ecx,2
rep movsd
jmp .next_iter
.not_aligned:
rep movsb
.next_iter:
pop eax
and eax,not (4096-1) ;eax - linear address of current page
call MEM_Free_Page_Linear ;free reference
mov ebx,edi ;new pointer to buffer - movsb automaticaly advance it.
pop ecx ;restore number of remaining bytes
test ecx,ecx
jnz .read_loop
popad
mov eax,ecx
ret
.page_not_found:
call MEM_Heap_UnLock ;error has appeared in critical region
sub ecx,[esp+24] ;[esp+24]<-->ecx
neg ecx ;ecx=number_of_read_bytes
mov [esp+28],ecx ;[esp+28]<-->eax
popad
ret
;-----------------------------------------------------------------------------
check_region:
;input:
; ebx - start of buffer
; ecx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
mov eax,[0x3000]
jmp check_process_region
;-----------------------------------------------------------------------------
check_process_region:
;input:
; eax - slot
; ebx - start of buffer
; ecx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
test ecx,ecx
jle .ok
shl eax,5
cmp word [0x3000+eax+TASKDATA.state],0
jnz .failed
shl eax,3
mov eax,[0x80000+eax+APPDATA.dir_table]
test eax,eax
jz .failed
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
;-----------------------------------------------------------------------------
new_sys_ipc:
;input:
; eax=1 - set ipc buffer area
; ebx=address of buffer
; ecx=size of buffer
; eax=2 - send message
; ebx=PID
; ecx=address of message
; edx=size of message
cmp eax,1
jnz .no_ipc_def
;set ipc buffer area
mov edi,[0x3000]
shl edi,8
add edi,0x80000
cli
mov [edi+APPDATA.ipc_start],ebx ;set fields in extended information area
mov [edi+APPDATA.ipc_size],ecx
sti
mov [esp+36],dword 0 ;success
ret
.no_ipc_def:
cmp eax,2
jnz .no_ipc_send
;send message
cli
;obtain slot from PID
mov eax,ebx
call pid_to_slot
test eax,eax
jz .no_pid
mov ebp,eax
;ebp = slot of other process
shl eax,8
mov edi,[eax+0x80000+APPDATA.ipc_start] ;is ipc area defined?
test edi,edi
jz .no_ipc_area
mov esi,[eax+0x80000+APPDATA.ipc_size] ;esi - size of buffer
push dword -1 ;temp variable for read_process_memory
mov ebx,esp
push ecx
push edx
mov ecx,4 ;read 4 bytes
mov eax,ebp
mov edx,edi ;from beginning of buffer.
call read_process_memory
mov eax,[esp+8]
test eax,eax
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now
add edx,4 ;move to next 4 bytes
mov eax,ebp
call read_process_memory ;read size of occupied space in buffer
sub esi,8
sub esi,[esp]
sub esi,[esp+8] ;esi=(buffer size)-(occupied size)-(message size)-(header of message size)
js .buffer_overflow ;esi<0 - not enough memory in buffer
mov esi,[esp+8] ;previous offset
add dword [esp+8],8
mov edi,[esp]
add [esp+8],edi ;add (size of message)+(size of header of message) to [buffer+4]
mov eax,ebp
call write_process_memory
add edx,esi
sub edx,4 ;move to beginning of place for our message
mov eax,[second_base_address+0x3010]
mov eax,[eax+TASKDATA.pid] ;eax - our PID
mov [esp+8],eax
mov eax,ebp
call write_process_memory ;write PID
mov ebx,esp ;address of size of message
mov eax,ebp
add edx,4
call write_process_memory ;write size of message
add edx,4
pop ecx ;ecx - size of message
pop eax
call trans_address
mov ebx,eax ;ebx - linear address of message
add esp,4 ;pop temporary variable
mov eax,ebp
call write_process_memory ;write message
sti
;awake other process
shl ebp,8
mov eax,ebp
or [eax+0x80000+APPDATA.event_mask],dword 0x40
cmp dword [check_idle_semaphore],20
jge .ipc_no_cis
mov dword [check_idle_semaphore],5
.ipc_no_cis:
mov dword [esp+36],0
ret
.no_ipc_send:
mov dword [esp+36],-1
ret
.no_pid:
sti
mov dword [esp+36],4
ret
.no_ipc_area:
sti
mov dword [esp+36],1
ret
.ipc_blocked:
sti
add esp,12
mov dword [esp+36],2
ret
.buffer_overflow:
sti
add esp,12
mov dword [esp+36],3
ret
;-----------------------------------------------------------------------------
trans_address:
;Input
; eax - application address
;Output
; eax - linear address for kernel
add eax,std_application_base_address
ret
;-----------------------------------------------------------------------------
new_start_application_hd:
;eax - file name (kernel address)
;ebx - file name length
;ecx - work area (kernel address)
;edx - flags
;ebp - parameters
mov [appl_path],edi
pushad
mov esi,new_process_loading
call sys_msg_board_str ;write message to message board
;lock application_table_status mutex
.table_status:
cli
cmp [application_table_status],0
jz .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
push ebp
push ebx
push eax
push ecx
call find_new_process_place ;find new process slot
sti
test eax,eax
mov ecx, -0x20 ; too many processes
jz .failed
;write application name
xor eax,eax
mov [appl_path_size],eax
mov eax,[esp+4]
.find_last_byte:
cmp byte [eax],0
jz .find_last_byte_end
inc eax
inc [appl_path_size]
jmp .find_last_byte
.find_last_byte_end:
add [appl_path_size],24
lea esi,[eax-11] ;last 11 bytes = application name
mov edi,[new_process_place]
shl edi,8
add edi,0x80000+APPDATA.app_name
mov ecx,11
cld
rep movsb ;copy name to extended information about process
;read header
mov eax,[esp+4] ;file name
mov esi,[esp] ;work area
mov ecx,1 ;read from first block
mov edx,1 ;read 1 block
call read_hd_file
mov ecx, eax
neg ecx
jnz .cleanfailed
 
pop esi
push esi
;check menuet signature
mov ecx, -0x1F ; not Menuet/Kolibri executable
cmp [esi+1024+0],dword 'MENU' ;read_hd_file function write file to +1024 offset
jnz .cleanfailed
cmp [esi+1024+4],word 'ET'
jnz .cleanfailed
add esi,1024
mov edi,0x90000
mov ecx,512/4
cld
rep movsd ;copy first block to 0x90000 address for get_app_params function
call get_app_params
mov ecx, -0x1F ; not Menuet/Kolibri executable
test esi,esi
jz .cleanfailed
mov eax,[new_process_place]
inc ecx ; -0x1E = no memory
call create_app_cr3_table ;create page directory
test eax,eax
jz .cleanfailed_mem
call MEM_Get_Linear_Address
mov ebx,std_application_base_address
mov ecx,[app_mem]
add ecx,4096-1
shr ecx,12
mov edx,eax ;edx - linear address of page directory
call mem_alloc_specified_region ;allocate memory for application
mov ecx, -0x1E ; no memory
test eax,eax
jz .cleanfailed_mem1
add edx,(std_application_base_address shr 20)
mov eax,[edx]
and eax,not (4096-1)
call MEM_Get_Linear_Address
push edx ;save pointer to first page table
mov edx,eax
;read file
mov ecx,1
xor ebp,ebp
.loop1:
;[esp] - pointer to current page directory entry
;edx - pointer to current page table
;ebp - offset in page
;ecx - current cluster
push edx
mov eax,[esp+12] ;file name
mov ebx,[esp+16] ;file name length
mov esi,[esp+8] ;work area
mov edx,1 ;number of blocks to read
push ecx
push ebp
cli
call read_hd_file
sti
pop ebp
test eax,eax
jnz .endloop1 ;check io errors
mov esi,[esp+8+4] ;work area
add esi,1024
mov eax,[esp+4] ;current page table
mov eax,[eax]
and eax,not (4096-1)
call MEM_Get_Linear_Address;calculate linear page address
lea edi,[eax+ebp] ;add page offset
mov ecx,512/4
cld
rep movsd ;copy data
pop ecx
inc ecx ;next block
mov eax,[app_i_end] ;todo: precalculate ([app_i_end]+4095)/4096
add eax,512-1
shr eax,9 ;calculate application image size
cmp ecx,eax
jg .endloop11
pop edx
add ebp,512 ;new offset
test ebp,4096
jz .loop1
xor ebp,ebp
add edx,4 ;go to next page
test edx,(4096-1)
jnz .loop1
add dword [esp],4 ;go to next directory entry
mov eax,[esp]
mov eax,[eax]
and eax,not (4096-1)
call MEM_Get_Linear_Address
mov edx,eax
jmp .loop1
.endloop1:
add esp,4 ;pop ecx
.endloop11:
add esp,4+4 ;pop edx, pop edx
;add_app_parameters
add esp,12 ;now pointer to parameters is on the top of the stack
call new_start_application_fl.add_app_parameters ;start process
mov [esp+28],eax
popad
ret
.cleanfailed_mem1:
;there is mem for directory entry, but there is no mem for pages
;so free directory entry
mov eax,[new_process_place]
shl eax,8
mov eax,[0x80000+eax+APPDATA.dir_table]
call MEM_Free_Page
.cleanfailed_mem:
;there is no mem for directory entry, display message.
mov esi,start_not_enough_memory
call sys_msg_board_str
.cleanfailed: ;clean process name
push ecx
;can't read file, clean process name.
;this avoid problems with panel application.
mov edi,[new_process_place]
shl edi,8
add edi,0x80000+APPDATA.app_name
mov ecx,11
mov eax,' '
cld
rep stosb
pop eax
.failed:
;no more slots
add esp,16
mov [esp+1Ch], eax
popad
mov [application_table_status],0
sti
ret
end if
 
; \begin{diamond}
include 'debug.inc'
 
fs_execute:
; ebx - cmdline
; edx - flags
; ebp - full filename
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it
pushad
; check filename length - with terminating NULL must be no more than 1024 symbols
mov edi, ebp
mov ecx, 1024
xor eax, eax
repnz scasb
jz @f
popad
mov eax, -ERROR_FILE_NOT_FOUND
ret
@@:
 
mov esi, new_process_loading
call sys_msg_board_str ; write message to message board
 
; lock application_table_status mutex
.table_status:
cli
cmp [application_table_status], 0
jz .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
push ebx ; save command line pointer for add_app_parameters
 
call find_new_process_place ; find new process slot
call safe_sti
test eax, eax
mov ecx, -0x20 ; too many processes
jz .failed
 
; write application name
push edi
mov ecx, edi
sub ecx, ebp
mov [appl_path], ebp
mov [appl_path_size], ecx
dec edi
std
mov al, '/'
repnz scasb
cld
jnz @f
inc edi
@@:
inc edi
; now edi points to name without path
mov esi, edi
mov ecx, 8 ; 8 chars for name
mov edi, [new_process_place]
shl edi, cl
add edi, 0x80000+APPDATA.app_name
.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 al, ' '
rep stosb
pop eax
mov cl, 3 ; 3 chars for extension
dec esi
@@:
dec eax
cmp eax, esi
jbe .copy_process_ext_done
cmp byte [eax], '.'
jnz @b
lea esi, [eax+1]
.copy_process_ext_loop:
lodsb
test al, al
jz .copy_process_ext_done
stosb
loop .copy_process_ext_loop
.copy_process_ext_done:
mov al, ' '
rep stosb
 
; read header
lea eax, [esp+8+36]
mov edi, 0x90000
call dword [eax-4]
mov ecx, eax
neg ecx
jnz .cleanfailed
; check menuet signature
mov ecx, -0x1F
cmp dword [0x90000], 'MENU'
jnz .cleanfailed
cmp word [0x90004], 'ET'
jnz .cleanfailed
call get_app_params
mov ecx, -0x1F
test esi, esi
jz .cleanfailed
 
mov eax, [new_process_place]
inc ecx ; -0x1E = no memory
call create_app_cr3_table
test eax, eax
jz .cleanfailed_mem
 
call MEM_Get_Linear_Address
 
mov ebx, std_application_base_address
mov ecx, [app_mem]
add ecx, 4095
shr ecx, 12
mov edx, eax ; edx - linear address of page directory
call mem_alloc_specified_region
mov ecx, -0x1E ; no memory
test eax, eax
jz .cleanfailed_mem1
 
add edx, std_application_base_address shr 20
mov eax, [edx]
and eax, not 4095
call MEM_Get_Linear_Address
push edx ; save pointer to first page table
mov edx, eax
; read file
; first block is already read to 0x90000
mov eax, [edx]
and eax, not 0xFFF
call MEM_Get_Linear_Address
mov esi, 0x90000
mov edi, eax
mov ecx, 512/4
rep movsd
sub edi, eax
.loop1:
; [esp] = pointer to current page directory entry
; edx = pointer to current page table
; edi = offset in page
mov eax, [edx]
and eax, not 0xFFF
call MEM_Get_Linear_Address
push edi
add edi, eax
lea eax, [esp+8+36+8]
call dword [eax-4]
pop edi
test eax, eax
jnz .endloop1
add edi, 512 ; new offset
cmp edi, 4096
jb .loop1
xor edi, edi
add edx, 4 ; go to next page
test edx, 4096-1
jnz .loop1
pop eax
add eax, 4 ; go to next directory entry
push eax
mov eax, [eax]
and eax, not 0xFFF
call MEM_Get_Linear_Address
mov edx, eax
jmp .loop1
.endloop1:
pop edx
cmp eax, 6
jnz .cleanfailed_mem2
call new_start_application_fl.add_app_parameters
mov [esp+28], eax
popad
ret
 
.cleanfailed_mem2:
; file read error; free all allocated mem
mov ecx, eax
neg ecx
mov eax, [new_process_place]
call dispose_app_cr3_table
jmp .cleanfailed
.cleanfailed_mem1:
; there is mem for directory entry, but there is no mem for pages
; so free directory entry
mov eax, [new_process_place]
shl eax, 8
mov eax, [0x80000+eax+0xB8]
call MEM_Free_Page
.cleanfailed_mem:
; there is no mem for directory entry, display message
mov esi, start_not_enough_memory
call sys_msg_board_str
.cleanfailed:
push ecx
; clean process name, this avoid problems with @panel
mov edi, [new_process_place]
shl edi, 8
add edi, 0x80000+APPDATA.app_name
mov ecx, 11
mov al, ' '
rep stosb
pop eax
.failed:
pop ebx
mov [esp+28], eax
popad
mov [application_table_status], 0
call safe_sti
ret
; \end{diamond}
/kernel/branches/gfx_kernel/core/physmem.inc
0,0 → 1,220
virtual at 0
physical_mem_block:
.start rd 1
.size rd 1
.flags rd 1 ;0-free, pid-used.
.sizeof:
end virtual
max_physical_mem_blocks = 24
uglobal
num_physical_mem_blocks rd 1
physical_mem_blocks rd 3*max_physical_mem_blocks
endg
Init_Physical_Memory_Manager:
pushad
mov edi,physical_mem_blocks
mov ecx,3*max_physical_mem_blocks
xor eax,eax
cld
rep stosd
mov dword [num_physical_mem_blocks],2
mov [physical_mem_blocks+physical_mem_block.start],0x60000
mov [physical_mem_blocks+physical_mem_block.size],0x20000 ;128Kb
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.start],0x780000
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.size],0x80000 ;512Kb
popad
ret
Insert_Block:
;input:
; eax - handle
;output:
; none
push eax ecx esi edi
sub eax,[num_physical_mem_blocks]
neg eax
mov edi,physical_mem_block.sizeof
imul eax,edi
shr eax,2
mov ecx,eax
mov esi,[num_physical_mem_blocks]
imul esi,edi
add esi,physical_mem_blocks
lea edi,[esi+physical_mem_block.sizeof]
std
rep movsd
pop edi esi ecx eax
ret
Delete_Block:
;input:
; eax - handle
;output:
; none
pushad
mov edi,eax
sub eax,[num_physical_mem_blocks]
neg eax
dec eax
mov esi,physical_mem_block.sizeof
imul eax,esi
imul edi,esi
add edi,physical_mem_blocks
lea esi,[edi+physical_mem_block.sizeof]
mov ecx,eax
shr ecx,2
cld
rep movsd
popad
ret
Allocate_Physical_Block:
;input:
; eax - size
;output:
; eax - address or 0 if not enough memory.
pushad
cmp [num_physical_mem_blocks],max_physical_mem_blocks
jge .error
mov ebx,eax
xor eax,eax
mov esi,physical_mem_blocks
.loop:
cmp dword [esi+physical_mem_block.flags],0
jnz .next
cmp [esi+physical_mem_block.size],ebx
jg .addblock
jz .noaddblock
.next:
inc eax
add esi,physical_mem_block.sizeof
cmp eax,[num_physical_mem_blocks]
jl .loop
.error:
popad
xor eax,eax
ret
.noaddblock:
mov eax,[esi+physical_mem_block.start]
mov [esp+28],eax
mov eax,[0x3010]
mov eax,[eax+TASKDATA.pid]
mov [esi+physical_mem_block.flags],eax
popad
ret
.addblock:
call Insert_Block
inc dword [num_physical_mem_blocks]
mov eax,[esi+physical_mem_block.start]
mov [esp+28],eax
mov ecx,[0x3010]
mov ecx,[ecx+TASKDATA.pid]
mov [esi+physical_mem_block.flags],ecx
mov ecx,[esi+physical_mem_block.size]
mov [esi+physical_mem_block.size],ebx
sub ecx,ebx
mov [esi+physical_mem_block.sizeof+physical_mem_block.size],ecx
add ebx,[esi+physical_mem_block.start]
mov [esi+physical_mem_block.sizeof+physical_mem_block.start],ebx
mov dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0
popad
ret
Free_Physical_Block:
;input:
; eax - address
;output:
; none
pushad
test eax,eax
jz .ret
mov ebx,eax
xor eax,eax
mov esi,physical_mem_blocks
.loop:
cmp ebx,[esi+physical_mem_block.start]
jz .endloop
inc eax
add esi,physical_mem_block.sizeof
cmp eax,[num_physical_mem_blocks]
jl .loop
jmp .ret
.endloop:
mov dword [esi+physical_mem_block.flags],0
test eax,eax
jz .no_union_previous
cmp dword [esi-physical_mem_block.sizeof+physical_mem_block.flags],0
jnz .no_union_previous
mov ebx,[esi-physical_mem_block.sizeof+physical_mem_block.start]
add ebx,[esi-physical_mem_block.sizeof+physical_mem_block.size]
cmp ebx,[esi+physical_mem_block.start]
jnz .no_union_previous
mov ebx,[esi+physical_mem_block.size]
add [esi-physical_mem_block.sizeof+physical_mem_block.size],ebx
call Delete_Block
dec eax
dec [num_physical_mem_blocks]
.no_union_previous:
inc eax
cmp eax,[num_physical_mem_blocks]
jge .no_union_next
cmp dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0
jnz .no_union_next
mov ebx,[esi+physical_mem_block.start]
add ebx,[esi+physical_mem_block.size]
cmp ebx,[esi+physical_mem_block.sizeof+physical_mem_block.start]
jnz .no_union_next
mov ebx,[esi+physical_mem_block.sizeof+physical_mem_block.size]
add [esi+physical_mem_block.size],ebx
call Delete_Block
dec [num_physical_mem_blocks]
.no_union_next:
.ret:
popad
ret
sys_allocate_physical_block:
;eax - subfunction number
mov eax,ebx
call Allocate_Physical_Block
mov [esp+36],eax
ret
sys_free_physical_block:
;eax - subfunction number
mov eax,ebx
call Free_Physical_Block
ret
sys_set_buffer:
add ecx,std_application_base_address
isys_set_buffer: ;for using in kernel
;eax - subfunction number
;ebx - physical address
;ecx - buffer start
;edx - buffer size
lea edi,[ebx+second_base_address]
mov esi,ecx
mov ecx,edx
cld
rep movsb
ret
sys_get_buffer:
add ecx,std_application_base_address
isys_get_buffer: ;for using in kernel
;eax - subfunction number
;ebx - physical address
;ecx - buffer start
;edx - buffer size
mov edi,ecx
lea esi,[ebx+second_base_address]
mov ecx,edx
cld
rep movsb
ret
sys_internal_services:
cmp eax,4
jle sys_sheduler
cmp eax,5
jz sys_allocate_physical_block
cmp eax,6
jz sys_free_physical_block
cmp eax,7
jz sys_set_buffer
cmp eax,8
jz sys_get_buffer
ret
/kernel/branches/gfx_kernel/core/sched.inc
0,0 → 1,191
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IRQ0 HANDLER (TIMER INTERRUPT) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
align 32
irq0:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
 
inc dword [timer_ticks]
 
mov eax, [timer_ticks]
call playNote ; <<<--- Speaker driver
 
cmp eax,[next_usage_update]
jb .nocounter
add eax,100
mov [next_usage_update],eax
call updatecputimes
.nocounter:
 
cmp [0xffff], byte 1
jne .change_task
 
mov al,0x20 ; send End Of Interrupt signal
mov dx,0x20
out dx,al
 
mov [0xffff], byte 0
 
restore_ring3_context
iret
 
.change_task:
call update_counters
 
call find_next_task
mov ecx, eax
 
mov al,0x20 ; send End Of Interrupt signal
mov dx,0x20
out dx,al
 
test ecx, ecx ; if there is only one running process
jnz .return
 
call do_change_task
.return:
restore_ring3_context
iret
 
 
align 4
change_task:
 
pushfd
cli
pushad
 
call update_counters
call find_next_task
test eax, eax ; the same task -> skip switch
jnz .return
 
mov [0xffff],byte 1
call do_change_task
 
.return:
popad
popfd
 
ret
 
 
uglobal
align 4
far_jump:
.offs dd ?
.sel dw ?
context_counter dd ? ;noname & halyavin
next_usage_update dd ?
timer_ticks dd ?
prev_slot dd ?
event_sched dd ?
endg
 
 
update_counters:
mov edi, [0x3010]
mov ebx, [edi+TASKDATA.counter_add] ; time stamp counter add
call _rdtsc
sub eax, ebx
add eax, [edi+TASKDATA.counter_sum] ; counter sum
mov [edi+TASKDATA.counter_sum], eax
ret
 
 
; Find next task to execute
; result: ebx = number of the selected task
; eax = 1 if the task is the same
; edi = address of the data for the task in ebx
; [0x3000] = ebx and [0x3010] = edi
; corrupts other regs
find_next_task:
mov ebx, [0x3000]
mov edi, [0x3010]
mov [prev_slot], ebx
 
.waiting_for_termination:
.waiting_for_reuse:
.waiting_for_event:
.suspended:
cmp ebx, [0x3004]
jb @f
mov edi, 0x3000
xor ebx, ebx
@@:
 
add edi,0x20
inc ebx
 
mov al, byte [edi+TASKDATA.state]
test al, al
jz .found
cmp al, 1
jz .suspended
cmp al, 2
jz .suspended
cmp al, 3
je .waiting_for_termination
cmp al, 4
je .waiting_for_termination
cmp al, 9
je .waiting_for_reuse
 
mov [0x3000],ebx
mov [0x3010],edi
 
cmp al, 5
jne .noevents
call get_event_for_app
test eax, eax
jz .waiting_for_event
mov [event_sched], eax
mov [edi+TASKDATA.state], byte 0
.noevents:
.found:
mov [0x3000],ebx
mov [0x3010],edi
call _rdtsc
mov [edi+TASKDATA.counter_add],eax
 
xor eax, eax
cmp ebx, [prev_slot]
sete al
ret
 
; in: ebx = TSS selector index
do_change_task:
shl ebx, 3
xor eax, eax
add ebx, tss0
mov [far_jump.sel], bx ; selector
mov [far_jump.offs], eax ; offset
jmp pword [far_jump]
inc [context_counter] ;noname & halyavin
ret
 
 
 
align 4
updatecputimes:
 
mov eax,[idleuse]
mov [idleusesec],eax
mov [idleuse],dword 0
mov ecx, [0x3004]
mov edi, 0x3020
.newupdate:
mov ebx,[edi+TASKDATA.counter_sum]
mov [edi+TASKDATA.cpu_usage],ebx
mov [edi+TASKDATA.counter_sum],dword 0
add edi,0x20
dec ecx
jnz .newupdate
 
ret
/kernel/branches/gfx_kernel/core/sync.inc
0,0 → 1,111
if ~defined sync_inc
sync_inc_fix:
sync_inc fix sync_inc_fix
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Synhronization for MenuetOS. ;;
;;Author: Halyavin Andrey, halyavin@land.ru ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;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 [0x3010+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,[0x3010+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,[0x3000+second_base_address]
mov eax,[eax+TASKDATA.pid]
cmp [name],eax
jz ok
cmp [name],0
jz ok
xor eax,eax
jmp try_end
ok=$
xor eax,eax
inc eax
try_end=$
}
_cli equ call MEM_HeapLock
_sti equ call MEM_HeapUnLock
end if
 
/kernel/branches/gfx_kernel/core/sys32.inc
0,0 → 1,1017
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; MenuetOS process management, protected ring3 ;;
;; ;;
;; Distributed under GPL. See file COPYING for details. ;;
;; Copyright 2003 Ville Turjanmaa ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 32
 
; GDT TABLE
 
gdts:
 
dw gdte-$-1
dd gdts
dw 0
 
int_code_l:
os_code_l:
 
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
 
int_data_l:
os_data_l:
 
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
 
; --------------- APM ---------------------
apm_code_32:
dw 0x10 ; limit 64kb
db 0, 0, 0
dw 11011111b *256 +10011010b
db 0x00
apm_code_16:
dw 0x10
db 0, 0, 0
dw 10011111b *256 +10011010b
db 0x00
apm_data_16:
dw 0x10
db 0, 0, 0
dw 10011111b *256 +10010010b
db 0x00
; -----------------------------------------
 
app_code_l:
dw ((0x80000000-std_application_base_address) shr 12) and 0xffff
dw 0
db 0
dw 11010000b*256+11111010b+256*((0x80000000-std_application_base_address) shr 28)
db std_application_base_address shr 24
 
app_data_l:
dw (0x80000000-std_application_base_address) shr 12 and 0xffff
dw 0
db 0
dw 11010000b*256+11110010b+256*((0x80000000-std_application_base_address) shr 28)
db std_application_base_address shr 24
 
graph_data_l:
 
dw 0x3ff
dw 0x0000
db 0x00
dw 11010000b *256 +11110010b
db 0x00
 
tss0_l:
times (max_processes+10) dd 0,0
 
gdte:
 
 
 
idtreg:
dw 8*0x41-1
dd idts+8
label idts at 0xB100-8
 
 
 
uglobal
tss_sceleton:
l.back dw 0,0
l.esp0 dd 0
l.ss0 dw 0,0
l.esp1 dd 0
l.ss1 dw 0,0
l.esp2 dd 0
l.ss2 dw 0,0
l.cr3 dd 0
l.eip dd 0
l.eflags dd 0
l.eax dd 0
l.ecx dd 0
l.edx dd 0
l.ebx dd 0
l.esp dd 0
l.ebp dd 0
l.esi dd 0
l.edi dd 0
l.es dw 0,0
l.cs dw 0,0
l.ss dw 0,0
l.ds dw 0,0
l.fs dw 0,0
l.gs dw 0,0
l.ldt dw 0,0
l.trap dw 0
l.io dw 0
endg
 
 
build_process_gdt_tss_pointer:
 
mov ecx,tss_data
mov edi,0
setgdtl2:
mov [edi+gdts+ tss0 +0], word tss_step
mov [edi+gdts+ tss0 +2], cx
mov eax,ecx
shr eax,16
mov [edi+gdts+ tss0 +4], al
mov [edi+gdts+ tss0 +7], ah
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b
add ecx,tss_step
add edi,8
cmp edi,8*(max_processes+5)
jbe setgdtl2
 
ret
 
 
build_interrupt_table:
 
mov edi, idts+8
mov esi, sys_int
mov ecx, 0x40
@@:
mov eax, [esi]
mov [edi], ax ; lower part of offset
mov [edi+2], word os_code ; segment selector
shr eax, 16
mov [edi+4], word 10001110b shl 8 ; interrupt descriptor
mov [edi+6], ax
add esi, 4
add edi, 8
dec ecx
jnz @b
;mov edi,8*0x40+idts+8
mov [edi + 0], word (i40 and ((1 shl 16)-1))
mov [edi + 2], word os_code
mov [edi + 4], word 11101110b*256
mov [edi + 6], word (i40 shr 16)
 
ret
 
 
 
iglobal
sys_int:
dd e0,debug_exc,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15
dd e16,e17
times 14 dd unknown_interrupt
 
dd irq0 ,irq1 ,p_irq2 ,p_irq3 ,p_irq4 ,p_irq5,p_irq6 ,p_irq7
dd p_irq8,p_irq9,p_irq10,p_irq11,p_irq12,irqD ,p_irq14,p_irq15
 
times 16 dd unknown_interrupt
 
dd i40
endg
 
macro save_ring3_context
{
push ds es
pushad
}
macro restore_ring3_context
{
popad
pop es ds
}
 
; simply return control to interrupted process
unknown_interrupt:
iret
 
macro exc_wo_code [num]
{
forward
e#num :
save_ring3_context
mov bl, num
jmp exc_c
}
 
macro exc_w_code [num]
{
forward
e#num :
add esp, 4
save_ring3_context
mov bl, num
jmp exc_c
}
 
exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15, 16 ; 18, 19
exc_w_code 8, 10, 11, 12, 13, 14, 17
 
exc_c:
mov ax, os_data
mov ds, ax
mov es, ax
 
; test if debugging
cli
mov eax, [0x3000]
shl eax, 8
mov eax, [0x80000+eax+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
add esp, 28h
movzx eax, bl
mov [error_interrupt], eax
call show_error_parameters
mov edx, [0x3010]
mov [edx + TASKDATA.state], byte 4
jmp change_task
 
.debug:
; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID
cld
movzx ecx, bl
push ecx
mov ecx, [0x3010]
push dword [ecx+TASKDATA.pid] ; PID of current process
push 12
pop ecx
push 1 ; 1=exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [0x3010]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task
restore_ring3_context
iretd
 
;;;;;;;;;;;;;;;;;;;;;;;
;; FPU ERROR HANDLER ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
e7:
save_ring3_context
clts
mov ax, os_data
mov ds, ax
mov es, ax
mov eax, [prev_user_of_fpu]
shl eax, 8
add eax, 0x80000 + APPDATA.fpu_save_area
fsave [eax]
mov eax, [0x3000]
mov [prev_user_of_fpu], eax
shl eax, 8
add eax, 0x80000
cmp [eax + APPDATA.is_fpu_saved], 0
je @f
frstor [eax+APPDATA.fpu_save_area]
@@:
mov [eax + APPDATA.is_fpu_saved], 1
restore_ring3_context
iret
iglobal
prev_user_of_fpu dd 1
endg
 
 
writehex:
pusha
mov edi, [write_error_to]
mov esi, 8
@@:
mov ecx, eax
and ecx, 0xf
 
mov cl,[ecx+hexletters]
mov [edi],cl
dec edi
 
shr eax,4
dec esi
jnz @b
 
popa
ret
 
iglobal
hexletters db '0123456789ABCDEF'
 
error_interrupt dd -1
 
process_error db 'K : Process - forced terminate INT: 00000000',13,10,0
process_pid db 'K : Process - forced terminate PID: 00000000',13,10,0
process_eip db 'K : Process - forced terminate EIP: 00000000',13,10,0
system_error db 'K : Kernel error',13,10,0
endg
 
uglobal
write_error_to dd 0x0
endg
 
show_error_parameters:
mov [write_error_to],process_pid+43
mov eax,[0x3000]
shl eax, 5
mov eax,[0x3000+TASKDATA.pid+eax]
call writehex
mov [write_error_to],process_error+43
mov eax,[error_interrupt]
call writehex
 
cmp dword [esp+4+4], os_code ; CS
jnz @f
mov esi,system_error
call sys_msg_board_str
@@:
mov eax, [esp+4] ; EIP
 
mov [write_error_to],process_eip+43
call writehex
 
mov esi,process_error
call sys_msg_board_str
 
mov esi,process_pid
call sys_msg_board_str
 
mov esi,process_eip
call sys_msg_board_str
 
ret
 
 
 
; irq1 -> hid/keyboard.inc
 
 
macro irqh [num]
{
forward
p_irq#num :
save_ring3_context
mov edi, num
jmp irq_c
}
 
irqh 2,5,7,8,9,10,11,14,15
 
irq_c:
mov ax, os_data
mov ds, ax
mov es, ax
call irqhandler
restore_ring3_context
iret
 
p_irq6:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
call fdc_irq
call ready_for_next_irq
restore_ring3_context
iret
 
p_irq3:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
cmp [com2_mouse_detected],0
je old_irq3_handler
call check_mouse_data_com2
jmp p_irq3_1
old_irq3_handler:
mov edi,3
call irqhandler
p_irq3_1:
restore_ring3_context
iret
 
p_irq4:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
cmp [com1_mouse_detected],0
je old_irq4_handler
call check_mouse_data_com1
jmp p_irq4_1
old_irq4_handler:
mov edi,4
call irqhandler
p_irq4_1:
restore_ring3_context
iret
 
p_irq12:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
call check_mouse_data_ps2
restore_ring3_context
iret
 
ready_for_next_irq:
mov [check_idle_semaphore],5
mov al, 0x20
out 0x20, al
ret
 
ready_for_next_irq_1:
mov [check_idle_semaphore],5
mov al, 0x20
out 0xa0,al
out 0x20, al
ret
 
irqD:
save_ring3_context
mov ax, os_data
mov ds, ax
mov es, ax
mov dx,0xf0
mov al,0
out dx,al
 
mov dx,0xa0
mov al,0x20
out dx,al
mov dx,0x20
out dx,al
 
restore_ring3_context
iret
 
 
irqhandler:
 
push edi
 
mov esi,edi ; 1
shl esi,6 ; 1
add esi,irq00read ; 1
shl edi,12 ; 1
add edi,0x2E0000
mov ecx,16
 
mov [check_idle_semaphore],5
 
irqnewread:
dec ecx
js irqover
 
mov dx,[esi] ; 2+
 
cmp dx,0 ; 1
jz irqover
cmp [esi+3],byte 1 ; 2 ; byte read
jne noirqbyte ; 4-11
 
in al,dx
 
mov edx,[edi]
cmp edx,4000
je irqfull
mov ebx,edi
add ebx,0x10
add ebx,edx
mov [ebx],al
inc edx
mov [edi],edx
 
add esi,4
jmp irqnewread
 
noirqbyte:
 
 
cmp [esi+3],byte 2 ; word read
jne noirqword
 
in ax,dx
 
mov edx,[edi]
cmp edx,4000
je irqfull
mov ebx,edi
add ebx,0x10
add ebx,edx
mov [ebx],ax
add edx,2
mov [edi],edx
add esi,4
jmp irqnewread
 
noirqword:
irqfull:
irqover:
 
mov al,0x20 ; ready for next irq
out 0x20,al
 
pop ebx
cmp ebx,7
jbe noa0
out 0xa0,al
noa0:
 
ret
 
 
 
set_application_table_status:
push eax
 
mov eax,[0x3000]
shl eax, 5
add eax,0x3000+TASKDATA.pid
mov eax,[eax]
 
mov [application_table_status],eax
 
pop eax
 
ret
 
 
clear_application_table_status:
push eax
 
mov eax,[0x3000]
shl eax, 5
add eax,0x3000+TASKDATA.pid
mov eax,[eax]
 
cmp eax,[application_table_status]
jne apptsl1
mov [application_table_status],0
apptsl1:
 
pop eax
 
ret
 
 
 
sys_resize_app_memory:
; eax = 1 - resize
; ebx = new amount of memory
 
cmp eax,1
jne .no_application_mem_resize
jmp new_mem_resize ;resize for new type of processes
 
 
.no_application_mem_resize:
 
ret
 
 
 
get_app_params:
 
push eax
 
cmp [0x90000+6],word '00'
jne no_00_header
 
mov eax,[0x90000+12]
mov [app_start],eax
mov eax,[0x90000+16]
mov [app_i_end],eax
mov eax,[0x90000+20]
mov [app_mem],eax
shr eax,1
sub eax,0x10
mov [app_esp],eax
mov eax,[0x90000+24]
mov [app_i_param],eax
mov [app_i_icon],dword 0
 
pop eax
mov esi,1
ret
 
no_00_header:
 
 
cmp [0x90000+6],word '01'
jne no_01_header
 
mov eax,[0x90000+12]
mov [app_start],eax
mov eax,[0x90000+16]
mov [app_i_end],eax
mov eax,[0x90000+20]
mov [app_mem],eax
mov eax,[0x90000+24]
mov [app_esp],eax
mov eax,[0x90000+28]
mov [app_i_param],eax
mov eax,[0x90000+32]
mov [app_i_icon],eax
 
pop eax
mov esi,1
ret
 
no_01_header:
 
pop eax
mov esi,0
ret
 
 
start_application_fl:
jmp new_start_application_fl
 
;************************************************************************
 
start_application_floppy:
jmp new_start_application_floppy
 
;********************************************************************
 
start_application_hd:
jmp new_start_application_hd
 
uglobal
new_process_place dd 0x0
app_start dd 0x0
app_i_end dd 0x0
app_mem dd 0x0
app_esp dd 0x0
app_i_param dd 0x0
app_i_icon dd 0x0
;app_mem_pos dd 0x0
appl_path dd 0x0
appl_path_size dd 0x0
endg
 
;iglobal
;hd_app_string db 'HDAPP '
;process_loading db 'K : Process - loading ',13,10,0
;process_running db 'K : Process - done',13,10,0
;first_gdt_search dd 0x2
;endg
 
 
sys_threads:
 
; eax=1 create thread
;
; ebx=thread start
; ecx=thread stack value
;
; on return : eax = pid
jmp new_sys_threads
 
iglobal
process_terminating db 'K : Process - terminating',13,10,0
process_terminated db 'K : Process - done',13,10,0
endg
 
 
terminate: ; terminate application
push esi
mov esi,process_terminating
call sys_msg_board_str
pop esi
 
@@:
cli
cmp [application_table_status],0
je term9
sti
call change_task
jmp @b
term9:
 
call set_application_table_status
mov eax,esi
call dispose_app_cr3_table
 
cmp [prev_user_of_fpu],esi ; if user fpu last -> fpu user = 1
jne fpu_ok_1
mov [prev_user_of_fpu],1
fpu_ok_1:
 
mov [0xf400],byte 0 ; empty keyboard buffer
mov [0xf500],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,[0xfe88]
mov eax,edi
cld
movzx ebx,word [edi]
inc bx
bnewba:
dec bx
jz bnmba
add eax,0x10
cmp cx,[eax]
jnz bnewba
pusha
mov ecx,ebx
inc ecx
shl ecx,4
mov ebx,eax
add eax,0x10
call memmove
dec dword [edi]
popa
jmp bnewba2
bnmba:
 
pusha ; save window coordinates for window restoring
cld
shl esi,5
add esi,window_data
mov eax,[esi+WDATA.box.left]
mov [dlx],eax
add eax,[esi+WDATA.box.width]
mov [dlxe],eax
mov eax,[esi+WDATA.box.top]
mov [dly],eax
add eax,[esi+WDATA.box.height]
mov [dlye],eax
 
mov [esi+WDATA.box.left], 0
mov [esi+WDATA.box.width], 5
mov eax,[0xFE04]
mov [esi+WDATA.box.top],eax
mov [esi+WDATA.box.height], 5
xor eax, 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, [0x80000+edi*8+APPDATA.debugger_slot]
test eax, eax
jz .nodebug
push 8
pop ecx
push dword [0x3000+edi+TASKDATA.pid] ; PID
push 2
call debugger_notify
pop ecx
pop ecx
.nodebug:
popad
 
pusha ; at 0x80000+
mov edi,esi
shl edi,8
add edi,0x80000
mov ecx,256/4
xor eax, eax
rep stosd
popa
 
pusha ; name to spaces
mov edi,esi
shl edi,8
add edi,0x80000+APPDATA.app_name
mov ecx,11
mov eax,' '
rep stosb
popa
 
 
; activate window
movzx eax, word [0xC000 + esi*2]
cmp eax, [0x3004]
jne .dont_activate
pushad
.check_next_window:
dec eax
cmp eax, 1
jbe .nothing_to_activate
lea esi, [0xc400+eax*2]
movzx edi, word [esi] ; edi = process
shl edi, 5
cmp [0x3000 + edi + TASKDATA.state], byte 9 ; skip dead slots
je .check_next_window
add edi, window_data
call waredraw
.nothing_to_activate:
popad
.dont_activate:
 
push esi ; remove hd1 & cd & flp reservation
shl esi, 5
mov esi, [esi+0x3000+TASKDATA.pid]
cmp [hd1_status], esi
jnz @f
mov [hd1_status], 0
@@:
cmp [cd_status], esi
jnz @f
mov [cd_status], 0
@@:
cmp [flp_status], esi
jnz @f
mov [flp_status], 0
@@:
pop esi
 
pusha ; remove all irq reservations
mov eax,esi
shl eax, 5
mov eax,[eax+0x3000+TASKDATA.pid]
mov edi,irq_owner
mov ecx,16
newirqfree:
scasd
jne nofreeirq
mov [edi-4],dword 0
nofreeirq:
loop newirqfree
popa
 
 
pusha ; remove all port reservations
mov edx,esi
shl edx, 5
add edx,0x3000
mov edx,[edx+TASKDATA.pid]
 
rmpr0:
 
mov esi,[0x2d0000]
 
cmp esi,0
je rmpr9
 
rmpr3:
 
mov edi,esi
shl edi,4
add edi,0x2d0000
 
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 [0x2d0000]
 
jmp rmpr0
 
rmpr9:
 
popa
mov edi,esi ; do not run this process slot
shl edi, 5
mov [edi+0x3000 + TASKDATA.state],byte 9
; debugger test - terminate all debuggees
mov eax, 2
mov ecx, 0x80000+2*0x100+APPDATA.debugger_slot
.xd0:
cmp eax, [0x3004]
ja .xd1
cmp dword [ecx], esi
jnz @f
and dword [ecx], 0
pushad
xchg eax, ebx
mov eax, 2
call sys_system
popad
@@:
inc eax
add ecx, 0x100
jmp .xd0
.xd1:
; call systest
sti ; .. and life goes on
 
mov eax, [dlx]
mov ebx, [dly]
mov ecx, [dlxe]
mov edx, [dlye]
call [calculatescreen]
xor eax, eax
xor esi, esi
call redrawscreen
 
mov [0xfff4],byte 0 ; no mouse background
mov [0xfff5],byte 0 ; draw mouse
 
mov [application_table_status],0
mov esi,process_terminated
call sys_msg_board_str
 
ret
 
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
call build_interrupt_table
 
ret
 
/kernel/branches/gfx_kernel/core/syscall.inc
0,0 → 1,151
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSTEM CALL ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 32
i40:
push ds es
pushad
cld
 
mov ax,word os_data
mov ds,ax
mov es,ax
 
; for syscall trace function
call save_registers
 
; load all registers in crossed order
mov edi,[esp+28] ; eax
mov eax,[esp+16] ; ebx
mov ebx,[esp+24] ; ecx
mov ecx,[esp+20] ; edx
mov edx,[esp+4] ; esi
mov esi,[esp+0] ; edi
 
; enable interupts - a task switch or an IRQ _CAN_ interrupt i40 handler
sti
push eax
and edi,0xff
call dword [servetable+edi*4]
pop eax
cli
popad
pop es ds
iretd
 
align 4
save_registers:
mov esi, [0x3010]
mov eax, [esi+TASKDATA.pid] ; load PID
lea esi, [esp+4]
inc [save_syscall_count]
mov edi,[save_syscall_count]
and edi,0xF
shl edi,6
add edi,save_syscall_data+32
mov [edi-32],eax
mov ecx,32 / 4
cld
rep movsd
ret
 
uglobal
save_syscall_count dd 0x0
endg
 
label save_syscall_data dword at 0x5000
 
 
iglobal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
servetable:
 
dd sys_drawwindow ; 0-DrawWindow
dd syscall_setpixel ; 1-SetPixel
dd sys_getkey ; 2-GetKey
dd sys_clock ; 3-GetTime
dd syscall_writetext ; 4-WriteText
dd delay_hs ; 5-DelayHs
dd syscall_openramdiskfile ; 6-OpenRamdiskFile
dd syscall_putimage ; 7-PutImage
dd sys_button ; 8-DefineButton
dd sys_cpuusage ; 9-GetProcessInfo
dd sys_waitforevent ; 10-WaitForEvent
dd sys_getevent ; 11-CheckForEvent
dd sys_redrawstat ; 12-BeginDraw and EndDraw
dd syscall_drawrect ; 13-DrawRect
dd syscall_getscreensize ; 14-GetScreenSize
dd sys_background ; 15-bgr
dd sys_cachetodiskette ; 16-FlushFloppyCache
dd sys_getbutton ; 17-GetButton
dd sys_system ; 18-System Services
dd syscall_startapp ; 19-StartApp
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 sys_sb16 ; 25-SetSb16
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,.
dd sys_wss ; 27-SetWssMainVol and SetWssCdVol
dd sys_sb16II ; 28-SetSb16
dd sys_date ; 29-GetDate
; dd syscall_readhd ; 30-ReadHd - obsolete <diamond>
dd undefined_syscall ; 30-reserved
; dd syscall_starthdapp ; 31-StartHdApp - obsolete <diamond>
dd undefined_syscall ; 31-reserved
dd syscall_delramdiskfile ; 32-DelRamdiskFile
dd syscall_writeramdiskfile; 33-WriteRamdiskFile
; dd read_floppy_file ; 34-ReadFloppyDrive - obsolete <diamond>
dd undefined_syscall ; 34-reserved
dd syscall_getpixel ; 35-GetPixel
dd syscall_readstring ; 36-ReadString (not yet ready)
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 display_settings ; 48-SetRedrawType and SetButtonType
dd sys_apm ; 49-Advanced Power Management (APM)
dd random_shaped_window ; 50-Window shape & scale
dd syscall_threads ; 51-Threads
dd stack_driver_stat ; 52-Stack driver status
dd socket ; 53-Socket interface
dd user_events ; 54-User events
dd sound_interface ; 55-Sound interface
dd write_to_hd ; 56-Write a file to hd
; dd delete_from_hd ; 57-Delete a file from hd - obsolete <diamond>
dd undefined_syscall ; 57-reserved
dd file_system ; 58-Common file system interface
dd sys_trace ; 59-System call trace
dd new_sys_ipc ; 60-Inter Process Communication
dd sys_gs ; 61-Direct graphics access
dd sys_pci ; 62-PCI functions
dd sys_msg_board ; 63-System message board
dd sys_resize_app_memory ; 64-Resize application memory usage
dd undefined_syscall ; 65-UTF
dd sys_process_def ; 66-Process definitions - keyboard
dd sys_window_move ; 67-Window move or resize
dd sys_internal_services ; 68-Some internal services
dd sys_debug_services ; 69-Debug
dd file_system_lfn ; 70-Common file system interface, version 2
dd syscall_windowsettings ; 71-Window settings
 
times 255 - ( ($-servetable) /4 ) dd undefined_syscall
 
dd sys_end ; -1-end application
endg