[go: up one dir, main page]

Menu

[r19]: / htdocs / articles / fb.html  Maximize  Restore  History

Download this file

512 lines (427 with data), 14.6 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
<html>
<head>
<title>linuxassembly.org - Using the framebuffer device under Linux</title>
</head>
<body bgcolor="#ffffff" text="#000000">
<h1 align="center">Using the framebuffer device under Linux</h1>
<p align="center"><font size="-1">by <a href="mailto:linuxassembly@unusedino.de">Karsten Scheibler</a></font></p>
<dl><dt><b>Remark&nbsp;(a):</b></dt>
<dd>Save this page as <tt>fb.html</tt> and use the following command to extract the source code with a sample Makefile:<br>
<tt>sh&nbsp;-c&nbsp;&quot;( mkdir&nbsp;fb&nbsp;&amp;&amp; cd&nbsp;fb&nbsp;&amp;&amp; awk&nbsp;'/^&lt;!--eof/{d=0}{if(d)print&gt;f}/^&lt;!--sof/{f=\$2;d=1}' )&nbsp;&lt;&nbsp;fb.html&quot;</tt>
</dd><dt><b>Remark&nbsp;(b):</b></dt>
<dd>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 ;-)
</dd><dt><b>Remark&nbsp;(c):</b></dt>
<dd>Some versions of nasm are known to generate broken code.
I have used nasm-0.98 for this example which worked for me.
</dd>
</dl>
<p align="justify">This is a short explanation, how you can use
the linux framebuffer device in assembler language.
If you find mistakes or have suggestions, mail
<a href="mailto:linuxassembly@unusedino.de">me</a>.</p>
<dl><dt><b>Note:</b></dt>
<dd><p align="justify">Nearly all of the %assign's and struc's listed here can be found in the
kernel source in C syntax.</p></dd></dl>
<p>short procedure for using the fb device:<ol type="1">
<li>tell the kernel that we switch to graphics mode via <a href="#graphics"><b>KD_GRAPHICS</b></a></li>
<li><a href="#open">open</a> the device with <b>sys_open</b></li>
<li><a href="#parameters">determine screen parameters</a> via <b>sys_ioctl</b></li>
<li><a href="#mmap">map</a> the device to the memory of your process via <b>sys_mmap</b></li>
<li>use the pointer given back from mmap as base address of the framebuffer
and <a href="#draw">draw</a> what you like</li>
</ol></p>
<p align="justify">If you want to enable virtual terminal switching
in this example, look at the <a href="vt.html">vt</a> example code</p>
<p align="justify">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).</p>
<p align="justify">In this example we use <b>STDIN</b> as file
descriptor for <b>sys_ioctl</b>. 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 <b>/dev/tty</b>
and use that file descriptor instead.</p>
<p>Suggestions/Tips:<ul>
<li>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])</li>
<li>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).
<li>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</li>
<li>vga16fb isn't a real fb-device: <b>sys_mmap</b> only works for the first 65535 bytes
of the screen, you have still to switch between the bitplanes manually
(look at the <a href="modex.html">ModeX</a> example, how this can be done)</li>
<li>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
<b>/usr/src/linux/Documentation/fb/vesafb.txt</b>
of the kernel source for possible boot time parameters.</li>
<li>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 ;-)</li>
</ul>
<center><table><tr><td><pre>
<!--sof fb.n -->
;****************************************************************************
;****************************************************************************
;*
;* USING THE FRAMEBUFFER DEVICE UNDER LINUX
;*
;* written by Karsten Scheibler, 2003-DEC-08
;*
;****************************************************************************
;****************************************************************************
global fb_start
;look at the <a href="vt.html">vt</a> 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
;<a name="graphics"></a>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
;<a name="open"></a>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
;<a name="parameters"></a>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
;<a name="mmap"></a>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
;<a name="mainloop"></a>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
;<a name="draw"></a>****************************************************************************
;* 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
;*********************************************** linuxassembly@unusedino.de *
<!--eof-->
</pre></td></tr></table></center>
<!--sof Makefile
NASM=nasm -w+orphan-labels -w+macro-params -w+number-overflow -f elf
STRIP=strip -R .note -R .comment
LD=ld -s
RM=rm -f
.PHONY: all clean
all: fb fb-vt
fb: fb.n
${NASM} -o fb.o fb.n
${LD} -e fb_start -o fb fb.o
${STRIP} fb
fb-vt: fb.n
${NASM} -o fb-vt.o -i ../vt/ -DUSE_VT fb.n
${LD} -e fb_start -o fb-vt fb-vt.o
${STRIP} fb-vt
clean:
${RM} *.bak *~ fb fb.o fb-vt fb-vt.o core
<!--eof-->
</body>
</html>