From 50e97c60fac066a6d30196ea32d32b555fa26c75 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Thu, 18 Feb 2016 02:03:38 +0000 Subject: [PATCH] kernel: restart, reboot and power off git-svn-id: svn://kolibrios.org@6244 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/boot/shutdown.inc | 357 ++++++++++++++++++++++----------- kernel/trunk/const.inc | 10 +- kernel/trunk/data32.inc | 8 +- kernel/trunk/init.inc | 29 ++- kernel/trunk/kernel.asm | 267 +----------------------- kernel/trunk/kernel32.inc | 2 +- 6 files changed, 277 insertions(+), 396 deletions(-) diff --git a/kernel/trunk/boot/shutdown.inc b/kernel/trunk/boot/shutdown.inc index 0635549663..4ff52919c9 100644 --- a/kernel/trunk/boot/shutdown.inc +++ b/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 @@ 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, 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 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 @@ 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 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 +.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 @@ -224,5 +348,10 @@ restart_kernel_4000: 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 diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 407d15aa26..6d48a623cc 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -354,9 +354,13 @@ EVENT_EXTENDED equ 0x00000400 EV_INTR equ 1 -STDIN_FILENO equ 0 -STDOUT_FILENO equ 1 -STDERR_FILENO equ 2 +STDIN_FILENO equ 0 +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 ? diff --git a/kernel/trunk/data32.inc b/kernel/trunk/data32.inc index fb15c136e8..dfbdeb4b04 100644 --- a/kernel/trunk/data32.inc +++ b/kernel/trunk/data32.inc @@ -173,11 +173,11 @@ end if 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 @@ os_stack_seg rd 1 srv.fd rd 1 srv.bk rd 1 - align 16 _display display_t - LFBAddress dd ? SCR_MODE rw 2 diff --git a/kernel/trunk/init.inc b/kernel/trunk/init.inc index 3b9af4672c..5ef7adde24 100644 --- a/kernel/trunk/init.inc +++ b/kernel/trunk/init.inc @@ -455,7 +455,27 @@ ACPI_FADT_SIGN equ 0x50434146 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 @@ acpi_locate: 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 diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index e7ce3f9f04..a367a5b491 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -253,7 +253,7 @@ B32: 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 @@ 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,266 +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 - -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,$ diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index 6706827c8a..e2237403b3 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -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