Nate Sigrist

Installing libGL and friends for Linux 4.9

Discussion created by Nate Sigrist on Jun 11, 2018

This is a how-to for installing GPU binaries for X11 so it can use the Vivante drivers.


Make sure your environment variables are set correctly as there will be lots of cross compiling :-)  See the end of this post for help on setting environment variables for cross compiling.  This should be understood before continuing this post.



My setup is currently built with an Arch Linux root file system,



# Ignore other board DTBs and mute warnings,

sudo tar xf ArchLinuxARM-armv7-latest.tar.gz \

    -C ${ROOTFS} \

    --warning=no-unknown-keyword \

    --exclude="./boot/dtbs" \

    --exclude="./boot/initramfs-linux.img" \



Of course you'll want to use which ever distro works best for you (e.g. Yacto).  Arch Linux comes with a package manager that can install packages without compiling (albeit for generic ARM >< ).


The rest of this post will build and install the following required to get Vivante working with X11.

  • Kernel Vivante module 6.2.4 (kernel-module-imx-gpu-viv)
  • Proprietary libgl binaries (imx-gpu-viv)
  • Xorg Vivante extension (xserver-xorg-video-imx-viv)



The first code to compile is the Linux kernel module for galcore.  There is an existing galcore module in the kernel source tree.  I wrestle with understanding which is more beneficial.  I've chosen to use the module code provided by NXP.  The following generates this binary,


/usr/lib/modules/$(uname -r)/kernel/drivers/mxc/gpu-viv/galcore.ko


git clone 
cd kernel-module-imx-gpu-viv
git checkout upstream/6.2.4.p1.0


Replace the kernel's version,

rm -rf ${KERNELDIR}/drivers/mxc/gpu-viv

mkdir ${KERNELDIR}/drivers/mxc/gpu-viv
cp -R kernel-module-imx-gpu-viv-src/* ${KERNELDIR}/drivers/mxc/gpu-viv/


Then make sure CONFIG_MXC_GPU_VIV is set in the linux configuration file (.config and your project's defconfig file) and rebuild and install the kernel.  Upon booting with the new kernel, dmesg will show Galcore loading with the new version,


$ dmesg | grep -i "galcore"

[ 1.139315] galcore: clk_get vg clock failed, disable vg!
[ 1.141816] Galcore version


The galcore clock failure can safely be ignored.


Required Packages

The following packages need to be installed before continuing (this example is for Arch Linux),


pacman -S --needed xorg-server libx11 libxext xorg-server-devel xf86-video-fbdev \
    pixman icu



Start by downloading the binary,


chmod +x imx-gpu-viv-5.0.11.p8.3-hfp.bin

./imx-gpu-viv-5.0.11.p8.3-hfp.bin --force --auto-accept


If you have a hard time reading their site try switching to source code view in your browser.  Adding --auto-accept means you are agreeing to their EULA.  I use the following method to place the binaries into my rootfs - it could be written more compactly ><


# Exit on error

set -e

# Echo commands for verification
set -x

# Select which interface to use (options: fb, x11, dfb, wl)


# It's very important to set this to your root file system!


cd imx-gpu-viv-5.0.11.p8.3-hfp


pushd gpu-core/usr/lib

# Clean up previous symbolic links from last run
rm -rf****

# Create ny symbolic links to point to our desired interface
ln -s libEGL-${_EGL}.so
ln -s libEGL-${_EGL}.so
ln -s libEGL-${_EGL}.so
ln -s libEGL-${_EGL}.so
ln -s libGAL-${_EGL}.so
ln -s libGLESv2-${_EGL}.so
ln -s libGLESv2-${_EGL}.so
ln -s libGLESv2-${_EGL}.so
ln -s libVIVANTE-${_EGL}.so



# Copy over the Vivante configuration file (Vivante.icd)
sudo cp -R gpu-core/etc ${ROOTFS}

pushd ${ROOTFS}/usr/lib

# Make sure there are no symbolic links.  Also remove the mesa stuff
sudo rm -rf*** mesa/* mesa/*



pushd gpu-core/usr

CP="sudo cp -r --remove-destination"

${CP} lib/libVDK* ${ROOTFS}/usr/lib/
${CP} lib/* ${ROOTFS}/usr/lib/
${CP} lib/libVSC* ${ROOTFS}/usr/lib/
${CP} lib/libGLSLC* ${ROOTFS}/usr/lib/
${CP} lib/libVIV* ${ROOTFS}/usr/lib/
${CP} lib/libGAL* ${ROOTFS}/usr/lib/
${CP} lib/libEGL* ${ROOTFS}/usr/lib/
${CP} lib/libOpen* ${ROOTFS}/usr/lib/
${CP} lib/libGLESv1* ${ROOTFS}/usr/lib/
${CP} lib/libGLESv2* ${ROOTFS}/usr/lib/

if [ ! -d ${ROOTFS}/usr/lib/dri ]; then
    sudo mkdir ${ROOTFS}/usr/lib/dri
${CP} lib/dri/* ${ROOTFS}/usr/lib/dri/

${CP} include/EGL ${ROOTFS}/usr/include/
${CP} include/GLES2 ${ROOTFS}/usr/include/
${CP} include/HAL ${ROOTFS}/usr/include/



# Make sure this file is not used instead of our own
sudo rm ${ROOTFS}/usr/lib/
sudo rm ${ROOTFS}/usr/lib/
sudo rm ${ROOTFS}/usr/lib/
sudo rm ${ROOTFS}/usr/lib/
sudo rm ${ROOTFS}/usr/lib/



So far, the kernel driver has been built and the proprietary binaries have been installed.  Now the hooks must be built so X11 will work correctly.  You will need some X11 headers installed.  For Arch Linux, this is libx11libxext, .  This produces the following,





Grab the source,



tar xf xserver-xorg-video-imx-viv-5.0.11.p8.3.tar.gz



I had to remove `xf86DisableRandR' (deprecated) and replace shadowUpdateRotatePackedWeak and
shadowUpdatePackedWeak by simply removing "Weak()" from,


I also had to wrap "#define XV 1" with checks and remove "#if XV" and it's corresponding "#endif".  This was not ideal since XV is defined in xorg/xorg-server.h and wrapping and forcing this value does not seem like the appropriate solution.  You can use the following patch (which includes the above fixes) to get it working for now,


diff --git a/EXA/src/vivante_fbdev/vivante_fbdev_driver.c b/EXA/src/vivante_fbdev/vivante_fbdev_driver.c
index 063802a..2b78773 100644
--- a/EXA/src/vivante_fbdev/vivante_fbdev_driver.c
+++ b/EXA/src/vivante_fbdev/vivante_fbdev_driver.c
@@ -59,7 +59,9 @@ static Bool gEnableFbSyncExt = FALSE;

+#if !defined(XV)
#define XV 1

#include "mipointer.h"

@@ -801,7 +803,7 @@ FBDevCreateScreenResources(ScreenPtr pScreen)

if(fPtr->shadowFB) {
if (!shadowAdd(pScreen, pPixmap, fPtr->rotate ?
- shadowUpdateRotatePackedWeak() : shadowUpdatePackedWeak(),
+ shadowUpdateRotatePacked : shadowUpdatePacked,
FBDevWindowLinear, fPtr->rotate, NULL)) {
return FALSE;
@@ -1048,7 +1050,7 @@ FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "display rotated; disabling DGA\n");
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "using driver rotation; disabling "
- xf86DisableRandR();
+ ;
if (pScrn->bitsPerPixel == 24)
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "rotation might be broken at 24 "
"bits per pixel\n");
@@ -1130,7 +1132,6 @@ FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
pScreen->CreateScreenResources = FBDevCreateScreenResources;

-#if XV
XF86VideoAdaptorPtr *ptr;

@@ -1139,7 +1140,6 @@ FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
xf86XVScreenInit(pScreen, ptr, n);

if(gEnableXRandR) {
if (!imxDisplayFinishScreenInit(pScrn->scrnIndex, pScreen)) {


Then build and install,


    sysroot=${ROOTFS} prefix=${ROOTFS}/usr LFLAGS="${LDFLAGS}" && \

sudo -E make prefix=${ROOTFS}/usr install


Xorg Configurations

Make sure to configure /etc/X11/xorg.conf file with the vivante information,


Section "Device"
    Identifier "i.MX Accelerated Framebuffer Device"
#    Driver "vivante"
    Option "fbdev" "/dev/fb0"
    Option "vivante_fbdev" "/dev/fb0"

Section "Screen"
    Identifier "Default Screen"
    SubSection "Display"
        Depth 24
        Modes "720x1280"


Obviously make sure that Modes and Depth are set according to your needs.  You may comment out Driver "Vivante" if you are not able to get the Vivante drivers to work.


Starting X

Some pointers when starting Xorg.  If you are just trying to get things started then make sure the following are done,


# Manually load the vivante module,

modprobe vivante

# Make sure the DRI card is accessible by Xorg,
chmod o+rw /dev/dri/card0
Xorg &

export DISPLAY=:0


Or write a udev rule, (/etc/udev/rules.d/98-galcore.rules)


# for mxc_asrc, mxc_ipu, and mxc_vpu,
KERNEL=="mxc_*", MODE="0666"
# Frame buffers (there probably is no fb2)
KERNEL=="fb[0-9]*", MODE="0666"
SUBSYSTEM=="video", MODE="0666"
KERNEL=="galcore", MODE="0666"
# Uncomment the following if you do not intend to add video group to your user
#SUBSYSTEM=="drm", MODE="0666"


The Vivante module can be loaded on startup as well,


echo "vivante" > /etc/modules-load.d/vivante.conf


I've had no luck getting udevadmin to restart and set the permissions correctly so instead, restart the device and everything should look correct. 


Most likely you will have some issues; don't fret.  If requested, I will show how to build xorg-server to ensure matching ABIs and firmware.


***Oddly, Xorg seems to segfault the first time but work afterwords.***



Cross Compiling Environment Variables

export ARCH=arm
export CPU=armv7l
export MARCH=armv7-a
export MTUNE=cortex-a9
export HOST=arm-linux-gnueabihf

export LINARO_PATH=[Cross compiler root path]

export ROOTFS=[Path to your ARM root file system]

export CFLAGS="-march=${MARCH} -mtune=${MTUNE} --sysroot=${ROOTFS}"

# I prefer GOLD since it is much faster
export LDFLAGS="-march=${MARCH} -mtune=${MTUNE} --sysroot=${ROOTFS} -Wl,-fuse-ld=gold"

export CONF_ARGS="\
    --host=${HOST} \
    --with-sysroot=${ROOTFS} \
    --prefix=/usr \
    --sysconfdir=/etc \
export CONFIGURE="./configure ${CONF_ARGS}"

# Some projects appear to be auto tools but really aren't and will need this defined,

# Required for auto tools using pkg-config.  This directs them to the root file system.

# This assumes that you have preserved the install and have not used some other process

# that cleans up /usr/lib/pkfconfig

export PKG_CONFIG_LIBDIR=${ROOTFS}/lib/pkgconfig:${ROOTFS}/usr/lib/pkgconfig

# Make sure the cross compiler is included in your environment variables.  Notice that

# we've used Linaro here ;-)

export PATH=${BUILD}/$(shell uname -m)/bin:${LINARO_PATH}/bin:${shell echo $${PATH}

# Kernel source

export KERNELDIR=[Path to your kernel source]