U-boot启动流程和bootz 启动 Linux 内核过程

本文详细介绍了U-Boot启动流程,包括stage1和stage2的CPU和外设初始化,以及如何将代码和数据从外部RAM加载到DDR。重点讲解了重定位过程,如relocate_code和relocate_vectors,以及bootz启动Linux内核的过程。讨论了不同情况下U-Boot可能避免重定位的情况,如固定内存映射和特殊硬件设计。
摘要由CSDN通过智能技术生成

一、U-boot启动流程

boot的启动大致可分为两个阶段:

stage1:使用汇编完成CPU的初始化

stage2:通过C语言分board_init_f 和 board_init_r 两个阶段完成外设的初始化

U-Boot在启动过程中,需要将自身代码、环境变量、内核等数据从外部的RAM加载到速度更快,性能更好的DDR内部中。首先,将U-Boot的二进制代码从Flash存储器中读取出来,加载到DDR的一个预设地址(通常是RAM的低地址区域)。然后,找到链接脚本(u-boot.lds)中制定的入口点,并开始执行u-boot的初始化代码。在执行初始化代码的过程中,会对U-boot代码中的变量、函数、环境变量等进行重定位(重定位就是u-boot将自身拷贝到DDR的另一个地方去继续运行(高地址处)),将它们的地址修正成正确的地址,以便在程序执行时能够正确地访问这些变量及函数,避免与操作系统或其他程序运行时所使用的内存区域发生冲突(重定位的原因)。主要过程如下:

  1. reset函数将处理器设置为SVC模式,并且关闭 FIQ 和 IRQ(在u-boot启动阶段不需要中断触发什么事件,避免干扰代码,使用CPSR禁用),设置中断向量表可重定位,并设置中断向量偏移,初始化CP15;
  2. lowlevel_init函数设置 SP 指针(任何C程序运行都要设置堆栈指针用于存储函数参数、局部变量和返回地址)、R9 寄存器(存储全局数据指针),调用 s_init (空函数);
  3. _main函数主要调用 board_init_f、relocate_code、relocate_vectors 和 board_init_r 这 4 个函数;
  4. board_init_f 函数初始化一系列外设,比如DDR、串口、定时器,或者打印一些消息等,初始化 gd(gd是全局数据(global_data)结构的一个指针,它包含了整个引导加载器运行过程中所需的各种信息。初始化gd的各个成员变量是U-Boot启动过程的关键部分) 的各个成员变量,用于重定位 u-boot。u-boot 会将自己重定位到 DRAM 最后面的地址区域(u-boot 原先运行在 DDR 的 0x87800000 地址处),也就是将自己拷贝到 DRAM 最后面的内存区域中。 这么做的目的是给 Linux 腾出空间,防止 Linux kernel 覆盖掉 u-boot,将 DRAM 前面的区域完整的空出来。在拷贝之前肯定要给 u-boot 各部分分配好内存位置和大小,比如 gd 应该存放到哪个位置,malloc 内存池应该存放到哪个位置等等。这些信息都保存在 gd 的成员变量中,因此要对 gd 的这些成员变量做初始化。最终形成一个完整的内存“分配图”,在后面重定位 u-boot 的时候就会用到这个内存“分配图”;

relocaddr是U-Boot在内存中的重定位地址,即U-Boot代码和数据从其初始加载地址复制到的目标地址;start_addr_sp是U-Boot栈的起始地址。在计算机程序中,栈是用于存储局部变量、函数参数、返回地址等临时数据的内存区域;

  1. relocate_code 为代码重定位函数,此函数负责将 uboot 拷贝到新的地方去,此函数定义在文件 arch/arm/lib/relocate.S 中;
  2. 函数 relocate_vectors 对中断向量表做重定位,此函数定义在文件 arch/arm/lib/relocate.S 中;
  3. board_init_f 函数初始化board_init_f 函数没有初始化的外设,函数定义在文件common/board_r.c中;
  4. run_main_loop 函数主要是调用parse_stream_outer函数,接收命令行输入,解析并执行相应的命令,最终真正执行命令解析和执行相应操作的函数;完成uboot 启动以后会进入 3 秒倒计的功能;

二、bootz 启动 Linux 内核过程

当U-Boot初始化完成后,会将内核等其他操作系统或者应用程序从Flash存储器中读取出来,并根据内核的要求进行重定位,从而实现内核的正常启动工作。主要过程如下:

  1. do_bootz(启动流程的开始):这个阶段由函数do_bootz负责,它是启动流程的入口点。该函数主要调用bootz_start和do_bootm_states以启动内核;
  2. bootz_start(初始化系统镜像):bootz_start函数用于初始化一个名为images的结构体,这个结构体包含了系统镜像的相关信息。 在bootz_start内部,它首先通过调用do_bootm_states执行BOOTM_STATE_START阶段。 接下来,bootz_setup函数用于判断当前的系统镜像文件是否为Linux镜像。 最后,bootm_find_images函数负责查找ramdisk(如果使用)和设备树。如果不使用ramdisk,这个函数仅用于查找和初始化设备树相关的 成员变量。

do_bootm_states函数处理三种主要的启动状态:

BOOTM_STATE_START:bootm_start函数执行初始化操作,包括重置images结构体,为系统镜像的加载做好准备。随后,bootm_os_get_boot_func函数被调用以确定特定操作系统的启动函数,对于Linux系统而言,这个函数是do_bootm_linux,并被赋予boot_fn函数指针。此时,boot_fn(现指向do_bootm_linux)负责处理接下来的两个状态

BOOTM_STATE_OS_PREP:boot_prep_linux处理环境变量bootargs,它们携带了启动Linux内核所需的参数。最终,在BOOTM_STATE_OS_GO状态,

BOOTM_STATE_OS_GO:boot_jump_linux函数执行Linux的kernel_entry函数,标志着内核的正式启动。这一系列精细协调的步骤确保了Linux内核在嵌入式系统中的平稳启动和运行。

补充:在某些情况下,U-Boot在启动时可能不需要重定位:

  1. 固定内存映射:如果系统的内存映射是固定的,并且U-Boot已经被编译为直接在其最终运行地址处执行,则不需要重定位。这通常在硬件设计时就已经决定了。
  2. 足够的启动内存地址空间:在某些系统中,如果启动时分配的内存地址空间足够大,足以容纳U-Boot的全部功能,且不会与操作系统或其他应用程序发生冲突,则U-Boot可以直接在其初始加载地址运行,无需重定位。
  3. 特殊的硬件设计:在某些特殊的硬件设计中,比如使用了特定的存储器或具有特殊的内存管理机制,U-Boot可能被设计为无需重定位就能运行。
  4. 简化版本的U-Boot:在某些应用中,可能使用了精简版的U-Boot,这个版本的U-Boot已经针对特定的硬件和使用场景进行了优化,从而无需进行重定位。

在这些情况下,U-Boot可以避免重定位过程,直接在其加载地址上运行。这样做可以简化启动过程,减少启动时间,但这通常需要特定的硬件设计和软件配置来支持。

u-boot启动过程中,有以下详细步骤: 1. u-boot被加载到内存中并运行。 2. u-boot执行do_bootm_linux函数,该函数用于启动Linux内核。 3. u-boot根据参数信息设置启动参数,这些参数由uboot传递给内核,用于配置内核的运行环境。 4. u-boot执行boot命令来启动Linux内核,常用的boot命令有bootz、bootm和boot。 5. 在bootm命令中,u-boot会执行bootcmd参数中定义的一系列命令。这些命令可以用于执行一些预定义的操作,比如显示logo信息、从存储设备中读取内核映像到内存等。 6. 最后,u-boot会将内核映像加载到内存中,并启动内核。 总结起来,uboot启动过程的详细步骤包括加载u-boot到内存中、设置启动参数、执行boot命令启动Linux内核,并根据bootcmd参数执行一些额外的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Uboot启动过程详解](https://blog.csdn.net/weixin_45566765/article/details/119082331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [linux-uboot 移植三 uboot启动内核过程](https://blog.csdn.net/u010681589/article/details/125195077)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曲途光未央

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值