祝各位道友念头通达
GitHub Gitee 语雀 打赏

uboot和内核启动大致流程

bootloader 启动流程和功能说明

bootloader 基本功能说明

  • 有的程序在启动bootloader之前会运行一段 固化程序
  • bootloader 启动过程分单阶段和多阶段
  • 多阶段可以提供更复杂的功能和更好的移植性
  • 一般从固态存储设备启动分两个阶段

第一个阶段 bootloader 启动说明

源码 U-boot/arch/arm/cpu/xxx(armv7)/start.S

  • 用汇编, 是因为机器刚开始就从某个内存地址开始取值操作, 这个时候内存没有初始化好, 汇编不需要堆栈
  • 硬件设备初始化(关闭 看门口, 关中断, 设置CPU的速度和时钟频率, RAM初始化)
  • 为加载第二阶段的 Bootloader 的代码准备 RAM 空间(初始化RAM芯片,使可用, 调用lowlevel_init使外接SDRAM可用)
  • 复制 Bootloader 的第二阶段代码到 RAM 空间
  • 设置好栈
  • 跳转到第二阶段代码的入口 C 处

第二个阶段 bootloader 启动阶段

源码 start.S 中, 初始化相关硬件之后, 会跳转 _main, 文件名: arch/arm/lib/crt0.S

  • 初始化本阶段要使用的硬件设备(CPU中断, 系统时钟,定时器, 检查flash, 串口初始化, 检测系统内存映射)
  • 检测系统内存映射
  • 将内核映像和根文件系统映像从 flash 上读到 RAM 空间中
  • 为内核设置启动参数
  • 调用内核, 至少初始化串口用于调试
    zynq 为例:
`crt0.S`:
  ->board_init_f
   ->ps7_init //初始化mio, pll(锁相环), clock, addr, peripherals(外围设备)
   ->arch_cpu_init //根据手册, 对APB, ROM 等寄存器初始化
  ->board_init_r //gpio, led, 时钟相关初始化, 加载环境变量,然后进入主循环
   -> main_loop()

bootloader 和 内核交互

  • 单向的交互
  • bootloader 将各类参数传递给内核, 由于不能同时运行, 传递办法只有一个: 将参数放在某个约定的地方
  • 然后再启动内核, 内核从约定的地方获取参数
  • uboot 下使用 go + [内存地址] 可以运行指定内存中的编译后的程序

linux 镜像启动过程

  • linux内核启动也是分为两个部分
    • 架构/开发板相关的引导过程, 用汇编编写 arch/arm/kernel/head.S, 内核启动执行的第一个文件
      • 连接内核时使用的虚拟地址, 所以要设置页表, 使能MMU
      • 调用 C 函数 start_kernel 之前的常规工作, 包括复制数据段、清除BSS段、调用 start_kernel
    • 后续的通用启动过程, C语言 init/main.c 中的 start_kernel
      • 内核初始化的全部工作
      • 调用 rest_init 函数启动init过程, 创建系统第一个进程
      • setup_arch 函数用于对芯片架构/开发板相关的设置, 比如重新设置页表, 设置系统时钟, 初始化串口

根文件系统

根文件系统: 既创建各种目录, 并且在里面创建各种文件, 比如在 /bin/sbin 目录下存放各种可执行程序, 在/etc目录下存放配置文件等等.

Busybox移植

Busybox 是一个遵循 GPL v2协议的开源项目。Busybox 将众多的 UNIX 命令集合进一个很小的可执行程序中, 用来替换 GUN fileutilsshellutils 等工具集, 其体积小, 动态链接只有几百KB, 静态链接也只有 1MB左右

posted @ 2023-05-22 17:13  韩若明瞳  阅读(77)  评论(0编辑  收藏  举报