2021-09-14 uboot移植开发

article/2025/10/6 15:46:41

引言:最近要改动uboot,实现像微软PC上,u盘一键刷机或手机上安全模式下刷机的操作
专门去好好研究了点uboot的启动过程;以下为总结:

嵌入式系统                                                        微软-PC
————————————————————————

bootloader   -引导.启动内核                              Bios

内核                                                                   引导操作系统Windows

挂载根文件                                                        识别系统盘(C/D盘)

应用程序                                                            应用程序....
————————————————————————
bootloader之uboot的作用:引导、启动内核

从flash中读内核到SDRAM,在这之前,要求先先关开门口内初始化时钟和初始化SDRAM(通常称为硬件相关初始化)

uboot三个步奏:
1)从flash读出内核,

2)将其放到sdram中运行(要求可:写读flash->初始化sdram(初始化时钟、初始化串口)

3)然后启动内核

4)为开发方便,额外加入其他功能--烧写flash(比如从网络,usb或串口传进来的内核)!

分析Makefile,达到分析文件结构;分析配置过程:

1)配置:比如make Linux-menuconfig

2)编译:makez

二.读出内核并启动内核

1.了解系统的上电过程:
board_init_r --> init_sequence_r --> run_main_loop --> main_loop --> bootdelay_process-->autoboot_command 主要就是这么个流程(下图从右向左)



所以:具体怎么决定是进命令行还是启动kernel是在autoboot_command决定的!!!
正常自动启动如下:
左边为终端打印:右方tstc()即为获取键值;此处可以设置特定键值为启动内核开关!!

如果看到:

if (bootdelay >= 0) 
{ //此处:键盘按Ctrl+C、enter、或者Space将abort置1,将不再启动内核if (tstc()) {    /* we got a key press    */             key = getc(); /* consume input */             puts("\b\b\b 0");             switch (key) {                 case 0x03:      /* ^C - Ctrl+C */                 case 0x0d:      /* Enter */                 case 0x20:      /* Space */ //only "enter" key can triger abort                 abort = 1;    /* don't auto boot    */             }         
}

如果abortboot_single_key / abortboot_normal返回1,则autoboot_command执行完成,回到main_loop继续跑到cli_loop-->cli_simple_loop进入,并停在命令行模式。
2.上面是命令行模式,如果abortboot_single_key/abortboot_normal返回0.则abortboot返回0,那么autoboot_command里调用run_command_list,run_command_list中执行命令bootcmd启动kernel!
接下来说,上电从flash读取内核存入系统内存并启动kernel的过程:
如上说到run_command_list函数,该函数会调取board_run_command(buff);
#ifdef CONFIG_CMDLINE
    rcode = cli_simple_run_command_list(buff, flag);
#else
    rcode = board_run_command(buff);
#endif


在调取之前,需要读取环境变量的数据参数;根据参数去读取指定位置flash的内核!
如下,是环境参数:

--------下面涉及到一般执行一个内核镜像的四个步骤-------
第一步先读取头信息,然后在头信息的特定地址找MAGIC_NUM,由此来确定种类,第二步对镜像进行校验,第三步再次读取头信息,由头信息的特定地址知道这个镜像的各种信息,包括长度,种类,入口地址等等,第四步就是去entrypoint处开始执行镜像,

 第一步:如果直接在kernel底下去make uImage会提示mkimage没找到,解决方案是在 /uboot/tool下去复制到 /usr/local/bin.下面去,复制它到系统目录下,再去执行make uImage就可以了;

do_bootm函数一直到397行之前都是进行zImage镜像的头部信息校验。校验时就要根据不同种类的image类型进行不同的校验。所以do_bootm函数的核心就是去分辨传进来的image到底是什么类型,然后按照这种类型的头信息格式去校验。校验通过则进入下一步准备启动内核;若果校验失败则认为镜像有问题,所以不能启动


do_bootm调用内核获取和校验


image_header_t结构体
(1)这个数据结构是我们uboot启动内核使用的一个标准启动数据结构,zImage头信息也是一个image_header_t,但是在实际启动之前需要进行一些改造,
if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
        printf("Boot with zImage\n");
        addr = virt_to_phys(addr);
        hdr = (image_header_t *)addr;
        hdr->ih_os = IH_OS_LINUX;
        hdr->ih_ep = ntohl(addr);
        memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t));

        /* save pointer to image header */
        images.legacy_hdr_os = hdr;

        images.legacy_hdr_valid = 1;

这里就是在进行改造。
(2)image全局变量是在bootm函数中使用,目的是用来指向 os/initrd/fdt images,也就是用来完成启动的,zImage校验过程先确定是不是zImage,然后再修改zImage头信息,到合适,也就是上面的改造,最后再用这个头信息去初始化image,然后完成了校验。
zImage启动方式是后来添加的,而且用了goto的方式跳转了一部分代码,本身对uboot的结构上添加的。
uImage启动
(1)在uboot启动的do_boot中有一个legacy的方法,指的就是uImage这样的方式,为什么是legacy(遗留的),是因为uImage本身是uboot发明的一种启动的方式,后来这种方式是不好的,被废弃,于是被一种新的方式给替代了,新的方式就是设备树的方式,在这里被叫做fit,这个就是设备树的方式。
(2)uImage启动校验函数是在boot_get_kernel这个函数里,主要任务就是校验我们的uImage的头信息,并且得到真正的kernel的起始位置去启动。
总结:uboot本身也只支持uImage方式启动的,后来有了设备树之后,就把uImage方式命名为legacy方式,fdt方式就命名为fit方式,于是乎多了#if  #endif添加代码。后来移植的人又为了省事添加了zImage的方式,又为了省事,添加了#if  #endif .
第二阶段校验头信息结束!

 第三阶段,启动Linux内核,调用do_bootm_linux这个函数

do_bootm_linux:找到do_bootm_linux,这个函数在lib_arm/bootm.c中() ,给内核传参-image结构体

 
第四步:镜像的entrypoint:
ep就是程序入口,一个镜像的起始部分不是在镜像的开头(镜像的开头有很多字节的头信息),真正开始执行的代码在中间的某个部分,相对于头有一定偏移量的,这个偏移量放在头信息中的。
 一般执行一个镜像都是:第一步先读取头信息,然后在头信息的特定地址找MAGIC_NUM,由此来确定种类,第二步对镜像进行校验,第三步再次读取头信息,由头信息的特定地址知道这个镜像的各种信息,包括长度,种类,入口地址等等,第四步就是去entrypoint处开始执行镜像(此处第四步)
theKernel = (void (*)(int, int, uint))ep;将真正的入口地址赋值给thekernel,就是操作系统的第一句代码
Starting kernel ...这里打印是uboot的最后打印信息,如果这句后,串口没输出信息了,说明内核没有成功被执行,原因是传参错误(80%),内核在DDR中的加载地址。。。
如果传参正确:"Starting kernel ..."是内核启动的第0条

接下来查看给内核传参并启动内核的操作

tag方式传参
(1)struct tag,tag是一个数据结构,在uboot和linux kernel中都有定义tag数据机构,而且定义是一样的。
(2)tag_header和tag_xxx。tag_header中有这个tag的size和类型编码,kernel拿到一个tag后先分析tag_header得到tag的类型和大小,然后将tag中剩余部分当作一个tag_xxx来处理。
(3)tag_start与tag_end。kernel接收到的传参是若干个tag构成的,这些tag由tag_start起始,到tag_end结束。
(4)tag传参的方式是由linux kernel发明的,kernel定义了这种向我传参的方式,uboot只是实现了这种传参方式从而可以支持给kernel传参。

配置传参宏
(1)CONFIG_SETUP_MEMORY_TAGS,tag_mem,传参内容是内存配置信息。
(2)CONFIG_CMDLINE_TAG,tag_cmdline,传参内容是启动命令行参数,也就是uboot环境变量的bootargs.
(3)CONFIG_INITRD_TAG
(4)CONFIG_MTDPARTITION,传参内容是iNand/SD卡的分区表。
(5)起始tag是ATAG_CORE、结束tag是ATAG_NONE,其他的ATAG_XXX都是有效信息tag。
思考:内核如何拿到这些tag?
uboot最终是调用theKernel函数来执行linux内核的,uboot调用这个函数(其实就是linux内核)时传递了3个参数。这3个参数就是uboot直接传递给linux内核的3个参数,通过寄存器来实现传参的。(第1个参数就放在r0中,第二个参数放在r1中,第3个参数放在r2中)第1个参数固定为0,第2个参数是机器码,第3个参数传递的就是大片传参tag的首地址。
移植时注意事项
(1)uboot移植时一般只需要配置相应的宏即可
(2)kernel启动不成功,注意传参是否成功。传参不成功首先看uboot中bootargs设置是否正确,其次看uboot是否开启了相应宏以支持传参。

附:uboot命令的实现-命令为输入的字符串+参数[比较简单,详细可以去看韦东山的uboot视频]

输入字符串---即为命令name--->存在针对于命令的结构体

结构体

{
。name
。fun =
。。。。
}

出现对应的动作--->函数fune-
run_common()的实现先比较,若name比较正确,执行对应的fun


 


http://chatgpt.dhexx.cn/article/7btIkOHk.shtml

相关文章

iTOP4412 uboot移植教程

好多刚开始学习uboot移植的同学总是觉得uboot好难,但是再难的问题如果把它一步步拆开,一个个解决,问题也就将迎刃而解。做uboot移植,我们首先就得了解uboot的编译流程,这里以在iTOP4412精英版2G内存的板子上移植u-boot…

<Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分)

<Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) 第一部分链接:系统移植-之-uboot移植第一部分 第一部分主要讲解了,uboot移植过程中使用的一些工具的安装,以及测试nxp远程uboot&a…

X210开发板(S5PV210芯片)uboot移植DM9000驱动移植

前言 本文是介绍在uboot中如何移植DM9000的驱动,并不深入去讲解DM9000芯片的操作时序和内部寄存器,想要读懂驱动代码要仔细阅读DM9000芯片的数据手册。移植的基础是手里有DM9000芯片可以用的驱动代码,只需要根据开发板中DM9000芯片的接线方式…

嵌入式linux UBoot移植篇

如何在U-boot添加自己的linux板卡并启动呢? uboot 的移植并不是说我们完完全全的从零开始将 uboot 移植到我们现在所使用的开发板或者开发平台上。这个对于我们来说基本是不可能的,这个工作一般是半导体厂商做的, 半导体厂商负责将 uboot 移…

Uboot移植流程

linux-Bootloader(Uboot)移植流程 前言 最近在做ZigBee的温室大棚项目,将自己学习的过程和经验分享给大家。本文基于linux3.4.39内核版本,s5p6818开发板实现。 1、uboot启动简介 uboot启动的过程比较复杂,这里就只…

IMX6ULL Uboot 移植

使用的开发板:正点原子ALPHA V2.2 Uboot简介 在学习STM32的过程中使用过IAP在线升级就会知道,有引导程序APP程序,即bootloader程序APP。在学习嵌入式Linux的时候也一样,这个引导程序就是Uboot. uboot移植主要是根据原厂的uboot移…

二、uboot移植

二、uboot移植 版本作者时间备注V 1.0bug设计工程师2021/11/10创建文件软件网盘链接0交叉编译工具链接:https://pan.baidu.com/s/1yFO2NDMet9_b1E1q1rMwEA提取码:42kluboot源码同上linux源码同上文件系统工具同上tftp工具同上2.1 简单说明 uboot制作结束会生成 u-boot-etc44…

linux-uboot 移植四 uboot的移植

概述 前边的章节中介绍到如果要移植uboot的话,最好的参考就是由官方提供的demo。 1、移植 1.1 添加board对应的板级文件夹 uboot 中每个板子都有一个对应的文件夹来存放板级文件,比如开发板上外设驱动文件等等。 NXP 的 I.MX 系列芯片的所有板级文件…

[uboot 移植]uboot 移植过程

文章目录 uboot 移植1 修改顶层 Makefile2 在 board 文件夹下添加开发板对应的板级文件2.1 imximage_lpddr2.cfg 和 imximage.cfg 文件2.2 plugin.S 文件2.3 Kconfig 文件2.4 igkboard.c 文件2.5 MAINTAINERS 文件2.6 Makefile 文件 3 添加 igkboard_defconfig 配置文件4 添加开…

UBoot 移植

1 NXP官方开发板uboot编译测试 1 查找 NXP 官方的开发板默认配置文件 因为我们的开发板是参考 NXP 官方的 I.MX6ULL EVK 开发板做的硬件,因此我们在移植 uboot 的时候就可以以 NXP 官方的 I.MX6ULL EVK 开发板为蓝本。 在 NXP 官方 I.MX6UL/6ULL 默认配置文件中找…

大话uboot 移植

结合作者多年的移植经验,尽量简单的为大家描述一个uboot 的移植过程。希望通过描述,给初入移植行道的你带来美好的希望。接下来,我们通过以下几个方面来描述。 1. arm soc 的启动方式 在描述soc 前,我们先看下一个简单的arm soc:…

uboot移植步骤

Uboot移植具体步骤(本例子为Samsung origen板) 第一步:准备源码 网上下载现成的uboot开源代码:https://ftp.denx.de/pub/u-boot/ 在该网站中选择与板子兼容的uboot源文件(公司中一般咨询硬件工程师) 在Linux系统下解压 tar xf 压缩包名 第二步:修改源码 1.抄板:将和你板子兼容…

(二)uboot移植--从零开始自制linux掌上电脑(F1C200S)<嵌入式项目>

目录 一、前言 二、F1C200s上电启动顺序 三、前期准备 四、新建用户 五、交叉编译环境配置 六、uboot简介 七、uboot移植 🍏 uboot下载 🍏 uboot默认配置 🍏 uboot图形界面配置 🍏 uboot编译 🍏 烧录bin…

U-Boot 移植初探

1. NXP官方开发板uboot编译测试 uboot移植不需要从零开始将uboot移植到使用的开发板上。因为半导体厂商通常都会自己做一个开发板, 将uboot移植到他们自己的原厂开发板上,再将这个uboot(原厂BSP 包)发布出去。因此使用自已的开发…

U-Boot移植

一、U-Boot Linux 系统要启动就必须需要一个 bootloader 程序,芯片上电以后先运行一段bootloader程序。 bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,NOR FLASH, SD, eMMC 等)拷贝到 DDR 中&…

uboot移植

一、我们知道uboot就是一个Bootloader。但是,arm不像我们的pc机一样,用一个老毛桃随便找一个网站下一个windows镜像就可以直接装了。 我们的uboot对应的就是老毛桃里面刷的引导程序。 虽然uboo支持很多架构很多不同的厂家的板子,但是UBOOT它…

【Linux】系统移植篇四--uboot移植

系统移植篇四--uboot移植 一、uboot源码结构1、uboot源码获取2、uboot特点3、uboot源码结构 二、uboot的配置与编译1、uboot配置2、uboot编译 前言:本篇主要介绍uboot的一些结构与相关配置,uboot是一款免费开源的芯片启动软件,代码完全开源&a…

uboot移植过程

uboot移植过程 IMX6ULL 文章目录 uboot移植过程 IMX6ULL 前言一、从原厂中移植uboot进行测试二、在U-Boot中添加自己的硬件1. 添加默认配置文件2. 添加对应的头文件3. 添加对应的板级文件夹3.1 修改Makefile文件3.2 修改 mx6ull_alientek 目录下的 imximage.cfg 文件3.3 修改 m…

MediaCodec对接到OMX的简单分析

一、引言: nuplayer播放器是使用MediaCodec来进行编解码的,而OMX组件则是MediaCodec的解码核心,但是因为涉及的面太过底层,往往是芯片公司才会涉及到这一块,所以就做一个简单分析,对通路有个大致了解就行。…

MediaCodec(native)状态机分析

一、引入: MediaCodec这条通路的调用逻辑是MediaCode->ACodec->OMX,因为OMX有自己的状态机,所以MediaCodec和ACodec也分别基于OMX组件的调用维护了其状态机,这篇博客就先分析MediaCodec的状态机是如何运转的。 二、MediaCo…