硬件:
-核心板:Tiny4412 - 1412
-底板: Tiny4412/Super4412SDK 1506
软件:
-移植uboot版本: u-boot-2017.05.tar.bz2
-工具链:arm-linux-gcc 4.5.1
工具链就不介绍如何安装了。
新版的UBOOT增加了SPL的支持。
SPL:Secondary Program Loader,第二阶段程序加载器(其实就相当于uboot的第一阶段,只不过单独编译成一个文件了)。编译u-boot-spl.bin复用的是u-boot的代码。通过宏定义CONFIG_SPL_BUILD进行条件编译,当然有一些函数虽然名字相同,但是调用的不同源文件里的函数,比如init_board_f(),后面再继续说。
我们要移植的处理器为三星公司的exynos4412。所以我到board/samsung/找到一款基于exynos4xxx(4412、4210)的处理器进行移植。在/board/samsung目录下基于exynos4xxx的开发板有:origen、odroid、trats、trats2,smdkv310。origen和smdkv310支持spl配置,这里笔者选择了origen进行移植。
首先
#make clean
#make distclean
然后
#grep “origen” * -nR
#grep “ORIGEN” * -nR
搜索,哪些文件跟origen相关
然后依葫芦画瓢。复制,粘贴, 修改。将origen修改为tiny4412,ORIGEN修改为TINY4412。
(注:mach-types.h这个文件是自动生成的,不需要修改。在include/configs/tiny4412.h:#define CONFIG_MACH_TYPE MACH_TYPE_TINY4412后就会自动生成编号)
拷贝,修改之后
#make tiny4412_defconfig
#make ARCH=arm CROSS_COMPILE=arm-linux- V=1 -j8
(V=1:表示显示编译详细信息。 -j8:笔者电脑是四核八线程,加该选项为了提高编译速度)
如果修改正确,此时是可以编译通过,如果不能编译通过,请检查,是否有文件遗漏未修改。
编译通过后在根目录生成
u-boot.bin(完整的uboot)
spl目录生成
u-boot-spl.bin(SPL)
当然,此时的镜像文件,烧写到SD是没有反应的,还需要做相应的修改。
(参考:Android_Exynos4412_iROM_Secure_Booting_Guide_Ver.1.00.00.pdf)
官方提供了BL1文件(E4412_N.bl1.bin),所以我们就将SPL镜像制作成BL2。(当然也可以不使用官方的BL1文件,将SPL镜像制作成BL1,为了简单,方便,笔者选择使用了官方的BL1)如果对启动流程不是很清楚的话请查看笔者的另一篇文章:《exynos4412启动流程》。
该片内内存映射反应了,BL2主要为主体+校验和+签名。在官方文档中有描述,BL2的签名已经写在BL1中,所以制作BL2不需要加签名,校验为前(14*1024-4)字节的校验和,并将校验和写在(14*1024-4)地址处,即完成BL2制作。
制作BL2的源码为/u-boot-2017.05/board/samsung/tiny4412/tools/mktiny4412spl.c(其实是复制mkorigenspl.c)
#include
#include
#include
#include
#include
#include
#include
/*
* no make BL1,so don't need add header
*/
#define BUFSIZE (16*1024)
#define IMG_SIZE ((14*1024)-4)
#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP \
| S_IWGRP | S_IROTH | S_IWOTH)
/*
* Requirement:
* IROM code reads first 14K bytes from boot device.
* It then calculates the checksum of 14K-4 bytes and compare with data at
* 14K-4 offset.
*
* This function takes two filenames:
* IN "u-boot-spl.bin" and
* OUT "$(BOARD)-spl.bin as filenames.
* It reads the "u-boot-spl.bin" in 16K buffer.
* It calculates checksum of 14K-4 Bytes and stores at 14K-4 offset in buffer.
* It writes the buffer to "$(BOARD)-spl.bin" file.
*/
/* in /scripts/Makefile.spl 274line在该Makefile会调用该工具制作BL2。
- argc = 3
- mktiny4412spl $(obj)/u-boot-spl.bin $(obj)/$(BOARD)-spl.bin
- argv[0] argv[1] argv[2]
*/
int main(int argc, char **argv)
{
int i, len;
unsigned char buffer[BUFSIZE] = {0};
int ifd, ofd;
unsigned int checksum = 0, count;
if (argc != 3) {
printf(" %d Wrong number of arguments\n", argc);
exit(EXIT_FAILURE);
}
ifd = open(argv[1], O_RDONLY);//open inputfile
if (ifd < 0) {
fprintf(stderr, "%s: Can't open %s: %s\n",
argv[0], argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
ofd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM);//open output file ,if no exist,creat
if (ofd < 0) {
fprintf(stderr, "%s: Can't open %s: %s\n",
argv[0], argv[2], strerror(errno));
if (ifd)
close(ifd);
exit(EXIT_FAILURE);
}
len = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
count = (len < IMG_SIZE)? (len) : (IMG_SIZE); //read 1024*14-4
if (read(ifd, buffer, count) != count) {
fprintf(stderr, "%s: Can't read %s: %s\n",
argv[0], argv[1], strerror(errno));
if (ifd)
close(ifd);
if (ofd)
close(ofd);
exit(EXIT_FAILURE);
}
for (i = 0; i < IMG_SIZE; i++)//calculates the checksum
{
checksum += (unsigned char)(buffer[i]);
}
*(unsigned int*)(buffer+i) = checksum;//write checksum
if (write(ofd, buffer, BUFSIZE) != BUFSIZE) {
fprintf(stderr, "%s: Can't write %s: %s\n",
argv[0], argv[2], strerror(errno));
if (ifd)
close(ifd);
if (ofd)
close(ofd);
exit(EXIT_FAILURE);
}
if (ifd)
close(ifd);
if (ofd)
close(ofd);
return EXIT_SUCCESS;
}
校验和就是简单相加,然后将校验和写入14*1024-4的位置,就OK了,很简单的工作。
因为我们制作的是BL2,所以需要将用来作BL1加头的代码去掉。
编译uboot之后在spl目录下生成的tiny4412-spl.bin(BL2)。
使用linux命令dd进行烧写。
#man dd 可知
dd:主要用于拷贝和转化文件
重要参数:
iflag=读取时采用同步方式
oflag=写入时采用同步方式
if = 输入文件
of =输出文件
seek=从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)。
为了减少反复输入命令,将烧写命令写成一个脚本。(参考开放板厂商代码的sd_fuse里面脚本修改)
源码根目录/sd_fuse/tiny4412/sd_fusing.sh
#
# Copyright (C) 2011 Samsung Electronics Co., Ltd.
# http://www.samsung.com/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
####################################
if [ -z $1 ]
then
echo "usage: ./sd_fusing.sh "
exit 0
fi
if [ -b $1 ]
then
echo "$1 reader is identified."
else
echo "$1 is NOT identified."
exit 0
fi
####################################
#
BDEV_NAME=`basename $1`
BDEV_SIZE=`cat /sys/block/${BDEV_NAME}/size`
if [ ${BDEV_SIZE} -le 0 ]; then
echo "Error: NO media found in card reader."
exit 1
fi
if [ ${BDEV_SIZE} -gt 32000000 ]; then
echo "Error: Block device size (${BDEV_SIZE}) is too large"
exit 1
fi
####################################
# check files
E4412_UBOOT=../../u-boot.bin
E4412_UBOOT_SPL=../../spl/tiny4412-spl.bin
if [ ! -f ${E4412_UBOOT} ]; then
echo "Error: u-boot.bin NOT found, please build it & try again."
exit -1
fi
if [ ! -f ${E4412_UBOOT_SPL} ]; then
echo "Error: tiny4412-spl.bin(BL2) NOT found, please build it & try again."
exit -1
fi
####################################
# fusing images
signed_bl1_position=1
bl2_position=17
uboot_position=49
tzsw_position=705
#
echo "---------------------------------------"
echo "BL1 fusing"
dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=$1 seek=$signed_bl1_position
#
echo "---------------------------------------"
echo "BL2 fusing"
dd iflag=dsync oflag=dsync if=./${E4412_UBOOT_SPL} of=$1 seek=$bl2_position
#
echo "---------------------------------------"
echo "u-boot fusing"
dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
#
echo "---------------------------------------"
echo "TrustZone S/W fusing"
dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
#
sync
####################################
#
echo "***************************************"
echo "U-boot image is fused successfully."
插入读卡器,此时发现设备文件/dev/sdc
进入到脚本的目录,执行脚本,完成烧写。
#sd_fusing /dev/sdc
当然在该目录还要有官方的BL1文件和E4412_tzsw.bin文件。
1.修改链接地址
include/configs/tiny4412.h
54:#define CONFIG_SPL_TEXT_BASE 0x02023400
2.添加调试LED代码
2.1 查看原理图,确定LED引脚
->
->
通过原理图可知,LED占用的GPM4 0-3引脚,低电平点亮。
2.2 查看芯片手册,确定寄存器地址
2.3 写驱动代码
arch/arm/cpu/armv7/start.S
...
reset:
bl light_led
...
@在文件后面添加代码
.globl light_led
light_led:
ldr r0, =0x110002E0 @ GPM4CON Register
ldr r1, =0x00001111 @ Configurate GPM4_0GPM4_1GPM4_2GPM4_3 output
str r1, [r0]
mov r1, #0xF0 @ light All led on
ldr r0, =0x110002E4 @ GPM4DAT Register
str r1, [r0]
mov pc, lr
执行编译命令:
#make ARCH=arm CROSS_COMPILE=arm-linux- V=1 -j8
烧写,将启动选择开关拨到SD卡启动,则可以看到开发板上的4颗LED灯被点亮。
本节内容结束,uboot移植未完待续。。。