X11 Forwarding on Duo

Getting X11 to (not) run on the Duo

In another bout of what can only be described as insanity I thought to myself “wouldn’t it be fun to try X11 forwarding on the duo?”

So far my attempts have been relatively unsuccessful, but here are my steps so far in case you want to try it at home:

Add X11-related packages

Add the following lines to build/boards/cv180x/cv1800b_milkv_duo_sd/cv1800b_milkv_duo_sd_defconfig:

# Stuff for X11 + VNC

Add polling support to the kernel

This didn’t really seem to make a difference but maybe it’ll help you?

Add the following lines to build/boards/cv180x/cv1800b_milkv_duo_sd/cv1800b_milkv_duo_sd_defconfig:


For now, all I get is an error that says failed to allocate poll structure, which using strace still reveals that polling support isn’t in the kernel, despite the fact is actually is.

If anyone has any insights as to why it’s not working, please let me know.


I’m doing something similar (running X on a SPI screen) and was having the same problem but I got past it, now I’m stuck trying to load the fb driver, it complains that can’t relocate the fb_driver.so.

Anyways, this is how I got xinit to pass the poll problem:

1-Very important, download the latest buildroot and whenever you want to change anything, start from scratch, not sure why but changes to the buildroot aren’t applied always, I’ve tried to make clean the buildroot, reconfigure the packages, etc, and once it is built once, the next times it sometimes ignores changes, a bummer.

2-under buildroot-2021.05 execute make milkv_duo_musl_riscv64_defconfig.

3-Modify configs/milkv_duo_musl_riscv64_defconfig with your packages, you can also use make menuconfig, that’s what I did, but had to manually add


4-Modify build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig and add the kernel modules, I have use these (it includes the modules for the fb):


5-Build with ./build_milkv.sh

With this the poll error went away but I’m now stuck with this:

Fatal server error:
(EE) no screens found(EE)

Checking the log I see this:

[ 1823.539] (II) Loading /usr/lib/xorg/modules/drivers/modesetting_drv.so
[ 1823.545] (EE) Failed to load /usr/lib/xorg/modules/drivers/modesetting_drv.so: Error relocating /usr/lib/xorg/modules/drivers/modesetting_drv.so: shadowSetup: symbol not found
[ 1823.545] (EE) Failed to load module “modesetting” (loader failed, 0)
[ 1823.545] (II) LoadModule: “fbdev”
[ 1823.546] (II) Loading /usr/lib/xorg/modules/drivers/fbdev_drv.so
[ 1823.550] (EE) Failed to load /usr/lib/xorg/modules/drivers/fbdev_drv.so: Error relocating /usr/lib/xorg/modules/drivers/fbdev_drv.so: fbdevHWEnterVT: symbol not found
[ 1823.550] (EE) Failed to load module “fbdev” (loader failed, 0)

So now I’m trying to find info on why it does not load, I have checked the so driver symbols with nm and all seem to be there, the architecture is correctly set to RISC-V and all looks good…

Thanks for your contribution. I’ll definitely try these config options when I get home in a little bit and share my results, though it looks like I might hit another dead end based on your progress.

Ok, more advances, and really good ones!

X is now running, but it complains about a problem with ttydev I/O, so this may be caused because the fb0 dirver, this may work for you.

The problem with the loadmodules was caused because of the stripping of the binaries, if you modify configs/milkv_duo_musl_riscv64_defconfig and set BR2_STRIP_strip=n it should work. I also added the option to include static libraries and increased the size of the ext2 partition but I think that’s not necessary.

Also, if you plan to use “startx” instead of “xinit” you will need to copi some libraries that are missing from the image, copy all the files from host-tools/gcc/riscv64-linux-musl-x86_64/sysroot/lib/ to /lib in the sd card.

Excellent! I’m excited to get this working with VNC when I get home. What results have you had so far with running apps? I’d try some basic ones like xterm or xeyes and you can also install Dillo or other apps. Not sure how well https would work since I haven’t gotten curl to install properly for some reason yet.

I can’t run anything because of the ttydev error, X starts, resets the framebuffer device and then it starts complaining about the ttydev I/O error, so it does not get to the point that I can run any app, but the server starts and takes control of the screen.

For now I assume that this is caused by the fbtft driver or how I hooked the console, so if you are going to use it with VNC and xvfb it should work.

It may also be a problem because I don’t have any real input device, I’m not sure if X can run without any kind of input device…

I will post my advances if I get something else.

Damn! It’s so close…

X works correctly, the apps are the ones that fail!

If I start X manually and specify the -retro flag I can see the old desktop and cursor, then starting xterm or anything else specifying -display localhost:0.0 the app tries to run but is not able to open the tty device, so it is indeed a problem with the terminal, but Xorg is completelly running.

Of course, I’ll update you in about 1-3 hours hopefully when I get home about my progress on getting VNC to work.

Your usage of a ST7789V display has the gears turning in my head for the idea of a functional mini Macintosh replica hahaha

It works! The problem is xterm!

I started manually xclock and xeyes and as these don’t use the terminal at all they work perfectly!

For now I need to stop but tomorrow I will create a small program that reproduces how xterm opens tty and will try to debug it in the duo in order to understand what prevents xterm from running.


1 Like

Excellent. Glad you could work out most of the issues on your end!

Follow up:

Last night I went through the process and built the image using your config after grabbing a clean build system, I’m still getting poll errors. Is there anything else you might have gone through to make the build?


Hmmm, may be what avoided the error then was activating the static and dynamic libraries…

In any case, this is the exact procedure that I follow, I just recreated the image from scratch to ensure these are 100% correct. Keep in mind that these include all the stuff to get the tft working as the primary screen. Also, for me when I start Linux the system itself starts Xorg and if you’re going to use vnc with Xvfb I suppose you will need to disable the auto startup of Xorg, I’m including at the end of the procedure how to do it.

1-Get a fresh copy of the buildroot:

git clone https://github.com/milkv-duo/duo-buildroot-sdk

From here, all the commands assume you’re inside the duo-buildroot-sdk folder.

–The following steps are only for the TFT screen, I think you can skip these safely

2-Modify linux_5.10/drivers/staging/fbtft/fb_st7789v.c with the proper settings for the screen

static struct fbtft_display display = {
        .regwidth = 8,
        .width = 240,
        .height = 240,
        .gamma_num = 2,
        .gamma_len = 14,
        .gamma = HSD20_IPS_GAMMA,
        .fbtftops = {
                .init_display = init_display,
                .set_var = set_var,
                .set_gamma = set_gamma,
                .blank = blank,

3-Modify build/boards/cv180x/cv1800b_milkv_duo_sd/dts_riscv/cv1800b_milkv_duo_sd.dts and replace the spi2 description.

&spi2 {
        status = "okay";
        cs-gpios = <&porta 18 0>;

        spidev@0 {
                status = "disabled";

        st7789v: st7789v@0{
                compatible = "sitronix,st7789v";
                reg = <0>;
                status = "okay";
                spi-max-frequency = <48000000>;
                fps = <60>;
                buswidth = <8>;
                dc-gpios = <&porta 24 GPIO_ACTIVE_HIGH>;
                reset-gpios = <&porta 23 GPIO_ACTIVE_HIGH>;
                debug = <0x4000000>;

4-Modify u-boot-2021.10/include/configs/cv180x-asic.h

"console=tty0 $othbootargs;"

–This has mixed definitions, some are required by the TFT screen, others by Xorg, I would recommend to add all, it will cause no harm. Also, add any other kernel module you need.

5-Modify build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig.

Remove CONFIG_EPOLL=n at the end of the file.


6-Enter buildroot-2021.05 and execute make milkv_duo_musl_riscv64_defconfig

7-Modify buildroot-2021.05/configs/milkv_duo_musl_riscv64_defconfig

As I have heavily modified the used packages I’m linking the file I use, it includes the static and dynamic libraries, enables debug symbols, includes Xorg, the fb drivers, Xvfb, the basic X apps, nano and more tools, you will need to also add openssh, x11vnc and so on. I just copy the file each time, and if I need to include anything else once copied to the folder I execute make menuconfig, load the file, add the packages and finally store it in a safe place to avoid breaking anything.

8-Generate the SD image

From the duo-buildroot-sdk folder execute ./build_milkv.sh

9-Burn the generated image from duo-buildroot-sdk/out

10-Boot the device, connect it to your computer and using scp copy the missing libraries required by startx:

cd host-tools/gcc/riscv64-linux-musl-x86_64/sysroot/lib
scp * root@

That’s it, with this the image boots with Xorg running on fb0 and the terminal is redirected also to fb0.
To avoid Xorg to start at boot remove /etc/init.d/S40xorg from the SD card.


I’m wondering if I perhaps missed removing CONFIG_EPOLL=n from the file. I’ll give some of this a shot later when I have more time.

Got some new things running: fluxbox, x11vnc, mpv and even stella running an atari 2600 game :smiley:

With small apps like xcalc plus x11vnc the performance is good, response is in real time, but with stella and mpv it’s slow, it might be because the fb driver, it sends everything using SPI and it consumes a lot of resources. Tomorrow I will check if with Xvfb it works better.


Excellent work! I’ve got an image building right now that should hopefully work.

I can’t believe you missed out on a chance to run Doom on the Duo. I’ll be sure to grab that package next image compilation as well as some other tweaks maybe :slight_smile:

EDIT: I just scrolled up and saw that chocolate doom was marked for install, oops hahaha

Well… I didn’t missed it, it crashes with a segmentation fault… :upside_down_face:

I tried chocolate-doom and chocolate-heretic and both fail to start, the window is shown a millisecond and it crashes, but I still think that it may be related to the tftfb and the spi screen.

But, the config app runs ok :smiley:

I’m waiting to receive the I/O board, with that maybe I will be able to do more as I will have a real keyboard and mouse connected to the device and will not need vnc to interact with X. OpenTyrian, ltetris and other games don’t start because there is no mouse so with the USB ports that may change.

I see. I just hit a problem with building the image.

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake:27 (message):
  The imported target "Qt5::Gui" references the file


  but this file does not exist.  Possible reasons include:

  * The file was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and contained


  but not all the files it references.

Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake:45 (_qt5_Gui_check_file_exists)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake:67 (_qt5gui_find_extra_libs)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake:186 (include)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsConfig.cmake:101 (find_package)
  Tests/CMakeLists.txt:1332 (find_package)

I have no idea why this may have occured, but it may have something to do with my host system? I do have libegl-dev installed on my Ubuntu 20.04 system, so I’m not sure what could be wrong.

Hmm, that’s strange, the build should not use any of your system libraries, it must use all the libs and the toolchain that it downloads automatically.

Have you executed by any chance any “make” manually beyond make menuconfig in the buildroot folder?

I did run make milkv_duo_musl_riscv64_defconfig and make menuconfig because I got a little confused.

Those work for me, these don’t build anything, just create the config files and set up the buildroot.

Very strange. Maybe you added some package that is trying to use Qt5?