为什么我们需要嵌入式设备中的引导加载程序?

时间:2013-03-21 12:47:28

标签: linux embedded arm bootloader

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

我知道引导加载程序的工作原理以及它正在做什么工作。但我有一个问题 - 为什么我们需要bootloader,为什么引导程序出生

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

6 个答案:

答案 0 :(得分:14)

在Linux环境中,引导加载程序负责某些预定义任务。由于此问题已已标记,我认为ARM booting可能是有用的资源。具体来说,引导加载程序负责设置一个ATAG列表,该列表描述了RAM的数量,内核命令行和其他参数。其中一个最重要的参数是机器类型。使用设备树,可以传递完整的电路板描述。这使得库存ARM Linux无法启动,无需使用一些代码来设置参数,如上所述。

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

您可能还希望在堆栈溢出时查看bootloader info页面。

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

Linux经常有一些潜在的驱动程序错误,驱动程序会假设时钟已初始化。例如,如果 Uboot 始终初始化特定计算机的以太网时钟,则Linux以太网驱动程序可能忽略了设置此时钟。对于时钟树来说尤其如此。

某些系统需要Linux不支持的启动映像格式;例如,可以立即初始化硬件的特殊标头;比如配置devices来读取初始代码。此外,通常还有应立即配置的硬件; 引导加载程序可以快速完成此操作,而Linux的正常结构可能会显着延迟,从而导致I / O冲突等。

从实用的角度来看,使用引导加载程序更简单。但是,没有什么可以阻止你改变Linux的源代码直接从它启动;虽然它可能就像将 boot loader 代码直接粘贴到Linux的开头一样。

另请参阅:CorebootUbootWikipedia's comparisonBarebox是一个鲜为人知但结构良好且现代的ARM引导加载程序。 RedBoot也用于某些ARM系统;内核树支持RedBoot分区。

答案 1 :(得分:13)

  

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

^ 来自Wikipedia Article

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

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

  

某些嵌入式系统不需要明显的启动顺序即可开始运行,启动时可能只需运行存储在ROM中的运行程序。

相同的来源

答案 2 :(得分:3)

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

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

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

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

答案 3 :(得分:3)

  

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

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

每个嵌入式处理器类型(E.G.386EX,Coretex-A53,EM5200)在重置或启动时都会自动执行 某些 。有时, 某些内容 会有所不同,具体取决于电源是否循环或设备是否已重置。某些嵌入式处理器允许您根据设备上电或复位时施加到不同引脚的电压来更改 某些

无论如何,处理器可以执行的 数量有限,因为定义 所需的处理器物理空间 ,无论是片上FLASH,指令微代码还是其他一些机制。

此限制表示 某事

  • 固定目的,尽快做一件事。
  • 范围和能力有限,通常将一小段代码(通常为几千字节或更少)加载到固定的内存位置,并从加载的代码的开头执行。
  • 不可修改的。

因此处理器响应重置或电源循环所做的事情无法改变,也无法做很多事情,我们也不希望它自动将数百兆字节或千兆字节复制到可能不存在的内存或可能没有初始化,可能需要花费很长时间。

...所以

我们设置了一个小程序,小于我们将要使用的所有设备允许的最小尺寸。该程序存储在 某些 所需的任何位置。

有时小程序是U-Boot。有时甚至U-Boot对于初始加载来说太大了,所以小程序然后加载U-Boot。

关键是, 加载的任何内容都是 可修改的 ,因为特定系统需要。如果它是U-Boot,那么很好,如果没有,它知道在哪里加载主操作系统或在哪里加载U-Boot(或其他一些引导加载程序)。

U-Boot(一般说来是引导程序)然后配置一组最小的设备,内存,芯片设置等,以便能够加载和启动主操作系统。主OS init负责任何其他配置或初始化。

所以顺序是:

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

除了所有其他答案中所述 - 这是正确的 - 在某些情况下,系统必须经历不同的执行模式,例如TrustZone用于安全的ARM芯片。可能仍然认为它是一种硬件初始化,但是它的特殊之处在于存在额外的限制(例如:可用内存),这使得在单个二进制文件中执行所有操作变得不切实际(如果不是不可能的话),因此可以使用多个阶段的引导加载程序。

此外,出于安全原因,每个人都签名并且只有在满足安全要求时才能执行其工作。