kolibrios/kernel/trunk/init.inc

513 lines
14 KiB
PHP
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
proc mem_test
; if we have BIOS with fn E820, skip the test
cmp [BOOT_LO.memmap_block_cnt], 0
jnz .ret
mov eax, cr0
and eax, not (CR0_CD + CR0_NW)
or eax, CR0_CD ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
xor edi, edi
mov ebx, 'TEST'
@@:
add edi, 0x100000
xchg ebx, dword [edi]
cmp dword [edi], 'TEST'
xchg ebx, dword [edi]
je @b
and eax, not (CR0_CD + CR0_NW) ;enable caching
mov cr0, eax
inc dword [BOOT_LO.memmap_block_cnt]
xor eax, eax
mov [BOOT_LO.memmap_blocks + e820entry.addr.lo], eax
mov [BOOT_LO.memmap_blocks + e820entry.addr.hi], eax
mov [BOOT_LO.memmap_blocks + e820entry.size.lo], edi
mov [BOOT_LO.memmap_blocks + e820entry.size.hi], eax
inc eax
mov [BOOT_LO.memmap_blocks + e820entry.type], eax
.ret:
ret
endp
align 4
proc init_mem
; calculate maximum allocatable address and number of allocatable pages
mov edi, BOOT_LO.memmap_blocks
mov ecx, [edi-4] ; memmap_block_cnt
xor esi, esi; esi will hold total amount of memory
xor edx, edx; edx will hold maximum allocatable address
.calcmax:
; round all to pages
mov eax, [edi + e820entry.addr.lo]
cmp byte [edi + e820entry.type], 1
jne .unusable
test eax, PAGE_SIZE-1
jz @f
neg eax
and eax, PAGE_SIZE-1
add [edi + e820entry.addr.lo], eax
adc [edi + e820entry.addr.hi], 0
sub [edi + e820entry.size.lo], eax
sbb [edi + e820entry.size.hi], 0
jc .unusable
@@:
and [edi + e820entry.size.lo], -PAGE_SIZE
jz .unusable
; ignore memory after 4 GiB
cmp [edi + e820entry.addr.hi], 0
jnz .unusable
mov eax, [edi + e820entry.addr.lo]
cmp [edi + e820entry.size.hi], 0
jnz .overflow
add eax, [edi + e820entry.size.lo]
jnc @f
.overflow:
mov eax, -PAGE_SIZE
@@:
cmp edx, eax
jae @f
mov edx, eax
@@:
sub eax, [edi + e820entry.addr.lo]
mov [edi + e820entry.size.lo], eax
add esi, eax
jmp .usable
.unusable:
; and dword [edi+e820entry.size.lo], 0
.usable:
add edi, sizeof.e820entry
loop .calcmax
.calculated:
mov [MEM_AMOUNT - OS_BASE], esi
mov [pg_data.mem_amount - OS_BASE], esi
shr esi, 12
mov [pg_data.pages_count - OS_BASE], esi
shr edx, 12
add edx, 31
and edx, not 31
shr edx, 3
mov [pg_data.pagemap_size - OS_BASE], edx
add edx, (sys_pgmap - OS_BASE)+PAGE_SIZE-1
and edx, -PAGE_SIZE
mov [tmp_page_tabs], edx
mov edx, esi
and edx, -1024
cmp edx, (OS_BASE/PAGE_SIZE)
jbe @F
mov edx, (OS_BASE/PAGE_SIZE)
jmp .set
@@:
cmp edx, (HEAP_BASE - OS_BASE + HEAP_MIN_SIZE)/PAGE_SIZE
jae .set
mov edx, (HEAP_BASE - OS_BASE + HEAP_MIN_SIZE)/PAGE_SIZE
.set:
mov [pg_data.kernel_pages - OS_BASE], edx
shr edx, 10
mov [pg_data.kernel_tables - OS_BASE], edx
xor eax, eax
mov edi, sys_proc - OS_BASE
mov ecx, 2*PAGE_SIZE/4
cld
rep stosd
mov edx, (sys_proc - OS_BASE + PROC.pdt_0) + (OS_BASE shr 20)
bt [cpu_caps - OS_BASE], CAPS_PSE
jnc .no_PSE
mov ebx, cr4
or ebx, CR4_PSE
mov eax, PDE_LARGE + PG_SWR
mov cr4, ebx
dec [pg_data.kernel_tables - OS_BASE]
mov [edx], eax
add edx, 4
mov edi, [tmp_page_tabs]
jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low"
.no_PSE:
mov eax, PG_SWR
mov ecx, [tmp_page_tabs]
shr ecx, 12
.map_low:
mov edi, [tmp_page_tabs]
@@: ;
stosd
add eax, PAGE_SIZE
dec ecx
jnz @B
.map_kernel_heap:
mov ecx, [pg_data.kernel_tables - OS_BASE]
shl ecx, 10
xor eax, eax
rep stosd
mov ecx, [pg_data.kernel_tables - OS_BASE]
mov eax, [tmp_page_tabs]
or eax, PG_SWR
mov edi, edx
.map_kernel_tabs:
stosd
add eax, PAGE_SIZE
dec ecx
jnz .map_kernel_tabs
mov dword [sys_proc-OS_BASE+PROC.pdt_0+(page_tabs shr 20)], sys_proc+PROC.pdt_0+PG_SWR-OS_BASE
mov edi, (sys_proc + PROC.pdt_0 - OS_BASE)
lea esi, [edi + (OS_BASE shr 20)]
movsd
movsd
ret
endp
align 4
proc init_page_map
; mark all memory as unavailable
mov edi, sys_pgmap - OS_BASE
mov ecx, [pg_data.pagemap_size - OS_BASE]
shr ecx, 2
xor eax, eax
cld
rep stosd
; scan through memory map and mark free areas as available
mov ebx, BOOT_LO.memmap_blocks
mov edx, [ebx-4]
.scanmap:
cmp byte [ebx + e820entry.type], 1
jne .next
mov ecx, [ebx + e820entry.size.lo]
shr ecx, 12; ecx = number of pages
jz .next
mov edi, [ebx + e820entry.addr.lo]
shr edi, 12; edi = first page
mov eax, edi
shr edi, 5
shl edi, 2
add edi, sys_pgmap - OS_BASE
and eax, 31
jz .startok
add ecx, eax
sub ecx, 32
jbe .onedword
push ecx
mov ecx, eax
or eax, -1
shl eax, cl
or [edi], eax
add edi, 4
pop ecx
.startok:
push ecx
shr ecx, 5
or eax, -1
rep stosd
pop ecx
and ecx, 31
neg eax
shl eax, cl
dec eax
or [edi], eax
jmp .next
.onedword:
add ecx, 32
sub ecx, eax
@@:
bts [edi], eax
inc eax
loop @b
.next:
add ebx, sizeof.e820entry
dec edx
jnz .scanmap
; mark kernel memory as allocated (unavailable)
mov ecx, [tmp_page_tabs]
mov edx, [pg_data.pages_count - OS_BASE]
shr ecx, 12
add ecx, [pg_data.kernel_tables - OS_BASE]
sub edx, ecx
mov [pg_data.pages_free - OS_BASE], edx
mov edi, sys_pgmap - OS_BASE
mov ebx, ecx
shr ecx, 5
xor eax, eax
rep stosd
not eax
mov ecx, ebx
and ecx, 31
shl eax, cl
and [edi], eax
add edi, OS_BASE
mov [page_start - OS_BASE], edi;
mov ebx, sys_pgmap
add ebx, [pg_data.pagemap_size - OS_BASE]
mov [page_end - OS_BASE], ebx
ret
endp
align 4
init_BIOS32:
mov edi, 0xE0000
.pcibios_nxt:
cmp dword[edi], '_32_'; "magic" word
je .BIOS32_found
.pcibios_nxt2:
add edi, 0x10
cmp edi, 0xFFFF0
je .BIOS32_not_found
jmp .pcibios_nxt
.BIOS32_found: ; magic word found, check control summ
movzx ecx, byte[edi + 9]
shl ecx, 4
mov esi, edi
xor eax, eax
cld ; paranoia
@@:
lodsb
add ah, al
loop @b
jnz .pcibios_nxt2; control summ must be zero
; BIOS32 service found !
mov ebp, [edi + 4]
mov [bios32_entry], ebp
; check PCI BIOS present
mov eax, '$PCI'
xor ebx, ebx
push cs ; special for 'ret far' from BIOS
call ebp
test al, al
jnz .PCI_BIOS32_not_found
; descriptors for PCI BIOS are created here
add ebx, OS_BASE
dec ecx
mov [(pci_code_32 - OS_BASE)], cx ;limit 0-15
mov [(pci_data_32 - OS_BASE)], cx ;limit 0-15
mov [(pci_code_32 - OS_BASE)+2], bx ;base 0-15
mov [(pci_data_32 - OS_BASE)+2], bx ;base 0-15
shr ebx, 16
mov [(pci_code_32 - OS_BASE)+4], bl ;base 16-23
mov [(pci_data_32 - OS_BASE)+4], bl ;base 16-23
shr ecx, 16
and cl, 0x0F
mov ch, bh
add cx, D32
mov [(pci_code_32 - OS_BASE)+6], cx ;lim 16-19 &
mov [(pci_data_32 - OS_BASE)+6], cx ;base 24-31
mov [(pci_bios_entry - OS_BASE)], edx
; jmp .end
.PCI_BIOS32_not_found:
; pci_emu_dat structure should be filled here
.BIOS32_not_found:
.end:
ret
align 4
proc test_cpu
locals
cpu_type dd ?
endl
xor eax, eax
mov [cpu_type], eax
mov [cpu_caps - OS_BASE], eax
mov [cpu_caps + 4 - OS_BASE], eax
mov [cpu_phys_addr_width - OS_BASE], 32
pushfd
pop eax
mov ecx, eax
xor eax, EFLAGS_AC
push eax
popfd
pushfd
pop eax
xor eax, ecx
mov [cpu_type], CPU_386
jz .end_cpuid
push ecx
popfd
mov [cpu_type], CPU_486
mov eax, ecx
xor eax, EFLAGS_ID
push eax
popfd
pushfd
pop eax
xor eax, ecx
je .end_cpuid
xor eax, eax
cpuid
mov [cpu_vendor - OS_BASE], ebx
mov [cpu_vendor + 4 - OS_BASE], edx
mov [cpu_vendor + 8 - OS_BASE], ecx
cmp eax, 1
jl .end_cpuid
mov eax, 1
cpuid
mov [cpu_sign - OS_BASE], eax
mov [cpu_info - OS_BASE], ebx
mov [cpu_caps - OS_BASE], edx
mov [cpu_caps + 4 - OS_BASE], ecx
bt edx, CAPS_PAE
jnc @f
mov [cpu_phys_addr_width - OS_BASE], 36
@@:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000008
jb @f
mov eax, 0x80000008
cpuid
mov [cpu_phys_addr_width - OS_BASE], al
@@:
mov eax, [cpu_sign - OS_BASE]
shr eax, 8
and eax, 0x0f
ret
.end_cpuid:
mov eax, [cpu_type]
ret
endp
ACPI_RSDP_CHECKSUM_LENGTH = 20
proc acpi_locate_tables uses ebx esi edi
mov ebx, [ebx + ACPI_RSDP.RsdtAddress]
mov [acpi_rsdt_base - OS_BASE], ebx
mov eax, [ebx + ACPI_RSDT.Length]
mov [acpi_rsdt_size - OS_BASE], eax
mov esi, [acpi_rsdt_base - OS_BASE]
mov ecx, [esi + ACPI_RSDT.Length]
lea edi, [esi + ecx]
add esi, sizeof.ACPI_TABLE
movi ecx, 1
.next_table:
cmp esi, edi
jae .done
lodsd
cmp [eax+ACPI_TABLE.Signature], 'SSDT' ; skip DSDT if present
jz .ssdt ; read it from FADT
cmp [eax+ACPI_TABLE.Signature], 'FACP' ; this is FADT
jz .fadt
cmp [eax+ACPI_TABLE.Signature], 'APIC' ; this is MADT
jz .madt
cmp [eax+ACPI_TABLE.Signature], 'HPET'
jz .hpet
jmp .next_table
.ssdt:
mov [acpi_ssdt_base + ecx*4 - OS_BASE], eax
mov eax, [eax+ACPI_TABLE.Length]
mov [acpi_ssdt_size + ecx*4 - OS_BASE], eax
inc ecx
jmp .next_table
.fadt:
mov [acpi_fadt_base - OS_BASE], eax
cmp [eax + ACPI_FADT.DSDT], 0
jz @f
mov edx, [eax + ACPI_FADT.DSDT]
mov [acpi_ssdt_base - OS_BASE], edx
mov edx, [edx + ACPI_TABLE.Length]
mov [acpi_ssdt_size - OS_BASE], edx
@@:
mov eax, [eax + ACPI_TABLE.Length]
mov [acpi_fadt_size - OS_BASE], eax
jmp .next_table
.madt:
mov [acpi_madt_base - OS_BASE], eax
mov eax, [eax + ACPI_TABLE.Length]
mov [acpi_madt_size - OS_BASE], eax
jmp .next_table
.hpet:
mov [acpi_hpet_base - OS_BASE], eax
mov eax, [eax + ACPI_TABLE.Length]
mov [acpi_hpet_size - OS_BASE], eax
jmp .next_table
.done:
mov [acpi_ssdt_cnt - OS_BASE], ecx
ret
endp
acpi_locate:
push ebx
push edi
mov ebx, [BOOT_LO.acpi_rsdp]
test ebx, ebx
jz .done
mov edi, ebx
call .check
.done:
mov [acpi_rsdp_base - OS_BASE], ebx
test ebx, ebx
jz @f
call acpi_locate_tables
@@:
pop edi
pop ebx
ret
.check:
cmp [ebx], dword 'RSD '
jne .next
cmp [ebx+4], dword 'PTR '
jne .next
mov edx, ebx
mov ecx, ACPI_RSDP_CHECKSUM_LENGTH
xor eax, eax
.sum:
add al, [edx]
inc edx
loop .sum
test al, al
jnz .next
ret
.next:
add ebx, 16
cmp ebx, edi
jb .check
xor ebx, ebx
ret