背景:
之前的帖子中也提到了,可以用FriendlyARM提供的sd_fuse工具制作可以给使用S5P6818 SOC设备使用的SD卡,由于GEC6818的配置和三星Nexell的Raptor,drone开发板以及友善的nanopi3系列本质是很相近的,所以他们的系统、uboot、甚至是bootloader小加修改就可以跑在粤嵌的GEC6818开发板上面,使用sd fuse工具制作在CSDN上面已经有详细的帖子教大家了,就不再赘述,现在我们使用Linux系统基本dd,fdisk,tar等命令来实现bl和uboot的写入,boot分区,rootfs分区,user分区的数据写入。这个掌握之后其实可以发现安装ArchLinux,Gentoo等系统是非常简单的。
开始之前照例先上两张效果图:
启动日志输出在屏幕:
系统登录:
系统启动流程:
之前24年8月修改开发了一个工具mk6818,用于调试bl1和u-boot,我补充了大致的启动流程在README,需要研究代码的同学可以去github查看:
https://github.com/celeron633/mk6818
这里介绍下大概:
下面介绍的bl1,bl2,bl33等名称全部按ATF的规范解释,即bl1为芯片上面的bootrom,bl2为bl1加载的一个类似于uboot-spl的程序,用于初始化DDR等外设,设置PLL频率。
上电之后,芯片内部的bootrom(bl1)会启动,这个是SOC出厂就写好的程序,无法修改,bootrom会根据引脚的选择,优先选择从内部MMC,或者外部SD,或者USB,串口启动。粤嵌GEC6818选择的优先启动位于SD0上面的SD卡。也就是下图中,蓝色排线对着那个槽。
另一个槽位是SD3,好像是不能被bootrom搜索到的,不过启动到uboot之后,插了卡照样是能启动里面的系统的。SD2粤嵌和FriendlyARM都没有引出卡槽,复用成其他接口了。
bootrom会搜索上面描述的那些设备的第1个扇区,里面有NISH信息描述bl2的位置,大小,加载在哪里,从哪个地址启动等信息,详情请看mk6818的README。读取bl2到内存后,然后跳转到了bl2,代码就进入到了bl2的领空了,这个时候,由于我们是armv8的64位启动了,按照ARM的ATF(ARM Trusted Firmware)规范,接下来会加载执行bl31(fip-loader.img),bl32(fip-secure.img),bl33(fip-nonsecure.img,也就是uboot了)。其中前面两个的代码ARM有开源,不过SOC厂商会修改,所以ARM开源的我们是不能用的。
能不能让bl1直接加载uboot,uboot再启动内核呢,其实粤嵌现有的32位系统就是这样的。没有那两个fip-loader和fip-secure。64位其实也可以,我自己就是用mk6818制作带nish的uboot,然后usb启动调试uboot的。但是这样有个问题,SMC调用没有在bl2中实现,Linux内核是没有办法跑起来的,内核需要调用SMC管理8个CPU核心的电源。这个有个波兰大神rafaello7已经实现了,后面再聊聊他的修改,我暂时还没有看懂。
ARM开源的ATF的链接如下:
GitHub - ARM-software/arm-trusted-firmware: Read-only mirror of Trusted Firmware-A
波兰大佬rafaello7修改bl1,支持smc调用的commit,看懂需要熟悉armv8的中断处理和GIC那一套。
added psci handler preliminary version · rafaello7/bl1-nanopi-m3@6792971 · GitHub
准备:
硬件:
需要准备一个读卡器,一张空白的SD卡,大于16G为妙,8G也能用。再小有点勉强了。
读卡器如果笔记本有,可以直接使用笔记本的。
软件:
准备一个Linux环境,windows没有dd,fdisk那些玩意,当然你要是用cygwin那些那当我没有说。
我使用的opensuse的Leap 15.6系统。你也可以使用ubuntu,arch,gentoo,centos任意GNU Linux系统。
需要下载的东西:
最好先clone整个repo:
GitHub - celeron633/docs_gec6818: 粤嵌GEC6818文档
东西全部都在prebuilt目录下,repo里面还有电路图等资料,prebuilt为预编译的一些二进制文件。
bl2:docs_gec6818/prebuilt/bl_and_uboot/bl1-mmcboot-sd.bin at master · celeron633/docs_gec6818 · GitHub
不要纠结为啥名字是bl1,按atf的规范,这个就是bl2
bl31:
docs_gec6818/prebuilt/bl_and_uboot/fip-loader.img at master · celeron633/docs_gec6818 · GitHub
bl32:
docs_gec6818/prebuilt/bl_and_uboot/fip-secure.img at master · celeron633/docs_gec6818 · GitHub
bl33(uboot编译后,处理生成的img文件):
boot分区备份的targz文件:
docs_gec6818/prebuilt/boot/boot.tar.gz at master · celeron633/docs_gec6818 · GitHub
还有个最重要的rootfs:
http://112.124.9.243/dvdfiles/s5p6818/rootfs/rootfs-ubuntu-noble-core-arm64.tgz
这个我们从FriendlyARM的服务器下载,放GitHub有点大了,不用lfs无法上传的。
rootfs不区分FriendlyARM的板子还是GEC6818
其他:
然后就是有空闲的时间和折腾的心态了。毕竟这个我觉得比安装ArchLinux还是麻烦一点的,不过也不是太多。
分区:
警告:这一步操作很危险,你要是弄错了要分区的块设备,可能导致分区表丢失,或者写到其他硬盘造成数据丢失。操作前一定要确认好是sdb,还是sdc还是sdd,这个每个人由于插的硬盘数不同,所以都不太一样。要是这个都不会建议还是先学习基础,先不要折腾了。
小知识:每个扇区512字节
写入的系统暂时还是使用FriendlyARM提供的那套系统,不用另外编译了。按FriendlyARM的方案,我们需要3个分区:
1:boot:用于存放内核,dtb,开机LOGO;这个也是uboot经常访问的部分。
2:rootfs:只读文件系统,用于存放根文件系统,Linux系统最主要的组成部分了,相当于ubuntu分区时的/分区
3:userdata:会以overlay的方式挂载到根分区上面去,对rootfs所有的修改会保存到userdata,而不会直接写入rootfs,这样有个显而易见的好处,就是方便恢复出厂设置了。很多路由器也是类似的方法。
对于分区1,我们不能直接从2048扇区开始(fdisk默认从2048),需要预留一些空间给前面说的bl2,bl31到bl33。直接从2048开始相当于只有扇区1到2047给到这些,只有(2047 * 512 / 1024)只有1023kb,其实差不多也够了,但是我们还是先预留16M给他们。
下面我们一步步来操作:
首先看看sd卡是哪个块设备,使用lsblk查看下,根据大小判断:
我的是sdb,你也可以插入读卡器后,dmesg查看,内核会打印是sd多少。
运行cfdisk:
sudo fdisk /dev/sdb
先创建boot分区,从16M的位置开始,大小128M:
我输入的命令如下:
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-62333951, default 2048): 34816
Last sector, +/-sectors or +/-size{K,M,G,T,P} (34816-62333951, default 62333951): 296959
Created a new partition 1 of type 'Linux' and of size 128 MiB.
Command (m for help):
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-62333951, default 2048): 34816
Last sector, +/-sectors or +/-size{K,M,G,T,P} (34816-62333951, default 62333951): 296959
Created a new partition 1 of type 'Linux' and of size 128 MiB.
Command (m for help):
关键步骤:输入n创建分区,输入p,创建主分区,分区编号一定要选择1,输入1;然后开始扇区输入34816,结束扇区输入296959。
至于为什么是这些数,是计算出来的,前面说了每个扇区512字节,如何16个MB多少个扇区,全部是算出来的。
执行完了之后,按w再回车保存退出,后面两个分区我们用cfdisk创建,cfdisk创建不支持起始位置,否则前面直接用cfdisk来了。
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
运行cfdisk:
cfdisk使用了tui,比fdisk友好,当然你是大佬可以直接使用fdisk完成这一步的操作,这一步的操作更多是给初学者看的
sudo cfdisk /dev/sdb
可以看到已经有一个sdb1分区了,大小128M,sdb1前面有16M空闲空间,这个是故意的。
然后按方向键下,光标移到绿色的free space,左右选择new回车:
大小输入4G,回车
选择主分区,千万不要选扩展
可以看到多了一个4G的主分区
接着同样的方法,创建另外一个分区用于userdata,就不再赘述了。我选择userdata为8个G,最终效果如图下:
完成后,左右选择write保存,输入yes确认,不要输入y,不认
显示分区表被修改后,选择quit退出
格式化:
我们刚才一共有3个分区sdb1,sdb2,sdb3,需要全部格式化为ext4格式,这里再次提醒一遍,千万不要搞错编号,sda,sdb,sdc,sdd等,否则你的数据真的要完蛋了。
依次输入下面的命令进行格式化:
sudo mkfs.ext4 /dev/sdb1
sudo mkfs.ext4 /dev/sdb2
sudo mkfs.ext4 /dev/sdb3
执行完之后可以再lsblk确认下:
写入bootloader和uboot:
准备好我们需要的下面几个文件:
对于这部分的写入,我们直接写入扇区,不需要挂载文件系统。
先看看sd_fuse里面,每个文件写入的扇区数,有点大概映像,参考这个文件:
sd-fuse_s5p6818/fusing.sh at master · friendlyarm/sd-fuse_s5p6818 · GitHub
脚本里面有写偏移:
这四个文件就是我们要写入到sdb的,只是我们不用fusing_bin,我们用dd
命令:
sudo dd if=./bl1-mmcboot-sd.bin of=/dev/sdb bs=512 seek=1
sudo dd if=./fip-loader.img of=/dev/sdb bs=512 seek=129
sudo dd if=./fip-secure.img of=/dev/sdb bs=512 seek=769
sudo dd if=./fip-nonsecure-GEC6818.img of=/dev/sdb bs=512 seek=3841
和友善的脚本里面描述的位置是完全对应的,使用seek参数,跳过n个bs大小,我们bs大小设置为了512,刚好是一个扇区的大小。
至于为什么是这些数,这个你得研究bl2的执行过程和NISH的数据结构了,可以参考我的mk6818写的README,然后学习bl2的代码。
执行日志:
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/bl_and_uboot> sudo dd if=./bl1-mmcboot-sd.bin of=/dev/sdb bs=512 seek=1
42+1 records in
42+1 records out
21552 bytes (22 kB, 21 KiB) copied, 0.00411888 s, 5.2 MB/s
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/bl_and_uboot> sudo dd if=./fip-loader.img of=/dev/sdb bs=512 seek=129
545+0 records in
545+0 records out
279040 bytes (279 kB, 272 KiB) copied, 0.0458411 s, 6.1 MB/s
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/bl_and_uboot> sudo dd if=./fip-secure.img of=/dev/sdb bs=512 seek=769
502+1 records in
502+1 records out
257136 bytes (257 kB, 251 KiB) copied, 0.0421259 s, 6.1 MB/s
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/bl_and_uboot> sudo dd if=./fip-nonsecure-GEC6818.img of=/dev/sdb bs=512 seek=3841
993+1 records in
993+1 records out
508440 bytes (508 kB, 497 KiB) copied, 0.082547 s, 6.2 MB/s
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/bl_and_uboot>
执行到这一步,恭喜已经写入好uboot和bootloader了。
写入boot分区:
挂载第一个128M的分区到/mnt:
sudo mount /dev/sdb1 /mnt
展开备份的boot.tar.gz:这个文件我前面已经提供了,是从我的机器提取出来的。
sudo tar -zxvp --xattrs -f ./boot.tar.gz -C /mnt
其实就是展开了几个文件到boot分区
使用tar的关键参数为:
-f:操作的源文件
-z:使用gzip
-x:解压
-v:显示详细日志
-p:恢复压缩时的权限
--xattrs:恢复扩展权限,chattr那些设置的
-C:程序解压时chdir到/mnt,相当于解压到/mnt目录,就是我们sdb1分区的挂载
执行完了之后,umount,sync再拔掉卡:
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/boot> sudo umount /mnt
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/boot> sudo sync
dengxh@openSUSE:~/data/s5p6818/docs_gec6818/prebuilt/boot>
写入rootfs:
聪明的读者已经不难想到了,rootfs不就和boot.tar.gz差不多嘛,解压到sdb2就完事了,确实,没毛病。今天有点晚了,改天更新,先占坑。
-- 2024-12-12 更新:
1. 先从FriendlyARM的服务器下载回来镜像:
wget http://112.124.9.243/dvdfiles/s5p6818/rootfs/rootfs-ubuntu-noble-core-arm64.tgz
等待一段时间,等待文件下载完成。
2. 挂载我们之前分区的第二个分区(我这里sdb2)到mnt
sudo mount /dev/sdb2 /mnt
3. 和boot.tar.gz一样,解压从友善下载回来的targz到mnt文件夹:
sudo tar -zxvp --xattrs -f ./rootfs-ubuntu-noble-core-arm64.tgz -C /mnt
等待解压完成:
命令的含义上面boot的时候已经解释过了。
4. 修正rootfs目录结构
到mnt目录下,可以看到linux标准目录前,多了一层ubuntu-noble-core-arm64文件夹和rootfs文件夹,我们要做的是把里面的子内容移到上一层:
sudo mv ubuntu-noble-core-arm64/rootfs/* ./
再ls可以看到正常的目录结构,类似/下面:
5. 之后执行sync,再取消挂载mnt
sudo sync
sudo umount /mnt
大告成功:
接着可以拔掉SD卡,插入开发板的SD0卡槽上电测试了,串口线可以接个终端便于观察输出日志。不出意外已经可以正常启动进入系统了。
至于uboot和内核的编译,专栏里面已经有介绍了,喜欢的同学
标签:系统启动,uboot,docs,分区,sudo,boot,开发板,64,gec6818 From: https://blog.csdn.net/m0_47367420/article/details/144408714