Linux主机上使用交叉编译移植u-boot到树莓派

0环境

Linux主机OS:Ubuntu14.04 64位,运行在wmware workstation 10虚拟机

树莓派版本:raspberry pi 2 B型.

树莓派OS: Debian Jessie  Raspbian Jessie

1树莓派的启动过程

树莓派1,2,3的启动过程大致相同,主要分为3个阶段:ROM上的GPU bootloader启动GPU,GPU启动CPU,CPU直接启动内核或通过u-boot启动内核.

由于树莓派涉及到GPU的东西不开源,移植u-boot到树莓派并不是真正意义上的bootloader,但是鉴于u-boot广泛的应用,还是很有学习的必要

树莓派启动过程:

HOW THE RASPBERRY PI BOOTS UP

树莓派3启动过程概述

RPi Software

2移植u-boot到Debian Jessie系统

最初想直接移植u-boot到Raspbian,尝试了多次都失败告终.google上u-boot启动raspberry pi大都是基于Debian Jessie,所以先照葫芦画瓢试一把.

移植u-boot到树莓派参考例程

(1)最全面的RPi u-boot例程RPi U-Boot

(2)基于RPi2的例程Booting a Raspberry Pi2, with u-boot and HYP enabled

(3)基于RPi2,提供现成文件的例程Raspberry Pi 2 – Debian Jessie and U-Boot

(4)基于mainline u-boot的例程How to compile mainline u-boot for Raspberry Pi ?

MicroSD卡烧写镜像:debian jessie下载地址

Ubuntu主机上u-boot使用Mainline版本,官网源码 亚马逊下载地址

Ubuntu主机上文件位置如下

家目录(/root)下u-boot-2016.09文件夹是解压后的u-boot

家目录(/root)下script_u-boot文件夹是自己写的环境配置,脚本

u-boot-2016.09文件夹如下,可以先读读README

script_u-boot文件夹内如下图,从左到右是scr配置文件,环境配置文件,生成u-boot.bin文件,生成scr文件

env_gnueabihf_mkimage文件代码如下

#添加树莓派的交叉编译工具链路径(主机是64位)export PATH=$PATH:/root/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

#指定编译目标架构为arm,编译器为PATH路径中的交叉编译器export ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

树莓派交叉编译工具链地址https://github.com/raspberrypi/tools

树莓派交叉编译可以参考Linux主机上实现树莓派的交叉编译及文件传输,远程登陆

在后续操作之前先source一下这个文件使配置生效,关闭终端或者重新登陆Ubuntu需要再次source

用echo查看变量,注意使用tab自动补全路径

make_ubootbin文件代码如下

#从脚本文件夹切换到u-boot文件夹下
cd /root/u-boot-2016.09

#配置适用于树莓派2的u-boot
make rpi_2_defconfig

#编译
make all
#返回脚本文件夹
cd /root/script_u-boot

切换路径是因为执行这个脚本是在script_u-boot文件夹,而make命令执行Makefile是在u-boot-2016.09文件夹,最后切回路径方便后续的source

这里make rpi_2_defconfig是针对树莓派2板,其它版本树莓派的make config参考前文的移植u-boot到树莓派参考例程(1)(4)

执行make_ubootbin无报错

在u-boot-2016.09文件夹下生成了u-boot.bin

把debian jessie的SD卡通过读卡器插到电脑,注意先选中虚拟机的Ubuntu系统,Ubuntu会自动读取(mount)SD卡

rootfs(根文件系统)分区:

firmware(debian jessie下的启动分区):

关于启动分区config.txt bootcode.bin cmdline.txt start.elf kernel7.img等文件,参考前文的树莓派启动过程

至此可以把u-boot.bin拷到sd卡的firmware(对于debian jessie系统)

然后在config.txt添加

kernel=u-boot.bin

指定用u-boot.bin启动内核kernel7,config.txt是内核的配置文件,类似电脑的BIOS配置

配置内核的方法:

一种方法是在u-boot阶段手动输入命令,而mainline版本的u-boot不支持usb输入,尝试过例程(1)中的Stephen Warren版本,也无法输入(问题还有待调查)

另一种是把u-boot中输入的命令写到一个脚本文件,通过mkimage命令将这个脚本生成.scr镜像,然后放到启动分区,u-boot会自动读取脚本来启动内核,这样更简单更容易修改,但是不利于调试错误信息

用第一种方法可以拔出SD卡,在树莓派上配置内核启动,注意在u-boot阶段只能通过HDMI外接显示屏或者串口来查看输出信息.关于串口可以参考RPi Serial Connection

用第二种方法是在Ubuntu主机上生成boot.scr镜像,先写一个配置文件:在script_u-boot文件夹下新建configure_scr_file,内容如下

#设置环境为树莓派2
setenv machid 0x00000c42
#设置打印信息,允许HDMI,允许串口,设置根文件系统路径和类型
setenv bootargs "earlyprintk console=tty0 console=ttyAMA0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait noinitrd"
#保存环境配置
saveenv
#载入内核镜像到MMC0的第一分区
fatload mmc 0:1 ${kernel_addr_r} kernel7.img
#启动内核
bootz ${kernel_addr_r} 

以上命令的语法都是u-boot软件规定,关于命令的细节可以参考RPi U-Boot   官方文档U-Bootdoc

然后新建一个脚本make_ubootscr生成scr镜像,make_ubootscr内容如下

#生成boot.scr镜像文件
mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /path/to/script /boot/firmware/boot.scr

/path/to/script是configure_scr_file的路径,替换后如下

mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /root/script_u-boot/configure_scr_file /boot/firmware/boot.scr

source报错,提示未安装mkimage

命令找不到通常是未安装软件,或者没添加路径,mkimage应该是包含在u-boot软件中的,由于之前用过树莓派交叉编译工具链的经验,在u-boot-2016.09文件夹的tools文件夹找到了mkimage程序

更通用的是用find命令查找

find 查找路径 -name 文件名

看来是没有添加mkimage的路径到环境变量,只需在env_gnueabihf_mkimage添加路径然后source

env_gnueabihf_mkimage修改如下

export PATH=$PATH:/root/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:/root/u-boot-2016.09/tools

export ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

提示路径不存在

这时就需要了解这条mkimage命令的具体含义了,参考mkimage - Generate image for U-Boot

/boot/firmware/boot.scr是生成boot.scr文件的路径,如果在树莓派上直接操作这个路径就是启动分区,但是我是在Ubuntu主机操作,SD卡是挂载到Ubuntu主机的路径被改变了

查看块设备可以用命令

lsblk

sdb就是SD卡,sdb1是firmware启动分区,sdb2是rootfs文件系统分区

事实上插入SD卡时Ubuntu自动把SD卡mount到了主机的/media路径,所以前面才能对u-boot.bin直接复制粘贴操作

但是想把SD卡的第一分区挂载到其它路径,比如主机的/mnt文件夹下,应该

mount /dev/sdb1 /mnt

注意设备的实际路径和挂载后路径的区别,/dev/xxx才是实际的设备路径

在debian jessie的树莓派上查看SD卡路径如下

这是因为debian jessie没有自动挂载功能

可以把boot.scr直接生成到firmware下(先在Ubuntu插好SD卡)

mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /root/script_u-boot/configure_scr_file /media/boot/firmware/boot.scr

更推荐生成在其它目录(比如u-boot-2016.09文件夹)再拷到SD卡,最终改为如下,-n是生成的文件名

mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n boot.scr -d /root/script_u-boot/configure_scr_file /root/u-boot-2016.09/boot.scr

成功生成boot.scr

在把u-boot.bin boot.scr拷到SD卡的firmware以后,确认config.txt添加了kernel=u-boot.bin就可以拔出SD卡启动树莓派2了

启动过程如下

进入登陆界面

登陆名(login):root

密码(password):debian

登录成功,至此在debian jessie上的u-boot移植完成

在主机上交叉编译生成boot.bin,也可以不添加环境变量ARCH,CROSS_COMPILE,直接在make语句指定编译器

make_ubootbin可以改为如下

cd /root/u-boot-2016.09
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- rpi_2_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4
cd /root/script_u-boot
-j4是采用四核处理器四线程编译,取决于主机CPU WIN7下查看CPU核心数

3移植u-boot到Raspbian Jessie系统

有了前面的尝试,后面的就水到渠成了

如果直接把刚才生成的u-boot.bin boot.scr拷到raspbian,在config.txt添加kernel=u-boot.bin

启动后停留在starting kernel...

信息显示kernel7已经通过boot.scr读取了,说明问题出在启动内核之后的部分

对比一下debian jessie和raspbian jessie的分区,文件系统都一样,就是启动分区有差别

debian jessie的启动分区

raspbian jessie的启动分区

发现raspbian多了一个kernel.img,几个.dtb文件,overlay里面也是.dtb文件

参考RPi U-Boot后感觉需要加载dtb(Device Tree binary)

修改boot.scr的配置文件(configure_scr_file)的内容如下

setenv machid 0x00000c42
#添加变量fdtfile的值为bcm2709-rpi-2-b.dtb
setenv fdtfile bcm2709-rpi-2-b.dtb
setenv bootargs "earlyprintk console=tty0 console=ttyAMA0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait noinitrd"
saveenv
fatload mmc 0:1 ${kernel_addr_r} kernel7.img
#载入fdtfile的值
fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}
bootz ${kernel_addr_r} - ${fdt_addr_r}

这里添加bcm2709-rpi-2-b.dtb是因为使用树莓派2,如果是其它版本酌情修改

然后source生成boot.scr

source make_ubootbin

将新的boot.scr拷到boot分区,u-boot.bin和之前完全相同,config.txt添加kernel=u-boot.bin

主机上拔出SD卡,启动树莓派

自动登录进入桌面

至此u-boot在raspbian jessie上移植完成

时间: 2024-08-08 01:28:08

Linux主机上使用交叉编译移植u-boot到树莓派的相关文章

LINUX主机上交叉编译树莓派详细教程

LINUX主机OS:Ubuntu14.04 64位,运行在wmware workstation 10上. 树莓派版本:raspberry pi 2 B型. 树莓派OS:官网下的的raspbian-jessie. 1.为什么需要交叉编译 在Ubuntu上直接编译一个.c源文件可以用系统自带的gcc编译器编译test.c gcc test.c -o test 然后执行生成的二进制文件 ./test 交叉编译就是把编译的过程在LINUX PC(或其它主机)上执行,然后拷贝二进制可执行文件到树莓派(或其

如何在linux主机上运行/调试 arm/mips架构的binary

如何在linux主机上运行/调试 arm/mips架构的binary 原文链接[email protected]0.0.0.55 本文中用于展示的binary分别来自Jarvis OJ上pwn的add,typo两道题 写这篇教程的主要目的是因为最近想搞其他系统架构的pwn,因此第一步就是搭建环境了,网上搜索了一波,发现很多教程都是需要树莓派,芯片等硬件,然后自己编译gdb,后来实践的过程中发现可以很简单地使用qemu实现运行和调试异架构binary,因此在这里分享一下我的方法. 主机信息: 以一

linux主机上编译安装rpcapd实现wireshark远程抓包功能

使用wireshark在远程linux系统抓包 简介 由于在做分布式HLR时,需要一边测试,一边抓取信令消息,而现在分布式HLR的系统都是采用linux,抓包可以使用tcpdump工具,不过感觉不是很方便.正好,之前的测试的同事,已经实现了使用笔记本上的wireshark远程抓包,而我以前对此没有做过了解,不是很懂,抽空在网上查了查资料,大概屡清楚了实现方法.实现远程抓包,主要借助winpacp这个软件中的rpcapd工具,这里就对在linux下的rpcapd工具的安装,使用和windows下的

Xftp工具连接到远程linux主机上传下载

linux上传下载文件有很多种方法,比较简单的安装lrzsz工具,使用rz上传,sz下载: 使用方法参考之前的博文:http://mofansheng.blog.51cto.com/8792265/1653048 下面介绍另一种windows本地连接到linux主机,上传下载的工具xftp: Xftp是一款连接linux服务器的ftp传送工具,支持FTP和SFTP 协议,支持多标签会话窗口.关键是免费,使用也很简单,支持拖放,类Shell管理模式,相当方便. Xftp是Xshell组件的一部分,

Linux主机上通过iptables实现NAT功能

实验:如下模型,node1为内网主机,IP地址为192.168.10.2:node3为外网主机,IP地址为10.72.37.177(假设此地址为公网地址),node3上提供web server和FTP Server的功能:内网主机node2主机有2块网卡,地址分别为eth0:192.168.10.1和eth2:10.72.37.91(假设此地址为公网地址): 现要求在node2上通过iptables配置实现SNAT功能,并做如下限制: 1.node1可以访问node3提供的web服务和ftp服务

Linux主机上用户的信息传递

(整理自<鸟哥的linux私房菜>基础篇) 1.查询使用者: w, who, last, lastlog 如果我们想要知道使用者到底啥时候登入的时候,或者其他详细的信息时,我们可以使用last命令,那如果你想要知道目前已登入在系统上面的用户呢?我们可以使用w或者who命令: 另外,如果您想要知道每个账号的最近登入的时间,则可以使用 lastlog 这个指令 lastlog 会去读取 /var/log/lastlog 文件,结果将数据输出如下表: 2.使用者对谈: write, mesg, wa

linux 主机上出现输入正确的账号和密码,无法登陆,如何操作

事情发生的背景:linux 虚拟机,在vmware那打开,输入账号和密码不得登陆,但是用其他的终端设备连入又可以顺利打开. 1.对事情进行排查,终端上使用命令,然后vmware 那进行登陆,查看日志tail -f /var/log/secure Mar 14 11:05:06 testOpenfire login: PAM unable to dlopen(/lib/security/pam_limits.so): /lib/security/pam_limits.so: cannot open

windows上配置rsync服务器收集linux主机巡检报告

客户这里,有很多linux主机,都是centos7的,我们需要定期每天对linux主机进行巡检,然后把巡检结果集中保存,方便对主机状态检查.为了巡检工作需要,需要在linux主机上编写巡检脚本,配置rsync客户端.. linux巡检脚本 我收集了一个巡检脚本,如下所示: #!bin/bash #主机信息每日巡检 IPADDR=$(ifconfig eth0 | grep '\<inet\>' | awk '{print $2}') #环境变量PATH没设好,在cron里执行时有很多命令会找不

Linux主机实现简单的路由转发功能

只要在Linux主机上添加一些简单的路由条目, 这些Linux主机就可以充当简单路由器的功能. 在实际生产坏境中, 当我们需要一台路由器简单作为转发数据, 但是手上却没有路由器的话, 我们就可以指定一台Linux主机充当一个简单的路由器,实现路由简单的转发. 上面所诉尤其强调简单, 所以说只是实现简单的路由的功能, 如果要实现非常复杂的功能的话, 一台Linux主机可能无法实现你想要的条件. 实验坏境: 基于VMware上的4台虚拟主机,主机名为R1.R2的两台主机(都是centos6.8系统)