kos-acpi: reworked restart etc

git-svn-id: svn://kolibrios.org@6242 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-02-17 14:32:29 +00:00
parent a73038cb78
commit d4aeb26207
5 changed files with 238 additions and 449 deletions

View File

@ -13,18 +13,212 @@
$Revision$
use32
become_real:
align 4
system_shutdown: ; shut down the system
cmp byte [BOOT_VARS+0x9030], 1
jne @F
ret
@@:
call stop_all_services
yes_shutdown_param:
; Shutdown other CPUs, if initialized
cmp [ap_initialized], 0
jz .no_shutdown_cpus
mov edi, [LAPIC_BASE]
add edi, 300h
mov esi, smpt+4
mov ebx, [cpu_count]
dec ebx
.shutdown_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
; don't send STARTUP IPI: let other CPUs be in wait-for-startup state
pop esi
dec ebx
jnz .shutdown_cpus_loop
.no_shutdown_cpus:
cli
call IRQ_mask_all
mov eax, [OS_BASE + 0x9030]
cmp al, SYSTEM_RESTART
jne @F
; load kernel.mnt to _CLEAN_ZONE
mov ebx, kernel_file_load
pushad
call file_system_lfn
popad
@@:
mov esi, OS_BASE+restart_code_start ; move kernel re-starter to 0x5000:0
mov edi, OS_BASE+0x50000
mov ecx, (restart_code_end - restart_code_start)/4
rep movsd
call create_trampoline_pgmap
mov cr3, eax
jmp @F
org $-OS_BASE
@@:
;disable paging
mov eax, cr0
and eax, 0x7FFFFFFF
mov cr0, eax
mov eax, cr3
mov cr3, eax
cmp byte [0x9030], SYSTEM_SHUTDOWN
jne no_acpi_power_off
; system_power_off
mov ebx, [acpi_fadt_base-OS_BASE]
cmp dword [ebx], 'FACP'
jne no_acpi_power_off
mov esi, [acpi_dsdt_base-OS_BASE]
cmp dword [esi], 'DSDT'
jne no_acpi_power_off
mov eax, [esi+4] ; DSDT length
sub eax, 36+4
jbe no_acpi_power_off
add esi, 36
.scan_dsdt:
cmp dword [esi], '_S5_'
jnz .scan_dsdt_cont
cmp byte [esi+4], 12h ; DefPackage opcode
jnz .scan_dsdt_cont
mov dl, [esi+6]
cmp dl, 4 ; _S5_ package must contain 4 bytes
; ...in theory; in practice, VirtualBox has 2 bytes
ja .scan_dsdt_cont
cmp dl, 1
jb .scan_dsdt_cont
lea esi, [esi+7]
xor ecx, ecx
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov cl, [esi]
@@:
inc esi
cmp dl, 2
jb @f
cmp byte [esi], 0
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov ch, [esi]
@@:
jmp do_acpi_power_off
.scan_dsdt_cont:
inc esi
dec eax
jnz .scan_dsdt
jmp no_acpi_power_off
do_acpi_power_off:
mov edx, [ebx+48]
test edx, edx
jz .nosmi
mov al, [ebx+52]
out dx, al
mov edx, [ebx+64]
@@:
in ax, dx
test al, 1
jz @b
.nosmi:
and cx, 0x0707
shl cx, 2
or cx, 0x2020
mov edx, [ebx+64]
in ax, dx
and ax, 203h
or ah, cl
out dx, ax
mov edx, [ebx+68]
test edx, edx
jz @f
in ax, dx
and ax, 203h
or ah, ch
out dx, ax
@@:
jmp $
no_acpi_power_off:
jmp 0x50000
align 4
restart_code_start:
org 0x50000
cmp byte [0x9030], SYSTEM_RESTART
jne @F
mov esi, _CLEAN_ZONE-OS_BASE
mov edi, 0x10000
mov ecx, 0x31000/4
cld
rep movsd
@@:
xor ebx, ebx
xor edx, edx
xor ecx, ecx
xor esi, esi
xor edi, edi
xor ebp, ebp
cli
ltr bx
lgdt [realmode_gdt-OS_BASE]
lidt [.idt]
lgdt [.gdt]
jmp 8:@f
align 8
.gdt:
; selector 0 - not used
dw 23
dd .gdt
dw 0
; selector 8 - code from 5000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 5
db 10011011b
db 00000000b
db 0
; selector 10h - data from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 1
db 10010011b
db 00000000b
db 0
.idt:
dw 256*4
dd 0
org $ - 0x50000
use16
@@:
mov ax, 10h
@ -33,109 +227,64 @@ use16
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and eax, not 80000001h
mov cr0, eax
jmp 0x1000:pr_mode_exit
jmp 0x5000:.real_mode
pr_mode_exit:
align 4
.real_mode:
; setup stack
mov ax, (TMP_STACK_TOP and 0xF0000) shr 4
mov ss, ax
mov esp, TMP_STACK_TOP and 0xFFFF
;setup ds
push cs
pop ds
lidt [old_ints_h]
;remap IRQs
mov al, 0x11
out 0x20, al
call rdelay
out 0xA0, al
call rdelay
mov al, 0x08
out 0x21, al
call rdelay
mov al, 0x70
out 0xA1, al
call rdelay
mov al, 0x04
out 0x21, al
call rdelay
mov al, 0x02
out 0xA1, al
call rdelay
mov al, 0x01
out 0x21, al
call rdelay
out 0xA1, al
call rdelay
mov al, 0xB8
out 0x21, al
call rdelay
mov al, 0xBD
out 0xA1, al
sti
temp_3456:
mov al, 00110100b
out 43h, al
mov al, 0xFF
out 40h, al
out 40h, al
xor ax, ax
mov es, ax
mov al, byte [es:0x9030]
cmp al, 1
jl nbw
cmp al, 4
jle nbw32
mov ds, ax
mov al, [0x9030]
cmp al, SYSTEM_RESTART
je .restart
nbw:
in al, 0x60
cmp al, 6
jae nbw
mov bl, al
nbw2:
in al, 0x60
cmp al, bl
je nbw2
cmp al, 240;ax,240
jne nbw31
mov al, bl
dec ax
jmp nbw32
nbw31:
add bl, 128
cmp al, bl
jne nbw
sub al, 129
cmp al, SYSTEM_SHUTDOWN
je .APM_PowerOff
nbw32:
dec ax
dec ax ; 2 = power off
jnz no_apm_off
call APM_PowerOff
jmp $
no_apm_off:
if ~ defined extended_primary_loader ; kernel restarting is not supported
dec ax ; 3 = reboot
jnz restart_kernel ; 4 = restart kernel
end if
push 0x40
pop ds
mov word[0x0072], 0x1234
mov word[0x0472], 0x1234
jmp 0xF000:0xFFF0
rdelay:
ret
APM_PowerOff:
.APM_PowerOff:
mov ax, 5304h
xor bx, bx
int 15h
@ -174,67 +323,24 @@ APM_PowerOff:
mov cx, 3
int 0x15
;!!!!!!!!!!!!!!!!!!!!!!!!
ret
jmp $
if ~ defined extended_primary_loader
restart_kernel:
mov ax, 0x0003 ; set text mode for screen
int 0x10
jmp 0x5000:0000
restart_kernel_5001:
cli
push ds
pop es
xor si, si
xor di, di
push 0x7100
pop ds
mov cx, 0x4000
rep movsd
push 0x8100
pop ds
push 0x2000
pop es
mov cx, 0x4000
rep movsd
push 0x9100
pop ds
push 0x3000
pop es
mov cx, 0x4000
rep movsd
xchg bx, bx
push 0xA100
pop ds
push 0x4000
pop es
mov cx, 0x800
rep movsd
wbinvd ; write and invalidate cache
mov al, 00110100b
out 43h, al
jcxz $+2
mov al, 0xFF
out 40h, al
jcxz $+2
out 40h, al
jcxz $+2
sti
.restart:
; (hint by Black_mirror)
; We must read data from keyboard port,
; because there may be situation when previous keyboard interrupt is lost
; (due to return to real mode and IRQ reprogramming)
; and next interrupt will not be generated (as keyboard waits for handling)
mov cx, 16
@@:
in al, 0x64
test al, 1
jz @F
in al, 0x60
loop @B
@@:
; bootloader interface
push 0x1000
@ -242,5 +348,10 @@ xchg bx, bx
mov si, kernel_restart_bootblock
mov ax, 'KL'
jmp 0x1000:0000
end if
align 4
org restart_code_start + $
restart_code_end:
org $+OS_BASE
use32

View File

@ -372,12 +372,10 @@ os_stack_seg rd 1
srv.fd rd 1
srv.bk rd 1
align 16
_display display_t
LFBAddress dd ?
SCR_MODE rw 2

View File

@ -463,8 +463,10 @@ acpi_locate:
call .check
test ebx, ebx
jnz .done
jz @F
jmp .done
@@:
mov ebx, ACPI_HI_RSDP_WINDOW_START
mov edi, ACPI_HI_RSDP_WINDOW_END
call .check

View File

@ -305,12 +305,7 @@ B32:
align 4
bios32_entry dd ?
tmp_page_tabs dd ?
use16
org $-0x10000
include "boot/shutdown.inc" ; shutdown or restart
org $+0x10000
ap_init16:
cli
lgdt [cs:gdts_ap-ap_init16]
@ -5722,323 +5717,6 @@ undefined_syscall: ; Undefined system call
mov [esp + 32], dword -1
ret
align 4
system_shutdown: ; shut down the system
cmp byte [BOOT_VARS+0x9030], 1
jne @F
ret
@@:
call stop_all_services
yes_shutdown_param:
; Shutdown other CPUs, if initialized
cmp [ap_initialized], 0
jz .no_shutdown_cpus
mov edi, [LAPIC_BASE]
add edi, 300h
mov esi, smpt+4
mov ebx, [cpu_count]
dec ebx
.shutdown_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
; don't send STARTUP IPI: let other CPUs be in wait-for-startup state
pop esi
dec ebx
jnz .shutdown_cpus_loop
.no_shutdown_cpus:
cli
call IRQ_mask_all
mov eax, [OS_BASE + 0x9030]
cmp al, SYSTEM_RESTART
jne @F
; load kernel.mnt to _CLEAN_ZONE
mov ebx, kernel_file_load
pushad
call file_system_lfn
popad
mov esi, OS_BASE+restart_kernel_5000 ; move kernel re-starter to 0x5000:0
mov edi, OS_BASE+0x50000
mov ecx, (restart_code_end - restart_kernel_5000)/4
rep movsd
@@:
;disable paging
call create_trampoline_pgmap
mov cr3, eax
jmp @F
org $-OS_BASE
@@:
mov eax, cr0
and eax, 0x7FFFFFFF
mov cr0, eax
mov eax, cr3
mov cr3, eax
cmp byte [0x9030], SYSTEM_SHUTDOWN
jne no_acpi_power_off
; system_power_off
mov ebx, [acpi_fadt_base-OS_BASE]
cmp dword [ebx], 'FACP'
jne no_acpi_power_off
mov esi, [acpi_dsdt_base-OS_BASE]
cmp dword [esi], 'DSDT'
jne no_acpi_power_off
mov eax, [esi+4] ; DSDT length
sub eax, 36+4
jbe no_acpi_power_off
add esi, 36
.scan_dsdt:
cmp dword [esi], '_S5_'
jnz .scan_dsdt_cont
cmp byte [esi+4], 12h ; DefPackage opcode
jnz .scan_dsdt_cont
mov dl, [esi+6]
cmp dl, 4 ; _S5_ package must contain 4 bytes
; ...in theory; in practice, VirtualBox has 2 bytes
ja .scan_dsdt_cont
cmp dl, 1
jb .scan_dsdt_cont
lea esi, [esi+7]
xor ecx, ecx
cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov cl, [esi]
@@:
inc esi
cmp dl, 2
jb @f
cmp byte [esi], 0
jz @f
cmp byte [esi], 0xA
jnz no_acpi_power_off
inc esi
mov ch, [esi]
@@:
jmp do_acpi_power_off
.scan_dsdt_cont:
inc esi
dec eax
jnz .scan_dsdt
jmp no_acpi_power_off
do_acpi_power_off:
mov edx, [ebx+48]
test edx, edx
jz .nosmi
mov al, [ebx+52]
out dx, al
mov edx, [ebx+64]
@@:
in ax, dx
test al, 1
jz @b
.nosmi:
and cx, 0x0707
shl cx, 2
or cx, 0x2020
mov edx, [ebx+64]
in ax, dx
and ax, 203h
or ah, cl
out dx, ax
mov edx, [ebx+68]
test edx, edx
jz @f
in ax, dx
and ax, 203h
or ah, ch
out dx, ax
@@:
jmp $
no_acpi_power_off:
jmp 0x50000
align 4
restart_kernel_5000:
org 0x50000
cmp byte [0x9030], SYSTEM_RESTART
jne @F
xchg bx, bx
mov esi, _CLEAN_ZONE-OS_BASE
mov edi, 0x10000
mov ecx, 0x31000/4
cld
rep movsd
@@:
xor ebx, ebx
xor edx, edx
xor ecx, ecx
xor esi, esi
xor edi, edi
xor ebp, ebp
lidt [.idt]
lgdt [.gdt]
jmp 8:@f
align 8
.gdt:
; selector 0 - not used
dw 23
dd .gdt
dw 0
; selector 8 - code from 5000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 5
db 10011011b
db 00000000b
db 0
; selector 10h - data from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 1
db 10010011b
db 00000000b
db 0
.idt:
dw 256*4
dd 0
org $ - 0x50000
use16
@@:
mov ax, 10h
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and eax, not 80000001h
mov cr0, eax
jmp 0x5000:.real_mode
align 4
.real_mode:
; setup stack
mov ax, (TMP_STACK_TOP and 0xF0000) shr 4
mov ss, ax
mov esp, TMP_STACK_TOP and 0xFFFF
;remap IRQs
mov al, 0x11
out 0x20, al
out 0xA0, al
mov al, 0x08
out 0x21, al
mov al, 0x70
out 0xA1, al
mov al, 0x04
out 0x21, al
mov al, 0x02
out 0xA1, al
mov al, 0x01
out 0x21, al
out 0xA1, al
mov al, 0xB8
out 0x21, al
mov al, 0xBD
out 0xA1, al
mov al, 00110100b
out 43h, al
mov al, 0xFF
out 40h, al
out 40h, al
mov al, byte [es:0x9030]
cmp al, SYSTEM_RESTART
je .do_restart
jmp $
.do_restart:
mov ax, 0x0003 ; set text mode for screen
int 0x10
sti
; (hint by Black_mirror)
; We must read data from keyboard port,
; because there may be situation when previous keyboard interrupt is lost
; (due to return to real mode and IRQ reprogramming)
; and next interrupt will not be generated (as keyboard waits for handling)
in al, 0x60
; bootloader interface
push 0x1000
pop ds
mov si, kernel_restart_bootblock
mov ax, 'KL'
jmp 0x1000:0000
align 4
org restart_kernel_5000 + $
restart_code_end:
iglobal
align 4
realmode_gdt:
; selector 0 - not used
dw 23
dd realmode_gdt-OS_BASE
dw 0
; selector 8 - code from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 5
db 10011011b
db 00000000b
db 0
; selector 10h - data from 1000:0000 to 1000:FFFF
dw 0FFFFh
dw 0
db 1
db 10010011b
db 00000000b
db 0
endg
org $+OS_BASE
if ~ lang eq sp
diff16 "end of .text segment",0,$

View File

@ -42,7 +42,7 @@ include "gui/event.inc"
include "gui/font.inc"
include "gui/button.inc"
; shutdown
include "boot/shutdown.inc" ; kernel shutdown
; file system