kernel: restart, reboot and power off

git-svn-id: svn://kolibrios.org@6244 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-02-18 02:03:38 +00:00
parent 465434cb12
commit 50e97c60fa
6 changed files with 277 additions and 396 deletions

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;; Shutdown for Menuet ;; ;; Shutdown for Menuet ;;
@ -13,11 +13,212 @@
$Revision$ $Revision$
use32 align 4
become_real: 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 cli
lgdt [realmode_gdt-OS_BASE] 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
lidt [.idt]
lgdt [.gdt]
jmp 8:@f 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 use16
@@: @@:
mov ax, 10h mov ax, 10h
@ -26,108 +227,64 @@ use16
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov eax, cr0 mov eax, cr0
and eax, not 80000001h and eax, not 80000001h
mov cr0, eax mov cr0, eax
jmp 0x1000:pr_mode_exit jmp 0x5000:.real_mode
pr_mode_exit: align 4
.real_mode:
; setup stack ; setup stack
mov ax, 0x3000
mov ss, ax
mov esp, 0x0EC00
; setup ds
push cs
pop ds
lidt [old_ints_h] mov ax, (TMP_STACK_TOP and 0xF0000) shr 4
mov ss, ax
mov esp, TMP_STACK_TOP and 0xFFFF
;remap IRQs ;remap IRQs
mov al, 0x11 mov al, 0x11
out 0x20, al out 0x20, al
call rdelay
out 0xA0, al out 0xA0, al
call rdelay
mov al, 0x08 mov al, 0x08
out 0x21, al out 0x21, al
call rdelay
mov al, 0x70 mov al, 0x70
out 0xA1, al out 0xA1, al
call rdelay
mov al, 0x04 mov al, 0x04
out 0x21, al out 0x21, al
call rdelay
mov al, 0x02 mov al, 0x02
out 0xA1, al out 0xA1, al
call rdelay
mov al, 0x01 mov al, 0x01
out 0x21, al out 0x21, al
call rdelay
out 0xA1, al out 0xA1, al
call rdelay
mov al, 0xB8 mov al, 0xB8
out 0x21, al out 0x21, al
call rdelay
mov al, 0xBD mov al, 0xBD
out 0xA1, al out 0xA1, al
sti
temp_3456: mov al, 00110100b
out 43h, al
mov al, 0xFF
out 40h, al
out 40h, al
xor ax, ax xor ax, ax
mov es, ax mov ds, ax
mov al, byte [es:0x9030] mov al, [0x9030]
cmp al, 1 cmp al, SYSTEM_RESTART
jl nbw je .restart
cmp al, 4
jle nbw32
nbw: cmp al, SYSTEM_SHUTDOWN
in al, 0x60 je .APM_PowerOff
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
nbw32: mov word[0x0472], 0x1234
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
jmp 0xF000:0xFFF0 jmp 0xF000:0xFFF0
.APM_PowerOff:
rdelay:
ret
APM_PowerOff:
mov ax, 5304h mov ax, 5304h
xor bx, bx xor bx, bx
int 15h int 15h
@ -166,57 +323,24 @@ APM_PowerOff:
mov cx, 3 mov cx, 3
int 0x15 int 0x15
;!!!!!!!!!!!!!!!!!!!!!!!! ;!!!!!!!!!!!!!!!!!!!!!!!!
ret jmp $
if ~ defined extended_primary_loader .restart:
restart_kernel:
mov ax, 0x0003 ; set text mode for screen
int 0x10
jmp 0x4000:0000
restart_kernel_4000:
cli
push ds
pop es
mov cx, 0x8000
push cx
push 0x7100
pop ds
xor si, si
xor di, di
rep movsw
pop cx
mov ds, cx
push 0x2000
pop es
rep movsw
push 0x9000
pop ds
push 0x3000
pop es
mov cx, 0xE000/2
rep movsw
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
; (hint by Black_mirror) ; (hint by Black_mirror)
; We must read data from keyboard port, ; We must read data from keyboard port,
; because there may be situation when previous keyboard interrupt is lost ; because there may be situation when previous keyboard interrupt is lost
; (due to return to real mode and IRQ reprogramming) ; (due to return to real mode and IRQ reprogramming)
; and next interrupt will not be generated (as keyboard waits for handling) ; 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 in al, 0x60
loop @B
@@:
; bootloader interface ; bootloader interface
push 0x1000 push 0x1000
@ -224,5 +348,10 @@ restart_kernel_4000:
mov si, kernel_restart_bootblock mov si, kernel_restart_bootblock
mov ax, 'KL' mov ax, 'KL'
jmp 0x1000:0000 jmp 0x1000:0000
end if
align 4
org restart_code_start + $
restart_code_end:
org $+OS_BASE
use32

View File

@ -354,9 +354,13 @@ EVENT_EXTENDED equ 0x00000400
EV_INTR equ 1 EV_INTR equ 1
STDIN_FILENO equ 0 STDIN_FILENO equ 0
STDOUT_FILENO equ 1 STDOUT_FILENO equ 1
STDERR_FILENO equ 2 STDERR_FILENO equ 2
SYSTEM_SHUTDOWN equ 2
SYSTEM_REBOOT equ 3
SYSTEM_RESTART equ 4
struct SYSCALL_STACK struct SYSCALL_STACK
_eip dd ? _eip dd ?

View File

@ -173,11 +173,11 @@ end if
vmode db '/sys/drivers/VMODE.MDR',0 vmode db '/sys/drivers/VMODE.MDR',0
;vrr_m db 'VRR_M',0 ;vrr_m db 'VRR_M',0
kernel_file_load: kernel_file_load:
; load kernel.mnt to 0x7000:0 ; load kernel.mnt to _CLEAN_ZONE
dd 0 ; subfunction dd 0 ; subfunction
dq 0 ; offset in file dq 0 ; offset in file
dd 0x30000 ; number of bytes to read dd 0x31000 ; number of bytes to read
dd OS_BASE + 0x71000 ; buffer for data dd _CLEAN_ZONE ; buffer for data
db '/RD/1/KERNEL.MNT',0 db '/RD/1/KERNEL.MNT',0
dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0 dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
@ -371,12 +371,10 @@ os_stack_seg rd 1
srv.fd rd 1 srv.fd rd 1
srv.bk rd 1 srv.bk rd 1
align 16 align 16
_display display_t _display display_t
LFBAddress dd ? LFBAddress dd ?
SCR_MODE rw 2 SCR_MODE rw 2

View File

@ -455,7 +455,27 @@ ACPI_FADT_SIGN equ 0x50434146
acpi_locate: acpi_locate:
push ebx push ebx
push edi
movzx ebx, word [0x40E]
shl ebx, 4
lea ecx, [ebx+1024]
call .check
test ebx, ebx
jz @F
jmp .done
@@:
mov ebx, ACPI_HI_RSDP_WINDOW_START mov ebx, ACPI_HI_RSDP_WINDOW_START
mov edi, ACPI_HI_RSDP_WINDOW_END
call .check
.done:
mov eax, ebx
pop edi
pop ebx
ret
.check: .check:
cmp [ebx], dword 0x20445352 cmp [ebx], dword 0x20445352
jne .next jne .next
@ -472,17 +492,12 @@ acpi_locate:
test al, al test al, al
jnz .next jnz .next
mov eax, ebx
pop ebx
ret ret
.next: .next:
add ebx, 16 add ebx, 16
cmp ebx, ACPI_HI_RSDP_WINDOW_END cmp ebx, edi
jb .check jb .check
xor ebx, ebx
pop ebx
xor eax, eax
ret ret
align 4 align 4

View File

@ -253,7 +253,7 @@ B32:
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov esp, 0x006CC00 ; Set stack mov esp, TMP_STACK_TOP ; Set stack
; CLEAR 0x280000 - HEAP_BASE ; CLEAR 0x280000 - HEAP_BASE
@ -305,12 +305,7 @@ B32:
align 4 align 4
bios32_entry dd ? bios32_entry dd ?
tmp_page_tabs dd ? tmp_page_tabs dd ?
use16 use16
org $-0x10000
include "boot/shutdown.inc" ; shutdown or restart
org $+0x10000
ap_init16: ap_init16:
cli cli
lgdt [cs:gdts_ap-ap_init16] lgdt [cs:gdts_ap-ap_init16]
@ -5722,266 +5717,6 @@ undefined_syscall: ; Undefined system call
mov [esp + 32], dword -1 mov [esp + 32], dword -1
ret 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
if ~ defined extended_primary_loader
; load kernel.mnt to 0x7000:0
mov ebx, kernel_file_load
pushad
call file_system_lfn
popad
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0
mov edi, OS_BASE+0x40000
mov ecx, 1000
rep movsb
end if
; mov esi, BOOT_VAR ; restore 0x0 - 0xffff
; mov edi, OS_BASE
; mov ecx, 0x10000/4
; cld
; rep movsd
call IRQ_mask_all
cmp byte [OS_BASE + 0x9030], 2
jnz no_acpi_power_off
; scan for RSDP
; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA).
movzx eax, word [OS_BASE + 0x40E]
shl eax, 4
jz @f
mov ecx, 1024/16
call scan_rsdp
jnc .rsdp_found
@@:
; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh.
mov eax, 0xE0000
mov ecx, 0x2000
call scan_rsdp
jc no_acpi_power_off
.rsdp_found:
mov esi, [eax+16] ; esi contains physical address of the RSDT
mov ebp, [ipc_tmp]
stdcall map_page, ebp, esi, PG_READ
lea eax, [esi+1000h]
lea edx, [ebp+1000h]
stdcall map_page, edx, eax, PG_READ
and esi, 0xFFF
add esi, ebp
cmp dword [esi], 'RSDT'
jnz no_acpi_power_off
mov ecx, [esi+4]
sub ecx, 24h
jbe no_acpi_power_off
shr ecx, 2
add esi, 24h
.scan_fadt:
lodsd
mov ebx, eax
lea eax, [ebp+2000h]
stdcall map_page, eax, ebx, PG_READ
lea eax, [ebp+3000h]
add ebx, 0x1000
stdcall map_page, eax, ebx, PG_READ
and ebx, 0xFFF
lea ebx, [ebx+ebp+2000h]
cmp dword [ebx], 'FACP'
jz .fadt_found
loop .scan_fadt
jmp no_acpi_power_off
.fadt_found:
; ebx is linear address of FADT
mov edi, [ebx+40] ; physical address of the DSDT
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_READ
lea eax, [ebp+5000h]
lea esi, [edi+0x1000]
stdcall map_page, eax, esi, PG_READ
and esi, 0xFFF
sub edi, esi
cmp dword [esi+ebp+4000h], 'DSDT'
jnz no_acpi_power_off
mov eax, [esi+ebp+4004h] ; DSDT length
sub eax, 36+4
jbe no_acpi_power_off
add esi, 36
.scan_dsdt:
cmp dword [esi+ebp+4000h], '_S5_'
jnz .scan_dsdt_cont
cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode
jnz .scan_dsdt_cont
mov dl, [esi+ebp+4000h+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+ebp+4000h+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
cmp esi, 0x1000
jb @f
sub esi, 0x1000
add edi, 0x1000
push eax
lea eax, [ebp+4000h]
stdcall map_page, eax, edi, PG_READ
push PG_READ
lea eax, [edi+1000h]
push eax
lea eax, [ebp+5000h]
push eax
stdcall map_page
pop eax
@@:
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 $
scan_rsdp:
add eax, OS_BASE
.s:
cmp dword [eax], 'RSD '
jnz .n
cmp dword [eax+4], 'PTR '
jnz .n
xor edx, edx
xor esi, esi
@@:
add dl, [eax+esi]
inc esi
cmp esi, 20
jnz @b
test dl, dl
jz .ok
.n:
add eax, 10h
loop .s
stc
.ok:
ret
no_acpi_power_off:
call create_trampoline_pgmap
mov cr3, eax
jmp become_real+0x10000
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 1
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
if ~ lang eq sp if ~ lang eq sp
diff16 "end of .text segment",0,$ diff16 "end of .text segment",0,$

View File

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