热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ARM板移植Linux系统启动(四)配置Kernel

如今的Linux比uboot要成熟得更多,所有的模块都是可配置的。所以基本上对于kernel的移植,特别是这种已经有基础源码的项目,代码改动其实相当少,更多是时间花在调试和配置上。


如今的Linux比uboot要成熟得更多,所有的模块都是可配置的。所以基本上对于kernel的移植,特别是这种已经有基础源码的项目,代码改动其实相当少,更多是时间花在调试和配置上。在所有工作中,最主要的困难恐怕就是怎么把系统跑进console了。


uImage & zImage



这个问题太基础,只是因为跟手动跑系统有关,所以稍微提一下。kernel编译后的成果是zImage,uImage只是添加了一个长度为0x40的头,用来记录给uboot的相关信息。虽然uImage是专门给uboot用的,但uboot的启动并不一定要uImage,它既可以接受uImage也可以接受zImage。可以说:uImage的头信息本质上是一种启动参数的传递形式。


制作uImage的工具是 mkimage ,它是来自于uboot。为了避免各种可能的版本问题,建议直接使用uboot编译后的 uboot/tools/mkimage 。而uImage的制作脚本则包含在kernel的编译脚本中,使用命令:


make uImage LOADADDR=0x80008000


即可编译获得uImage,前提是你已经将mkimage放入了编译环境的/bin/文件夹下。LOADADDR是kernel的启动地址( 注意,这不是真正的kernel运行地址 ),uBoot会将kernel拷贝到此地址后(实际中也可能不拷贝)执行。关于uboot使用的几个内存地址的具体讲解也很多,这么些年也没什么变化,需要了解的可以自行去搜索。



根文件系统的制作


一个系统必须要有文件系统才能跑起来,即使是很小很小的文件系统。目前一个最基本的文件系统都是基于Busybox制作的,制作过程的教程很多也大同小异,我就不赘述了。有的厂商或者Linux系统发行商也会提供根文件系统的下载,不过大多太过冗余,需要自行裁剪。


你看到的是非授权版本!爬虫凶猛,请尊重知识产权!


转载请注明出处:http://conanwhf.coding.me/2017/06/12/bootup-4-kernel/


访问原文「 ARM板移植Linux系统启动(四)配置Kernel 」获取最佳阅读体验并参与讨论


对于一块空板子,通常的做法是用一个能进入命令行的最小文件系统,然后将完整的文件系统和kernel等烧写到存储设备上。所以如何做一个能够启动的最小系统,就成了第一个步骤。由于这种最小系统启动时还不会用到存储装置(emmc or nand flash),文件系统是跑在RAM里的,有两种做法:将其包含在Kernel的镜像中,或者用uboot加载到内存后告诉kernel加载的内存地址。


带Ramdisk的Kernel镜像



menuconfig里面配置kernel:


General setup —> 选中Initial RAM filesystem and RAM disk (initramfs/initrd) support,将()Initramfs source file(s)填写为准备好的根文件系统路径



保存,编译后即可。



U-boot支持的rootfs镜像


另一种方法是使用单独的根文件系统镜像,这样不需要重新编译kernel,只需要把数据重新打包即可。



  1. 生成空白Image,可以稍微预留大一点,全0数据压缩后可以忽略:

    dd if=/dev/zero of=TEMP bs=1M count=5


  2. 将image挂载为loop文件系统

    losetup /dev/loop0 TEMP
    sudo mke2fs -m 0 /dev/loop0
    mkdir -p loop
    sudo mount -t ext2 /dev/loop0 loop


  3. 将数据copy到挂载后的image中,然后卸载:

    sudo cp -raf initramfs/* loop
    sudo umount loop; rm -rf loop


  4. 压缩并制作成img:

    gzip -v9 TEMP
    mkimage -n 'YOUR_MARK ext2 uboot ramdisk' -A arm -O linux -T ramdisk -C gzip -d TEMP.gz ramdisk.img

    这里的mkimage就是上文提到的来自于uboot的工具,它同样也只是将已有的文件加了一个uboot可以识别的头信息。注意这里的 -A arm 必须和kernel的目标平台相对应,否则uboot会拒绝引导。



DTS(Device Tree Source)


在老的内核版本中,关于硬件的定义、配置和描述都是通过各种头文件和 #define 来实现的,而在新的内核中已经全部使用了DTS来描述硬件信息,从而实现了更加灵活的硬件支持和配置。DTS中的“硬件描述”,准确地说是设备描述,包括所有的硬件设备和软件设备节点,从CPU到外设,从型号描述到地址定义,具体到设备节点到硬件的链接等等,都可以定义。


DTS的具体表达文件是 *.dtb ,它们是由一组遵循特定语法的dts源文件编译而成,放在 arch/$PLATFORM/boot/dts 下,对于arm板来说就是 arch/arm/boot/dts/ 。这个文件夹底下的文件有点像config file,每个 *.dts 文件对应一种配置,而dts文件又可以通过include某些 $SLICON.dtsi 来作为配置的基础,在此基础上添加、覆盖原有内容。一个dts一般只对应一种板子,但同一块板子可以使用几种不同的dts,例如可以通过指定不同的dtb文件,来选择启动时将HDMI还是LCD屏作为标准输出(lcdc0)。以BeagleBoneBlack举例,它的基本启动配置是am335x-boneblack.dts,而它又inlcude了am33xx.dtsi, am335x-bone-common.dtsi, am33xx-pruss-rproc.dtsi等文件。


查找编译所对应的dts file,可以查看 arch/arm/boot/dts/Makefile ,看看kernel config里定义的 CONFIG_SOC_XXX 所对应编译出来的dtb文件。一般来说一个芯片下有好几个dtb文件,它们就是对应了不同的应用场景,需要根据需要选择一个来作为启动配置。如果需要添加自己的dts文件,除了新建一个dts文件以外,还要记得在这个Makefile中把自己的target dtb添加进去。


关于DTS设备定义的语法,也不是这篇文章的重点,请允许我跳过。


使用DTS启动系统


之前我并没有使用过DTS,对它也只有耳闻,所以开始移植的时候并没有想到这个部分。做好了kernel在uboot中手动引导启动后,我发现系统停在了 Starting kernel ... 这样的打印信息之后。经过搜索资料,我发现很有可能是因为uboot和kernel的机器号(Mechine ID)不匹配,为了确定这个问题,我在kernel config中打开low-level的调试选项:


Kernel hacking —>


|- (X) Kernel low-level debugging functions (read help!)


-|— Kernel low-level debugging port (Kernel low-level debugging… —>


—- |- ( ) Kernel low-level debugging messages via OMAP36XX UART4


—- |- ( ) Kernel low-level debugging messages via OMAP4/5 UART4


—- |- ( ) Kernel low-level debugging messages via TI81XX UART1


—- |- ( ) Kernel low-level debugging messages via TI81XX UART2


—- |- ( ) Kernel low-level debugging messages via TI81XX UART3


—- |- (X) Kernel low-level debugging messages via AM33XX UART1


|- (X) Early printk


记得选对UART驱动,不然是看不到打印的。这个驱动不是在kernel的drivers里面配置对了就可以的,driver里面的驱动要等基本的项目初始化后才会跑,这里指的是提前初始化UART以提供打印的驱动程序。


然后再次尝试,看打印信息果然是这个原因,但奇怪的是,在aviliable mechine的list里面,只有一个0xFFFFFFFF的mechine ID。我跟踪了很久的kernel和uboot代码,还是对此一筹莫展,直到再次搜索了类似的情况,发现有人说使用新版本的kernel才会出现这种情况,才想到了是没有使用DTS的原因。


于是我添加了对dts文件的地址指定:


fatload usb 0:1 0x82000000 am335x-boneblack.dtb
fatload usb 0:1 0x83000000 uImage
bootm 0x83000000 - 0x82000000

这次uboot将dtb加载并传递了地址给kernel,kernel能够看到所需要的各种初始化信息,终于顺利地将系统跑了起来。


编译后的文件location


至此,系统已经能够跑进console,剩下的就是引导和烧写问题了。编译后的相关文件location如下,在制作文件系统时需要将它们更新至软件包中:



  • kernel: ./boot/zImage

  • dts: ./boot/dst/XXX.dtb

  • firmware: ./lib/firmware/

  • module:/lib/modules/$KERNEL_VERSION




推荐阅读
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
author-avatar
吴台吉国瑋智仁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有