These are the steps to create the image, based on Miki Shapiros ansible scripts. Some pieces are borrowed from the Nintendo Switch Fed32 setup. The generic raspi4 notes are here.
This guide here installs plain Fedora 32 on the sdcard, but you might want to consider these steps for dualboot with RaspiOS instead. For firmware upgrades, it's probably good to have a usable RaspiOS at the card.
The steps guide to:
These steps can be executed on a normal Fedora system, I use Fedora 32 x86_64. Before you start, upgrade the firmware of your Raspi to the latest available versions. The builder for RaspiOS is pi-gen.
# Our directory for storing images etc. WORKDIR="/home/chris/Downloads/raspi" # Our output device OUTDEV="/dev/mmcblk0" mkdir -p $WORKDIR/mnt/fedora32/root $WORKDIR/mnt/raspbian/root \ $WORKDIR/mnt/piroot $WORKDIR/mnt/boot ### Fetch and prepare Fedora cd $WORKDIR curl http://ftp.riken.jp/Linux/fedora/releases/32/Server/aarch64/images/Fedora-Server-32-1.6.aarch64.raw.xz xz -dk Fedora-Server-32-1.6.aarch64.raw.xz kpartx -av Fedora-Server-32-1.6.aarch64.raw # This created /dev/mapper/loopXp1 (vfat part) and /dev/mapper/loopXp2 (ext4 partition) vgchange -ay fedora mount /dev/fedora/root $WORKDIR/mnt/fedora32/root ### Fetch and prepare RaspiOS curl http://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2020-05-28/2020-05-27-raspios-buster-lite-armhf.zip unzip 2020-05-27-raspios-buster-lite-armhf.zip kpartx -av 2020-05-27-raspios-buster-lite-armhf.img # This created /dev/mapper/loopYp1 (vfat part) and /dev/mapper/loopYp2 (ext4 partition) mount /dev/mapper/loop1p2 $WORKDIR/mnt/raspbian/root ### Prepare the sdcard # We copy everything until the end of the boot partition to # $OUTDEV. As long as you use the same RaspiOS image, # you can stay with these numbers. ( dd if=$WORKDIR/2020-05-27-raspios-buster-lite-armhf.img count=8 bs=524288; dd if=$WORKDIR/2020-05-27-raspios-buster-lite-armhf.img bs=524288 skip=8 count=512 ) | dd of=$OUTDEV bs=524288 # Expand partition 2 to span the whole device parted /dev/mmcblk0 resizepart 2 100% mkfs.ext4 ${OUTDEV}p2 ### copy over the Fedora root filesystem mount ${OUTDEV}p2 $WORKDIR/mnt/piroot cd $WORKDIR/mnt/fedora32/root tar cfp - . | ( cd $WORKDIR/mnt/piroot; tar xfp - ) ### Prepare new image cd $WORKDIR/mnt/piroot # set your root-password to 'fedora' sed -ie 's,^root.*,root:$6$g1sdJY/CulQKzQmS$heAUJV60eTr1HQtTTR188WlA/vOTj6LPuKA7JB1wKEgPiW1qX2gPJHU8lLhSL8KeKgx.hGgUvQ4uzW6JQ68u40:18388:0:99999:7:::,' etc/shadow # As an alternative, execute 'vi etc/shadow' and manually # change the password hash to something else. echo 'PermitRootLogin yes' >>etc/ssh/sshd_config echo pi4.local >etc/hostname echo '127.0.0.1 pi4.local pi4' >>etc/hosts # We just need these 2 lines echo '/dev/mmcblk0p1 /boot vfat defaults,noatime 0 0' >etc/fstab echo '/dev/mmcblk0p2 / ext4 defaults,noatime 0 0' >>etc/fstab # Copy over RaspiOS kernel modules, firmware, modprobe blacklist cp -urfp $WORKDIR/mnt/raspbian/root/lib/modules $WORKDIR/mnt/piroot/usr/lib cp -urfp $WORKDIR/mnt/raspbian/root/lib/firmware $WORKDIR/mnt/piroot/root/lib cp -urfp $WORKDIR/mnt/raspbian/root/etc/modprobe.d/. $WORKDIR/mnt/piroot/etc/modprobe.d/ umount $WORKDIR/mnt/raspbian/root cat >etc/sysconfig/network-scripts/ifcfg-eth0<<EOT TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy IPADDR=192.168.0.4 PREFIX=24 GATEWAY=192.168.0.1 DNS1=8.8.8.8 NAME=eth0 DEVICE=eth0 ONBOOT=yes AUTOCONNECT_PRIORITY=-999 EOT # Disable the initial-setup and other unneeded services rm -f etc/systemd/system/multi-user.target.wants/initial-setup.service rm -f etc/systemd/system/multi-user.target.wants/abrtd.service rm -f etc/systemd/system/multi-user.target.wants/abrt-journal-core.service rm -f etc/systemd/system/multi-user.target.wants/abrt-oops.service rm -f etc/systemd/system/multi-user.target.wants/abrt-vmcore.service rm -f etc/systemd/system/multi-user.target.wants/abrt-xorg.service rm -f etc/systemd/system/multi-user.target.wants/cups.service rm -f etc/systemd/system/multi-user.target.wants/nfs-client.service rm -f etc/systemd/system/multi-user.target.wants/vboxservice.service rm -f etc/systemd/system/multi-user.target.wants/vmtoolsd.service rm -f etc/systemd/system/multi-user.target.wants/ModemManager.service rm -f etc/systemd/system/multi-user.target.wants/rngd.service rm -f etc/systemd/system/multi-user.target.wants/avahi-daemon.service rm -f etc/systemd/system/multi-user.target.wants/auditd.service rm -f etc/systemd/system/multi-user.target.wants/smartd.service rm -f etc/systemd/system/multi-user.target.wants/libvirtd.service rm -f etc/systemd/system/multi-user.target.wants/remote-fs.service rm -f etc/systemd/system/sysinit.target.wants/multipathd.service rm -f etc/systemd/system/sockets.target.wants/multipathd.socket cd .. ### prepare boot partition mount ${OUTDEV}p1 $WORKDIR/mnt/boot vi $WORKDIR/mnt/boot/cmdline.txt # change 'console=[..]' # into 'console=serial0,115200 console=tty1 root=PARTUUID=738a4d67-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait' # Configure the firmware to boot the 64bit kernel, not the 32bit one # details: https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=250730 echo 'arm_64bit=1' >>$WORKDIR/mnt/boot/config.txt chmod 0755 $WORKDIR/mnt/piroot umount $WORKDIR/mnt/boot umount $WORKDIR/mnt/piroot umount $WORKDIR/mnt/fedora32/root lvchange -a n fedora kpartx -dv $WORKDIR/Fedora-Server-32-1.6.aarch64.raw kpartx -dv $WORKDIR/2020-05-27-raspios-buster-lite-armhf.img
You should now be able to boot from the sdcard and login.
cat >>~/.bashrc<<EOT # extend prompt to have temperature export PS1='[\u@\h $(cut -b 1,2 /sys/devices/virtual/thermal/thermal_zone0/temp)°C \W]\$ ' # colored iostat output export S_COLORS=always EOT ### tuning cat >/etc/rc.local<<EOT #!/usr/bin/bash # VM writeback timeout echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs' # power saving for wlan and usb chips echo 'auto' > '/sys/bus/pci/devices/0000:01:00.0/power/control' echo 'auto' > '/sys/bus/pci/devices/0000:00:00.0/power/control' EOT chmod +x /etc/rc.local /etc/rc.local ln -s /etc/rc.local /etc/rc.d/rc.local # To get further ideas about services we do not need systemd-analyze plot >file.svg # For my use cases: systemctl disable lmsensors firewalld # I like gkrellm dnf -y install gkrellm-daemon sysstat htop echo 'allow-host 192.168.0.2' >>/etc/gkrellmd.conf systemctl enable --now gkrellmd # update dnf -y update