为什么我们需要embedded式设备中的引导程序?

我正在使用ARM cortex-A8上的ELinux内核。

我知道bootloader是如何工作的,以及它在做什么工作。 但我有一个问题 – 为什么我们需要引导程序, 为什么引导程序是天生的

为什么我们不能直接从没有bootloader的闪存加载内核到RAM中? 如果我们加载它会发生什么? 事实上,处理器不会支持它,但为什么我们要遵循这个程序呢?

Solutions Collecting From Web of "为什么我们需要embedded式设备中的引导程序?"

引导加载程序是一种计算机程序,用于在完成自检后加载计算机的主操作系统或运行时环境。

^ 从维基百科条款

所以基本上bootloader正在做你想做的 – 把数据从闪存复制到操作内存中。 这真的很简单。

如果你想了解更多关于操作系统的信息,我强烈建议你阅读链接的文章。 引导阶段除了测试之外,还包括检查外围设备和其他一些事情。 跳过它们只在非常简单的嵌入式设备上才有意义,这就是为什么它们的引导程序更简单:

某些嵌入式系统不需要明显的启动顺序即可开始工作,启动时可以简单地运行存储在ROM中的操作程序。

相同的来源

在Linux的情况下,引导加载程序负责一些预定义的任务。 由于这个问题是arm标签,我认为ARM启动可能是一个有用的资源。 具体来说,引导加载程序负责设置描述RAM数量,内核命令行和其他参数的ATAG列表。 机器类型是最重要的参数之一。 通过设备树 ,电路板的整个描述被传递。 这使得ARM Linux的库存无法启动,出现一些代码来设置参数。

这些参数允许一个通用 Linux支持多个设备。 例如,ARM Debian内核可以支持数百种不同的板卡类型。 Uboot或其他引导装载程序可以动态地确定这些信息,或者可以对板进行硬编码。

您可能还想在堆栈溢出处查看bootloader信息页面。

一个基本的系统可能能够设置ATAGS并将NOR闪存复制到SRAM。 但是,它通常比这更复杂一点。 Linux需要RAM设置,所以你可能需要初始化一个SDRAM控制器。 如果使用NAND闪存,则必须处理坏块 ,并且复制可能比memcpy()稍复杂。

Linux通常有一些潜在的驱动程序错误,驱动程序会假设时钟已经初始化。 例如,如果Uboot总是为特定的机器初始化以太网时钟,那么Linux以太网驱动程序可能忽略了设置这个时钟。 时钟树尤其如此。

某些系统需要Linux不支持的启动映像格式; 例如可以立即初始化硬件的特殊头文件; 就像配置devices从中读取初始代码一样。 另外,通常应该立即配置硬件。 一个引导加载程序可以快速完成这个任务,而Linux的正常结构可能会延迟这个过程,导致I / O冲突等等。

从实用的角度来看,使用引导装载程序更简单。 但是,没有什么可以阻止你改变Linux的源代码直接从它启动; 尽管它可能像直接粘贴引导加载程序代码到Linux的开始。

另请参阅: Coreboot , Uboot和Wikipedia的比较 。 Barebox是一个鲜为人知的,但结构合理,现代的ARM引导加载程序。 RedBoot也用于某些ARM系统; 内核树中支持RedBoot分区。

主引导程序通常内置在芯片中,并执行将在系统中运行的第一个USER代码的加载。

存在自举程序是因为没有用于加载第一个代码的标准化协议,因为它依赖于芯片。 有时代码可以通过串口,闪存,甚至硬盘加载。 它是引导程序功能来定位它。

一旦用户代码被加载并运行,引导加载程序就不再使用,系统执行的正确性是用户的责任。

在嵌入式linux链中,主引导程序将设置并运行Uboot。 然后Uboot会找到Linux内核并加载它。

为什么我们不能直接从没有bootloader的闪存加载内核到RAM中? 如果我们加载它会发生什么? 事实上,处理器不会支持它,但为什么我们要遵循这个程序呢?

Bartek,Artless和Felipe都给出了部分图片。

每个嵌入式处理器类型(EG 386EX,Coretex-A53,EM5200)在重置或开机时都会自动执行某些操作。 有时根据电源是否循环或设备重置, 有所不同。 某些嵌入式处理器允许您在器件上电或复位时根据施加于不同引脚的电压进行更改。

无论如何,处理器可以做的事情是有限的,因为在处理器上需要定义物理空间,无论是片上闪存,指令微代码还是其他一些机制。

这个限制意味着什么

  • 固定的目的,尽快做一件事。
  • 在范围和能力上受到限制,通常将一小块代码(通常是几千字节或更少)加载到固定的存储器位置并从加载的代码开始执行。
  • 不可修改。

因此,处理器对重置或重新启动的响应是无法改变的,而且不能做太多的工作,而且我们不希望它自动将数百兆字节或千兆字节拷贝到可能不存在或不可能被初始化的内存中,这可能需要一段漫长的时间。

所以….

我们建立了一个小的程序,比我们要使用的所有设备所允许的最小尺寸要小。 该程序存储在任何需要它的地方。

有时候这个小程序是U-Boot。 有时甚至U-Boot对于初始负载来说都太大了,所以小程序又会加载U-Boot。

重点是,无论什么东西加载,可以根据需要修改一个特定的系统。 如果是U-Boot,很好,如果不是的话,它知道在哪里加载主操作系统,或者在哪里加载U-Boot(或其他的引导加载程序)。

U-Boot(通常指的是引导程序)然后配置一组最小的设备,内存,芯片设置等,以使主OS能够被加载和启动。 主要的操作系统初始化负责任何额外的配置或初始化。

所以顺序是:

  • 处理器开机或重置
  • 东西加载初始引导代码(或U-Boot风格的嵌入式引导程序)
  • 初始启动代码(可能不需要)
  • U-Boot(或其他通用嵌入式引导程序)
  • Linux初始化

内核要求您正在工作的硬件处于特定的状态。 您所使用的所有硬件都需要检查其状态并进行初始化以便进一步操作。 除了将内核映像加载到RAM中之外,这是在嵌入式(或任何其他环境)中使用引导加载程序的主要原因之一。
当你打开一个系统时,RAM也没有处于一个有用的状态(完全初始化使用),以便我们加载内核。 因此,我们不能直接加载一个内核(回答你的问题),因此需要一个构造来初始化它。

除了所有其他答案中提到的情况 – 这是正确的 – 在某些情况下,系统必须经历不同的执行模式,以TrustZone为例来说明安全的ARM芯片。 有可能仍然认为它是一种HW初始化,但是特别的是有一些额外的限制(例如:可用的内存)使得在一个单一的二进制中做所有事情是不切实际的,即使不是不可能的,引导程序的多个阶段都可用。

此外,出于安全原因,每个人都是签名的,只有在符合安全要求的情况下才能执行工作。