【久久派】LS2K0300 的 LoongOS 原装系统启动分析
1、理解固件
PMON - 用于引导系统, 使用 EJTAG 下载到 NOR flash上,一般为 W25Q 系列; gzrom-dtb 。一般不用动,否则 变砖。
内核 - 负责管理系统资源驱动 等 ; 存放在 /boot/下,用 boot.cfg 进行启动时的加载管理。类似 windows操作系统完成后自动安装的一系列显卡、声卡、网卡驱动。
文件系统 - 数据组织与存储,管理文件的权限和属性;这个文件最大可采用 镜像或者U盘烧录,类似 windows操作系统。
2 旧世界启动盘制作
LS2K300 久久派 预安装系统是 LoongOS, 用户和密码均是 root。 如果要恢复,可自行制作U盘,在PMON启动后,进行恢复。官方给的资料恢复LoongOS相关文件。
根目录(U盘/升级盘) ├─ boot.cfg 顶层备用配置 ├─ vmlinuz 顶层备用内核 ├─ update.sh 升级脚本 ├─ update.cpio.gz └─ update/ 脚本标准升级包目录 ├─ boot.cfg 正式升级用配置 ├─ vmlinuz 正式升级内核 └─ loongos-qt.cpio.gz...在 U 盘的根目录下的 boot.cfg(若U盘与硬盘同时存在boot.cfg系统优先读取使用U盘中的) 中内容如下 :
default0timeout2showmenu0title 2k300 CC Update kernel(usb0,0)/vmlinuz initrd(usb0,0)/update.cpio.gz argsconsole=ttyS0,115200意思 是 从U盘加载内核 vmlinuz ,然后从U盘加载 文件系统 update.cpio.gz, 打开串口控制台。进入文件系统后,运行 update.sh:
#!/bin/shif[!-e"/dev/mmcblk0"];thenecho"################ emmc driver load fail ###################"exit1fiif[!-e"/dev/mmcblk0p1"];thenecho-e"n\np\n1\n\n\nw\n"|fdisk/dev/mmcblk0echo-e"y"|mkfs.ext4 /dev/mmcblk0p1fifdisk-lif[!-e"/dev/mmcblk0p1"];thenecho"############## emmc partition error ###################"exit2fiupdir=/updatemkdir$updirmount/dev/mmcblk0p1$updirif[-e"/mnt/update/boot.cfg"];thencp/mnt/update/boot.cfg$updirsyncfirm-rf$updir/* zcat /mnt/update/loongos-qt.cpio.gz|{cd$updir;cpio-idu;}if[-e"/mnt/update/vmlinuz"];thencp/mnt/update/vmlinuz /update/boot/.syncfiif[-e"/mnt/update/ddr_app.sh"];thencp/mnt/update/ddr_app.sh$updirsyncfiif[-e"/mnt/update/stressapptest"];thencp/mnt/update/stressapptest$updirsyncfiecho"########### Update successfully ##################"主要功能:
1、EMMC 设备存在性检测:先检查/dev/mmcblk0(EMMC 主设备)是否存在,不存在则提示驱动加载失败并退出。
2、分区与格式化:若/dev/mmcblk0p1(EMMC 第一个分区)不存在,通过fdisk创建主分区,再用mkfs.ext4格式化为 ext4 文件系统。
3、分区验证:再次检测/dev/mmcblk0p1,确保分区创建成功,失败则提示错误并退出。
4、挂载与系统更新:创建挂载目录/update,挂载 EMMC 分区,然后拷贝boot.cfg、vmlinuz等系统文件,解压根文件系统镜像loongos-qt.cpio.gz,最后提示更新成功。
当看到“########### Update successfully ##################”字样,表示还原完毕
最后,拔掉U盘,重新按下复位键重启。
如果 启动时按 c 进入pmon, 手动加载内核 启动 文件系统:
load(emmc0,0)/boot/vmlinuz gconsole=ttyS0,115200rootdelay=3root=/dev/mmcblk0p1 quietloglevel=4sdio_run //静默启动,不显示 或者使用 gconsole=ttyconsole=ttyS0,115200rdinit=/sbin/initrootdelay=5root=/dev/mmcblk0p1 //暂停5s 显示启动信息顶层 vmlinuz、boot.cfg 的作用是手动应急救砖、临时调试,不属于自动升级流程,是轻量化启动参数,多用于调试、救砖,参数更精简。
自动升级(运行 update.sh):会使用 update/ 内部的 vmlinuz、boot.cfg,这是配套 Qt 图形完整系统,参数适配整机完整业务;
3 旧世界更换内核
进入文件系统后,修改 /boot/boot.cfg, 可更换所使用的内核和文件系统。
timeout3default0showmenu1title'LoongOS (2k300)'kernel(emmc0,0)/boot/vmlinuz argsconsole=ttyconsole=ttyS0,115200rdinit=/sbin/initrootdelay=5root=/dev/mmcblk0p1 title'LoongOS (2k300 by tftp)'kernel tftp://192.168.0.13/vmlinuz argsconsole=ttyconsole=ttyS0,115200rdinit=/sbin/initrootdelay=5root=/dev/mmcblk0p1 title'LoongOS (2k300 by USB/vmlinuz)'kernel(usb0,0)/vmlinuz argsconsole=ttyconsole=ttyS0,115200rdinit=/sbin/initrootdelay=5root=/dev/mmcblk0p1开机时停止 3 S , 由用户选择装载哪个内核, 以上配置中,分别为:从emmc、tftp 、USB中加载内核 , 从emmc中加载文件系统。其中用 tftp 装载最为方便, 必须将将linux中的某个文件夹配置为tftp服务器,配置服务的方法参考 Linux TFTP使用。
文件系统也可以使用 NFS, 不过在嵌入式系统开发中,文件系统做好以后,一般就不再更换。 内核由于要处理内核态的很多驱动,比如添加摄像头、和 显示器、GPIO等,需要要内核中添加相关设备,修改设备树,经常用 tftp 加载内核 。
4 PMON下常用命令
开机后,按c 进入PMON。
PMON是一个兼有BIOS和boot loader部分功能的开放源码软件,多用于嵌入式系统。
基于龙芯的系统采用 pmon 作为类 BIOS 兼 bootloader,并做了很多完善工作。
4.1 通过pmon启动内核相关命令
网络加载:
load tftp://server‐ip/vmlinux initrd tftp://server‐ip/initrd.gz gconsole=ttyconsole=ttyS0,115200u 盘启动:
load(usb0,0)/vmlinux initrd(usb0,0)/initrd.gz gconsole=ttyconsole=ttyS0,115200命令解释:
命令: load
格式: load <elf‐file>
解释:
load 命令是 PMON 中一个很重要命令。作用是加载一个 elf 文件到内存中(这里只是存放到内存中,而没有烧写到flash中),加载过程是一个自动根据elf文件的信息处理elf文件重定向的等等操作的总体过程,所以这里不需要指定加载的内存地址,load命令会自动完成。
如:load tftp://server‐ip/vmlinux
如上命令,是从网络 tftp 服务器中加载内核到内存中。
如:load /dev/mtd0b
如上命令, 是从 nandflash 的第一个分区开始处中加载一个elf文件到内存中,这里一般存放着内核,这也是加载内核的另一种方法。
注:这里的 vmlinux 是一个 elf 文件,如果指定加载的文件不是 elf 文件,将提示错误。
用例: 以下分别为 U 盘加载, 硬盘加载, NVME 硬盘加载, 网络加载, nand
加载,
将首个分区中的 boot 目录下的 vmlinuz 文件并作为内核加载, 如:
load (usb0,0)/boot/vmlinuz
load (wd0,0)/boot/vmlinuz
load (nvme0,0)/boot/vmlinuz
load tftp://192.168.1.11/vmlinuz
load /dev/mtd (查看当前系统下所拥有的可操作 flash )
load /dev/mtd1 (读取 mtd1 中数据作为内核二进制)
命令: initrd
格式: initrd
解释:
加载initrd image
用例: 以下分别为 U 盘加载, 硬盘加载, NVME 硬盘加载, 网络加载,
将首个分区中的 boot 目录下的 rootfs.cpio.gz 文件并作为文件系统加载, 如:
initrd (usb0,0)/boot/rootfs.cpio.gz
initrd (wd0,0)/boot/rootfs.cpio.gz
initrd (nvme0,0)/boot/rootfs.cpio.gz
initrd tftp://192.168.1.11/rootfs.cpio.gz
命令: g
格式: g [‐s][‐b bpaddr][‐e addr][‐‐args]
解释:
g 命令是 PMON 中一个很重要的命令,直接从指定内存地址处开始执行程序
如:g –e addr
如上命令,直接从内存地址 addr 处开始执行程序,正常操作前提是在 addr 开始处的内存中已经存放了一个可执行的程序,addr 是这个程序的入口地址,如我们知道内存地址0x80010000 是 pmon 代码段存放开始地址, 执行 g –e 0x80010000 将会从新执行pmon 代码, 相当于了重启 PMON (这时不会从 flash 中拷贝执行 pmon)
用例:
load tftp://server‐ip/vmlinux
g console=ttyS0,115200 rdinit=/sbin/init
如上命令和 load 命令配合使用,在 load 完成后,使用 g 命令自动从加载后的内核入口地址开始执行内核,这是 g 后面在参数 “console=ttyS0,115200 rdinit=/sbin/init”是内核启动的参数
4.2 跟启动相关的环境变量
跟启动相关的环境变量有 al1, rd, append,分别对应内核,initrd 路径及启动参数,例如
可以设置为:
setal1 /dev/mtd0setrd /dev/fs/yaffs2@mtd1/initrd.gzsetappendconsole=ttyconsole=ttyS0,115200命令解释:
命令: set
格式: set [name] [value]
解释:
查看 pmon 中的环境变量,设置环境变量 name 为 value
如: set (查看显示 pmon 中所有的环境变量) ;
set wk kkk (添加或者修改环境 wk 的值为 kkk)
4.3 pmon 烧写内核及文件系统到 nand 方法
烧写之前需要擦除,命令如下:
mtd_erase /dev/mtd0r //0 代表分区,r 后缀代表擦除不跳过坏快 mtd_erase /dev/mtd1r devcp tftp://server‐ip/vmlinux /dev/mtd0 devcp tftp://server‐ip/roofs‐yaffs2.img /dev/mtd1ysetal1 /dev/mtd0setappendconsole=ttyS0,115200rdinit=/sbin/initroot=/dev/mtdblock1 rwrootfs=yaffs2命令解释:
命令: devcp
格式: devcp <src ‐device> <desc‐device>
解释:
devcp 命令应该是 PMON 中比较重要的命令。
其实现是:打开 src‐device 和 desc‐device 两个设备,从 src‐device 读取一定数量的字节数据,写到 desc‐device 设备中去,完成后关闭这两个设备。
如:devcp tftp://server‐ip/vmlinux /dev/mtd0
如上命令,从 tftp 服务器中接收读取内核 vmlinux,写到 nandflash 的第一个分区中,这是常用的烧写内核到 flash 中一个常用命令
如:devcp tftp://server‐ip/roofs‐yaffs2.img /dev/mtd1y
如上命令,从 tftp 服务器中接收读取根文件系统 的 yaffs2 镜像文件 rootfs‐yaffs2.img
烧写到 nandflash 的第二个分区中。这是常用的烧写 yaffs2 文件系统到 nandflash 中的一个常用命令。
命令: mtdparts
格式: mtdparts
解释: 显示 nandflash 的现在分区信息。
命令: mtd_erase
格式: mtd_erase <mtd‐device>
解释:
擦除 nandflash 的一个分区
(擦除 nandflash 的第一个分区,跳过已经是坏块的地方,不会尝试擦除已经是坏块的地方);
mtd_erase /dev/mtd0r
(擦除 nandflash 的第一个分区,这时会尝试擦除所有的块,即使是坏块也会尝试执行擦
除操作)。
fload
功能: 固件烧录 bin
句式: fload 所在路径/文件名称
用例: 以下分别为 U 盘加载, 硬盘加载, NVME 硬盘加载, 网络加载
fload (usb0,0)/gzrom-dtb.bin
fload (wd0,0)/gzrom-dtb.bin
fload (nvme0,0)/gzrom-dtb.bin
fload tftp://192.168.1.11/gzrom-dtb.bin
注: 烧录过程会先擦除原始固件请确保整个过程不要中断或断电, 当重新
回到
“PMON>” 命令行模式则烧录完成, 可以进行重启
烧录新世界的命令: fload tftp://192.168.1.11/u-boot-spl-gz.bin
bl
功能: 跳转运行某功能, 暂时只用于手动读取 boot.cfg
句式: bl 所在路径/boot.cfg
用例: 以下分别为 U 盘加载, 硬盘加载, NVME 硬盘加载, 网络加载
bl -d ide (usb0,0)/boot/boot.cfg
bl -d ide (wd0,0)/boot/boot.cfg
bl -d ide (nvme0,0)/boot/boot.cfg
bl -d ide tftp://192.168.1.11/boot.cfg
4.4 pmon 下查看及修改 dtb
Pmon 命令行支持,查看、删除、重新烧写 dtb。
Pmon 下查看 dtb 命令:
Print_dtb / 打印出 dtb 所有内容 Print_dtb /soc/dc@0x400c0000 打印出dc的所有内容Pmon 下删除 dtb
rm_dtb_node / 删除整个 dtb rm_dtb_node /soc/hda@0x400d00000 删除 had 内容pmon 下重新烧写 dtb
dtb 会把内存大小信息传递给内核,如果这部分内容传递错误会造成不可预知错误。如果重新烧写内部部分内容,需要通过 print_dtb 命令把内存部分内容读出,更新到新的 dts 文件中(3号处理器不传递内存信息)。
在 pmon 编译目录下执行 make dtb 会生成 Bonito3a3000_7a.dtb 文件。此文件可单独烧写。
烧写命令和 烧写pmon一致
4.5 网络相关命令
ifconfig/ifaddr
功能: 设置对应网口 IP, 该设置不被保存
句式: ifconfig/ifaddr 网口名 IP 号
用例: ifconfig syn0 192.168.1.50 / ifaddr syn0 192.168.1.50
注: PMON 下使用该命令设置某网口 IP 后, 若需临时使用另一网口, 则需要ifconfig syn0 remove 来移除已经配置灯网口才能对新网口进行配置
ping
功能: 网络链路测试
句式: ping 主机 IP
用例: ping 192.168.1.10
注: 请确保网口设置成功 IP 后再 ping
lwdhcp
功能: 使用 DHCP 自动分配 IP
句式: lwdhcp 网口名
用例: lwdhcp
默认自动分配 syn0 地址
lwdhcp syn1
自动分配 syn1 地址
4.6 其他命令简介
h
功能: 显示当前 PMON 全部可用命令
句式: h 或 h 想查询的指令
用例: h load (详细显示该命令的句式结构与可用参数 )
vers
功能: 查看当前 PMON 版本
句式: vers
用例: vers
命令: d1
格式: d1
解释: display 简写
按无符号字符型(unsigned char)访问显示 num 个从地址 addr 开始的内容值。
如:d1 0x85000000 0x10
显示从内存地址 0x85000000 地址处的 0x10 个字节(8 位),0x85000000‐0x8500000f
命令: d2
格式: d2
解释: display 简写
按 (unsigned short) 访问显示 num 个从地址 addr 开始的内容值。
如: d2 0x85000000 0x10
显示从内存地址 0x85000000 地址处的 0x10 个 unsigned short 类型(16 位)的数值,0x85000000‐0x8500001e
命令: d4
格式: d4
解释: display 简写
按(unsigned long)访问显示 num 个从地址 addr 开始的内容值。
如: d4 0x85000000 0x10
显示从内存地址 0x85000000 地址处的 0x10 个 unsigned long 类型(32 位)的数值,0x85000000‐0x8500003c
命令:d8
格式: d8
解释: display 简写
按 (unsigned long long) 访问显示 num 个从地址 addr 开始的内容值。
如: d8 0x85000000 0x10
显示从内存地址 0x85000000 地址处的 0x10 个 unsigned longlong(64 位)类型的数值, 0x85000000‐0x85000078
命令: m1
格式: m1
解释: modify 简写
按无符号字符型(unsigned char)访问修改地址 addr 的内容值。
如: m1 0x85000000 0x10
修改内存地址 0x85000000 地址处的一个 unsigned char 型值相当于:(unsigned char)addr = value;
命令: m2
格式: m2
解释: modify 简写
按无符号字符型(unsigned short)访问修改地址 addr 的内容值。
如: m2 0x85000000 0x10
修改内存地址 0x85000000 地址处的一个 unsigned short 型值相当于:(unsigned short)addr = value;
命令: m4
格式: m4
解释: modify 简写
按无符号字符型(unsigned long)访问修改地址 addr 的内容值。
如: m4 0x85000000 0x10
修改内存地址 0x85000000 地址处的一个 unsigned long 型值相当于:(unsigned long)addr = value;
命令: m8
格式: m8
解释: modify 简写
按无符号字符型(unsigned long long)访问修改地址 addr 的内容值。
如: m8 0x85000000 0x10
修改内存地址 0x85000000 地址处的一个 unsigned long 型值相当于:(unsigned long long)addr = value;
命令: devls
格式: devls
解释: 查看 pmon 的部分设备, 这里显示出来的设备不是全部的设备。
一般会有网卡, USB,CF 卡,sd 卡,硬盘等等,主要用查看设备的名字,以供其他操作的使用。
命令: ifaddr
格式: ifaddr
解释: 设置网卡的 IP 地址,如:ifaddr syn0 192.168.0.1 (syn0 是网卡的名字,可以使用 devls 命令查看获得,这里不用设置子网掩码,pmon 会自动设置子网掩码为255.255.255.0)
set
功能: 查看或增改 PMON 环境变量
句式: set 或 set 环境变量名 环境变量值
用例: set (无参数时会打印所有当前环境变量, 回车继续, q 退出)
set ifconfig syn0:192.168.1.50 (添加环境变量 ifconfig 其值为
syn0:192.168.1.50, 再次启动时对应的网口自动设置 IP)
set al1 (wd0,0)/boot/vmlinuz (启动后自动加载该路径二进制文件
作为内核文件, 并启动内核)
命令: unset
格式: unset
解释: 去掉名字为 name 的环境变量。关于环境变量的讲解参看附录 PMON 环境变量
data
功能: 读写内部 RTC
句式: data / date [yyyymmddhhmm.ss]
用例: date 读取当前时间
date 202211010955.
spi_base
功能: spi 操作片选, 默认为 0
句式: spi_base 片选
用例: spi_base 0
spi_id
功能: 读取当前片选下 flashID
句式: spi_id
用例: spi_id
