引导 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 内核和独立应用程序有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Linux 内核和 Windows 内核有啥区别

操作系统的用户模式、内核模式、实模式、保护模式都是啥?有啥区别和联系?

Docker和LXC有啥不同

linux系统中参数-和--有啥区别?

linux系统与嵌入式linux有啥区别和关系?

linux中设备和驱动到底有啥区别,有啥联系啊?学习2.6的内核,搞得好晕呢!