飞腾E2000默认可以通过wic格式安装,wic格式按照的方式如下。
Win32DiskImager 可以烧录img格式文件。主要步骤如下
a 选择wic文件
b 选择需要刻录的设备
c 点击写入
将U盘插入机器,通过dd命令直接更新,如下:
sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/sda status=progress
注意这里/dev/sda为U盘识别的块,而不是U盘识别的分区.如果插入U盘是sdb。则这里填写/dev/sdb 以此类推
在启动过程中一直按着空格或者enter键,如果是uboot启动就会进入uboot模式
E2000默认的串口波特率为115200,根据实际板子情况接入TTL串口,通过串口功能确保能够正常读写
开机一直按下ctrl+c,直到进入uboot shell,如下所示
在 uboot shell中输入 usb start 能够开启USB功能,此时uboot阶段即可正常识别U盘设备,命令如下:
E2000#usb start starting USB... Bus usb3@31a00000: Register 2000110 NbrPorts 2 Starting the controller USB XHCI 1.10 Bus usb3@31a20000: Register 2000110 NbrPorts 2 Starting the controller USB XHCI 1.10 scanning bus usb3@31a00000 for devices... 5 USB Device(s) found scanning bus usb3@31a20000 for devices... 1 USB Device(s) found scanning usb for storage devices... 1 Storage Device(s) found
这里如看到”scanning usb for storage devices... 1 Storage Device(s) found“ 字样,则代表U盘已经识别,如看不到,则检查硬件或uboot驱动
通过ls 命令可以查看盘符内文件系统内容,如下
ls usb 0:1 / 为查看USB设备第一个盘符的文件内容 ls usb 0:2 / 为查看USB设备第二个盘符的文件内容 E2000#ls usb 0:1 / EFI/ System Volume Information/ 0 file(s), 2 dir(s) E2000#ls usb 0:2 / <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found <SYM> 7 bin <SYM> 8 sbin <SYM> 7 lib 0 .exectl <DIR> 4096 var <DIR> 4096 usr <DIR> 4096 boot <DIR> 4096 dev <DIR> 4096 etc <DIR> 4096 home <DIR> 4096 proc <DIR> 4096 root <DIR> 4096 run <DIR> 4096 sys <DIR> 4096 tmp <DIR> 4096 mnt <DIR> 4096 srv <DIR> 4096 opt <DIR> 4096 media <DIR> 4096 download
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda2 rw rootwait security=none';
在Uboot shell中敲入如上命令即可修改开机挂载root分区的具体位置
这里上述参数仅修改root=,用于指定内核挂载操作系统的真实根文件系统位置(root=/dev/sda2),这里通过u盘挂载,则默认可知rootfs位置为/dev/sda2
如不更新内核,在此步骤上,可以直接运行boot命令启动系统。这样能够达到在使用原内核直接启动/dev/sda2的系统的目的。
boot # 该命令使用原来内核启动系统
如果不使用kylin内核,则直接跳转到《三:U盘系统内操作》
ext4load usb 0:2 $kernel_addr boot/uImage-5.4.18-63-generic;
上述参数,可以更换uboot启动过程中的内核加载uimage的实际文件。这里实际内核文件为uImage-5.4.18-63-generic,存放于usb设备的第二个分区的/boot目录。
注意:内核uImage需适配硬件,否则有概率启动失败
ext4load usb 0:2 $ft_fdt_addr /boot/dtb-5.4.18-63-generic/device-tree/phytium/e2000d-demo-board.dtb
上述参数,可以更换uboot启动过程中加载设备树dtb的实际文件,这里实际设备树文件为e2000d-demo-board.dtb,存放于usb设备的第二个分区的/boot/dtb-5.4.18-63-generic/device-tree/phytium/目录
注意:内核设备树需适配硬件,否则有概率启动失败
bootm $kernel_addr -:- $ft_fdt_addr
上述参数可以直接将内核启动,通过如上方法,E2000可以正常启动为U盘(sda2)内的系统镜像
saveenv
上述命令可以保存uboot中的环境变量,后续每次启动将自动启动,无需重复配置.
当一切就绪后,可使用此保存当前环境变量,U盘启动无需保存,因其仅启动一次,如设置nvme/sata/mmc启动则可保存,以免重复配置
在上述方式通过U盘进入系统之后,进入终端,可以发现系统是通过sda2挂载的。现在需要将其正式的更新到固定磁盘上。
root@kylinos:~# mount /dev/sda2 on / type ext4 (rw,relatime)
通过上述命令可以发现,现在已经进入U盘系统中,需要在U盘系统中将系统更新到emmc中,主要如下:
tar xzvf Kylin-embedded_vkylin_arm64-xxxx-rc1.wic.tar.gz
# 目的盘为nvme sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/nvme0n1 status=progress # 目的盘为sata sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/sda status=progress
需要注意的是,这里的of=指定的是真实存在的物理设备,例如/dev/nvme0n1为机器的nvme盘,具体安装情况视当前硬件情况决定
如果不想dd wic文件,可以直接将U盘的根分区内容直接对拷到目的硬盘。例如
cp -raf /run/media/usb_storage/* /rum/media/nvme0np2/
这里/run/media/usb_storage/ 是U盘的根分区挂载,可以通过 mount /dev/sda2 /run/media/usb_storage/挂载
这里/rum/media/nvme0np2/
通过上述操作,实际已经安装好系统,现在仅需要进入uboot中,保存自己需要启动的环境变量。从而做到每次开机自动加载即可。
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda2 rw rootwait security=none'; setenv load_kernel 'ext4load scsi 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load scsi 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda3 rw rootwait security=none'; setenv load_kernel 'ext4load usb 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load usb 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/nvme0n1p3 rw rootwait security=none'; setenv load_kernel 'ext4load nvme 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load nvme 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
printenv可以打印变量,确定自己设置的和打印的是否一致即可。接下来就能正常启动新的系统了。
第一次登录需要手动运行resize-assistant。用于扩大rootfs分区
默认密码 kylin qwer1234
设置启动一共就三步,分别为,设置内核地址,设置设备树地址,设置启动命令,保存配置。通常仅修改加载内核和设备树的地址。 现在示例想系统更新到mmc盘符,主要操作如下: 打印uboot的所有配置:printenv,setenv args "contents"可以配置具体的环境变量,最后saveenv保存环境变量最后重启即可生效
如下是我们配置的usb启动的整个例子可以参考:
E2000#printenv arch=arm baudrate=115200 board=e2000 board_name=e2000 boot_os=bootm $kernel_addr -:- $ft_fdt_addr bootargs=console=ttyAMA1,115200 earlycon=pl011,0x2800d000 \\\ root=/dev/mmcblk0p1 rw rootwait security=none bootcmd=usb start; run load_kernel; run load_fdt; run boot_os bootdelay=2 cpu=armv8 distro_bootcmd=run load_kernel; run load_initrd; run load_fdt; run boot_os eth0addr=00:11:22:33:44:55 eth1addr=10:22:33:44:55:66 eth2addr=10:11:22:33:44:55 eth3addr=00:22:33:44:55:66 ethaddr=00:11:22:33:44:55 fdtcontroladdr=f9c3f7f0 fileaddr=90100000 filesize=17d0240 ft_fdt_addr=0x90000000 ft_fdt_name=boot/dtb/e2000.dtb gatewayip=202.197.67.1 initrd_addr=0x95000000 ipaddr=202.197.67.2 kernel_addr=0x90100000 load_fdt=ext4load usb 0:2 0x90000000 boot/e2000d-demo-board.dtb load_initrd=ext4load usb 0:2 0x95000000 initrd.img-5.4.18-65-generic load_kernel=ext4load usb 0:2 0x90100000 boot/uImage-kylin loadaddr=0x90000000 netdev=eth0 netmask=255.255.255.0 serverip=202.197.67.3 stderr=uart@2800d000 stdin=uart@2800d000 stdout=uart@2800d000 vendor=phytium Environment size: 1047/4092 bytes
备注:
bootargs=console=ttyAMA1,115200 earlycon=pl011,0x2800d000 \\\ root=/dev/mmcblk0p1 rw rootwait security=none
/dev/mmcblk0p1为系统分区,可以从内核串口log中可以看到,如果找不到rootfs可以查看此处
load_fdt=ext4load usb 0:2 0x90000000 boot/e2000d-demo-board.dtb load_kernel=ext4load usb 0:2 0x90100000 boot/uImage-kylin
e2000d-demon-board.dtb和uImage两个文件我们可以手动复制到u盘中的/boot/目录下,根据cpu的不同e2000d,e2000q,e2000s可以选择不同的dtb文件
setenv load_kernel 'ext4load usb 0:2 $kernel_addr boot/uImage-5.4.18-63-generic'; setenv load_fdt 'ext4load usb 0:2 $ft_fdt_addr boot/e2000d-demo-board.dtb'; setenv bootcmd 'usb start; run load_kernel; run load_fdt; run boot_os' setenv boot_os 'bootm $kernel_addr -:- $ft_fdt_addr' saveenv
这里设置了内核地址为U盘的 boot/uImage-5.4.18-63-generic,设备树地址为 U盘的 boot/e2000d-demo-board.dtb,启动命令为 bootm ft_fdt_addr
dd if=Kylin-embedded_vkylin_arm64_rc1_20230419.wic of=/dev/mmcblk0 status=progress
setenv load_kernel 'ext4load mmc 0:2 $kernel_addr boot/uImage-5.4.18-63-generic'; setenv load_fdt 'ext4load mmc 0:2 $ft_fdt_addr boot/e2000d-demo-board.dtb'; setenv bootcmd 'usb start; run load_kernel; run load_fdt; run boot_os' setenv boot_os 'bootm $kernel_addr -:- $ft_fdt_addr' saveenv
通过上述设置,下次启动则可以正常加载新的系统。
通常e2000的机器,设备树默认使用机器本身的,内核使用麒麟和客户自身的均可以,系统必须指定为麒麟系统即可完成正常安装
有客户需要在不接任何显示器的前提下能够正常启动图形服务器。但是linux drm框架下,drm是建立在connector上。所以需要内核打开虚拟显示屏,这样能够将图形启动在虚拟显示器上,下面介绍主要操作方法
配置文件打开
CONFIG_ROCKCHIP_VCONN=y
这个配置依赖于
HAS_IOMEN[=y]
与
DRM_ROCKCHIP[=y]
一般都是打开的
virtual_con { compatible = "rockchip,virtual-connector"; };
static int rockchip_virtual_connector_probe(struct platform_device *pdev) { return component_add(&pdev->dev, &rockchip_virtual_connector_ops); }
因为rk的drm驱动走的component框架,这里只需要为其添加组件即可
static const struct component_ops rockchip_virtual_connector_ops = { .bind = rockchip_virtual_connector_bind, .unbind = rockchip_virtual_connector_unbind, };
drm驱动会逐个绑定drm的connector,然后根据具体的connector紧张逐个绑定encoder
rockchip_virtual_connector_register(vconn); list_for_each_entry_safe(vconn_dev, n, &vconn->list_head, list) { drm_simple_encoder_init(vconn->drm_dev, encoder, vconn_dev→encoder_type); drm_connector_init(vconn->drm_dev, connector, &rockchip_virtual_connector_funcs, vconn_dev→output_type); drm_connector_attach_encoder(connector, encoder);
在绑定的时候会注册connector,然后根据之前创建的设备逐个绑定connector和decoder
root@kylin:~# xrandr Screen 0: minimum 320 x 200, current 1024 x 768, maximum 16384 x 16384 Virtual-1 connected primary 1024x768+0+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00*+ 4096x2160 60.00 59.94 2560x1600 59.99 59.97 1920x1440 60.00 1856x1392 60.00 1792x1344 60.00 2048x1152 60.00 1920x1200 59.88 59.95 1920x1080 60.00 1600x1200 60.00 1680x1050 59.95 59.88 1400x1050 59.98 59.95 1600x900 60.00 1280x1024 60.02 1440x900 59.89 59.90 1280x960 60.00 1366x768 59.79 60.00 1360x768 60.02 1280x800 59.81 59.91 1280x768 59.87 59.99 1280x720 60.00 800x600 60.32 56.25 848x480 60.00 640x480 59.94
至此,即使机器没有任何的实际connector,也可以虚拟一个假的connector,也就是虚拟显示屏来执行图形APP的运行
为了丰富版本的调试功能,这里提供了web ssh来支持浏览器打开ssh。只需要四步即可完成,只要实施步骤如下
apt install shellinabox
根据自身机器环境配置网络即可
为了更加安全,这里使用9999端口,如下
sed -i 's/SHELLINABOX_PORT=4200/SHELLINABOX_PORT=9999/g' /etc/default/shellinabox
systemctl restart shellinabox
netstat -ntp | grep shellinabox
如果一切正常,则看到出现9999端口的shellinaboxd
项目中有客户需要将设备当作纯U盘来使用,已知Linux的gadget本身就支持U盘设备,这里描述一下如何将Linux系统作为U盘使用。
对于usb gadget功能,需要打开内核默认设置,主要配置如下:
CONFIG_USB_F_MASS_STORAGE=y CONFIG_USB_LIBCOMPOSITE=y CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_MASS_STORAGE=m
将CONFIG_USB_MASS_STORAGE作为ko的原因是需要加载时传参,如果希望固化,则可以将传参写到cmdline中。
对于U盘功能,则需要单独划一块分区给U盘使用,这里可以是单独的分区,也可以是一个img文件。
如果是单独的分区,则如下:
mkfs.vfat /dev/mmc0blk1p5 insmod g_mass_stroage.ko file=/dev/mmc0blk1p5 removable=1
如果需要系统内也能看到文件修改,这里增加一个fstab即可。如下
/dev/mmc0blk1p5 /data1 vfat defaults,user,rw,codepage=936,iocharset=utf8 0 0
如果是单独的文件,则如下:
dd if=/dev/zero of=/media/usb_stroage.img bs=512 count=2097152 # (1G大小) mkfs.vfat /media/usb_stroage.img
这里可以利用fstab的挂载
/media/usb_stroage.img /data1 vfat defaults,user,rw,codepage=936,iocharset=utf8 0 0
然后加载驱动
insmod g_mass_stroage.ko file=/dev/loop0 removable=1
如果不确定loop0是否为自己的img,可以指定挂载如下
losetup /dev/loop0 /media/usb_stroage.img
使用就非常简单了,将otg的功能的USB接上电脑,电脑会按照U盘的方式弹出一个已经格式化好的文件。此时正常使用U盘即可。
客户有一个4K的屏幕,放在两个显示器上面显示,现在需要将其对半分割为两个正常的显示器。这么说不好理解,转换需求可以这样理解,一个4K的显示分辨率的显示器,需要系统将其认为两个2K的显示器显示。通过前期调研,发现了两种方法实现。分别如下
此方案是为X增加了两个monitor,然后根据窗管的识别,将其认定为两个单独的屏幕,此方法需要修改系统代码。主要如下
--- xorg-server-21.1.4/randr/rrmonitor.c.orig 2022-09-30 00:09:40.458561832 +0200 +++ xorg-server-21.1.4/randr/rrmonitor.c 2022-09-30 00:09:46.298529786 +0200 @@ -528,27 +528,6 @@ continue; } - /* For each output in 'info.outputs', each one is removed from all - * pre-existing Monitors. If removing the output causes the list - * of outputs for that Monitor to become empty, then that - * Monitor will be deleted as if RRDeleteMonitor were called. - */ - - for (eo = 0; eo < existing->numOutputs; eo++) { - for (o = 0; o < monitor->numOutputs; o++) { - if (monitor->outputs[o] == existing->outputs[eo]) { - memmove(existing->outputs + eo, existing->outputs + eo + 1, - (existing->numOutputs - (eo + 1)) * sizeof (RROutput)); - --existing->numOutputs; - --eo; - break; - } - } - if (existing->numOutputs == 0) { - (void) RRMonitorDelete(client, screen, existing->name); - break; - } - } if (monitor->primary) existing->primary = FALSE; }
这里屏蔽了Xorg本身将存在的output的monitor删除的代码
--- src/gtk/gdk/x11/gdkscreen-x11.c.orig 2022-09-30 16:24:00.181850959 +0200 +++ src/gtk/gdk/x11/gdkscreen-x11.c 2022-09-30 21:32:47.288912422 +0200 @@ -644,21 +644,14 @@ #undef EDID_LENGTH } - monitor = find_monitor_by_output (x11_display, output); - if (monitor) - monitor->remove = FALSE; - else - { - monitor = g_object_new (GDK_TYPE_X11_MONITOR, - "display", display, - NULL); - monitor->output = output; - monitor->add = TRUE; - g_ptr_array_add (x11_display->monitors, monitor); - } + monitor = g_object_new (GDK_TYPE_X11_MONITOR, + "display", display, + NULL); + monitor->add = TRUE; + g_ptr_array_add (x11_display->monitors, monitor); gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); - name = g_strndup (output_info->name, output_info->nameLen); + name = gdk_x11_get_xatom_name_for_display(display, rr_monitors[i].name); newgeo.x = rr_monitors[i].x / x11_screen->window_scale; newgeo.y = rr_monitors[i].y / x11_screen->window_scale; @@ -687,7 +680,6 @@ gdk_monitor_set_connector (GDK_MONITOR (monitor), name); gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), manufacturer); g_free (manufacturer); - g_free (name); if (rr_monitors[i].primary) primary_output = monitor->output;
这里找到monitor不是通过output寻找,而是直接增加monitor,这就避免了同一个显示器上不能输出两块屏幕的问题
这边尝试了metacity和mutter,均没办法正常识别,但是基于gtk3的xfce是能够正常识别到两个屏幕的。
apt install -y xfce4
根据如上理解,我们后续要做的工作是,将例如kwin这类的窗管,在创建屏幕的过程中,不应该绑定一个output就一个monitor的方式。而是根据所有的monitor来都创建显示display
xrandr --delmonitor VIRTUAL-LEFT xrandr --delmonitor VIRTUAL-RIGHT xrandr --setmonitor VIRTUAL-LEFT 960/0x1200/1+0+0 DSI-1 xrandr --setmonitor VIRTUAL-RIGHT 960/1x1200/1+960+0 none xrandr --listmonitors xrandr --fb 1921x1200 xrandr --fb 1920x1200
https://github.com/micw/xorg-split-screen-archlinux/blob/packages/gtk3/trunk/multiple_monitors_per_output.patch https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/981/diffs?commit_id=21e569ef1e87e4dfcedbdac99216e7147e2b05ff
https://gitlab.gnome.org/GNOME/gtk/-/issues/2013#note_1280968
通过修改xrandr的api,可以实现将x划分为多个显示接口,也就是xrandr显示的是自己设置的虚假的显示器
参考仓库地址
https://github.com/phillipberndt/fakexrandr
参考测试示例
https://gist.github.com/phillipberndt/7688785#file-fake-xinerama-L50
相应论坛信息
https://unix.stackexchange.com/questions/605755/use-xrandr-to-split-display-in-two-virtual-screens
DWM窗管支持全屏补丁
https://dwm.suckless.org/patches/fakefullscreen/dwm-fakefullscreen-20210714-138b405.diff
fakeXinerama仓库
https://github.com/Xpra-org/libfakeXinerama
xrdp补丁
https://github.com/asafge/xrdp_dualmon/blob/master/fakexinerama/Xinerama.c
参考论坛
https://gitlab.gnome.org/GNOME/gtk/-/issues/2013#note_1280968
测试例子
fakexrandr-manage.py gui
通过上述两种办法试验,均可以在X86上正常切换屏幕。当前在麒麟系统上的kwin不能直接使用,需要修改代码