uboot之do_bootm_linux启动内核函数源码解析

news2026/3/20 16:37:38
当配置了CONFIG_PPC时将调用common/cmd_bootm.c中的do_bootm_linux。本处是调用libarm/armlinux.c中的。u-boot.h中static struct tagparams;typedef struct bd_info {int bi_baudrate; /serial console baudrate/波特率unsigned long bi_ip_addr; /IP Address/即服务器IP地址unsigned char bi_enetaddr[6]; /Ethernet adress */struct environment_sbi_env;//开发板机器ID即1008(MACH_TYPE_SMDK2440)gd-bd-bi_arch_number MACH_TYPE_SMDK2440; (smdk2440.c)ulong bi_arch_number; /unique id for this board///准确地说这是启动参数的地址gd-bd-bi_boot_params 0x30000100;(smdk2440.c)与内核中需要一致。ulong bi_boot_params; /where this board expects params/准确地说,这是启动参数的地址struct /RAM configuration/{ulong start;//内存起始地址ulong size;//内存大小} bi_dram[CONFIG_NR_DRAM_BANKS];#ifdef CONFIG_HAS_ETH1/second onboard ethernet port */unsigned char bi_enet1addr[6];#endif} bd_t;在u-boot下输入bd就可以查看开发板的一些信息uplooking # bdarch_number 0x0000065Aenv_t 0x00000000boot_params 0x50000100DRAM bank 0x00000000- start 0x50000000- size 0x08000000ethaddr 00:40:5C:26:0A:5Bip_addr 192.168.1.20baudrate 115200 bps///////////////////////////////////////////////////////////////////////////////////////command.h/*Monitor Command Table*/struct cmd_tbl_s {charname; /Command Name//命令名/int maxargs; /maximum number of arguments//命令的最大参数个数/int repeatable; /autorepeat allowed?//是否自动重复//Implementation function */int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);/命令执行函数/charusage; /Usage message (short) */ /简单的使用说明/#ifdef CFG_LONGHELPcharhelp; /Help message (long)/ /详细使用说明/#endif#ifdef CONFIG_AUTO_COMPLETE /自动补全参数//do auto completion on the arguments */int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);#endif};在文件include/command.h中定义了结构体cmd_tbl_s各成员含义如上面注释。U-boot的每一条命令都将封装成结构体 cmd_tbl_s存到链接文件中指定的.u_boot_cmd区。当向u-boot中添加命令时都将调用宏 U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)来初始化一个cmd_tbl_s 结构体。typedef struct cmd_tbl_s cmd_tbl_t;////////////////////////////////////////////////////////////////////////////当定义了CONFIG_PPC时将使用common/cmd_bootm.c文件中的do_bootm_linux函数当系统中没有定义该宏时系统将使用lib_arm/armlinux.c文件中定义的do_bootm_linux函数。注意这两个函数有很大的区别void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],ulong addr, ulong *len_ptr, int verify){ulong len 0, checksum;ulong initrd_start, initrd_end;ulong data;void (theKernel)(int zero, int arch, uint params);image_header_thdr header;bd_tbd gd-bd;#ifdef CONFIG_CMDLINE_TAGcharcommandline getenv (“bootargs”);//调用了getenv将bootargs环境变量保存在commandline#endif//uboot set参数命令行bootm 50008000;//打印出来发现 hdr-ih_ep 0x800050 也就是必须ntohl之后才是50008000theKernel (void ()(int, int, uint))ntohl(hdr-ih_ep);//打印出来发现theKernel 0x50008000//设置内核入口地址(不是加载地址加载是程序存储地址)入口地址是PC指针倒是后程序跳到这个地址运行//mkimage.c//#define ntohl(a) SWAP_LONG(a)//#define htonl(a) SWAP_LONG(a)/#define SWAP_LONG(x)((__u32)((((__u32)(x) (__u32)0x000000ffUL) 24) |(((__u32)(x) (__u32)0x0000ff00UL) 8) |(((__u32)(x) (__u32)0x00ff0000UL) 8) |(((__u32)(x) (__u32)0xff000000UL) 24) ))***//Check if there is an initrd image //跳过 不是initrd镜像/if (argc 3) {addr simple_strtoul (argv[2], NULL, 16);printf (“## Loading Ramdisk Image at %08lx …\n”, addr);/Copy header so we can blank CRC field for re-calculation */#ifdef CONFIG_HAS_DATAFLASHif (addr_dataflash (addr)) {read_dataflash (addr, sizeof (image_header_t), (char *) header);}else#endifmemcpy (header, (char *) addr, sizeof (image_header_t));if (ntohl (hdr-ih_magic) ! IH_MAGIC) {printf (“Bad Magic Number\n”);do_reset (cmdtp, flag, argc, argv);}data (ulong) header;len sizeof (image_header_t);checksum ntohl (hdr-ih_hcrc);hdr-ih_hcrc 0;if (crc32 (0, (unsigned char) data, len) ! checksum) {printf (“Bad Header Checksum\n”);do_reset (cmdtp, flag, argc, argv);}print_image_hdr (hdr);data addr sizeof (image_header_t);len ntohl (hdr-ih_size);#ifdef CONFIG_HAS_DATAFLASHif (addr_dataflash (addr)) {read_dataflash (data, len, (char) CFG_LOAD_ADDR);data CFG_LOAD_ADDR;}#endif/**do_bootm函数中** s getenv (“verify”);verify (s (*s ‘n’)) ? 0 : 1;//为是否对镜像头做校验做准备读取uboot的环境变量verify如果环境变量verify等于’n’则局部变量verify赋值成为0如果环境变量verify为空即没有定义环境变量verify或者环境变量verify不等于’n’则局部变量verify赋值成为1。****/if (verify) {ulong csum 0;printf ( Verifying Checksum … );csum crc32 (0, (unsigned char) data, len);if (csum ! ntohl (hdr-ih_dcrc)) {printf (“Bad Data CRC\n”);do_reset (cmdtp, flag, argc, argv);}printf (“OK\n”);}if ((hdr-ih_os ! IH_OS_LINUX) || (hdr-ih_arch ! IH_CPU_ARM) || (hdr-ih_type ! IH_TYPE_RAMDISK)) {printf (“No Linux ARM Ramdisk Image\n”);do_reset (cmdtp, flag, argc, argv);}#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)/*we need to copy the ramdisk to SRAM to let Linux boot*/memmove ((void *) ntohl(hdr-ih_load), (uchar *)data, len);//与上文的memcpy (header, (char) addr, sizeof (image_header_t));区别data ntohl(hdr-ih_load);#endif /CONFIG_B2 || CONFIG_EVB4510//Now check if we have a multifile image/} //end of if (argc 3) {else if ((hdr-ih_type IH_TYPE_MULTI) (len_ptr[1])) {ulong tail ntohl (len_ptr[0]) % 4;int i;/skip kernel length and terminator/data (ulong) (len_ptr[2]);/skip any additional image length fields/for (i 1; len_ptr[i]; i)data 4;/add kernel length, and align/data ntohl (len_ptr[0]);if (tail) {data 4 - tail;}len ntohl (len_ptr[1]);}else {/no initrd image*/len data 0;}#ifdef DEBUGif (!data) {printf (“No initrd\n”);}#endifif (data) {initrd_start data;initrd_end initrd_start len;} else {initrd_start 0;initrd_end 0;}debug (“## Transferring control to Linux (at address %08lx) …\n”,(ulong) theKernel);#if defined (CONFIG_SETUP_MEMORY_TAGS) ||defined (CONFIG_CMDLINE_TAG) ||defined (CONFIG_INITRD_TAG) ||defined (CONFIG_SERIAL_TAG) ||defined (CONFIG_REVISION_TAG) ||defined (CONFIG_LCD) ||defined (CONFIG_VFD)setup_start_tag (bd);#ifdef CONFIG_SERIAL_TAGsetup_serial_tag (?ms);#endif#ifdef CONFIG_REVISION_TAGsetup_revision_tag (?ms);#endif#ifdef CONFIG_SETUP_MEMORY_TAGSsetup_memory_tags (bd);#endif#ifdef CONFIG_CMDLINE_TAGsetup_commandline_tag (bd, commandline); //设置启动命令行tags#endif#ifdef CONFIG_INITRD_TAGif (initrd_start initrd_end)setup_initrd_tag (bd, initrd_start, initrd_end);#endif#if defined (CONFIG_VFD) || defined (CONFIG_LCD)setup_videolfb_tag ((gd_t) gd);#endifsetup_end_tag (bd);#endif/we assume that the kernel is in place */printf (“\nStarting kernel …\n\n”);#ifdef CONFIG_USB_DEVICE{extern void udc_disconnect (void);udc_disconnect ();}#endifcleanup_before_linux ();//传递的参数//R0必须为0 //R1机器类型ID 本机为ARMbd- bi_arch_number//R2:启动参数列表在内存中的位置bd- bi_boot_paramstheKernel (0, bd-bi_arch_number, bd-bi_boot_params);//嵌入式linux应用开发P264 bd-bi_boot_params就是标记列表的开始地址。}///image.h/*all data in network byte order (aka natural aka bigendian)/typedef struct image_header {uint32_t ih_magic; /Image Header Magic Number/ /镜像幻数/uint32_t ih_hcrc; /Image Header CRC Checksum/ /镜像头CRC校验值*/uint32_t ih_time; /* Image Creation Timestamp/ /镜像创建时间*/uint32_t ih_size; /* Image Data Size//镜像大小*/uint32_t ih_load; /* Data Load Address//数据加载地址*/uint32_t ih_ep; /* Entry Point Address/ //theKernel函数指针指向这个地址也就是从uboot跳到内核的地址,镜像入口*/uint32_t ih_dcrc; /* Image Data CRC Checksum/ /镜像数据区的CRC校验值*/uint8_t ih_os; /* Operating System//操作系统类型*/uint8_t ih_arch; /* CPU architecture//CPU架构*/uint8_t ih_type; /* Image Type/ /镜像类型*/uint8_t ih_comp; /* Compression Type/ /压缩类型*/uint8_t ih_name[IH_NMLEN]; /* Image Name//镜像名*/} image_header_t;Linux编译出的二进制文件是zImageuboot中提供mkimage工具可将zImage制作成uImage实际上就是在zImage前加一个image_header头。制作uImage的命令如下。./mkimage -n ‘linux-2.6.36’ -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.binMkimage工具参数的含义如下-A 设置体系架构类型-O 设置操作系统类型-T 设置镜像类型-C 设置压缩类型-a 设置加载地址-e 设置镜像入口位置-n 设置镜像名-d 设置生成最终镜像所需的文件-x 设置片上执行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2430484.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…