Statistics

Members: 1925
News: 292
Web Links: 1
Visitors: 3731898

Who's Online

Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow Submit Your Paper!
Using the framebuffer device under Linux
User Rating: / 0
PoorBest 
Written by Karsten Scheibler   


This is a short explanation, how you can use the linux framebuffer device in assembler language.
Remark (a):
Save this page as fb.html and use the following command to extract the source code with a sample Makefile:
sh -c "( mkdir fb && cd fb && awk '/^<!--eof/{d=0}{if(d)print>f}/^<!--sof/{f=\$2;d=1}' ) < fb.html"
Remark (b):
Some browsers try to be super smart and reformat the html code so you may have trouble to extract the files. This is the right time to learn more about wget, a tool to download files via http or ftp ;-)
Remark (c):
Some versions of nasm are known to generate broken code. I have used nasm-0.98 for this example which worked for me.

This is a short explanation, how you can use the linux framebuffer device in assembler language. If you find mistakes or have suggestions, mail This e-mail address is being protected from spam bots, you need JavaScript enabled to view it .

Note:

Nearly all of the %assign's and struc's listed here can be found in the kernel source in C syntax.

short procedure for using the fb device:

  1. tell the kernel that we switch to graphics mode via KD_GRAPHICS
  2. open the device with sys_open
  3. determine screen parameters via sys_ioctl
  4. map the device to the memory of your process via sys_mmap
  5. use the pointer given back from mmap as base address of the framebuffer and draw what you like

If you want to enable virtual terminal switching in this example, look at the vt example code

If you use color depths less or equal than 8 bpp you have to set a color palette in order to see that what you draw (default: first 16 colors are set to the normal terminal ANSI colors, the rest should be black). Linux uses 16 bit for every color component (red, green, blue, transparent).

In this example we use STDIN as file descriptor for sys_ioctl. This is ok as long as nobody redirects it to a file or pipe. If you want that the program even works in this cases: open /dev/tty and use that file descriptor instead.

Suggestions/Tips:

  • don't assume fixed screen geometries (never trust only the physical screen resolution, you should also examine the virtual screen resolution, or you will see strange effects, if the virtual line length [virtual_x_resolution] is larger than the physical [x_resolution])
  • if you have a large virtual_y_resolution always set x_offset and y_offset to zero for your settings and also when restoring the old video mode (some fb-drivers [for example matroxfb] uses large virtual_y_resolution to speed up console scrolling).
  • if you use vesafb you are not able to change color depth or resolution. if you run this example code with greater than 8bpp it won't work, because switching to 8bpp fails
  • vga16fb isn't a real fb-device: sys_mmap only works for the first 65535 bytes of the screen, you have still to switch between the bitplanes manually (look at the ModeX example, how this can be done)
  • vesafb supports only a subset of all fb device operations i.e. you can't change the resolution or color depth after boot. If you boot with a color depth other than 8 bpp the example code shown here won't work. Consult /usr/src/linux/Documentation/fb/vesafb.txt of the kernel source for possible boot time parameters.
  • before drawing something to screen, you should check if your program was called from local console. If you do not, you get funny effects: assume your program was started from a xterm, or from a remote connection ;-)

;****************************************************************************
;****************************************************************************
;*
;* USING THE FRAMEBUFFER DEVICE UNDER LINUX
;*
;* written by Karsten Scheibler, 2003-DEC-08
;*
;****************************************************************************
;****************************************************************************
global fb_start
;look at the vt example code for more
%ifdef USE_VT
%include "vt.n"
%endif ;USE_VT
;****************************************************************************
;* some assign's
;****************************************************************************
%assign SYS_READ			3
%assign SYS_OPEN			5
%assign SYS_IOCTL			54
%assign SYS_MMAP			90
%assign PROT_READ			1
%assign PROT_WRITE			2
%assign MAP_SHARED			1
%assign STDIN				0
%assign STDERR				2
%assign O_RDWR				2
%assign FBIOGET_VSCREENINFO		0x00004600
%assign FBIOPUT_VSCREENINFO		0x00004601
%assign FBIOGETCMAP			0x00004604
%assign FBIOPUTCMAP			0x00004605
%assign KDSETMODE			0x00004b3a
%assign KDGETMODE			0x00004b3b
%assign KD_TEXT				0
%assign KD_GRAPHICS			1
struc	tcmap
alignb	4
tcmap_offset:				resd	1
tcmap_length:				resd	1
tcmap_red:				resd	1
tcmap_green:				resd	1
tcmap_blue:				resd	1
tcmap_transparent:			resd	1
endstruc
struc	tscreen
alignb	4
tscreen_x_resolution:			resd	1
tscreen_y_resolution:			resd	1
tscreen_virtual_x_resolution:		resd	1
tscreen_virtual_y_resolution:		resd	1
tscreen_x_offset:			resd	1
tscreen_y_offset:			resd	1
tscreen_bits_per_pixel:			resd	1
tscreen_grayscale:			resd	1
tscreen_red_offset:			resd	1
tscreen_red_length:			resd	1
tscreen_red_msb_right:			resd	1
tscreen_green_offset:			resd	1
tscreen_green_length:			resd	1
tscreen_green_msb_right:		resd	1
tscreen_blue_offset:			resd	1
tscreen_blue_length:			resd	1
tscreen_blue_msb_right:			resd	1
tscreen_transparent_offset:		resd	1
tscreen_transparent_length:		resd	1
tscreen_transparent_msb_right:		resd	1
tscreen_non_standard_format:		resd	1
tscreen_activate:			resd	1
tscreen_height:				resd	1
tscreen_width:				resd	1
tscreen_acceleration_flags:		resd	1
tscreen_pixel_clock:			resd	1
tscreen_left_margin:			resd	1
tscreen_right_margin:			resd	1
tscreen_upper_margin:			resd	1
tscreen_lower_margin:			resd	1
tscreen_hsync_length:			resd	1
tscreen_vsync_length:			resd	1
tscreen_sync:				resd	1
tscreen_vmode:				resd	1
tscreen_reserved:			resd	6
endstruc
%assign FB_KDMODE_SAVED			0x00000001
%assign FB_SCREENINFO_SAVED		0x00000002
%assign FB_COLORMAP_SAVED		0x00000004
;****************************************************************************
;* data
;****************************************************************************
section .data
align	4
fb_state:				dd	0
fb_handle:				dd	0
fb_address:				dd	0
fb_kdmode:				dd	0
colormap_saved:				istruc tcmap
at tcmap_offset,	dd 0
at tcmap_length,	dd 256
at tcmap_red,		dd red_saved
at tcmap_green,		dd green_saved
at tcmap_blue,		dd blue_saved
at tcmap_transparent,	dd transparent_saved
iend
colormap_data:				istruc tcmap
at tcmap_offset,	dd 0
at tcmap_length,	dd 256
at tcmap_red,		dd grey_scale
at tcmap_green,		dd grey_scale
at tcmap_blue,		dd grey_scale
at tcmap_transparent,	dd transparent_saved
iend
section .bss
alignb	4
screeninfo_saved:			resb	tscreen_size
screeninfo_data:			resb	tscreen_size
grey_scale:				resw	256
red_saved:				resw	256
green_saved:				resw	256
blue_saved:				resw	256
transparent_saved:			resw	256
;****************************************************************************
;* fb_start
;****************************************************************************
section .text
fb_start:
mov	dword eax, SYS_IOCTL
mov	dword ebx, STDIN
mov	dword ecx, KDGETMODE
mov	dword edx, fb_kdmode
int	byte  0x80
test	dword eax, eax
js	near  fb_error
or	dword [fb_state], FB_KDMODE_SAVED
;tell kernel that we switch to graphics mode.
;this means the kernel won't do things that may change the video ram
;(vt switching, vt blanking, cursor, mouse cursor [gpm])
mov	dword eax, SYS_IOCTL
mov	dword ebx, STDIN
mov	dword ecx, KDSETMODE
mov	dword edx, KD_GRAPHICS
int	byte  0x80
test	dword eax, eax
js	near  fb_error
;open
mov	dword eax, SYS_OPEN
mov	dword ebx, .device
mov	dword ecx, O_RDWR
int	byte  0x80
test	dword eax, eax
js	near  fb_error
mov	dword [fb_handle], eax
;get screen parameters
mov	dword ebx, eax
mov	dword eax, SYS_IOCTL
mov	dword ecx, FBIOGET_VSCREENINFO
mov	dword edx, screeninfo_saved
int	byte  0x80
test	dword eax, eax
js	near  fb_error
xor	dword eax, eax
mov	dword [screeninfo_saved + tscreen_x_offset], eax
mov	dword [screeninfo_saved + tscreen_y_offset], eax
mov	dword esi, screeninfo_saved
mov	dword edi, screeninfo_data
mov	dword ecx, (tscreen_size / 4)
cld
rep movsd
or	dword  [fb_state], FB_SCREENINFO_SAVED
;get current colormap
mov	dword eax, SYS_IOCTL
mov	dword ebx, [fb_handle]
mov	dword ecx, FBIOGETCMAP
mov	dword edx, colormap_saved
int	byte  0x80
test	dword eax, eax
js	short .no_colormap_saved
or	dword [fb_state], FB_COLORMAP_SAVED
.no_colormap_saved:
;set screen parameters
mov	dword eax, [screeninfo_data + tscreen_x_resolution]
mov	dword ebx, [screeninfo_data + tscreen_y_resolution]
mov	dword ecx, 8
mov	dword [screeninfo_data + tscreen_virtual_x_resolution], eax
mov	dword [screeninfo_data + tscreen_virtual_y_resolution], ebx
mov	dword [screeninfo_data + tscreen_bits_per_pixel], ecx
mov	dword eax, SYS_IOCTL
mov	dword ebx, [fb_handle]
mov	dword ecx, FBIOPUT_VSCREENINFO
mov	dword edx, screeninfo_data
int	byte  0x80
test	dword eax, eax
js	near  fb_error
cmp	dword [screeninfo_data + tscreen_bits_per_pixel], 8
jne	near  fb_error
;set colormap
mov	dword eax, 0x01000000
xor	dword ebx, ebx
.set_grey:
mov	dword [grey_scale + 4 * ebx], eax
add	dword eax, 0x02000200
inc	dword ebx
cmp	dword ebx, byte 127
jbe	short .set_grey
mov	dword eax, SYS_IOCTL
mov	dword ebx, [fb_handle]
mov	dword ecx, FBIOPUTCMAP
mov	dword edx, colormap_data
int	byte  0x80
;mmap
mov	dword eax, [screeninfo_data + tscreen_y_resolution]
mul	dword [screeninfo_data + tscreen_virtual_x_resolution]
xor	dword ebx, ebx
push	dword ebx
push	dword [fb_handle]
push	dword MAP_SHARED
push	dword (PROT_READ | PROT_WRITE)
push	dword eax
push	dword ebx
mov	dword eax, SYS_MMAP
mov	dword ebx, esp
int	byte  0x80
add	dword esp, byte 24
test	dword eax, eax
jz	near  fb_error
mov	dword [fb_address], eax
;"press enter to exit" ...
%ifndef USE_VT
call	near  fb_draw
push	dword eax
mov	dword eax, SYS_READ
mov	dword ebx, STDIN
mov	dword ecx, esp
mov	dword edx, 1
int	byte  0x80
add	dword esp, byte 4
jmp	near  fb_end
%else ;USE_VT
mov	dword eax, fb_end
mov	dword ebx, fb_error
call	near  vt_init
;mainloop
.loop:
call	near  fb_draw
.keypress1:
call	near  vt_check_keypress
cmp	dword eax, byte 1
je	near  fb_end
call	near  vt_check_release
test	dword eax, eax
js	short .keypress1
call	near  vt_commit_release
test	dword eax, eax
js	short .keypress1
.keypress2:
call	near  vt_check_keypress	;vt is not active => no keypress
;possible, we simply use select to
;wait here
call	near  vt_check_acquire
test	dword eax, eax
js	short .keypress2
jmp	short .loop
%endif ;USE_VT
.device:				db	"/dev/fb0", 0
;****************************************************************************
;* fb_draw
;****************************************************************************
section .text
fb_draw:
mov	dword edi, [fb_address]
mov	dword ebp, [screeninfo_data + tscreen_virtual_x_resolution]
sub	dword ebp, [screeninfo_data + tscreen_x_resolution]
mov	dword ebx, [screeninfo_data + tscreen_y_resolution]
.draw_line:
mov	dword eax, ebx
mov	dword ecx, [screeninfo_data + tscreen_x_resolution]
.draw_pixel:
stosb
inc	dword eax
dec	dword ecx
jnz	short .draw_pixel
add	dword edi, ebp
dec	dword ebx
jnz	short .draw_line
ret
;****************************************************************************
;* fb_restore
;****************************************************************************
section .text
fb_restore:
test	dword [fb_state], FB_SCREENINFO_SAVED
jz	short .skip_screeninfo
mov	dword eax, SYS_IOCTL
mov	dword ebx, [fb_handle]
mov	dword ecx, FBIOPUT_VSCREENINFO
mov	dword edx, screeninfo_saved
int	byte  0x80
.skip_screeninfo:
test	dword [fb_state], FB_COLORMAP_SAVED
jz	short .skip_colormap
mov	dword eax, SYS_IOCTL
mov	dword ebx, [fb_handle]
mov	dword ecx, FBIOPUTCMAP
mov	dword edx, colormap_saved
int	byte  0x80
.skip_colormap:
test	dword [fb_state], FB_KDMODE_SAVED
jz	short .skip_kdmode
mov	dword eax, SYS_IOCTL
mov	dword ebx, STDIN
mov	dword ecx, KDSETMODE
mov	dword edx, [fb_kdmode]
int	byte  0x80
.skip_kdmode:
ret
;****************************************************************************
;* fb_error
;****************************************************************************
section .text
fb_error:
call	near  fb_restore
xor	dword eax, eax
inc	dword eax
mov	dword ebx, eax
int	byte  0x80
;****************************************************************************
;* fb_end
;****************************************************************************
section .text
fb_end:
call	near  fb_restore
xor	dword eax, eax
xor	dword ebx, ebx
inc	dword eax
int	byte  0x80
;*********************************************** 
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
  *