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 ;; |
;; ;; |
;; Shutdown for Menuet ;; |
13,11 → 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 |
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 |
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 |
26,108 → 227,64 |
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, 0x3000 |
|
mov ax, (TMP_STACK_TOP and 0xF0000) shr 4 |
mov ss, ax |
mov esp, 0x0EC00 |
; setup ds |
push cs |
pop ds |
mov esp, TMP_STACK_TOP and 0xFFFF |
|
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 |
166,57 → 323,24 |
mov cx, 3 |
int 0x15 |
;!!!!!!!!!!!!!!!!!!!!!!!! |
ret |
jmp $ |
|
if ~ defined extended_primary_loader |
restart_kernel: |
.restart: |
|
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) |
; 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 |
224,5 → 348,10 |
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 |