MNT Reform
MNT Reform is an ARM Cortex-A53 powered open hardware laptop.
Hardware
root #
lspci
root #
lsusb
root #
cat /proc/cpuinfo
Installation
Installing Gentoo on the MNT Reform is very similar to how one installs Gentoo on just about any desktop / laptop system. The only parts that need special attention are the bootloader and the kernel.
u-boot
The MNT Reform boots using the u-boot bootloader. There is a patched version available in a separate repository. This bootloader can be used on either an SD-card or on the internal storage, or on both of them.
Unmodified, the bootloader will first attempt to find an OS on the SD card when one is present. For that purpose, it will search the SD-cards first partition for a file /boot.scr and if it can't find that file, for /boot/boot.scr with boot.scr being a u-boot script. If no SD-card is present or none of the above files can be found on the SD-card, the bootloader will then proceed to search for the same files on the first partition of the internal storage.
The exact behavior can be studied and / or modified in the file board/boundary/nitrogen8m_som/nitrogen8m_som.c of the above-mentioned repository.
To build the bootloader, run these commands:
root #
cd /usr/src
root #
git clone https://source.mnt.re/reform/reform-boundary-uboot u-boot
root #
cd u-boot
root #
cp mntreform-config .config
root #
make flash.bin
To install the bootloader to a device, run this command:
root #
dd if=./flash.bin of=/dev/mmcblk1 conv=notrunc bs=1k seek=33
With /dev/mmcblk1 being the SD-card to install it to.
boot script
The bootloader, as prepared above, will load a boot script. This boot script contains the further details on how to load the kernel, device tree, initrd and pass the kernel command line parameters.
The official images for the MNT Reform use a Debian tool called flash-kernel to generate the boot script. But it can pretty easily be done by hand.
First, install the u-boot utilities:
root #
emerge --ask dev-embedded/u-boot-tools
Now, a boot script is needed in human-readable text form. Start out with the same template as used by Debian's flash-kernel. The file is located at: https://salsa.debian.org/installer-team/flash-kernel/-/blob/master/bootscript/arm64/bootscr.uboot-generic
Place that in a file boot.txt, then edit it. Primarily, replace the @@LINUX_KERNEL_CMDLINE_DEFAULTS@@
and @@LINUX_KERNEL_CMDLINE@@
values. The values used in the official Image (as of v3) are ro no_console_suspend cma=512M pci=nomsi
and console=ttymxc1,115200 console=tty1
respectively.
Replace @@KERNEL_VERSION@@
with the kernel version information and remove the @@UBOOT_ENV_EXTRA@@
part.
Once satisfied, compile it by running:
root #
mkimage -A arm -O linux -T script -C none -a 0x0 -e 0x0 -n "boot script" -d boot.txt boot.scr
The while compiling, the file's header information will be printed. To show that information later, run:
root #
dumpimage -l boot.scr
The output is supposed to look a bit like this:
Image Name: boot script Created: Mon Mar 14 15:31:46 2022 Image Type: ARM Linux Script (uncompressed) Data Size: 2441 Bytes = 2.38 KiB = 0.00 MiB Load Address: 00000000 Entry Point: 00000000 Contents: Image 0: 2433 Bytes = 2.38 KiB = 0.00 MiB
Here is the complete boot script used when creating this tutorial:
root #
cat boot.txt
Install to SD-card
Having u-boot and the boot script, install them to an SD-card. Since the SD-card will only hold the kernel and initrd, it can be relatively small.
First, prepare the partition table:
root #
parted --script /dev/mmcblk1 "mklabel msdos"
root #
parted --script /dev/mmcblk1 "mkpart primary ext4 4MiB -1"
root #
mkfs.ext4 /dev/mmcblk1p1
Next, write the bootloader to the exact location it needs to be at:
root #
dd if=./flash.bin of=/dev/mmcblk1 conv=notrunc bs=1k seek=33
Now, mount the SD-card's first partition, and place the files in a structure like so (using kernel version 5.12.0 in the below example):
├── boot.scr # The boot script ├── dtb-5.12.0 # The device tree ├── initrd.img-5.12.0 # The initramfs └── vmlinuz-5.12.0 # The kernel
Install to internal storage
To boot from the internal storage instead of the SD-card, first partition the storage at mmcblk0
:
root #
parted --script /dev/mmcblk0 "mklabel msdos"
root #
parted --script /dev/mmcblk0 "mkpart primary ext4 4MiB -1"
root #
mkfs.ext4 /dev/mmcblk0p1
Now, before we can write the bootloader to the internal storage, we have to make it writeable:
root #
echo 0 > /sys/class/block/mmcblk0boot0/force_ro
Now, we can write the bootloader:
root #
dd if=./flash.bin of=/dev/mmcblk0boot0 conv=notrunc bs=1k seek=33
Now, mount the partition created above and place the files in a structure like so (using kernel version 5.12.0 in the below example):
├── boot.scr # The boot script ├── dtb-5.12.0 # The device tree ├── initrd.img-5.12.0 # The initramfs └── vmlinuz-5.12.0 # The kernel
Depending on when you received your MNT Reform, you might have to toggle the DIP switch on the SOM to enable booting from the internal storage.
initrd
When generating an initrd make sure the following kernel modules are included and loaded early, to ensure the display output is working:
- reset_imx7
- mux_mmio
- fixed
- i2c-imx
- fan53555
- i2c_mux_pca954x
- pwm_imx27
- pwm_bl
- panel_edp
- ti_sn65dsi86
- imx-dcss
- phy-fsl-imx8-mipi-dphy
- nwl-dsi
- mxsfb
- usbhid
- imx8mq-interconnect
- nvme
The above list is based off this script from the reference image. Depending on which tool you use to generate the initrd, all or some of those might be included automatically.
When using dracut to build the initrd, add a configuration file that looks like this:
/etc/dracut.conf.d/20_mnt-reform-2.conf
force_drivers+=" reset_imx7 mux_mmio fixed i2c-imx fan53555 i2c_mux_pca954x pwm_imx27 pwm_bl panel_edp ti_sn65dsi86 imx-dcss phy-fsl-imx8-mipi-dphy nwl-dsi mxsfb usbhid imx8mq-interconnect nvme "
Kernel
I have created an ebuild for a patched kernel.
This ebuild is based on the sys-kernel/gentoo-kernel and thus includes the usual Gentoo-specific kernel patches and is based on the same configuration as the Gentoo kernel. Additionally, it also incorporates the patches and configuration used in building the reference kernel.
Note that the author of this ebuild is not associated with MNT and this kernel is not officially supported by MNT.
First, add the necessary repository:
root #
eselect repository enable mnt-reform
root #
emerge --sync mnt-reform
Optionally updated eix:
root #
eix-update --repo-name mnt-reform2
Now, install the kernel. Note that this will take about 8 hours on the MNT Reform itself:
root #
emerge --ask sys-kernel/mnt-reform2-kernel
By default, this will also trigger initramfs generation through dracut. Make sure to end up with a working initramfs as in the the previous chapter.
As of now, the resulting image is gzip compressed, but u-boot expects an uncompressed kernel image. Manually unpack the image and place it in the correct location for the system to successfully boot:
root #
mv /boot/vmlinuz-${kernel_version}-mnt-reform2{,.gz}
root #
gunzip /boot/vmlinuz-${kernel_version}-mnt-reform2.gz
Check the format of the resulting file:
root #
file /boot/vmlinuz-${kernel_version}-mnt-reform2
/boot/vmlinuz-6.1.8-mnt-reform2: Linux kernel ARM64 boot executable Image, little-endian, 4K pages
Before rebooting the system, please make sure all files are named correctly. In particular, the u-boot boot script expects the kernel to be named vmlinuz-<VERSION> whereas the file installed by this ebuild is called vmlinuz-<VERSION>-mnt-reform2.
The same goes for the initrd which is expected by the boot script to be named initrd.img-<VERSION> whereas the file generated by dracut will be called initramfs-<VERSION>-mnt-reform2.img.
So either rename the files or modify the boot script to make this work.
f0 respawning
With a default arm64 system, error messages like this will appear both on the default TTY
in the system log:
Id "f0" respawning too fast: disabled for 5 minutes
To get rid of those, edit the inittab
at /etc/inittab and remove or comment out the last line, that looks something like this:
/etc/inittab
# Architecture specific features
f0:12345:respawn:/sbin/agetty 9600 ttyAMA0 vt100
Then, restart the system.
Clock loses time on reboot
The Reform has two Real-time clocks installed in the system - a battery backed up PCF8523
and an on-CPU SNVS
. The SNVS
clock is powered by the same rail as the i.MX8M
CPU and will reset together with the system.
By default, the hwclock
is using /dev/rtc0, which might be the wrong clock.
To fix this issue, either remove the rtc-snvs
kernel driver, or edit the following line in the /etc/conf.d/hwclock file:
/etc/conf.d/hwclock
clock_args="--rtc /dev/rtc1"
Check which RTC has been assigned to which device by looking at the kernel ring buffer:
user $
dmesg | grep --ignore-case rtc
[ 3.556883] rtc-pcf8523 2-0068: registered as rtc0 [ 3.563641] rtc-pcf8523 2-0068: setting system clock to 2020-07-13T17:27:26 UTC (1594661246)
In the above example, the PCF8523
is the only RTC and it is assigned to /dev/rtc0.
Build the out-off-tree LPC kernel module
An out of tree kernel module exists that allows the OS to interact with the LPC System controller. Foremost, it makes battery / charge information available in Linux.
The GCC used to compile the module must be the exact same that was used to build the kernel, otherwise, the build will abort with an error.
root #
cd /usr/src/
root #
git clone https://source.mnt.re/reform/reform-tools.git
root #
cd reform-tools/lpc/
Once compiled, you can now load the module like so:
root #
insmod /usr/src/reform-tools/lpc/reform2_lpc.ko
Details about the laptop's power supply is now available through /sys/class/power_supply/8xlifepo4/.
To install the module into a path where it can be handled more easily, run these commands:
root #
mkdir --parents /lib/modules/$(uname --kernel-release)/kernel/drivers/other/reform2_lpc
root #
cp /usr/src/reform-tools/lpc/reform2_lpc.ko /lib/modules/$(uname --kernel-release)/kernel/drivers/other/reform2_lpc/
root #
depmod
You should now be able to load the module lik so:
root #
modprobe reform2_lpc