引导 linux 内核和独立应用程序有啥区别?
Posted
技术标签:
【中文标题】引导 linux 内核和独立应用程序有啥区别?【英文标题】:What's the difference between booting a linux kernel and a standalone application?引导 linux 内核和独立应用程序有什么区别? 【发布时间】:2019-10-16 05:36:18 【问题描述】:我有一个基于 MIPS 的开发板 (MediaTek mt7620),它带有一个专有的封闭式引导加载程序 (u-boot),它切断了很多功能,例如 booting a standalone application
。 (我不允许更改/重新刷新这个引导加载程序,因为很多客户都使用这个板,如果我们更新引导加载程序并且它失败了,我们将面临很多砖块 :) (引导加载程序支持boot over tftp
协议))
我正在尝试更改电路板制造商提供的引导顺序:ROM bootloader --> flash bootloader (u-boot) --> linux kernel 为:ROM bootloader --> flash bootloader (u-boot) --> 引导陷阱 --> linux 内核。对于另一个带有支持booting a standalone application
的u-boot的板(mt7621),我能够创建一些boot trap
u-boot映像(独立应用程序)并将其放入闪存而不是linux内核(我移动了linux内核下)。 (这个boot trap
做了一些工作,通过使用u-boot 通过跳转表提供的ranand_read/do_bootm
函数来加载和引导Linux 内核。
正如我提到的,基于 mt7620 的板的 u-boot 不支持 booting a standalone application
,所以我决定创建一个 boot trap
作为 u-boot linux 映像(而不是作为 u-boot 独立应用程序图像)保持boot trap
的代码几乎相同(我只更改了函数签名:对于独立应用程序 u-boot 映像 2 args 被传递,对于 linux u-boot 映像 - 4;和加载/入口地址)。
这是来自串口的日志, 对于基于 mt7621 的板:
## Booting image at bc140000 ...
Image Name: Boot trap
Image Type: MIPS U-Boot Standalone Program (uncompressed)
Data Size: 524 Bytes = 0.5 kB
Load Address: a0600000
Entry Point: a0600000
Verifying Checksum ... OK
OK
boot trap: got a control
boot trap: load a real kernel...
.......................
boot trap: boot a real kernel...
## Booting image at 88000000 ...
Image Name: OpenWrt Linux-3.10.14
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 1494179 Bytes = 1.4 MB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 256
Starting kernel ...
LINUX started...
对于基于 mt7620 的板:
## Booting image at bc140000 ...
Image Name: Boot trap
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 345 Bytes = 0.3 kB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 256
Starting kernel ...
如您所见,“引导陷阱”(作为 linux u-boot 映像)中的代码卡住了,我没有 JTAG
调试器,所以我只能猜测发生了一些异常并且板卡在无穷大在异常处理程序中循环。
我在基于 mt7621 的板的 u-boot 源代码中看到(我有它们 :))这样的代码行:
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
...
switch (hdr->ih_type)
case IH_TYPE_STANDALONE:
appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);
(*appl)(argc-1, &argv[1]); // <--- pass a control to a standalone app
return 0;
...
switch (hdr->ih_os)
default:
case IH_OS_LINUX:
do_bootm_linux (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
...
以及下一行:
void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong * len_ptr, int verify)
...
void (*theKernel) (int, char **, char **, int *);
theKernel = (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep);
...
theKernel (linux_argc, linux_argv, linux_env, 0); // <--- pass a control to a linux kernel
那么问题是引导 linux 内核和独立应用程序之间有什么区别?如果我们已经有一个有效的 C 环境,为什么 linux 在获得控制(linux/arch/mips/kernel/head.S)后必须设置一个堆栈指针?为什么 linux 在将控制权传递给自己的第一个 C 函数之前必须做这么多工作(在独立应用程序中,我们能够将 C 函数代码直接放入地址中,u-boot 将控制权传递给)?
为什么不可能将代码放在 u-boot 将控件传递到的地址中并让它像我为独立应用程序制作的那样运行?
【问题讨论】:
“我有一个基于 MIPS 的开发板 (MediaTek mt7620),带有一个专有的封闭式引导加载程序 (u-boot)...” -- 如果这类似于 MStar 7816(MIPS,支持 Linux 或独立),联发科收购,然后 U-Boot 违反了 GPL。 MStar 有一个定制版本的 U-Boot,但不向产品所有者提供该源代码,这违反了 GPL。 【参考方案1】:Linux 内核设计用于在从小型嵌入式设备到大型服务器的数千种不同系统上运行。在内核中包含每个可能的架构、板或配置的代码是不切实际的,因此内核定义了一组启动要求,必须满足这些要求才能运行。引导加载程序的任务通常是设置适当的环境并满足这些要求。
相比之下,“独立应用程序”通常是为特定的目标系统(架构、电路板、配置)编写的,并负责自行设置几乎所有内容。
这就是为什么 u-boot 以不同方式处理这两种情况的原因。如果您正在引导 Linux 内核,那么 u-boot 会按照内核期望的方式设置所有内容。如果您正在启动一个独立的应用程序,则假定该应用程序将执行所需的任何操作。
【讨论】:
以上是关于引导 linux 内核和独立应用程序有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章