1094 lines
25 KiB
NASM
1094 lines
25 KiB
NASM
|
;===============================================================================
|
||
|
;Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved.
|
||
|
;===============================================================================
|
||
|
|
||
|
; information for linker
|
||
|
section .rodata
|
||
|
|
||
|
; align routine
|
||
|
align 0x08, db 0x00
|
||
|
kernel_service_list:
|
||
|
dq kernel_service_exit
|
||
|
dq kernel_service_framebuffer
|
||
|
dq kernel_service_memory_alloc
|
||
|
dq kernel_service_memory_release
|
||
|
dq kernel_service_task_pid
|
||
|
dq kernel_service_driver_mouse
|
||
|
dq kernel_service_storage_read
|
||
|
dq kernel_service_exec
|
||
|
dq kernel_service_ipc_send
|
||
|
dq kernel_service_ipc_receive
|
||
|
dq kernel_service_memory_share
|
||
|
dq driver_ps2_keyboard_key_read
|
||
|
dq kernel_service_task_status
|
||
|
dq kernel_stream_out
|
||
|
dq kernel_stream_in
|
||
|
dq kernel_service_serial_char
|
||
|
dq kernel_service_serial_string
|
||
|
dq kernel_service_serial_value
|
||
|
dq driver_rtc_time
|
||
|
dq kernel_stream_set
|
||
|
dq kernel_stream_get
|
||
|
dq kernel_service_sleep
|
||
|
dq kernel_service_uptime
|
||
|
dq kernel_stream_out_value
|
||
|
dq kernel_service_task
|
||
|
dq kernel_service_memory
|
||
|
dq kernel_service_thread
|
||
|
kernel_service_list_end:
|
||
|
|
||
|
; information for linker
|
||
|
section .text
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to Memory descriptor
|
||
|
kernel_service_memory:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push r8
|
||
|
|
||
|
; kernel environment variables/rountines base addrrax
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; return information about
|
||
|
|
||
|
; all available pages
|
||
|
mov rax, qword [r8 + KERNEL_STRUCTURE.page_total]
|
||
|
mov qword [rdi + LIB_SYS_STRUCTURE_MEMORY.total], rax
|
||
|
|
||
|
; and currently free
|
||
|
mov rax, qword [r8 + KERNEL_STRUCTURE.page_available]
|
||
|
mov qword [rdi + LIB_SYS_STRUCTURE_MEMORY.available], rax
|
||
|
|
||
|
; restore original registers
|
||
|
pop r8
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; void
|
||
|
kernel_service_exit:
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; mark task as closed and not active
|
||
|
or word [r9 + KERNEL_TASK_STRUCTURE.flags], KERNEL_TASK_FLAG_closed
|
||
|
and word [r9 + KERNEL_TASK_STRUCTURE.flags], ~KERNEL_TASK_FLAG_active
|
||
|
|
||
|
; release rest of AP time
|
||
|
int 0x20
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - sleep amount in microtime
|
||
|
kernel_service_sleep:
|
||
|
; preserve original registers
|
||
|
push rdi
|
||
|
push r8
|
||
|
push r9
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; current uptime
|
||
|
add rdi, qword [r8 + KERNEL_STRUCTURE.hpet_microtime]
|
||
|
|
||
|
; go to sleep for N ticks
|
||
|
mov qword [r9 + KERNEL_TASK_STRUCTURE.sleep], rdi
|
||
|
|
||
|
; release the remaining CPU time
|
||
|
int 0x20
|
||
|
|
||
|
; restore original registers
|
||
|
pop r9
|
||
|
pop r8
|
||
|
pop rdi
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; out:
|
||
|
; rax - current uptime in microtime
|
||
|
kernel_service_uptime:
|
||
|
; return current microtime index
|
||
|
mov rax, qword [kernel_environment_base_address]
|
||
|
mov rax, qword [rax + KERNEL_STRUCTURE.hpet_microtime]
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to mouse descriptor
|
||
|
kernel_service_driver_mouse:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push r8
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; share information about mouse location and status
|
||
|
mov ax, word [r8 + KERNEL_STRUCTURE.driver_ps2_mouse_x]
|
||
|
mov word [rdi + LIB_SYS_STRUCTURE_MOUSE.x], ax
|
||
|
mov ax, word [r8 + KERNEL_STRUCTURE.driver_ps2_mouse_y]
|
||
|
mov word [rdi + LIB_SYS_STRUCTURE_MOUSE.y], ax
|
||
|
mov al, byte [r8 + KERNEL_STRUCTURE.driver_ps2_mouse_status]
|
||
|
mov byte [rdi + LIB_SYS_STRUCTURE_MOUSE.status], al
|
||
|
|
||
|
; restore original registers
|
||
|
pop r8
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdx - stream flags
|
||
|
; rsi - length of file name/path
|
||
|
; rdi - pointer to file name/path
|
||
|
; out:
|
||
|
; rax - process ID
|
||
|
kernel_service_exec:
|
||
|
; preserve original registers
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push rbp
|
||
|
push r8
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; reorganize registers
|
||
|
mov rcx, rsi ; length of string
|
||
|
mov rsi, rdx ; pointer to string
|
||
|
xchg rsi, rdi ; stream flags
|
||
|
|
||
|
; execute file from path
|
||
|
call kernel_exec
|
||
|
|
||
|
; restore original registers
|
||
|
pop r8
|
||
|
pop rbp
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to framebuffer descriptor
|
||
|
kernel_service_framebuffer:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push rcx
|
||
|
push rdx
|
||
|
push rsi
|
||
|
push r8
|
||
|
push r9
|
||
|
push r11
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; return properties of framebuffer
|
||
|
|
||
|
; width in pixels
|
||
|
mov ax, word [r8 + KERNEL_STRUCTURE.framebuffer_width_pixel]
|
||
|
mov word [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.width_pixel], ax
|
||
|
|
||
|
; height in pixels
|
||
|
mov ax, word [r8 + KERNEL_STRUCTURE.framebuffer_height_pixel]
|
||
|
mov word [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.height_pixel], ax
|
||
|
|
||
|
; scanline in Bytes
|
||
|
mov eax, dword [r8 + KERNEL_STRUCTURE.framebuffer_scanline_byte]
|
||
|
mov dword [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.scanline_byte], eax
|
||
|
|
||
|
; framebuffer manager
|
||
|
mov rax, qword [r8 + KERNEL_STRUCTURE.framebuffer_pid]
|
||
|
|
||
|
; framebuffer manager exist?
|
||
|
test rax, rax
|
||
|
jnz .return ; yes
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; calculate size of framebuffer space
|
||
|
mov eax, dword [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.scanline_byte]
|
||
|
movzx ecx, word [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.height_pixel]
|
||
|
mul rcx
|
||
|
|
||
|
; convert to pages
|
||
|
add rax, ~STATIC_PAGE_mask
|
||
|
shr rax, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; share framebuffer memory space with process
|
||
|
xor ecx, ecx ; no framebuffer manager, if error on below function
|
||
|
xchg rcx, rax ; length of shared space in pages
|
||
|
mov rsi, qword [r8 + KERNEL_STRUCTURE.framebuffer_base_address]
|
||
|
mov r11, qword [r9 + KERNEL_TASK_STRUCTURE.cr3]
|
||
|
call kernel_memory_share
|
||
|
jc .return ; no enough memory?
|
||
|
|
||
|
; return pointer to shared memory of framebuffer
|
||
|
mov qword [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.base_address], rax
|
||
|
|
||
|
; new framebuffer manager
|
||
|
mov rax, qword [r9 + KERNEL_TASK_STRUCTURE.pid]
|
||
|
mov qword [r8 + KERNEL_STRUCTURE.framebuffer_pid], rax
|
||
|
|
||
|
.return:
|
||
|
; inform about framebuffer manager
|
||
|
mov qword [rdi + LIB_SYS_STRUCTURE_FRAMEBUFFER.pid], rax
|
||
|
|
||
|
; restore original registers
|
||
|
pop r11
|
||
|
pop r9
|
||
|
pop r8
|
||
|
pop rsi
|
||
|
pop rdx
|
||
|
pop rcx
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - ID of target process
|
||
|
; rsi - pointer to message data
|
||
|
kernel_service_ipc_send:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push r8
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
.lock:
|
||
|
; request an exclusive access
|
||
|
mov cl, LOCK
|
||
|
lock xchg byte [r8 + KERNEL_STRUCTURE.ipc_semaphore], cl
|
||
|
|
||
|
; assigned?
|
||
|
test cl, cl
|
||
|
jnz .lock ; no
|
||
|
|
||
|
.restart:
|
||
|
; amount of entries
|
||
|
mov rcx, KERNEL_IPC_limit
|
||
|
|
||
|
; set pointer to first message
|
||
|
mov rdx, qword [r8 + KERNEL_STRUCTURE.ipc_base_address]
|
||
|
|
||
|
.loop:
|
||
|
; free entry?
|
||
|
mov rax, qword [r8 + KERNEL_STRUCTURE.hpet_microtime]
|
||
|
cmp qword [rdx + LIB_SYS_STRUCTURE_IPC.ttl], rax
|
||
|
jbe .found ; yes
|
||
|
|
||
|
; next entry from list
|
||
|
add rdx, LIB_SYS_STRUCTURE_IPC.SIZE
|
||
|
|
||
|
; end of message list?
|
||
|
dec rcx
|
||
|
jz .restart ; yes
|
||
|
|
||
|
; no
|
||
|
jmp .loop
|
||
|
|
||
|
.found:
|
||
|
; set message time out
|
||
|
add rax, KERNEL_IPC_timeout
|
||
|
mov qword [rdx + LIB_SYS_STRUCTURE_IPC.ttl], rax
|
||
|
|
||
|
; set message source
|
||
|
call kernel_task_pid
|
||
|
mov qword [rdx + LIB_SYS_STRUCTURE_IPC.source], rax
|
||
|
|
||
|
; set message target
|
||
|
mov qword [rdx + LIB_SYS_STRUCTURE_IPC.target], rdi
|
||
|
|
||
|
; load data into message
|
||
|
mov ecx, LIB_SYS_IPC_DATA_size_byte
|
||
|
mov rdi, rdx
|
||
|
add rdi, LIB_SYS_STRUCTURE_IPC.data
|
||
|
rep movsb
|
||
|
|
||
|
.end:
|
||
|
; release access
|
||
|
mov byte [r8 + KERNEL_STRUCTURE.ipc_semaphore], UNLOCK
|
||
|
|
||
|
; restore original registers
|
||
|
pop r8
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to message descriptor
|
||
|
; sil - message type
|
||
|
; out:
|
||
|
; TRUE if message retrieved
|
||
|
kernel_service_ipc_receive:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rdi
|
||
|
push r8
|
||
|
push rsi
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
.lock:
|
||
|
; request an exclusive access
|
||
|
mov cl, LOCK
|
||
|
lock xchg byte [r8 + KERNEL_STRUCTURE.ipc_semaphore], cl
|
||
|
|
||
|
; assigned?
|
||
|
test cl, cl
|
||
|
jnz .lock ; no
|
||
|
|
||
|
; retrieve ID of current process
|
||
|
call kernel_task_pid
|
||
|
|
||
|
; amount of entries
|
||
|
mov rcx, KERNEL_IPC_limit
|
||
|
|
||
|
; set pointer to first message
|
||
|
mov rsi, qword [r8 + KERNEL_STRUCTURE.ipc_base_address]
|
||
|
|
||
|
.loop:
|
||
|
; message alive?
|
||
|
mov rbx, qword [r8 + KERNEL_STRUCTURE.hpet_microtime]
|
||
|
cmp qword [rsi + LIB_SYS_STRUCTURE_IPC.ttl], rbx
|
||
|
ja .check ; yes
|
||
|
|
||
|
.next:
|
||
|
; next entry from list?
|
||
|
add rsi, LIB_SYS_STRUCTURE_IPC.SIZE
|
||
|
dec rcx
|
||
|
jnz .loop ; yes
|
||
|
|
||
|
; no message for us
|
||
|
xor eax, eax
|
||
|
|
||
|
; no
|
||
|
jmp .end
|
||
|
|
||
|
.check:
|
||
|
; message type selected?
|
||
|
cmp byte [rsp], LIB_SYS_IPC_TYPE_ANY
|
||
|
je .any ; no
|
||
|
|
||
|
; requested message type?
|
||
|
mov bl, byte [rsp]
|
||
|
cmp bl, byte [rsi + LIB_SYS_STRUCTURE_IPC.data + LIB_SYS_STRUCTURE_IPC_DEFAULT.type]
|
||
|
jne .next ; no
|
||
|
|
||
|
.any:
|
||
|
; message for us?
|
||
|
cmp qword [rsi + LIB_SYS_STRUCTURE_IPC.target], rax
|
||
|
jne .next ; no
|
||
|
|
||
|
; preserve original register
|
||
|
push rsi
|
||
|
|
||
|
; load message to process descriptor
|
||
|
mov ecx, LIB_SYS_STRUCTURE_IPC.SIZE
|
||
|
rep movsb
|
||
|
|
||
|
; restore original register
|
||
|
pop rsi
|
||
|
|
||
|
; release entry
|
||
|
mov qword [rsi + LIB_SYS_STRUCTURE_IPC.ttl], EMPTY
|
||
|
|
||
|
; message transferred
|
||
|
mov eax, TRUE
|
||
|
|
||
|
.end:
|
||
|
; release access
|
||
|
mov byte [r8 + KERNEL_STRUCTURE.ipc_semaphore], UNLOCK
|
||
|
|
||
|
; restore original registers
|
||
|
pop rsi
|
||
|
pop r8
|
||
|
pop rdi
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - length of space in Bytes
|
||
|
; out:
|
||
|
; rax - pointer to allocated space
|
||
|
; or EMPTY if no enough memory
|
||
|
kernel_service_memory_alloc:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push r8
|
||
|
push r9
|
||
|
push r11
|
||
|
|
||
|
; convert size to pages (align up to page boundaries)
|
||
|
add rdi, ~STATIC_PAGE_mask
|
||
|
shr rdi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; set pointer of process paging array
|
||
|
mov r11, qword [r9 + KERNEL_TASK_STRUCTURE.cr3]
|
||
|
|
||
|
; aquire memory space from process memory map
|
||
|
mov r9, qword [r9 + KERNEL_TASK_STRUCTURE.memory_map]
|
||
|
mov rcx, rdi ; number of pages
|
||
|
call kernel_memory_acquire
|
||
|
jc .error ; no enough memory
|
||
|
|
||
|
; convert first page number to logical address
|
||
|
shl rdi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; assign pages to allocated memory in process space
|
||
|
mov rax, rdi
|
||
|
mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write | KERNEL_PAGE_FLAG_user | KERNEL_PAGE_FLAG_process
|
||
|
call kernel_page_alloc
|
||
|
jnc .allocated ; space allocated
|
||
|
|
||
|
; take back modifications
|
||
|
mov rsi, rcx
|
||
|
call kernel_service_memory_release
|
||
|
|
||
|
.error:
|
||
|
; no enough memory
|
||
|
xor eax, eax
|
||
|
|
||
|
; end
|
||
|
jmp .end
|
||
|
|
||
|
.allocated:
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; process memory usage
|
||
|
add qword [r9 + KERNEL_TASK_STRUCTURE.page], rcx
|
||
|
|
||
|
.end:
|
||
|
; restore original registers
|
||
|
pop r11
|
||
|
pop r9
|
||
|
pop r8
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to allocated space
|
||
|
; rsi - length of space in Bytes
|
||
|
kernel_service_memory_release:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push r9
|
||
|
push r11
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; convert bytes to pages
|
||
|
add rsi, ~STATIC_PAGE_mask
|
||
|
shr rsi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; pointer and counter at place
|
||
|
mov rcx, rsi
|
||
|
mov rsi, rdi
|
||
|
|
||
|
.loop:
|
||
|
; delete first physical page from logical address
|
||
|
mov r11, qword [r9 + KERNEL_TASK_STRUCTURE.cr3]
|
||
|
call kernel_page_remove
|
||
|
|
||
|
; page removed?
|
||
|
test rax, rax
|
||
|
jnz .release ; yes
|
||
|
|
||
|
; convert to page number
|
||
|
shr rsi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; continue
|
||
|
jmp .next
|
||
|
|
||
|
.release:
|
||
|
; release page inside kernels binary memory map
|
||
|
mov rdi, rax
|
||
|
or rdi, qword [kernel_page_mirror]
|
||
|
call kernel_memory_release_page
|
||
|
|
||
|
; release page inside process binary memory map
|
||
|
shr rsi, STATIC_PAGE_SIZE_shift
|
||
|
mov rdi, qword [r9 + KERNEL_TASK_STRUCTURE.memory_map]
|
||
|
bts qword [rdi], rsi
|
||
|
|
||
|
; process memory usage
|
||
|
dec qword [r9 + KERNEL_TASK_STRUCTURE.page]
|
||
|
|
||
|
.next:
|
||
|
; next page from space
|
||
|
inc rsi
|
||
|
shl rsi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; another page?
|
||
|
dec rcx
|
||
|
jnz .loop ; yes
|
||
|
|
||
|
; restore original registers
|
||
|
pop r11
|
||
|
pop r9
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to source memory space
|
||
|
; rsi - length of space in Bytes
|
||
|
; rdx - target process ID
|
||
|
; out:
|
||
|
; rax - pointer to shared memory between processes
|
||
|
kernel_service_memory_share:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push r9
|
||
|
push r11
|
||
|
|
||
|
; convert Bytes to pages
|
||
|
mov rcx, rsi
|
||
|
add rcx, ~STATIC_PAGE_mask
|
||
|
shr rcx, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; retrieve task paging structure pointer
|
||
|
call kernel_task_by_id
|
||
|
mov r11, qword [rbx + KERNEL_TASK_STRUCTURE.cr3]
|
||
|
|
||
|
; set source pointer in place
|
||
|
mov rsi, rdi
|
||
|
|
||
|
; acquire memory space from target process
|
||
|
mov r9, qword [rbx + KERNEL_TASK_STRUCTURE.memory_map]
|
||
|
call kernel_memory_acquire
|
||
|
|
||
|
; convert page number to offset
|
||
|
shl rdi, STATIC_PAGE_SIZE_shift
|
||
|
|
||
|
; connect memory space of parent process with child
|
||
|
mov rax, rdi
|
||
|
mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write | KERNEL_PAGE_FLAG_user | KERNEL_PAGE_FLAG_process | KERNEL_PAGE_FLAG_shared
|
||
|
call kernel_page_clang
|
||
|
|
||
|
; restore original registers
|
||
|
pop r11
|
||
|
pop r9
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; out:
|
||
|
; rax - PID of current task
|
||
|
kernel_service_task_pid:
|
||
|
; preserve original registers
|
||
|
push r9
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
call kernel_task_active
|
||
|
|
||
|
; set pointer of process paging array
|
||
|
mov rax, qword [r9 + KERNEL_TASK_STRUCTURE.pid]
|
||
|
|
||
|
; restore original registers
|
||
|
pop r9
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - process ID
|
||
|
; out:
|
||
|
; ax - task status
|
||
|
kernel_service_task_status:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rdx
|
||
|
|
||
|
; retrieve pointer to current task descriptor
|
||
|
mov rdx, rdi
|
||
|
call kernel_task_by_id
|
||
|
|
||
|
; by default not found
|
||
|
xor ax, ax
|
||
|
|
||
|
; not found?
|
||
|
test rbx, rbx
|
||
|
jz .error ; yep
|
||
|
|
||
|
; set pointer of process paging array
|
||
|
mov ax, word [rbx + KERNEL_TASK_STRUCTURE.flags]
|
||
|
|
||
|
.error:
|
||
|
; restore original registers
|
||
|
pop rdx
|
||
|
pop rbx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - ASCII character
|
||
|
kernel_service_serial_char:
|
||
|
; preserve original register
|
||
|
push rax
|
||
|
|
||
|
; send character to serial
|
||
|
mov al, dil
|
||
|
call driver_serial_char
|
||
|
|
||
|
; restore original register
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to string
|
||
|
; rsi - length of string in Bytes
|
||
|
kernel_service_serial_string:
|
||
|
; preserve original registers
|
||
|
push rcx
|
||
|
push rsi
|
||
|
|
||
|
; send string to serial
|
||
|
mov rcx, rsi
|
||
|
mov rsi, rdi
|
||
|
call driver_serial_string
|
||
|
|
||
|
; restore original registers
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - value
|
||
|
; sil - base
|
||
|
; rdx - prefix length
|
||
|
; cl - TRUE/FALSE signed value?
|
||
|
kernel_service_serial_value:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rdx
|
||
|
|
||
|
; send value to serial
|
||
|
mov rax, rdi
|
||
|
movzx ebx, sil
|
||
|
xchg rcx, rdx
|
||
|
call driver_serial_value
|
||
|
|
||
|
; restore original registers
|
||
|
pop rdx
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to file descriptor
|
||
|
kernel_service_storage_read:
|
||
|
; preserve original registers
|
||
|
push rax
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rsi
|
||
|
push rbp
|
||
|
push r8
|
||
|
push r9
|
||
|
push r11
|
||
|
push rdi
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
; prepare space for file descriptor
|
||
|
sub rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE
|
||
|
mov rbp, rsp ; pointer of file descriptor
|
||
|
|
||
|
; get file properties
|
||
|
movzx eax, byte [r8 + KERNEL_STRUCTURE.storage_root_id]
|
||
|
movzx ecx, byte [rdi + LIB_SYS_STRUCTURE_STORAGE.length]
|
||
|
lea rsi, [rdi + LIB_SYS_STRUCTURE_STORAGE.name]
|
||
|
call kernel_storage_file
|
||
|
|
||
|
; file found?
|
||
|
cmp qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY
|
||
|
je .end ; no
|
||
|
|
||
|
; prepare space for file content
|
||
|
mov rdi, qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.size_byte]
|
||
|
call kernel_service_memory_alloc
|
||
|
|
||
|
; no enough memory?
|
||
|
test rax, rax
|
||
|
jz .end ; yes
|
||
|
|
||
|
; load file content into prepared space
|
||
|
mov rsi, qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id]
|
||
|
mov rdi, rax
|
||
|
movzx eax, byte [r8 + KERNEL_STRUCTURE.storage_root_id]
|
||
|
call kernel_storage_read
|
||
|
|
||
|
; retrieve current task pointer
|
||
|
call kernel_task_active
|
||
|
|
||
|
; restore file descriptor
|
||
|
mov rax, qword [rsp + KERNEL_STORAGE_STRUCTURE_FILE.SIZE]
|
||
|
|
||
|
; inform process about file location and size
|
||
|
push qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.size_byte]
|
||
|
pop qword [rax + LIB_SYS_STRUCTURE_STORAGE.size_byte]
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_STORAGE.address], rdi
|
||
|
|
||
|
.end:
|
||
|
; remove file descriptor from stack
|
||
|
add rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE
|
||
|
|
||
|
; restore original registers
|
||
|
pop rdi
|
||
|
pop r11
|
||
|
pop r9
|
||
|
pop r8
|
||
|
pop rbp
|
||
|
pop rsi
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
pop rax
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; out:
|
||
|
; rax - pointer to list of first task descriptor
|
||
|
kernel_service_task:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rdx
|
||
|
push rsi
|
||
|
push rdi
|
||
|
push r8
|
||
|
push r10
|
||
|
|
||
|
; kernel environment variables/rountines base address
|
||
|
mov r8, qword [kernel_environment_base_address]
|
||
|
|
||
|
.lock:
|
||
|
; request an exclusive access
|
||
|
mov al, LOCK
|
||
|
lock xchg byte [r8 + KERNEL_STRUCTURE.task_queue_semaphore], al
|
||
|
|
||
|
; assigned?
|
||
|
test al, al
|
||
|
jnz .lock ; no
|
||
|
|
||
|
; length of tasks descriptors in Bytes
|
||
|
mov eax, LIB_SYS_STRUCTURE_TASK.SIZE
|
||
|
mul qword [r8 + KERNEL_STRUCTURE.task_count]
|
||
|
|
||
|
; assign place for task descriptor list
|
||
|
mov rdi, rax
|
||
|
add rdi, STATIC_QWORD_SIZE_byte << STATIC_MULTIPLE_BY_2_shift
|
||
|
call kernel_service_memory_alloc
|
||
|
|
||
|
; store information about size of this space
|
||
|
add rdi, ~STATIC_PAGE_mask
|
||
|
shr rdi, STATIC_PAGE_SIZE_shift
|
||
|
mov qword [rax], rdi
|
||
|
|
||
|
; parse every entry
|
||
|
mov rbx, KERNEL_TASK_limit
|
||
|
mov r10, qword [r8 + KERNEL_STRUCTURE.task_queue_address]
|
||
|
|
||
|
; preserve memory space pointer of tasks descriptors
|
||
|
add rax, STATIC_QWORD_SIZE_byte << STATIC_MULTIPLE_BY_2_shift
|
||
|
push rax
|
||
|
|
||
|
.loop:
|
||
|
; entry exist?
|
||
|
cmp word [r10 + KERNEL_TASK_STRUCTURE.flags], EMPTY
|
||
|
je .next ; no
|
||
|
|
||
|
; do not pass kernel entry
|
||
|
cmp qword [r10 + KERNEL_TASK_STRUCTURE.pid], EMPTY
|
||
|
je .next
|
||
|
|
||
|
; share default information about task
|
||
|
|
||
|
; process ID
|
||
|
mov rdx, qword [r10 + KERNEL_TASK_STRUCTURE.pid]
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_TASK.pid], rdx
|
||
|
|
||
|
; process parents ID
|
||
|
mov rdx, qword [r10 + KERNEL_TASK_STRUCTURE.pid_parent]
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_TASK.pid_parent], rdx
|
||
|
|
||
|
; wake up process micotime
|
||
|
mov rdx, qword [r10 + KERNEL_TASK_STRUCTURE.sleep]
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_TASK.sleep], rdx
|
||
|
|
||
|
; amount of pages used by process
|
||
|
mov rdx, qword [r10 + KERNEL_TASK_STRUCTURE.page]
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_TASK.page], rdx
|
||
|
|
||
|
; current task status
|
||
|
mov dx, word [r10 + KERNEL_TASK_STRUCTURE.flags]
|
||
|
mov word [rax + LIB_SYS_STRUCTURE_TASK.flags], dx
|
||
|
|
||
|
; taks name length
|
||
|
movzx ecx, byte [r10 + KERNEL_TASK_STRUCTURE.length]
|
||
|
mov byte [rax + LIB_SYS_STRUCTURE_TASK.length], cl
|
||
|
|
||
|
; task name itself
|
||
|
lea rsi, [r10 + KERNEL_TASK_STRUCTURE.name]
|
||
|
lea rdi, [rax + LIB_SYS_STRUCTURE_TASK.name]
|
||
|
rep movsb
|
||
|
|
||
|
; next task descriptor position
|
||
|
add rax, LIB_SYS_STRUCTURE_TASK.SIZE
|
||
|
|
||
|
.next:
|
||
|
; move pointer to next entry of task table
|
||
|
add r10, KERNEL_TASK_STRUCTURE.SIZE
|
||
|
|
||
|
; end of tasks inside table?
|
||
|
dec rbx
|
||
|
jnz .loop ; no
|
||
|
|
||
|
; last entry set as empty
|
||
|
mov qword [rax + LIB_SYS_STRUCTURE_TASK.pid], EMPTY
|
||
|
|
||
|
; return memory pointer of tasks descriptors
|
||
|
pop rax
|
||
|
|
||
|
; release access
|
||
|
mov byte [r8 + KERNEL_STRUCTURE.task_queue_semaphore], UNLOCK
|
||
|
|
||
|
; restore original registers
|
||
|
pop r10
|
||
|
pop r8
|
||
|
pop rdi
|
||
|
pop rsi
|
||
|
pop rdx
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
|
||
|
; return from routine
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------------
|
||
|
; in:
|
||
|
; rdi - pointer to function of current task to execute as thread
|
||
|
; rsi - pointer to string as name of thread
|
||
|
; rdx - length of that string
|
||
|
;out:
|
||
|
; rax - process ID of thread
|
||
|
kernel_service_thread:
|
||
|
; preserve original registers
|
||
|
push rbx
|
||
|
push rcx
|
||
|
push rdx
|
||
|
push rsi
|
||
|
push r9
|
||
|
push r10
|
||
|
push r11
|
||
|
push r15
|
||
|
push rdi
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; prepare task for execution
|
||
|
;-----------------------------------------------------------------------
|
||
|
|
||
|
; register new task on queue
|
||
|
mov rcx, rdx
|
||
|
call kernel_task_add
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; paging array of new process
|
||
|
;-----------------------------------------------------------------------
|
||
|
|
||
|
; make space for the process paging table
|
||
|
call kernel_memory_alloc_page
|
||
|
|
||
|
; update task entry about paging array
|
||
|
mov qword [r10 + KERNEL_TASK_STRUCTURE.cr3], rdi
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; context stack and return point (initialization entry)
|
||
|
;-----------------------------------------------------------------------
|
||
|
|
||
|
; describe the space under context stack of process
|
||
|
mov rax, KERNEL_TASK_STACK_address
|
||
|
mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write | KERNEL_PAGE_FLAG_process
|
||
|
mov ecx, KERNEL_TASK_STACK_SIZE_page
|
||
|
mov r11, rdi
|
||
|
call kernel_page_alloc
|
||
|
|
||
|
; set process context stack pointer
|
||
|
mov rsi, KERNEL_TASK_STACK_pointer - (KERNEL_EXEC_STRUCTURE_RETURN.SIZE + KERNEL_EXEC_STACK_OFFSET_registers)
|
||
|
mov qword [r10 + KERNEL_TASK_STRUCTURE.rsp], rsi
|
||
|
|
||
|
; prepare exception exit mode on context stack of process
|
||
|
mov rsi, KERNEL_TASK_STACK_pointer - STATIC_PAGE_SIZE_byte
|
||
|
call kernel_page_address
|
||
|
|
||
|
; set pointer to return descriptor
|
||
|
and rax, STATIC_PAGE_mask ; drop flags
|
||
|
add rax, qword [kernel_page_mirror] ; convert to logical address
|
||
|
add rax, STATIC_PAGE_SIZE_byte - KERNEL_EXEC_STRUCTURE_RETURN.SIZE
|
||
|
|
||
|
; set first instruction executed by thread
|
||
|
mov rdx, qword [rsp]
|
||
|
mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.rip], rdx
|
||
|
|
||
|
; code descriptor
|
||
|
mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.cs], KERNEL_GDT_STRUCTURE.cs_ring3 | 0x03
|
||
|
|
||
|
; default processor state flags
|
||
|
mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.eflags], KERNEL_TASK_EFLAGS_default
|
||
|
|
||
|
; default stack pointer
|
||
|
mov rdx, KERNEL_EXEC_STACK_pointer - 0x10 ; no args
|
||
|
mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.rsp], rdx
|
||
|
|
||
|
; stack descriptor
|
||
|
mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.ss], KERNEL_GDT_STRUCTURE.ds_ring3 | 0x03
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; stack
|
||
|
;-----------------------------------------------------------------------
|
||
|
|
||
|
; alloc stack space
|
||
|
mov rcx, KERNEL_EXEC_STACK_SIZE_page
|
||
|
call kernel_memory_alloc
|
||
|
|
||
|
; map executable space to thread paging array
|
||
|
mov rax, KERNEL_EXEC_STACK_address
|
||
|
or bx, KERNEL_PAGE_FLAG_user
|
||
|
mov rsi, rdi
|
||
|
sub rsi, qword [kernel_page_mirror]
|
||
|
call kernel_page_map
|
||
|
|
||
|
; process memory usage
|
||
|
add qword [r10 + KERNEL_TASK_STRUCTURE.page], rcx
|
||
|
|
||
|
; process stack size
|
||
|
add qword [r10 + KERNEL_TASK_STRUCTURE.stack], rcx
|
||
|
|
||
|
; aquire parent task properties
|
||
|
call kernel_task_active
|
||
|
|
||
|
; threads use same memory map as parent
|
||
|
mov rax, qword [r9 + KERNEL_TASK_STRUCTURE.memory_map]
|
||
|
mov qword [r10 + KERNEL_TASK_STRUCTURE.memory_map], rax
|
||
|
|
||
|
; threads use same streams as parent
|
||
|
|
||
|
; in
|
||
|
mov rax, qword [r9 + KERNEL_TASK_STRUCTURE.stream_in]
|
||
|
inc qword [rax + KERNEL_STREAM_STRUCTURE.count]
|
||
|
mov qword [r10 + KERNEL_TASK_STRUCTURE.stream_in], rax
|
||
|
|
||
|
; out
|
||
|
mov rax, qword [r9 + KERNEL_TASK_STRUCTURE.stream_out]
|
||
|
inc qword [rax + KERNEL_STREAM_STRUCTURE.count]
|
||
|
mov qword [r10 + KERNEL_TASK_STRUCTURE.stream_out], rax
|
||
|
|
||
|
; map kernel space to process
|
||
|
mov r15, qword [r9 + KERNEL_TASK_STRUCTURE.cr3]
|
||
|
or r15, qword [kernel_page_mirror]
|
||
|
call kernel_page_merge
|
||
|
|
||
|
; mark thread as ready
|
||
|
or word [r10 + KERNEL_TASK_STRUCTURE.flags], KERNEL_TASK_FLAG_active | KERNEL_TASK_FLAG_thread | KERNEL_TASK_FLAG_init
|
||
|
|
||
|
; return process ID of new thread
|
||
|
mov rax, qword [r10 + KERNEL_TASK_STRUCTURE.pid]
|
||
|
|
||
|
; restore original registers
|
||
|
pop rdi
|
||
|
pop r15
|
||
|
pop r11
|
||
|
pop r10
|
||
|
pop r9
|
||
|
pop rsi
|
||
|
pop rdx
|
||
|
pop rcx
|
||
|
pop rbx
|
||
|
|
||
|
; end of routine
|
||
|
ret
|