kolibrios/kernel/trunk/kernel.asm

4533 lines
121 KiB
NASM
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (C) KolibriOS team 2004-2022. All rights reserved.
;; Kernel programmers are acknowledged in CREDITS.TXT
;;
;; Data in this file was originally part of MenuetOS project which is
;; distributed under the terms of GNU GPL. It is modified and redistributed as
;; part of KolibriOS project under the terms of GNU GPL.
;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa
;;
;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY
;; WARRANTY. No author or distributor accepts responsibility to anyone for the
;; consequences of using it or for whether it serves any particular purpose or
;; works at all, unless he says so in writing. Refer to the GNU General Public
;; License (the "GPL") for full details.
;
;; Everyone is granted permission to copy, modify and redistribute KolibriOS,
;; but only under the conditions described in the GPL. A copy of this license
;; is supposed to have been given to you along with KolibriOS so you can know
;; your rights and responsibilities. It should be in a file named COPYING.
;; Among other things, the copyright notice and this notice must be preserved
;; on all copies.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as "mnt"
include 'macros.inc'
include 'struct.inc'
$Revision$
USE_COM_IRQ = 1 ; make irq 3 and irq 4 available for PCI devices
VESA_1_2_VIDEO = 0 ; enable vesa 1.2 bank switch functions
; Enabling the next line will enable serial output console
;debug_com_base = 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
include "proc32.inc"
include "kglobals.inc"
include "lang.inc"
include "encoding.inc"
include "const.inc"
iglobal
; The following variable, if equal to 1, duplicates debug output to the screen.
debug_direct_print db 0
; Start the first app (LAUNCHER) after kernel is loaded? (1=yes, 2 or 0=no)
launcher_start db 1
endg
max_processes = 255
tss_step = 128 + 8192 ; tss & i/o - 65535 ports, * 256=557056*4
os_stack = os_data_l - gdts ; GDTs
os_code = os_code_l - gdts
graph_data = 3 + graph_data_l - gdts
tss0 = tss0_l - gdts
app_code = 3 + app_code_l - gdts
app_data = 3 + app_data_l - gdts
app_tls = 3 + tls_data_l - gdts
pci_code_sel = pci_code_32-gdts
pci_data_sel = pci_data_32-gdts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Included files:
;;
;; Kernel16.inc
;; - Booteng.inc English text for bootup
;; - Bootcode.inc Hardware setup
;; - Pci16.inc PCI functions
;;
;; Kernel32.inc
;; - Sys32.inc Process management
;; - Shutdown.inc Shutdown and restart
;; - Fat32.inc Read / write hd
;; - Vesa12.inc Vesa 1.2 driver
;; - Vesa20.inc Vesa 2.0 driver
;; - Vga.inc VGA driver
;; - Stack.inc Network interface
;; - Mouse.inc Mouse pointer
;; - Scincode.inc Window skinning
;; - Pci32.inc PCI functions
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; In bios boot mode the kernel code below is appended to bootbios.bin file.
; That is a loading and initialization code that also draws the blue screen
; menu with svn revision number near top right corner of the screen. This fasm
; preprocessor code searches for '****' signature inside bootbios.bin and
; places revision number there.
if ~ defined UEFI
bootbios:
if defined extended_primary_loader
file 'bootbios.bin.ext_loader'
else if defined pretest_build
file 'bootbios.bin.pretest'
else
file 'bootbios.bin'
end if
if __REV__ > 0
cur_pos = 0
cnt = 0
repeat $ - bootbios
load a byte from %
if a = '*'
cnt = cnt + 1
else
cnt = 0
end if
if cnt = 4
cur_pos = % - 1
break
end if
end repeat
store byte ' ' at cur_pos + 1
rev_var = __REV__
while rev_var > 0
store byte rev_var mod 10 + '0' at cur_pos
cur_pos = cur_pos - 1
rev_var = rev_var / 10
end while
store byte ' ' at cur_pos
store dword ' SVN' at cur_pos - 4
end if
end if
use32
org $+0x10000
align 4
B32:
mov ax, os_stack ; Selector for os
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, TMP_STACK_TOP ; Set stack
; CLEAR 0x280000 - HEAP_BASE
xor eax, eax
mov edi, CLEAN_ZONE
mov ecx, (HEAP_BASE - OS_BASE - CLEAN_ZONE) / 4
cld
rep stosd
; CLEAR KERNEL UNDEFINED GLOBALS
mov edi, endofcode - OS_BASE
mov ecx, 0x90000
sub ecx, edi
shr ecx, 2
rep stosd
; SAVE & CLEAR 0-0xffff
mov edi, 0x1000
mov ecx, 0x8000 / 4
rep stosd
mov edi, 0xa000
mov ecx, 0x6000 / 4
rep stosd
call test_cpu
bts [cpu_caps - OS_BASE], CAPS_TSC ;force use rdtsc
call acpi_locate
call init_BIOS32
; MEMORY MODEL
call mem_test
call init_mem
call init_page_map
; ENABLE PAGING
mov eax, sys_proc - OS_BASE + PROC.pdt_0
mov cr3, eax
mov eax, cr0
or eax, CR0_PG + CR0_WP
mov cr0, eax
lgdt [gdts]
jmp pword os_code:high_code
align 4
bios32_entry dd ?
tmp_page_tabs dd ?
use16
ap_init16:
cli
lgdt [cs:gdts_ap - ap_init16]
mov eax, [cs:cr3_ap - ap_init16]
mov cr3, eax
mov eax, [cs:cr4_ap - ap_init16]
mov cr4, eax
mov eax, CR0_PE + CR0_PG + CR0_WP
mov cr0, eax
jmp pword os_code:ap_init_high
align 16
gdts_ap:
dw gdte-gdts-1
dd gdts
dw 0
cr3_ap dd ?
cr4_ap dd ?
ap_init16_size = $ - ap_init16
use32
__DEBUG__ fix 1
__DEBUG_LEVEL__ fix 1
include 'init.inc'
org OS_BASE+$
include 'fdo.inc'
align 4
high_code:
mov ax, os_stack
mov bx, app_data
mov cx, app_tls
mov ss, ax
add esp, OS_BASE
mov ds, bx
mov es, bx
mov fs, cx
mov gs, bx
xor eax, eax
mov ebx, 0xFFFFF000 + PG_SHARED + PG_NOCACHE + PG_UWR
bt [cpu_caps], CAPS_PAT
setc al
shl eax, 7
or ebx, eax
mov eax, PG_GLOBAL
bt [cpu_caps], CAPS_PGE
jnc @F
or [sys_proc + PROC.pdt_0 + (OS_BASE shr 20)], eax
or ebx, eax
mov eax, cr4
or eax, CR4_PGE
mov cr4, eax
@@:
mov [pte_valid_mask], ebx
xor eax, eax
mov dword [sys_proc + PROC.pdt_0], eax
mov dword [sys_proc + PROC.pdt_0+4], eax
mov eax, cr3
mov cr3, eax ; flush TLB
mov ecx, pg_data.mutex
call mutex_init
mov ecx, disk_list_mutex
call mutex_init
mov ecx, keyboard_list_mutex
call mutex_init
mov ecx, unpack_mutex
call mutex_init
mov ecx, application_table_mutex
call mutex_init
mov ecx, ide_mutex
call mutex_init
mov ecx, ide_channel1_mutex
call mutex_init
mov ecx, ide_channel2_mutex
call mutex_init
mov ecx, ide_channel3_mutex
call mutex_init
mov ecx, ide_channel4_mutex
call mutex_init
mov ecx, ide_channel5_mutex
call mutex_init
mov ecx, ide_channel6_mutex
call mutex_init
;-----------------------------------------------------------------------------
; SAVE REAL MODE VARIABLES
;-----------------------------------------------------------------------------
; --------------- APM ---------------------
; init selectors
mov ebx, [BOOT.apm_entry] ; offset of APM entry point
movzx eax, word [BOOT.apm_code_32] ; real-mode segment base address of
; protected-mode 32-bit code segment
movzx ecx, word [BOOT.apm_code_16] ; real-mode segment base address of
; protected-mode 16-bit code segment
movzx edx, word [BOOT.apm_data_16] ; real-mode segment base address of
; protected-mode 16-bit data segment
shl eax, 4
mov [dword apm_code_32 + 2], ax
shr eax, 16
mov [dword apm_code_32 + 4], al
shl ecx, 4
mov [dword apm_code_16 + 2], cx
shr ecx, 16
mov [dword apm_code_16 + 4], cl
shl edx, 4
mov [dword apm_data_16 + 2], dx
shr edx, 16
mov [dword apm_data_16 + 4], dl
mov dword[apm_entry], ebx
mov word [apm_entry + 4], apm_code_32 - gdts
mov eax, dword[BOOT.apm_version] ; version & flags
mov [apm_vf], eax
; -----------------------------------------
mov al, [BOOT.dma] ; DMA access
mov [allow_dma_access], al
mov al, [BOOT.debug_print] ; If nonzero, duplicates debug output to the screen
mov [debug_direct_print], al
mov al, [BOOT.launcher_start] ; Start the first app (LAUNCHER) after kernel is loaded?
mov [launcher_start], al
mov eax, [BOOT.devicesdat_size]
mov [acpi_dev_size], eax
mov eax, [BOOT.devicesdat_data]
mov [acpi_dev_data], eax
mov esi, BOOT.bios_hd
movzx ecx, byte [esi-1]
mov [NumBiosDisks], ecx
mov edi, BiosDisksData
shl ecx, 2
rep movsd
; -------- Fast System Call init ----------
; Intel SYSENTER/SYSEXIT (AMD CPU support it too)
bt [cpu_caps], CAPS_SEP
jnc .SEnP ; SysEnter not Present
xor edx, edx
mov ecx, MSR_SYSENTER_CS
mov eax, os_code
wrmsr
mov ecx, MSR_SYSENTER_ESP
; mov eax, sysenter_stack ; Check it
xor eax, eax
wrmsr
mov ecx, MSR_SYSENTER_EIP
mov eax, sysenter_entry
wrmsr
.SEnP:
; AMD SYSCALL/SYSRET
cmp byte[cpu_vendor], 'A'
jne .noSYSCALL
mov eax, 0x80000001
cpuid
test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support
jz .noSYSCALL
mov ecx, MSR_AMD_EFER
rdmsr
or eax, 1 ; bit_0 - System Call Extension (SCE)
wrmsr
; !!!! It`s dirty hack, fix it !!!
; Bits of EDX :
; Bit 3116 During the SYSRET instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
; Bit 150 During the SYSCALL instruction, this field is copied into the CS register
; and the contents of this field, plus 8, are copied into the SS register.
; mov edx, (os_code + 16) * 65536 + os_code
mov edx, 0x1B0008
mov eax, syscall_entry
mov ecx, MSR_AMD_STAR
wrmsr
.noSYSCALL:
; -----------------------------------------
stdcall alloc_page
stdcall map_page, tss-0xF80, eax, PG_SWR
stdcall alloc_page
stdcall map_page, tss+0x80, eax, PG_SWR
stdcall alloc_page
stdcall map_page, tss+0x1080, eax, PG_SWR
; LOAD IDT
call build_interrupt_table ;lidt is executed
;lidt [idtreg]
call init_kernel_heap
call init_fpu
mov eax, [xsave_area_size]
lea eax, [eax*2 + RING0_STACK_SIZE*2]
stdcall kernel_alloc, eax
mov [os_stack_seg], eax
lea esp, [eax + RING0_STACK_SIZE]
mov [tss._ss0], os_stack
mov [tss._esp0], esp
mov [tss._esp], esp
mov [tss._cs], os_code
mov [tss._ss], os_stack
mov [tss._ds], app_data
mov [tss._es], app_data
mov [tss._fs], app_data
mov [tss._gs], app_data
mov [tss._io], 128
;Add IO access table - bit array of permitted ports
mov edi, tss._io_map_0
xor eax, eax
not eax
mov ecx, 8192/4
rep stosd ; access to 4096*8=65536 ports
mov ax, tss0
ltr ax
mov eax, sys_proc
list_init eax
add eax, PROC.thr_list
list_init eax
call init_video
call init_pat_mtrr
mov [LFBAddress], LFB_BASE
mov ecx, bios_fb
call set_framebuffer
call init_malloc
stdcall alloc_kernel_space, 0x50000 ; FIXME check size
mov [default_io_map], eax
add eax, 0x2000
mov [ipc_tmp], eax
mov ebx, 0x1000
add eax, 0x40000
mov [proc_mem_map], eax
add eax, 0x8000
mov [proc_mem_pdir], eax
add eax, ebx
mov [proc_mem_tab], eax
add eax, ebx
mov [tmp_task_ptab], eax
add eax, ebx
mov [ipc_pdir], eax
add eax, ebx
mov [ipc_ptab], eax
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl \
(unpack.lc + unpack.lp)))*4
mov [unpack.p], eax
call init_events
mov eax, srv.fd - SRV.fd
mov [srv.fd], eax
mov [srv.bk], eax
;Set base of graphic segment to linear address of LFB
mov eax, [LFBAddress] ; set for gs
mov [graph_data_l+2], ax
shr eax, 16
mov [graph_data_l+4], al
mov [graph_data_l+7], ah
stdcall kernel_alloc, [_display.win_map_size]
mov [_display.win_map], eax
xor eax, eax
inc eax
; set background
mov [BgrDrawMode], eax
mov [BgrDataWidth], eax
mov [BgrDataHeight], eax
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
; set clipboard
xor eax, eax
mov [clipboard_slots], eax
mov [clipboard_write_lock], eax
stdcall kernel_alloc, PAGE_SIZE
test eax, eax
jnz @f
dec eax
@@:
mov [clipboard_main_list], eax
call check_acpi
mov eax, [hpet_base]
test eax, eax
jz @F
stdcall map_io_mem, [hpet_base], 1024, PG_GLOBAL + PAT_UC + PG_SWR
mov [hpet_base], eax
mov eax, [eax+HPET_ID]
DEBUGF 1, "K : HPET caps %x\n", eax
call init_hpet
@@:
; SET UP OS TASK
mov esi, boot_setostask
call boot_log
mov edi, sys_proc + PROC.heap_lock
mov ecx, (PROC.ht_free - PROC.heap_lock)/4
xor eax, eax
cld
rep stosd
mov [edi], dword (PROC.pdt_0 - PROC.htab)/4 - 3
mov [edi+4], dword 3 ;reserve handles for stdin stdout and stderr
mov ecx, (PROC.pdt_0 - PROC.htab)/4
add edi, 8
inc eax
@@:
stosd
inc eax
cmp eax, ecx
jbe @B
mov [sys_proc + PROC.pdt_0_phys], sys_proc - OS_BASE + PROC.pdt_0
mov eax, -1
mov edi, thr_slot_map+4
mov [edi-4], dword 0xFFFFFFF8
stosd
stosd
stosd
stosd
stosd
stosd
stosd
mov [current_process], sys_proc
mov edx, SLOT_BASE + sizeof.APPDATA*1
mov ebx, [os_stack_seg]
add ebx, RING0_STACK_SIZE
add ebx, [xsave_area_size]
call setup_os_slot
mov dword [edx], 'IDLE'
sub [edx + APPDATA.saved_esp], 4
mov eax, [edx + APPDATA.saved_esp]
mov dword [eax], idle_thread
mov ecx, IDLE_PRIORITY
call scheduler_add_thread
mov edx, SLOT_BASE + sizeof.APPDATA*2
mov ebx, [os_stack_seg]
call setup_os_slot
mov dword [edx], 'OS'
xor ecx, ecx
call scheduler_add_thread
mov dword [current_slot_idx], 2
mov [thread_count], 2
mov dword [current_slot], SLOT_BASE + sizeof.APPDATA*2
; Move other CPUs to deep sleep, if it is useful
uglobal
use_mwait_for_idle db 0
endg
cmp [cpu_vendor+8], 'ntel'
jnz .no_wake_cpus
bt [cpu_caps+4], CAPS_MONITOR-32
jnc .no_wake_cpus
dbgstr 'using mwait for idle loop'
inc [use_mwait_for_idle]
mov ebx, [cpu_count]
cmp ebx, 1
jbe .no_wake_cpus
call create_trampoline_pgmap
mov [cr3_ap + OS_BASE], eax
mov eax, cr4
mov [cr4_ap + OS_BASE], eax
mov esi, OS_BASE + ap_init16
mov edi, OS_BASE + 8000h
mov ecx, (ap_init16_size + 3) / 4
rep movsd
mov eax, [LAPIC_BASE]
test eax, eax
jnz @f
stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_GLOBAL + PG_NOCACHE + PG_SWR
mov [LAPIC_BASE], eax
@@:
lea edi, [eax + APIC_ICRL]
mov esi, smpt+4
dec ebx
.wake_cpus_loop:
lodsd
push esi
xor esi, esi
inc esi
shl eax, 24
mov [edi+10h], eax
; assert INIT IPI
mov dword [edi], 0C500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; deassert INIT IPI
mov dword [edi], 8500h
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
; send STARTUP IPI
mov dword [edi], 600h + (8000h shr 12)
call delay_ms
@@:
test dword [edi], 1000h
jnz @b
pop esi
dec ebx
jnz .wake_cpus_loop
mov eax, [cpu_count]
dec eax
@@:
cmp [ap_initialized], eax
jnz @b
mov eax, [cr3_ap + OS_BASE]
call free_page
.no_wake_cpus:
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
mov esi, boot_initirq
call boot_log
call init_irqs
mov esi, boot_picinit
call boot_log
call PIC_init
mov esi, boot_v86machine
call boot_log
; Initialize system V86 machine
call init_sys_v86
mov esi, boot_inittimer
call boot_log
; Initialize system timer (IRQ0)
call PIT_init
; Register ramdisk file system
if ~ defined extended_primary_loader
cmp [BOOT.rd_load_from], RD_LOAD_FROM_HD ; will be loaded later
je @f
end if
cmp [BOOT.rd_load_from], RD_LOAD_FROM_NONE
je @f
call register_ramdisk
;--------------------------------------
@@:
mov esi, boot_initapic
call boot_log
; Try to Initialize APIC
call APIC_init
mov esi, boot_enableirq
call boot_log
; Enable timer IRQ (IRQ0) and co-processor IRQ (IRQ13)
; they are used: when partitions are scanned, hd_read relies on timer
call unmask_timer
; Prevent duplicate timer IRQs in APIC mode
cmp [irq_mode], IRQ_APIC
jz @f
stdcall enable_irq, 2 ; @#$%! PIC
@@:
stdcall enable_irq, 13 ; co-processor
; Setup serial output console (if enabled)
if defined debug_com_base
; reserve port so nobody else will use it
xor ebx, ebx
mov ecx, debug_com_base
mov edx, debug_com_base+7
call r_f_port_area
; enable Divisor latch
mov dx, debug_com_base+3
mov al, 1 shl 7
out dx, al
; Set speed to 115200 baud (max speed)
mov dx, debug_com_base
mov al, 0x01
out dx, al
mov dx, debug_com_base+1
mov al, 0x00
out dx, al
; No parity, 8bits words, one stop bit, dlab bit back to 0
mov dx, debug_com_base+3
mov al, 3
out dx, al
; disable interrupts
mov dx, debug_com_base+1
mov al, 0
out dx, al
; clear + enable fifo (64 bits)
mov dx, debug_com_base+2
mov al, 0x7 + 1 shl 5
out dx, al
end if
;-----------------------------------------------------------------------------
; show SVN version of kernel on the message board
;-----------------------------------------------------------------------------
mov eax, [version_inf.rev]
DEBUGF 1, "K : kernel SVN r%d\n", eax
;-----------------------------------------------------------------------------
; show CPU count on the message board
;-----------------------------------------------------------------------------
mov eax, [cpu_count]
test eax, eax
jnz @F
mov al, 1 ; at least one CPU
@@:
DEBUGF 1, "K : %d CPU detected\n", eax
;-----------------------------------------------------------------------------
; detect Floppy drives
;-----------------------------------------------------------------------------
mov esi, boot_detectfloppy
call boot_log
include 'detect/dev_fd.inc'
;-----------------------------------------------------------------------------
; create pci-devices list
;-----------------------------------------------------------------------------
mov [pci_access_enabled], 1
call pci_enum
;-----------------------------------------------------------------------------
; initialisation IDE ATA code
;-----------------------------------------------------------------------------
include 'detect/init_ata.inc'
;-----------------------------------------------------------------------------
; initialisation AHCI code
;-----------------------------------------------------------------------------
jmp ahci_code_end
include 'blkdev/ahci.inc'
ahci_code_end:
call ahci_init
;-----------------------------------------------------------------------------
if 0
mov ax, [BOOT.sys_disk]
cmp ax, 'r1'; if using not ram disk, then load librares and parameters {SPraid.simba}
je no_lib_load
mov esi, boot_loadlibs
call boot_log
; LOADING LIBRARES
stdcall dll.Load, @IMPORT ; loading librares for kernel (.obj files)
call load_file_parse_table ; prepare file parse table
call set_kernel_conf ; configure devices and gui
no_lib_load:
end if
; Display APIC status
mov esi, boot_APIC_found
cmp [irq_mode], IRQ_APIC
je @f
mov esi, boot_APIC_nfound
@@:
call boot_log
; PRINT AMOUNT OF MEMORY
mov esi, boot_memdetect
call boot_log
movzx ecx, word [boot_y]
if lang eq ru
or ecx, (10+30*6) shl 16
else if lang eq sp
or ecx, (10+33*6) shl 16
else
or ecx, (10+29*6) shl 16
end if
sub ecx, 10
mov edx, 0xFFFFFF
mov ebx, [MEM_AMOUNT]
shr ebx, 20
xor edi, edi
mov eax, 0x00040000
inc edi
call display_number_force
; BUILD SCHEDULER
; call build_scheduler; sys32.inc
; mov esi, boot_devices
; call boot_log
include "detect/vortex86.inc" ; Vortex86 SoC detection code
stdcall load_pe_driver, szVidintel, 0
call usb_init
; SET PRELIMINARY WINDOW STACK AND POSITIONS
mov esi, boot_windefs
call boot_log
call set_window_defaults
; SET BACKGROUND DEFAULTS
mov esi, boot_bgr
call boot_log
call init_background
call calculatebackground
; RESERVE SYSTEM IRQ'S JA PORT'S
mov esi, boot_resirqports
call boot_log
call reserve_irqs_ports
mov [SLOT_BASE + APPDATA.window], window_data
mov [SLOT_BASE + sizeof.APPDATA + APPDATA.window], window_data + sizeof.WDATA
mov [SLOT_BASE + sizeof.APPDATA*2 + APPDATA.window], window_data + sizeof.WDATA*2
mov [window_data + WDATA.thread], SLOT_BASE
mov [window_data + sizeof.WDATA + WDATA.thread], SLOT_BASE + sizeof.APPDATA
mov [window_data + sizeof.WDATA*2 + WDATA.thread], SLOT_BASE + sizeof.APPDATA*2
call init_display
mov eax, [def_cursor]
mov [window_data + sizeof.WDATA + WDATA.cursor], eax
mov [window_data + sizeof.WDATA*2 + WDATA.cursor], eax
; PRINT CPU FREQUENCY
mov esi, boot_cpufreq
call boot_log
cli
mov ebx, [hpet_base]
test ebx, ebx
jz @F
mov ebx, [ebx + HPET_COUNTER]
rdtsc
mov ecx, 1000
sub eax, [hpet_tsc_start]
sbb edx, [hpet_tsc_start + 4]
shld edx, eax, 10
shl eax, 10
mov esi, eax
mov eax, edx
mul ecx
xchg eax, esi
mul ecx
adc edx, esi
div ebx
mul ecx
div [hpet_period]
mul ecx
DEBUGF 1, "K : cpu frequency %u Hz\n", eax
jmp .next
@@:
rdtsc
mov ecx, eax
mov esi, 250 ; wait 1/4 a second
call delay_ms
rdtsc
sub eax, ecx
xor edx, edx
shld edx, eax, 2
shl eax, 2
.next:
mov dword [cpu_freq], eax
mov dword [cpu_freq + 4], edx
mov ebx, 1000000
div ebx
mov ebx, eax
movzx ecx, word [boot_y]
if lang eq ru
add ecx, (10+19*6) shl 16 - 10
else if lang eq sp
add ecx, (10+25*6) shl 16 - 10
else
add ecx, (10+17*6) shl 16 - 10
end if
mov edx, 0xFFFFFF
xor edi, edi
mov eax, 0x00040000
inc edi
call display_number_force
; SET VARIABLES
call set_variables
; STACK AND FDC
call stack_init
call fdc_init
; PALETTE FOR 320x200 and 640x480 16 col
cmp [SCR_MODE], word 0x12
jne no_pal_vga
mov esi, boot_pal_vga
call boot_log
call paletteVGA
no_pal_vga:
cmp [SCR_MODE], word 0x13
jne no_pal_ega
mov esi, boot_pal_ega
call boot_log
call palette320x200
no_pal_ega:
; LOAD DEFAULT SKIN
call load_default_skin
; Protect I/O permission map
mov esi, [default_io_map]
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
add esi, 0x1000
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
stdcall map_page, tss._io_map_0, \
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
stdcall map_page, tss._io_map_1, \
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
; SET KEYBOARD PARAMETERS
mov al, 0xf6 ; reset keyboard, scan enabled
call kb_write_wait_ack
test ah, ah
jnz .no_keyboard
iglobal
align 4
ps2_keyboard_functions:
dd .end - $
dd 0 ; no close
dd ps2_set_lights
.end:
endg
stdcall register_keyboard, ps2_keyboard_functions, 0
; mov al, 0xED ; Keyboard LEDs - only for testing!
; call kb_write_wait_ack
; mov al, 111b
; call kb_write_wait_ack
mov al, 0xF3 ; set repeat rate & delay
call kb_write_wait_ack
mov al, 0; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500
call kb_write_wait_ack
;// mike.dld [
call set_lights
;// mike.dld ]
stdcall attach_int_handler, 1, irq1, 0
DEBUGF 1, "K : IRQ1 return code %x\n", eax
.no_keyboard:
; Load PS/2 mouse driver
mov esi, boot_setmouse
call boot_log
stdcall load_pe_driver, szPS2MDriver, 0
; LOAD FIRST APPLICATION
cmp byte [launcher_start], 1 ; Check if starting LAUNCHER is selected on blue screen (1 = yes)
jnz first_app_found
cli
mov ebp, firstapp
call fs_execute_from_sysdir
test eax, eax
jns first_app_found
mov esi, boot_failed
call boot_log
mov eax, 0xDEADBEEF ; otherwise halt
hlt
first_app_found:
; START MULTITASKING
preboot_blogesc = 0 ; start immediately after bootlog
; A 'All set - press ESC to start' messages if need
if preboot_blogesc
mov esi, boot_tasking
call boot_log
.bll1:
in al, 0x60 ; wait for ESC key press
cmp al, 129
jne .bll1
end if
mov [timer_ticks_enable], 1 ; for cd driver
sti
call mtrr_validate
jmp osloop
; Fly :)
uglobal
align 4
ap_initialized dd 0
endg
ap_init_high:
mov ax, os_stack
mov bx, app_data
mov cx, app_tls
mov ss, ax
mov ds, bx
mov es, bx
mov fs, cx
mov gs, bx
xor esp, esp
mov eax, sys_proc - OS_BASE + PROC.pdt_0
mov cr3, eax
lock inc [ap_initialized]
jmp idle_loop
include 'unpacker.inc'
align 4
boot_log:
pushad
mov ebx, 10*65536
mov bx, word [boot_y]
add [boot_y], dword 10
mov ecx, 0x80ffffff; ASCIIZ string with white color
xor edi, edi
mov edx, esi
inc edi
call dtext
mov [novesachecksum], 1000
call checkVga_N13
popad
ret
;-----------------------------------------------------------------------------
; Register ramdisk file system
register_ramdisk:
mov esi, boot_initramdisk
call boot_log
call ramdisk_init
ret
; in: edx -> APPDATA for OS/IDLE slot
; in: ebx = stack base
proc setup_os_slot
xor eax, eax
mov ecx, sizeof.APPDATA/4
mov edi, edx
rep stosd
mov eax, tss+0x80
call get_pg_addr
inc eax
mov [edx + APPDATA.io_map], eax
mov eax, tss+0x1080
call get_pg_addr
inc eax
mov [edx + APPDATA.io_map + 4], eax
mov dword [edx + APPDATA.pl0_stack], ebx
lea edi, [ebx + RING0_STACK_SIZE]
mov dword [edx + APPDATA.fpu_state], edi
mov dword [edx + APPDATA.saved_esp0], edi
mov dword [edx + APPDATA.saved_esp], edi
mov dword [edx + APPDATA.terminate_protection], 1 ; make unkillable
mov esi, fpu_data
mov ecx, [xsave_area_size]
add ecx, 3
shr ecx, 2
rep movsd
lea eax, [edx + APP_EV_OFFSET]
mov dword [edx + APPDATA.fd_ev], eax
mov dword [edx + APPDATA.bk_ev], eax
lea eax, [edx + APP_OBJ_OFFSET]
mov dword [edx + APPDATA.fd_obj], eax
mov dword [edx + APPDATA.bk_obj], eax
mov dword [edx + APPDATA.cur_dir], sysdir_path-2
mov [edx + APPDATA.process], sys_proc
lea ebx, [edx + APPDATA.list]
lea ecx, [sys_proc + PROC.thr_list]
list_add_tail ebx, ecx
mov [edx + APPDATA.wnd_number], dh
mov byte [edx + APPDATA.tid], dh
movzx eax, dh
shl eax, BSF sizeof.WDATA
add eax, window_data
mov [edx + APPDATA.window], eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MAIN OS LOOP START ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32
osloop:
mov edx, osloop_has_work?
xor ecx, ecx
call Wait_events
xor eax, eax
xchg eax, [osloop_nonperiodic_work]
test eax, eax
jz .no_periodic
call __sys_draw_pointer
call window_check_events
call mouse_check_events
call checkmisc
call checkVga_N13
;--------------------------------------
.no_periodic:
call stack_handler
call check_fdd_motor_status
call check_ATAPI_device_event
call check_lights_state
call check_timers
jmp osloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MAIN OS LOOP END ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc osloop_has_work?
cmp [osloop_nonperiodic_work], 0
jnz .yes
call stack_handler_has_work?
jnz .yes
call check_fdd_motor_status_has_work?
jnz .yes
call check_ATAPI_device_event_has_work?
jnz .yes
call check_lights_state_has_work?
jnz .yes
call check_timers_has_work?
jnz .yes
.no:
xor eax, eax
ret
.yes:
xor eax, eax
inc eax
ret
endp
proc wakeup_osloop
mov [osloop_nonperiodic_work], 1
ret
endp
uglobal
align 4
osloop_nonperiodic_work dd ?
endg
uglobal
align 64
idle_addr rb 64
endg
idle_thread:
sti
; The following code can be executed by all CPUs in the system.
; All other parts of the kernel do not expect multi-CPU.
; Also, APs don't even have a stack here.
; Beware. Don't do anything here. Anything at all.
idle_loop:
cmp [use_mwait_for_idle], 0
jnz .mwait
.hlt:
hlt
jmp .hlt
.mwait:
mov eax, idle_addr
xor ecx, ecx
xor edx, edx
monitor
xor ecx, ecx
mov eax, 20h ; or 10h
mwait
jmp .mwait
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; INCLUDED SYSTEM FILES ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include "kernel32.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; KERNEL FUNCTIONS ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
reserve_irqs_ports:
; RESERVE PORTS
mov eax, RESERVED_PORTS
mov ecx, 1
mov [eax], dword 4
mov [eax+16], ecx
mov [eax+16+4], dword 0
mov [eax+16+8], dword 0x2D
mov [eax+32], ecx
mov [eax+32+4], dword 0x30
mov [eax+32+8], dword 0x4D
mov [eax+48], ecx
mov [eax+48+4], dword 0x50
mov [eax+48+8], dword 0xDF
mov [eax+64], ecx
mov [eax+64+4], dword 0xE5
mov [eax+64+8], dword 0xFF
ret
iglobal
process_number dd 0x2
endg
set_variables:
mov ecx, 0x16 ; flush port 0x60
@@:
in al, 0x60
loop @b
push eax
mov ax, [BOOT.y_res]
shr ax, 1
shl eax, 16
mov ax, [BOOT.x_res]
shr ax, 1
mov [MOUSE_X], eax
call wakeup_osloop
xor eax, eax
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list
mov byte [KEY_COUNT], al ; keyboard buffer
mov byte [BTN_COUNT], al ; button buffer
pop eax
ret
;-----------------------------------------------------------------------------
align 4
display_number:
; add check pointers
test bl, bl
jz @f
bt ebx, 30 ; check 30 bit
jb @f
stdcall is_region_userspace, ecx, 4
jz @f
ret
@@:
jz @f
stdcall is_region_userspace, ecx, 8
jz @f
ret
@@:
test esi, 0x08000000
jz @f
stdcall is_region_userspace, edi, 1
jz @f
ret
@@:
;It is not optimization
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
; eax = print type, al=0 -> ebx is number
; al=1 -> ebx is pointer
; ah=0 -> display decimal
; ah=1 -> display hexadecimal
; ah=2 -> display binary
; eax bits 16-21 = number of digits to display (0-32)
; eax bits 22-31 = reserved
;
; ebx = number or pointer
; ecx = x shl 16 + y
; edx = color
xor edi, edi
display_number_force:
push eax
and eax, 0x3fffffff
cmp eax, 0xffff ; length > 0 ?
pop eax
jge .cont_displ
ret
.cont_displ:
push eax
and eax, 0x3fffffff
cmp eax, 61*0x10000 ; length <= 60 ?
pop eax
jb .cont_displ2
ret
.cont_displ2:
pushad
cmp al, 1 ; ecx is a pointer ?
jne @f
mov ebp, ebx
add ebp, 4
mov ebp, [ebp] ;[ebp + std_application_base_address]
mov ebx, [ebx] ;[ebx + std_application_base_address]
@@:
sub esp, 64
test ah, ah ; DECIMAL
jnz .no_display_desnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 10
@@:
xor edx, edx
call division_64_bits
div ebx
add dl, 48
mov [edi], dl
dec edi
loop @b
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
.no_display_desnum:
cmp ah, 0x01 ; HEXADECIMAL
jne .no_display_hexnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 16
@@:
xor edx, edx
call division_64_bits
div ebx
;hexletters = __fdo_hexdigits
add edx, __fdo_hexdigits ;hexletters
mov dl, [edx]
mov [edi], dl
dec edi
loop @b
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
.no_display_hexnum:
cmp ah, 0x02 ; BINARY
jne .no_display_binnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 2
@@:
xor edx, edx
call division_64_bits
div ebx
add dl, 48
mov [edi], dl
dec edi
loop @b
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
.no_display_binnum:
add esp, 64
popad
ret
normalize_number:
test ah, 0x80
jz .continue
mov ecx, 48
and eax, 0x3f
@@:
inc edi
cmp [edi], cl
jne .continue
dec eax
cmp eax, 1
ja @r
mov al, 1
.continue:
and eax, 0x3f
ret
division_64_bits:
test [esp+1+4], byte 0x40
jz .continue
push eax
mov eax, ebp
div ebx
mov ebp, eax
pop eax
.continue:
ret
draw_num_text:
mov esi, eax
mov edx, 64+4
sub edx, eax
add edx, esp
mov ebx, [esp+64+32-8+4]
; add window start x & y
mov ecx, [current_slot]
mov ecx, [ecx + APPDATA.window]
mov eax, [ecx + WDATA.box.left]
add eax, [ecx + WDATA.clientbox.left]
shl eax, 16
add eax, [ecx + WDATA.box.top]
add eax, [ecx + WDATA.clientbox.top]
add ebx, eax
mov ecx, [esp+64+32-12+4]
mov eax, [esp+64+8] ; background color (if given)
mov edi, [esp+64+4]
and ecx, 5FFFFFFFh
bt ecx, 27
jnc @f
mov edi, eax
@@:
jmp dtext
;-----------------------------------------------------------------------------
align 4
sys_setup:
; 1 = roland mpu midi base , base io address
; 2 = keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3 = not used
; 4 = not used
; 5 = system language, 1eng 2fi 3ger 4rus
; 6 = not used
; 7 = not used
; 8 = not used
; 9 = not used
; 10 = not used
; 11 = enable lba read
; 12 = enable pci access
;-----------------------------------------------------------------------------
and [esp + SYSCALL_STACK.eax], dword 0
; F.21.1 - set MPU MIDI base port
dec ebx
jnz @f
cmp ecx, 0x100
jb @f
mov esi, 65535
cmp esi, ecx
jb @f
mov [midi_base], cx
mov word [mididp], cx
inc cx
mov word [midisp], cx
ret
;--------------------------------------
@@:
; F.21.2 - set keyboard layout
dec ebx
jnz @f
mov eax, edx
; 1 = normal layout
dec ecx
jnz .shift
mov ebx, keymap
mov ecx, 128
call memmove
ret
;--------------------------------------
.shift:
; 2 = layout at pressed Shift
dec ecx
jnz .alt
mov ebx, keymap_shift
mov ecx, 128
call memmove
ret
;--------------------------------------
.alt:
; 3 = layout at pressed Alt
dec ecx
jnz .country
mov ebx, keymap_alt
mov ecx, 128
call memmove
ret
;--------------------------------------
.country:
; country identifier
sub ecx, 6
jnz .error
mov word [keyboard], dx
ret
;--------------------------------------
@@:
; F.21.5 - set system language
sub ebx, 3
jnz @f
mov [syslang], ecx
ret
;--------------------------------------
@@:
; F.21.11 - enable/disable low-level access to HD
and ecx, 1
sub ebx, 6
jnz @f
mov [lba_read_enabled], ecx
ret
;--------------------------------------
@@:
; F.21.12 - enable/disable low-level access to PCI
dec ebx
jnz .error
mov [pci_access_enabled], ecx
ret
;--------------------------------------
.error:
or [esp + SYSCALL_STACK.eax], dword -1
ret
;-----------------------------------------------------------------------------
align 4
sys_getsetup:
; 1 = roland mpu midi base , base io address
; 2 = keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3 = not used
; 4 = not used
; 5 = system language, 1eng 2fi 3ger 4rus
; 6 = not used
; 7 = not used
; 8 = not used
; 9 = get hs timer tic
; 10 = not used
; 11 = get the state "lba read"
; 12 = get the state "pci access"
;-----------------------------------------------------------------------------
; F.26.1 - get MPU MIDI base port
dec ebx
jnz @f
movzx eax, [midi_base]
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
@@:
; F.26.2 - get keyboard layout
dec ebx
jnz @f
mov ebx, edx
; if given memory address belongs to kernel then error
stdcall is_region_userspace, ebx, 128
jnz .addr_error
; 1 = normal layout
dec ecx
jnz .shift
mov eax, keymap
mov ecx, 128
call memmove
ret
;--------------------------------------
.shift:
; 2 = layout with pressed Shift
dec ecx
jnz .alt
mov eax, keymap_shift
mov ecx, 128
call memmove
ret
;--------------------------------------
.alt:
; 3 = layout with pressed Alt
dec ecx
jne .country
mov eax, keymap_alt
mov ecx, 128
call memmove
ret
;--------------------------------------
.country:
; 9 = country identifier
sub ecx, 6
jnz .error
movzx eax, word [keyboard]
mov [esp + SYSCALL_STACK.eax], eax
ret
.addr_error: ; if given memory address is illegal
or dword [esp + SYSCALL_STACK.eax], -1
ret
;--------------------------------------
@@:
; F.26.5 - get system language
sub ebx, 3
jnz @f
mov eax, [syslang]
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
@@:
; F.26.9 - get the value of the time counter
sub ebx, 4
jnz @f
mov eax, [timer_ticks]
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
@@:
; F.26.10 - get the time from kernel launch in nanoseconds
dec ebx
jnz @f
call get_clock_ns
mov [esp + SYSCALL_STACK.edx], edx
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
@@:
; F.26.11 - Find out whether low-level HD access is enabled
dec ebx
jnz @f
mov eax, [lba_read_enabled]
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
@@:
; F.26.12 - Find out whether low-level PCI access is enabled
dec ebx
jnz .error
mov eax, [pci_access_enabled]
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
.error:
or [esp + SYSCALL_STACK.eax], dword -1
ret
;-----------------------------------------------------------------------------
get_timer_ticks:
mov eax, [timer_ticks]
ret
;-----------------------------------------------------------------------------
iglobal
midi_base dw 0
endg
align 4
sys_midi:
cmp word [mididp], 0
jnz @f
mov [esp + SYSCALL_STACK.eax], 1
ret
@@:
and [esp + SYSCALL_STACK.eax], 0
dec ebx
jnz .smn1
; call setuart
@@:
call .is_output
test al, al
jnz @b
mov dx, word [midisp]
mov al, 0xff
out dx, al
@@:
mov dx, word [midisp]
mov al, 0xff
out dx, al
call .is_input
test al, al
jnz @b
call .get_mpu_in
cmp al, 0xfe
jnz @b
@@:
call .is_output
test al, al
jnz @b
mov dx, word [midisp]
mov al, 0x3f
out dx, al
ret
.smn1:
dec ebx
jnz .ret
@@:
call .get_mpu_in
call .is_output
test al, al
jnz @b
mov al, bl
call .put_mpu_out
.ret:
ret
.is_input:
push edx
mov dx, word [midisp]
in al, dx
and al, 0x80
pop edx
ret
.is_output:
push edx
mov dx, word [midisp]
in al, dx
and al, 0x40
pop edx
ret
.get_mpu_in:
push edx
mov dx, word [mididp]
in al, dx
pop edx
ret
.put_mpu_out:
push edx
mov dx, word [mididp]
out dx, al
pop edx
ret
;-----------------------------------------------------------------------------
sys_end:
; restore default cursor before killing
pusha
mov ecx, [current_slot]
mov ecx, [ecx + APPDATA.window]
call restore_default_cursor_before_killing
popa
;--------------------------------------
; kill all sockets this process owns
pusha
mov edx, [current_slot]
mov edx, [edx + APPDATA.tid]
call socket_process_end
popa
;--------------------------------------
mov ecx, [current_slot]
mov eax, [ecx + APPDATA.tls_base]
test eax, eax
jz @F
stdcall user_free, eax
@@:
mov eax, [current_slot]
mov [eax + APPDATA.state], TSTATE_ZOMBIE
call wakeup_osloop
.waitterm: ; wait here for termination
call change_task
jmp .waitterm
;------------------------------------------------------------------------------
align 4
; ecx - ptr WDATA
restore_default_cursor_before_killing:
pushfd
cli
mov eax, [def_cursor]
mov [ecx + WDATA.cursor], eax
movzx eax, word [MOUSE_Y]
movzx ebx, word [MOUSE_X]
mov eax, [d_width_calc_area + eax*4]
add eax, [_display.win_map]
movzx edx, byte [ebx + eax]
shl edx, BSF sizeof.WDATA
mov esi, [window_data + edx + WDATA.cursor]
cmp esi, [current_cursor]
je @f
cmp [_display.select_cursor], 0
jz @f
stdcall [_display.select_cursor], esi
mov [current_cursor], esi
@@:
mov [redrawmouse_unconditional], 1
call wakeup_osloop
popfd
ret
;------------------------------------------------------------------------------
iglobal
align 4
sys_system_table:
dd sysfn_deactivate ; 1 = deactivate window
dd sysfn_terminate ; 2 = terminate thread
dd sysfn_activate ; 3 = activate window
dd sysfn_getidletime ; 4 = get idle time
dd sysfn_getcpuclock ; 5 = get cpu clock
dd sysfn_saveramdisk ; 6 = save ramdisk
dd sysfn_getactive ; 7 = get active window
dd sysfn_sound_flag ; 8 = get/set sound_flag
dd sysfn_shutdown ; 9 = shutdown with parameter
dd sysfn_minimize ; 10 = minimize window
dd sysfn_getdiskinfo ; 11 = get disk subsystem info
dd undefined_syscall ; 12 = get last pressed key. function removed. sysfn_lastkey
dd sysfn_getversion ; 13 = get kernel version
dd sysfn_waitretrace ; 14 = wait retrace
dd sysfn_centermouse ; 15 = center mouse cursor
dd sysfn_getfreemem ; 16 = get free memory size
dd sysfn_getallmem ; 17 = get total memory size
dd sysfn_terminate2 ; 18 = terminate thread using PID
; instead of slot
dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration
dd sysfn_meminfo ; 20 = get extended memory info
dd sysfn_pid_to_slot ; 21 = get slot number for pid
dd sysfn_min_rest_window ; 22 = minimize and restore any window
dd sysfn_min_windows ; 23 = minimize all windows
dd sysfn_set_screen_sizes ; 24 = set screen sizes for Vesa
dd sysfn_zmodif ; 25 = get/set window z modifier ;Fantomer
sysfn_num = ($ - sys_system_table)/4
endg
;------------------------------------------------------------------------------
sys_system:
dec ebx
cmp ebx, sysfn_num
jae @f
jmp dword [sys_system_table + ebx*4]
@@:
ret
;------------------------------------------------------------------------------
sysfn_shutdown: ; 18.9 = system shutdown
cmp ecx, SYSTEM_SHUTDOWN
jl .exit_for_anyone
cmp ecx, SYSTEM_RESTART
jg .exit_for_anyone
mov [BOOT.shutdown_type], cl
mov eax, [thread_count]
mov [SYS_SHUTDOWN], al
mov [shutdown_processes], eax
call wakeup_osloop
and dword [esp + SYSCALL_STACK.eax], 0
.exit_for_anyone:
ret
uglobal
shutdown_processes:
dd 0x0
endg
;------------------------------------------------------------------------------
; in: eax -- APPDATA ptr
; out: Z/z -- is/not kernel thread
is_kernel_thread:
mov eax, [eax + APPDATA.process]
cmp eax, [SLOT_BASE + 2*sizeof.APPDATA + APPDATA.process] ; OS
ret
;------------------------------------------------------------------------------
sysfn_terminate: ; 18.2 = TERMINATE
push ecx
cmp ecx, 2
jb .noprocessterminate
mov edx, [thread_count]
cmp ecx, edx
ja .noprocessterminate
mov eax, [thread_count]
shl ecx, BSF sizeof.APPDATA
add ecx, SLOT_BASE
mov edx, [ecx + APPDATA.tid]
cmp byte [ecx + APPDATA.state], TSTATE_FREE
jz .noprocessterminate
push eax
mov eax, ecx
call is_kernel_thread
pop eax
jz .noprocessterminate
push ecx edx
mov edx, ecx
call request_terminate
pop edx ecx
test eax, eax
jz .noprocessterminate
;--------------------------------------
; terminate all network sockets it used
pusha
mov eax, edx ;TODO: check function
call socket_process_end
popa
;--------------------------------------
; restore default cursor before killing
pusha
mov ecx, [esp+32]
shl ecx, BSF sizeof.WDATA
add ecx, window_data
mov eax, [def_cursor]
cmp [ecx + WDATA.cursor], eax
je @f
call restore_default_cursor_before_killing
@@:
popa
;--------------------------------------
;call MEM_Heap_Lock ;guarantee that process isn't working with heap
mov [ecx + APPDATA.state], TSTATE_ZOMBIE; clear possible i40's
call wakeup_osloop
;call MEM_Heap_UnLock
cmp edx, [application_table_owner]; clear app table stat
jne .noatsc
call unlock_application_table
.noatsc:
.noprocessterminate:
add esp, 4
ret
;------------------------------------------------------------------------------
sysfn_terminate2:
call lock_application_table
mov eax, ecx
call pid_to_slot
test eax, eax
jz .not_found
mov ecx, eax
cli
call sysfn_terminate
call unlock_application_table
sti
and dword [esp + SYSCALL_STACK.eax], 0
ret
.not_found:
call unlock_application_table
or dword [esp + SYSCALL_STACK.eax], -1
ret
;------------------------------------------------------------------------------
sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW
cmp ecx, 2
jb .nowindowdeactivate
cmp ecx, [thread_count]
ja .nowindowdeactivate
movzx esi, word [WIN_STACK + ecx*2]
cmp esi, 1
je .nowindowdeactivate ; already deactive
mov edi, ecx
shl edi, BSF sizeof.WDATA
add edi, window_data
movzx esi, word [WIN_STACK + ecx * 2]
lea esi, [WIN_POS + esi * 2]
call window._.window_deactivate
call syscall_display_settings.calculateScreen
call syscall_display_settings.redrawScreen
.nowindowdeactivate:
ret
;------------------------------------------------------------------------------
sysfn_activate: ; 18.3 = ACTIVATE WINDOW
cmp ecx, 2
jb .nowindowactivate
cmp ecx, [thread_count]
ja .nowindowactivate
;-------------------------------------
@@:
; If the window is captured and moved by the user,
; then you can't change the position in window stack!!!
mov al, [mouse.active_sys_window.action]
and al, WINDOW_MOVE_AND_RESIZE_FLAGS
test al, al
jz @f
call change_task
jmp @b
@@:
;-------------------------------------
mov [window_minimize], 2; restore window if minimized
call wakeup_osloop
movzx esi, word [WIN_STACK + ecx*2]
cmp esi, [thread_count]
je .nowindowactivate; already active
mov edi, ecx
shl edi, BSF sizeof.WDATA
add edi, window_data
movzx esi, word [WIN_STACK + ecx * 2]
lea esi, [WIN_POS + esi * 2]
call waredraw
.nowindowactivate:
ret
;------------------------------------------------------------------------------
align 4
sysfn_zmodif:
;18,25,1 - get z_modif
;18,25,2 - set z_modif
;edx = -1(for current task) or TID
;esi(for 2) = new value z_modif
;return:
;1: eax = z_modif
;2: eax=0(fail),1(success) for set z_modif
cmp edx, -1
jne @f
mov edx, [current_slot_idx]
@@:
cmp edx, [thread_count]
ja .fail
cmp edx, 1
je .fail
mov eax, edx
shl edx, BSF sizeof.WDATA
add edx, window_data
test [edx + WDATA.fl_wstate], WSTATE_USED
jz .fail
cmp ecx, 1
jnz .set_zmod
movzx eax, [edx + WDATA.z_modif]
jmp .exit
.set_zmod:
cmp ecx, 2
jnz .fail
mov ebx, esi
mov esi, eax
cmp bl, ZPOS_ALWAYS_TOP
jg .fail
mov [edx + WDATA.z_modif], bl
mov eax, [edx + WDATA.box.left]
mov ebx, [edx + WDATA.box.top]
mov ecx, [edx + WDATA.box.width]
mov edx, [edx + WDATA.box.height]
add ecx, eax
add edx, ebx
call window._.set_screen
call window._.set_top_wnd
call window._.redraw_top_wnd
shl esi, BSF sizeof.WDATA
mov [esi + window_data + WDATA.fl_redraw], WSTATE_REDRAW
mov eax, 1
jmp .exit
.fail:
xor eax, eax
.exit:
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_getidletime: ; 18.4 = GET IDLETIME
mov eax, [SLOT_BASE + sizeof.APPDATA + APPDATA.cpu_usage]
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC
mov eax, dword [cpu_freq]
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
get_cpu_freq:
mov eax, dword [cpu_freq]
mov edx, dword [cpu_freq+4]
ret
; SAVE ramdisk to /hd/1/kolibri.img
;!!!!!!!!!!!!!!!!!!!!!!!!
include 'blkdev/rdsave.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!
;------------------------------------------------------------------------------
align 4
sysfn_getactive: ; 18.7 = get active window
mov eax, [thread_count]
movzx eax, word [WIN_POS + eax*2]
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_sound_flag: ; 18.8 = get/set sound_flag
; cmp ecx,1
dec ecx
jnz .set_flag
movzx eax, byte [sound_flag]; get sound_flag
mov [esp + SYSCALL_STACK.eax], eax
ret
.set_flag:
; cmp ecx,2
dec ecx
jnz .err
xor byte [sound_flag], 1
.err:
ret
;------------------------------------------------------------------------------
sysfn_minimize: ; 18.10 = minimize window
mov [window_minimize], 1
call wakeup_osloop
ret
;------------------------------------------------------------------------------
align 4
sysfn_getdiskinfo: ; 18.11 = get disk info table
dec ecx
jnz .exit
.small_table:
stdcall is_region_userspace, edx, DRIVE_DATA_SIZE
jnz .exit
mov edi, edx
mov esi, DRIVE_DATA
mov ecx, DRIVE_DATA_SIZE ;10
cld
rep movsb
.exit:
ret
;------------------------------------------------------------------------------
sysfn_getversion: ; 18.13 = get kernel ID and version
; if given memory address belongs to kernel then error
stdcall is_region_userspace, ecx, version_inf.size
jnz .addr_error
mov edi, ecx
mov esi, version_inf
mov ecx, version_inf.size
rep movsb
ret
.addr_error: ; if given memory address is illegal
mov dword [esp + SYSCALL_STACK.eax], -1
ret
;------------------------------------------------------------------------------
sysfn_waitretrace: ; 18.14 = sys wait retrace
;wait retrace functions
mov edx, 0x3da
.loop:
in al, dx
test al, 1000b
jz .loop
and [esp + SYSCALL_STACK.eax], dword 0
ret
;------------------------------------------------------------------------------
align 4
sysfn_centermouse: ; 18.15 = mouse centered
mov eax, [_display.width]
shr eax, 1
mov [MOUSE_X], ax
mov eax, [_display.height]
shr eax, 1
mov [MOUSE_Y], ax
call wakeup_osloop
xor eax, eax
and [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_mouse_acceleration: ; 18.19 = set/get mouse features
cmp ecx, 8
jnc @f
jmp dword [.table + ecx*4]
.get_mouse_acceleration:
xor eax, eax
mov ax, [mouse_speed_factor]
mov [esp + SYSCALL_STACK.eax], eax
ret
.set_mouse_acceleration:
mov [mouse_speed_factor], dx
ret
.get_mouse_delay:
xor eax, eax
mov al, [mouse_delay]
mov [esp + SYSCALL_STACK.eax], eax
ret
.set_mouse_delay:
mov [mouse_delay], dl
@@:
ret
.set_pointer_position:
cmp dx, word[_display.height]
jae @b
rol edx, 16
cmp dx, word[_display.width]
jae @b
mov [MOUSE_X], edx
mov [mouse_active], 1
jmp wakeup_osloop
.set_mouse_button:
mov [BTN_DOWN], edx
mov [mouse_active], 1
jmp wakeup_osloop
.get_doubleclick_delay:
xor eax, eax
mov al, [mouse_doubleclick_delay]
mov [esp + SYSCALL_STACK.eax], eax
ret
.set_doubleclick_delay:
mov [mouse_doubleclick_delay], dl
ret
align 4
.table:
dd .get_mouse_acceleration
dd .set_mouse_acceleration
dd .get_mouse_delay
dd .set_mouse_delay
dd .set_pointer_position
dd .set_mouse_button
dd .get_doubleclick_delay
dd .set_doubleclick_delay
;------------------------------------------------------------------------------
sysfn_getfreemem:
mov eax, [pg_data.pages_free]
shl eax, 2
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_getallmem:
mov eax, [MEM_AMOUNT]
shr eax, 10
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_pid_to_slot:
mov eax, ecx
call pid_to_slot
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_min_rest_window:
pushad
mov eax, edx ; ebx - operating
shr ecx, 1
jnc @f
call pid_to_slot
@@:
or eax, eax ; eax - number of slot
jz .error
cmp eax, max_processes ; varify maximal slot number
ja .error
movzx eax, word [WIN_STACK + eax*2]
shr ecx, 1
jc .restore
; .minimize:
call minimize_window
jmp .exit
.restore:
call restore_minimized_window
.exit:
popad
xor eax, eax
mov [esp + SYSCALL_STACK.eax], eax
ret
.error:
popad
xor eax, eax
dec eax
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
sysfn_min_windows:
call minimize_all_window
mov [esp + SYSCALL_STACK.eax], eax
call change_task
ret
;------------------------------------------------------------------------------
sysfn_set_screen_sizes:
cmp [SCR_MODE], word 0x13
jbe .exit
cmp [_display.select_cursor], select_cursor
jne .exit
cmp ecx, [display_width_standard]
ja .exit
cmp edx, [display_height_standard]
ja .exit
pushfd
cli
mov eax, ecx
mov ecx, [_display.lfb_pitch]
mov [_display.width], eax
dec eax
mov [_display.height], edx
dec edx
; eax - new Screen_Max_X
; edx - new Screen_Max_Y
mov [do_not_touch_winmap], 1
call set_screen
mov [do_not_touch_winmap], 0
popfd
call change_task
.exit:
ret
;------------------------------------------------------------------------------
uglobal
screen_workarea RECT
display_width_standard dd 0
display_height_standard dd 0
do_not_touch_winmap db 0
window_minimize db 0
sound_flag db 0
endg
iglobal
version_inf:
db 0,7,7,0 ; version 0.7.7.0
db 0
.rev dd __REV__
.size = $ - version_inf
endg
;------------------------------------------------------------------------------
align 4
sys_cachetodiskette:
cmp ebx, 1
jb .no_floppy_save
cmp ebx, 2
ja .no_floppy_save
call save_image
mov [esp + SYSCALL_STACK.eax], eax
ret
.no_floppy_save:
mov [esp + SYSCALL_STACK.eax], dword 1
ret
;------------------------------------------------------------------------------
align 4
sys_cpuusage:
; RETURN:
;
; +00 dword process cpu usage
; +04 word position in windowing stack
; +06 word windowing stack value at current position (cpu nro)
; +10 12 bytes name
; +22 dword start in mem
; +26 dword used mem
; +30 dword PID , process idenfification number
;
; if given memory address belongs to kernel then error
stdcall is_region_userspace, ebx, 0x4C
jnz .addr_error
cmp ecx, -1 ; who am I ?
jne .no_who_am_i
mov ecx, [current_slot_idx]
.no_who_am_i:
cmp ecx, max_processes
ja .nofillbuf
; +4: word: position of the window of thread in the window stack
mov ax, [WIN_STACK + ecx * 2]
mov [ebx+4], ax
; +6: word: number of the thread slot, which window has in the window stack
; position ecx (has no relation to the specific thread)
mov ax, [WIN_POS + ecx * 2]
mov [ebx+6], ax
shl ecx, BSF sizeof.APPDATA
; +0: dword: memory usage
mov eax, [SLOT_BASE + ecx + APPDATA.cpu_usage]
mov [ebx], eax
; +10: 11 bytes: name of the process
push ecx
lea eax, [SLOT_BASE + ecx + APPDATA.app_name]
add ebx, 10
mov ecx, 11
call memmove
pop ecx
; +22: address of the process in memory
; +26: size of used memory - 1
push edi
lea edi, [ebx+12]
xor eax, eax
mov edx, 0x100000*16
cmp ecx, 1 shl BSF sizeof.APPDATA
je .os_mem
mov edx, [SLOT_BASE + ecx + APPDATA.process]
mov edx, [edx + PROC.mem_used]
mov eax, std_application_base_address
.os_mem:
stosd
lea eax, [edx-1]
stosd
mov edx, [SLOT_BASE + ecx + APPDATA.window]
; +30: PID/TID
mov eax, [SLOT_BASE + ecx + APPDATA.tid]
stosd
; window position and size
push esi
lea esi, [edx + WDATA.box]
movsd
movsd
movsd
movsd
; Process state (+50)
movzx eax, byte [SLOT_BASE + ecx + APPDATA.state]
stosd
; Window client area box
lea esi, [edx + WDATA.clientbox]
movsd
movsd
movsd
movsd
; Window state
mov al, [edx + WDATA.fl_wstate]
stosb
; Event mask (+71)
mov eax, dword [SLOT_BASE + ecx + APPDATA.event_mask]
stosd
; Keyboard mode (+75)
mov al, byte [SLOT_BASE + ecx + APPDATA.keyboard_mode]
stosb
pop esi
pop edi
.nofillbuf:
; return number of processes
mov eax, [thread_count]
mov [esp + SYSCALL_STACK.eax], eax
ret
.addr_error: ; if given memory address is illegal
mov dword [esp + SYSCALL_STACK.eax], -1
ret
; redraw status
align 4
sys_redrawstat:
cmp ebx, 1
jne .no_widgets_away
; buttons away
mov ecx, [current_slot_idx]
.sys_newba2:
mov edi, [BTN_ADDR]
cmp [edi], dword 0 ; empty button list ?
je .end_of_buttons_away
movzx ebx, word [edi]
inc ebx
mov eax, edi
.sys_newba:
dec ebx
jz .end_of_buttons_away
add eax, 0x10
cmp cx, [eax]
jnz .sys_newba
push eax ebx ecx
mov ecx, ebx
inc ecx
shl ecx, 4
mov ebx, eax
add eax, 0x10
call memmove
dec dword [edi]
pop ecx ebx eax
jmp .sys_newba2
.end_of_buttons_away:
ret
.no_widgets_away:
cmp ebx, 2
jnz .srl1
mov edx, [current_slot] ; return whole screen draw area for this app
mov edx, [edx + APPDATA.window]
mov [edx + WDATA.draw_data.left], 0
mov [edx + WDATA.draw_data.top], 0
mov eax, [_display.width]
dec eax
mov [edx + WDATA.draw_data.right], eax
mov eax, [_display.height]
dec eax
mov [edx + WDATA.draw_data.bottom], eax
.srl1:
ret
;ok - 100% work
;nt - not tested
;---------------------------------------------------------------------------------------------
;eax
;0 - task switch counter. Ret switch counter in eax. Block. ok.
;1 - change task. Ret nothing. Block. ok.
;2 - performance control
; ebx
; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode.
; returned new cr4 in eax. Ret cr4 in eax. Block. ok.
; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok.
; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok.
; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok.
;eax
;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok.
;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok.
;---------------------------------------------------------------------------------------------
iglobal
align 4
sheduler:
dd sys_sheduler.00
dd change_task
dd sys_sheduler.02
dd sys_sheduler.03
dd sys_sheduler.04
endg
sys_sheduler:
;rewritten by <Lrz> 29.12.2009
jmp dword [sheduler + ebx*4]
;.shed_counter:
.00:
mov eax, [context_counter]
mov [esp + SYSCALL_STACK.eax], eax
ret
.02:
;.perf_control:
inc ebx ;before ebx=2, ebx=3
cmp ebx, ecx ;if ecx=3, ebx=3
jz cache_disable
dec ebx ;ebx=2
cmp ebx, ecx ;
jz cache_enable ;if ecx=2 and ebx=2
dec ebx ;ebx=1
cmp ebx, ecx
jz is_cache_enabled ;if ecx=1 and ebx=1
dec ebx
test ebx, ecx ;ebx=0 and ecx=0
jz modify_pce ;if ecx=0
ret
.03:
;.rdmsr_instr:
;now counter in ecx
;(edx:eax) esi:edi => edx:esi
mov eax, esi
mov ecx, edx
rdmsr
mov [esp + SYSCALL_STACK.eax], eax
mov [esp + SYSCALL_STACK.ebx], edx ;ret in ebx?
ret
.04:
;.wrmsr_instr:
;now counter in ecx
;(edx:eax) esi:edi => edx:esi
; Fast Call MSR can't be destroy
; Но MSR_AMD_EFER можно изменять, т.к. в этом регистре лиш
; включаются/выключаются расширенные возможности
cmp edx, MSR_SYSENTER_CS
je @f
cmp edx, MSR_SYSENTER_ESP
je @f
cmp edx, MSR_SYSENTER_EIP
je @f
cmp edx, MSR_AMD_STAR
je @f
mov eax, esi
mov ecx, edx
wrmsr
; mov [esp + 32], eax
; mov [esp + 20], edx ;ret in ebx?
@@:
ret
cache_disable:
mov eax, cr0
or eax, 01100000_00000000_00000000_00000000b
mov cr0, eax
wbinvd ;set MESI
ret
cache_enable:
mov eax, cr0
and eax, 10011111_11111111_11111111_11111111b
mov cr0, eax
ret
is_cache_enabled:
mov eax, cr0
and eax, 01100000_00000000_00000000_00000000b
mov [esp + SYSCALL_STACK.eax], eax
ret
modify_pce:
mov eax, cr4
; mov ebx,0
; or bx,100000000b ;pce
; xor eax,ebx ;invert pce
bts eax, 8;pce=cr4[8]
mov cr4, eax
mov [esp + SYSCALL_STACK.eax], eax
ret
;---------------------------------------------------------------------------------------------
iglobal
cpustring db 'CPU',0
endg
uglobal
background_defined db 0 ; diamond, 11.04.2006
endg
;-----------------------------------------------------------------------------
align 4
checkmisc:
cmp [ctrl_alt_del], 1
jne .nocpustart
mov ebp, cpustring
call fs_execute_from_sysdir
mov [ctrl_alt_del], 0
;--------------------------------------
align 4
.nocpustart:
cmp [mouse_active], 1
jne .mouse_not_active
mov [mouse_active], 0
xor edi, edi
mov ebx, window_data
mov ecx, [thread_count]
movzx eax, word [WIN_POS + ecx*2] ; active window
shl eax, BSF sizeof.APPDATA
push eax
movzx eax, word [MOUSE_X]
movzx edx, word [MOUSE_Y]
;--------------------------------------
align 4
.set_mouse_event:
add edi, sizeof.APPDATA
add ebx, sizeof.WDATA
test [SLOT_BASE + edi + APPDATA.event_mask], EVM_MOUSE_FILTER
jz .pos_filter
cmp edi, [esp] ; skip if filtration active
jne .skip
;--------------------------------------
align 4
.pos_filter:
test [SLOT_BASE + edi + APPDATA.event_mask], EVM_CURSOR_FILTER
jz .set
mov esi, [ebx + WDATA.box.left]
cmp eax, esi
jb .skip
add esi, [ebx + WDATA.box.width]
cmp eax, esi
ja .skip
mov esi, [ebx + WDATA.box.top]
cmp edx, esi
jb .skip
add esi, [ebx + WDATA.box.height]
cmp edx, esi
ja .skip
;--------------------------------------
align 4
.set:
or [SLOT_BASE + edi + APPDATA.occurred_events], EVENT_MOUSE
;--------------------------------------
align 4
.skip:
loop .set_mouse_event
pop eax
;--------------------------------------
align 4
.mouse_not_active:
cmp [REDRAW_BACKGROUND], 0 ; background update ?
jz nobackgr
cmp [background_defined], 0
jz nobackgr
;--------------------------------------
align 4
backgr:
mov eax, [background_window + WDATA.draw_data.left]
shl eax, 16
add eax, [background_window + WDATA.draw_data.right]
mov [BG_Rect_X_left_right], eax ; [left]*65536 + [right]
mov eax, [background_window + WDATA.draw_data.top]
shl eax, 16
add eax, [background_window + WDATA.draw_data.bottom]
mov [BG_Rect_Y_top_bottom], eax ; [top]*65536 + [bottom]
call drawbackground
; DEBUGF 1, "K : drawbackground\n"
; DEBUGF 1, "K : backg x %x\n",[BG_Rect_X_left_right]
; DEBUGF 1, "K : backg y %x\n",[BG_Rect_Y_top_bottom]
;--------- set event 5 start ----------
push ecx edi
mov edi, window_data
mov ecx, [thread_count]
;--------------------------------------
align 4
set_bgr_event:
add edi, sizeof.WDATA
mov eax, [BG_Rect_X_left_right]
mov edx, [BG_Rect_Y_top_bottom]
cmp [edi + WDATA.draw_bgr_x], 0
jz .set
.join:
cmp word [edi + WDATA.draw_bgr_x], ax
jae @f
mov word [edi + WDATA.draw_bgr_x], ax
@@:
shr eax, 16
cmp word [edi + WDATA.draw_bgr_x + 2], ax
jbe @f
mov word [edi + WDATA.draw_bgr_x + 2], ax
@@:
cmp word [edi + WDATA.draw_bgr_y], dx
jae @f
mov word [edi + WDATA.draw_bgr_y], dx
@@:
shr edx, 16
cmp word [edi + WDATA.draw_bgr_y+2], dx
jbe @f
mov word [edi + WDATA.draw_bgr_y+2], dx
@@:
jmp .common
.set:
mov [edi + WDATA.draw_bgr_x], eax
mov [edi + WDATA.draw_bgr_y], edx
.common:
mov eax, [edi + WDATA.thread]
test eax, eax
jz @f
or [eax + APPDATA.occurred_events], EVENT_BACKGROUND
@@:
loop set_bgr_event
pop edi ecx
;--------- set event 5 stop -----------
dec [REDRAW_BACKGROUND] ; got new update request?
jnz backgr
xor eax, eax
mov [background_window + WDATA.draw_data.left], eax
mov [background_window + WDATA.draw_data.top], eax
mov [background_window + WDATA.draw_data.right], eax
mov [background_window + WDATA.draw_data.bottom], eax
;--------------------------------------
align 4
nobackgr:
; system shutdown request
cmp [SYS_SHUTDOWN], byte 0
je noshutdown
mov edx, [shutdown_processes]
cmp [SYS_SHUTDOWN], dl
jne noshutdown
lea ecx, [edx-1]
mov edx, SLOT_BASE + sizeof.APPDATA*2 ;OS_BASE+0x3040
jecxz no_mark_system_shutdown
;--------------------------------------
align 4
markz:
push ecx edx
cmp [edx + APPDATA.state], TSTATE_FREE
jz .nokill
cmp [edx + APPDATA.process], sys_proc
jz .nokill
call request_terminate
jmp .common
.nokill:
dec byte [SYS_SHUTDOWN]
xor eax, eax
.common:
pop edx ecx
test eax, eax
jz @f
mov [edx + APPDATA.state], TSTATE_ZOMBIE
@@:
add edx, sizeof.APPDATA
loop markz
call wakeup_osloop
;--------------------------------------
align 4
@@:
no_mark_system_shutdown:
dec byte [SYS_SHUTDOWN]
je system_shutdown
;--------------------------------------
align 4
noshutdown:
mov eax, [thread_count] ; termination
mov ebx, SLOT_BASE + sizeof.APPDATA + APPDATA.state
mov esi, 1
;--------------------------------------
align 4
newct:
mov cl, [ebx]
cmp cl, TSTATE_ZOMBIE
jz .terminate
cmp cl, TSTATE_TERMINATING
jnz .noterminate
.terminate:
pushad
push esi
mov ecx, dword[ebx - APPDATA.state + APPDATA.window]
call restore_default_cursor_before_killing
pop esi
call terminate
popad
cmp byte [SYS_SHUTDOWN], 0
jz .noterminate
dec byte [SYS_SHUTDOWN]
je system_shutdown
.noterminate:
add ebx, sizeof.APPDATA
inc esi
dec eax
jnz newct
ret
;-----------------------------------------------------------------------------
align 4
; eax - ptr to WDATA
redrawscreen:
; eax , if process window_data base is eax, do not set flag/limits
pushad
push eax
;;; mov ebx,2
;;; call delay_hs
;mov ecx,0 ; redraw flags for apps
xor ecx, ecx
;--------------------------------------
align 4
newdw2:
inc ecx
push ecx
mov eax, ecx
shl eax, BSF sizeof.WDATA
add eax, window_data
cmp eax, [esp+4]
je not_this_task
; check if window in redraw area
mov edi, eax
cmp ecx, 1 ; limit for background
jz bgli
mov eax, [esp+4] ;if upper in z-position - no redraw
test eax, eax
jz @f
mov al, [eax + WDATA.z_modif]
cmp [edi + WDATA.z_modif], al
jg ricino
@@:
mov eax, [edi + WDATA.box.left]
mov ebx, [edi + WDATA.box.top]
cmp ebx, [draw_limits.bottom] ; ecx = area y end ebx = window y start
jae ricino
cmp eax, [draw_limits.right] ; ecx = area x end eax = window x start
jae ricino
mov eax, [edi + WDATA.box.left]
mov ebx, [edi + WDATA.box.top]
mov ecx, [edi + WDATA.box.width]
mov edx, [edi + WDATA.box.height]
add ecx, eax
add edx, ebx
mov eax, [draw_limits.top] ; eax = area y start edx = window y end
cmp edx, eax
jb ricino
mov eax, [draw_limits.left] ; eax = area x start ecx = window x end
cmp ecx, eax
jb ricino
;--------------------------------------
align 4
bgli:
cmp dword[esp], 1 ; check index in window_data array, 1 - idle
jnz .az
cmp [REDRAW_BACKGROUND], 0
jz .az
mov dl, 0
mov ebx, [draw_limits.left]
cmp ebx, [edi + WDATA.draw_data.left]
jae @f
mov [edi + WDATA.draw_data.left], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.top]
cmp ebx, [edi + WDATA.draw_data.top]
jae @f
mov [edi + WDATA.draw_data.top], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.right]
cmp ebx, [edi + WDATA.draw_data.right]
jbe @f
mov [edi + WDATA.draw_data.right], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.bottom]
cmp ebx, [edi + WDATA.draw_data.bottom]
jbe @f
mov [edi + WDATA.draw_data.bottom], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
add [REDRAW_BACKGROUND], dl
call wakeup_osloop
jmp newdw8
;--------------------------------------
align 4
.az:
mov ebx, [draw_limits.left] ; set limits
mov [edi + WDATA.draw_data.left], ebx
mov ebx, [draw_limits.top]
mov [edi + WDATA.draw_data.top], ebx
mov ebx, [draw_limits.right]
mov [edi + WDATA.draw_data.right], ebx
mov ebx, [draw_limits.bottom]
mov [edi + WDATA.draw_data.bottom], ebx
cmp dword [esp], 1 ; check idle thread
jne nobgrd
inc [REDRAW_BACKGROUND]
call wakeup_osloop
;--------------------------------------
align 4
newdw8:
nobgrd:
;--------------------------------------
push edi ebp
mov edi, [esp+8]
cmp edi, 1
je .found
mov eax, [draw_limits.left]
mov ebx, [draw_limits.top]
mov ecx, [draw_limits.right]
sub ecx, eax
test ecx, ecx
jz .not_found
mov edx, [draw_limits.bottom]
sub edx, ebx
test edx, edx
jz .not_found
; eax - x, ebx - y
; ecx - size x, edx - size y
add ebx, edx
;--------------------------------------
align 4
.start_y:
push ecx
;--------------------------------------
align 4
.start_x:
add eax, ecx
mov ebp, [d_width_calc_area + ebx*4]
add ebp, [_display.win_map]
movzx ebp, byte[eax+ebp] ; get value for current point
cmp ebp, edi
jne @f
pop ecx
jmp .found
;--------------------------------------
align 4
@@:
sub eax, ecx
dec ecx
jns .start_x
pop ecx
dec ebx
dec edx
jns .start_y
;--------------------------------------
align 4
.not_found:
pop ebp edi
jmp ricino
;--------------------------------------
align 4
.found:
pop ebp edi
mov [edi + WDATA.fl_redraw], WSTATE_REDRAW ; mark as redraw
;--------------------------------------
align 4
ricino:
not_this_task:
pop ecx
cmp ecx, [thread_count]
jle newdw2
pop eax
popad
ret
;-----------------------------------------------------------------------------
align 4
calculatebackground: ; background
mov edi, [_display.win_map] ; set os to use all pixels
mov eax, 0x01010101
mov ecx, [_display.win_map_size]
shr ecx, 2
rep stosd
mov byte[background_window + WDATA.z_modif], ZPOS_DESKTOP
mov [REDRAW_BACKGROUND], 0
ret
;-----------------------------------------------------------------------------
uglobal
imax dd 0x0
endg
;-----------------------------------------------------------------------------
align 4
delay_ms: ; delay in 1/1000 sec
pushad
cmp [hpet_base], 0
jz .no_hpet
mov eax, esi
mov edx, 1_000_000 ; ms to ns
mul edx
mov ebx, edx
mov ecx, eax
push ecx
call get_clock_ns
pop ecx
mov edi, edx
mov esi, eax
.wait:
push ecx
call get_clock_ns
pop ecx
sub eax, esi
sbb edx, edi
sub eax, ecx
sbb edx, ebx
jc .wait
jmp .done
.no_hpet:
mov ecx, esi
; <CPU clock fix by Sergey Kuzmin aka Wildwest>
imul ecx, 33941
shr ecx, 9
; </CPU clock fix>
in al, 0x61
and al, 0x10
mov ah, al
cld
.cnt1:
in al, 0x61
and al, 0x10
cmp al, ah
jz .cnt1
mov ah, al
loop .cnt1
.done:
popad
ret
;-----------------------------------------------------------------------------
align 4
set_app_param:
mov edi, [current_slot]
xchg ebx, [edi + APPDATA.event_mask] ; set new event mask
mov [esp + SYSCALL_STACK.eax], ebx ; return old mask value
ret
;-----------------------------------------------------------------------------
; this is for syscall
proc delay_hs_unprotected
call unprotect_from_terminate
call delay_hs
call protect_from_terminate
ret
endp
if 1
align 4
delay_hs: ; delay in 1/100 secs
; ebx = delay time
pushad
push ebx
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
test eax, eax
jz .done
mov ebx, edx
mov ecx, [esp]
push edx
push eax
call wait_event_timeout
pop eax
pop ebx
call destroy_event
.done:
add esp, 4
popad
ret
else
align 4
delay_hs: ; delay in 1/100 secs
; ebx = delay time
push ecx
push edx
mov edx, [timer_ticks]
;--------------------------------------
align 4
.newtic:
mov ecx, [timer_ticks]
sub ecx, edx
cmp ecx, ebx
jae .zerodelay
call change_task
jmp .newtic
;--------------------------------------
align 4
.zerodelay:
pop edx
pop ecx
ret
end if
;-----------------------------------------------------------------------------
align 16 ;very often call this subrutine
memmove: ; memory move in bytes
; eax = from
; ebx = to
; ecx = no of bytes
test ecx, ecx
jle .ret
push esi edi ecx
mov edi, ebx
mov esi, eax
test ecx, not 11b
jz @f
push ecx
shr ecx, 2
rep movsd
pop ecx
and ecx, 11b
jz .finish
;--------------------------------------
align 4
@@:
rep movsb
;--------------------------------------
align 4
.finish:
pop ecx edi esi
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
; in: eax = port
; ebp = subfunction
; 0 - set access
; 1 - clear access
; out: not return value
align 4
set_io_access_rights:
push edi eax
mov edi, tss._io_map_0
test ebp, ebp ; enable access - ebp = 0
jnz .siar1
btr [edi], eax
pop eax edi
ret
.siar1:
bts [edi], eax ; disable access - ebp = 1
pop eax edi
ret
align 4
; @brief ReservePortArea and FreePortArea
; @param edx number end arrea of ports (include last number of port)
; @param ecx number start arrea of ports
; @param ebx sub function 0 - reserve, 1 - free
; @param eax 46 - number function
; @returns eax = 0 - succesful eax = 1 - error
syscall_reserveportarea: ; ReservePortArea and FreePortArea
call r_f_port_area
mov [esp + SYSCALL_STACK.eax], eax
ret
;reserve/free group of ports
; * eax = 46 - number function
; * ebx = 0 - reserve, 1 - free
; * ecx = number start arrea of ports
; * edx = number end arrea of ports (include last number of port)
;Return value:
; * eax = 0 - succesful
; * eax = 1 - error
; * The system has reserve this ports:
; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port).
;destroys eax,ebx, ebp
r_f_port_area:
test ebx, ebx
jnz .free_port_area
cmp ecx, edx ; beginning > end ?
ja .err
cmp edx, 65536 ;test ebx, not 0xffff
jae .err
mov eax, [RESERVED_PORTS]
test eax, eax ; no reserved areas ?
je .rpal2
cmp eax, 255 ; max reserved
jae .err
.rpal3:
mov ebx, eax
shl ebx, 4 ;16 byte is sizeof item in RESERVED_PORTS table
add ebx, RESERVED_PORTS
cmp ecx, [ebx+8]
ja .rpal4
cmp edx, [ebx+4]
jae .err
.rpal4:
dec eax
jnz .rpal3
jmp .rpal2
.err:
xor eax, eax
inc eax
ret
.rpal2:
; enable port access at port IO map
pushad ; start enable io map
mov eax, ecx
xor ebp, ebp ; enable - eax = port
cli
.new_port_access:
call set_io_access_rights
inc eax
cmp eax, edx
jbe .new_port_access
sti
popad ; end enable io map
mov eax, [RESERVED_PORTS]
inc eax
mov [RESERVED_PORTS], eax
shl eax, 4
add eax, RESERVED_PORTS
mov ebx, [current_slot]
mov ebx, [ebx + APPDATA.tid]
mov [eax], ebx ; tid
mov [eax+4], ecx ;start port
mov [eax+8], edx ;finish port
xor eax, eax
ret
.free_port_area:
mov eax, [RESERVED_PORTS]; no reserved areas ?
test eax, eax
jz .frpal2
mov ebx, [current_slot]
mov ebx, [ebx + APPDATA.tid]
.frpal3:
mov edi, eax
shl edi, 4
add edi, RESERVED_PORTS
cmp ebx, [edi]
jne .frpal4
cmp ecx, [edi+4]
jne .frpal4
cmp edx, [edi+8]
jne .frpal4
jmp .frpal1
.frpal4:
dec eax
jnz .frpal3
.frpal2:
inc eax
ret
.frpal1:
push ecx
mov ecx, 256
sub ecx, eax
shl ecx, 4
mov esi, edi
add esi, 16
cld
rep movsb
dec dword [RESERVED_PORTS]
;disable port access at port IO map
; start disable io map
pop eax ;start port
;cmp edx, 65536
;jge no_mask_io
xor ebp, ebp
inc ebp
.new_port_access_disable: ; disable - eax = port
call set_io_access_rights
inc eax
cmp eax, edx
jbe .new_port_access_disable
; end disable io map
xor eax, eax
ret
;-----------------------------------------------------------------------------
align 4
drawbackground:
cmp [BgrDrawMode], dword 1
jne .bgrstr
call vesa20_drawbackground_tiled
call __sys_draw_pointer
ret
;--------------------------------------
align 4
.bgrstr:
call vesa20_drawbackground_stretch
call __sys_draw_pointer
ret
;-----------------------------------------------------------------------------
align 4
syscall_putimage: ; PutImage
; add check pointer
push ecx
mov ax, cx
shr ecx, 16
imul eax, ecx
lea eax, [eax*3]
stdcall is_region_userspace, ebx, eax
pop ecx
jnz sys_putimage.exit
sys_putimage:
test ecx, 0x80008000
jnz .exit
test ecx, 0x0000FFFF
jz .exit
test ecx, 0xFFFF0000
jnz @f
;--------------------------------------
align 4
.exit:
ret
;--------------------------------------
align 4
@@:
mov edi, [current_slot]
mov edi, [edi + APPDATA.window]
add dx, word[edi + WDATA.clientbox.top]
rol edx, 16
add dx, word[edi + WDATA.clientbox.left]
rol edx, 16
;--------------------------------------
align 4
.forced:
push ebp esi 0
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
;--------------------------------------
align 4
sys_putimage_bpp:
call vesa20_putimage
pop ebp esi ebp
ret
; jmp [draw_pointer]
;-----------------------------------------------------------------------------
align 4
sys_putimage_palette:
; ebx = pointer to image
; ecx = [xsize]*65536 + [ysize]
; edx = [xstart]*65536 + [ystart]
; esi = number of bits per pixel, must be 8, 24 or 32
; edi = pointer to palette
; ebp = row delta
; check pointer
push ecx esi
mov ax, cx
shr ecx, 16
imul eax, ecx
; imul eax, esi ; eax*count bit in 1 pixel
; shr eax, 3
stdcall is_region_userspace, ebx, eax
pop esi ecx
jnz sys_putimage.exit
mov eax, [current_slot]
mov eax, [eax + APPDATA.window]
add dx, word [eax + WDATA.clientbox.top]
rol edx, 16
add dx, word [eax + WDATA.clientbox.left]
rol edx, 16
;--------------------------------------
align 4
.forced:
cmp esi, 1
jnz @f
push edi
mov eax, [edi+4]
sub eax, [edi]
push eax
push dword [edi]
push 0ffffff80h
mov edi, esp
call put_mono_image
add esp, 12
pop edi
ret
;--------------------------------------
align 4
@@:
cmp esi, 2
jnz @f
push edi
push 0ffffff80h
mov edi, esp
call put_2bit_image
pop eax
pop edi
ret
;--------------------------------------
align 4
@@:
cmp esi, 4
jnz @f
push edi
push 0ffffff80h
mov edi, esp
call put_4bit_image
pop eax
pop edi
ret
;--------------------------------------
align 4
@@:
push ebp esi ebp
cmp esi, 8
jnz @f
mov ebp, putimage_get8bpp
mov esi, putimage_init8bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 9
jnz @f
mov ebp, putimage_get9bpp
mov esi, putimage_init9bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 15
jnz @f
mov ebp, putimage_get15bpp
mov esi, putimage_init15bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 16
jnz @f
mov ebp, putimage_get16bpp
mov esi, putimage_init16bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 24
jnz @f
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 32
jnz @f
mov ebp, putimage_get32bpp
mov esi, putimage_init32bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
pop ebp esi ebp
ret
;-----------------------------------------------------------------------------
align 4
put_mono_image:
push ebp esi ebp
mov ebp, putimage_get1bpp
mov esi, putimage_init1bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
put_2bit_image:
push ebp esi ebp
mov ebp, putimage_get2bpp
mov esi, putimage_init2bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
put_4bit_image:
push ebp esi ebp
mov ebp, putimage_get4bpp
mov esi, putimage_init4bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
putimage_init24bpp:
lea eax, [eax*3]
putimage_init8bpp:
putimage_init9bpp:
ret
;-----------------------------------------------------------------------------
align 16
putimage_get24bpp:
movzx eax, byte [esi+2]
shl eax, 16
mov ax, [esi]
add esi, 3
ret 4
;-----------------------------------------------------------------------------
align 16
putimage_get8bpp:
movzx eax, byte [esi]
push edx
mov edx, [esp+8]
mov eax, [edx + eax*4]
pop edx
inc esi
ret 4
;-----------------------------------------------------------------------------
align 16
putimage_get9bpp:
lodsb
mov ah, al
shl eax, 8
mov al, ah
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init1bpp:
add eax, ecx
push ecx
add eax, 7
add ecx, 7
shr eax, 3
shr ecx, 3
sub eax, ecx
pop ecx
ret
;-----------------------------------------------------------------------------
align 16
putimage_get1bpp:
push edx
mov edx, [esp+8]
mov al, [edx]
add al, al
jnz @f
lodsb
adc al, al
@@:
mov [edx], al
sbb eax, eax
and eax, [edx+8]
add eax, [edx+4]
pop edx
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init2bpp:
add eax, ecx
push ecx
add ecx, 3
add eax, 3
shr ecx, 2
shr eax, 2
sub eax, ecx
pop ecx
ret
;-----------------------------------------------------------------------------
align 16
putimage_get2bpp:
push edx
mov edx, [esp+8]
mov al, [edx]
mov ah, al
shr al, 6
shl ah, 2
jnz .nonewbyte
lodsb
mov ah, al
shr al, 6
shl ah, 2
add ah, 1
.nonewbyte:
mov [edx], ah
mov edx, [edx+4]
movzx eax, al
mov eax, [edx + eax*4]
pop edx
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init4bpp:
add eax, ecx
push ecx
add ecx, 1
inc eax ;add eax, 1
shr ecx, 1
shr eax, 1
sub eax, ecx
pop ecx
ret
;-----------------------------------------------------------------------------
align 16
putimage_get4bpp:
push edx
mov edx, [esp+8]
add byte [edx], 80h
jc @f
movzx eax, byte [edx+1]
mov edx, [edx+4]
and eax, 0x0F
mov eax, [edx + eax*4]
pop edx
ret 4
@@:
movzx eax, byte [esi]
add esi, 1
mov [edx+1], al
shr eax, 4
mov edx, [edx+4]
mov eax, [edx + eax*4]
pop edx
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init32bpp:
shl eax, 2
ret
;-----------------------------------------------------------------------------
align 16
putimage_get32bpp:
lodsd
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init15bpp:
putimage_init16bpp:
add eax, eax
ret
;-----------------------------------------------------------------------------
align 16
putimage_get15bpp:
; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000
push ecx edx
movzx eax, word [esi]
add esi, 2
mov ecx, eax
mov edx, eax
and eax, 0x1F
and ecx, 0x1F shl 5
and edx, 0x1F shl 10
shl eax, 3
shl ecx, 6
shl edx, 9
or eax, ecx
or eax, edx
pop edx ecx
ret 4
;-----------------------------------------------------------------------------
align 16
putimage_get16bpp:
; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000
push ecx edx
movzx eax, word [esi]
add esi, 2
mov ecx, eax
mov edx, eax
and eax, 0x1F
and ecx, 0x3F shl 5
and edx, 0x1F shl 11
shl eax, 3
shl ecx, 5
shl edx, 8
or eax, ecx
or eax, edx
pop edx ecx
ret 4
;-----------------------------------------------------------------------------
;align 4
; eax x beginning
; ebx y beginning
; ecx x end
; edx y end
; edi color
;__sys_drawbar:
; mov esi, [current_slot]
; mov esi, [esi + APPDATA.window]
; add eax, [esi + WDATA.clientbox.left]
; add ecx, [esi + WDATA.clientbox.left]
; add ebx, [esi + WDATA.clientbox.top]
; add edx, [esi + WDATA.clientbox.top]
;--------------------------------------
;align 4
;.forced:
; call vesa20_drawbar
; call [draw_pointer]
; ret
;-----------------------------------------------------------------------------
if used _rdtsc
_rdtsc:
bt [cpu_caps], CAPS_TSC
jnc .ret_rdtsc
rdtsc
ret
.ret_rdtsc:
mov edx, 0xffffffff
mov eax, 0xffffffff
ret
end if
sys_msg_board_str:
pushad
@@:
cmp [esi], byte 0
je @f
mov ebx, 1
movzx ecx, byte [esi]
call sys_msg_board
inc esi
jmp @b
@@:
popad
ret
sys_msg_board_byte:
; in: al = byte to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 2
shl eax, 24
jmp @f
sys_msg_board_word:
; in: ax = word to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 4
shl eax, 16
jmp @f
sys_msg_board_dword:
; in: eax = dword to display
; out: nothing
; destroys: nothing
pushad
mov ecx, 8
@@:
push ecx
rol eax, 4
push eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
mov cl, al
xor ebx, ebx
inc ebx
call sys_msg_board
pop eax
pop ecx
loop @b
popad
ret
msg_board_data_size = 65536 ; Must be power of two
uglobal
msg_board_data rb msg_board_data_size
msg_board_count dd ?
endg
iglobal
msg_board_pos dd 42*6*65536+10 ; for printing debug output on the screen
endg
sys_msg_board:
; ebx=1 -> write, cl = byte to write
; ebx=2 -> read, ecx=0 -> no data, ecx=1 -> data in al
push eax ebx
mov eax, ebx
mov ebx, ecx
mov ecx, [msg_board_count]
cmp eax, 1
jne .read
if defined debug_com_base
push dx ax
@@: ; wait for empty transmit register
mov dx, debug_com_base+5
in al, dx
test al, 1 shl 5
jz @r
mov dx, debug_com_base ; Output the byte
mov al, bl
out dx, al
pop ax dx
end if
mov [msg_board_data+ecx], bl
cmp byte [debug_direct_print], 1
jnz .end
pusha
lea edx, [msg_board_data+ecx]
mov ecx, 0x40FFFFFF
mov ebx, [msg_board_pos]
mov edi, 1
mov esi, edi ;1
call dtext
popa
add word [msg_board_pos+2], 6
cmp word [msg_board_pos+2], 105*6
jnc @f
cmp bl, 10
jnz .end
@@:
mov word [msg_board_pos+2], 42*6
add word [msg_board_pos], 10
mov eax, [_display.height]
sub eax, 10
cmp ax, word [msg_board_pos]
jnc @f
mov word [msg_board_pos], 10
@@:
pusha
mov eax, [msg_board_pos]
movzx ebx, ax
shr eax, 16
mov edx, 105*6
xor ecx, ecx
mov edi, 1
mov esi, 9
@@:
call hline
inc ebx
dec esi
jnz @b
popa
.end:
inc ecx
and ecx, msg_board_data_size - 1
mov [msg_board_count], ecx
.ret:
pop ebx eax
ret
.read:
cmp eax, 2
jne .ret
add esp, 8 ; returning data in ebx and eax, so no need to restore them
test ecx, ecx
jnz @f
mov [esp + SYSCALL_STACK.eax], ecx
mov [esp + SYSCALL_STACK.ebx], ecx
ret
@@:
mov eax, msg_board_data+1
mov ebx, msg_board_data
movzx edx, byte [ebx]
call memmove
dec [msg_board_count]
mov [esp + SYSCALL_STACK.eax], edx
mov [esp + SYSCALL_STACK.ebx], 1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 61 sys function. ;;
;; in eax=61,ebx in [1..3] ;;
;; out eax ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iglobal
align 4
f61call:
dd sys_gs.1 ; resolution
dd sys_gs.2 ; bits per pixel
dd sys_gs.3 ; bytes per scanline
endg
align 4
sys_gs: ; direct screen access
dec ebx
cmp ebx, 2
ja .not_support
jmp dword [f61call + ebx*4]
.not_support:
or [esp + SYSCALL_STACK.eax], dword -1
ret
.1: ; resolution
mov eax, [_display.width]
shl eax, 16
mov ax, word [_display.height]
mov [esp + SYSCALL_STACK.eax], eax
ret
.2: ; bits per pixel
mov eax, [_display.bits_per_pixel]
mov [esp + SYSCALL_STACK.eax], eax
ret
.3: ; bytes per scanline
mov eax, [_display.lfb_pitch]
mov [esp + SYSCALL_STACK.eax], eax
ret
align 4
syscall_getscreensize: ; GetScreenSize
mov ax, word [_display.width]
dec ax
shl eax, 16
mov ax, word [_display.height]
dec ax
mov [esp + SYSCALL_STACK.eax], eax
ret
;-----------------------------------------------------------------------------
align 4
syscall_cdaudio:
; ECX - position of CD/DVD-drive
; from 0=Primary Master to 3=Secondary Slave for first IDE contr.
; from 4=Primary Master to 7=Secondary Slave for second IDE contr.
; from 8=Primary Master to 11=Secondary Slave for third IDE contr.
cmp ecx, 11
ja .exit
mov eax, ecx
shr eax, 2
lea eax, [eax*5]
mov al, [eax + DRIVE_DATA + 1]
push ecx ebx
mov ebx, ecx
and ebx, 11b
shl ebx, 1
mov cl, 6
sub cl, bl
shr al, cl
test al, 2 ; it's not an ATAPI device
pop ebx ecx
jz .exit
cmp ebx, 4
je .eject
cmp ebx, 5
je .load
;--------------------------------------
.exit:
ret
;--------------------------------------
.load:
call .reserve
call LoadMedium
jmp .free
;--------------------------------------
.eject:
call .reserve
call clear_CD_cache
call allow_medium_removal
call EjectMedium
jmp .free
;--------------------------------------
.reserve:
call reserve_cd
mov ebx, ecx
inc ebx
mov [cdpos], ebx
mov eax, ecx
shr eax, 1
and eax, 1
inc eax
mov [ChannelNumber], al
mov eax, ecx
and eax, 1
mov [DiskNumber], al
call reserve_cd_channel
ret
;--------------------------------------
.free:
call free_cd_channel
and [cd_status], 0
ret
;-----------------------------------------------------------------------------
align 4
syscall_getpixel_WinMap: ; GetPixel WinMap
xor eax, eax
cmp ebx, [_display.width]
jae .store
cmp ecx, [_display.height]
jae .store
;--------------------------------------
mov eax, [d_width_calc_area + ecx*4]
add eax, [_display.win_map]
movzx eax, byte[eax+ebx] ; get value for current point
;--------------------------------------
align 4
.store:
mov [esp + SYSCALL_STACK.eax], eax
ret
;-----------------------------------------------------------------------------
align 4
syscall_getpixel: ; GetPixel
mov ecx, [_display.width]
xor edx, edx
mov eax, ebx
div ecx
mov ebx, edx
xchg eax, ebx
and ecx, 0xFBFFFFFF ;negate 0x04000000 use mouseunder area
call dword [GETPIXEL]; eax - x, ebx - y
mov [esp + SYSCALL_STACK.eax], ecx
ret
;-----------------------------------------------------------------------------
align 4
syscall_getarea:
;eax = 36
;ebx = pointer to bufer for img BBGGRRBBGGRR...
;ecx = [size x]*65536 + [size y]
;edx = [start x]*65536 + [start y]
pushad
mov edi, ebx
mov eax, edx
shr eax, 16
mov ebx, edx
and ebx, 0xffff
dec eax
dec ebx
; eax - x, ebx - y
mov edx, ecx
shr ecx, 16
and edx, 0xffff
mov esi, ecx
; ecx - size x, edx - size y
mov ebp, edx
lea ebp, [ebp*3]
imul ebp, esi
stdcall is_region_userspace, edi, ebp
jnz .exit
mov ebp, edx
dec ebp
lea ebp, [ebp*3]
imul ebp, esi
mov esi, ecx
dec esi
lea esi, [esi*3]
add ebp, esi
add ebp, edi
add ebx, edx
;--------------------------------------
align 4
.start_y:
push ecx edx
;--------------------------------------
align 4
.start_x:
push eax ebx ecx
add eax, ecx
and ecx, 0xFBFFFFFF ;negate 0x04000000 use mouseunder area
call dword [GETPIXEL]; eax - x, ebx - y
mov [ebp], cx
shr ecx, 16
mov [ebp+2], cl
pop ecx ebx eax
sub ebp, 3
dec ecx
jnz .start_x
pop edx ecx
dec ebx
dec edx
jnz .start_y
.exit:
popad
ret
;-----------------------------------------------------------------------------
align 4
syscall_threads: ; CreateThreads
;
; ecx=thread entry point
; edx=thread stack pointer
;
; on return : eax = pid
xor ebx, ebx
call new_sys_threads
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
align 4
calculate_fast_getting_offset_for_WinMapAddress:
; calculate data area for fast getting offset to _WinMapAddress
xor eax, eax
mov ecx, [_display.height]
mov edi, d_width_calc_area
cld
@@:
stosd
add eax, [_display.width]
dec ecx
jnz @r
ret
;------------------------------------------------------------------------------
align 4
calculate_fast_getting_offset_for_LFB:
; calculate data area for fast getting offset to LFB
xor eax, eax
mov ecx, [_display.height]
mov edi, BPSLine_calc_area
cld
@@:
stosd
add eax, [_display.lfb_pitch]
dec ecx
jnz @r
ret
;------------------------------------------------------------------------------
align 4
set_screen:
; in:
; eax - new Screen_Max_X
; ecx - new BytesPerScanLine
; edx - new Screen_Max_Y
pushfd
cli
mov [_display.lfb_pitch], ecx
mov [screen_workarea.right], eax
mov [screen_workarea.bottom], edx
push ebx
push esi
push edi
pushad
cmp [do_not_touch_winmap], 1
je @f
stdcall kernel_free, [_display.win_map]
mov eax, [_display.width]
mul [_display.height]
mov [_display.win_map_size], eax
stdcall kernel_alloc, eax
mov [_display.win_map], eax
test eax, eax
jz .epic_fail
; store for f.18.24
mov eax, [_display.width]
mov [display_width_standard], eax
mov eax, [_display.height]
mov [display_height_standard], eax
@@:
call calculate_fast_getting_offset_for_WinMapAddress
; for Qemu or non standart video cards
; Unfortunately [BytesPerScanLine] does not always
; equal to [_display.width] * [ScreenBPP] / 8
call calculate_fast_getting_offset_for_LFB
popad
call repos_windows
xor eax, eax
xor ebx, ebx
mov ecx, [_display.width]
mov edx, [_display.height]
dec ecx
dec edx
call calculatescreen
pop edi
pop esi
pop ebx
popfd
ret
.epic_fail:
hlt ; Houston, we've had a problem
; --------------- APM ---------------------
uglobal
apm_entry dp 0
apm_vf dd 0
endg
align 4
sys_apm:
xor eax, eax
cmp word [apm_vf], ax ; Check APM BIOS enable
jne @f
inc eax
or dword [esp + 44], eax ; error
add eax, 7
mov dword [esp + SYSCALL_STACK.eax], eax ; 32-bit protected-mode interface not supported
ret
@@:
; xchg eax, ecx
; xchg ebx, ecx
cmp dx, 3
ja @f
and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0
mov eax, [apm_vf]
mov [esp + SYSCALL_STACK.eax], eax
shr eax, 16
mov [esp + SYSCALL_STACK.ecx], eax
ret
@@:
mov esi, [master_tab+(OS_BASE shr 20)]
xchg [master_tab], esi
push esi
mov edi, cr3
mov cr3, edi ;flush TLB
call pword [apm_entry] ;call APM BIOS
xchg eax, [esp]
mov [master_tab], eax
mov eax, cr3
mov cr3, eax
pop eax
mov [esp + SYSCALL_STACK.edi], edi
mov [esp + SYSCALL_STACK.esi], esi
mov [esp + SYSCALL_STACK.ebx], ebx
mov [esp + SYSCALL_STACK.edx], edx
mov [esp + SYSCALL_STACK.ecx], ecx
mov [esp + SYSCALL_STACK.eax], eax
setc al
and [esp + 44], byte 0xfe
or [esp + 44], al
ret
; -----------------------------------------
align 4
undefined_syscall: ; Undefined system call
mov [esp + SYSCALL_STACK.eax], dword -1
ret
align 4
; @brief Check if given memory region lays in lower 2gb (userspace memory) or not
; @param base Base address of region
; @param len Lenght of region
; @return ZF = 1 if region in userspace memory,
; ZF = 0 otherwise
proc is_region_userspace stdcall, base:dword, len:dword
push eax
mov eax, [base]
cmp eax, OS_BASE-1
ja @f ; zf
add eax, [len]
jc @f ; zf
cmp eax, OS_BASE
ja @f ; zf
cmp eax, eax ; ZF
@@:
pop eax
ret
endp
align 4
; @brief Check whether given string lays in userspace memory, i.e. below OS_BASE
; @param base Base address of string
; @return ZF = 1 if string in userspace memory,
; zf = 0 otherwise
proc is_string_userspace stdcall, base:dword
push eax ecx edi
xor eax, eax
mov edi, [base]
mov ecx, OS_BASE-1
sub ecx, edi
jb .done ; zf
inc ecx
cmp ecx, 0x10000 ; don't allow strings larger than 64k?
jbe @f
mov ecx, 0x10000
@@:
repnz scasb
.done:
pop edi ecx eax
ret
endp
if ~ lang eq sp
diff16 "end of .text segment",0,$
end if
include "data32.inc"
__REV__ = __REV
if ~ lang eq sp
diff16 "end of kernel code",0,$
end if