前言

今天在使用 buildroot 编译 licheepi zero 镜像时,看到 buildroot 会去下载 linux-firmware 压缩包。很好奇这个压缩包是干嘛用的?

解释

linux-firmware 里面包含了各种外设的固件。很多外设硬件需要自己的固件才能运行。本来这些固件应该存放在自己外设硬件的存储器里。但是因为各种“成本”和难度的原因,现在很多都是由驱动代为载入到外设中的。 通常,很多硬件产品并不是出厂就把 firmware 刷好,而是需要驱动将 firmware 刷到硬件中去,而 linux-firmware 就是存在这些外设固件的地方。

因此为Linux拼凑某个设备的驱动时,有时我们需要从windows版的驱动包里把Firmware拷过来使用(比如我家的Benq扫描仪)。个人认为这样的好处是只要更新最新驱动就能同时使用最新的固件,不需要像以前一样需要自己刻意去刷固件。

driver & firmware

在Linux Kernel中,Driver和Firmware是有明确含义的,其中Driver是控制被操作系统管理的外部设备(Device)的代码段。很多时候Driver会被实现为LKM,但这不是必要条件。driver通过driver_register()注册到总线(bus_type)上,代表系统具备了驱动某种设备(device)的能力。当某个device被注册到同样的总线的时候(通常是总线枚举的时候发现了这个设备),总线驱动会对driver和device会通过一定的策略进行binding(即进行匹配),如果Binding成功,总线驱动会调用driver的probe()函数,把设备的信息(例如端口,中断号等)传递给驱动,驱动就可以对真实的物理部件进行初始化,并把对该设备的控制接口注册到Linux的其他子系统上(例如字符设备,v4l2子系统等)。这样操作系统的其他部分就可以通过这些通用的接口来访问设备了。

而Firmware,是表示运行在非“控制处理器”(指不直接运行操作系统的处理器,例如外设中的处理器,或者被用于bare metal的主处理器的其中一些核)中的程序。这些程序很多时候使用和操作系统所运行的处理器完全不同的指令集。这些程序以二进制形式存在于Linux内核的源代码树中,生成目标系统的时候,通常拷贝在/lib/firmware目录下。当driver对device进行初始化的时候,通过request_firmware()等接口,在一个用户态helper程序的帮助下,可以把指定的firmware加载到内存中,由驱动传输到指定的设备上。

所以,总的来说,其实driver和firmware没有什么直接的关系,但firmware通常由驱动去加载。我们讨论的那个OS,一般不需要理解firmware是什么,只是把它当做数据。firmware是什么,只有使用这些数据的那个设备才知道。好比你用一个电话,电话中有一个软件,这个软件你完全不关心如何工作的,你换这个软件的时候,就可以叫这个软件是“固件”,但如果你用了一个智能手机,你要细细关系什么是上面的应用程序,Android平台,插件之类的细节内容,你可能就不叫这个东西叫“固件”了。

参考

linux-firmware软件包是干什么用的