Rockchip RK3399 - 移植linux 5.2.8
----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4
开发板
eMMC
:16GB
LPDDR3
:4GB
显示屏 :15.6
英寸HDMI
接口显示屏
u-boot
:Rockchip
官方uboot 2017.09
linux
:5.2.8
----------------------------------------------------------------------------------------------------------------------------
在前面的章节,我们已经介绍了在RK3399
上面移植Rockchip
官方提供的uboot 2017.09
,这一节我们将移植linux 5.2.8
到RK3399
上。
一、linux内核
像uboot
一样,linux
内核通常有三种:
linux
官方源码:《https://github.com/torvalds/linux
》,linux
官方源码是由linux
官方维护,支持非常全面的芯片,但对具体某款开发板支持情况一般;- 半导体厂商瑞芯微官方源码:《
https://github.com/rockchip-linux/kernel
》,半导体厂商基于linux
官方源码进行修改,对自家的芯片进行完善的支持,针对某款处理器支持情况较好; - 开发板友善之家官方源码:《
https://github.com/friendlyarm/kernel-rockchip
》,开发板厂商基于半导体厂商维护的linux
,对自家的开发板进行板级支持,针对某款开发板支持情况较好;
由于Rockchip
官方提供的内核版本较低,所以这里我们直接去linux
官方去下载,然后后面参考开发板友善之家官方源码修改使其能够支持NanoPC-T4
开发板。
1.1 源码下载
内核源码下载地址为:《https://www.kernel.org/
》,这里我们不下载最新的6.3.2
版本,我们和之前介绍的《Mini2440
内核移植》一样,选择5.2.8
版本:
也可以到内核镜像网址下载https://mirrors.edge.kernel.org/pub/linux/kernel/
,这里下载速度更快。
如果下载速度太慢,无法下载,提供另一个链接:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
。
我们这里下载linux-5.2.8
版本,执行如下命令:
root@zhengyang:/work/sambashare/rk3399# wget http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/v5.x/linux-5.2.8.tar.gz
这里我是下载到/work/sambashare/rk3399
路径下的,这个路径是用来专门存放与rk3399
相关的内容。
解压源码:
root@zhengyang:/work/sambashare/rk3399# tar -xvf linux-5.2.8.tar.gz
关于《linux
内核的目录结构》我们之前已经介绍过,这里就不再重复叙述了。
root@zhengyang:/work/sambashare/rk3399# cd linux-5.2.8/
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll
总用量 840
drwxrwxr-x 24 root root 4096 Aug 9 2019 ./
drwxr-xr-x 8 root root 4096 May 17 04:16 ../
drwxrwxr-x 27 root root 4096 Aug 9 2019 arch/
drwxrwxr-x 3 root root 4096 Aug 9 2019 block/
drwxrwxr-x 2 root root 4096 Aug 9 2019 certs/
-rw-rw-r-- 1 root root 14943 Aug 9 2019 .clang-format
-rw-rw-r-- 1 root root 59 Aug 9 2019 .cocciconfig
-rw-rw-r-- 1 root root 423 Aug 9 2019 COPYING
-rw-rw-r-- 1 root root 99486 Aug 9 2019 CREDITS
drwxrwxr-x 4 root root 4096 Aug 9 2019 crypto/
drwxrwxr-x 122 root root 12288 Aug 9 2019 Documentation/
drwxrwxr-x 140 root root 4096 Aug 9 2019 drivers/
drwxrwxr-x 73 root root 4096 Aug 9 2019 fs/
-rw-rw-r-- 1 root root 71 Aug 9 2019 .get_maintainer.ignore
-rw-rw-r-- 1 root root 30 Aug 9 2019 .gitattributes
-rw-rw-r-- 1 root root 1658 Aug 9 2019 .gitignore
drwxrwxr-x 27 root root 4096 Aug 9 2019 include/
drwxrwxr-x 2 root root 4096 Aug 9 2019 init/
drwxrwxr-x 2 root root 4096 Aug 9 2019 ipc/
-rw-rw-r-- 1 root root 1513 Aug 9 2019 Kbuild
-rw-rw-r-- 1 root root 563 Aug 9 2019 Kconfig
drwxrwxr-x 18 root root 4096 Aug 9 2019 kernel/
drwxrwxr-x 15 root root 12288 Aug 9 2019 lib/
drwxrwxr-x 6 root root 4096 Aug 9 2019 LICENSES/
-rw-rw-r-- 1 root root 12316 Aug 9 2019 .mailmap
-rw-rw-r-- 1 root root 512407 Aug 9 2019 MAINTAINERS
-rw-rw-r-- 1 root root 60262 Aug 9 2019 Makefile
drwxrwxr-x 3 root root 4096 Aug 9 2019 mm/
drwxrwxr-x 70 root root 4096 Aug 9 2019 net/
-rw-rw-r-- 1 root root 727 Aug 9 2019 README
drwxrwxr-x 29 root root 4096 Aug 9 2019 samples/
drwxrwxr-x 15 root root 4096 Aug 9 2019 scripts/
drwxrwxr-x 11 root root 4096 Aug 9 2019 security/
drwxrwxr-x 26 root root 4096 Aug 9 2019 sound/
drwxrwxr-x 36 root root 4096 Aug 9 2019 tools/
drwxrwxr-x 2 root root 4096 Aug 9 2019 usr/
drwxrwxr-x 4 root root 4096 Aug 9 2019 virt/
1.2 配置Makefile
修改顶层的Makefile
,打开Makefile
文件,找到下面语句:
ARCH ?= $(SUBARCH)
修改为:
ARCH ?= arm64
CROSS_COMPILE ?= arm-linux-
其中,ARCH
是指定目标平台为arm64
,CROSS_COMPILE
是指定交叉编译器,这里指定的是系统默认的交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。
1.3 内核defconfig
配置
接下来要做的就是内核配置、编译了。单板的默认配置文件在arch/arm64/configs
目录下:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll arch/arm64/configs/defconfig
-rw-rw-r-- 1 root root 18417 Aug 9 2019 arch/arm64/configs/defconfig
在这个目录下就这一个配置,我们也没有其它选择了,那只能走一步看一步了。
配置文件defconfig
其定义如下:
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_NUMA_BALANCING=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_AGILEX=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_ALPINE=y
CONFIG_ARCH_BCM2835=y
CONFIG_ARCH_BCM_IPROC=y
CONFIG_ARCH_BERLIN=y
CONFIG_ARCH_BRCMSTB=y
CONFIG_ARCH_EXYNOS=y
CONFIG_ARCH_K3=y
CONFIG_ARCH_LAYERSCAPE=y
CONFIG_ARCH_LG1K=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_ARCH_MESON=y
CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_MXC=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_RENESAS=y
CONFIG_ARCH_ROCKCHIP=y
CONFIG_ARCH_SEATTLE=y
CONFIG_ARCH_STRATIX10=y
CONFIG_ARCH_SYNQUACER=y
CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_SPRD=y
CONFIG_ARCH_THUNDER=y
CONFIG_ARCH_THUNDER2=y
CONFIG_ARCH_UNIPHIER=y
CONFIG_ARCH_VEXPRESS=y
CONFIG_ARCH_XGENE=y
CONFIG_ARCH_ZX=y
CONFIG_ARCH_ZYNQMP=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_NUMA=y
CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_COMPAT=y
CONFIG_HIBERNATION=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ARM_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPUFREQ_DT=y
CONFIG_ACPI_CPPC_CPUFREQ=m
CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_TEGRA186_CPUFREQ=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_INTEL_STRATIX10_SERVICE=y
CONFIG_TI_SCI_PROTOCOL=y
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_IMX_SCU=y
CONFIG_IMX_SCU_PD=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_SHA3_ARM64=m
CONFIG_CRYPTO_SM3_ARM64_CE=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IPV6=m
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
CONFIG_BT=m
CONFIG_BT_HIDP=m
# CONFIG_BT_HS is not set
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=m
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_IOV=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_PCI_AARDVARK=y
CONFIG_PCI_TEGRA=y
CONFIG_PCIE_RCAR=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
CONFIG_PCIE_ALTERA_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_ROCKCHIP_HOST=m
CONFIG_PCI_LAYERSCAPE=y
CONFIG_PCI_HISI=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_ARMADA_8K=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_HISI_STB=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_MARVELL=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=m
CONFIG_SRAM=y
CONFIG_EEPROM_AT25=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_SCSI_HISI_SAS=y
CONFIG_SCSI_HISI_SAS_PCI=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_HISI=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_CEVA=y
CONFIG_AHCI_MVEBU=y
CONFIG_AHCI_XGENE=y
CONFIG_AHCI_QORIQ=y
CONFIG_SATA_SIL24=y
CONFIG_SATA_RCAR=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_TUN=y
CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
CONFIG_ATL1C=m
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
CONFIG_FEC=y
CONFIG_HIX5HD2_GMAC=y
CONFIG_HNS_DSAF=y
CONFIG_HNS_ENET=y
CONFIG_HNS3=y
CONFIG_HNS3_HCLGE=y
CONFIG_HNS3_ENET=y
CONFIG_E1000E=y
CONFIG_IGB=y
CONFIG_IGBVF=y
CONFIG_MVNETA=y
CONFIG_MVPP2=y
CONFIG_SKY2=y
CONFIG_QCOM_EMAC=m
CONFIG_RAVB=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_SNI_AVE=y
CONFIG_SNI_NETSEC=y
CONFIG_STMMAC_ETH=m
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_AT803X_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y
CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_HISI_POWERKEY=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_OMAP=y
CONFIG_SERIAL_8250_MT6577=y
CONFIG_SERIAL_8250_UNIPHIER=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_MESON=y
CONFIG_SERIAL_MESON_CONSOLE=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_TEGRA_TCU=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_QCOM_GENI=y
CONFIG_SERIAL_QCOM_GENI_CONSOLE=y
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_MVEBU_UART=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_BCM2835=m
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_IMX=y
CONFIG_I2C_MESON=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_PXA=y
CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_SH_MOBILE=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_RCAR=y
CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
CONFIG_SPI_ARMADA_3700=y
CONFIG_SPI_BCM2835=m
CONFIG_SPI_BCM2835AUX=m
CONFIG_SPI_NXP_FLEXSPI=y
CONFIG_SPI_MESON_SPICC=m
CONFIG_SPI_MESON_SPIFC=m
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=y
CONFIG_SPI_ROCKCHIP=y
CONFIG_SPI_QUP=y
CONFIG_SPI_S3C64XX=y
CONFIG_SPI_SPIDEV=m
CONFIG_SPI_SUN6I=y
CONFIG_SPMI=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QXP=y
CONFIG_PINCTRL_IPQ8074=y
CONFIG_PINCTRL_MSM8916=y
CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCS404=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_SDM845=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_RCAR=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_GPIO_XGENE=y
CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
CONFIG_POWER_AVS=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_SBS=m
CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_SENSORS_INA2XX=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_ROCKCHIP_THERMAL=m
CONFIG_RCAR_THERMAL=y
CONFIG_RCAR_GEN3_THERMAL=y
CONFIG_ARMADA_THERMAL=y
CONFIG_BCM2835_THERMAL=m
CONFIG_BRCMSTB_THERMAL=m
CONFIG_EXYNOS_THERMAL=y
CONFIG_TEGRA_BPMP_THERMAL=m
CONFIG_QCOM_TSENS=y
CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_S3C2410_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_RENESAS_WDT=y
CONFIG_UNIPHIER_WATCHDOG=y
CONFIG_BCM2835_WDT=y
CONFIG_MFD_ALTERA_SYSMGR=y
CONFIG_MFD_BD9571MWV=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_CHARDEV=m
CONFIG_MFD_EXYNOS_LPASS=m
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_HI655X_PMIC=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RK808=y
CONFIG_MFD_SEC_CORE=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_HI655X=y
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_RPMH=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_VCTRL=m
CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_IR_MESON=m
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_VIDEO_SUN6I_CSI=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
CONFIG_VIDEO_RENESAS_FCP=m
CONFIG_VIDEO_RENESAS_VSP1=m
CONFIG_DRM=m
CONFIG_DRM_NOUVEAU=m
CONFIG_DRM_EXYNOS=m
CONFIG_DRM_EXYNOS5433_DECON=y
CONFIG_DRM_EXYNOS7_DECON=y
CONFIG_DRM_EXYNOS_DSI=y
# CONFIG_DRM_EXYNOS_DP is not set
CONFIG_DRM_EXYNOS_HDMI=y
CONFIG_DRM_EXYNOS_MIC=y
CONFIG_DRM_ROCKCHIP=m
CONFIG_ROCKCHIP_ANALOGIX_DP=y
CONFIG_ROCKCHIP_CDN_DP=y
CONFIG_ROCKCHIP_DW_HDMI=y
CONFIG_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_ROCKCHIP_INNO_HDMI=y
CONFIG_DRM_RCAR_DU=m
CONFIG_DRM_SUN4I=m
CONFIG_DRM_SUN8I_DW_HDMI=m
CONFIG_DRM_SUN8I_MIXER=m
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_VC4=m
CONFIG_DRM_HISI_HIBMC=m
CONFIG_DRM_HISI_KIRIN=m
CONFIG_DRM_MESON=m
CONFIG_DRM_PL111=m
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_HDA_TEGRA=m
CONFIG_SND_HDA_CODEC_HDMI=m
CONFIG_SND_SOC=y
CONFIG_SND_BCM2835_SOC_I2S=m
CONFIG_SND_MESON_AXG_SOUND_CARD=m
CONFIG_SND_SOC_ROCKCHIP=m
CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
CONFIG_SND_SOC_ROCKCHIP_RT5645=m
CONFIG_SND_SOC_RK3399_GRU_SOUND=m
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SOC_RCAR=m
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
CONFIG_SND_SOC_PCM3168A_I2C=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_SND_AUDIO_GRAPH_CARD=m
CONFIG_I2C_HID=m
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_TEGRA=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EXYNOS=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_EXYNOS=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_RENESAS_USBHS=m
CONFIG_USB_STORAGE=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_RENESAS_USBHS_UDC=m
CONFIG_USB_RENESAS_USB3=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_F_SDH30=y
CONFIG_MMC_MESON_GX=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_UNIPHIER=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_BCM2835=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_EDAC=y
CONFIG_EDAC_GHES=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_CROS_EC=y
CONFIG_RTC_DRV_S3C=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_ARMADA38X=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_IMX_SC=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
CONFIG_FSL_EDMA=y
CONFIG_DMA_BCM2835=m
CONFIG_K3_DMA=y
CONFIG_MV_XOR=y
CONFIG_MV_XOR_V2=y
CONFIG_PL330_DMA=y
CONFIG_TEGRA20_APB_DMA=y
CONFIG_QCOM_BAM_DMA=y
CONFIG_QCOM_HIDMA_MGMT=y
CONFIG_QCOM_HIDMA=y
CONFIG_RCAR_DMAC=y
CONFIG_RENESAS_USB_DMAC=m
CONFIG_VFIO=y
CONFIG_VFIO_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_CROS_EC_I2C=y
CONFIG_CROS_EC_SPI=y
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_CLK_IMX8MQ=y
CONFIG_CLK_IMX8QXP=y
CONFIG_TI_SCI_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_QCOM_CLK_RPMH=y
CONFIG_IPQ_GCC_8074=y
CONFIG_MSM_GCC_8916=y
CONFIG_MSM_GCC_8994=y
CONFIG_MSM_MMCC_8996=y
CONFIG_MSM_GCC_8998=y
CONFIG_QCS_GCC_404=y
CONFIG_SDM_GCC_845=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
CONFIG_PLATFORM_MHU=y
CONFIG_BCM2835_MBOX=y
CONFIG_TI_MESSAGE_MANAGER=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=m
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
CONFIG_QCOM_SYSMON=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=m
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_QCOM_COMMAND_DB=y
CONFIG_QCOM_GENI_SE=y
CONFIG_QCOM_GLINK_SSR=m
CONFIG_QCOM_RPMH=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=y
CONFIG_QCOM_SMSM=y
CONFIG_ARCH_R8A774A1=y
CONFIG_ARCH_R8A774C0=y
CONFIG_ARCH_R8A7795=y
CONFIG_ARCH_R8A7796=y
CONFIG_ARCH_R8A77965=y
CONFIG_ARCH_R8A77970=y
CONFIG_ARCH_R8A77980=y
CONFIG_ARCH_R8A77990=y
CONFIG_ARCH_R8A77995=y
CONFIG_ROCKCHIP_PM_DOMAINS=y
CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_TEGRA_210_SOC=y
CONFIG_ARCH_TEGRA_186_SOC=y
CONFIG_ARCH_TEGRA_194_SOC=y
CONFIG_ARCH_K3_AM6_SOC=y
CONFIG_SOC_TI=y
CONFIG_TI_SCI_PM_DOMAINS=y
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_ROCKCHIP_SARADC=m
CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_IIO_CROS_EC_BARO=m
CONFIG_PWM=y
CONFIG_PWM_BCM2835=m
CONFIG_PWM_CROS_EC=m
CONFIG_PWM_MESON=m
CONFIG_PWM_RCAR=m
CONFIG_PWM_ROCKCHIP=y
CONFIG_PWM_SAMSUNG=y
CONFIG_PWM_SUN4I=m
CONFIG_PWM_TEGRA=m
CONFIG_RESET_TI_SCI=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_HISTB_COMBPHY=y
CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
CONFIG_PHY_QCOM_QMP=m
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_RCAR_GEN3_USB3=m
CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_ROCKCHIP_INNO_HDMI=m
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_PCIE=m
CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PHY_UNIPHIER_USB2=y
CONFIG_PHY_UNIPHIER_USB3=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
CONFIG_QCOM_QFPROM=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_UNIPHIER_EFUSE=y
CONFIG_MESON_EFUSE=m
CONFIG_FPGA=y
CONFIG_FPGA_MGR_STRATIX10_SOC=m
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_FPGA_REGION=m
CONFIG_OF_FPGA_REGION=m
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_HUGETLBFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_EFIVAR_FS=y
CONFIG_SQUASHFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
在linux内核根目录下执行如下命令,执行完之后会在内核根目录下生成默认配置文件.config:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# make defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.h
HOSTCC scripts/kconfig/lexer.lex.o
YACC scripts/kconfig/parser.tab.c
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTLD scripts/kconfig/conf
*** Default configuration is based on 'defconfig'
#
# configuration written to .config
#
1.4 内核裁切
我们可以通过make menuconfig
配置内核支持的功能:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# make menuconfig
打开如下页面:
1.4.1 支持设备树
实际上在linux 5.2.8
版本内核已经把设备树作为默认配置项了,因此也不需要我们配置了。
内核在启动时,会执行setup_arch
函数,该函数用于在内核启动期间对硬件进行初始化,包括设置CPU
、内存、设备树等等。该函数的实现是针对特定架构的,因此不同的架构会有不同的setup_arch
实现。以ARM
(非ARM64
)为例:
setup_arch(&command_line); // arch/arm/kernel/setup.c
mdesc = setup_machine_fdt(__atags_pointer); // arch/arm/kernel/devtree.c
// 检验设备树头部,判断设备树有效性
early_init_dt_verify(phys_to_virt(dt_phys) // drivers/of/fdt.c
initial_boot_params = params;
// 找到最匹配的machine_desc
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); // drivers/of/fdt.c
early_init_dt_scan_nodes() // drivers/of/fdt.c
// 从dtb文件中读取chosen节点的信息,包括命令行boot_command_line,initrd location及size
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line)
// 得到根节点的 #address-cells 和 #size-cells属性信息
of_scan_flat_dt(early_init_dt_scan_root, NULL)
// 得到/memory节点的reg属性
of_scan_flat_dt(early_init_dt_scan_memory, NULL)
machine_desc = mdesc;
......
of_flat_dt_match_machine
函数通过遍历所有的machine_desc
,找到与设备树中compatible
最匹配的一个machine_desc
(每一个开发板都对应一个machine_desc
,通过它定义开发板相关的一些属性及函数,比如机器类型ID
、中断初始化函数、I/O
映射函数、machine
初始化函数等;这些函数会在内核启动阶段被回调,在较早的版本中,init_machine
会包含大量的平台设备注册的代码)。
然而在ARM64
中,其实现发生了改变:
setup_arch(&command_line); // arch/arm64/kernel/setup.c
// 参数为dtb在内存的首地址
setup_machine_fdt(__fdt_pointer) // arch/arm64/kernel/setup.c
// 为fdt建立地址映射,在该函数的最后,顺便就调用memblock_reserve保留了该段内存
void *dt_virt = fixmap_remap_fdt(dt_phys)
// 校验并解析dtb文件
early_init_dt_scan(dt_virt) // drivers/of/fdt.c
// 检验设备树头部,判断设备树有效性
early_init_dt_verify()
early_init_dt_scan_nodes() // drivers/of/fdt.c
// 从dtb文件中读取chosen节点的信息,包括命令行boot_command_line,initrd location及size
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line)
// 得到根节点的 #address-cells 和 #size-cells属性信息
of_scan_flat_dt(early_init_dt_scan_root, NULL)
// 得到/memory节点的reg属性
of_scan_flat_dt(early_init_dt_scan_memory, NULL)
// 获取machine名称
name = of_flat_dt_get_machine_name(); // drivers/of/fdt.c
// 获取设备树的根节点
unsigned long dt_root = of_get_flat_dt_root()
// 这里直接获取设备树的model属性
name = of_get_flat_dt_prop(dt_root, "model", NULL)
parse_early_param();
......
arm64_memblock_init()
......
// 解析dtb文件,转换成节点是device_node的树状结构, 其中设备节点会被转换为device_node结构
unflatten_device_tree()
......
可以看到这里没有了设备树和machine_desc
的匹配过程了,也就是说ARM64
已经完全抛弃了machine_desc
,全部采用设备树的实现方式,关于《为什么要采用设备树》我在设备树章节已经具体介绍过。
1.4.2 支持NFS
文件系统
使用NFS
作为根文件系统,因为文件系统在宿主机中,这样在修改文件系统就非常方便,主要用于开发阶段使用。
File systems --->
[*] Network File Systems --->
<*> NFS client support
<*> NFS client support for NFS version 2
<*> NFS client support for NFS version 3
<*> NFS client support for NFS version 4
[*] Root file system on NFS
勾选NFS client support for NFS version 4
。
1.4.3 配置uevent helper
配置Support for uevent helper
;
Device Drivers --->
Generic Driver Options --->
[*] Support for uevent helper
(/sbin/mdev) path to uevent helper (NEW)
该选项的作用是启用uevent helper
程序的支持。uevent
是内核与用户空间之间通信的一种方式,当内核检测到新的设备时,会生成一个uevent
来通知用户空间,使得用户空间能够及时响应设备插拔事件,并做出相应的处理。其中, uevent helper
程序就是在接收到uevent
后执行的用户空间程序,用来完成设备的热插拔处理。
在内核中,CONFIG_UEVENT_HELPER=y
的设定可以确保uevent helper
程序能够被编译到内核中,从而能够正常地接收并响应uevent
事件。
path to uevent helper
配置为/sbin/mdev
;即指定uevent helper
程序为/sbin/mdev
。
具体参考:《dev
下无法生成节点的分析思路和解决方法及原理》。
1.4.4 支持RAM
块设备
如果我们需要使用ramdisk
根文件系统,就需要配置RAM
块设备驱动,否者不用配置这个。
ram disk
顾名思义,内存磁盘。我们平常接触的一些存储介质,如:Nor Flash
、Nand Flash
、eMMC
、ufs、以及机械硬盘固态硬盘等,都是用来存储数据的,同理内存也是可以当成磁盘来存储数据的,唯一不同的就是ram
是掉电不保存的,而前面提到的那些存储介质掉电都是保存数据的。
我们都知道,在linux
中,上面介绍的Flash
这些存储介质,都是需要有对应的驱动,注册成块设备。并向上层提供接口。如Nor
、Nand
等都抽象成mtdblock
块设备。
同理,linux
中的ram disk
意思就是拿出ram
中的一部分大小,用对应的驱动注册层块设备,提供给上层调用。一般的ram disk
注册成的块设备,在文件系统中设备节点体现为/dev/ramx
。
我们需要配置内核支持ramdisk
:
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
这里的意思是配置内核初始化时,去寻找initramfs
和initrd
,initrd
就是我们的ramdisk
文件系统,至于initramfs
,是一个可以编译进内核的根文件映像。
Device Drivers --->
[*] Block devices --->
<*> RAM block device support
(1) Default number of RAM disks
(327680) Default RAM disk size (kbytes)
勾选第一项RAM block device support
,才会出来第二项和第三项的选项;
- 第一项的意思是内核支持
ram disk
块设备驱动; - 第二项是注册的块设备数量,内核默认是
16
,我这里就写了1
,内核启动后会有/dev/ram0
块设备节点,配置16
则会有/dev/ram0~ram15
; - 第三项的意思是
ram disk
占得最大内存,这里我写的是32M
,一般来说可以写的再小点。实际在使用/dev/ramx
设备时,并不是一下子就占系统32M
内存,而是根据实际使用情况而分配的;
1.4.5 支持ext4
文件系统
由于后面我们会制作ext4
类型的根文件系统,因此需要勾选对ext4
文件系统格式的支持,内核默认已经勾选了。
File systems --->
-*- The Extended 4 (ext4) filesystem
[*] Ext4 POSIX Access Control Lists
[ ] Ext4 Security Labels
[ ] Ext4 debugging support
1.4.6 配置DRM
驱动
DRM
,全称Direct Rending Manger
。是目前Linux
主流的图形显示框架。配置这个的目的是为了在移植了带有桌面的ubuntu
根文件系统后,通过显示器来显示ubuntu
桌面;
Device Drivers --->
Graphics support --->
[*] Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
[*] DRM Support for Rockchip
1.4.7 配置有线网卡驱动
RK3399
内置了以太网控制器,所以只要搭配一颗以太网PHY
芯片就可以实现以太网功能。这里我使用的NanoPC-T4
开发板搭载的以太网PHY
芯片型号为RTL8211E-VB-CG
,是Realtek
瑞昱推出的一款高集成的网络接收PHY
芯片,它符合10Base-T
,100Base-TX
和1000Base-T IEEE802.3
标准,该芯片在网络通信中属于物理层,用于MAC
与PHY
之间的数据通信。
10/100M
以太网PHY
和MAC
之间的接口主要有MII
和RMII
,而10/100/1000M
以太网PHY
和MAC
之间的接口主要有RGMII
。而RK3399
对RMII
、RGMII
接口均支持,也就是说RK3399
支持100M
网卡、1000M
网卡。
因此我们需要配置:
Device Drivers --->
[*] Network device support --->
[*] Ethernet driver support --->
[*] STMicroelectronics 10/100/1000/EQOS Ethernet driver
[*] STMMAC Platform bus support
[*] Rockchip dwmac support
需要注意RTL8211
和我们之前接触的DM9000
有很大的差异:
- 功能不同:
RTL8211E
是一款物理层网络接口芯片,主要负责物理层的处理和传输;而DM9000
是一款以太网控制器芯片,主要负责数据链路层的处理和管理; - 高度不同:
RTL8211E
是一个高度集成化的单芯片方案,可直接与处理器连接,不需要外部存储器;DM9000
则需要和存储器结合使用,并且需要外部时钟电路的支持; - 传输速率不同:
RTL8211E
支持千兆以太网(1000Mbps
)和百兆以太网(100Mbps
)的数据传输,而DM9000
只支持百兆以太网(100Mbps
); - 接口不同:
RTL8211E
采用RGMII
接口标准,而DM9000
采用MII
接口标准; - 芯片封装不同:
RTL8211E
常见的封装形式是QFN
,很容易焊接到PCB
上;而DM9000
常见的封装形式是QFP
,需要进行插件式安装;
1.4.8 配置无线网卡驱动
我使用的NanoPC-T4
开发板搭载的WiFi
模组为AP6356
,符合IEEE802.11a/b/g/n/ac 2x2 MIMO
标准,并可在802.11n
中通过双流达到867Mbps
的速度以连接无线局域网。该集成模块提供SDIO/PCIe
接口用于WiFi
,UART/PCM
接口用于蓝牙。
由于linux 5.2.8
版本并没有直接支持AP6356
,因此需要对源码和设备树进行大量调整,就不在这里介绍了。如果需要支持无线网卡的话具体参考:《Rockchip RK3399 - WiFi AP6356
驱动》。
1.4.9 屏蔽开机logo
屏蔽内核启动开机logo
:
Device Drivers --->
Graphics support --->
[] Bootup logo --->
1.4.10 保存配置
保存配置:
存档:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# mv rk3399_defconfig ./arch/arm64/configs/
重新配置内核:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# make rk3399_defconfig
1.5 修改设备树
1.5.1 配置display-subsystem
设备节点
执行如下命令:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# vim arch/arm64/boot/dts/rockchip/rk3399.dtsi
将以下节点:
display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <&vopl_out>, <&vopb_out>;
};
修改为:
display_subsystem: display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <&vopl_out>, <&vopb_out>;
};
1.5.2 配置gmac
设备节点
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
中为以下节点新增属性:
&gmac {
assigned-clock-parents = <&clkin_gmac>;
assigned-clocks = <&cru SCLK_RMII_SRC>;
clock_in_out = "input";
pinctrl-names = "default";
pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_rstb>;
phy-handle = <&rtl8211e>;
phy-mode = "rgmii";
phy-supply = <&vcc3v3_s3>;
tx_delay = <0x28>;
rx_delay = <0x11>;
status = "okay";
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
rtl8211e: ethernet-phy@1 {
reg = <1>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
reset-assert-us = <10000>;
reset-deassert-us = <30000>;
reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
};
};
};
同时配置引脚配置节点:
&pinctrl {
......
gmac {
phy_intb: phy-intb {
rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
};
phy_rstb: phy-rstb {
rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
.....
}
1.5.2 新增子节点属性
同时在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
中为以下节点新增属性:
&i2c7 {
status = "okay";
};
&display_subsystem {
status = "okay";
};
&vopl {
status = "okay";
};
&vopl_mmu {
status = "okay";
};
&vopb {
status = "okay";
};
&vopb_mmu {
status = "okay";
};
&hdmi {
ddc-i2c-bus = <&i2c7>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_cec>;
status = "okay";
};
1.6 编译内核
1.6.1 编译内核
在linux
内核根目录下执行如下命令:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# make -j8
HOSTCC scripts/extract-cert
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: 没有那个文件或目录
21 | #include <openssl/bio.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.host:95:scripts/extract-cert] 错误 1
make: *** [Makefile:1204:scripts] 错误 2
make: *** 正在等待未完成的任务....
如果出现如上错误,安装libssl-dev
即可:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# sudo apt install libssl-dev
这个编译属实有点久,如果可以的话,尽量裁切掉一些没用的驱动。
编译完成后会在linux
根目录下生成vmlinux
文件,elf
格式:这个文件属实有点大214M
,真是惊呆了;
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll vmlinux
-rwxr-xr-x 1 root root 223823704 May 23 21:00 vmlinux*
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# du -sh vmlinux
214M vmlinux
此外,在arch/arm64/boot/
文件夹下生成Image
镜像文件,以及设备树dst/rockchip/xxx.dtb
文件;
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll arch/arm64/boot
总用量 44032
drwxr-xr-x 3 root root 4096 May 16 11:28 ./
drwxr-xr-x 14 root root 4096 May 16 11:15 ../
drwxr-xr-x 33 root root 4096 May 16 10:27 dts/
-rw-r--r-- 1 root root 55 May 16 10:27 .gitignore
-rw-r--r-- 1 root root 33616384 May 16 11:27 Image
-rw-r--r-- 1 root root 134 May 16 11:27 .Image.cmd
-rw-r--r-- 1 root root 11617499 May 16 11:28 Image.gz
-rw-r--r-- 1 root root 101 May 16 11:28 .Image.gz.cmd
-rw-r--r-- 1 root root 1562 May 16 10:27 install.sh
-rw-r--r-- 1 root root 960 May 16 10:27 Makefile
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8/arch/arm64# cd arch/arm64/boot
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8/arch/arm64/boot# ls dts/rockchip/*rk3399*.dtb
dts/rockchip/rk3399-evb.dtb dts/rockchip/rk3399-gru-scarlet-kd.dtb dts/rockchip/rk3399-rock960.dtb
dts/rockchip/rk3399-ficus.dtb dts/rockchip/rk3399-nanopc-t4.dtb dts/rockchip/rk3399-rock-pi-4.dtb
dts/rockchip/rk3399-firefly.dtb dts/rockchip/rk3399-nanopi-m4.dtb dts/rockchip/rk3399-rockpro64.dtb
dts/rockchip/rk3399-gru-bob.dtb dts/rockchip/rk3399-nanopi-neo4.dtb dts/rockchip/rk3399-roc-pc.dtb
dts/rockchip/rk3399-gru-kevin.dtb dts/rockchip/rk3399-orangepi.dtb dts/rockchip/rk3399-sapphire.dtb
dts/rockchip/rk3399-gru-scarlet-inx.dtb dts/rockchip/rk3399-puma-haikou.dtb dts/rockchip/rk3399-sapphire-excavator.dtb
除此之外在arch/arm64/boot/
路径下也生成了Image.gz
文件,需要注意的是该文件和zImage
文件并不一样,该文件并没有内嵌gzip
解压缩代码,就是单纯的gzip
压缩后的文件。
1.6.2 编译dts
如果需要单独编译设备树,在linux
内核根目录执行如下命令:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# make arch/arm64/boot/dts/rockchip/rk3399-evb.dts dtbs V=1
即可把arch/arm64/boot/dts/rockchip
里的dts
文件编译成dtb
文件。
二、内核镜像文件介绍
linux
内核常用的镜像文件格式有以下几种:
vmlinux
:linux
内核编译出来的原始的内核文件,elf
格式。该文件包含了符号表、重定位等信息,可以用来调试,但不能直接引导linux
系统启动;可以使用arm-linx-readelf -h vmlinux
查看文件信息;Image
:linux
内核编译时,使用arm-linux-objcopy
处理vmlinux
后生成的二进制文件。该文件是raw binary
二进制文件,bin
文件是将elf
文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像,可直接引导linux
系统启动;Image.gz
:使用gzip
压缩Image
后得到的压缩文件;zImage
:首先将Image.gz
文件开头嵌入gzip
解压缩代码,然后编译得到elf
格式文件arch/arm/boot/compressed/vmlinux
,最后使用arm-linux-objcopy
命令对其处理生成的linux
内核镜像;uImage
:uImage
又分为两种Legacy uImage
和FIT uImage
。以Legacy uImage
为例,其在zImage
前面增加一个64
字节的头,描述镜像文件类型,加载位置,大小等信息,比如我们熟悉的Mini2440
使用的就是这种;
下图展示了不同类型的linux镜像生成过程:
2.1 vmlinux
在linux
根目录下的.vmlinux.cmd
文件可以看到vmlinux
的生成命令:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cat .vmlinux.cmd
cmd_vmlinux := /bin/bash scripts/link-vmlinux.sh arm-linux-ld -EL -maarch64elf --no-undefined -X --fix-cortex-a53-843419 --build-id ; true
2.2 Image
在linux
根目录下的arch/arm64/boot/.Image.cmd
文件可以看到vmlinux
的生成命令:
cmd_arch/arm64/boot/Image := arm-linux-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
这里利用arm-linux-objcopy
命令将elf
格式的vmlinux
文件转换为二进制文件Image
。其中 :
-O binary
:指定输出的文件格式为二进制文件;-R note
:从输出文件中删除掉所有名为.note
的段;-R .note.gnu.build-id
:从输出文件中删除掉所有名为.not.build-id
的段;-R .comment
:从输出文件中删除掉所有名为.comment
的段;-S
:不从源文件中复制重定位信息和符号信息到目标文件中;
2.3 Image.gz
在linux
根目录下的arch/arm64/boot/.Image.gz.cmd
文件可以看到vmlinux
的生成命令:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cat arch/arm64/boot/.Image.gz.cmd
cmd_arch/arm64/boot/Image.gz := cat arch/arm64/boot/Image | gzip -n -f -9 > arch/arm64/boot/Image.gz
这里使用gzip
文件对Image
文件进行压缩,处理得到Image.gz
文件;其中:
-n
:压缩文件时,不保存原来的文件名称及时间戳记;-f
:强行压缩文件。不理会文件名称或硬连接是否存在以及该文件是否为符号连接;-9
:表示高压缩比,多在创建压缩包时使用;
2.4 zImage
在arm64
的arch/arm64/boot
路径下并没有生成zImage
文件,但是我们在为Mini2440
开发板编译内核时,在arch/arm/boot/
路径下是生成了zImage
文件的。
其编译命令位于arch/arm/boot/.zImage.cmd
文件:
root@zhengyang:/work/sambashare/linux-5.2.8-dt# cat arch/arm/boot/.zImage.cmd
cmd_arch/arm/boot/zImage := arm-linux-objcopy -O binary -R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
可以看到这里利用arm-linux-objcopy
命令将arch/arm/boot/compressed/vmlinux
转换为二进制位zImage
。那问题来了arch/arm/boot/compressed/vmlinux
是哪里来的呢?
arch/arm/boot/compressed/vmlinux
的生成包括两步:
(1) 使用gzip
命令将Image
进行压缩得到piggy_data
文件;
root@zhengyang:/work/sambashare/linux-5.2.8-dt# cat arch/arm/boot/compressed/.piggy_data.cmd
cmd_arch/arm/boot/compressed/piggy_data := cat arch/arm/boot/compressed/../Image | gzip -n -f -9 > arch/arm/boot/compressed/piggy_data
(2) 将piggy_data
文件开头嵌入gzip
解压缩代码编译得到elf
格式文件arch/arm/boot/compressed/vmlinux
;
root@zhengyang:/work/sambashare/linux-5.2.8-dt# cat arch/arm/boot/compressed/.vmlinux.cmd
cmd_arch/arm/boot/compressed/vmlinux := arm-linux-ld -EL \
--defsym _kernel_bss_size=202320 \
--defsym zreladdr=0x30008000 \
--no-undefined \
-X \
-T arch/arm/boot/compressed/vmlinux.lds \
arch/arm/boot/compressed/head.o \
arch/arm/boot/compressed/piggy.o \
arch/arm/boot/compressed/misc.o \
arch/arm/boot/compressed/decompress.o \
arch/arm/boot/compressed/string.o \
arch/arm/boot/compressed/lib1funcs.o \
arch/arm/boot/compressed/ashldi3.o \
arch/arm/boot/compressed/bswapsdi2.o \
-o arch/arm/boot/compressed/vmlinux
这里是将压缩的内核镜像数据(arch/arm/boot/compressed/piggy_data
).piggydata
段中,并定义符号 input_data
和input_data_end
引用该段的开始和结束地址,具体实现在arch/arm/boot/compressed/piggy.S
文件,该文件会被编译成arch/arm/boot/compressed/piggy.o
:
/* SPDX-License-Identifier: GPL-2.0 */
.section .piggydata,#alloc
.globl input_data
input_data:
.incbin "arch/arm/boot/compressed/piggy_data"
.globl input_data_end
input_data_end:
其中,.section
指令用于切换当前段至.piggydata
段,#alloc
表示告知编译器该段需要分配内存,input_data
和input_data_end
为符号名,用于访问所在段的起始地址和结束地址。最关键的是.incbin "arch/arm/boot/compressed/piggy_data"
指令,它用于将arch/arm/boot/compressed/piggy_data
中的二进制数据按字节复制到.piggydata
段中,从而实现内核镜像数据的加载。
内核镜像数据的解压是在arch/arm/boot/compressed/misc.c
文件实现的:
extern char input_data[];
extern char input_data_end[];
extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
void
decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
unsigned long free_mem_ptr_end_p,
int arch_id)
{
int ret;
output_data = (unsigned char *)output_start;
free_mem_ptr = free_mem_ptr_p;
free_mem_end_ptr = free_mem_ptr_end_p;
__machine_arch_type = arch_id;
arch_decomp_setup();
putstr("Uncompressing Linux...");
ret = do_decompress(input_data, input_data_end - input_data,
output_data, error);
if (ret)
error("decompressor returned an error");
else
putstr(" done, booting the kernel.\n");
}
在链接arch/arm/boot/compressed/vmlinux.lds
中将段.piggydata
链接在后面:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
/DISCARD/ : {
*(.ARM.exidx*)
*(.ARM.extab*)
*(.data)
}
. = 0;
_text = .;
.text : {
_start = .;
*(.start)
*(.text)
*(.text.*)
*(.fixup)
*(.gnu.warning)
*(.glue_7t)
*(.glue_7)
}
.table : ALIGN(4) {
_table_start = .;
LONG((2))
LONG((0x5a534c4b))
LONG((__piggy_size_addr - _start))
LONG((_kernel_bss_size))
LONG(0)
_table_end = .;
}
.rodata : {
*(.rodata)
*(.rodata.*)
*(.data.rel.ro)
}
.piggydata : {
*(.piggydata)
__piggy_size_addr = . - 4;
}
. = ALIGN(4);
_etext = .;
.got.plt : { *(.got.plt) }
_got_start = .;
.got : { *(.got) }
_got_end = .;
.pad : { BYTE(0); . = ALIGN(8); }
_edata = .;
.image_end (NOLOAD) : {
_edata_real = .;
}
_magic_sig = (0x016f2818);
_magic_start = (_start);
_magic_end = (_edata);
_magic_table = (_table_start - _start);
. = ALIGN(8);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
. = ALIGN(8);
.stack : { *(.stack) }
PROVIDE(__pecoff_data_size = ALIGN(512) - ADDR(.data));
PROVIDE(__pecoff_end = ALIGN(512));
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
ASSERT(_edata_real == _edata, "error: zImage file size is incorrect");
2.5 uImage
在arm64
的arch/arm64/boot
路径下并没有生成uImage
文件。但是我们在为Mini2440
开发板编译内核时,在arch/arm/boot/
路径下是生成了uImage
文件的,更具体的说是Legacy uImage
。
其编译命令位于arch/arm/boot/.uImage.cmd
文件:
root@zhengyang:/work/sambashare/linux-5.2.8-dt# cat arch/arm/boot/.uImage.cmd
cmd_arch/arm/boot/uImage := /bin/bash ./scripts/mkuboot.sh \
-A arm \ // 架构
-O linux \ // 操作系统
-C none \ // 压缩类型为none,这样uboot就不会对镜像文件进行解压操作了;解压工作交由内核镜像头部的gzip解压代码完成
-T kernel \ // 镜像类型
-a 0x30008000 \ // 加载地址
-e 0x30008000 \ // 入口地址
-n 'Linux-5.2.8' \ // 镜像名称
-d arch/arm/boot/zImage arch/arm/boot/uImage // 输入文件
这里使用使用./scripts/mkuboot.sh
脚本来制作uImage
,最终调用mkimage
工具来制作uImage
。
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Build U-Boot image when `mkimage' tool is available.
#
MKIMAGE=$(type -path "${CROSS_COMPILE}mkimage")
if [ -z "${MKIMAGE}" ]; then
MKIMAGE=$(type -path mkimage)
if [ -z "${MKIMAGE}" ]; then
# Doesn't exist
echo '"mkimage" command not found - U-Boot images will not be built' >&2
exit 1;
fi
fi
# Call "mkimage" to create U-Boot image
${MKIMAGE} "$@"
2.5.1 加载/入口地址等
在内核移植中我们经常提到load address
、entry point
、bootm address
、kernel
运行地址,那这些地址有什么关系;
load address
:加载地址load_addr
,由mkimage -a
指定;entry point
: 入口地址entry_point
,由mkimage -e
指定;bootm address
:bootm
命令后面紧跟的地址,也就是加载地址addr
;kernel
运行地址:zImage
自解压后将kernel
解压到实际运行的物理地址;
所谓加载地址是指bootm
将内核镜像文件拷贝到内存空间的位置,入口地址是加载地址确定后bootm
从内核镜像文件中开始执行的地址。
理论上zImage
转化为uImage
需要添加0x40
长度的header
头, 所以entry_point
== load_addr
+ 0x40
。
2.5.2 bootm
对uImage
处理
(1) addr != load_addr
从addr
所在地址提取取出内核镜像头部信息中进行处理, 并将去掉头部的内核直接加载到-a
指定的地址load_addr
。
然后进入load_addr
进行内核引导(entry_point
)。所以此时地址:addr
!= load_addr
== entry_point
。
(2) addr == load_addr
也就是说bootm
后的地址等于加载地址,即已经将内核镜像(带头部)加载到-a
指定的内存地址load_addr
中。
此时:addr
== load_addr
== entry_point
- 0x40
;
2.5.3 制作镜像
以Mini2440
开发板为例,制作镜像头以及下载地址有以下两种情况:
(1) 情景一(内核linux-5.2.8
使用)
mkimage -n 'Linux-5.2.8' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage
加载地址和入口地址相同:load_addr
== entry_point
,烧录和启动命令;
tftp 0x31000000 uImage
bootm 0x31000000
# Starting kernel...之前有内核搬移(从0x31000040->0x0x30008000),并从0x30008000启动
下载地址可以任意放,也可以指定为0x30008000
,此时也进行了内核搬移,从0x30008040
->0x0x30008000
。
(2) 情景二
mkimage -n 'Linux-5.2.8' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage
入口地址在加载地址后面64个字节:entry_point
== load_addr
+ 0x40
;烧录和启动命令;
tftp 0x30008000 uImage
bootm 0x30008000
# 没有内核搬移,从从0x30008040启动
下载地址一定要在指定的加载地址上。
三、boot
启动命令解析
当我们在uboot
命令行执行了boot
命令时,uboot
会获取bootcmd
环境变量的内容,然后执行bootcmd
中保存的启动命令。接下来我们来分析一下bootcmd
默认配置。
3.1 bootcmd
在uboot include/configs/evb_rk3399.h
文件中配置了默认的启动命令:
#ifndef CONFIG_SPL_BUILD
#undef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND RKIMG_BOOTCOMMAND
#endif
而RKIMG_BOOTCOMMAND
定义在include/configs/rockchip-common.h
文件中:
#if defined(CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE)
#define RKIMG_BOOTCOMMAND \
"boot_android ${devtype} ${devnum};"
#elif defined(CONFIG_FIT_SIGNATURE)
#define RKIMG_BOOTCOMMAND \
"boot_fit;"
#else
#define RKIMG_BOOTCOMMAND \ # 这里这个会生效
"boot_android ${devtype} ${devnum};" \
"boot_fit;" \
"bootrkp;" \
"run distro_bootcmd;"
#endif
可以看到:
- 如果配置了
CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE
,则执行命令boot_android \${devtype} \${devnum}
; - 如果配置了
CONFIG_FIT_SIGNATURE
,则执行命令boot_fit
,boot_fit
命令是用来执行FIT uImage
的; - 由于前两个我们都没有配置,因此执行的命令是最后一个;
我们在uboot
命令行执行print
也可以看到cmdline
环境变量的值:
bootcmd=boot_android ${devtype} ${devnum};boot_fit;bootrkp;run distro_bootcmd;
如果后面实验环境我们烧录的内核镜像是boot.img
,那么其内核镜像格式既不是Android
,也不是FIT uImage
,因此前两种启动方式都会失败,我们从内核启动日志可以看到:
=> boot
Could not find misc partition
ANDROID: reboot reason: "(none)"
No valid android hdr
Android image load failed
Android boot failed, error -1.
## Booting FIT Image FIT: No fit blob
do_boot_fit 1
FIT: No FIT image
3.2 boot_fit
启动方式
boot_fit
启动方式使用的内核镜像为FIT uImage
。由于Rockchip
官方提供的uboot
在启动方式上做了大量魔改,尤其是bootm
命令:
do_bootm // cmd/bootm.c
// 支持
// - Android: bootm [aosp addr]
// - FIT: bootm [fit addr]
// - uImage: bootm [uimage addr]
board_do_bootm(argc,argv) // arch/arm/mach-rockchip/board.c Rockchip自己扩充的,用于从不同位置加载内核镜像
// 获取内核镜像格式 支持三种Android、FIT uImage、以及Legacy uImage;不同的内核镜像格式,处理逻辑不一样
format = (genimg_get_format(img)) //common/image.c
// 当镜像格式为FIT uImage时,会走下面的代码
bootm_image_populate_dtb(img)
rockchip_ram_read_dtb_file(img, (void *)gd->fdt_blob) // arch/arm/mach-rockchip/boot_rkimg.c
// 如果配置了CONFIG_ROCKCHIP_RESOURCE_IMAGE,这节点名字就是resource,否者就是fdt
// 关于resource节点指向的文件,应该是Rockchip自己定义的资源文件格式,相关代码位于arch/arm/mach-rockchip/resource_img.c
// 我们以fdt节点为例介绍,获取/images/fdt节点偏移
noffset = fdt_path_offset(img,"/images/fdt) // lib/libfdt/fdt_ro.c 207
//获取fdt节点data属性以及指定的dtb文件的大小
fit_image_get_data(img, noffset, &data, &size) // common/image-fit.c:900
// 获取"data"属性(返回的是指针)以及dtb文件的长度 即/incbin/("rk3399-evb.dtb")
*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
// 获取"data-size"属性,从而得dtb文件
fit_image_get_data_size(fit, noffset, &len)
// 获取"data-offset"属性,从而得到dtb文件的偏移
fit_image_get_data_offset(fit, noffset, (int *)&data_off)
// 获取"data-position"属性,该属性并不存在
fit_image_get_data_position(fit, noffset, (int *)&data_pos)
fdt_check_header(data)
memcpy(fdt, data, size)
sysmem_alloc_base(MEM_FDT, (phys_addr_t)fdt,ALIGN(fdt_totalsize(fdt), RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD)
run_command(boot_cmd, 0) // boot_cmd设置为"boot_fit <addr>" 执行bootcmd中的命令,相当于执行boot_fit addr命令
do_bootm_states(....)
这里为了适配各种镜像格式,Rockchip
自己实现了一个board_do_bootm
的逻辑,尤其是bootm_image_populate_dtb
里面又搞了一些幺蛾子,而且我对这段逻辑也没啥兴趣,所以干脆我就放弃使用bootm
命令去启动内核了,直接采用boot_fit
命令启动FIT uImage
镜像,其启动命令格式如下
=> help boot_fit
boot_fit - Boot FIT Image from memory or boot/recovery partition
Usage:
boot_fit boot_fit [addr]
其实现位于cmd/bootfit.c
以及arch/arm/mach-rockchip/fit.c
等文件,阅读代码我发现几处比较有意思的地方。
当我们把FIT uImage
下载到内存某个地址,比如0x10000000
,运行boot_fit 0x10000000
启动内核,该命令会执行do_boot_fit
函数,函数位于cmd/bootfit.c
:
static int do_boot_fit(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
char *bootm_args[1];
char fit_addr[12];
ulong size;
void *fit;
int ret;
if (argc > 2)
return CMD_RET_USAGE;
printf("## Booting FIT Image ");
if (argc == 1)
fit = do_boot_fit_storage(&size);
else
fit = do_boot_fit_ram(argv, &size);
if (!fit) {
FIT_I("No FIT image\n");
goto out;
}
if (fdt_check_header(fit)) {
FIT_I("Invalid FIT format\n");
goto out;
}
/* fixup entry/load and alloc sysmem */
if (fit_image_pre_process(fit)){
goto out;
}
env_set("bootm-no-reloc", "y");
snprintf(fit_addr, sizeof(fit_addr), "0x%lx", (ulong)fit);
bootm_args[0] = fit_addr;
printf("at %s with size 0x%08lx\n", fit_addr, size);
ret = do_bootm_states(NULL, 0, ARRAY_SIZE(bootm_args), bootm_args,
BOOTM_STATE_START |
BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
BOOTM_STATE_LOADOS |
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
BOOTM_STATE_RAMDISK |
#endif
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO, &images, 1);
if (ret && argc != 1) {
fit_image_fail_process(fit);
goto out;
}
return CMD_RET_SUCCESS;
out:
return CMD_RET_FAILURE;
}
如果boot_fit
命令只有1个参数:比如boot_fit
,则从eMMC
存储设备加载FIT uImage
并启动 。
如果boot_fit
命令有2个参数: 比如boot_fit <load_addr>
,则从RAM
启动;采用boot_fit <load_addr>
需要先将FIT-uImage
加载到内存,然后根据传入的加载地址启动内核。
3.2.1 支持fit
启动
支持从fit
启动,需要进行如下配置:
(1) 取消CONFIG_ROCKCHIP_RESOURCE_IMAGE
配置,不使用Rockchip resource
镜像; 配置CONFIG_ROCKCHIP_FIT_IMAGE
,即使用fit
镜像;
ARM architecture --->
[ ] Enable support for rockchip resource image
[*] Enable support for FIT image
(2) 配置CONFIG_CMD_BOOT_FIT
,CONFIG_CMD_BOOT_FIT
依赖CONFIG_ROCKCHIP_FIT_IMAGE
:
Command line interface --->
Device access commands --->
-*- boot_fit
在cmd/Makefile
中定义有:
obj-$(CONFIG_CMD_BOOT_FIT) += bootfit.o
在include/image.h
定义有:
#define IMAGE_ENABLE_FIT CONFIG_IS_ENABLED(FIT) // 配置了CONFIG_FIT
3.2.2 do_boot_fit_storage
这里我们看一下do_boot_fit_storage
函数是如何从eMMC
存储设备加载FIT uImage
镜像到内存的 。
fit = do_boot_fit_storage(&size); // cmd/bootfit.c
fit_image_load_bootables(size) // arch/arm/mach-rockchip/fit.c
// 获取启动设备
dev_desc = rockchip_get_bootdev();
fit = fit_get_blob(dev_desc, &part, false)
// 根据分区名获取分区信息 part_name = PART_BOOT 即"boot"
// 分区名称是写在gpt分区表中的,开始扇区0x8000,占用扇区数量0x38000 扇区大小112MB
part_get_info_by_name(dev_desc, part_name, &part) // disk/part.c
// 除法运算,向上取整 应该为 1
blk_num = DIV_ROUND_UP(sizeof(struct fdt_header), dev_desc->blksz);
// 分配一个512字节大小,地址是ARCH_DMA_MINALIGN的倍数的内存块
fdt = memalign(ARCH_DMA_MINALIGN, blk_num * dev_desc->blksz);
// 读取第一个扇区数据到fdt,地址范围0x00000000~0x00000027表示的是fdt_header结构体的成员信息
blk_dread(dev_desc, part.start, blk_num, fdt);
// 首先获取totalsize->totalsize,即计算kernel.its文件打包后在kernel.itb中所占的大小,由于我们编译指定了-E属性,因此这里计算的是不包含image data file文件的大小,更准确的说应该是fdt blob的大小
blk_num = DIV_ROUND_UP(fdt_totalsize(fdt), dev_desc->blksz);
// 分配一个blk_num*dev_desc->blksz大小,地址是ARCH_DMA_MINALIGN的倍数的内存块
fit = memalign(ARCH_DMA_MINALIGN, blk_num * dev_desc->blksz);
// 将fdt blob(不包含image)加载到内存地址fit
blk_dread(dev_desc, part.start, blk_num, fit);
经过分析我们可以推断出: 采用boot_fit
命令启动内核,必须要设置GPT
分区, 默认boot_fit
命令从eMMC
中boot
分区加载FIT-uImage
实际使用到的镜像文件到内存,然后启动内核 。
3.2.3 fit_image_pre_process
函数fit_image_pre_process
用于对FIT uImage
进行预处理:包括检查其格式是否合法、修正镜像元素的入口地址和加载地址等信息,并且在必要时分配系统内存。
fit_image_pre_process(fit) // arch/arm/mach-rockchip/fit.c
fit_image_fixup_alloc(fit, FIT_FDT_PROP,"fdt_addr_r", MEM_FDT) // 检查fdt节点
// 从环境变量获取fdt_addr_r地址 环境变量默认配置的fdt_addr_r=0x08300000
addr = env_get_ulong(addr_name, 16, 0); // addr_name="fdt_addr_r"
// 获取fdt节点data-offset属性值保存到offset变量
// 获取fdt节点data-size属性值保存到size变量
// 获取fdt镜像加载到内存的地址,保存到load变量
fit_image_get_param(fit, prop_name, &load, &offset, &size) // prop_name="fdt"
fdt_image_get_offset_size(fit, prop_name, offset, size)
// 获取fdt节点
noffset = fit_default_conf_get_node(fit, prop_name);
// 获取"data-size"属性,保存到sz
fit_image_get_data_size(fit, noffset, &sz)
// 获取"data-position"属性 没有该属性
ret = fit_image_get_data_position(fit, noffset, &offs);
if (!ret)
offs -= fdt_totalsize(fit);
else
// 获取"data-offset"属性,保存到offs
ret = fit_image_get_data_offset(fit, noffset, &offs);
// 获取fdt镜像在内存中的地址,保存到load
fdt_image_get_load(fit, prop_name, load)
// 修正fdt的入口地址和加载地址
fix_image_set_addr(fit, prop_name, load, addr); // 入参:old=load, new=addr(环境变量中的地址)
/* do not fix if verified-boot */
if (!fit_image_addr_is_placeholder(old) || // 默认不使用环境变量中的地址修正,就使用its文件文件中配置的load、entry地址
fit_sig_require_conf(fit, gd_fdt_blob()))
return 0;
// 设置fit节点entry属性值为new
fit_image_set_entry(fit, noffset, new); // common/image-fit.c
// 设置load节点entry属性值为new
fit_image_set_load(fit, noffset, new);
sysmem_alloc_base(mem, (phys_addr_t)addr,ALIGN(size, RK_BLK_SIZE))
fit_image_fixup_alloc(fit, FIT_KERNEL_PROP,"kernel_addr_r", MEM_KERNEL) // 检查kernel节点
fit_image_fixup_alloc(fit, FIT_RAMDISK_PROP,"ramdisk_addr_r", MEM_RAMDISK) // 检查ramdisk节点
do_bootm_states(....);
从这段代码中不难看出FIT uImage
必须满足以下条件:
- 必须要有
ramdisk
、kernel
、fdt
节点;(这里就很烦人,ramdisk
你限制个屁,为此我还去做了ramdisk
镜像); - 校验
kernel
、ramdisk
、ftd
的data-offset
、data-size
属性,这个就导致在使用tools/mkimage
工具生成FIT uImage
镜像的时候必须要指定-E
参数,不然生成的FIT uImage
是不会有这两个属性的;
上面有一块内容我们需要单独提一下,就是啥时候我们会使用环境变量中的fdt_addr_r
、kernel_addr_r
、ramdisk_addr_r
值去修正its
文件中配置的load
、entry
地址。具体需要看一下fit_image_addr_is_placeholder
函数实现;
#define FIT_PLACEHOLDER_ADDR 0xffffff00
static inline int fit_image_addr_is_placeholder(ulong addr)
{
return (addr & 0xffffff00) == FIT_PLACEHOLDER_ADDR;
}
可以看到如果addr
满足(addr & 0xffffff00) == 0xffffff00
时该函数就会返回true
,这样就会执行fit_image_set_entry
、fit_image_set_load
函数进行修正its
文件中配置的load
、entry
地址。
3.3 distro boot
启动方式
有关distro boot
启动方式的内容就比较多了,但这不是我们这一节的重点,我们大概看一下distro_bootcmd
命令的内容:
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
有关bistro boot
启动相关的环境变量定义在include/config_distro_bootcmd.h
文件中,有兴趣可以自行研究。
cat include/config_distro_bootcmd.h
/*
* (C) Copyright 2014
* NVIDIA Corporation <www.nvidia.com>
*
* Copyright 2014 Red Hat, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _CONFIG_CMD_DISTRO_BOOTCMD_H
#define _CONFIG_CMD_DISTRO_BOOTCMD_H
/*
* A note on error handling: It is possible for BOOT_TARGET_DEVICES to
* reference a device that is not enabled in the U-Boot configuration, e.g.
* it may include MMC in the list without CONFIG_CMD_MMC being enabled. Given
* that BOOT_TARGET_DEVICES is a macro that's expanded by the C pre-processor
* at compile time, it's not possible to detect and report such problems via
* a simple #ifdef/#error combination. Still, the code needs to report errors.
* The best way I've found to do this is to make BOOT_TARGET_DEVICES expand to
* reference a non-existent symbol, and have the name of that symbol encode
* the error message. Consequently, this file contains references to e.g.
* BOOT_TARGET_DEVICES_references_MMC_without_CONFIG_CMD_MMC. Given the
* prevalence of capitals here, this looks like a pre-processor macro and
* hence seems like it should be all capitals, but it's really an error
* message that includes some other pre-processor symbols in the text.
*/
#define BOOTENV_SHARED_BLKDEV_BODY(devtypel) \
"if " #devtypel " dev ${devnum}; then " \
"setenv devtype " #devtypel "; " \
"run scan_dev_for_boot_part; " \
"fi\0"
#define BOOTENV_SHARED_BLKDEV(devtypel) \
#devtypel "_boot=" \
BOOTENV_SHARED_BLKDEV_BODY(devtypel)
#define BOOTENV_DEV_BLKDEV(devtypeu, devtypel, instance) \
"bootcmd_" #devtypel #instance "=" \
"setenv devnum " #instance "; " \
"run " #devtypel "_boot\0"
#define BOOTENV_DEV_NAME_BLKDEV(devtypeu, devtypel, instance) \
#devtypel #instance " "
#ifdef CONFIG_SANDBOX
#define BOOTENV_SHARED_HOST BOOTENV_SHARED_BLKDEV(host)
#define BOOTENV_DEV_HOST BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_HOST BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_SHARED_HOST
#define BOOTENV_DEV_HOST \
BOOT_TARGET_DEVICES_references_HOST_without_CONFIG_SANDBOX
#define BOOTENV_DEV_NAME_HOST \
BOOT_TARGET_DEVICES_references_HOST_without_CONFIG_SANDBOX
#endif
#ifdef CONFIG_CMD_MMC
#define BOOTENV_SHARED_MMC BOOTENV_SHARED_BLKDEV(mmc)
#define BOOTENV_DEV_MMC BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_MMC BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_SHARED_MMC
#define BOOTENV_DEV_MMC \
BOOT_TARGET_DEVICES_references_MMC_without_CONFIG_CMD_MMC
#define BOOTENV_DEV_NAME_MMC \
BOOT_TARGET_DEVICES_references_MMC_without_CONFIG_CMD_MMC
#endif
#ifdef CONFIG_CMD_UBIFS
#define BOOTENV_SHARED_UBIFS \
"ubifs_boot=" \
"if ubi part UBI && ubifsmount ubi${devnum}:boot; then " \
"setenv devtype ubi; " \
"setenv bootpart 0; " \
"run scan_dev_for_boot; " \
"fi\0"
#define BOOTENV_DEV_UBIFS BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_UBIFS BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_SHARED_UBIFS
#define BOOTENV_DEV_UBIFS \
BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
#define BOOTENV_DEV_NAME_UBIFS \
BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
#endif
#ifdef CONFIG_EFI_LOADER
#if defined(CONFIG_ARM64)
#define BOOTEFI_NAME "bootaa64.efi"
#elif defined(CONFIG_ARM)
#define BOOTEFI_NAME "bootarm.efi"
#endif
#endif
#ifdef BOOTEFI_NAME
#if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
/*
* On 32bit ARM systems there is a reasonable number of systems that follow
* the $soc-$board$boardver.dtb name scheme for their device trees. Use that
* scheme if we don't have an explicit fdtfile variable.
*/
#define BOOTENV_EFI_SET_FDTFILE_FALLBACK \
"if test -z \"${fdtfile}\" -a -n \"${soc}\"; then " \
"setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; " \
"fi; "
#else
#define BOOTENV_EFI_SET_FDTFILE_FALLBACK
#endif
#define BOOTENV_SHARED_EFI \
"boot_efi_binary=" \
"load ${devtype} ${devnum}:${distro_bootpart} " \
"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; " \
"if fdt addr ${fdt_addr_r}; then " \
"bootefi ${kernel_addr_r} ${fdt_addr_r};" \
"else " \
"bootefi ${kernel_addr_r} ${fdtcontroladdr};" \
"fi\0" \
\
"load_efi_dtb=" \
"load ${devtype} ${devnum}:${distro_bootpart} " \
"${fdt_addr_r} ${prefix}${efi_fdtfile}\0" \
\
"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0" \
"scan_dev_for_efi=" \
"setenv efi_fdtfile ${fdtfile}; " \
BOOTENV_EFI_SET_FDTFILE_FALLBACK \
"for prefix in ${efi_dtb_prefixes}; do " \
"if test -e ${devtype} " \
"${devnum}:${distro_bootpart} " \
"${prefix}${efi_fdtfile}; then " \
"run load_efi_dtb; " \
"fi;" \
"done;" \
"if test -e ${devtype} ${devnum}:${distro_bootpart} " \
"efi/boot/"BOOTEFI_NAME"; then " \
"echo Found EFI removable media binary " \
"efi/boot/"BOOTEFI_NAME"; " \
"run boot_efi_binary; " \
"echo EFI LOAD FAILED: continuing...; " \
"fi; " \
"setenv efi_fdtfile\0"
#define SCAN_DEV_FOR_EFI "run scan_dev_for_efi;"
#else
#define BOOTENV_SHARED_EFI
#define SCAN_DEV_FOR_EFI
#endif
#ifdef CONFIG_SATA
#define BOOTENV_SHARED_SATA BOOTENV_SHARED_BLKDEV(sata)
#define BOOTENV_DEV_SATA BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_SATA BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_SHARED_SATA
#define BOOTENV_DEV_SATA \
BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_SATA
#define BOOTENV_DEV_NAME_SATA \
BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_SATA
#endif
#ifdef CONFIG_SCSI
#define BOOTENV_RUN_SCSI_INIT "run scsi_init; "
#define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; "
#define BOOTENV_SHARED_SCSI \
"scsi_init=" \
"if ${scsi_need_init}; then " \
"setenv scsi_need_init false; " \
"scsi scan; " \
"fi\0" \
\
"scsi_boot=" \
BOOTENV_RUN_SCSI_INIT \
BOOTENV_SHARED_BLKDEV_BODY(scsi)
#define BOOTENV_DEV_SCSI BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_SCSI BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_RUN_SCSI_INIT
#define BOOTENV_SET_SCSI_NEED_INIT
#define BOOTENV_SHARED_SCSI
#define BOOTENV_DEV_SCSI \
BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI
#define BOOTENV_DEV_NAME_SCSI \
BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI
#endif
#ifdef CONFIG_IDE
#define BOOTENV_SHARED_IDE BOOTENV_SHARED_BLKDEV(ide)
#define BOOTENV_DEV_IDE BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_IDE BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_SHARED_IDE
#define BOOTENV_DEV_IDE \
BOOT_TARGET_DEVICES_references_IDE_without_CONFIG_IDE
#define BOOTENV_DEV_NAME_IDE \
BOOT_TARGET_DEVICES_references_IDE_without_CONFIG_IDE
#endif
#if defined(CONFIG_DM_PCI)
#define BOOTENV_RUN_NET_PCI_ENUM "run boot_net_pci_enum; "
#define BOOTENV_SHARED_PCI \
"boot_net_pci_enum=pci enum\0"
#else
#define BOOTENV_RUN_NET_PCI_ENUM
#define BOOTENV_SHARED_PCI
#endif
#ifdef CONFIG_CMD_USB
#define BOOTENV_RUN_NET_USB_START "run boot_net_usb_start; "
#define BOOTENV_SHARED_USB \
"boot_net_usb_start=usb start\0" \
"usb_boot=" \
"usb start; " \
BOOTENV_SHARED_BLKDEV_BODY(usb)
#define BOOTENV_DEV_USB BOOTENV_DEV_BLKDEV
#define BOOTENV_DEV_NAME_USB BOOTENV_DEV_NAME_BLKDEV
#else
#define BOOTENV_RUN_NET_USB_START
#define BOOTENV_SHARED_USB
#define BOOTENV_DEV_USB \
BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
#define BOOTENV_DEV_NAME_USB \
BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
#endif
#if defined(CONFIG_CMD_DHCP)
#if defined(CONFIG_EFI_LOADER)
#if defined(CONFIG_ARM64)
#define BOOTENV_EFI_PXE_ARCH "0xb"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00011:UNDI:003000"
#elif defined(CONFIG_ARM)
#define BOOTENV_EFI_PXE_ARCH "0xa"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00010:UNDI:003000"
#elif defined(CONFIG_X86)
/* Always assume we're running 64bit */
#define BOOTENV_EFI_PXE_ARCH "0x7"
#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00007:UNDI:003000"
#else
#error Please specify an EFI client identifier
#endif
/*
* Ask the dhcp server for an EFI binary. If we get one, check for a
* device tree in the same folder. Then boot everything. If the file was
* not an EFI binary, we just return from the bootefi command and continue.
*/
#define BOOTENV_EFI_RUN_DHCP \
"setenv efi_fdtfile ${fdtfile}; " \
BOOTENV_EFI_SET_FDTFILE_FALLBACK \
"setenv efi_old_vci ${bootp_vci};" \
"setenv efi_old_arch ${bootp_arch};" \
"setenv bootp_vci " BOOTENV_EFI_PXE_VCI ";" \
"setenv bootp_arch " BOOTENV_EFI_PXE_ARCH ";" \
"if dhcp ${kernel_addr_r}; then " \
"tftpboot ${fdt_addr_r} dtb/${efi_fdtfile};" \
"if fdt addr ${fdt_addr_r}; then " \
"bootefi ${kernel_addr_r} ${fdt_addr_r}; " \
"else " \
"bootefi ${kernel_addr_r} ${fdtcontroladdr};" \
"fi;" \
"fi;" \
"setenv bootp_vci ${efi_old_vci};" \
"setenv bootp_arch ${efi_old_arch};" \
"setenv efi_fdtfile;" \
"setenv efi_old_arch;" \
"setenv efi_old_vci;"
#else
#define BOOTENV_EFI_RUN_DHCP
#endif
#define BOOTENV_DEV_DHCP(devtypeu, devtypel, instance) \
"bootcmd_dhcp=" \
BOOTENV_RUN_NET_USB_START \
BOOTENV_RUN_NET_PCI_ENUM \
"if dhcp ${scriptaddr} ${boot_script_dhcp}; then " \
"source ${scriptaddr}; " \
"fi;" \
BOOTENV_EFI_RUN_DHCP \
"\0"
#define BOOTENV_DEV_NAME_DHCP(devtypeu, devtypel, instance) \
"dhcp "
#else
#define BOOTENV_DEV_DHCP \
BOOT_TARGET_DEVICES_references_DHCP_without_CONFIG_CMD_DHCP
#define BOOTENV_DEV_NAME_DHCP \
BOOT_TARGET_DEVICES_references_DHCP_without_CONFIG_CMD_DHCP
#endif
#if defined(CONFIG_CMD_DHCP) && defined(CONFIG_CMD_PXE)
#define BOOTENV_DEV_PXE(devtypeu, devtypel, instance) \
"bootcmd_pxe=" \
BOOTENV_RUN_NET_USB_START \
BOOTENV_RUN_NET_PCI_ENUM \
"dhcp; " \
"if pxe get; then " \
"pxe boot; " \
"fi\0"
#define BOOTENV_DEV_NAME_PXE(devtypeu, devtypel, instance) \
"pxe "
#else
#define BOOTENV_DEV_PXE \
BOOT_TARGET_DEVICES_references_PXE_without_CONFIG_CMD_DHCP_or_PXE
#define BOOTENV_DEV_NAME_PXE \
BOOT_TARGET_DEVICES_references_PXE_without_CONFIG_CMD_DHCP_or_PXE
#endif
#define BOOTENV_DEV_NAME(devtypeu, devtypel, instance) \
BOOTENV_DEV_NAME_##devtypeu(devtypeu, devtypel, instance)
#define BOOTENV_BOOT_TARGETS \
"boot_targets=" BOOT_TARGET_DEVICES(BOOTENV_DEV_NAME) "\0"
#define BOOTENV_DEV(devtypeu, devtypel, instance) \
BOOTENV_DEV_##devtypeu(devtypeu, devtypel, instance)
#define BOOTENV \
BOOTENV_SHARED_HOST \
BOOTENV_SHARED_MMC \
BOOTENV_SHARED_PCI \
BOOTENV_SHARED_USB \
BOOTENV_SHARED_SATA \
BOOTENV_SHARED_SCSI \
BOOTENV_SHARED_IDE \
BOOTENV_SHARED_UBIFS \
BOOTENV_SHARED_EFI \
"boot_prefixes=/ /boot/\0" \
"boot_scripts=boot.scr.uimg boot.scr\0" \
"boot_script_dhcp=boot.scr.uimg\0" \
BOOTENV_BOOT_TARGETS \
\
"boot_extlinux=" \
"sysboot ${devtype} ${devnum}:${distro_bootpart} any " \
"${scriptaddr} ${prefix}extlinux/extlinux.conf\0" \
\
"scan_dev_for_extlinux=" \
"if test -e ${devtype} " \
"${devnum}:${distro_bootpart} " \
"${prefix}extlinux/extlinux.conf; then " \
"echo Found ${prefix}extlinux/extlinux.conf; " \
"run boot_extlinux; " \
"echo SCRIPT FAILED: continuing...; " \
"fi\0" \
\
"boot_a_script=" \
"load ${devtype} ${devnum}:${distro_bootpart} " \
"${scriptaddr} ${prefix}${script}; " \
"source ${scriptaddr}\0" \
\
"scan_dev_for_scripts=" \
"for script in ${boot_scripts}; do " \
"if test -e ${devtype} " \
"${devnum}:${distro_bootpart} " \
"${prefix}${script}; then " \
"echo Found U-Boot script " \
"${prefix}${script}; " \
"run boot_a_script; " \
"echo SCRIPT FAILED: continuing...; " \
"fi; " \
"done\0" \
\
"scan_dev_for_boot=" \
"echo Scanning ${devtype} " \
"${devnum}:${distro_bootpart}...; " \
"for prefix in ${boot_prefixes}; do " \
"run scan_dev_for_extlinux; " \
"run scan_dev_for_scripts; " \
"done;" \
SCAN_DEV_FOR_EFI \
"\0" \
\
"scan_dev_for_boot_part=" \
"part list ${devtype} ${devnum} -bootable devplist; " \
"env exists devplist || setenv devplist 1; " \
"for distro_bootpart in ${devplist}; do " \
"if fstype ${devtype} " \
"${devnum}:${distro_bootpart} " \
"bootfstype; then " \
"run scan_dev_for_boot; " \
"fi; " \
"done\0" \
\
BOOT_TARGET_DEVICES(BOOTENV_DEV) \
\
"distro_bootcmd=" BOOTENV_SET_SCSI_NEED_INIT \
"for target in ${boot_targets}; do " \
"run bootcmd_${target}; " \
"done\0"
#ifndef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND "run distro_bootcmd"
#endif
#endif /* _CONFIG_CMD_DISTRO_BOOTCMD_H */
最终distro boot
启动机制会从我们的eMMC
中boot
分区加载内核镜像,然后启动内核,因此需要确保GPT
分区表没有问题,不然uboot
是无法找到boot
分区的内核镜像的。
而根路径的挂载是由内核完成的,内核通过启动命令中配置的root=PARTUUID=B921B045-1D
找到根文件系统所在的分区(块设备号为179:5
、即/dev/mmcblk0p5
),然后将根路径挂载到/dev/mmcblk0p5
设备节点。
[ 1.856037] EXT4-fs (mmcblk0p5): mounted filesystem with ordered data mode. Opts: (null)
[ 1.865144] VFS: Mounted root (ext4 filesystem) on device 179:5.
[ 1.873579] devtmpfs: mounted
四、distro boot
启动内核镜像制作
Rockchp
官方uboot
给出的使用教程就是使用distro boot
方式启动内核,其需要我们制作一个包含内核镜像和设备树的启动分区。
4.1 目录结构
创建一个名为boot
的文件夹:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# mkdir boot
然后,将设备树二进制文件复制到该文件夹中,这里我们和uboot
移植一样,选择官方的评估板对应的设备树文件rk3399-evb.dtb
:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cp arch/arm64/boot/dts/rockchip/rk3399-evb.dtb boot/rk3399.dtb
接着,将内核镜像复制到该文件夹中:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cp arch/arm64/boot/Image boot/
为了实现distro
引导,我们需要在启动分区中添加extlinux
引导程序以及相应的配置文件。
我们需要创建一个名为extlinux
的文件夹,在其中创建一个名为extlinux.conf
的文件:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# mkdir boot/extlinux
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# touch boot/extlinux/extlinux.conf
在所有这些文件都准备好之后,boot
文件夹结构如下:
boot
├── extlinux
│ └── extlinux.conf
├── Image
└── rk3399-evb.dtb
4.2 extlinux.conf
在extlinux.conf
文件中编写配置信息,指定内核镜像和设备树的路径,以及其它启动参数。配置文件内容如下:
label rockchip-kernel-5.2.8
kernel /Image
fdt /rk3399.dtb
append earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rw rootwait rootfstype=ext4 init=/sbin/init
4.2.1 earlycon
这里最后一行实际上就是配置uboot
的bootargs
参数,这里首先设置了:
earlycon=uart8250,mmio32,0xff1a0000
ARM64
在kernel
未建立console
之前,使用earlycon
,实现日志信息的打印,因此首先配置了earlycon
:其中:
uart8250
表示针对uart8250
这个串口设备;mio32
表示内存I/O
资源32
位,0xff1a0000
是RK3399 UART2
寄存器基地址,这里没有配置波特率,默认还是使用uboot
中配置的波特率。
4.2.2 console
接着设置了控制台console
,当RK3399 UART2
控制台驱动注册之后,将会注销earlycon
驱动,将内核输出的日志通过指定的console
打印出来。
console=ttyS2,1500000n8
如果我们没有设置console
,那么console
将会使用tty0
这个终端(tty0
表示当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上。有关虚拟终端的信息,可以参考《linux
驱动移植-tty架构)》,这将导致内核启动日志输出到如下这个位置将会停止(即无法通过串口输出):
[ 0.015084] printk: console [tty0] enabled
[ 0.019585] printk: bootconsole [uart8250] disabled
注意:我们需要根据自己的开发板配置串口。
4.2.3 root
指定根文件系统以及根文件系统类型;通过root
属性指定根文件系统所在位置,通常这是一个必须明确设置的选项,格式如下:
root=字符串 rw rootwait rootfstype=ext4
rw
表示可以对根文件系统进行读写,默认配置是只读;
rootwait
表示在根文件系统就绪之前无限等待。主要用于等待那些反应速度较慢的异步检测的设备就绪(例如USB/MMC/FireWire)
;
rootfstype
为根文件系统类型;
“字符串”可以采用如下几种形式:
XXxx
:一个16
进制数,其中XX
是主设备号,xx
是次设备号。例如/dev/sdc15
(主设备号是8
,次设备号是47
),可以表示成082F
;/dev/nfs
:表示使用nfsroot
选项指定的NFS
磁盘,仅在根文件系统位于NFS
文件系统上的时候才可以使用,比如配置成root=/dev/nfs rw rootwait nfsroot=192.168.0.200:/work/nfs_root/ubuntu,vers=4 ip=192.168.0.105:192.168.0.200:192.168.0.1:255.255.255.0::eth0:off
;/dev/disk
:表示一块完整的无分区块设备。比如/dev/mmcblk0
、/dev/sdb
;/dev/diskN
:表示disk
磁盘的第N
个分区,这是最常见的写法,比如:/dev/mtdblock3
、/dev/mmcblk0p5
、/dev/sda2
;PARTUUID=b921b045-1df0-41c3-af44-4c6f280d3fae
:仅用于EFI/GPT
格式的磁盘,表示分区表中UUID
值为b921b045-1df0-41c3-af44-4c6f280d3fae
的分区;PARTUUID=SSSSSSSS-PP
:仅用于传统的MSDOS
分区表,SSSSSSSS
是用16
进制表示的32
位NT disk signature
,PP
是用16
进制表示的分区号。比如:PARTUUID=97531ACF-02
可能相当于/dev/sda2
;major:minor
由一对十进制数组成,其中major
是主设备号,minor
是次设备号。例如/dev/sdc15
(主设备号是8
,次设备号是47
),可以表示成8:47
。
在uboot
命令行下我们使用mmc part
查看分区UUID
:
=> mmc part
Partition Map for MMC device 0 -- Partition Type: EFI
Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
1 0x00000040 0x00001f7f "loader1"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: 8ef917d1-5bd0-2c4f-9a33-b225b21cf919
2 0x00004000 0x00005fff "loader2"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: 77877125-2374-ad40-8b02-609e37971c59
3 0x00006000 0x00007fff "trust"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: b4b84b8a-f8ae-0443-b5af-3605b195c4c9
4 0x00008000 0x0003ffff "boot"
attrs: 0x0000000000000004
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: 35219908-db08-c643-9133-2213191e57ff
5 0x00040000 0x01d1efde "rootfs"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: b921b045-1df0-41c3-af44-4c6f280d3fae
我们发现rootfs
分区对应的UUID
为b921b045-1df0-41c3-af44-4c6f280d3fae
,而我们上面配置的root=PARTUUID=B921B045-1D
并不是上面我们介绍的任意一种方式,但是这个是Rockchip
官方给的示例,运行也是没问题的。如果采用PARTUUID
的方式。按照我们上面说的应该配置为:
root=PARTUUID=b921b045-1df0-41c3-af44-4c6f280d3fae
4.3 ext2
镜像
使用genext2fs
工具可以生成一个ext2
文件系统镜像文件。在使用genext2fs
命令时,需要指定生成文件系统的大小、块大小、inode
大小等参数,以及输出的镜像文件名称和所在路径。
执行以下命令,将boot
文件夹中的文件和目录打包成一个ext2
文件系统镜像:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# sudo apt-get install genext2fs
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# genext2fs -b 32768 -B $((64*1024*1024/32768)) -d boot/ -i 8192 -U boot.img
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ll boot.img
-rw-r--r-- 1 root root 33554432 May 17 05:17 boot.img
其中:
-b
:表示文件系统块的数量;-B
: 表示文件系统块的大小,单位为字节;-d
:从指定目录开始创建文件系统-i 8192
;每个inode
使用的字节数;-U
:选项表示创建一个唯一的文件系统UUID
;
这里我们设置了32768
个块,每个块大小为64*1024*1024/32768
,所以文件系统总大小为64MB
,足够放下boot
文件夹内的所有文件。
五、FIT uImage
镜像制作
我们在《Mini2440
之uboot
移植流程之linux
内核启动分析》中介绍过FIT uImage
的制作流程,其通过一定语法和格式将一些需要使用到的镜像(例如kernel
、dtb
以及文件系统)组合到一起生成一个image file
。
5.1 Image.gz
linux
内核5.2.8
版本的编译完成后会在arch/arm64/boot/
文件夹下生成内核镜像文件Image
,其中Image
是内核镜像原生二进制文件,可以直接在芯片上运行的,由于Image
文件较大,我们将Image
压缩转换为Image.gz
(内核编译默认也会生成这个文件):
cat arch/arm64/boot/Image | gzip -n -f -9 > arch/arm64/boot/Image.gz
5.2 创建its
文件
因为mkimage
是根据its
文件中的描述来打包镜像生成itb
文件(FIT uImage
),所以首先需要制作一个its
文件,在its
文件中描述需要被打包的镜像,主要是kernel
镜像,dtb
文件,ramdisk
镜像。
我们创建一个kernel.its
文件,内容如下:
/*
* Simple U-Boot uImage source file containing a single kernel and FDT blob
*/
/dts-v1/;
/ {
description = "Simple image with single Linux kernel and FDT blob";
#address-cells = <1>;
images {
kernel {
description = "Vanilla Linux kernel";
data = /incbin/("arch/arm64/boot/Image.gz");
type = "kernel";
arch = "arm64";
os = "linux";
compression = "gzip";
load = <0x280000>;
entry = <0x280000>;
hash-1 {
algo = "crc32";
};
hash-2 {
algo = "sha1";
};
};
fdt {
description = "Flattened Device Tree blob";
data = /incbin/("arch/arm64/boot/dts/rockchip/rk3399-evb.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
load = <0x8300000>;
entry = <0x8300000>;
hash-1 {
algo = "crc32";
};
hash-2 {
algo = "sha1";
};
};
ramdisk {
description = "Ramdisk for project-x";
data = /incbin/("ramdisk.gz");
type = "ramdisk";
arch = "arm64";
os = "linux";
load = <00000000>;
entry = <00000000>;
compression = "gzip";
hash-1 {
algo = "crc32";
};
};
};
configurations {
default = "conf-1";
conf-1 {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel";
fdt = "fdt";
ramdisk = "ramdisk";
};
};
};
这里我们内核镜像使用的Image.gz
文件,该文件是通过gzip
对Image
进行压缩得到的,因此需要在kernel
属性中指定compression
,这样uboot
才知道如何解压。
5.2.1 内核加载地址0x280000
这里有一点一定要注意:kernel
的load
、entry
地址一定要指定为0x280000
;我最初将load
、entry
都指定为0x20000000
、0x20080000
,后来又尝试了0x200000
,uboot
启动内核时都会卡在Starting kernel
...,就这个小小的问题我排查了好多天,说多了这都是泪啊;那我后来是怎么发现load
、entry
加载地址有问题的呢?
因为distro boot
启动内核的方式(Rockchip
官方推荐的)是可以成功启动内核的。所以我修改了arch/arm/lib/bootm.c
文件,将images->ep
(Image
镜像的加载地址)、images->fd_addr
(fdt
的加载地址)信息打印出来。
/* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
void (*kernel_entry)(void *fdt_addr, void *res0, void *res1,
void *res2);
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
int es_flag = 0;
#if defined(CONFIG_AMP)
es_flag = arm64_switch_amp_pe(images);
#elif defined(CONFIG_ARM64_SWITCH_TO_AARCH32)
es_flag = arm64_switch_aarch32(images);
#endif
kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1,
void *res2))images->ep;
printf("## Transferring control to Linux (at address %lx)...\n",
(ulong) kernel_entry);
printf("%s 0x%x=0x%x \n",__func__,images->ep,*((unsigned int *)images->ep));
printf("%s 0x%x=0x%x \n",__func__,images->ep + 4,*((unsigned int *)(images->ep + 4) ));
printf("%s 0x%x=0x%x \n",__func__,images->ep + 20,*((unsigned int *)(images->ep + 20) ));
printf("%s 0x%x=0x%x \n",__func__,images->ft_addr,*((unsigned int *)images->ft_addr));
printf("%s 0x%x=0x%x \n",__func__,((unsigned int *)images->ft_addr)+1,*((unsigned int *)images->ft_addr+1));
printf("%s 0x%x=0x%x \n",__func__,((unsigned int *)images->ft_addr)+5,*((unsigned int *)images->ft_addr+5));
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(images, fake); // 这里面会输出Starting kernel
if (!fake) {
#ifdef CONFIG_ARMV8_PSCI // 不会走
armv8_setup_psci();#endif
do_nonsec_virt_switch();
update_os_arch_secondary_cores(images->os.arch);
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 // 不会走
armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
(u64)switch_to_el1, ES_TO_AARCH64);
#else
if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
(images->os.arch == IH_ARCH_ARM)){
armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number,
(u64)images->ft_addr, es_flag,
(u64)images->ep,
ES_TO_AARCH32);
}else { // 走这里
armv8_switch_to_el2((u64)images->ft_addr, 0, 0, es_flag,
images->ep,
ES_TO_AARCH64);
}
#endif
}
...... // 后面是非CONFIG_ARM64成立时,才会走的代码
}
当采用distro boot
方式启动内核时,这是当时打印出来的内容:
## Transferring control to Linux (at address 280000)...
boot_jump_linux 0x280000=0x91005a4d
boot_jump_linux 0x280004=0x14433fff
boot_jump_linux 0x280014=0x0
boot_jump_linux 0x8300000=0xedfe0dd0
boot_jump_linux 0x8300004=0xc00000
boot_jump_linux 0x8300014=0x11000000
Total: 5818.548 ms
Starting kernel ...
而采用boot_fit
启动方式时,我配置的kernel.its
文件kernel
节点load
、entry
为0x20000000
时,打印出来的内容:
## Transferring control to Linux (at address 20000000)...
boot_jump_linux 0x20000000=0x91005a4d
boot_jump_linux 0x20000004=0x14433fff
boot_jump_linux 0x20000014=0x0
boot_jump_linux 0xf4606000=0xedfe0dd0
boot_jump_linux 0xf4606004=0xc00000
boot_jump_linux 0xf4606014=0x11000000
同时比对这两次启动输出的ep
、fd_addr
内容差异:我发现kernel
、fdt
都成功加载到内存了,除了加载的地址不一样,但是内存的数据是完全一样的。
最开始我也没有往加载地址这方面去想,然后就开始百度,各种尝试。然而网上相关资料少之又少;后来我尝试了很多办法:
(1) 最初我想的是会不会是内核启动时卡住了,所以我就去定位内核日志缓冲区log_buf
在内存的地址,然后去查看该内存的内容,但是该缓冲区并没有任何有用的数据;我就开始怀疑人生了,难道是我排查的方法有问题,在文章结尾我会记录这种方法;实际上现在回想起来,内核代码应该都没有执行到,直接卡在了armv8_switch_to_el2
函数;该函数等后面我们有时间再研究;
(2) 然后又在想是不是启动参数bootargs
配置的有问题,导致内核日志没有通过串口打印出来,专文为此我还去研究了一下earlycon
控制台驱动和uart8250
串口驱动;但是同样的bootargs
配置,采用distro boot
方式启动内核内核时时有日志输出的,所以就排除了这个原因;
(3) 后来我发现distro boot
方式启动内核会从环境变量中获取kernel
以及fdt
的加载地址,我就想着要不按照这个改一下,后来尝试发现内核竟然真的可以启动了,撒花啊......,至于为啥一定要配置kernel
的load
地址为0x280000
,目前我还不知道原因,等后面有时间研究一下。
fdt_addr_r=0x08300000
kernel_addr_r=0x00280000
5.2.2 ramdisk
关于ramdisk
根文件系统的制作可以参考《ramdisk
根文件系统镜像》。
5.3 生成kernel.itb
FIT image
文件的编译过程很简单,这里我们需要将uboot
路径下的mkimage
工具拷贝过来,然后在命令行使用mkimage
工具编译即可:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cp ../u-boot/tools/mkimage ./
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# ./mkimage -f kernel.its -E kernel.itb
需要注意的是这里一定要指定-E
参数,不然image data file
就会被放到FIT
结构里面。
《Rockchip RK3399
- 移植uboot 2023.04 & linux 6.3
》中移植uboot 2023.04
版本的时候,烧录的FIT uImage
在编译的的时候是不可以指定-E
参数的。
六、烧录内核
6.1 准备镜像
我们按照之前的流程得到了如下文件idbloader.img
、u-boot.itb
,boot.img
、kernel.itb
、busybox_ext4_rootfs.img
。
关于Rockchip
官方uboot 2017.09
镜像制作参考:《Rockchip RK3399 - TPL/SPL
方式加载uboot
》。
关于ext4
根文件系统镜像制作参考:《Rockchip RK3399 - busybox 1.36.0
制作根文件系统制作》。
按照Rockchip
官方要求将:
idbloader.img
烧录到eMMC
的0x40
扇区;u-boot.itb
烧录到0x4000
扇区;- 如果采用
boot_fit
启动方式,烧录kernel.itb
到0x8000
扇区;如果采用distro boot
启动机制,烧录boot.img
烧录到0x8000
扇区; busybox_ext4_rootfs.img
烧录到0x40000
扇区;
我们需要将idbloader.img
、u-boot.itb
、boot.img
、kernel.itb
、busybox_ext4_rootfs.img
拷贝到rkdeveloptool
路径下:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../u-boot/idbloader.img ./
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../u-boot/u-boot.itb ./
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../linux-5.2.8/boot.img ./
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../linux-5.2.8/kernel.itb ./
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# cp ../rootfs/busybox_ext4_rootfs.img ./
6.2 进入MASKROM
升级模式
NanoPC-T4
开发板如需进入MASKROM
升级模式,需要进入如下操作:
- 将开发板连接上电源,并且连接
Type-C
数据线到PC
; - 按住
BOOT
键再长按Power
键开机(保持按下BOOT
键5秒以上),将强制进入MASKROM
模式。
一般电脑识别到USB
连接,都会发出声音。或者观察虚拟机右下角是否突然多个USB
设备:右键点击链接;
6.3 烧录boot.img
使用下载引导命令去使目标机器初始化DDR
与运行usbplug
(初始化DDR
的原因是由于升级需要很大的内存,所以需要使用到DDR
);
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool db rk3399_loader_v1.27.126.bin
Downloading bootloader succeeded.
由于BootROM
启动会将rk3399_loader_v1.27.126.bin
将在到内部SRAM
中,然后跳转到ddr.bin
代码进行DDR
的初始化,ddr.bin
执行之后会回跳到BootROM
程序,BootROM
程序继续加载usbplug.bin
,由usbplug.bin
完成程序的下载以及烧录到eMMC
。
使用wl
命令烧写镜像到目标机器的eMMC
,需要注意的是访问DDR
所需的所有其他命令都应在使用db
命令之后才能使用;
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x40 idbloader.img
Write LBA from file (100%)
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x4000 u-boot.itb
Write LBA from file (100%)
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x8000 boot.img
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x40000 busybox_ext4_rootfs.img
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd
需要注意我们这里烧录的时内核镜像是boot.img
,也就意味着采用distro boot
启动方式。
在烧写镜像完成后使用rd
命令重启目标机器:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd
Reset Device OK.
6.3.1 设置GPT
分区表
重启开发板,在倒计时执行完之前,按CTRL+C
即可进入uboot
命令行。使用以下命令将分区信息写入GPT
分区表:
=> gpt write mmc 0 $partitions
Writing GPT: success!
其中mmc 0
表示eMMC
设备编号为0
,partitions
是存储分区表的环境变量,定义在include/configs/rockchip-common.h
文件:
#ifdef CONFIG_ARM64
#define ROOT_UUID "B921B045-1DF0-41C3-AF44-4C6F280D3FAE;\0"
#else
#define ROOT_UUID "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3;\0"
#endif
#define PARTS_DEFAULT \
"uuid_disk=${uuid_gpt_disk};" \
"name=loader1,start=32K,size=4000K,uuid=${uuid_gpt_loader1};" \
"name=loader2,start=8MB,size=4MB,uuid=${uuid_gpt_loader2};" \
"name=trust,size=4M,uuid=${uuid_gpt_atf};" \
"name=boot,size=112M,bootable,uuid=${uuid_gpt_boot};" \
"name=rootfs,size=-,uuid="ROOT_UUID
通过uboot
命令行环境变量可以看到分区信息:
partitions=uuid_disk=${uuid_gpt_disk}; \
name=loader1,start=32K,size=4000K,uuid=${uuid_gpt_loader1}; \ // eMMC 0x40扇区
name=loader2,start=8MB,size=4MB,uuid=${uuid_gpt_loader2}; \ // eMMC 0x4000扇区
name=trust,size=4M,uuid=${uuid_gpt_atf}; \ // eMMC 0x6000扇区
name=boot,size=112M,bootable,uuid=${uuid_gpt_boot}; \ // eMMC 0x8000扇区
name=rootfs,size=-,uuid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE; // eMMC 0x40000扇区
6.3.2 验证GPT
分区表
使用以下命令验证GPT
分区表是否成功写入:
=> gpt verify mmc 0 $partitions
Verify GPT: success!
6.3.3 boot
命令启动内核
我们在uboot
命令行输入boot
命令,将会进行内核的启动,输出内容比较多:
U-Boot TPL 2017.09-gef1dd65-dirty #root (May 25 2023 - 20:51:38)
Channel 0: LPDDR3, 800MHz
BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=32 Size=2048MB
Channel 1: LPDDR3, 800MHz
BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=32 Size=2048MB
256B stride
Returning to boot ROM...
U-Boot SPL board init
U-Boot SPL 2017.09-gef1dd65-dirty #root (May 25 2023 - 20:51:38)
rockchip_sdhci_probe
Trying to boot from MMC1
Trying fit image at 0x4000 sector
## Verified-boot: 0
## Checking atf@1 0x00040000 ... sha256(5c636c7ea9...) + OK
## Checking uboot 0x00200000 ... sha256(900454cc1d...) + OK
## Checking fdt 0x002d4820 ... sha256(5416082316...) + OK
## Checking atf@2 0xff3b0000 ... sha256(ce42caf496...) + OK
## Checking atf@3 0xff8c0000 ... sha256(68c573972f...) + OK
## Checking atf@4 0xff8c1000 ... sha256(50a7da66c2...) + OK
## Checking atf@5 0xff8c2000 ... sha256(e3b0c44298...) + OK
board_init_r
addr 0x00000000 = 0x14000001
addr 0x00000004 = 0x14000009
addr 0x00000008 = 0x0
addr 0x00040000 = 0xaa0003f4
addr 0x00050018 = 0xb8656883
addr 0xff8c2000 = 0x33334b52
Jumping to U-Boot(0x00200000) via ARM Trusted Firmware(0x00040000)
Total: 921.750 ms
NOTICE: BL31: v2.8(release):41914de
NOTICE: BL31: Built : 09:31:58, May 11 2023
U-Boot 2017.09-gef1dd65-dirty #root (May 25 2023 - 20:51:51 +0800)
Model: Rockchip RK3399 Evaluation Board
Serial: raw, 0xff1a0000
DRAM: 3.9 GiB
Sysmem: init
Relocation Offset: f5ba2000
Relocation fdt: f3d89500 - f3d98ce0
CR: M/C/I
I2c0 speed: 400000Hz
PMIC: RK808
vdd_center init 950000 uV
Using default environment
MMC: rockchip_sdhci_probe
dwmmc@fe320000: 1, sdhci@fe330000: 0
Card did not respond to voltage select!
mmc_init: -95, time 12
switch to partitions #0, OK
mmc0(part 0) is current device
Bootdev(scan): mmc 0
MMC0: HS400, 150Mhz
PartType: EFI
Could not find baseparameter partition
In: serial
Out: serial
Err: serial
Model: Rockchip RK3399 Evaluation Board
No misc partition
boot mode: None
failed to display uboot logo
CLK: (uboot. arml: enter 816000 KHz, init 816000 KHz, kernel 0N/A)
CLK: (uboot. armb: enter 816000 KHz, init 816000 KHz, kernel 0N/A)
aplll 816000 KHz
apllb 816000 KHz
dpll 800000 KHz
cpll 24000 KHz
gpll 800000 KHz
npll 600000 KHz
vpll 24000 KHz
aclk_perihp 133333 KHz
hclk_perihp 66666 KHz
pclk_perihp 33333 KHz
aclk_perilp0 266666 KHz
hclk_perilp0 88888 KHz
pclk_perilp0 44444 KHz
hclk_perilp1 100000 KHz
pclk_perilp1 50000 KHz
No misc partition
Net: eth0: ethernet@fe300000
Hit key to stop autoboot('CTRL+C'): 0
=> boot
Could not find misc partition
ANDROID: reboot reason: "(none)"
No valid android hdr
Android image load failed
Android boot failed, error -1.
## Booting FIT Image FIT: No fit blob
do_boot_fit 1
FIT: No FIT image
## Booting Rockchip Format Image
Could not find kernel partition, ret=-1
Card did not respond to voltage select!
mmc_init: -95, time 13
switch to partitions #0, OK
mmc0(part 0) is current device
Scanning mmc 0:4...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
204 bytes read in 3 ms (66.4 KiB/s)
1: rockchip-kernel-5.2.8
Retrieving file: /Image
20945408 bytes read in 104 ms (192.1 MiB/s)
append: earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rootwait rootfstype=ext4 init=/sbin/init
Retrieving file: /rk3399.dtb
47365 bytes read in 3 ms (15.1 MiB/s)
Fdt Ramdisk skip relocation
No misc partition
## Flattened Device Tree blob at 0x08300000
Booting using the fdt blob at 0x08300000
Using Device Tree in place at 0000000008300000, end 000000000830e904
can't found rockchip,drm-logo, use rockchip,fb-logo
WARNING: could not set reg FDT_ERR_BADOFFSET.
failed to reserve fb-loader-logo memory
Adding bank: 0x00200000 - 0xf8000000 (size: 0xf7e00000)
Total: 8842.674 ms
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[ 0.000000] Linux version 5.2.8 (root@zhengyang) (gcc version 12.2.1 20221205 (Arm GNU Toolchain 12.2.Rel1 (Build arm-12.24))) #2 SMP PREEMPT Tue May 23 20:59:23 CST 2023
[ 0.000000] Machine model: Rockchip RK3399 Evaluation Board
[ 0.000000] earlycon: uart8250 at MMIO32 0x00000000ff1a0000 (options '')
[ 0.000000] printk: bootconsole [uart8250] enabled
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] cma: Reserved 32 MiB at 0x00000000f6000000
[ 0.000000] kmemleak: Kernel memory leak detector disabled
[ 0.000000] NUMA: No NUMA configuration found
[ 0.000000] NUMA: Faking a node at [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] NUMA: NODE_DATA [mem 0xf57fb840-0xf57fcfff]
[ 0.000000] Zone ranges:
[ 0.000000] DMA32 [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.1 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] psci: SMC Calling Convention v1.0
[ 0.000000] percpu: Embedded 23 pages/cpu s56728 r8192 d29288 u94208
[ 0.000000] Detected VIPT I-cache on CPU0
[ 0.000000] CPU features: detected: ARM erratum 845719
[ 0.000000] CPU features: detected: GIC system register CPU interface
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 999432
[ 0.000000] Policy zone: DMA32
[ 0.000000] Kernel command line: earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rw rootwait rootfstype=ext4 init=/sbin/init
[ 0.000000] Memory: 3933112K/4061184K available (11324K kernel code, 1766K rwdata, 5836K rodata, 1472K init, 444K bss, 95304K reserved, 32768K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=6, Nodes=1
[ 0.000000] rcu: Preemptible hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=6.
[ 0.000000] Tasks RCU enabled.
[ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=6
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[ 0.000000] GICv3: Distributor has no Range Selector support
[ 0.000000] GICv3: no VLPI support, no direct LPI support
[ 0.000000] GICv3: CPU0: found redistributor 0 region 0:0x00000000fef00000
[ 0.000000] ITS [mem 0xfee20000-0xfee3ffff]
[ 0.000000] ITS@0x00000000fee20000: allocated 65536 Devices @f1080000 (flat, esz 8, psz 64K, shr 0)
[ 0.000000] ITS: using cache flushing for cmd queue
[ 0.000000] GICv3: using LPI property table @0x00000000f1040000
[ 0.000000] GIC: using cache flushing for LPI property table
[ 0.000000] GICv3: CPU0: using allocated LPI pending table @0x00000000f1050000
[ 0.000000] GICv3: GIC: PPI partition interrupt-partition-0[0] { /cpus/cpu@0[0] /cpus/cpu@1[1] /cpus/cpu@2[2] /cpus/cpu@3[3] }
[ 0.000000] GICv3: GIC: PPI partition interrupt-partition-1[1] { /cpus/cpu@100[4] /cpus/cpu@101[5] }
[ 0.000000] random: get_random_bytes called from start_kernel+0x2a8/0x440 with crng_init=0
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] arch_timer: cp15 timer(s) running at 24.00MHz (phys).
[ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[ 0.000005] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[ 0.010210] Console: colour dummy device 80x25
[ 0.015130] kmemleak: Early log buffer exceeded (4684), please increase DEBUG_KMEMLEAK_EARLY_LOG_SIZE
[ 0.025317] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
[ 0.036588] pid_max: default: 32768 minimum: 301
[ 0.041738] LSM: Security Framework initializing
[ 0.048451] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[ 0.057192] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[ 0.064982] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[ 0.072380] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[ 0.104306] ASID allocator initialised with 32768 entries
[ 0.118264] rcu: Hierarchical SRCU implementation.
[ 0.131636] Platform MSI: interrupt-controller@fee20000 domain created
[ 0.139066] PCI/MSI: /interrupt-controller@fee00000/interrupt-controller@fee20000 domain created
[ 0.151625] EFI services will not be available.
[ 0.164627] smp: Bringing up secondary CPUs ...
[ 0.201789] Detected VIPT I-cache on CPU1
[ 0.201821] GICv3: CPU1: found redistributor 1 region 0:0x00000000fef20000
[ 0.201834] GICv3: CPU1: using allocated LPI pending table @0x00000000f1060000
[ 0.201873] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[ 0.233839] Detected VIPT I-cache on CPU2
[ 0.233861] GICv3: CPU2: found redistributor 2 region 0:0x00000000fef40000
[ 0.233872] GICv3: CPU2: using allocated LPI pending table @0x00000000f1070000
[ 0.233898] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[ 0.265908] Detected VIPT I-cache on CPU3
[ 0.265928] GICv3: CPU3: found redistributor 3 region 0:0x00000000fef60000
[ 0.265939] GICv3: CPU3: using allocated LPI pending table @0x00000000f1100000
[ 0.265962] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[ 0.297987] CPU features: detected: EL2 vector hardening
[ 0.297992] ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware
[ 0.297998] Detected PIPT I-cache on CPU4
[ 0.298023] GICv3: CPU4: found redistributor 100 region 0:0x00000000fef80000
[ 0.298034] GICv3: CPU4: using allocated LPI pending table @0x00000000f1110000
[ 0.298061] CPU4: Booted secondary processor 0x0000000100 [0x410fd082]
[ 0.330060] Detected PIPT I-cache on CPU5
[ 0.330078] GICv3: CPU5: found redistributor 101 region 0:0x00000000fefa0000
[ 0.330089] GICv3: CPU5: using allocated LPI pending table @0x00000000f1120000
[ 0.330110] CPU5: Booted secondary processor 0x0000000101 [0x410fd082]
[ 0.330195] smp: Brought up 1 node, 6 CPUs
[ 0.482328] SMP: Total of 6 processors activated.
[ 0.487494] CPU features: detected: 32-bit EL0 Support
[ 0.493154] CPU features: detected: CRC32 instructions
[ 0.499591] CPU: All CPU(s) started at EL2
[ 0.504131] alternatives: patching kernel code
[ 0.511658] devtmpfs: initialized
[ 0.521401] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.532153] futex hash table entries: 2048 (order: 5, 131072 bytes)
[ 0.539757] pinctrl core: initialized pinctrl subsystem
[ 0.546795] DMI not present or invalid.
[ 0.551385] NET: Registered protocol family 16
[ 0.556675] audit: initializing netlink subsys (disabled)
[ 0.562708] audit: type=2000 audit(0.436:1): state=initialized audit_enabled=0 res=1
[ 0.571254] cpuidle: using governor menu
[ 0.575737] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[ 0.588022] DMA: preallocated 256 KiB pool for atomic allocations
[ 0.595917] Serial: AMBA PL011 UART driver
[ 0.629686] HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
[ 0.637059] HugeTLB registered 32.0 MiB page size, pre-allocated 0 pages
[ 0.644438] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[ 0.651795] HugeTLB registered 64.0 KiB page size, pre-allocated 0 pages
[ 0.661374] cryptd: max_cpu_qlen set to 1000
[ 0.670618] ACPI: Interpreter disabled.
[ 0.676345] vcc5v0_host: supplied by vcc5v0_sys
[ 0.683098] vgaarb: loaded
[ 0.686335] SCSI subsystem initialized
[ 0.690832] usbcore: registered new interface driver usbfs
[ 0.696950] usbcore: registered new interface driver hub
[ 0.702855] usbcore: registered new device driver usb
[ 0.709212] pps_core: LinuxPPS API ver. 1 registered
[ 0.714722] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[ 0.724769] PTP clock support registered
[ 0.729207] EDAC MC: Ver: 3.0.0
[ 0.733803] FPGA manager framework
[ 0.737647] Advanced Linux Sound Architecture Driver Initialized.
[ 0.744843] clocksource: Switched to clocksource arch_sys_counter
[ 0.751682] VFS: Disk quotas dquot_6.6.0
[ 0.756035] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.763739] pnp: PnP ACPI: disabled
[ 0.774794] NET: Registered protocol family 2
[ 0.779903] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes)
[ 0.788617] TCP established hash table entries: 32768 (order: 6, 262144 bytes)
[ 0.796898] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[ 0.804683] TCP: Hash tables configured (established 32768 bind 32768)
[ 0.811979] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[ 0.818685] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[ 0.826011] NET: Registered protocol family 1
[ 0.831125] RPC: Registered named UNIX socket transport module.
[ 0.837822] RPC: Registered udp transport module.
[ 0.842988] RPC: Registered tcp transport module.
[ 0.848153] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.855229] PCI: CLS 0 bytes, default 64
[ 0.860245] hw perfevents: enabled with armv8_cortex_a53 PMU driver, 7 counters available
[ 0.869489] hw perfevents: enabled with armv8_cortex_a72 PMU driver, 7 counters available
[ 0.878720] kvm [1]: IPA Size Limit: 40bits
[ 0.883831] kvm [1]: vgic-v2@fff20000
[ 0.887871] kvm [1]: GIC system register CPU interface enabled
[ 0.894409] kvm [1]: vgic interrupt IRQ10
[ 0.898990] kvm [1]: Hyp mode initialized successfully
[ 0.912062] Initialise system trusted keyrings
[ 0.917100] workingset: timestamp_bits=44 max_order=20 bucket_order=0
[ 0.930050] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.937099] NFS: Registering the id_resolver key type
[ 0.942663] Key type id_resolver registered
[ 0.947254] Key type id_legacy registered
[ 0.951791] 9p: Installing v9fs 9p2000 file system support
[ 0.958926] Key type asymmetric registered
[ 0.963434] Asymmetric key parser 'x509' registered
[ 0.968822] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[ 0.976947] io scheduler mq-deadline registered
[ 0.981921] io scheduler kyber registered
[ 0.999882] EINJ: ACPI disabled.
[ 1.009768] dma-pl330 ff6d0000.dma-controller: Loaded driver for PL330 DMAC-241330
[ 1.018096] dma-pl330 ff6d0000.dma-controller: DBUFF-32x8bytes Num_Chans-6 Num_Peri-12 Num_Events-12
[ 1.029384] dma-pl330 ff6e0000.dma-controller: Loaded driver for PL330 DMAC-241330
[ 1.037715] dma-pl330 ff6e0000.dma-controller: DBUFF-128x8bytes Num_Chans-8 Num_Peri-20 Num_Events-16
[ 1.051833] pwm-regulator: supplied by regulator-dummy
[ 1.061368] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[ 1.070090] printk: console [ttyS2] disabled
[ 1.074831] ff1a0000.serial: ttyS2 at MMIO 0xff1a0000 (irq = 30, base_baud = 1500000) is a 16550A
[ 1.084727] printk: console [ttyS2] enabled
[ 1.084727] printk: console [ttyS2] enabled
[ 1.094100] printk: bootconsole [uart8250] disabled
[ 1.094100] printk: bootconsole [uart8250] disabled
[ 1.106191] SuperH (H)SCI(F) driver initialized
[ 1.111853] msm_serial: driver initialized
[ 1.117561] cacheinfo: Unable to detect cache hierarchy for CPU 0
[ 1.130723] loop: module loaded
[ 1.138942] libphy: Fixed MDIO Bus: probed
[ 1.143793] tun: Universal TUN/TAP device driver, 1.6
[ 1.150296] thunder_xcv, ver 1.0
[ 1.153950] thunder_bgx, ver 1.0
[ 1.157584] nicpf, ver 1.0
[ 1.161283] hclge is initializing
[ 1.164996] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
[ 1.173074] hns3: Copyright (c) 2017 Huawei Corporation.
[ 1.179072] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[ 1.185598] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[ 1.192250] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.6.0-k
[ 1.200035] igb: Copyright (c) 2007-2014 Intel Corporation.
[ 1.206301] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
[ 1.215058] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[ 1.222064] sky2: driver version 1.30
[ 1.226917] VFIO - User Level meta-driver version: 0.3
[ 1.234341] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 1.241654] ehci-pci: EHCI PCI platform driver
[ 1.246655] ehci-platform: EHCI generic platform driver
[ 1.254702] ehci-platform fe380000.usb: EHCI Host Controller
[ 1.261053] ehci-platform fe380000.usb: new USB bus registered, assigned bus number 1
[ 1.270465] ehci-platform fe380000.usb: irq 26, io mem 0xfe380000
[ 1.292861] ehci-platform fe380000.usb: USB 2.0 started, EHCI 1.00
[ 1.300232] hub 1-0:1.0: USB hub found
[ 1.304451] hub 1-0:1.0: 1 port detected
[ 1.311237] ehci-platform fe3c0000.usb: EHCI Host Controller
[ 1.317590] ehci-platform fe3c0000.usb: new USB bus registered, assigned bus number 2
[ 1.326551] ehci-platform fe3c0000.usb: irq 28, io mem 0xfe3c0000
[ 1.348863] ehci-platform fe3c0000.usb: USB 2.0 started, EHCI 1.00
[ 1.356191] hub 2-0:1.0: USB hub found
[ 1.360410] hub 2-0:1.0: 1 port detected
[ 1.365174] ehci-orion: EHCI orion driver
[ 1.369817] ehci-exynos: EHCI EXYNOS driver
[ 1.374597] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[ 1.381523] ohci-pci: OHCI PCI platform driver
[ 1.386543] ohci-platform: OHCI generic platform driver
[ 1.392534] ohci-platform fe3a0000.usb: Generic Platform OHCI controller
[ 1.400044] ohci-platform fe3a0000.usb: new USB bus registered, assigned bus number 3
[ 1.409015] ohci-platform fe3a0000.usb: irq 27, io mem 0xfe3a0000
[ 1.477372] hub 3-0:1.0: USB hub found
[ 1.481593] hub 3-0:1.0: 1 port detected
[ 1.486344] ohci-platform fe3e0000.usb: Generic Platform OHCI controller
[ 1.493856] ohci-platform fe3e0000.usb: new USB bus registered, assigned bus number 4
[ 1.502774] ohci-platform fe3e0000.usb: irq 29, io mem 0xfe3e0000
[ 1.573281] hub 4-0:1.0: USB hub found
[ 1.577506] hub 4-0:1.0: 1 port detected
[ 1.582250] ohci-exynos: OHCI EXYNOS driver
[ 1.587560] usbcore: registered new interface driver usb-storage
[ 1.597324] i2c /dev entries driver
[ 1.607951] sdhci: Secure Digital Host Controller Interface driver
[ 1.614864] sdhci: Copyright(c) Pierre Ossman
[ 1.620222] Synopsys Designware Multimedia Card Interface Driver
[ 1.627946] sdhci-pltfm: SDHCI platform and OF driver helper
[ 1.635763] mmc0: CQHCI version 5.10
[ 1.665711] mmc0: SDHCI controller on fe330000.sdhci [fe330000.sdhci] using ADMA
[ 1.675725] ledtrig-cpu: registered to indicate activity on CPUs
[ 1.683873] usbcore: registered new interface driver usbhid
[ 1.690167] usbhid: USB HID core driver
[ 1.698423] NET: Registered protocol family 17
[ 1.703575] 9pnet: Installing 9P2000 support
[ 1.708396] Key type dns_resolver registered
[ 1.714078] registered taskstats version 1
[ 1.718701] Loading compiled-in X.509 certificates
[ 1.744185] hctosys: unable to open rtc device (rtc0)
[ 1.750572] ALSA device list:
[ 1.753925] No soundcards found.
[ 1.757934] ttyS2 - failed to request DMA
[ 1.762531] Waiting for root device PARTUUID=B921B045-1D...
[ 1.787575] mmc0: Command Queue Engine enabled
[ 1.792572] mmc0: new HS400 Enhanced strobe MMC card at address 0001
[ 1.804391] mmcblk0: mmc0:0001 AJNB4R 14.6 GiB
[ 1.809668] mmcblk0boot0: mmc0:0001 AJNB4R partition 1 4.00 MiB
[ 1.816490] mmcblk0boot1: mmc0:0001 AJNB4R partition 2 4.00 MiB
[ 1.823672] mmcblk0rpmb: mmc0:0001 AJNB4R partition 3 4.00 MiB, chardev (237:0)
[ 1.836490] mmcblk0: p1 p2 p3 p4 p5
[ 1.856037] EXT4-fs (mmcblk0p5): mounted filesystem with ordered data mode. Opts: (null)
[ 1.865144] VFS: Mounted root (ext4 filesystem) on device 179:5.
[ 1.873579] devtmpfs: mounted
[ 1.877696] Freeing unused kernel memory: 1472K
[ 1.921261] Run /sbin/init as init process
[ 1.985061] usb 4-1: new low-speed USB device number 2 using ohci-platform
Please press Enter to activate this console. [ 2.229953] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0001/input/input0
[ 2.242646] hid-generic 0003:1C4F:0065.0001: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
[ 4.628916] usb 4-1: USB disconnect, device number 2
[ 5.017065] usb 4-1: new low-speed USB device number 3 using ohci-platform
[ 5.261859] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0002/input/input1
[ 5.274573] hid-generic 0003:1C4F:0065.0002: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
[ 7.663956] usb 4-1: USB disconnect, device number 3
[ 7.720959] random: fast init done
[ 8.053066] usb 4-1: new low-speed USB device number 4 using ohci-platform
[ 8.297920] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0003/input/input2
[ 8.310618] hid-generic 0003:1C4F:0065.0003: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
[ 10.699883] usb 4-1: USB disconnect, device number 4
[ 11.089066] usb 4-1: new low-speed USB device number 5 using ohci-platform
[ 11.333832] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0004/input/input3
[ 11.346505] hid-generic 0003:1C4F:0065.0004: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
[ 13.736998] usb 4-1: USB disconnect, device number 5
[ 14.105066] usb 4-1: new low-speed USB device number 6 using ohci-platform
[ 14.349886] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0005/input/input4
[ 14.362579] hid-generic 0003:1C4F:0065.0005: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
[ 17.735239] usb 4-1: USB disconnect, device number 6
[ 18.145064] usb 4-1: new low-speed USB device number 7 using ohci-platform
[ 18.388670] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0006/input/input5
[ 18.401560] hid-generic 0003:1C4F:0065.0006: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
6.4 烧录kernel.itb
使用下载引导命令去使目标机器初始化DDR
与运行usbplug
(初始化DDR
的原因是由于升级需要很大的内存,所以需要使用到DDR
);
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool db rk3399_loader_v1.27.126.bin
Downloading bootloader succeeded.
由于BootROM
启动会将rk3399_loader_v1.27.126.bin
将在到内部SRAM
中,然后跳转到ddr.bin
代码进行DDR
的初始化,ddr.bin
执行之后会回跳到BootROM
程序,BootROM
程序继续加载usbplug.bin
,由usbplug.bin
完成程序的下载以及烧录到eMMC
。
使用wl
命令烧写镜像到目标机器的eMMC
,需要注意的是访问DDR
所需的所有其他命令都应在使用db
命令之后才能使用;
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x40 idbloader.img
Write LBA from file (100%)
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x4000 u-boot.itb
Write LBA from file (100%)
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x8000 kernel.itb
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool wl 0x40000 busybox_ext4_rootfs.img
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd
需要注意我们这里烧录的时内核镜像是kernel.itb
,也就意味着采用boo_fit
启动方式。
在烧写镜像完成后使用rd
命令重启目标机器:
root@zhengyang:/work/sambashare/rk3399/rkdeveloptool# rkdeveloptool rd
Reset Device OK.
6.4.1 设置GPT
分区表
重启开发板,在倒计时执行完之前,按CTRL+C
即可进入uboot
命令行。使用以下命令将分区信息写入GPT
分区表:
=> gpt write mmc 0 $partitions
Writing GPT: success!
6.4.2 验证GPT
分区表
使用以下命令验证GPT
分区表是否成功写入:
=> gpt verify mmc 0 $partitions
Verify GPT: success!
6.4.3 设置ip
以及bootargs
这里我们这是本机和服务器的ip
地址:
=> setenv ipaddr 192.168.0.105
=> setenv serverip 192.168.0.200
=> saveenv
Saving Environment to MMC... Writing to MMC(0)... OK
设置启动命令参数:
=> setenv bootargs earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rw rootwait rootfstype=ext4 init=/sbin/init
=> saveenv
Saving Environment to MMC... Writing to MMC(0)... OK
=> print bootargs
bootargs=earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rw rootwait rootfstype=ext4 init=/sbin/init
6.4.4 boot_fit
命令启动内核
我们在uboot
命令行输入boot_fit
命令,将会进行内核的启动,输出内容比较多:
=> boot_fit
## Booting FIT Image fdt_image_get_offset_size noffset=464
fdt_image_get_offset_size sz=47365
fdt_image_get_offset_size offs=8648704
fdt_image_get_offset_size noffset=148
fdt_image_get_offset_size sz=8648300
fdt_image_get_offset_size offs=0
fdt_image_get_offset_size noffset=760
fdt_image_get_offset_size sz=134661
fdt_image_get_offset_size offs=8696320
fdt_image_get_offset_size noffset=464
fdt_image_get_offset_size sz=47365
fdt_image_get_offset_size offs=8648704
fit_image_fixup_alloc fdt offset=0x83f800,size=47365,fit=0xf331bf00,load=0x8300000
fit_image_fixup_alloc fdt addr=0x8300000
fdt_image_get_offset_size noffset=148
fdt_image_get_offset_size sz=8648300
fdt_image_get_offset_size offs=0
fit_image_fixup_alloc kernel offset=0x0,size=8648300,fit=0xf331bf00,load=0x280000
fit_image_fixup_alloc kernel addr=0x280000
fdt_image_get_offset_size noffset=760
fdt_image_get_offset_size sz=134661
fdt_image_get_offset_size offs=8696320
fit_image_fixup_alloc ramdisk offset=0x84b200,size=134661,fit=0xf331bf00,load=0x0
fit_image_fixup_alloc ramdisk addr=0xa200000
at 0xf331bf00 with size 0x0086c800
Fdt Ramdisk skip relocation
No misc partition
## Loading kernel from FIT Image at f331bf00 ...
Using 'conf-1' configuration
## Verified-boot: 0
Trying 'kernel' kernel subimage
Description: Vanilla Linux kernel
Type: Kernel Image
Compression: gzip compressed
Data Start: 0xf331c500
Data Size: 8648300 Bytes = 8.2 MiB
Architecture: AArch64
OS: Linux
Load Address: 0x00280000
Entry Point: 0x00280000
Hash algo: crc32
Hash value: 6470c524
Hash algo: sha1
Hash value: b0f2e3608a5689b77fc110e7c399cf6a0398c691
Verifying Hash Integrity ... crc32+ sha1+ OK
## Loading ramdisk from FIT Image at f331bf00 ...
Using 'conf-1' configuration
Trying 'ramdisk' ramdisk subimage
Description: Ramdisk for project-x
Type: RAMDisk Image
Compression: gzip compressed
Data Start: 0xf3b67700
Data Size: 134661 Bytes = 131.5 KiB
Architecture: AArch64
OS: Linux
Load Address: 0x00000000
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 649c78d3
Verifying Hash Integrity ... crc32+ OK
## Loading fdt from FIT Image at f331bf00 ...
Using 'conf-1' configuration
Trying 'fdt' fdt subimage
Description: Flattened Device Tree blob
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0xf3b5bd00
Data Size: 47365 Bytes = 46.3 KiB
Architecture: AArch64
Load Address: 0x08300000
Hash algo: crc32
Hash value: 2489ab59
Hash algo: sha1
Hash value: 002b18a40044056ce9097742d3cf5f4480338521
Verifying Hash Integrity ... crc32+ sha1+ OK
Loading fdt from 0xf3b5bd00 to 0x08300000
Booting using the fdt blob at 0x08300000
Uncompressing GZIP Kernel Image from 0xf331c500 to 0x00280000 ... with 013f9a00 bytes OK
kernel loaded at 0x00280000, end = 0x01679a00
Using Device Tree in place at 0000000008300000, end 000000000830e904
can't found rockchip,drm-logo, use rockchip,fb-logo
WARNING: could not set reg FDT_ERR_BADOFFSET.
failed to reserve fb-loader-logo memory
Adding bank: 0x00200000 - 0xf8000000 (size: 0xf7e00000)
## Transferring control to Linux (at address 280000)...
boot_jump_linux 0x280000=0x91005a4d
boot_jump_linux 0x280004=0x14433fff
boot_jump_linux 0x280014=0x0
boot_jump_linux 0x8300000=0xedfe0dd0
boot_jump_linux 0x8300004=0x80c00000
boot_jump_linux 0x8300014=0x11000000
Total: 13990.773 ms
Starting kernel ...
4
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[ 0.000000] Linux version 5.2.8 (root@zhengyang) (gcc version 12.2.1 20221205 (Arm GNU Toolchain 12.2.Rel1 (Build arm-12.24))) #2 SMP PREEMPT Tue May 23 20:59:23 CST 2023
[ 0.000000] Machine model: Rockchip RK3399 Evaluation Board
[ 0.000000] earlycon: uart8250 at MMIO32 0x00000000ff1a0000 (options '')
[ 0.000000] printk: bootconsole [uart8250] enabled
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] cma: Reserved 32 MiB at 0x00000000f6000000
[ 0.000000] kmemleak: Kernel memory leak detector disabled
[ 0.000000] NUMA: No NUMA configuration found
[ 0.000000] NUMA: Faking a node at [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] NUMA: NODE_DATA [mem 0xf57fb840-0xf57fcfff]
[ 0.000000] Zone ranges:
[ 0.000000] DMA32 [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000200000-0x00000000f7ffffff]
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.1 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] psci: SMC Calling Convention v1.0
[ 0.000000] percpu: Embedded 23 pages/cpu s56728 r8192 d29288 u94208
[ 0.000000] Detected VIPT I-cache on CPU0
[ 0.000000] CPU features: detected: ARM erratum 845719
[ 0.000000] CPU features: detected: GIC system register CPU interface
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 999432
[ 0.000000] Policy zone: DMA32
[ 0.000000] Kernel command line: earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 root=PARTUUID=B921B045-1D rw rootwait rootfstype=ext4 init=/sbin/init
[ 0.000000] Memory: 3932392K/4061184K available (11324K kernel code, 1766K rwdata, 5836K rodata, 1472K init, 444K bss, 96024K reserved, 32768K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=6, Nodes=1
[ 0.000000] rcu: Preemptible hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=6.
[ 0.000000] Tasks RCU enabled.
[ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=6
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[ 0.000000] GICv3: Distributor has no Range Selector support
[ 0.000000] GICv3: no VLPI support, no direct LPI support
[ 0.000000] GICv3: CPU0: found redistributor 0 region 0:0x00000000fef00000
[ 0.000000] ITS [mem 0xfee20000-0xfee3ffff]
[ 0.000000] ITS@0x00000000fee20000: allocated 65536 Devices @f5080000 (flat, esz 8, psz 64K, shr 0)
[ 0.000000] ITS: using cache flushing for cmd queue
[ 0.000000] GICv3: using LPI property table @0x00000000f5040000
[ 0.000000] GIC: using cache flushing for LPI property table
[ 0.000000] GICv3: CPU0: using allocated LPI pending table @0x00000000f5050000
[ 0.000000] GICv3: GIC: PPI partition interrupt-partition-0[0] { /cpus/cpu@0[0] /cpus/cpu@1[1] /cpus/cpu@2[2] /cpus/cpu@3[3] }
[ 0.000000] GICv3: GIC: PPI partition interrupt-partition-1[1] { /cpus/cpu@100[4] /cpus/cpu@101[5] }
[ 0.000000] random: get_random_bytes called from start_kernel+0x2a8/0x440 with crng_init=0
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] rockchip_mmc_get_phase: invalid clk rate
[ 0.000000] arch_timer: cp15 timer(s) running at 24.00MHz (phys).
[ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[ 0.000005] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[ 0.010121] Console: colour dummy device 80x25
[ 0.015042] kmemleak: Early log buffer exceeded (4684), please increase DEBUG_KMEMLEAK_EARLY_LOG_SIZE
[ 0.025233] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
[ 0.036504] pid_max: default: 32768 minimum: 301
[ 0.041653] LSM: Security Framework initializing
[ 0.048374] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[ 0.057122] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[ 0.064911] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[ 0.072307] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[ 0.104234] ASID allocator initialised with 32768 entries
[ 0.118192] rcu: Hierarchical SRCU implementation.
[ 0.131559] Platform MSI: interrupt-controller@fee20000 domain created
[ 0.138983] PCI/MSI: /interrupt-controller@fee00000/interrupt-controller@fee20000 domain created
[ 0.151314] EFI services will not be available.
[ 0.164315] smp: Bringing up secondary CPUs ...
[ 0.201476] Detected VIPT I-cache on CPU1
[ 0.201508] GICv3: CPU1: found redistributor 1 region 0:0x00000000fef20000
[ 0.201521] GICv3: CPU1: using allocated LPI pending table @0x00000000f5060000
[ 0.201559] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[ 0.233526] Detected VIPT I-cache on CPU2
[ 0.233549] GICv3: CPU2: found redistributor 2 region 0:0x00000000fef40000
[ 0.233560] GICv3: CPU2: using allocated LPI pending table @0x00000000f5070000
[ 0.233587] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[ 0.265596] Detected VIPT I-cache on CPU3
[ 0.265616] GICv3: CPU3: found redistributor 3 region 0:0x00000000fef60000
[ 0.265627] GICv3: CPU3: using allocated LPI pending table @0x00000000f5100000
[ 0.265652] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[ 0.297676] CPU features: detected: EL2 vector hardening
[ 0.297682] ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware
[ 0.297688] Detected PIPT I-cache on CPU4
[ 0.297713] GICv3: CPU4: found redistributor 100 region 0:0x00000000fef80000
[ 0.297724] GICv3: CPU4: using allocated LPI pending table @0x00000000f5110000
[ 0.297750] CPU4: Booted secondary processor 0x0000000100 [0x410fd082]
[ 0.329749] Detected PIPT I-cache on CPU5
[ 0.329768] GICv3: CPU5: found redistributor 101 region 0:0x00000000fefa0000
[ 0.329778] GICv3: CPU5: using allocated LPI pending table @0x00000000f5120000
[ 0.329799] CPU5: Booted secondary processor 0x0000000101 [0x410fd082]
[ 0.329885] smp: Brought up 1 node, 6 CPUs
[ 0.482017] SMP: Total of 6 processors activated.
[ 0.487183] CPU features: detected: 32-bit EL0 Support
[ 0.492843] CPU features: detected: CRC32 instructions
[ 0.499277] CPU: All CPU(s) started at EL2
[ 0.503817] alternatives: patching kernel code
[ 0.511344] devtmpfs: initialized
[ 0.521079] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.531837] futex hash table entries: 2048 (order: 5, 131072 bytes)
[ 0.539489] pinctrl core: initialized pinctrl subsystem
[ 0.546498] DMI not present or invalid.
[ 0.551092] NET: Registered protocol family 16
[ 0.556389] audit: initializing netlink subsys (disabled)
[ 0.562426] audit: type=2000 audit(0.436:1): state=initialized audit_enabled=0 res=1
[ 0.570968] cpuidle: using governor menu
[ 0.575462] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[ 0.587730] DMA: preallocated 256 KiB pool for atomic allocations
[ 0.595616] Serial: AMBA PL011 UART driver
[ 0.601747] OF: amba_device_add() failed (-19) for /amba/dma-controller@ff6d0000
[ 0.610030] OF: amba_device_add() failed (-19) for /amba/dma-controller@ff6e0000
[ 0.643533] HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
[ 0.650912] HugeTLB registered 32.0 MiB page size, pre-allocated 0 pages
[ 0.658281] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[ 0.665640] HugeTLB registered 64.0 KiB page size, pre-allocated 0 pages
[ 0.675116] cryptd: max_cpu_qlen set to 1000
[ 0.683936] ACPI: Interpreter disabled.
[ 0.689577] vcc5v0_host: supplied by vcc5v0_sys
[ 0.696370] vgaarb: loaded
[ 0.699587] SCSI subsystem initialized
[ 0.704058] usbcore: registered new interface driver usbfs
[ 0.710127] usbcore: registered new interface driver hub
[ 0.716023] usbcore: registered new device driver usb
[ 0.722315] pps_core: LinuxPPS API ver. 1 registered
[ 0.727778] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[ 0.737825] PTP clock support registered
[ 0.742263] EDAC MC: Ver: 3.0.0
[ 0.746861] FPGA manager framework
[ 0.750680] Advanced Linux Sound Architecture Driver Initialized.
[ 0.757903] clocksource: Switched to clocksource arch_sys_counter
[ 0.764743] VFS: Disk quotas dquot_6.6.0
[ 0.769094] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.776803] pnp: PnP ACPI: disabled
[ 0.787910] NET: Registered protocol family 2
[ 0.793099] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes)
[ 0.801837] TCP established hash table entries: 32768 (order: 6, 262144 bytes)
[ 0.810118] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[ 0.818112] TCP: Hash tables configured (established 32768 bind 32768)
[ 0.825411] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[ 0.832119] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[ 0.839460] NET: Registered protocol family 1
[ 0.844644] RPC: Registered named UNIX socket transport module.
[ 0.851151] RPC: Registered udp transport module.
[ 0.856318] RPC: Registered tcp transport module.
[ 0.861482] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.868559] PCI: CLS 0 bytes, default 64
[ 0.872973] Unpacking initramfs...
[ 0.877160] Initramfs unpacking failed: no cpio magic
[ 0.882782] Freeing initrd memory: 128K
[ 0.887603] hw perfevents: enabled with armv8_cortex_a53 PMU driver, 7 counters available
[ 0.896841] hw perfevents: enabled with armv8_cortex_a72 PMU driver, 7 counters available
[ 0.906114] kvm [1]: IPA Size Limit: 40bits
[ 0.911224] kvm [1]: vgic-v2@fff20000
[ 0.915265] kvm [1]: GIC system register CPU interface enabled
[ 0.921821] kvm [1]: vgic interrupt IRQ10
[ 0.926399] kvm [1]: Hyp mode initialized successfully
[ 0.939158] Initialise system trusted keyrings
[ 0.944178] workingset: timestamp_bits=44 max_order=20 bucket_order=0
[ 0.957046] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.964109] NFS: Registering the id_resolver key type
[ 0.969684] Key type id_resolver registered
[ 0.974278] Key type id_legacy registered
[ 0.978811] 9p: Installing v9fs 9p2000 file system support
[ 0.986490] Key type asymmetric registered
[ 0.990995] Asymmetric key parser 'x509' registered
[ 0.996386] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[ 1.004511] io scheduler mq-deadline registered
[ 1.009485] io scheduler kyber registered
[ 1.026955] EINJ: ACPI disabled.
[ 1.038567] pwm-regulator: supplied by regulator-dummy
[ 1.047940] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[ 1.056629] printk: console [ttyS2] disabled
[ 1.061362] ff1a0000.serial: ttyS2 at MMIO 0xff1a0000 (irq = 30, base_baud = 1500000) is a 16550A
[ 1.071269] printk: console [ttyS2] enabled
[ 1.071269] printk: console [ttyS2] enabled
[ 1.080632] printk: bootconsole [uart8250] disabled
[ 1.080632] printk: bootconsole [uart8250] disabled
[ 1.092670] SuperH (H)SCI(F) driver initialized
[ 1.098303] msm_serial: driver initialized
[ 1.103952] cacheinfo: Unable to detect cache hierarchy for CPU 0
[ 1.117068] loop: module loaded
[ 1.125140] libphy: Fixed MDIO Bus: probed
[ 1.130004] tun: Universal TUN/TAP device driver, 1.6
[ 1.136468] thunder_xcv, ver 1.0
[ 1.140113] thunder_bgx, ver 1.0
[ 1.143747] nicpf, ver 1.0
[ 1.147397] hclge is initializing
[ 1.151109] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
[ 1.159184] hns3: Copyright (c) 2017 Huawei Corporation.
[ 1.165176] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[ 1.171701] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[ 1.178352] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.6.0-k
[ 1.186138] igb: Copyright (c) 2007-2014 Intel Corporation.
[ 1.192400] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
[ 1.201156] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[ 1.208124] sky2: driver version 1.30
[ 1.212945] VFIO - User Level meta-driver version: 0.3
[ 1.220244] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 1.227585] ehci-pci: EHCI PCI platform driver
[ 1.232590] ehci-platform: EHCI generic platform driver
[ 1.240636] ehci-platform fe380000.usb: EHCI Host Controller
[ 1.246985] ehci-platform fe380000.usb: new USB bus registered, assigned bus number 1
[ 1.256766] ehci-platform fe380000.usb: irq 26, io mem 0xfe380000
[ 1.281914] ehci-platform fe380000.usb: USB 2.0 started, EHCI 1.00
[ 1.289325] hub 1-0:1.0: USB hub found
[ 1.293545] hub 1-0:1.0: 1 port detected
[ 1.300331] ehci-platform fe3c0000.usb: EHCI Host Controller
[ 1.306683] ehci-platform fe3c0000.usb: new USB bus registered, assigned bus number 2
[ 1.315663] ehci-platform fe3c0000.usb: irq 28, io mem 0xfe3c0000
[ 1.337920] ehci-platform fe3c0000.usb: USB 2.0 started, EHCI 1.00
[ 1.345257] hub 2-0:1.0: USB hub found
[ 1.349479] hub 2-0:1.0: 1 port detected
[ 1.354242] ehci-orion: EHCI orion driver
[ 1.358879] ehci-exynos: EHCI EXYNOS driver
[ 1.363655] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[ 1.370581] ohci-pci: OHCI PCI platform driver
[ 1.375601] ohci-platform: OHCI generic platform driver
[ 1.381602] ohci-platform fe3a0000.usb: Generic Platform OHCI controller
[ 1.389112] ohci-platform fe3a0000.usb: new USB bus registered, assigned bus number 3
[ 1.398077] ohci-platform fe3a0000.usb: irq 27, io mem 0xfe3a0000
[ 1.466467] hub 3-0:1.0: USB hub found
[ 1.470686] hub 3-0:1.0: 1 port detected
[ 1.475435] ohci-platform fe3e0000.usb: Generic Platform OHCI controller
[ 1.482945] ohci-platform fe3e0000.usb: new USB bus registered, assigned bus number 4
[ 1.491858] ohci-platform fe3e0000.usb: irq 29, io mem 0xfe3e0000
[ 1.562345] hub 4-0:1.0: USB hub found
[ 1.566571] hub 4-0:1.0: 1 port detected
[ 1.571312] ohci-exynos: OHCI EXYNOS driver
[ 1.576584] usbcore: registered new interface driver usb-storage
[ 1.586235] i2c /dev entries driver
[ 1.596590] sdhci: Secure Digital Host Controller Interface driver
[ 1.603515] sdhci: Copyright(c) Pierre Ossman
[ 1.608855] Synopsys Designware Multimedia Card Interface Driver
[ 1.616528] sdhci-pltfm: SDHCI platform and OF driver helper
[ 1.624312] mmc0: CQHCI version 5.10
[ 1.654146] mmc0: SDHCI controller on fe330000.sdhci [fe330000.sdhci] using ADMA
[ 1.664112] ledtrig-cpu: registered to indicate activity on CPUs
[ 1.672264] usbcore: registered new interface driver usbhid
[ 1.678516] usbhid: USB HID core driver
[ 1.686341] NET: Registered protocol family 17
[ 1.691503] 9pnet: Installing 9P2000 support
[ 1.696321] Key type dns_resolver registered
[ 1.701584] registered taskstats version 1
[ 1.706174] Loading compiled-in X.509 certificates
[ 1.731572] hctosys: unable to open rtc device (rtc0)
[ 1.737418] mmc0: Command Queue Engine enabled
[ 1.738022] ALSA device list:
[ 1.742418] mmc0: new HS400 Enhanced strobe MMC card at address 0001
[ 1.745717] No soundcards found.
[ 1.753421] mmcblk0: mmc0:0001 AJNB4R 14.6 GiB
[ 1.761881] ttyS2 - failed to request DMA
▒ 1.761936] mmcblk0boot0: mmc0:0001 AJNB4R partition 1 4.00 MiB
[ 1.773212] mmcblk0boot1: mmc0:0001 AJNB4R partition 2 4.00 MiB
[ 1.780028] mmcblk0rpmb: mmc0:0001 AJNB4R partition 3 4.00 MiB, chardev (237:0)
[ 1.796358] mmcblk0: p1 p2 p3 p4 p5
[ 1.809072] EXT4-fs (mmcblk0p5): recovery complete
[ 1.814985] EXT4-fs (mmcblk0p5): mounted filesystem with ordered data mode. Opts: (null)
[ 1.824092] VFS: Mounted root (ext4 filesystem) on device 179:5.
[ 1.831559] devtmpfs: mounted
[ 1.835657] Freeing unused kernel memory: 1472K
[ 1.878335] Run /sbin/init as init process
[ 1.978009] usb 4-1: new low-speed USB device number 2 using ohci-platform
Please press Enter to activate this console. [ 2.454069] usb 4-1: device descriptor read/64, error -62
[ 2.803691] input: SIGMACHIP Usb Mouse as /devices/platform/fe3e0000.usb/usb4/4-1/4-1:1.0/0003:1C4F:0065.0001/input/input0
[ 2.816298] hid-generic 0003:1C4F:0065.0001: input: USB HID v1.10 Mouse [SIGMACHIP Usb Mouse] on usb-fe3e0000.usb-1/input0
6.5 linux
命令测试
6.5.1 查看块设备
查看eMMC
块设备文件:
[root@zy:/]# ls /dev/mmc* -l
brw-rw---- 1 0 0 179, 0 Jan 1 00:00 /dev/mmcblk0
brw-rw---- 1 0 0 179, 32 Jan 1 00:00 /dev/mmcblk0boot0
brw-rw---- 1 0 0 179, 64 Jan 1 00:00 /dev/mmcblk0boot1
brw-rw---- 1 0 0 179, 1 Jan 1 00:00 /dev/mmcblk0p1
brw-rw---- 1 0 0 179, 2 Jan 1 00:00 /dev/mmcblk0p2
brw-rw---- 1 0 0 179, 3 Jan 1 00:00 /dev/mmcblk0p3
brw-rw---- 1 0 0 179, 4 Jan 1 00:00 /dev/mmcblk0p4
brw-rw---- 1 0 0 179, 5 Jan 1 00:00 /dev/mmcblk0p5
crw-rw---- 1 0 0 237, 0 Jan 1 00:00 /dev/mmcblk0rpmb
这里一共有8个块设备节点和1个字符设备节点;其中:
/dev/mmcblk0
表示的是eMMC
这个设备,其主设备号为179
,次设备号为0;mmcblk0boot0
和mmcblk0boot1
对应两个Boot Area Partition
;每一个Boot Area Partition
大小都是4MB
;mmcblk0rpmb
则为RPMB Partition
;大小为4MB
;mcblk0px
为User Data Area
划分出来的SW Partitions
;实际上就是通过解析GPT
分区表创建的分区,分区编号依次为1,2,3,4,5
;
使用cat /proc/partitions
,可以查看全部分区信息:
[root@zy:/]# cat /proc/partitions
major minor #blocks name
179 0 15267840 mmcblk0
179 1 4000 mmcblk0p1
179 2 4096 mmcblk0p2
179 3 4096 mmcblk0p3
179 4 114688 mmcblk0p4
179 5 15136751 mmcblk0p5
其中blocks
表示分区的容量,每个blocks
是1KB
。这里:
mmcblk0p1
对应loader1
分区,大小为4000KB
;mmcblk0p2
对应loader2
分区,大小为4MB
;mmcblk0p3
对应trust
分区,大小为4MB
;mmcblk0p4
对应boot
分区,大小为112MB
;mmcblk0p5
对应rootfs
分区,大小为剩余所有空间;
6.5.2 查看磁盘空间
这里我们可以通过df -hT
查看磁盘空间信息;
[root@zy:/]# df -hT
Filesystem Type Size Used Available Use% Mounted on
/dev/root ext4 274.6M 97.7M 155.9M 39% /
devtmpfs devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs tmpfs 1.9G 0 1.9G 0% /tmp
显示内容参数说明:
Filesystem
:文件系统;Type
:文件系统类型;Size
: 分区大小;Used
: 已使用容量;Avail
: 还可以使用的容量;Use%
: 已用百分比;Mounted on
: 挂载点;
这里我们可以看到根目录挂载在/dev/root
设备节点上,文件系统格式是ext4
,然后通过查看/dev/root
链接关系,看到/dev/root
其实就是/dev/mmcblk0p5
,也就是eMMC
设备的rootfs
分区;
[root@zy:/]# readlink /dev/root
mmcblk0p5
但是为什么这里看到的/dev/root
大小只有274MB
呢?不是应该有十几个G
么?这主要是因为我们的根文件系统镜像制作的就是那么大,剩余的eMMC
空间并未使用。
6.5.3 fdisk
分区命令
使用fdisk -l
查看磁盘分区情况:
[root@zy:/]# fdisk -l
Disk /dev/mmcblk0: 15 GB, 15634268160 bytes, 30535680 sectors
1908480 cylinders, 1 heads, 16 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 0,0,0 0,0,0 1 30535679 30535679 14.5G ee EFI GPT
从上面的内容可以看到磁盘/dev/mmcblk0
大小为15GB
,包含1个磁头、1个磁头有1904840
个柱面,每个柱面有16
个扇区,所以总容量为1908480*16*512=15,634,268,160
字节。
这里fdisk -l
只识别到了eMMC
设备的1号分区/dev/mmcblk0p1
,并没有识别到/dev/mmcblk0p2~5
分区,比较奇怪,网上搜索了一下好像是由于fdisk
不支持GPT
,所以才导致无法识别GPT
分区表。更多fdisk
命令相关能容可以参考:《使用fdisk
对磁盘分区》。
6.5.4 parted
分区命令
对于GPT
格式的分区,fdisk
工具是无能为力的,同时,fdisk
工具对分区是有大小限制的,它只能划分小于2T
的磁盘。
但是现在的磁盘空间很多都已经是远远大于2T
,此时就需要另外一个磁盘管理工具parted
来完成大于2T
的磁盘分区工作。
但是不幸的是buxybox
并不支持parted
命令,这里我也懒得去整了,后面我们直接移植ubuntu
根文件系统,然后通过resize2fs
指令进行扩容。
七、启动卡在Starting kernel
排查方法
如果你在内核启动时,卡在了Starting kernel
...。如果想解决问题,就必须知道问题出现在了哪里,因此一般通过内核启动的时候打印的信息来定位问题产生的原因。我们在linux
内核调试-printk
说过printk
函数输出的日志都会被保存到内核日志缓冲区__log_buf
中,因此我们可以直接读取该缓冲区, __log_buf
其地址在System.map
被标记出来,我们可以找到具体的位置。具体步骤如下:
(1) 首先去内核编译目录找到System.map
文件。
(2) 找到System.map
中_text
(代码段起始地址)的虚拟地址,执行:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# nm vmlinux | grep _text
ffff000010080000 T _text
(3) 找到System.map
中__log_buf
对应的虚拟地址,执行:
root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# nm vmlinux | grep __log_buf
ffff000011493358 __log_buf
(4) 直接从eMMC
第0x8000
个扇区加载内核,启动内核,内核此时卡在Starting kernel
…位置;7
=> mmc read 0x10000000 0x8000 0xA000
MMC read: dev # 0, block # 32768, count 40960 ... 40960 blocks read: OK
=> bootm 0x10000000
(5) 重新启动系统(注意:不要断电启动,按下复位键即可),进入uboot
命令行界面;
(6) 计算__log_buf
在内存的物理地址:
PA__log_buf = __log_buf - _text + PA
其中PA
为内核在内存的起始地址,这里是0x280000
;这里通过计算得到0x1693358
;
在命令行输入(数字是刚才得到的数字):
md 0x1693358
(7) 不停的敲击回车键,直到为全为0。
这个内容在内存中是使用struct prink_log
结构存储的,每个struct prink_log
后面跟着需要输出的内容,内容长度由text_len
字段确定。
struct printk_log {
u64 ts_nsec; // 时间ns
u16 len; // 该条消息在内存占用的长度,包括当前结构体
u16 text_len; // 输出的内容长度
u16 dict_len;
u8 facility;
u8 flags:5;
u8 level:3;
#iddef CONFIG_PRINTK_CALLER
u32 caller_id
#endif
}
如果想解析内核日志缓冲区log_buf
的内容,可以参考《DUMP kernel log_buf
以及解析log_buf
字符的办法》这篇博客,这篇博客提供了python
脚本解析内核日志缓存器的内容。
参考文章
[1] Rockchip Kernel
[2] 嵌入式ARM64 Linux
内核编译及根文件系统构建
[5] Rochchip
Partitions
[6] 在rk3399
(rockpi 4b
)上运行linux-5.3
的mainline
内核
[7] 简单介绍MBR
与GPT
的特点
[8] 利用parted
工具规划磁盘分区
[10] RK3399-HDMI
音频