kolibrios/kernel/trunk/boot/shutdown.inc
Sergey Semyonov (Serge) 50e97c60fa kernel: restart, reboot and power off
git-svn-id: svn://kolibrios.org@6244 a494cfbc-eb01-0410-851d-a64ba20cac60
2016-02-18 02:03:38 +00:00

358 lines
8.3 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Shutdown for Menuet ;;
;; ;;
;; Distributed under General Public License ;;
;; See file COPYING for details. ;;
;; Copyright 2003 Ville Turjanmaa ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
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
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
xor ax, ax
mov ds, ax
mov al, [0x9030]
cmp al, SYSTEM_RESTART
je .restart
cmp al, SYSTEM_SHUTDOWN
je .APM_PowerOff
mov word[0x0472], 0x1234
jmp 0xF000:0xFFF0
.APM_PowerOff:
mov ax, 5304h
xor bx, bx
int 15h
;!!!!!!!!!!!!!!!!!!!!!!!!
mov ax, 0x5300
xor bx, bx
int 0x15
push ax
mov ax, 0x5301
xor bx, bx
int 0x15
mov ax, 0x5308
mov bx, 1
mov cx, bx
int 0x15
mov ax, 0x530E
xor bx, bx
pop cx
int 0x15
mov ax, 0x530D
mov bx, 1
mov cx, bx
int 0x15
mov ax, 0x530F
mov bx, 1
mov cx, bx
int 0x15
mov ax, 0x5307
mov bx, 1
mov cx, 3
int 0x15
;!!!!!!!!!!!!!!!!!!!!!!!!
jmp $
.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
pop ds
mov si, kernel_restart_bootblock
mov ax, 'KL'
jmp 0x1000:0000
align 4
org restart_code_start + $
restart_code_end:
org $+OS_BASE
use32