帧缓冲控制台

顾名思义,帧缓冲控制台 (fbcon) 是一个运行在帧缓冲设备之上的文本控制台。它具有任何标准文本控制台驱动程序(例如 VGA 控制台)的功能,并具有可归因于帧缓冲图形性质的附加功能。

在 x86 架构中,帧缓冲控制台是可选的,有些人甚至将其视为玩具。对于其他架构,它是唯一可用的显示设备,无论是文本还是图形。

fbcon 有什么功能?帧缓冲控制台支持高分辨率、各种字体类型、显示旋转、原始多头等。理论上,多色字体、混合、抗锯齿以及底层显卡提供的任何功能也是可能的。

A. 配置

可以使用您喜欢的内核配置工具启用帧缓冲控制台。它位于设备驱动程序->图形支持->控制台显示驱动程序支持->帧缓冲控制台支持下。选择“y”以静态编译支持,或选择“m”以获得模块支持。该模块将是 fbcon。

为了使 fbcon 激活,至少需要一个帧缓冲驱动程序,因此请从众多可用的驱动程序中选择一个。对于 x86 系统,它们几乎普遍具有 VGA 卡,因此 vga16fb 和 vesafb 将始终可用。但是,使用特定于芯片组的驱动程序将为您提供更高的速度和功能,例如动态更改视频模式的能力。

要显示企鹅徽标,请选择图形支持->启动徽标中可用的任何徽标。

此外,您至少需要选择一个编译到内核中的字体,但如果您不执行任何操作,内核配置工具将为您选择一个,通常是 8x16 字体。

注意:一个常见的错误报告是启用帧缓冲而未启用帧缓冲控制台。根据驱动程序的不同,您可能会获得空白或乱码的显示,但系统仍会引导完成。如果您幸运地拥有一个不更改图形芯片的驱动程序,那么您仍然会获得 VGA 控制台。

B. 加载

可能的情况

  1. 驱动程序和 fbcon 都是静态编译的

    通常,fbcon 会自动接管您的控制台。一个明显的例外是 vesafb。它需要使用 vga= 启动选项参数显式激活。

  2. 驱动程序是静态编译的,fbcon 是作为模块编译的

    根据驱动程序的不同,您要么获得标准控制台,要么获得如上所述的乱码显示。要获得帧缓冲控制台,请执行“modprobe fbcon”。

  3. 驱动程序是作为模块编译的,fbcon 是静态编译的

    您将获得标准控制台。一旦使用“modprobe xxxfb”加载驱动程序,fbcon 将自动接管控制台,但使用 fbcon=map:n 选项的除外。请参阅下文。

  4. 驱动程序和 fbcon 都是作为模块编译的。

    您可以按任意顺序加载它们。一旦两者都加载,fbcon 将接管控制台。

  1. 启动选项

    帧缓冲控制台有几个在很大程度上未知的启动选项,可以更改其行为。

  1. fbcon=font:<name>

    选择要使用的初始字体。值“name”可以是任何编译到内核中的字体:10x18、6x10、6x8、7x14、Acorn8x8、MINI4x6、PEARL8x8、ProFont6x11、SUN12x22、SUN8x16、TER16x32、VGA8x16、VGA8x8。

    请注意,并非所有驱动程序都可以处理宽度不能被 8 整除的字体,例如 vga16fb。

  2. fbcon=map:<0123>

    这是一个有趣的选项。它告诉哪个驱动程序映射到哪个控制台。值“0123”是一个序列,它会重复直到总长度为 64,这是可用控制台的数量。在上面的示例中,它被扩展为 012301230123...,并且映射将是

    tty | 1 2 3 4 5 6 7 8 9 ...
    fb  | 0 1 2 3 0 1 2 3 0 ...
    
    ('cat /proc/fb' should tell you what the fb numbers are)
    

    一个可能有用的副作用是使用超出已加载 fb 驱动程序数量的 map 值。例如,如果只有一个驱动程序可用,即 fb0,添加 fbcon=map:1 会告诉 fbcon 不要接管控制台。

    稍后,当您想将控制台映射到帧缓冲设备时,可以使用 con2fbmap 实用程序。

  3. fbcon=vc:<n1>-<n2>

    此选项告诉 fbcon 仅接管由值“n1”和“n2”指定的控制台范围。给定范围之外的其余控制台仍将由标准控制台驱动程序控制。

    注意:对于 x86 机器,标准控制台是 VGA 控制台,通常位于同一显卡上。因此,由 VGA 控制台控制的控制台将出现乱码。

  4. fbcon=rotate:<n>

    此选项更改控制台显示的方向角度。值“n”接受以下值

    • 0 - 正常方向(0 度)

    • 1 - 顺时针方向(90 度)

    • 2 - 上下颠倒方向(180 度)

    • 3 - 逆时针方向(270 度)

    之后,可以通过将相同的数字“回显”到 /sys/class/graphics/fbcon 中找到的 2 个属性中的任何一个来随时更改角度

    • rotate - 旋转活动控制台的显示

    • rotate_all - 旋转所有控制台的显示

    只有在内核中编译了帧缓冲控制台旋转支持时,控制台旋转才可用。

    注意:这纯粹是控制台旋转。任何使用帧缓冲的其他应用程序都将保持其“正常”方向。实际上,底层的 fb 驱动程序完全不知道控制台旋转。

  5. fbcon=margin:<color>

    此选项指定边距的颜色。边距是屏幕右侧和底部未使用文本的剩余区域。默认情况下,此区域将为黑色。“color”值是一个整数,它取决于所使用的帧缓冲驱动程序。

  6. fbcon=nodefer

    如果内核使用延迟 fbcon 接管支持编译,通常,固件/引导加载程序留在原位的帧缓冲内容将被保留,直到实际上有一些文本输出到控制台。此选项使 fbcon 立即绑定到 fbdev 设备。

  7. fbcon=logo-pos:<location>

    唯一可能的“location”是“center”(不带引号),并且在给出时,启动徽标将从默认的左上角位置移动到帧缓冲的中心。如果由于多个 CPU 而显示多个徽标,则收集到的徽标行将作为一个整体移动。

  8. fbcon=logo-count:<n>

    值“n”覆盖启动徽标的数量。0 禁用徽标,-1 给出默认值,即在线 CPU 的数量。

  1. 附加、分离和卸载

在继续介绍如何附加、分离和卸载帧缓冲控制台之前,对依赖项的说明可能会有所帮助。

与大多数子系统一样,控制台层需要一个与硬件接口的驱动程序。因此,在 VGA 控制台中

console ---> VGA driver ---> hardware.

假设可以卸载 VGA 驱动程序,则必须先从控制台层取消绑定 VGA 驱动程序,然后再卸载该驱动程序。如果 VGA 驱动程序仍绑定到控制台层,则无法卸载它。(有关详细信息,请参阅控制台驱动程序)。

在帧缓冲控制台 (fbcon) 的情况下,这更加复杂,因为 fbcon 是控制台和驱动程序之间的中间层

console ---> fbcon ---> fbdev drivers ---> hardware

如果 fbdev 驱动程序绑定到 fbcon,则无法卸载它们,并且如果 fbcon 绑定到控制台层,则无法卸载 fbcon。

因此,要卸载 fbdev 驱动程序,必须首先从控制台取消绑定 fbcon,然后从 fbcon 取消绑定 fbdev 驱动程序。幸运的是,从控制台层取消绑定 fbcon 会自动从 fbcon 取消绑定帧缓冲驱动程序。因此,无需显式从 fbcon 取消绑定 fbdev 驱动程序。

那么,我们如何从控制台取消绑定 fbcon 呢?部分答案在控制台驱动程序中。总结如下

将一个值回显到表示帧缓冲控制台驱动程序的绑定文件。因此,假设 vtcon1 代表 fbcon,则

echo 1 > /sys/class/vtconsole/vtcon1/bind - attach framebuffer console to
                                           console layer
echo 0 > /sys/class/vtconsole/vtcon1/bind - detach framebuffer console from
                                           console layer

如果 fbcon 从控制台层分离,您的启动控制台驱动程序(通常是 VGA 文本模式)将接管。一些驱动程序(rivafb 和 i810fb)会为您恢复 VGA 文本模式。对于其余驱动程序,在分离 fbcon 之前,您必须采取一些额外的步骤,以确保正确恢复 VGA 文本模式。以下是您可以执行的几种方法之一

  1. 下载或安装 vbetool。此实用程序现在包含在大多数发行版中,通常是挂起/恢复工具的一部分。

  2. 在内核配置中,确保 CONFIG_FRAMEBUFFER_CONSOLE 设置为“y”或“m”。启用一个或多个您喜欢的帧缓冲驱动程序。

  3. 引导到文本模式并以 root 身份运行

    vbetool vbestate save > <vga state file>
    

    上述命令将图形硬件的寄存器内容保存到 <vga 状态文件>。您只需要执行此步骤一次,因为状态文件可以重复使用。

  4. 如果 fbcon 编译为模块,请通过执行以下操作来加载 fbcon

    modprobe fbcon
    
  5. 现在分离 fbcon

    vbetool vbestate restore < <vga state file> && \
    echo 0 > /sys/class/vtconsole/vtcon1/bind
    
  6. 就是这样,您回到了 VGA 模式。如果您将 fbcon 编译为模块,则可以通过“rmmod fbcon”将其卸载。

  7. 要重新附加 fbcon

    echo 1 > /sys/class/vtconsole/vtcon1/bind
    

8. 一旦 fbcon 被取消绑定,注册到系统的所有驱动程序也将被取消绑定。这意味着可以随意卸载或重新加载 fbcon 和各个帧缓冲驱动程序。重新加载驱动程序或 fbcon 将自动将控制台、fbcon 和驱动程序绑定在一起。卸载所有驱动程序而不卸载 fbcon 将使控制台无法绑定 fbcon。

vesafb 用户的注意事项:

不幸的是,如果您的启动行包含一个 vga=xxx 参数,该参数会将硬件设置为图形模式(例如加载 vesafb 时),vgacon 将不会加载。相反,vgacon 会将默认的启动控制台替换为 dummycon,并且在分离 fbcon 后,您将看不到任何显示。您的机器仍然存活,因此您可以重新附加 vesafb。但是,要重新附加 vesafb,您需要执行以下操作之一

方法 1

  1. 在分离 fbcon 之前,执行以下操作

    vbetool vbemode save > <vesa state file> # do once for each vesafb mode,
                                             # the file can be reused
    
  2. 如步骤 5 中所述分离 fbcon。

  3. 附加 fbcon

    vbetool vbestate restore < <vesa state file> && \
    echo 1 > /sys/class/vtconsole/vtcon1/bind
    

方法 2

  1. 在分离 fbcon 之前,执行以下操作

    echo <ID> > /sys/class/tty/console/bind
    
    vbetool vbemode get
    
  2. 记下模式编号

  1. 如步骤 5 中所述分离 fbcon。

  2. 附加 fbcon

    vbetool vbemode set <mode number> && \
    echo 1 > /sys/class/vtconsole/vtcon1/bind
    

示例:

这里有两个示例 bash 脚本,如果您使用的是 X86 机器,可以使用它们来绑定或解除绑定帧缓冲控制台驱动程序

#!/bin/bash
# Unbind fbcon

# Change this to where your actual vgastate file is located
# Or Use VGASTATE=$1 to indicate the state file at runtime
VGASTATE=/tmp/vgastate

# path to vbetool
VBETOOL=/usr/local/bin


for (( i = 0; i < 16; i++))
do
  if test -x /sys/class/vtconsole/vtcon$i; then
      if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
           = 1 ]; then
          if test -x $VBETOOL/vbetool; then
             echo Unbinding vtcon$i
             $VBETOOL/vbetool vbestate restore < $VGASTATE
             echo 0 > /sys/class/vtconsole/vtcon$i/bind
          fi
      fi
  fi
done

#!/bin/bash
# Bind fbcon

for (( i = 0; i < 16; i++))
do
  if test -x /sys/class/vtconsole/vtcon$i; then
      if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
           = 1 ]; then
        echo Unbinding vtcon$i
        echo 1 > /sys/class/vtconsole/vtcon$i/bind
      fi
  fi
done

Antonino Daplas <adaplas@pol.net>