Power management

If you ever though about how to use just software methods to turn off the hard drives or reboot your computer (without pressing any buttons), then this article should answer all your questions.



Hard drives.


(skip hard drives)

As a decent system, Linux won't let us operate directly on the hard drive. But it will let us do it by using the system call sys_ioctl.

Below you'll find a working (although to open the hard drive device file, you need root privileges) piece of code which stops the hard drive. I wrote this code thanks to analysing the hdparm program's source code (you'll find all the details there and on the manual pages: ioctl, ioctl_list). If you aren't using my library, change the constant names to their value given in the comments.

Here's the code (NASM syntax):


(skip code for stopping hard drives)
%include "bibl/incl/linuxbsd/nasm/n_system.inc"		; system constants

section .text

global _start

_start:
	mov	eax, sys_open			; =5. open the file....
	mov	ebx, dysk			; ....of the hard drive
	mov	ecx, O_RDONLY|O_NONBLOCK	; 04000q octal
	int	80h

	cmp	eax, 0
	jle	koniec				; if there's an error,
						; leave the program

	mov	ebx, eax		; save the file descriptor

	mov	eax, sys_ioctl			; =54
	; EBX = file descriptor
	mov	ecx, 0x031f			; drive special command
	mov	edx, args1			; first parameters
	int	80h

	mov	eax, sys_ioctl
	; EBX = file descriptor
	mov	ecx, 0x031f			; drive special command
	mov	edx, args2			; second parameters
	int	80h

	mov	eax, sys_close			; =6
	; EBX = file descriptor
	int	80h				; close the open file

koniec:
	mov	eax, sys_exit			; =1
	xor	ebx, ebx
	int	80h				; exit the program

section .data
args1	db	0e6h, 0, 0, 0			; copied from hdparm.c
args2	db	99h, 0, 0, 0			; also copied
dysk	db	"/dev/hda",0			; first drive,hdb = second

NOTE: you need to wait for while for the program to finish working. During the program running, your computer may stop responding.
After stopping the hard drive it can be started again by doing any file system operation (like displaying the current directory contents).


Rebooting the computer or switching it off.


(skip rebooting)

In order to reboot the computer, we're going to use the system function sys_reboot, giving it the right parameters. Here's a program which immediately reboots the computer:


(skip the reboot program)
%include "bibl/incl/linuxbsd/nasm/n_system.inc"

section .text

global _start

_start:
	mov	eax, sys_reboot			; =88
	mov	ebx, 0fee1deadh			; required constant
	mov	ecx, 672274793			; required constant
				; EDX = reboot mode. Here: normal reboot
	mov	edx, LINUX_REBOOT_CMD_RESTART	; =0x01234567
	int	80h

	; what's below will never be executed
	mov	eax, sys_exit			; =1
	xor	ebx, ebx
	int	80h

Here's a program which immediately switches off the computer:


(skip the poweroff program)
%include "bibl/incl/linuxbsd/nasm/n_system.inc"

section .text

global _start

_start:
	mov	eax, sys_reboot			; =88
	mov	ebx, 0fee1deadh			; required constant
	mov	ecx, 672274793			; required constant
			; EDX = reboot mode. Here: poweroff
	mov	edx, LINUX_REBOOT_CMD_POWER_OFF	; =0x4321FEDC
	int	80h

	; what's below will never be executed
	mov	eax, sys_exit			; =1
	xor	ebx, ebx
	int	80h

NOTE: because of the fact, that the given programs switch off or reboot the machine right after launching them, I do NOT recommend using them, as this may be bad for the file system.



Turning the monitor off.

Well, maybe this won't be exactly turning off, but in any case, the displayed picture will be gone. To do this, we're going to use to svgalib library (to compile the program, a svgalib-devel package will probably be necessary).

Everything is very simple: initialize the library using the vga_init function, turn the picture off using the vga_screenoff function, wait for a key being pressed (system function sys_read reading from the standard input) and bring the picture back using vga_screenon. The vga functions do not need any parameters.

The program looks like this:


(skip monitor switching off code)
; Program uses SVGAlib to switc off the monitor
;
; Author: Bogdan D., bogdandr (at) op.pl
; compile:
;   nasm -O999 -f elf -o mon_off.o mon_off.asm
;   gcc -o mon_off mon_off.o -lvga

section .text
global	main

extern	vga_screenoff
extern	vga_screenon
extern	vga_init

%idefine	stdin		0
%idefine	sys_read	3

main:
	call	vga_init
	call	vga_screenoff

	mov	eax, sys_read	; read-from-file function
	mov	ebx, stdin	; standard input
	mov	ecx, znak	; address of where to put the data
	mov	edx, 1		; read 1 byte
	int	80h

	call	vga_screenon

	ret

section .data

znak		db	0

Notice the compiling method. Since we're using C language libraries, we'll use GCC for compiling. Then, our entry function must be called main - just like in C language programs (and just like in C programs, we can end it with a RET). The needed functions are simply declared external (extern).

I ran this program under a graphical environment (X11). Nothing bad happened, but after the program was finished, I had to go to the text console (Ctrl+Alt+F1) and then go back to the graphic interface to bring the picture back.

To work under X, this program may need access to the /dev/console file, under the text console - to /dev/mem.


On-line contents (Alt+2)
Helpers for people with disabilities (Alt+0)