- 加载/ 启动linux内核脚本
下面就是如何如何通过Usb加载运行编译出来的kernel及ramdisk.img了(脚本:Android-Q/nanopi-neo/boot/run.sh):
#! /bin/bash
set -e -x
RAMDISK=../../out/target/product/nanopi/ramdisk.img
SIZE_RAMDISK=`printf '0x%x' $(stat -c %s ${RAMDISK})`
cat << EOF > boot.cmd
# Recompile with: mkimage -C none -A arm -T script -d boot.cmd boot.scr
# CPU=H3
# OS=friendlycore/ubuntu-oled/ubuntu-wifiap/openwrt/debian/debian-nas...
echo "running boot.scr"
setenv ramdisk ramdisk.img
setenv kernel zImage
setenv env_addr 0x43100000
setenv kernel_addr 0x46000000
setenv ramdisk_addr 0x47000000
setenv dtb_addr 0x48000000
setenv ramdisk_size ${SIZE_RAMDISK}
fdt addr \${dtb_addr}
# setup MAC address
fdt set ethernet0 local-mac-address \${mac_node}
# setup XR819 MAC address
if test \$board = nanopi-duo; then fdt set xr819 local-mac-address \${wifi_mac_node}; fi
# setup boot_device
fdt set mmc\${boot_mmc} boot_device <1>
setenv fbcon map:0
#setenv hdmi_res drm_kms_helper.edid_firmware=HDMI-A-1:edid/1280x720.bin video=HDMI-A-1:1280x720@60
setenv extra androidboot.hardware=nanopi androidboot.selinux=permissive androidboot.serialno=621415251279
setenv bootargs console=ttyS0,115200 earlyprintk panic=10 fbcon=\${fbcon} printk.devkmsg=on ignore_loglevel \${extra}
bootz \${kernel_addr} \${ramdisk_addr}:\${ramdisk_size} \${dtb_addr}
EOF
../u-boot/tools/mkimage -C none -A arm -T script -d boot.cmd boot.scr
../sunxi-tools/sunxi-fel -p -v uboot ../u-boot/u-boot-sunxi-with-spl.bin \
write 0x43100000 boot.scr \
write 0x48000000 ../../kernel-common/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dtb \
write 0x46000000 ../../kernel-common/arch/arm/boot/zImage \
write 0x47000000 ${RAMDISK}
从这里可以看到,这个脚本:
1。首先会在当前路径下创建一个名为boot.cmd(Android-Q/nanopi-neo/boot/boot.cmd)的文件
2。再通过mkimage转换成u-boot可以识别的boot.scr(Android-Q/nanopi-neo/boot/boot.scr)文件
3。最后会通过sunxi-fel工具,将相关的文件boot.scr, sun8i-h3-nanopi-eno.dtb,zImage及ramdisk.img文件,下载到开发板中,并运行。
这里需要注意的是:ramdisk.img文件大小需要明确指定,并且大小是十六进制格式(无论前面没有加0x)。
使用这样的方式加载的好处是不用将这些文件copy到TF卡中,对早期需要反复修改kernel/dtb文件非常便利。
下面是另外一个脚本(Android-Q/nanopi-neo/boot/cmd.sh),用于加载TF卡中的kernel/dtb/ramdisk.img文件,也非常好用:
#! /bin/bash
set -e -x
cat << EOF > boot.cmd
# Recompile with: mkimage -C none -A arm -T script -d boot.cmd boot.scr
# CPU=H3
# OS=friendlycore/ubuntu-oled/ubuntu-wifiap/openwrt/debian/debian-nas...
echo "running boot.scr"
setenv ramdisk ramdisk.img
setenv kernel zImage
setenv env_addr 0x43100000
setenv kernel_addr 0x46000000
setenv ramdisk_addr 0x47000000
setenv dtb_addr 0x48000000
fatload mmc 0 \${kernel_addr} \${kernel}
fatload mmc 0 \${ramdisk_addr} \${ramdisk}
setenv ramdisk_size \${filesize}
fatload mmc 0 \${dtb_addr} sun8i-\${cpu}-\${board}.dtb
fdt addr \${dtb_addr}
# setup MAC address
fdt set ethernet0 local-mac-address \${mac_node}
# setup XR819 MAC address
if test \$board = nanopi-duo; then fdt set xr819 local-mac-address \${wifi_mac_node}; fi
# setup boot_device
fdt set mmc\${boot_mmc} boot_device <1>
setenv fbcon map:0
#setenv hdmi_res drm_kms_helper.edid_firmware=HDMI-A-1:edid/1280x720.bin video=HDMI-A-1:1280x720@60
setenv extra androidboot.hardware=nanopi androidboot.selinux=permissive androidboot.serialno=621415251279
setenv bootargs console=ttyS0,115200 earlyprintk panic=10 fbcon=\${fbcon} printk.devkmsg=on ignore_loglevel \${extra}
bootz \${kernel_addr} \${ramdisk_addr}:\${ramdisk_size} \${dtb_addr}
EOF
../u-boot/tools/mkimage -C none -A arm -T script -d boot.cmd boot.scr
../sunxi-tools/sunxi-fel -p -v uboot ../u-boot/u-boot-sunxi-with-spl.bin \
write 0x43100000 boot.scr
写这两个脚本,是由于之前在修改kernel配置的时候,出现无法开机的情况,使用这两个脚本,可以有效地减少更新TF卡文件的烦恼。
- Android-Q分区配置
目前看来,TF只需要这几个分区就可以了:
1。boot分区:用于存放boot.scr, dtb, zImage及ramdisk.img文件, 需要~64MiB
2。system分区:用于写入system.img,需要~350MiB
3。vendor分区:用于写入vendor.img,需要~128MiB
4。userdata分区:用于存放系统及用户数据
- Android fstab
Android init进程启动时,在第一阶段需要挂载vendor分区(及system分区?),需要修改sun8i-h3-neo.dts文件:
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
index 9f33f6f..f1f7c6e9 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
@@ -45,6 +45,30 @@
/ {
model = "FriendlyARM NanoPi NEO";
compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
+
+ firmware: firmware {
+ android {
+ compatible = "android,firmware";
+
+ android_fstab: fstab {
+ compatible = "android,fstab";
+ system {
+ compatible = "android,system";
+ dev = "/dev/block/mmcblk0p2";
+ type = "ext4";
+ mnt_flags = "ro,barrier=1,discard";
+ fsmgr_flags = "wait";
+ };
+ vendor {
+ compatible = "android,vendor";
+ dev = "/dev/block/mmcblk0p3";
+ type = "ext4";
+ mnt_flags = "ro,barrier=1,discard";
+ fsmgr_flags = "wait";
+ };
+ };
+ };
+ };
};
- first stage中的console
在system/core的aosp/master分支中,在first stage中加入了console的代码,这个感觉还是非常有用的:
commit d75f30a4f0ca10ebd87798d7aeed467e0da40daa
Author: Steve Muckle <smuckle@google.com>
Date: Tue May 21 15:50:39 2019 -0700
first_stage_init: add console
Start and wait on a console if androidboot.first_stage_console=1 is
present on the kernel command line. This only works on eng and
userdebug builds.
Change-Id: I978e9390a89509431b399ea58b284736b27eeb1b
希望在Android Q的最终版本上也能有这样的功能Cool。