site  contact  subhomenews

fbwhiptail, whiptail for the framebuffer

September 26, 2018 — BarryK

I have posted recently about tools to create GUIs that run on the Linux framebuffer:

http://bkhome.org/news/201808/gui-creation-for-the-linux-framebuffer.html

http://bkhome.org/news/201808/considering-ugfx.html

http://bkhome.org/news/201808/littlevgl-evaluation-part-3.html

Today, I was reading the latest blog post at the Purism site (the guys who are developing the Librem 5 phone):

https://puri.sm/posts/the-librem-key-makes-tamper-detection-easy/

Where they mentioned "fbwhiptail", which is whiptail modified to run on the Linux framebuffer. Whiptail is like 'dialog', a tool to popup GUI windows from shell scripts. They both create "text mode" GUIs, dialog uses 'ncurses' and whiptail uses 'newt'.

Interesting, fbwhiptail compiles to 'fbwhiptail' and 'gtkwhiptail', so will also work with cairo and gtk. Here is the project page:

https://source.puri.sm/coreboot/fbwhiptail/

The same developer also has it on github:

https://github.com/kakaroto/fbwhiptail

I have tested it... there is a lot of functionality missing, compared with whiptail.  Most of the dialogs are not yet implemented. I tested a simple "--msgbox" and "--yesno". There does not seem to be any automatic text wrap, the <height> and <width> parameters seem to do nothing, text-input only, my mouse did not work. There seems to be a fixed theme.

Conclusion: in it's current state, it probably suits their simple need, however, for me LittlevGL is way ahead -- just need to solve the non-functional evdev keyboard input.

EDIT 20180927:
Oh wow! I posted an "issue" to the fbwhiptail github page, and the developer, Youness, posted a very detailed reply:

https://github.com/kakaroto/fbwhiptail/issues/1

...yes, I see that fbwhiptail is tailored to their particular need. The extra info is good too, for anyone who might like to use it.

Tags: linux

Low-level container how-tos

September 25, 2018 — BarryK

I have accumulated some links with information about containers at a low-level. Some are very grass-roots, DIY, tutorials, some are simple implementations. These are in no particular order:

http://cesarvr.github.io/post/2018-05-22-create-containers/

https://blog.lizzie.io/linux-containers-in-500-loc.html

https://github.com/p8952/bocker

https://ericchiang.github.io/post/containers-from-scratch/

https://dev.to/napicellatwit/containers-from-scratch-in-18-lines-of-code-3pmn

https://www.brighttalk.com/webcast/15077/253233/containers-from-scratch

https://wvi.cz/diyC/

http://blog.z3bra.org/2016/03/hand-crafted-containers.html

https://github.com/arachsys/containers

http://doger.io/

https://github.com/ghedo/pflask

https://github.com/xemul/libct

https://github.com/subgraph/oz

The above are NOT about using Docker, LXC, LXD, or any of the mainstream container implementations! Also, I stayed away from implementions in languages other than C or shell script -- there are some sites with low-level code in Go for example.

Tags: linux

Linux containers in 580 lines of C

September 23, 2018 — BarryK

'contained' is an executable written in C, for chrooting into a filesystem, with maximum security:

https://blog.lizzie.io/linux-containers-in-500-loc.html

...as the author states, it did grow a bit beyond 500 lines! Here is the C code:

https://blog.lizzie.io/linux-containers-in-500-loc/contained.c

Using the 4.14.71 kernel, with cgroups support now enabled, I got 'contained' to work. Was able to "chroot" into a rootfs, and it is very locked down. Too locked down to actually do anything useful.

However, it is very educational to study. It has given me an introduction how cgroups can be used, and the intention is to apply cgroups to EasyContainers.


Tags: linux

Goodbye uClibc-ng

September 09, 2018 — BarryK

I have used uClibc over the years, to created small static executables. It is a competitor to musl, dietlibc and newlib. The offical uClibc project died, and got forked as uClibc-ng. At that time, just about everybody moved to musl -- Landley dropped it from Aboriginal Linux, OpenEmbeded/Yocto dropped it -- Buildroot continue to offer a choice of glibc, uClibc or musl, ditto OpenADK.

I have a fork of Landley Aboriginal, the last that supports uClibc:

http://bkhome.org/news/201803/aboriginal-linux-120x-resuscitated.html

Over the last few days, I have been playing with creating a native toolchain based on uClibc-ng. I was checking out various projects, and discovered 'pts-tcc', part of which has a utility that is a wrapper around gcc, enabling to compile with uClibc library, rather then glibc. This works like the 'diet' utility in dietlibc, that is, 'diet' is a wrapper for gcc, to link with the diet libraries.

I used uClibc-ng version 1.0.30, the latest. I posted to the 'pts-tcc' project about a problem:

https://github.com/pts/pts-tcc/issues/1

However, the wrapper utility 'i386-uclibc-gcc' works. I even compiled it for aarch64. Using it, I compiled a static "Hello World", which after stripping was 262KB. Similar size for aarch64. Oh dear, it should be down under 20KB -- that is the main reason for using this library, to create small static executables. So, posted a report:

https://github.com/pts/pts-tcc/issues/2

...oh dear, another person reporting 107K and going up, this is not good!

I might try the most recent version from the original uClibc project, for comparison.

EDIT:
Yes, tested with the original uClibc, plus some patches, got a stripped hello world 254KB. Hmmm, investigated the .config file, found the main reason for the bloat, posted here:

https://github.com/pts/pts-tcc/issues/2

Now down to 86K, still big but a huge improvement. Will study the .config file some more. And will go back to uclibc-ng, test that.

Tags: linux

Alpine aarch64 chrootable rootfs

August 31, 2018 — BarryK

I posted awhile back how easy it is to create an Alpine musl-based chrootable filesystem folder:

http://bkhome.org/news/201704/alpine-x8664-chrootable-rootfs.html

At the time, I created i686, x86_64 and armv7 root-filesystems.

Now that I am embracing aarch64, want a rootfs for compiling static executables. Hence:

http://distro.ibiblio.org/quirky/alpine/aarch64/developer/

After expansion of the tarball, instructions are inside. You will of course need to be running a aarch64 host OS, in my case on the new Rock64 board.

I compiled squashfs-tools 4.3, and it needs a patch for musl:

http://cgit.openembedded.org/openembedded-core/tree/meta/recipes-devtools/squashfs-tools/squashfs-tools/fix-compat.patch

For good measure, I also applied all the patches from Debian. My rootfs does not have zlib-dev, so had to install that:

# apk add zlib-dev

...the rootfs has the Alpine apk package manager in it.

Tags: linux

LittlevGL evaluation part 3

August 23, 2018 — BarryK

Progress! Parts 1 and 2 are here:

http://bkhome.org/news/201808/first-go-at-evaluating-littlevgl.html

http://bkhome.org/news/201808/tentative-first-step-framebuffer-with-littlevgl.html

I didn't know how to get the mouse working without X, so posted a question to the developer's site:

https://github.com/littlevgl/lvgl/issues/374

Now have a window with buttons, and a mouse! Furthermore, it is compiled statically with uClibc and the executable is 217KB -- bigger than it needs to be as have included more modules than actually used.

I used my fork of Landley's uClibc-based Aboriginal chrootable filesystem:

http://distro.ibiblio.org/easyos/project/aboriginal/

...follow the instructions, and you will end up with a filesystem folder that you can chroot into.

LittlevGL is the pc-simulator tarball, as explained in the earlier posts. But first, the exciting part... I excited from X and executed 'demo":

image

The "mouse pointer" is that little power-button symbol, don't yet know how to create a proper image. I can move the pointer over a button, click, and get output on the screen. Yay!

My changes to 'lv_conf.h':

#define LV_COLOR_DEPTH     24                     /* BKColor depth: 1/8/16/24*/

Changes to 'lv_drv_conf.h':

#define USE_FBDEV           1
...
#define USE_EVDEV 1

Here is my 'Makefile':

#
# Makefile
#
CC = gcc
#CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
CFLAGS = -Wall -Wshadow -Wundef
CFLAGS += -O3 -g3 -I./
#LDFLAGS += -lSDL2 -lm
BIN = demo
VPATH =
LDFLAGS = -static

LVGL_DIR = ${shell pwd}

MAINSRC = main.c

#LIBRARIES
include ./lvgl/lv_core/lv_core.mk
include ./lvgl/lv_hal/lv_hal.mk
include ./lvgl/lv_objx/lv_objx.mk
include ./lvgl/lv_misc/lv_fonts/lv_fonts.mk
include ./lvgl/lv_misc/lv_misc.mk
include ./lvgl/lv_themes/lv_themes.mk
include ./lvgl/lv_draw/lv_draw.mk

#DRIVERS
include ./lv_drivers/display/display.mk
include ./lv_drivers/indev/indev.mk

OBJEXT ?= .o

AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))

MAINOBJ = $(MAINSRC:.c=$(OBJEXT))

SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
OBJS = $(AOBJS) $(COBJS)

## MAINOBJ -> OBJFILES

all: clean default

%.o: %.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "CC $<"

default: $(AOBJS) $(COBJS) $(MAINOBJ)
$(CC) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS)

clean:
rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)
Here is my 'main.c':
#include "lvgl/lvgl.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <stdio.h>

//Add a display for the LittlevGL using the frame buffer driver
void register_display(void)
{
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.disp_flush = fbdev_flush; //It flushes the internal graphical buffer to the frame buffer
lv_disp_drv_register(&disp_drv);
}

static lv_res_t btn_click_action(lv_obj_t * btn)
{
uint8_t id = lv_obj_get_free_num(btn);

printf("Button %d is released\n", id);

/* The button is released.
* Make something here */

return LV_RES_OK; /*Return OK if the button is not deleted*/
}

int main(void)
{
/*LittlevGL init*/
lv_init();

/*Linux frame buffer device init*/
fbdev_init();

// get a display
register_display();

// enable event input
evdev_init();

// get an input device like mouse
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read = evdev_read;
// lv_indev_drv_register(&indev_drv);

lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);

lv_obj_t * cursor_obj = lv_img_create(lv_scr_act(), NULL); /*Create an image for the cursor */
lv_img_set_src(cursor_obj, SYMBOL_POWER); /*For simlicity add a built in symbol not an image*/
lv_indev_set_cursor(mouse_indev, cursor_obj); /* connect the object to the driver*/


/*Create a title label*/
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(label, "Default buttons");
lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 5);

/*Create a normal button*/
lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
lv_cont_set_fit(btn1, true, true); /*Enable resizing horizontally and vertically*/
lv_obj_align(btn1, label, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_obj_set_free_num(btn1, 1); /*Set a unique number for the button*/
lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, btn_click_action);

/*Add a label to the button*/
label = lv_label_create(btn1, NULL);
lv_label_set_text(label, "Normal");

/*Copy the button and set toggled state. (The release action is copied too)*/
lv_obj_t * btn2 = lv_btn_create(lv_scr_act(), btn1);
lv_obj_align(btn2, btn1, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_btn_set_state(btn2, LV_BTN_STATE_TGL_REL); /*Set toggled state*/
lv_obj_set_free_num(btn2, 2); /*Set a unique number for the button*/

/*Add a label to the toggled button*/
label = lv_label_create(btn2, NULL);
lv_label_set_text(label, "Toggled");

/*Copy the button and set inactive state.*/
lv_obj_t * btn3 = lv_btn_create(lv_scr_act(), btn1);
lv_obj_align(btn3, btn2, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_btn_set_state(btn3, LV_BTN_STATE_INA); /*Set inactive state*/
lv_obj_set_free_num(btn3, 3); /*Set a unique number for the button*/

/*Add a label to the inactive button*/
label = lv_label_create(btn3, NULL);
lv_label_set_text(label, "Inactive");

/*Handle LitlevGL tasks (tickless mode)*/
while(1)
{
lv_tick_inc(5);
lv_task_handler();
usleep(5000);
}

return 0;
}
What we have now is a great jumping-off point for creating useful apps.

Tags: linux, easy

Considering uGFX

August 19, 2018 — BarryK

I posted about a first hands-on with LittlevGL:

http://bkhome.org/news/201808/tentative-first-step-framebuffer-with-littlevgl.html

In an earlier post, there is a list of contenders for creating GUI apps that will run on the Linux framebuffer:

http://bkhome.org/news/201808/gui-creation-for-the-linux-framebuffer.html

...in that post, I mentioned µGFX. Yeah, looks good. The intention now, is to have a hands-on with µGFX.

image

µGFX is commercial, open-source, free for personal and educational use. I am OK with that. In fact, this kind of model might be more likely to stick around into the future (unless the company gets bought by Microsoft, and then dies -- that's a joke!). Also likely to be more sophisticated and polished that a totally freebie product.

One thing that did put me off initially, is that it only generates 32-bit executables. As I am currently working with 64-bit builds of Easy and Quirky, without any 32-bit libraries, this is a problem. Well, that applies to my "Pyro" series, which is compiled from source in my fork of OpenEmbedded.

There is Quirky Xerus 8.6, built with Ubuntu DEBs, and that does have 32-bit libs available, however, I am moving away from that, in future will likely focus on the Pyro series.

Does it matter that executables are 32-bit? Actually, no, as my planned usage is to create static executables, and they will work on both 32-bit and 64-bit systems, no shared libraries required. In which case, there is an advantage to building 32-bit executables.

The easiest platform (for me) on which to evaluate µGFX will be a i686 build of EasyOS, Pyro series. Compiling it right now. Might even release it, for those who still need a 32-bit x86 distro.

Another preliminary impression of µGFX is of it's maturity and capability -- the new beta 0.2 of µGFX-Studio is written using µGFX libraries. It is a drag-and-drop GUI designer. This uses SDL2 and will run on the desktop. Here is a forum thread:

https://community.ugfx.io/topic/843-ugfx-studio-v020-beta/

image

A comment about SDL2: it uses OpenGL for rendering, cannot use the Linux framebuffer. SDL1 can use the framebuffer. Unfortunate!

There is an active user community:

https://community.ugfx.io/

The online documentation looks good:

https://wiki.ugfx.io/

https://api.ugfx.io/

Project homepage:

https://ugfx.io/

Looks good, keen to try it! 

Tags: linux

Tentative first step framebuffer with LittleVGL

August 19, 2018 — BarryK


As posted earlier today, I have started to evaluate LittlevGL:

http://bkhome.org/news/201808/first-go-at-evaluating-littlevgl.html

the "PC simulator" does look like a good starting point, though it is setup to create a binary named "demo" that is linked against SDL2. That's OK for learning, but I am aiming to talk directly to the Linux framebuffer.

For EasyOS, SDL2 packages are available here (libsdl2-*):

http://distro.ibiblio.org/easyos/amd64/packages/compat/oe/pyro/

Download the pc-simulator zip file:

https://littlevgl.com/download
Direct link to version 5.1.1:
https://littlevgl.com/download/pc_simulator_v5_1_1.zip

Expand the zip file, and this is what you see:

image

Open a terminal, and type "make". That's it, a binary named "demo" will be created. Run it "# ./demo", and you get a GUI:

image

There is another tutorial web page that explains how to create a simple "Hello World" app using the Linux framebuffere, so onto that...

Hello World with Linux framebuffer

There is an introduction and tutorial here:

https://littlevgl.com/blog/23/embedded-gui-using-linux-frame-buffer-device-with-littlevgl

I fiddled around for awhile. Like the "PC Simulator" tutorial page, there is a conceptual-gap in the instructions. Here:

2. Compile the code and go back to character terminal mode

...er, how to compile it? For a beginner, this is an awkward step. A Makefile is needed. These are the steps that I followed:

  1. Run "make clean"
  2. In the 'pc-simulator' folder, I moved 'lv-conf.h', 'lv_drv_conf.h', 'lv_ex_conf.h', 'main.c' and 'Makefile' elsewhere.
  3. I then created new 'lv_drv.h', 'lv_conf.h' and 'main.c' as per instructions in the above URL.
  4. I copied-back the 'Makefile' that I had previously moved away, and edited it. Snapshot of the files, 'hide1' is where I moved the original files to:

image

Here is my edited Makefile:

#
# Makefile
#
CC = gcc
CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
CFLAGS += -O3 -g3 -I./
#LDFLAGS += -lSDL2 -lm
BIN = demo
VPATH =

LVGL_DIR = ${shell pwd}

MAINSRC = main.c

#LIBRARIES
include ./lvgl/lv_core/lv_core.mk
include ./lvgl/lv_hal/lv_hal.mk
include ./lvgl/lv_objx/lv_objx.mk
include ./lvgl/lv_misc/lv_fonts/lv_fonts.mk
include ./lvgl/lv_misc/lv_misc.mk
include ./lvgl/lv_themes/lv_themes.mk
include ./lvgl/lv_draw/lv_draw.mk

#DRIVERS
include ./lv_drivers/display/display.mk
include ./lv_drivers/indev/indev.mk

OBJEXT ?= .o

AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))

MAINOBJ = $(MAINSRC:.c=$(OBJEXT))

SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
OBJS = $(AOBJS) $(COBJS)

## MAINOBJ -> OBJFILES

all: clean default

%.o: %.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "CC $<"

default: $(AOBJS) $(COBJS) $(MAINOBJ)
$(CC) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS)

clean:
rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)

I do realise that more modules than are needed, are being included in the build, but that's OK, as I plan to play with adding more widgets. Notice that SDL2 is not being linked.

Run "make", it creates 'demo'. This will not run on the Xorg desktop, though I vaguely recall a method of doing it in a terminal. Anyway, the way to test 'demo' is to exit from X, via the Shutdown menu in EasyOS (and most pups). Then, on the commandline, as long as a framebuffer has command of the screen, which is likely (there are some caveats), just execute 'demo', where-ever it is.

On the commandline, here is what it looks like:

image

That's as far as I've got. Next, need to investigate mouse support...

LVGL evaluation Part-3 here:

http://bkhome.org/news/201808/littlevgl-evaluation-part-3.html 

Tags: linux