Deploying an Embedded System using Windows and Linux
Russian-language version here.
Introduction
Development of devices with graphical human-machine interface sooner or later uncovers a problem of choosing a hardware and software platform for the interface. There are several solutions of this problem, there can be either a single-board computer with an operating system, or a microcontroller with a screen and a set of appropriate libraries, or some another custom device.
Sometimes top level of control system does not simply run the interface, but also maintain some external connections and operates a wide number of peripheral devices. Furthermore the interface itself can have serious requirements for graphical system capabilities. In this case in terms of labor saving it is suitable to take a single-board computer as a base and install a complete operating system on it. This decision can also greatly simplify a development of software by using modern frameworks with proper documentation and collection of examples.
Interface Features
For the user convenience, interface should meet the following requirements:
In other words, a completely restricted user access, stability and scalability.
As for the operating system for a single-board computer, we will consider two options at once, one based on Windows, the other based on Linux, and compare them to each other.
A touchscreen kiosk interface will be created for illustrative example. As for application, we will take one of the Qt Quick training examples and implement it with some changes. Qt framework is available for both operating systems.
In order to avoid the issues of installing Windows or Linux on the ARM platform, the system can be easily built on the basis of some x86-compatible processor. In our case, for the experiments, one of the many available boards on the Intel Bay Trail platform was used.
Open-source code is available on GitHub.
The Windows Way
Windows Embedded from Microsoft was once introduced exactly to create embedded systems. Even in the early Windows Embedded XP version there were number of tools for assembling images which were severely truncated, but equipped with all the necessary drivers. These images required a minimum of RAM and were running smoothly even on low-end processors. This technology was improved in the Windows Embedded Standard 7 version, where the process of creating custom assemblies was slightly refined. In Windows Embedded, the ideology of an open directory of modules was used, and anyone could equip their system with only the necessary set of components. The latest version in which this approach was available, although in a reduced form, was Windows Embedded Standard 8.1.
Modern Windows 10 IoT is promoted as an alternative to Windows Embedded, but is very different from its predecessors. The open component catalog is no longer available. There is no more easy way to build light images using regular tools and make custom installation disks. Special options of the embedded system, such as the write filter, bootloader branding, keyboard filter, etc., are now able to be configured only in the pre-installed system. Moreover, the support of these functions is available only as part of the heavy Windows 10 Enterprise versions.
However, despite the high system requirements, especially in terms of RAM, the use of even heavy versions in embedded solutions does not cause any special problems, especially due to the cheap hardware components. And not to forget that lately it has become more difficult to buy a license for any obsolete products of Microsoft.
Quick Solution
It turns out that even in the usual Windows 10 there is already a built-in function "Assigned Access" (Fig. 1), which looks like a ready-made solution to the problem.
Fig. 1. "Assigned Access" Function
A program that can be used in this case as an interface should be initially developed as a Universal Windows Platform application. These applications in appx format are installed, for example, on Windows Phone. A simple full-screen application, of course, can be converted to appx and signed with the appropriate certificates, and then installed. It can work as an interface, but without proper protection. Unfortunately, in the normal mode "Assigned access" user still has access to some system settings and hotkeys. It is impossible to create an interface that meets all the above requirements with the help of this approach. The system has to be configured manually and in another way.
Proper Solution
1. Basic Installation
So, first of all, we need a distribution of Windows 10 Enterprise LTSB. You can take the original image of Microsoft, or some lightweight one, or make your own, using third-party tools. For the experimental board, one of the custom assemblies was chosen (a lightweight 32-bit version).
Let us install the system from the distribution on the target board. During the installation, we divide the disk into two sections, C: - for the system, D: - for the main application, utilities and journals. Such a division will be useful later for the write filter. After installation wait for the settings menu to appear, or the network settings menu and do not continue any further.
Reboot into service mode using Ctrl+Shift+F3.
If there were no errors in the installation process, then after rebooting the system will go into the administrator’s service account and the SysPrep window will appear on the screen (Fig. 2). It must be closed, we will start SysPrep in another way, using a special answer file that has yet to be created.
Fig. 2. Service Mode.
2. System Configuration
For further action, we need the Deployment Tools from the Windows 10 Assessment and Deployment Kit.
From the disk with the Windows distribution installed on the board, we need to extract the install.wim image file. It happens that in some assemblies this file can be stored in a compressed form with the esd extension. In this case, it must first be unpacked. To do this, use the dism utility.
Find out the sequence number of the desired version inside the container (SourceIndex).
dism /Get-WimInfo /WimFile:install.esd
Then, extract the image file (in this case, the first one in the container).
dism /export-image /SourceImageFile:install.esd /SourceIndex:1 /DestinationImageFile:install.wim /Compress:max /CheckIntegrity
Now we need to open the image in the Windows System Image Manager (from the Deployment Tools kit) and generate a catalog.
It is worth to mention that it is possible to work with images in the Windows System Image Manager only if the bit set of the system image matches the bit set of the host. That is, it is impossible to edit an image of a 32-bit version in a 64-bit system. Here, as they say, no comments.
When the directory is created, edit the answers file for the SysPrep utility. We will enter data about the owner, add the right users and configure the first autologin (Fig. 3).
Fig. 3. Answers File.
There is no point in describing all the parameters, you can get acquainted with the contents of the response file in the repository. The most important thing not to forget here is to set the CopyProfile parameter to true, SkipReam to 1 and enable the administrator autologin. Your product key can be entered in section 4 specialize - Microsoft-Windows-Shell-Setup - ProductKey.
3. Software Installation
Next, you need the actual image file install.wim, so you need to put it next to the answers file customize.xml, in which, after saving, you must manually replace the path to the image. At the end of the file, the line should look like this:
<cpi:offlineImage cpi:source="wim:d:/service/install.wim#Windows 10 Enterprise LTSB" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
To get the "KioskShell" demo interface, you need to build a version for Windows from source. Build tips are inside the repository.
Copy the files to the board and get the following file and directory structure:
C:\
└── Design\
├── backgroundDefault.jpg - admin wallpaper (with tips)
└── oemlogo.bmp - logo of the organization to be embedded in the system
D:\
├── Logs\ - folder for system and program logs
├── Service\
│ ├── AfterSetup.bat - additional packages installation, configuring the log and SysPrep launch
│ ├── FirstLogon.bat - basic automatic system setup at first start
│ ├── customize.xml - answers file
│ ├── install.wim - distribution to use and to set up
│ ├── CustomShellSetup.ps1 - PowerShell script to configure secure interface
│ ├── EnableRules.ps1 - PowerShell script to disable keyboard shortcuts
│ ├── DisableAllRules.ps1 - script to enable hot keys (for administrator)
│ └── UserLogon.bat - auto cleaning and disabling the keyboard filter (for administrator)
└── Shell\ - folder with the interface application "KioskShell.exe" and a set of libraries
4. Manual system setup
When the system is in service mode, you can reboot as many times as you need, the system will return to it automatically. With a long idle time before the power setting, however, the screen may be locked and you will not be able to return into system, only a reboot will help. Since each particular project may have its own features in customization, it is better to do it manually, but you can also use automation scripts.
Let us install the necessary components of the embedded system and disable UAC (see AfterSetup.bat from the repository)
Then we must install all the drivers, configure the hardware (IP of the network card, resolution and screen orientation, setup ports of external devices, etc.), disable sticky keys and all accessibility features.
Since it would be convenient to have a remote access for administrative needs, we should enable RDP. The administrator password expiration time will be disabled during the automatic configuration phase.
Next, we need to disable the system update in the Local Group Policy Editor (in the section Computer Configuration - Administrative Templates - Windows Components - Windows Update we must set the Configured Automatic Updates to Disabled). In addition, we also need to disable the automatic scanning of Windows Update (in the Task Scheduler section in the section Microsoft - Windows - UpdateOrchestrator we must disable all tasks), otherwise every time at system start up a black window will pop up, and Windows can suddenly start updating when connected to the Internet.
Now let us configure the power settings. To do this, we must first make all of them visible in the Advanced Power Settings (for this in the registry in each subsection of HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\238C9FA8-0AAD-41ED-83F4-97BE242C8F20 if Attributes parameter is present set it to 2). Now, when all the settings are available, turn off the sleep mode, absence mode, remove the action for the power button (unless, of course, you need specific one) and disable the authorization timer when idle. Next, we must disable the standby connected mode (in the section HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power set the CsEnabled to 0). If necessary, turn off the adaptive adjustment of the screen brightness.
When all the system settings have been made, we have the last opportunity to make any changes, since the second launch of the AfterSetup.bat script will start the automatic configuration mechanism using SysPrep, which cannot be stopped. Don't forget to activate the system (you can get information about the options for activating corporate versions of Windows by yourself). At this stage, you can make a backup of the entire disk to be able to fix the preliminary state of the image in case of any changes in the future.
At the end of the process SysPrep instead of restarting will turn off the computer — at this point you can create a working image ready for cloning to the series.
5. Final Automatic System Setup
After the first boot up of working image (see FirstLogon.bat from the repository), the protected interface will be set up, autologin will be reconfigured to the User account, and keyboard shortcuts that can break the system will be disabled. Next, Unified Write Filter will be configured and activated. In this case, the filter is configured to protect all partitions, except for the Service and Logs folders, and uses a 256 MB swap. The system will reboot several times and, if everything has been done correctly, at the next boot a protected interface started in User account will appear.
For system local maintenance, it is possible to access the login screen and, for example, log in to the administrator account. In Windows 10 there is a regular way fot it, you just need to press the "Win" key 5 times.
The Linux Way
There is no standard way to create embedded systems with graphical interface based on Linux. Nor is there a single common distribution, after all, this is a family of systems that is created on entirely different principles. Yocto Linux project might seem mostly related to the subject. However, it is quite complicated in Yocto Linux to build images with many different applications, drivers and third-party libraries. To solve the problem, it is easier to take some ready-made well-supported distribution and configure it manually.
Simple Solution
1. Basic Installation
So, first of all, we need a distribution, for example Debian. You can take another one, or even make your own. The main thing is that the distribution should not have any automatic update system. Debian Linux 9 (64-bit version, kernel 4.9) was chosen for the experimental board.
Let us install the system in the traditional way. During the installation we divide the disk into two partitions, sda1 - / for the system, sda2 - /var/log for system and program logs. Such a division will be useful later for the write filter. We add a regular graphical manager xfce and ssh server. We also add administrator account and set the password for it.
After installation the first thing we need to do is to add the administrator to the sudo group from the root account.
apt install sudo
adduser administrator sudo
Log in as administrator and add a new user user.
sudo useradd -m user
For convenience, you can remove the password, since for this account access anyway will be denied everywhere.
sudo passwd -d user
2. System Configuration
Install drivers, firmware packages, some additional programs if you wish.
To enable remote administration feature, if necessary, you can install and configure a vnc server. However, in our case, there is no point in doing this, since all administration tasks can be easily performed via the console, and for this we only need ssh access.
Linux has the ability to use different window managers for different users. Let us install a minimalist manager with the ability to fine tuning for the user interface. And for the configuration will need a few more applications.
sudo apt install fluxbox arandr plymouth
Using arandr, you can change the resolution and orientation of the screen, if necessary, and then save the configuration as a script file (Fig. 4).
Fig. 4. Screen Setup.
Next, we need to log in to the system under the user account once, selecting previously installed fluxbox as the window manager, and then back out. This is necessary in order for the fluxbox to create all the configuration files on the first launch and be selected as the standard manager for the user account (see the .dmrc file inside the user's home directory).
Now we need to configure fluxbox to meet the interface requirements described above. To do this in /home/user/.fluxbox/init turn off the panel session.screen0.toolbar.visible: false, in /home/user/.fluxbox/keys comment out all key combinations except the volume buttons, and in /home/user/.fluxbox/startup add the launch of the screen customization script, disable the energy-saving monitor functions and autorun the full-screen application. The script will restart the application in case of an unexpected failure.
set_resolution.sh
xset -dmps s off
/home/user/autostart.sh &
Now we need to speed up the boot process and hide it from the user. To do this in /etc/default/grub set GRUB_TIMEOUT=0 and in /etc/grub.d/10_linux set quiet_boot="1". To display the animation when loading add into the GRUB_CMDLINE_LINUX kernel parameters a splash option, and in case of changing the screen orientation add another option fbcon=rotate:1 or fbcon=rotate:3 depending on the direction. If necessary, you can change the resolution and orientation on the login screen. To do this, in /etc/lightdm/lightdm.conf you need to specify display-setup-script=set_resolution.sh. And if you need to hide the cursor, then add xserver-command=X -core -nocursor.
Let us choose a download style animation.
sudo plymouth-set-default-theme -R text
And finally save all the changes.
sudo update-grub2
3. Software Installation
To get the "KioskShell" demo interface, you need to build a version for Linux from source. Build tips are inside the repository.
Copy the files to the board and get the following file and directory structure:
/
├── usr/ - folder with the interface application "KioskShell" and a set of libraries
├── local/
│ └── bin/
│ └── set_resolution.sh
└── home/
├── administrator/
│ └── relogin.sh - cript to changing autologin user
└── user/
└── autostart.sh - startup script for main application
4. Final System Setup
At this stage, you can make a backup of the entire disk to be able to fix the preliminary state of the image in case of any changes in the future.
Set up automatic login into the system under the user account, to do this, in /etc/lightdm/lightdm.conf set autologin-user=user.
Now we need to set the write protection.
sudo apt install bilibop
During the installation select the dynamic fake device map.
Edit the settings file /etc/bilibop/bilibop.conf. Activate the module with the parameter BILIBOP_LOCKFS="true" and add a section with logs to the exceptions BILIBOP_LOCKFS_WHITELIST="/var/log". Let us enable the possibility of temporarily disabling protection if necessary BILIBOP_LOCKFS_POLICY="soft". And since there is no encryption in the system, we need to set BILIBOP_LOCKFS_SWAP_POLICY="soft".
Reboot the system, and, if everything has been done correctly, at the next boot a protected interface started in user account will appear.
The last stage can be easily automated to get the system with capability of automatic configuration at the first start. This will create a distribution for cloning to multiple devices (you can implement this mechanism by yourself).
For system local maintenance, it is possible to access the login screen and log in to the administrator account. In Linux, you must first get to the console via Ctrl+Alt+F1. After logging in to the administrator account, force user to log out.
sudo skill -KILL -u user
Then return to the graphic mode via Ctrl+Alt+F7 and log in again as the administrator.
Summary
Regardless of which way was chosen, ultimately we will get the same result. When properly configured, the user interface will meet all the requirements described above. Only visual differences are possible, usually related to the features of drawing graphic elements using hardware acceleration on different platforms.
Fig. 5. Running Interface.
Since the basis of the system is a single-board computer, it is easy to install any touchscreen or other controls. If you have an appropriate application, using this base you can create not only a simple control panel or an interactive dashboard, but also other devices, such as information or trading terminals.
The Problem of Choice
It has been argued that Linux is very difficult to set up and maintain, but it is free, while Windows is simple and convenient, but it costs money. This is probably true, but only in daily life. When it comes to creating embedded systems, other circumstances should be taken into account. For example, fine-tuning Windows, especially in terms of power management and other low-level elements, does not seems any simple or convenient. And do not forget that Windows 10 is quite greedy for resources. In this example, it has been managed to measure several times the memory consumption of a clean lightweight system, and it was about 400 MB in an idle state. For comparison, Linux Debian with all additions used about 200 MB of memory. Of course, if you have several gigabytes of RAM, this is not a problem, but still, when using Windows and high-loaded client applications, you would better use more powerful single-board computers. Linux is less demanding on resources, but is really difficult to set up and requires a careful approach, especially when working with the bootloader. Moreover, when developing and introducing some elements into the system, sometimes you can find it necessary to build your own kernel with special parameters. It is effective, but requires an appropriate level of qualification.
Within creation of secure interface, it is difficult to make an distinct choice. The complexity of deploying systems is about the same. The cost of acquiring licenses for Windows for a series of devices can be equal to the costs of maintaining systems on Linux. It is for you to decide which system to choose.
Various human-machine interfaces, created on the basis of the described examples, were introduced by the author into electronic devices for a variety of applications and have proven their performance in the real world.