Grafik & Görüntü
TEKNİK REHBER GRAFİK & GÖRÜNTÜ FRAMEBUFFER / FBDEV 2026

Linux Framebuffer —
/dev/fb0.

Doğrudan piksel yazımından boot splash screen'e, Python ile video playback'ten DRM/KMS migration yoluna kadar Linux framebuffer alt sisteminin eksiksiz rehberi.

00 fbdev nedir

Linux framebuffer (fbdev), kullanıcı alanının doğrudan ekran belleğine yazmasına olanak tanıyan eski bir kernel sürücüsüdür. GPU hızlandırması olmadan, CPU piksel verisini doğrudan gönderir.

Tarihsel bağlam

fbdev (1995+)
Kernel'ın ilk birleşik display API'si. X11 sunucuları, konsol ve oyun motorları tarafından kullanıldı. /dev/fb0 karakter cihazı üzerinden erişilir.
DRM/KMS (2008+)
Modern GPU yönetimi: mode setting, buffer yönetimi, GPU render. Fbdev'in yerini almaktadır. Ancak basit embedded ekranlar için fbdev hala kullanılır.
simpledrm (2021+)
Linux 5.14+ ile fbdev sürücülerinin yerini alan DRM sürücüsü. Aynı donanımda modern API sunar. DRM_FBDEV_EMULATION ile geriye uyumluluk sağlar.

Hangi durumlarda fbdev?

  Basit, statik display (logo, status bar)?
       ├─ Evet  → fbdev yeterli
       └─ Hayır
            ↓
  GPU hızlandırma gerekli?
       ├─ Evet  → DRM/KMS + libdrm veya Qt/LVGL
       └─ Hayır → fbdev veya simpledrm
    

Kernel konfigürasyonu

Kconfig
CONFIG_FB=y
CONFIG_FB_VESA=y              # x86 VESA framebuffer
CONFIG_FB_EFI=y               # UEFI GOP framebuffer
CONFIG_FB_BCM2708=y           # Raspberry Pi legacy fbdev
CONFIG_FRAMEBUFFER_CONSOLE=y  # fbcon: kernel konsolu
CONFIG_LOGO=y                 # boot logo (penguen)

01 ioctl API — fb_var_screeninfo, fb_fix_screeninfo

/dev/fb0 açıldıktan sonra ioctl çağrıları ile ekranın özelliklerini sorgulayabilir ve bazılarını değiştirebilirsin.

fb_var_screeninfo — değiştirilebilir özellikler

xres / yres
Aktif çözünürlük (piksel). xres_virtual/yres_virtual double buffering için sanal çözünürlük.
bits_per_pixel
Piksel başına bit: 16 (RGB565), 24 (RGB888), 32 (ARGB8888).
xoffset / yoffset
Sanal ekranda görüntüleme ofseti. Double buffering için yoffset değiştirilir.
red/green/blue/transp
Her renk kanalının bit ofseti ve uzunluğu. Piksel formatını tanımlar.

fb_fix_screeninfo — sabit özellikler

smem_start
Framebuffer fiziksel adresi (belgeleme amaçlı; mmap için kullanma).
smem_len
Toplam framebuffer bellek boyutu (byte).
line_length
Bir satırın byte cinsinden uzunluğu (stride/pitch). Her zaman xres * bytes_per_pixel'e eşit değildir; hizalama padding olabilir.

ioctl örneği

C — fb bilgisi okuma
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>

int main(void)
{
    int fd = open("/dev/fb0", O_RDWR);
    if (fd < 0) { perror("/dev/fb0"); return 1; }

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;

    ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

    printf("Çözünürlük   : %dx%d\n",
        vinfo.xres, vinfo.yres);
    printf("Bit/piksel   : %d bpp\n",
        vinfo.bits_per_pixel);
    printf("Satır uzunluğu: %d byte\n",
        finfo.line_length);
    printf("FB bellek    : %d KB\n",
        finfo.smem_len / 1024);
    printf("Kırmızı      : ofset=%d, uzunluk=%d\n",
        vinfo.red.offset, vinfo.red.length);
    printf("Yeşil        : ofset=%d, uzunluk=%d\n",
        vinfo.green.offset, vinfo.green.length);
    printf("Mavi         : ofset=%d, uzunluk=%d\n",
        vinfo.blue.offset, vinfo.blue.length);

    close(fd);
    return 0;
}

02 mmap ile piksel yazma

Framebuffer'a en verimli erişim mmap() ile sağlanır. Kernel belleğini kullanıcı alanına eşler; memcpy gibi standart bellek işlemleri ile piksel yazılır.

Piksel adresi hesabı

Formül
offset = y * line_length + x * bytes_per_pixel

/* bytes_per_pixel = bits_per_pixel / 8 */
/* line_length ≥ xres * bytes_per_pixel  (padding olabilir!) */

RGB565 piksel yazma — tam örnek

C — RGB565 framebuffer
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdint.h>

/* RGB888 → RGB565 dönüşümü */
static inline uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b) {
    return ((r & 0xF8) << 8) |
           ((g & 0xFC) << 3) |
           ((b & 0xF8) >> 3);
}

int main(void)
{
    int fd = open("/dev/fb0", O_RDWR);

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

    int width  = vinfo.xres;
    int height = vinfo.yres;
    int bpp    = vinfo.bits_per_pixel / 8;  /* byte/piksel */
    long fb_size = finfo.line_length * height;

    uint8_t *fb = mmap(NULL, fb_size,
        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    /* Gradyan çiz */
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint16_t color = rgb565(
                x * 255 / width,           /* kırmızı: soldan sağa */
                y * 255 / height,          /* yeşil: yukarıdan aşağı */
                128                         /* mavi: sabit */
            );
            /* piksel adresine yaz */
            long offset = y * finfo.line_length + x * bpp;
            *(uint16_t *)(fb + offset) = color;
        }
    }

    sleep(3);
    munmap(fb, fb_size);
    close(fd);
    return 0;
}

ARGB8888 — 32-bit piksel

C — ARGB8888
/* 32-bit piksel: A=31:24, R=23:16, G=15:8, B=7:0 */
uint32_t *pixels32 = (uint32_t *)fb;

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        /* line_length/4 kullan (uint32 adreslemesi) */
        pixels32[y * (finfo.line_length / 4) + x] =
            0xFF000000 |           /* A = opak */
            ((x * 255 / width)  << 16) |  /* R */
            ((y * 255 / height) << 8)  |  /* G */
            0x80;                          /* B */
    }
}

03 Double buffering — FBIOPAN_DISPLAY, vsync

Tek buffer'a yazıp göstermek tearing'e yol açar. Double buffering ile bir buffer görüntülenirken diğerine yazılır; VBlank anında tamponlar değiştirilir.

Sanal çözünürlük ile double buffer

C — double buffering
#include <linux/fb.h>

struct fb_var_screeninfo vinfo;
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);

/* Dikey sanal çözünürlüğü 2x yap */
vinfo.yres_virtual = vinfo.yres * 2;
ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo);

long fb_size = finfo.line_length * vinfo.yres_virtual;
uint8_t *fb = mmap(NULL, fb_size,
    PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);

/* Buffer 0: fb[0 ... line_length*yres-1]          */
/* Buffer 1: fb[line_length*yres ... fb_size-1]     */

int current_buf = 0;

while (rendering) {
    int next_buf = 1 - current_buf;
    uint8_t *draw_fb = fb + next_buf * finfo.line_length * vinfo.yres;

    /* next_buf'a çiz */
    render_frame(draw_fb);

    /* VBlank'i bekle ve tamponları değiştir */
    vinfo.yoffset = next_buf * vinfo.yres;
    ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo);

    /* Opsiyonel: FBIO_WAITFORVSYNC ile VBlank senkronizasyonu */
    int zero = 0;
    ioctl(fb_fd, FBIO_WAITFORVSYNC, &zero);

    current_buf = next_buf;
}
FBIO_WAITFORVSYNC

FBIO_WAITFORVSYNC ioctl'i tüm sürücülerde desteklenmeyebilir. Raspberry Pi'nin legacy fbdev sürücüsünde çalışır. Desteklenmiyorsa EINVAL veya ENOIOCTLCMD döner. Modern sistemlerde DRM/KMS atomic commit ile page flip eventi tercih edilir.

04 fbset — timing değiştirme, custom modeline

fbset aracı, framebuffer sürücüsünün timing parametrelerini kullanıcı alanından değiştirmek için kullanılır.

fbset kullanımı

bash
# Mevcut mod bilgisi
fbset -i

# Belirli bir çözünürlük ayarla
fbset -xres 1280 -yres 720 -depth 32

# Refresh rate değiştir
fbset -a 1024x768-75   # /etc/fb.modes'dan

# Özel modeline
fbset \
    -xres 800 -yres 480 \
    -vxres 800 -vyres 960 \
    -depth 16 \
    -left 40 -right 40 -upper 29 -lower 13 \
    -hslen 48 -vslen 3 \
    -pixclock 33333 \
    -sync 0 -vmode 0

# Desteklenen tüm modları listele
cat /etc/fb.modes

/etc/fb.modes — mod veritabanı

/etc/fb.modes — custom mod
mode "800x480-60"
    geometry 800 480 800 960 16
    timings 33333 40 40 29 13 48 3
    rgba 5/11,6/5,5/0,0/0
endmode

mode "1024x600-60"
    geometry 1024 600 1024 1200 16
    timings 15385 140 160 20 12 20 3
    rgba 5/11,6/5,5/0,0/0
endmode
pixel clock hesabı

Timings değerindeki ilk sayı piksel saati periyodu (pikosaniye). Hesap: pixclock = 1e12 / (Hz * htotal * vtotal). 800x480@60Hz için htotal≈888, vtotal≈525: pixclock = 1e12 / (60 * 888 * 525) ≈ 35818.

05 Splash screen — Plymouth, psplash, BMP decode

Boot splash screen, kullanıcıya sistem hazırlanırken görsel geri bildirim sağlar. Systemd öncesinde fbdev üzerinden gösterilir.

Plymouth — systemd entegreli splash

bash — Plymouth kurulumu
# Yocto'da plymouth
IMAGE_INSTALL:append = " plymouth plymouth-script"

# Tema seçimi
plymouth-set-default-theme -R bgrt  # ya da "spinner", "solar"

# Özel tema
mkdir -p /usr/share/plymouth/themes/my-brand/
cat > /usr/share/plymouth/themes/my-brand/my-brand.plymouth << 'EOF'
[Plymouth Theme]
Name=My Brand
Description=Custom splash
ModuleName=script

[script]
ImageDir=/usr/share/plymouth/themes/my-brand
ScriptFile=/usr/share/plymouth/themes/my-brand/my-brand.script
EOF

psplash — Yocto için minimal splash

bash — psplash Yocto
# local.conf
IMAGE_INSTALL:append = " psplash"

# Özel logo: 40x40 piksel PNG, RGBA
# psplash-poky-img.h formatına dönüştür
gdk-pixbuf-csource --name=psplash_poky_img \
    my_logo.png > psplash-poky-img.h

# psplash kernel cmdline parametresi
# APPEND += " psplash=true"

# İlerleme çubuğu rengi (yüzde 0-100)
psplash-write "PROGRESS 50"
psplash-write "MSG Sistem başlatılıyor..."

C ile BMP decode → framebuffer

C — BMP yükle ve fb'ye yaz
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#pragma pack(1)
typedef struct {
    uint16_t type;        /* "BM" = 0x4D42 */
    uint32_t size;
    uint16_t reserved1, reserved2;
    uint32_t offset;      /* piksel verisi başlangıcı */
    uint32_t hdr_size;
    int32_t  width, height;
    uint16_t planes, bpp; /* 24 veya 32 */
    uint32_t compression;
    uint32_t img_size;
    int32_t  xppm, yppm;
    uint32_t clr_used, clr_important;
} BmpHeader;
#pragma pack()

void bmp_to_fb(const char *bmp_path, uint8_t *fb,
               int fb_width, int line_length, int fb_bpp)
{
    FILE *f = fopen(bmp_path, "rb");
    BmpHeader hdr;
    fread(&hdr, sizeof(hdr), 1, f);

    /* BMP'de satırlar alt-üst sırada, hizalama 4-byte */
    int bmp_bpp  = hdr.bpp / 8;
    int row_size = ((hdr.width * bmp_bpp + 3) / 4) * 4;
    uint8_t *row = malloc(row_size);

    for (int y = 0; y < hdr.height; y++) {
        /* BMP: en alt satır önce */
        int fb_y = hdr.height - 1 - y;
        fseek(f, hdr.offset + y * row_size, SEEK_SET);
        fread(row, 1, row_size, f);

        for (int x = 0; x < hdr.width && x < fb_width; x++) {
            /* BMP: BGR sırası */
            uint8_t b = row[x * bmp_bpp + 0];
            uint8_t g = row[x * bmp_bpp + 1];
            uint8_t r = row[x * bmp_bpp + 2];

            if (fb_bpp == 2) {
                /* RGB565 */
                uint16_t px = ((r & 0xF8) << 8) |
                              ((g & 0xFC) << 3) |
                              ((b) >> 3);
                *(uint16_t *)(fb + fb_y * line_length + x * 2) = px;
            } else {
                /* ARGB8888 */
                uint32_t px = 0xFF000000 | (r << 16) | (g << 8) | b;
                *(uint32_t *)(fb + fb_y * line_length + x * 4) = px;
            }
        }
    }
    free(row);
    fclose(f);
}

06 Python ile framebuffer — Pillow, numpy, video playback

Python'dan framebuffer erişimi hızlı prototipleme için kullanışlıdır. Pillow ile resim yükle, numpy ile piksel manipülasyonu yap, mmap ile direkt yaz.

Temel Python framebuffer yazımı

Python — /dev/fb0 yazma
import mmap
import struct
import fcntl
import ctypes

# fb_var_screeninfo ioctl yapısı (kısaltılmış)
FBIOGET_VSCREENINFO = 0x4600
FBIOGET_FSCREENINFO = 0x4602

with open('/dev/fb0', 'r+b') as fb:
    # Ekran bilgisini al (ilk 8 uint32: xres, yres, xvres, yvres,
    #                     xoffset, yoffset, bpp, grayscale)
    vinfo_buf = bytearray(160)
    fcntl.ioctl(fb, FBIOGET_VSCREENINFO, vinfo_buf)
    xres, yres, _, _, _, _, bpp = struct.unpack_from('7I', vinfo_buf)

    finfo_buf = bytearray(68)
    fcntl.ioctl(fb, FBIOGET_FSCREENINFO, finfo_buf)
    line_length = struct.unpack_from('I', finfo_buf, 16)[0]

    fb_size = line_length * yres
    fb_mem  = mmap.mmap(fb.fileno(), fb_size,
                        mmap.MAP_SHARED,
                        mmap.PROT_READ | mmap.PROT_WRITE)

    # Kırmızı ekran (RGB565: R=0b11111, G=0, B=0 → 0xF800)
    fb_mem.seek(0)
    fb_mem.write(b'\x00\xF8' * (fb_size // 2))

Pillow + numpy ile resim gösterme

Python — Pillow → fb0
from PIL import Image
import numpy as np
import mmap, fcntl, struct

def show_image(img_path, fb_path='/dev/fb0'):
    with open(fb_path, 'r+b') as fb:
        # Ekran bilgisi (xres, yres, bpp al)
        vinfo = bytearray(160)
        fcntl.ioctl(fb, 0x4600, vinfo)
        xres, yres, _, _, _, _, bpp = struct.unpack_from('7I', vinfo)

        finfo = bytearray(68)
        fcntl.ioctl(fb, 0x4602, finfo)
        line_length = struct.unpack_from('I', finfo, 16)[0]

        img = Image.open(img_path).convert('RGB')
        img = img.resize((xres, yres), Image.LANCZOS)
        arr = np.array(img, dtype=np.uint8)

        if bpp == 16:
            # RGB888 → RGB565
            r = (arr[:, :, 0] >> 3).astype(np.uint16)
            g = (arr[:, :, 1] >> 2).astype(np.uint16)
            b = (arr[:, :, 2] >> 3).astype(np.uint16)
            pixels = ((r << 11) | (g << 5) | b).astype(np.uint16)
        else:
            # ARGB8888
            a = np.full((yres, xres), 255, dtype=np.uint8)
            pixels = np.stack([arr[:,:,2], arr[:,:,1],
                                arr[:,:,0], a], axis=2)

        fb_mem = mmap.mmap(fb.fileno(), line_length * yres)
        fb_mem.seek(0)
        fb_mem.write(pixels.tobytes()[:line_length * yres])

show_image('/tmp/splash.png')

Video playback (frame by frame)

Python — OpenCV + framebuffer video
import cv2
import numpy as np
import mmap, fcntl, struct, time

def fb_video(video_path, fb_path='/dev/fb0'):
    cap = cv2.VideoCapture(video_path)
    fps = cap.get(cv2.CAP_PROP_FPS) or 25

    with open(fb_path, 'r+b') as fb:
        vinfo = bytearray(160)
        fcntl.ioctl(fb, 0x4600, vinfo)
        xres, yres, _, _, _, _, bpp = struct.unpack_from('7I', vinfo)
        finfo = bytearray(68)
        fcntl.ioctl(fb, 0x4602, finfo)
        line_length = struct.unpack_from('I', finfo, 16)[0]

        fb_mem = mmap.mmap(fb.fileno(), line_length * yres)

        frame_time = 1.0 / fps
        while cap.isOpened():
            t0 = time.monotonic()
            ret, frame = cap.read()
            if not ret:
                cap.set(cv2.CAP_PROP_POS_FRAMES, 0)  # döngü
                continue

            frame = cv2.resize(frame, (xres, yres))
            # BGR → RGB565
            r = (frame[:,:,2] >> 3).astype(np.uint16)
            g = (frame[:,:,1] >> 2).astype(np.uint16)
            b = (frame[:,:,0] >> 3).astype(np.uint16)
            px = ((r << 11) | (g << 5) | b).astype(np.uint16)

            fb_mem.seek(0)
            fb_mem.write(px.tobytes()[:line_length * yres])

            # FPS sınırla
            elapsed = time.monotonic() - t0
            if elapsed < frame_time:
                time.sleep(frame_time - elapsed)

    cap.release()

07 fbdev → DRM migration

Kernel 5.14+ ile birçok eski fbdev sürücüsünün yerini simpledrm aldı. DRM_FBDEV_EMULATION ise DRM sürücüsü üzerinden /dev/fb0 arayüzü sunar.

simpledrm

Kconfig — simpledrm
CONFIG_DRM_SIMPLEDRM=y
# EFI framebuffer, VESA, platform framebuffer gibi
# basit donanımlar için DRM sürücüsü
# Eski vesafb, efifb'nin yerine geçer

DRM_FBDEV_EMULATION — geriye uyumluluk

Kconfig + bash
CONFIG_DRM_FBDEV_EMULATION=y
# DRM sürücüsü /dev/fb0 arayüzü sağlar
# fbdev uygulamaları kod değişikliği olmadan çalışmaya devam eder

# Kontrol: hangi driver /dev/fb0'ı sunuyor?
cat /sys/class/graphics/fb0/device/uevent
# DRIVER=simpledrm  veya  DRIVER=vc4 gibi

# DRM cihazı
ls /dev/dri/
# card0  renderD128

# fbdev emulation debug
dmesg | grep "fbdev"

Migration kontrol listesi

1. mmap erişimi
DRM FBDEV_EMULATION üzerinden mmap hala çalışır. Test: mevcut fbdev uygulamanı değiştirmeden çalıştır.
2. ioctl uyumluluğu
FBIOGET_VSCREENINFO, FBIOPAN_DISPLAY emulasyon katmanında desteklenir.
3. Performans
DRM sürücüsüne geçildiğinde libdrm ile doğrudan KMS kullanmak daha performanslıdır.
4. fbcon
Kernel console (text mode) CONFIG_FRAMEBUFFER_CONSOLE ile DRM üzerinden çalışmaya devam eder.

08 Pratik

Üç gerçek senaryo: Raspberry Pi /dev/fb0 ile pixel art çizimi, C + BMP parser ile boot splash screen ve framebuffer console font değiştirme.

Raspberry Pi — /dev/fb0 ile pixel art

C — sprite çizici
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdint.h>

/* 8x8 pixel art sprite (RGB565) */
static const uint16_t smile[8][8] = {
    {0,0,0xF800,0xF800,0xF800,0xF800,0,0},
    {0,0xF800,0,0,0,0,0xF800,0},
    {0xF800,0,0x001F,0,0,0x001F,0,0xF800},
    {0xF800,0,0,0,0,0,0,0xF800},
    {0xF800,0,0x001F,0,0,0x001F,0,0xF800},
    {0xF800,0,0,0x07E0,0x07E0,0,0,0xF800},
    {0,0xF800,0,0,0,0,0xF800,0},
    {0,0,0xF800,0xF800,0xF800,0xF800,0,0},
};

void draw_sprite(uint8_t *fb, int line_length,
                 int sx, int sy, int scale)
{
    for (int y = 0; y < 8; y++) {
        for (int x = 0; x < 8; x++) {
            uint16_t color = smile[y][x];
            /* Ölçeklenmiş piksel bloğu çiz */
            for (int dy = 0; dy < scale; dy++) {
                for (int dx = 0; dx < scale; dx++) {
                    long off = (sy + y*scale + dy) * line_length
                             + (sx + x*scale + dx) * 2;
                    *(uint16_t *)(fb + off) = color;
                }
            }
        }
    }
}

Boot splash screen — C + BMP parser

bash — splash uygulama servisi
# /etc/systemd/system/splash.service
[Unit]
Description=Boot Splash Screen
DefaultDependencies=no
After=sysinit.target
Before=basic.target

[Service]
Type=oneshot
ExecStart=/usr/bin/fb-splash /usr/share/splash.bmp
RemainAfterExit=yes

[Install]
WantedBy=basic.target
C — fb-splash main
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Kullanım: fb-splash <dosya.bmp>\n");
        return 1;
    }

    int fd = open("/dev/fb0", O_RDWR);
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

    long fb_size = finfo.line_length * vinfo.yres;
    uint8_t *fb = mmap(NULL, fb_size,
        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    int bpp = vinfo.bits_per_pixel / 8;
    bmp_to_fb(argv[1], fb, vinfo.xres,
              finfo.line_length, bpp);

    munmap(fb, fb_size);
    close(fd);
    return 0;
}

Framebuffer console font değiştirme

bash — fbcon font
# Mevcut font listesi
ls /usr/share/consolefonts/*.psf*

# Font değiştir (setfont)
setfont /usr/share/consolefonts/Lat2-Terminus16.psf

# Büyük font (HiDPI ekran)
setfont /usr/share/consolefonts/Uni3-Terminus32x16.psf

# Kernel parametresi ile kalıcı (cmdline)
# fbcon=font:VGA8x16

# Yüksek çözünürlüklü ekranda okunabilir font
# Grub GRUB_CMDLINE_LINUX içine ekle:
# "fbcon=font:TER16x32"

# Ekran döndürme (90 derece)
echo 1 > /sys/class/graphics/fbcon/rotate_all
# 0=normal, 1=CCW90, 2=180, 3=CW90