Bootloader应用分析

1、Bootloader介绍

Boot 概念

  • 启动引导,自举程序
  • 由于boot设计比较偏底层,所以根据cpu架构和OS类型可能有所不同
  • uboot是对cpu架构和os类型支持比较多的一种开源引导程序

Bootloader中文解释为:启动引导程序

Bootloader的种类繁多,归纳如下:

2、s5p6818启动过程

S5P6818的启动过程

  • 芯片选择启动irom设备
  • iROM选择启动下一阶段引导程序所在设备(p5)
  • iROM启动UBOOT第一阶段BL1
  • UBOOT第一阶段启动UBOOT第二阶段BL2
  • UBOOT第二阶段启动内核

s5p6818启动流程

  • 芯片最先是从iRom启动,叫BL0
  • iROM选择启动下一阶段引导程序BL1
  1. 单阶段启动:如果BL1可以完成内核加载,这就是单阶段启动
  2. 多阶段启动:启动加载内核的工作由BL2之后的程序完成,这就是多阶段启动。

TPS: BL1的内存不能超过56K,因为UBOOT有的达到400K, 所以会分两个阶段启动BL2。增加DRAM的内存,DRAM可达1G.

问:为什么BL1不直接加载到DRAM里面?

  • SRAM比DDR更快
  • DDR需要初始化,而SRAM不需要

BL1启动Bootloader第二阶段BL2,BL2启动内核,内核加载根文件系统。

引导传参:引导程序最终没有了,达成一个共识,引导程序怎么给内存传参。

  • 所传数据结构必须约定一致,不一致即便传过去,内核解析不出来。
  • 引导程序与内核之间必须约定一个参数存放的地址base+0x100(一般可以修改)
  • 数据格式约定一致,比如用户传递给内核的参数:

3、u-boot介绍

3.1、u-boot介绍及配置

u-boot介绍

  • 源码获取:
  1. 官网下载
  2. 从芯片原厂获取配套的BSP
  3. 拷贝"资料/sourcecode/u-boot.xxxx.tar.bz2"到虚拟机
  4. 解压源码:tar xvf xxxxx
  5. 拷贝内核镜像生成工具(编译uImage时用到):sudo cp tools/mkImage /bin/
  • u-boot最初是由PPCBoot发展而来
  • 已经成为当前主流引导程序
  • 官方引导程序由于与硬件平台差异,所以并不能下载直接运行(需要经过调试和修改及移植)
  • 编译uboot

API:只是一些接口不一定用到

arch:非常重要,每个目录代表一个架构

board:代表芯片,平台,基于arm的芯片和平台特别多

commom:绝大部分cmd开头,每个cmd代表一个命令,例如:loadb

disk:磁盘

doc:针对u-boot开源软件的介绍

drivers:驱动,这些驱动绝大部分第二阶段的代码,第一阶段不需要那么多驱动,只是完成DDR的初始化和拷贝。

dts:设备树,现在内核把设备树直接跟内核放在和镜像打成一个包,下载直接下载到指定的地址。

fs:文件系统,uboot支持很多文件系统,ext4ls 直接通过命令查看很多文件内容 例如:ext4ls mmc 0:1

include:头文件的集中营,绝大部分头文件汇总到这里

lib:很多的库,不能使用带有系统调用的C库,因为很多人写习惯可以自己实现跟C类似的库。

licenses:走到GPL,BSD,LGPI开源公共协议

net:不是网卡驱动,走的协议相关的,除了支持串口USB,也支持网络下载

post:自检,检查系统是否正常的相关代码

prototype: 兼容性相关的 s5p4418 和 s5p6818能否引导程序在这上面跑起来。

scripts:脚本,完成系统的配置,编译引导程序之前,需要配置,生成目标平台。

tools:处理制作镜像用到的工具,内核生成制作镜像也会用到,例如:mkimage。

配置编译uboot

  1. 进入uboot源码目录:cd u-boot-2014.07
  2. 清除编译痕迹(只是第一次做):make distclean,不需要每次都做,每次要好几分钟
  3. 编译器配置成目标平台:make x6818_config
  4. 编译源码:make
  5. 在源码根目录下会生成镜像:ubootpak.bin

镜像烧写

  • 找到官方提供的标准镜像
  • 开发板开机 进uboot命令行模式
  • 执行下载命令:fastboot
  • 插入miniUSB下载线
  • 如果打开了虚拟机,要确认USB链接到的是物理主机
  • 未安装驱动效果,和安装驱动效果如下图右边。

  • 安装驱动,双击打开fastboot 驱动。
  • 安装完驱动后重新插拔USB线
  • 下载:通过fastboot.exe
  1. 修改下载脚本文件:REM表示注释一行
  2. 下载uboot:fastboot flash ubootpark ../linux_image/ubootpak.bin
  3. 下载内核:fastboot flah boot ../linux_image/boot.img
  4. 下载根文件系统:flash gtkfs ../linux_image/gtkfa.img
  • 双击:"sp_linux_image_down.bat",下载完成,开发板提示:FLASH:ubootpark - DONE
  • 下载完成后,Ctrl+C退回命令行,或直接重启开发板即可

配置编译原理分析

  • 用户执行make x6818_config,其实是调用了一个脚本:
bash 复制代码
/u-boot-2014.07/mkconfig -A x6818 #$(MKCONFIG) -A $(@:_config=)
  • mkconfig脚本从u-boot-2014.07/boards.cfg中找到x6818所在行,并将该所有信息设置成mkconfig脚本的新的命令行参数:

  • mkconfig将定义的变量值修改成命令行获取到的参数,存入include/config.mk文件中:

  • mkconfig创建include/config.h 并写入一个定制的头文件及目标平台相关信息
  1. include/config.h默认是被所有源码所包含的不变的头文件
  2. 所以只要包含了include/config.h文件的源码,就会间接包含x6818.h
  3. 包含方法:#include <configs/${CONFIG_NAME}.h>
  • x6818.h中的裁剪配置宏均以CONFIG_开头
  1. 这个宏会被脚本解析成变量定义在include/autoconf.mk
  2. include/autoconf.mk最后又会被Makefile所包含,并决定哪些文件需要编译。

uboot镜像产生

  • 链接脚本:arch/arm/cpu/slsiap/u-boot.lds
  • 查看更加详细的编译过程: make V=1
bash 复制代码
arm-linux-ld -pie --gc-sections -Bstatic -Ttext 0x43C0000  ......
  • 如果命令行和链接脚本同时指定了同一个段的链接地址,命令行的优先有效。
  • 裁剪镜像去格式处理:
  • uboot源码生成的可执行程序是:u-boot.bin
  • 镜像打包:镜像组成:nsih+2ndboot+u-boot.bin=ubootpak.bin

3.2、控制命令

设置启动命令行参数:setenv bootargs

boot启动系统时,自动加载的环境变量;setenv bootcmd ext4load mmc ..

下载镜像命令,至少三种:

  1. loadb 0x48000000 (通过串口下载文件到内存中)
  2. fastboot (通过usb下载文件到磁盘中)
  3. tftp 0x48000000(通过网络下载文件到内中)

启动命令:

  1. boot(从外存启动)
  2. bootm 0x48000000(从指定内存启动系统)
  3. 从上位机启动(主要用于调试内核)
  • fastboot flash app uImage(先从PC端下载镜像到内存0x48000000)
  • bootm ox48000000(从指定内存启动系统)

3.3、命令实现

uboot添加一条自定义命令:

  • 在common/文件夹下建立cmd_helloworld.c
  • 还可以在include/configs/行818.h中增加一项宏定义:
cpp 复制代码
#define CONFIG_CMD_HELLOWORLD 1
  • 包含必备头文件
cpp 复制代码
#include <common.h>
#include <command.h>
  • 调用命令定义宏:
  • 完成命令回调函数
  • 在common/Makefile中增加一项

3.4、启动过程

  • 通过ext4load或fastboot下载一个内核uImage到内存0x48000000

  • 通过bootm 0x48000000启动内核

  • 先找到cmd_bootm.c文件

  • 找到bootm命令回调函数

  • 具体调用关系如下:

    cpp 复制代码
    do_bootm() ->
       do_bootm_states() ->
          bootm_os_get_boot_func() ->
             boot_os[] ->
                do_bootm_linux() ->
                   boot_jump_linux() ->
                      kernel_entry(0,machid,r2);//启动内核
相关推荐
时空未宇1 小时前
海鸥派顺利运行YOLO11S
linux·运维·服务器
ElevenS_it1881 小时前
日志在哪里找?分布式环境下日志采集断裂的5个排查路径
运维·网络·分布式
半壶清水1 小时前
ubuntu中部署开源交换机模拟器bmv2详细步骤
linux·运维·网络·网络协议·tcp/ip·ubuntu
j_xxx404_1 小时前
Linux:深入解析ELF文件结构
linux·运维·服务器
互联网推荐官1 小时前
上海软件定制开发与数字化建设:D-coding 全平台应用架构及实施指南
大数据·运维
ShineWinsu1 小时前
对于Linux:进程间通信IPC(共享内存)的解析
linux·服务器·面试·笔试·进程·共享内存·ipc
代码中介商1 小时前
Linux 进程间通信:共享内存与消息队列完全指南
linux·运维·服务器
计算机安禾2 小时前
【Linux从入门到精通】第27篇:文本处理三剑客(上)——grep 正则表达式实战
linux·运维·正则表达式
码到成功>_<2 小时前
Linux中grep命令使用说明
linux