nils-werner / raspi-overlayroot

Protect your SD card against wear and tear
MIT License
117 stars 21 forks source link

overlayroot on GoFlex NET with arch Linux - ! NOW WORKING! #7

Closed Lalarian closed 6 years ago

Lalarian commented 6 years ago

Hello!

I just tried this on my arch system (goflex net, but should be working anyway, or shouldn't it?) When logging in I get the confirmation, that overlayfs is active and changes wheren't persistent, but:

First I tried it with / being mounted as rw in fstab, but changes on / still where persistent. So I tried changing to ro in fstab, but all I then got was a simple ro / filesystem. I cannot write anything to root. So there's no difference as if I had simply put root to ro in fstab without overlayfs. Also "mount|grep overlay" doesn't show me anything? What is wrong?

Thank you! :)

nils-werner commented 6 years ago

Can you post

Lalarian commented 6 years ago
[root@alarm ~]# cat /etc/mkinitcpio.conf
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck overlayroot)

Everything else is commented.

[root@alarm ~]# mkinitcpio -P
==> Building image from preset: /etc/mkinitcpio.d/linux-kirkwood.preset: 'default'
  -> -k 4.4.162-1-ARCH -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 4.4.162-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
  -> Running build hook: [overlayroot]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful

/boot/cmdline.txt is filled following your example, adapted to the GoFlex NET:

root=/dev/sda1 ro rootwait console=ttyS0,115200 console=ttyS0 dwc_otg.lpm_enable=0 kgdboc=ttyS0,115200 elevator=noop overlayroot

I don't think this has an effect on this device, though, as it's done by setting an ENV here:

setargs=setenv bootargs console=${console},${baudrate} ${optargs} root=/dev/sd${letter}1 rw rootwait ${mtdparts} overlayroot
[root@alarm ~]# cat /etc/fstab
<file system> <dir> <type> <options> <dump> <pass>
/dev/sda1   /   ext2    defaults,rw 0   1
UUID="ccc6cd26-2bfc-44de-af89-978b7842fb3f" none swap sw 0 0

There also is the welcome message:

[root@alarm ~]# ssh root@prtsrv
Last login: Mon Nov  5 22:54:58 2018 from 192.168.1.35

==> WARNING: Overlayroot in effect.
None of the changes you make will be preseved after reboot.

To disable overlayroot remove the 'overlayroot' argument
from the kernel commandline.

And the overlayroot process is running:

[root@alarm ~]# ps aux| grep overlay
root         1  3.3  5.8  14716  7040 ?        Ss   22:58   0:05 /sbin/init overlayroot
nils-werner commented 6 years ago

Please read the markdown docs on how to format your post

Lalarian commented 6 years ago

I have removed all commented lines. I think it's readable now.

nils-werner commented 6 years ago

Not really, sorry... :-D

Lalarian commented 6 years ago

There's some bug with my webbrowser cropping the formatting code. I hope it's acceptable now, I have filled all code manually.

nils-werner commented 6 years ago

I only just realized that you're not using this on a Raspberry Pi. I have no idea how this device works, so I don't think I can help you there. The only remaining issue I can think of, but this is very Raspi-specific, is that /boot/config.txt is missing the line

initramfs initramfs-linux.img followkernel

Also, I have fixed your post to make it more readable. Please familiarize yourself with Markdown more, so you can help people help you.

Lalarian commented 6 years ago

Yes. The thing is that I think there's enough similarity for making it work, as soon as the "lowlevel" criteria are fulfilled. I can confirm, that the bootargs are realized correctly, from searching a dmesg:

dmesg

[    0.000000] Kernel command line: console=ttyS0,115200 root=/dev/sda1 ro rootwait mtdparts=orion_nand:1M(u-boot),-(rootfs) initramfs initramfs-linux.img followkernel overlayroot

So the next thing I wonder about is that, what should normally happen next? From what I see the problems seems to be that the hook scripts are not executed. Should the modified initramfs execute the scripts in /usr/lib/initcpio/hooks/ while booting, or are these scripts directly embedded into the initramfs by "mkinitcpio -P"?

Also I am wondering, if there's a way to check, if the system really loaded the initramfs file as instructed in the bootargs.

Lalarian commented 6 years ago

Hello!

Inspired by those thoughts before, I examined the loading of the initramfs further. I then learned that I had to convert the initramfs to an uInitrd image using mkimage and load it manually by adding a parameter to UBoot's "bootm" command. The initramfs now is successfully loaded at boot!

Serial Log:

Attempting to boot from ide 0:1...
** File not found /boot/uEnv.txt **
Checking if uenvcmd is set ...
Running default loadzimage ...
** File not found /boot/zImage **
5914697 bytes read in 1651 ms (3.4 MiB/s)
Running default loaduimage ...
4604768 bytes read in 1182 ms (3.7 MiB/s)
Booting from 0 ...
## Booting kernel from Legacy Image at 00810000 ...
   Image Name:   Linux-4.4.162-1-ARCH
   Created:      2018-10-28   4:03:32 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    4604704 Bytes = 4.4 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 01100000 ...
   Image Name:   initramfs-linux.img-2018-11
   Created:      2018-11-06  11:59:26 UTC
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    5914633 Bytes = 5.6 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
   Loading Ramdisk to 07569000, end 07b0d009 ... OK

Starting kernel ...

The remaining problem is, that the initramfs does not contain the overlay module, although it has been built successfully using mkinitcpio. Do you have an idea, where I could search for the reason for this problem?

[   25.650611] random: nonblocking pool is initialized===      / 89.6%   
root: 85328/235248 files (5.4% non-contiguous), 774288/939264 blocks           
:: mounting '/dev/sda1' on real root
[   26.368534] EXT4-fs (sda1): mounting ext2 file system using the ext4 subsystem
[   26.380182] EXT4-fs (sda1): mounted filesystem without journal. Opts: (null)
:: running late hook [overlayroot]
mount: /new_root: unknown filesystem type 'overlay'.
nils-werner commented 6 years ago

Interesting and glad you made some progress!

/etc/mkinitcpio.conf should contain an array MODULES, have you tried adding overlay to it and then rebuilding your initramfs?

Lalarian commented 6 years ago

Yeah! I got it working! :)

What I had to do, in case someone else might ever need it: Installation on Seagate GoFlex NET with latest UBoot from bodhi / Doozan and arch Linux.

For anyone following my way: PLEASE BE CAREFUL IF YOU DON'T KNOW WHAT YOU ARE DOING AND FIRST TRY THIS ON AN USB MEDIUM, as it might make you device unbootable if done wrong!

(Should work same on Debian, but instead of initcpio it's initramfs there https://manpages.ubuntu.com/manpages/trusty/man5/initramfs.conf.5.html)

1. Change the mkinitpcio.conf. Force mkinitcpio to add the overlay module to initramfs. Otherwise the created initramfs will lack the overlay module. cat /etc/mkinitcpio.conf

# vim:set ft=sh
# MODULES
# The following modules are loaded before any boot hooks are
# run.  Advanced users may wish to specify all system modules
# in this array.  For instance:
#     MODULES=(piix ide_disk reiserfs)
MODULES=(overlay)

# BINARIES
# This setting includes any additional binaries a given user may
# wish into the CPIO image.  This is run last, so it may be used to
# override the actual binaries included by a given hook
# BINARIES are dependency parsed, so you may safely ignore libraries
BINARIES=()

# FILES
# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in any way.  This is useful for config files.
FILES=(/usr/lib/modules/4.4.162-1-ARCH/kernel/fs/overlayfs/overlay.ko)

# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
##   This setup specifies all modules in the MODULES setting above.
##   No raid, lvm2, or encrypted root is needed.
#    HOOKS=(base)
#
##   This setup will autodetect all modules for your system and should
##   work as a sane default
#    HOOKS=(base udev autodetect block filesystems)
#
##   This setup will generate a 'full' image which supports most systems.
##   No autodetection is done.
#    HOOKS=(base udev block filesystems)
#
##   This setup assembles a pata mdadm array with an encrypted root FS.
##   Note: See 'mkinitcpio -H mdadm' for more information on raid devices.
#    HOOKS=(base udev block mdadm encrypt filesystems)
#
##   This setup loads an lvm2 volume group on a usb device.
#    HOOKS=(base udev block lvm2 filesystems)
#
##   NOTE: If you have /usr on a separate partition, you MUST include the
#    usr, fsck and shutdown hooks.
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck overlayroot)

# COMPRESSION
# Use this to compress the initramfs image. By default, gzip compression
# is used. Use 'cat' to create an uncompressed image.
#COMPRESSION="gzip"
#COMPRESSION="bzip2"
#COMPRESSION="lzma"
#COMPRESSION="xz"
#COMPRESSION="lzop"
#COMPRESSION="lz4"

# COMPRESSION_OPTIONS
# Additional options for the compressor
#COMPRESSION_OPTIONS=()

2. Create the initramfs

mkinitcpio -P

3. create an uImage from initramfs-linux.img

mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 -n Linux(insert version here if you like)  -d /boot/initramfs-linux.img /boot/uInitrd

4. Make the GoFlex-UBoot load the freshly created uInitrd into RAM and add parameter to bootm for loading this additional to the kernel (there's no need for "initramfs initramfs-linux.img followkernel" in the kernel bootargs on this device, but my bootargs are modified, because I tried this before I knew better. Also cmdline.txt is not needed):

arcNumber=3089
baudrate=115200
bootcmd=ide reset; usb start; setenv letter 9;for type in ide usb; do for disk in 0 1; do if ls ${type} ${disk};then setexpr letter $letter + 1;run load;fi;done;done;
bootcmdold=ide reset; usb start; setenv letter 9;for type in ide usb; do for disk in 0 1; do if ${type} part ${disk};then setexpr letter $letter + 1;run load;fi;done;done;
bootdelay=3
bootm=echo Booting from ${disk} ...; run setargs; bootm ${loadaddr} 0x1100000;
bootm-new=echo Booting from ${disk} ...; run setargs; bootm ${loadaddr} 0x1100000;
bootm-old=echo Booting from ${disk} ...; run setargs; bootm ${loadaddr};
bootz=echo Booting from ${disk} ...; run setargs; bootz ${loadaddr} - ${fdt_addr};
console=ttyS0
ethact=egiga0```
ethaddr=11:22:33:44:55:66
fdt_addr=0x800000
fdt_file=/boot/dtbs/kirkwood-goflexnet.dtb
importbootenv=echo Importing environment (uEnv.txt)...; env import -t $loadaddr $filesize
letter=9
load=echo Attempting to boot from ${type} ${disk}:1...;if run loadbootenv; then run importbootenv;fi;echo Checking if uenvcmd is set ...;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;echo Running default loadzimage ...;if run loadzimage; then run loadfdt;run bootz;fi;run loaduinitrd;echo Running default loaduimage ...;if run loaduimage; then run bootm 0x800000 0x1100000;fi;
load-old=echo Attempting to boot from ${type} ${disk}:1...;if run loadbootenv; then run importbootenv;fi;echo Checking if uenvcmd is set ...;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;echo Running default loadzimage ...;if run loadzimage; then run loadfdt;run bootz;fi;echo Running default loaduimage ...;if run loaduimage; then run bootm;fi;
loadaddr=0x810000
loadbootenv=load ${type} ${disk}:1 ${loadaddr} /boot/uEnv.txt
loadfdt=load ${type} ${disk}:1 ${fdt_addr} ${fdt_file}
loaduimage=load ${type} ${disk}:1 ${loadaddr} ${uimage}
loaduinitrd=ext2load ide 0:1 0x1100000 /boot/uInitrd;
loadzimage=load ${type} ${disk}:1 ${loadaddr} ${zimage}
mtdids=nand0=orion_nand
mtdparts=mtdparts=orion_nand:1M(u-boot),-(rootfs)
rootfstype=ext4
setargs=setenv bootargs console=${console},${baudrate} ${optargs} root=/dev/sd${letter}1 rw rootwait ${mtdparts} overlayroot
stderr=serial
stdout=serial
sterr=serial
uimage=/boot/uImage
zimage=/boot/zImage

Toggle write protection script, for persistent changes to the system's configuration: I also made a script (some years later ;) ) to easily toogle between 'write protected' and non write protected mode. (This script reboots the device! There's an 'official' way to avoding a reboot and commit changes to the flash live, but it was too complicated for me to use at some point)

` cat /usr/bin/toggleoverlayroot

/bin/bash

status=$(fw_printenv overlayroot)

echo $status

if [[ "$status" == "overlayroot" ]] then echo "flash is protected, now unprotecting!" fw_setenv overlayroot '' else echo "flash is unprotected, now protecting!" fw_setenv overlayroot 'overlayroot' fi sleep 3 sync sync sync echo "Rebooting!" reboot `

Lalarian commented 4 months ago

Here's the firmware-ENV adapted for the tooglescript to work. Sorry, I forgot to post these changes before!

[root@prtsrv ~]# fw_printenv 
bootcmd_exec=run load_uimage; if run load_initrd; then if run load_dtb; then bootm $load_uimage_addr $load_initrd_addr $load_dtb_addr; else bootm $load_uimage_addr $load_initrd_addr; fi; else if run load_dtb; then bootm $load_uimage_addr - $load_dtb_addr; else bootm $load_uimage_addr; fi; fi
bootdelay=10
bootdev=usb
device=0:1
devices=usb ide mmc
disks=0 1 2 3
ethact=egiga0
ethaddr=00:50:43:00:02:02
led_error=orange blinking
led_exit=green off
led_init=green blinking
load_dtb_addr=0x1c00000
load_initrd_addr=0x1100000
load_uimage_addr=0x800000
load_dtb=echo loading DTB $dtb_file ...; load $bootdev $device $load_dtb_addr $dtb_file
load_initrd=echo loading uInitrd ...; load $bootdev $device $load_initrd_addr /boot/uInitrd
load_uimage=echo loading uImage ...; load $bootdev $device $load_uimage_addr /boot/uImage
mainlineLinux=yes
mtdids=nand0=orion_nand
partition=nand0,2
stderr=serial
stdin=serial
stdout=serial
uenv_addr=0x810000
uenv_import=echo importing envs ...; env import -t $uenv_addr $filesize
uenv_init_devices=setenv init_usb "usb start";  setenv init_ide "ide reset";  setenv init_mmc "mmc rescan"; for devtype in $devices; do run init_$devtype; done;
uenv_load=run uenv_init_devices; setenv uenv_loaded 0; for devtype in $devices;  do for disknum in 0; do run uenv_read_disk; done; done;
uenv_read_disk=if test $devtype -eq mmc; then if $devtype part; then run uenv_read;  fi; else if $devtype part $disknum; then run uenv_read; fi;  fi
uenv_read=echo loading envs from $devtype $disknum ...; if load $devtype $disknum:1 $uenv_addr /boot/uEnv.txt; then setenv uenv_loaded 1; fi
usb_ready_retry=15
arcNumber=3089
dtb_file=/boot/dts/kirkwood-goflexnet.dtb
mtdparts=mtdparts=orion_nand:1M(u-boot),4M(uImage),32M(rootfs),-(data)
set_bootargs_rescue=setenv bootargs console=$console ubi.mtd=2 root=ubi0:rootfs ro rootfstype=ubifs $mtdparts
bootcmd_rescue=run set_bootargs_rescue; nand read.e 0x800000 0x100000 0x400000; bootm 0x800000
bootcmd_pogo=run bootcmd_rescue
rescue_installed=1
if_netconsole=ping $serverip
start_netconsole=setenv ncip $serverip; setenv bootdelay 10; setenv stdin nc; setenv stdout nc; setenv stderr nc; version;
preboot_nc=setenv nc_ready 0; for pingstat in 1 2 3 4 5; do; sleep 1; if run if_netconsole; then setenv nc_ready 1; fi; done; if test $nc_ready -eq 1; then run start_netconsole; fi
preboot=run preboot_nc
scan_disk=echo running scan_disk ...; scan_done=0; setenv scan_usb "usb start";  setenv scan_ide "ide reset";  setenv scan_mmc "mmc rescan"; for dev in $devices; do if test $scan_done -eq 0; then echo Scan device $dev; run scan_$dev; for disknum in $disks; do if test $scan_done -eq 0; then echo device $dev $disknum:1; sleep $sleep_period; if load $dev $disknum:1 $load_uimage_addr /boot/uImage 1; then scan_done=1; echo Found bootable drive on $dev $disknum; setenv device $disknum:1; setenv bootdev $dev; fi; fi; done; fi; done
ipaddr=192.168.1.40
sleep_period=3
bootcmd_uenv=run uenv_load; if test $uenv_loaded -eq 1; then run uenv_import; fi; sleep 3
bootcmd=sleep 3; run scan_disk; run set_bootargs; run bootcmd_exec; run bootcmd_pogo; reset
serverip=192.168.1.31
set_bootargs=setenv bootargs console=ttyS0,115200 root=LABEL=root rootdelay=10 $mtdparts $custom_params $overlayroot
custom_params=usbcore.autosuspend=-1
overlayroot=overlayroot