Others: Android Q on NanoPi Neo – bootloader & kernel 二

  • 加载/ 启动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。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注