/kernel/trunk/boot/shutdown.inc |
---|
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 |
/kernel/trunk/const.inc |
---|
358,6 → 358,10 |
STDOUT_FILENO equ 1 |
STDERR_FILENO equ 2 |
SYSTEM_SHUTDOWN equ 2 |
SYSTEM_REBOOT equ 3 |
SYSTEM_RESTART equ 4 |
struct SYSCALL_STACK |
_eip dd ? |
_edi dd ? ; +4 |
/kernel/trunk/data32.inc |
---|
173,11 → 173,11 |
vmode db '/sys/drivers/VMODE.MDR',0 |
;vrr_m db 'VRR_M',0 |
kernel_file_load: |
; load kernel.mnt to 0x7000:0 |
; load kernel.mnt to _CLEAN_ZONE |
dd 0 ; subfunction |
dq 0 ; offset in file |
dd 0x30000 ; number of bytes to read |
dd OS_BASE + 0x71000 ; buffer for data |
dd 0x31000 ; number of bytes to read |
dd _CLEAN_ZONE ; buffer for data |
db '/RD/1/KERNEL.MNT',0 |
dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0 |
371,12 → 371,10 |
srv.fd rd 1 |
srv.bk rd 1 |
align 16 |
_display display_t |
LFBAddress dd ? |
SCR_MODE rw 2 |
/kernel/trunk/init.inc |
---|
455,7 → 455,27 |
acpi_locate: |
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 edi, ACPI_HI_RSDP_WINDOW_END |
call .check |
.done: |
mov eax, ebx |
pop edi |
pop ebx |
ret |
.check: |
cmp [ebx], dword 0x20445352 |
jne .next |
472,17 → 492,12 |
test al, al |
jnz .next |
mov eax, ebx |
pop ebx |
ret |
.next: |
add ebx, 16 |
cmp ebx, ACPI_HI_RSDP_WINDOW_END |
cmp ebx, edi |
jb .check |
pop ebx |
xor eax, eax |
xor ebx, ebx |
ret |
align 4 |
/kernel/trunk/kernel.asm |
---|
253,7 → 253,7 |
mov fs, ax |
mov gs, ax |
mov ss, ax |
mov esp, 0x006CC00 ; Set stack |
mov esp, TMP_STACK_TOP ; Set stack |
; CLEAR 0x280000 - HEAP_BASE |
305,12 → 305,7 |
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,267 → 5717,7 |
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 |
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 |
diff16 "end of .text segment",0,$ |
end if |
/kernel/trunk/kernel32.inc |
---|
42,7 → 42,7 |
include "gui/font.inc" |
include "gui/button.inc" |
; shutdown |
include "boot/shutdown.inc" ; kernel shutdown |
; file system |