From 912b85db0e3c3827d4e6ad1bcbd865f3779a016d Mon Sep 17 00:00:00 2001 From: Tracker-Friendly Date: Mon, 14 Aug 2023 02:03:12 +0100 Subject: [PATCH] Migrated to codeberg --- .gitignore | 16 + COPYING | 23 + Makefile | 111 ++ README.md | 71 + build-x86-images.sh | 148 ++ data/issue | 28 + data/splash.png | Bin 0 -> 11858 bytes dracut/autoinstaller/autoinstall.cfg | 76 + dracut/autoinstaller/install.sh | 300 ++++ dracut/autoinstaller/module-setup.sh | 44 + dracut/netmenu/module-setup.sh | 86 + dracut/netmenu/netmenu.sh | 18 + dracut/vmklive/59-mtd.rules | 8 + dracut/vmklive/61-mtd.rules | 20 + dracut/vmklive/accessibility.sh | 10 + dracut/vmklive/adduser.sh | 57 + dracut/vmklive/display-manager-autologin.sh | 63 + dracut/vmklive/getty-serial.sh | 18 + dracut/vmklive/locale.sh | 22 + dracut/vmklive/module-setup.sh | 31 + dracut/vmklive/mtd.sh | 7 + grub/grub.cfg | 15 + grub/grub_void.cfg.in | 96 ++ include-i686/home/anon/.bashrc | 1 + include-i686/home/anon/.profile | 1 + include-i686/root/.bashrc | 1 + include-i686/root/.profile | 2 + include-i686/usr/bin/evolution-installer | 1533 +++++++++++++++++ include-i686/usr/bin/evolution-installer-beta | 239 +++ ...*-evolution-installer-repository-main.conf | 1 + ...:cf:16:5d:12:f8:b1:03:13:e5:c1:9d:4d.plist | 12 + include/home/anon/.bashrc | 1 + include/home/anon/.profile | 1 + include/root/.bashrc | 1 + include/root/.profile | 2 + include/usr/bin/evolution-installer | 1533 +++++++++++++++++ include/usr/bin/evolution-installer-beta | 239 +++ ...*-evolution-installer-repository-main.conf | 1 + ...:cf:16:5d:12:f8:b1:03:13:e5:c1:9d:4d.plist | 12 + isolinux/isolinux.cfg.in | 58 + ...:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist | 12 + ...:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist | 12 + lib.sh | 354 ++++ mkimage.sh | 409 +++++ mklive.sh | 453 +++++ mknet.sh | 275 +++ mkplatformfs.sh | 241 +++ mkrootfs.sh | 224 +++ packer/.gitignore | 6 + packer/hcl2/build-cloud-generic.pkr.hcl | 37 + packer/hcl2/build-vagrant.pkr.hcl | 45 + packer/hcl2/source-qemu.pkr.hcl | 13 + packer/hcl2/source-virtualbox-ose.pkr.hcl | 16 + packer/hcl2/vagrant/build-vagrant.pkr.hcl | 1 + .../vagrant/source-virtualbox-ose.pkr.hcl | 1 + packer/http/cloud.cfg | 39 + packer/http/x86_64-musl.cfg | 42 + packer/http/x86_64.cfg | 39 + packer/scripts/cloud.sh | 29 + packer/scripts/vagrant.sh | 31 + pxelinux.cfg/pxelinux.cfg.in | 36 + release.sh | 68 + version | 1 + 63 files changed, 7290 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Makefile create mode 100644 README.md create mode 100755 build-x86-images.sh create mode 100644 data/issue create mode 100644 data/splash.png create mode 100644 dracut/autoinstaller/autoinstall.cfg create mode 100755 dracut/autoinstaller/install.sh create mode 100644 dracut/autoinstaller/module-setup.sh create mode 100644 dracut/netmenu/module-setup.sh create mode 100755 dracut/netmenu/netmenu.sh create mode 100644 dracut/vmklive/59-mtd.rules create mode 100644 dracut/vmklive/61-mtd.rules create mode 100644 dracut/vmklive/accessibility.sh create mode 100644 dracut/vmklive/adduser.sh create mode 100644 dracut/vmklive/display-manager-autologin.sh create mode 100644 dracut/vmklive/getty-serial.sh create mode 100644 dracut/vmklive/locale.sh create mode 100644 dracut/vmklive/module-setup.sh create mode 100755 dracut/vmklive/mtd.sh create mode 100644 grub/grub.cfg create mode 100644 grub/grub_void.cfg.in create mode 100644 include-i686/home/anon/.bashrc create mode 100644 include-i686/home/anon/.profile create mode 100644 include-i686/root/.bashrc create mode 100644 include-i686/root/.profile create mode 100755 include-i686/usr/bin/evolution-installer create mode 100755 include-i686/usr/bin/evolution-installer-beta create mode 100644 include-i686/usr/share/xbps.d/*-evolution-installer-repository-main.conf create mode 100644 include-i686/var/db/xbps/keys/2e:ef:96:72:cf:16:5d:12:f8:b1:03:13:e5:c1:9d:4d.plist create mode 100644 include/home/anon/.bashrc create mode 100644 include/home/anon/.profile create mode 100644 include/root/.bashrc create mode 100644 include/root/.profile create mode 100755 include/usr/bin/evolution-installer create mode 100755 include/usr/bin/evolution-installer-beta create mode 100644 include/usr/share/xbps.d/*-evolution-installer-repository-main.conf create mode 100644 include/var/db/xbps/keys/2e:ef:96:72:cf:16:5d:12:f8:b1:03:13:e5:c1:9d:4d.plist create mode 100644 isolinux/isolinux.cfg.in create mode 100644 keys/3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist create mode 100644 keys/60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist create mode 100755 lib.sh create mode 100755 mkimage.sh create mode 100755 mklive.sh create mode 100755 mknet.sh create mode 100755 mkplatformfs.sh create mode 100755 mkrootfs.sh create mode 100644 packer/.gitignore create mode 100644 packer/hcl2/build-cloud-generic.pkr.hcl create mode 100644 packer/hcl2/build-vagrant.pkr.hcl create mode 100644 packer/hcl2/source-qemu.pkr.hcl create mode 100644 packer/hcl2/source-virtualbox-ose.pkr.hcl create mode 120000 packer/hcl2/vagrant/build-vagrant.pkr.hcl create mode 120000 packer/hcl2/vagrant/source-virtualbox-ose.pkr.hcl create mode 100644 packer/http/cloud.cfg create mode 100644 packer/http/x86_64-musl.cfg create mode 100644 packer/http/x86_64.cfg create mode 100644 packer/scripts/cloud.sh create mode 100644 packer/scripts/vagrant.sh create mode 100644 pxelinux.cfg/pxelinux.cfg.in create mode 100755 release.sh create mode 100644 version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de82e05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.img +*.xz +*.iso +*.raw +*.tar.gz +*.box +xbps-cache +xbps-cachedir* +stamps* +!dracut/*/*.sh +!packer/scripts/*.sh +void-live-*/ +release/ +include/var/cache/xbps +include-i686/var/cache/xbps +tmp*/ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b87022b --- /dev/null +++ b/COPYING @@ -0,0 +1,23 @@ +# Copyright (c) 2009-2015 Juan RP +# Copyright (c) 2012 Dave Elusive +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e17e85e --- /dev/null +++ b/Makefile @@ -0,0 +1,111 @@ +DATECODE:=$(shell date -u "+%Y%m%d") +SHELL=/bin/bash + +T_LIVE_ARCHS=i686 x86_64{,-musl} + +T_PLATFORMS=rpi-{armv{6,7}l,aarch64}{,-musl} beaglebone{,-musl} cubieboard2{,-musl} odroid-c2{,-musl} GCP{,-musl} pinebookpro{,-musl} +T_ARCHS=i686 x86_64{,-musl} armv{6,7}l{,-musl} aarch64{,-musl} + +T_SBC_IMGS=rpi-{armv{6,7}l,aarch64}{,-musl} beaglebone{,-musl} cubieboard2{,-musl} odroid-c2{,-musl} pinebookpro{,-musl} +T_CLOUD_IMGS=GCP{,-musl} + +T_PXE_ARCHS=x86_64{,-musl} + +LIVE_ARCHS:=$(shell echo $(T_LIVE_ARCHS)) +LIVE_FLAVORS:=base enlightenment xfce mate cinnamon gnome kde lxde lxqt +ARCHS:=$(shell echo $(T_ARCHS)) +PLATFORMS:=$(shell echo $(T_PLATFORMS)) +SBC_IMGS:=$(shell echo $(T_SBC_IMGS)) +CLOUD_IMGS:=$(shell echo $(T_CLOUD_IMGS)) +PXE_ARCHS:=$(shell echo $(T_PXE_ARCHS)) + +ALL_LIVE_ISO=$(foreach arch,$(LIVE_ARCHS), $(foreach flavor,$(LIVE_FLAVORS),void-live-$(arch)-$(DATECODE)-$(flavor).iso)) +ALL_ROOTFS=$(foreach arch,$(ARCHS),void-$(arch)-ROOTFS-$(DATECODE).tar.xz) +ALL_PLATFORMFS=$(foreach platform,$(PLATFORMS),void-$(platform)-PLATFORMFS-$(DATECODE).tar.xz) +ALL_SBC_IMAGES=$(foreach platform,$(SBC_IMGS),void-$(platform)-$(DATECODE).img.xz) +ALL_CLOUD_IMAGES=$(foreach cloud,$(CLOUD_IMGS),void-$(cloud)-$(DATECODE).tar.gz) +ALL_PXE_ARCHS=$(foreach arch,$(PXE_ARCHS),void-$(arch)-NETBOOT-$(DATECODE).tar.gz) + +SUDO := sudo + +REPOSITORY := https://repo-default.voidlinux.org/current +XBPS_REPOSITORY := -r $(REPOSITORY) -r $(REPOSITORY)/musl -r $(REPOSITORY)/aarch64 +COMPRESSOR_THREADS:=2 + +all: + +checksum: dist + cd distdir-$(DATECODE)/ && sha256 * > sha256sum.txt + +distdir-$(DATECODE): + mkdir -p distdir-$(DATECODE) + +dist: distdir-$(DATECODE) + mv void*$(DATECODE)* distdir-$(DATECODE)/ + +live-iso-all: $(ALL_LIVE_ISO) + +live-iso-all-print: + @echo $(ALL_LIVE_ISO) | sed "s: :\n:g" + +void-live-%.iso: + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./build-x86-images.sh -r $(REPOSITORY) -t $* + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +rootfs-all: $(ALL_ROOTFS) + +rootfs-all-print: + @echo $(ALL_ROOTFS) | sed "s: :\n:g" + +void-%-ROOTFS-$(DATECODE).tar.xz: + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./mkrootfs.sh $(XBPS_REPOSITORY) -x $(COMPRESSOR_THREADS) $* + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +platformfs-all: $(ALL_PLATFORMFS) + +platformfs-all-print: + @echo $(ALL_PLATFORMFS) | sed "s: :\n:g" + +.SECONDEXPANSION: +void-%-PLATFORMFS-$(DATECODE).tar.xz: void-$$(shell ./lib.sh platform2arch %)-ROOTFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./mkplatformfs.sh $(XBPS_REPOSITORY) -x $(COMPRESSOR_THREADS) $* void-$(shell ./lib.sh platform2arch $*)-ROOTFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +images-all: platformfs-all images-all-sbc images-all-cloud + +images-all-sbc: $(ALL_SBC_IMAGES) + +images-all-sbc-print: + @echo $(ALL_SBC_IMAGES) | sed "s: :\n:g" + +images-all-cloud: $(ALL_CLOUD_IMAGES) + +images-all-print: + @echo $(ALL_SBC_IMAGES) $(ALL_CLOUD_IMAGES) | sed "s: :\n:g" + +void-%-$(DATECODE).img.xz: void-%-PLATFORMFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./mkimage.sh -x $(COMPRESSOR_THREADS) void-$*-PLATFORMFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +# Some of the images MUST be compressed with gzip rather than xz, this +# rule services those images. +void-%-$(DATECODE).tar.gz: void-%-PLATFORMFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./mkimage.sh -x $(COMPRESSOR_THREADS) void-$*-PLATFORMFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +pxe-all: $(ALL_PXE_ARCHS) + +pxe-all-print: + @echo $(ALL_PXE_ARCHS) | sed "s: :\n:g" + +void-%-NETBOOT-$(DATECODE).tar.gz: void-%-ROOTFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf "::group::\x1b[32mBuilding $@...\x1b[0m\n" || true + $(SUDO) ./mknet.sh void-$*-ROOTFS-$(DATECODE).tar.xz + @[ -n "${CI}" ] && printf '::endgroup::\n' || true + +.PHONY: all checksum dist live-iso-all live-iso-all-print rootfs-all-print rootfs-all platformfs-all-print platformfs-all pxe-all-print pxe-all diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c43fda --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# The Void Linux image/live/rootfs maker and installer + +This repository contains utilities for Void Linux: + + * installer (The Void Linux el-cheapo installer for x86) + * mklive (The Void Linux live image maker for x86) + + * mkimage (The Void Linux image maker for ARM platforms) + * mkplatformfs (The Void Linux filesystem tool to produce a rootfs for a particular platform) + * mkrootfs (The Void Linux rootfs maker for ARM platforms) + * mknet (Script to generate netboot tarballs for Void) + +## Dependencies + * Compression type for the initramfs image + * liblz4 (for lz4, xz) (default) + * xbps>=0.45 + * qemu-user-static binaries (for mkrootfs) + * bash + +## Usage + +See the usage output: + + $ ./mklive.sh -h + $ ./mkrootfs.sh -h + $ ./mkimage.sh -h + +### Examples + +Build a native live image keyboard set to 'fr': + + # ./mklive.sh -k fr + +Build an i686 (on x86\_64) live image with some additional packages: + + # ./mklive.sh -a i686 -p 'vim rtorrent' + +Build an x86\_64 musl live image with packages stored in a local repository: + + # ./mklive.sh -a x86_64-musl -r /path/to/host/binpkgs + +See the usage output for more information :-) + +## Kernel Command-line Parameters + +`void-mklive`-based live images support several kernel command-line arguments +that can change the behavior of the live system: + +- `live.autologin` will skip the initial login screen on `tty1`. +- `live.user` will change the username of the non-root user from the default `anon`. The password remains `voidlinux`. +- `live.shell` sets the default shell for the non-root user in the live environment. +- `live.accessibility` enables accessibility features like the console screenreader `espeakup` in the live environment. +- `console` can be set to `ttyS0`, `hvc0`, or `hvsi0` to enable `agetty` on that serial console. +- `locale.LANG` will set the `LANG` environment variable. Defaults to `en_US.UTF-8`. +- `vconsole.keymap` will set the console keymap. Defaults to `us`. + +### Examples: + +- `live.autologin live.user=foo live.shell=/bin/bash` would create the user `foo` with the default shell `/bin/bash` on boot, and log them in automatically on `tty1` +- `live.shell=/bin/bash` would set the default shell for the `anon` user to `/bin/bash` +- `console=ttyS0 vconsole.keymap=cf` would enable `ttyS0` and set the keymap in the console to `cf` +- `locale.LANG=fr_CA.UTF-8` would set the live system's language to `fr_CA.UTF-8` + +--------------------------------------- + +Notes from Tracker-Friendly + +--------------------------------------- + +In include, populate include/var/cache/xbps with packages downloaded from base-system, and sign them as a repo. +Add include as -I in mklive to make the installer work. Also add -p "dialog". diff --git a/build-x86-images.sh b/build-x86-images.sh new file mode 100755 index 0000000..5d9a93b --- /dev/null +++ b/build-x86-images.sh @@ -0,0 +1,148 @@ +#!/bin/sh + +set -eu + +. ./lib.sh + +PROGNAME=$(basename "$0") +ARCH=$(uname -m) +IMAGES="base enlightenment xfce mate cinnamon gnome kde lxde lxqt" +TRIPLET= +REPO= +DATE=$(date -u +%Y%m%d) + +help() { + echo "$PROGNAME: [-a arch] [-b base|enlightenment|xfce|mate|cinnamon|gnome|kde|lxde|lxqt] [-d date] [-t arch-date-variant] [-r repo]" >&2 +} + +while getopts "a:b:d:t:hr:V" opt; do +case $opt in + a) ARCH="$OPTARG";; + b) IMAGES="$OPTARG";; + d) DATE="$OPTARG";; + h) help; exit 0;; + r) REPO="-r $OPTARG $REPO";; + t) TRIPLET="$OPTARG";; + V) version; exit 0;; + *) help; exit 1;; +esac +done +shift $((OPTIND - 1)) + +INCLUDEDIR=$(mktemp -d) +trap "cleanup" INT TERM + +cleanup() { + rm -r "$INCLUDEDIR" +} + +setup_pipewire() { + PKGS="$PKGS pipewire alsa-pipewire" + mkdir -p "$INCLUDEDIR"/etc/xdg/autostart + ln -s /usr/share/applications/pipewire.desktop "$INCLUDEDIR"/etc/xdg/autostart/ + mkdir -p "$INCLUDEDIR"/etc/pipewire/pipewire.conf.d + ln -s /usr/share/examples/wireplumber/10-wireplumber.conf "$INCLUDEDIR"/etc/pipewire/pipewire.conf.d/ + ln -s /usr/share/examples/pipewire/20-pipewire-pulse.conf "$INCLUDEDIR"/etc/pipewire/pipewire.conf.d/ + mkdir -p "$INCLUDEDIR"/etc/alsa/conf.d + ln -s /usr/share/alsa/alsa.conf.d/50-pipewire.conf "$INCLUDEDIR"/etc/alsa/conf.d + ln -s /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf "$INCLUDEDIR"/etc/alsa/conf.d +} + +build_variant() { + variant="$1" + shift + IMG=void-live-${ARCH}-${DATE}-${variant}.iso + GRUB_PKGS="grub-i386-efi grub-x86_64-efi" + A11Y_PKGS="espeakup void-live-audio brltty" + PKGS="dialog cryptsetup lvm2 mdadm void-docs-browse xtools-minimal xmirror $A11Y_PKGS $GRUB_PKGS" + XORG_PKGS="xorg-minimal xorg-input-drivers xorg-video-drivers setxkbmap xauth font-misc-misc terminus-font dejavu-fonts-ttf orca" + SERVICES="sshd" + + LIGHTDM_SESSION='' + + case $variant in + base) + SERVICES="$SERVICES dhcpcd wpa_supplicant acpid" + ;; + enlightenment) + PKGS="$PKGS $XORG_PKGS lightdm lightdm-gtk3-greeter enlightenment terminology udisks2 firefox" + SERVICES="$SERVICES acpid dhcpcd wpa_supplicant lightdm dbus polkitd" + LIGHTDM_SESSION=enlightenment + ;; + xfce) + PKGS="$PKGS $XORG_PKGS lightdm lightdm-gtk3-greeter xfce4 gnome-themes-standard gnome-keyring network-manager-applet gvfs-afc gvfs-mtp gvfs-smb udisks2 firefox xfce4-pulseaudio-plugin" + SERVICES="$SERVICES dbus elogind lightdm NetworkManager polkitd" + LIGHTDM_SESSION=xfce + ;; + mate) + PKGS="$PKGS $XORG_PKGS lightdm lightdm-gtk3-greeter mate mate-extra gnome-keyring network-manager-applet gvfs-afc gvfs-mtp gvfs-smb udisks2 firefox" + SERVICES="$SERVICES dbus elogind lightdm NetworkManager polkitd" + LIGHTDM_SESSION=mate + ;; + cinnamon) + PKGS="$PKGS $XORG_PKGS lightdm lightdm-gtk3-greeter cinnamon gnome-keyring colord gnome-terminal gvfs-afc gvfs-mtp gvfs-smb udisks2 firefox" + SERVICES="$SERVICES dbus elogind lightdm NetworkManager polkitd" + LIGHTDM_SESSION=cinnamon + ;; + gnome) + PKGS="$PKGS $XORG_PKGS gnome firefox" + SERVICES="$SERVICES dbus elogind gdm NetworkManager polkitd" + ;; + kde) + PKGS="$PKGS $XORG_PKGS kde5 konsole firefox dolphin" + SERVICES="$SERVICES dbus elogind NetworkManager sddm" + ;; + lxde) + PKGS="$PKGS $XORG_PKGS lxde lightdm lightdm-gtk3-greeter gvfs-afc gvfs-mtp gvfs-smb udisks2 firefox" + SERVICES="$SERVICES acpid dbus dhcpcd wpa_supplicant lightdm polkitd" + LIGHTDM_SESSION=LXDE + ;; + lxqt) + PKGS="$PKGS $XORG_PKGS lxqt sddm gvfs-afc gvfs-mtp gvfs-smb udisks2 firefox" + SERVICES="$SERVICES elogind dbus dhcpcd wpa_supplicant sddm polkitd" + ;; + *) + >&2 echo "Unknown variant $variant" + exit 1 + ;; + esac + + if [ -n "$LIGHTDM_SESSION" ]; then + mkdir -p "$INCLUDEDIR"/etc/lightdm + echo "$LIGHTDM_SESSION" > "$INCLUDEDIR"/etc/lightdm/.session + fi + + if [ "$variant" != base ]; then + setup_pipewire + fi + + ./mklive.sh -a "$ARCH" -o "$IMG" -p "$PKGS" -S "$SERVICES" -I "$INCLUDEDIR" ${REPO} "$@" +} + +if [ ! -x mklive.sh ]; then + echo mklive.sh not found >&2 + exit 1 +fi + +if [ -x installer.sh ]; then + MKLIVE_VERSION="$(PROGNAME='' version)" + installer=$(mktemp) + sed "s/@@MKLIVE_VERSION@@/${MKLIVE_VERSION}/" installer.sh > "$installer" + install -Dm755 "$installer" "$INCLUDEDIR"/usr/bin/void-installer + rm "$installer" +else + echo installer.sh not found >&2 + exit 1 +fi + +if [ -n "$TRIPLET" ]; then + VARIANT="${TRIPLET##*-}" + REST="${TRIPLET%-*}" + DATE="${REST##*-}" + ARCH="${REST%-*}" + build_variant "$VARIANT" "$@" +else + for image in $IMAGES; do + build_variant "$image" "$@" + done +fi diff --git a/data/issue b/data/issue new file mode 100644 index 0000000..c6b86b0 --- /dev/null +++ b/data/issue @@ -0,0 +1,28 @@ +############################################################################### + +Welcome to the Void Linux Live system. Two users are available to log in: + + - root:voidlinux + - anon:voidlinux + +The `anon` user additionally has `sudo(8)` permissions to run any command +without a password. + +To start the installation please type: + + # void-installer + +and follow the on-screen instructions. To install additional software make +sure to configure your network interface and then use: + + - xbps-install(1) to install/update packages + - xbps-query(1) to query for package info + +The Void Linux Handbook is also available for offline access in multiple +formats, and can be accessed with the `void-docs(1)` utility. + +Thanks for using Void Linux. + + https://www.voidlinux.org + +############################################################################### diff --git a/data/splash.png b/data/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e3a9a32c94567fa3521ab252fdf22227feb02b GIT binary patch literal 11858 zcmeHtbySp5xAzc&L8&Mm3Q9>1-AZ@2bTf2!h>9Q~-HbF0F?5&GEj4s^Nq2qE@ZN8I zcfD)9>s$A||J*;WYxxY%%s%Jrv-7w2Il+qZ64;N4AA>+3Y$-`mWe^C}9|S^Kc!&Xf z!!b0o0=#^&6cJIB5)q-aceFFJv^E8SXd`_h1teP)@xLhOWWQGX^%CEqOELA`w-9ct z7a@wTMjsdPCNv!5Cb3h~F@=AE{Q3oLhXsBwFUBeUM0t+3w6>PD@%qhNJid0D`{IG% zK>hmuoR5FAo*8VC6(=vrH0znet7zR9pWyq3pvDaeO`{w^nh+^>#JGTq%51xPoZCEf zEOSK`;~afSD~IIe0mi{`PPWq=O?XL079R9@1d;RmC5hr*re+5w?w$3-r&Os)G~swp zzHr7(C%nLpbr0c&T$L55W+|Aj2^v4@5;;g%=WI$ zVqB6nGUKQw$gk_*`$|-|8Y)#MD!t+>9^ZYTa{(Q&5YOVS8m}y11cd$S-P!SHM=$Na>8px3wTq|df7Abb#{ZBWFif4r z{&^wFr}X)AW(QKcvQ;&N(e4%RumyWk;+2FXGj>*Kpv_I1#~i$wo3zC5QZRy|`KAy@ z>JbVE)WWGu2z-E09s&X+&}O9zrUgXngIVLWB<@_ONHY~U5# z^VqaBrs__{_~|!pNjkRiI{5>tQpzx}8XcY8%@r3Xi3&e?Jhhm4hBWoF5Yg8mvJ&`@ zB-jN6itM=y4~87DPqAQ`nId-NzAE4wFc!JLDG&7_wMA?rM!XHD%qf1m$HK_z4Ngryd_s4G!$SfEWN{**>$T`Iu&`gk^FkNXtn-Er3u;!)mB$e zrYmi>IWd4ViOy2J1y) z!W`^N<&)^!6UMh&+|%j13U=e=&F*oANTxo1d;%fZGKO9y#1(7y5H<6}Nm7pvO{K4= zdCN~j=LY^U&pWq2MaT}XNWMD-uUKQ5Y0U{=va#`JtV7+?;NOwl zq(JMNyyJ^&P9N8f%wV;CdKUayo`SC^h{9V_t}}`7A)vgL`f0!t>vqel=``_72&D`h zjg*;%Zpz577LBoxnp-%VJz1@HUUkvvS#@O%r5^Fl&=R`sq}c8&1>X}0Yd87U3LX(a zl`OUBS|yE)jg6-+H`M3I9tzWif?6cczNOGLj4)3=Kt-9oSa;j9Yr5b%yt=_cFDX@( z(l^KQZww0y+uToYh3Tl}_6fg5lQIg&50dVYR`nBWtQ&C6hv!D5BSUBX#0l5T~5;a(u&px-d()mPr^~K6&%U?7sUvSkF%74W<64@TeZ8OX^^b=YfuEvKi>7L%!z73~SlNC7GvR@rN}^A_r{w#|K{B3K zkSWuc+ITNm4hI8p1kjF!k;x~Gwh7rJ z8aW0;;h%{%z|tz&fM3uJBtGI)QN&MYn=-@$9Ejg50O@KFbVr^Ey%eV0m&`haU9z7a zq67PJZC^D=7GF4Qe;m}x>vWBUhJyUEZPkE8{O3^-IAA$**-D^aAV8SSUQ(I`1GHX{ zRVJ!md&WTjj*;C;H(2z;Vs}YSP7Zz=7KDvGKltF0*zc!u3JMH@BpN2X8Hrt?OTjh# zcl9bZ_3YpH6$zvu6kW^^&Zw+Fim$W@$>) z^|z>*LwR2@zjE-i6b8(pxKz1V&2L|gjt#rK_oHZ@hhH*mt7+-x1Chz&fk#j8V07np z=`1I1SkQ3`7x|yXaoi(Jq;cW}5D1}Wf|X9rP7CTYb#f!1hysO1SZQe~&($QCpL;pr zK`@V__57N`3C{Q26GC}j&E9(taBYyb@LDm7oh(gVLMBL_Tp*vo_u|v#)m2zZ!2I60 z8kc@{HbWfD(J&j8Cm?HXjjV{QZk_q>P#Zcl3=I&Y=)!|g5 zHld|6{KeCbsR+F)^|9{-tG)YgRyl=y&uji(^m*46MlLHj|;Yt&yMAK)p%+)?>GQ{J7E1J0g_=*yV&EYV*O17jY>%=pD-rm0Z=^ zvFrLnN6p@X`R3)fXxk_0$wFCMQ&zPz#aZWxKx87nJ6N8&oKSc51&l@*{r2oB;rI4Y z?>a5!yGzquciW(%wek|z^s1Rsv0lVG6>aULRll@-6V3U?^?Kf#JxV^IdoB41p)McP zB!zQr3f=AsRrrnj>I_;K?tYj(-JDjfhpF3EPY(;p*tx-*j^p*qR&J8~$qwG&fe6~$ zx;}@K@@Bk%+}%|NdhvQ5pEnB@2Q?l2sGF|05z1T)Fx>U_$W2n4rR)UAuv)A?qGHJ2X=r=aao$W~Z`o~*2Iro#;E~j9_quI{ zK;S?4`aR>nF{GI}J1SoNUBj$NGw&RsnjKCo%PI$WXAJ;Xa0{R;Y9N7mmK@Sh5=$7G^m; zGOenu2a7s9)*uo@n-@}c)wN+bf)T!;ogE!dI)`N zQj*oRXYX44=KgIfkjYJ#QP3&<-O5+udSi5yoaOIym@ubRT9dJp($cEhxW4Gx#(#S7 z9#A(82@YV&*RRr+_!*mQcP~;W0Y(@($RNu4ZcrKP>$?cipNv45fK?Z0R5C!qd_Qo%c_a3v{YwK09x!i%%CEx<*!3RyHFwa% zl{De2P2TD3(<)aWuY-9}%N@(8gPgDNputGry|bK@;OvgR==4F0^FrOthnFh=cn7AV zlUu>=#EeORPp~nm&)WOoFiY=IXRKp^pDqCWx}@$7x3u`j!S!r+0$(*bLmLF) z#BCwzxx)#=2?4hFX(XKrbd z=6a`YsXO-I&IO=WD9Y7db*--i@I@r^_tVP;N6!@A>kdQCmn=a*?ZZ;tqk;I?pg*&y zIN4*x*yKSKSQY7a*WCz_j77;3^mrShT9t9Rbo+MZxrNM?>)(;X z%HCLlKCrEg9$bSwB1oYP#pxT^zl9W5lVE-~_cY*0UAg z&s2cqVS-2s3i_JlKoncQe)US!Y;LLiLWV#To@U*n?$E~zORN<5x9C_skH-{nb| zc0}vqA6eSIucg7zyYuy=umR%A93WDc8Uidx>e*K71Q?a;_3M3jE~biMrm=W47csLzzifa>V6nqob-eO}=0f zjGE6Wp`aS)Pfw&nwFeC#@fal2HsCuXOrhlZ*(aRSpa-X>BgKJuTYoebF$VCdKjYe; zvEl5S`qS+m+{7dDCNUWT2Y;Y4ro6~nagTl4$7v=|x=|=^tuR;aH$LZB1b7-Ot3ot! zG7+d3Ry`xi;X{deZ#!t%1=)&=PnpOB+*JXLnHF>8ar{f7(zDgd6rC+pQvoP3;tDl0 zmV+XkNgOrD z&7^PMr_};WqQ}7pU?+8apFtcegvfGlOtbfA_PQ1j9(DF=)OyvKRg!3Sqps6#{q;$T zXMO?*Y|OnxDdKK>*@|z>Y?4S`RyJ?ZAdsnki;W7QqN$vhGE558PEIW#CN@2E?2o8N zi19r8A#W-~)HfRE<7_T=0dCt#58uDvp(Ck&zPUXGJ*&=omwuhRy7DjLUu+*jm^6Hq zns9bX|F%-iGR{r`c-e`q(@k1RZb;Tb96$p+79fJFK@uuJsymOJ(r!~XD26t=3K>0XUuq69SMRn9Tx!eZJ8?jeiWu9vmObKOHAh5K+K-a z7u8j|#7(aO7I0j7)nu0caOQM}vwvWKxHRst#}S7V(72|Kr+mvdm(QIahy`s^2b*Sn z24|D>1?J198_RN(^)CiA-j&aRI|uUW8>hcj;^PxML=H;g8VQZx2|v+XZ}ii@xq@2_ zv2FX2RCzj7-k$E=A=tJBhTMODb6Htg&C4tM7KjN1F$8{Lfg)@=^sLAYTGBDn487?c zv|7Dfsl~J&yHvZJArLYTuC(J;e5Oe+=Zrl=uo+=+kY&Jq{sI^ZvTN zq8S+7L@k_`gyVT2&vAH!5B>8%YGjavSINgeq!(4;P0s~u)KU0SD*geq%ciP+)qe5 z=V5|&esjS}-DGzaAD{J31Jm4#@HcsQt0Y@0?_fV^|ODhKC+y2#3A~&wPV2i;&PRqmcC^7RtX3p zbz?3a#deNHfA`2v+yzjPM)X)1O%L)cHH454dfB_R%CbPWS-WJM>FT5YsjNa!xJoecO z^d{d(=>aA_Qn%0izqZLyo2-dY#*gb4$Ee~6(dE-=HyPGOLP*HimNy+DBCbF{K~wTD zelXN4-i(TsYF&l5IVN?bTDFnEG0(i~n+pIVfmOeP+d~zS`(=|oaDNIdnA3Q8y-YM4 zFfy45W$vm;VRC(j3>Lo@*{MKODkI_poy%*51AZ9coqa8dq@2s-E$nD|c{oVi%Lu~e zK_kRYCh{L(r{U|K4v020TR1*DV~CXOyJ=c7(MNg-y)O>L^lY0w*{Loa+u5qi}L7T0YN|w_0Ny;mzJBG;sfiV zt&d!z=6NUGhr3)%O%ok3?41o_Qt$nQkZT33Z3|6=6Y>n%f9h?C%E`?M3tLPv2!Fc0 zVYj#Le;-iVf?7j5*KXhA#gESrFyZ3jO#2EE5fiex+5{A~%-r#Ww2#fr4WQg_?i-Ok z#ZQ{n8PE>@wB?mg+X_*_eyv~{2m@gI6N&`@-=MW9?w1>u(|c4j;R#;MCY~KL^Fq8F z9PRh6i@NV!i;dHwk>()=bO&tCB7m|HE^wDry4~B=lW@c#tKa~oMGE_QYTDJfM#3fD zH)=T`n_f7V1H@pOK?@_J-xDW^`}q5#)Ihxjm{0-{+JGMS$c!}eAeXCnz1vRJ?ro{t zx}NcP)glbrF}HSI5G3*s4L*M)M_d|iU|L!Vo~m+5#<<)$Q{DgoYvXZ2e5kIzi%lgE z@5q;=00@Ns?k&HSILK_poJ1g(OV6v-^{Qiz%qvV!-%u(YpxPl?5k^X{@-x=Or}seG z*x(VkZVcjJ<2FjZF*0!%)uEV_2Bigpa|i4xk*1~Hk>rUV(GD6P%ayyk^$TZL(McKz_NeS!pglc@IZOxk$MLY%^&V}IjaN$%|1D2xYB1*VP; z$(P5qlx;hNUVilqx{uqIMizbFTufHXbd2M$AXYMUH$RK=<>s$C&O-Igl}sZ; zq`!x1%1B5A0X<9qH`rCqB&Ff1)hb7vOr>pozWcir7T(VMmZt%wk*qfh(?TU}+CuIl zn5&NUYu;o);|M4_{v+9iRi6?ah~Y^+R_`xw>(f@K+DgYHmk!xOS5T1K&c(e|Euzt3 zES&>jE79|Q^+X~-Zs&n-CHmZ>SPQrZ*}&8FK5*aDKZESg6H9koBSc?&o=f0D&SVho z?Q)cOik2SvPa&Io+v_a=>hW(!v+oKe_`oM%+do~=#^&U;slmJ%Ngv@De(YlFE&|4oe7or>hU^OuFQfL8RXZefpK*-EbK3b zh34-DJul~>RilL(#X6RK+Qf4f3-?P_x=>iFzq9JN+C^=@a9lOjwDR?;-W$6)o3jfp z|DbDL?|e7DH$Fh%s%_O#u%(e-@jJA)IsM=V(9UQNKtqO`Cq#$5399BW7?X}|?FGkQ z$f*A8fyUI$mTmj8!!jaXlG@pR@BQq}mwK0#mZ!b_XHyY+1u^*GTi%V$4FK(ZM3ol@ zee^cgMSF~&bilT@aQ!T`WP`NXYtU`%d`R49M<5aJz*(eenP0`oNYjwtZS z)eS7afYnUEJbBO&z_sm

`L}mi8Cl+ttb%dP4n9JZ3`PED;M#n|EtfrC1LQ5V+AZ z2+2GUd*E2Rw$|tZ0Q;$v9wwjlf_bIobn)K5$rL^(+^i~Pn`R!PNe=*PZ(N=E>WjsS)t#K`RGQroXPfIK zO@5_m<#k;6=6lO5q@f`bzk1ex$*>is)hoQ`FVCK`a1V123HL}?--5u0<*GGh(v3j_ znw~iVi~^Upjq@5TgrjoM1}UIfpvDFlrOPKc^{sM$S6m#<#6fO73cfoHy}XKE7I3Ma zcd0-8wAMgTRv8>GgoaM}!^BgeicZtCBRbBJTeY+pafotWb$jc3vvLcSjM`Ekw;XXv zR#n%^$%uM=!REcUJ)Q!bK>%&A0Zydzx#=7(hM$!kz{13f*86Ae9DgD`wDx$%ZaAX= z(Utm_)kq-Vll2Rrf^eJ9&q_LqM3cCcDJ+_-5Fe`?d;AjU)F)E`=R|+m&-~{22*boV zfS$dqiFm6>>(=&`3i7POi?Oy@%xl`*R^`1z0P8jo>w&IWLq`BAB`9D8JO#EG)oSVC zkcnaf&0F3T-%K?_g!tz7_OEX0E;|asw2^agV%a}BAQxVEw#7GRr2Y`Soc#_KYfYGZ zF{}uLR88$7@=D_kjDYEULkv@ zjn<@q3q_4DOzLGKmJhtte3m^qL*-^XJBtppuR^s)N<}&+SO7dgU5(&Upd|-yJDGiv zp^vG|iwQGEQ@GxF$k3-b*J4*-y>0EPnNfdTOEzUEjC`B zX#1#-Be;Kw!ifZKr;d*6@B76wI*NMZpZ_@&YD~g5$$Xgdz4sU3*=g7DG?O4;s}nNb z+=b~?lVZwE^7-@USjg7ym8IuR-co6T!#2>i> z8tCWxI!PW()dSJZ(44`no@%O#`Ge|^=+{)m? zoozKGo7f@T&kg;tYwGV^YM+JIh)-Wlx^vnW#|KJCh`Y>d?2W9fP>Ue@kb7^4LwX|D zRBb)d-yo8gWYuiNN*g?UPoN9R6i;b^gGL)4lLDL_ftC`$&|7MWEqB%QPWU~p1!W4y zfi7`5r3Bz@?3~;gU9{#tJ9q(mt_lmKt)0iM&3CUvP=N*3AQ_X2c(QVzK6?64a8J4Js`PN-QV-vjXpv{S0V)~)Gnz9kp^*L8k@D@E+*fpdDG0n|0EMZX^G>Edpx|~IS z!IXKFmET=}YZ@#8Jfb3R8u|OVN)maZL96s*gj$|$Z!Eo*`kVMpMjq0hcYU!80&;YJFv={xu{{oxZ+7SS6iROgzV$#J7@5Hz%aBviU5l z8fZ!W&dL={s%*yZRv%KIL2A?1@W`V1xiz?k_^Fn8Yhp%M;X!X2NWXsxGt@Ce3*0kAx zzseC;p>hdKl*mJCU4Y~@9$<^Yo2wVFyK@f5D}Jf7a8;gV|PjS$1dyLGg4 zmZl!`(D%f0{c!j-H!pcVNHVI2i&3S2tl-_1$v#h~0)P6xrsVQXE3w5U`<5CT9gkkW zPL<;1(Wf5zF10DKYiEk54}mN}DFv%FOr=LKm5vRPejl*1a{iE>&Kl;1od?erSu8G< zIrK8uAfU@F6i)nd(bLr(#ntO3g_iOV{XWW!&3S&2j%O@6!O9o`P9tS4dGXb$@e#-F zk}6csi77}&Omyye?s$Q|ERot5>A~(FozUV6ENBCfpa7mXdh-1%m6g{~jkX?79}DuL#hi|(M^l_`wR}L7_g6z!z;i@w8hJ0T zZTpWE?nUo^q~dY%IJT%*NxLq>P_t!aAy501RO#%O*;f?6O80MTXKmGV_2Em|M;@l3 z=^2aPc!`rnkAElsgSp?2RM+x7kBEWn7}L6FK#B29%zSKowAgt1lunS;j1nnn0*SdY zN43HtHF-Tcn2fH1Xn#J<|PfxSE+^aU0PundiRctVoA- zamy4>swcX?U-9vaL2QruIBfxUgxwQ;YM`P2b*gUcI5{xo01c1?i-f0`;u8d;((NZ@ z9*>}f2Tvb;;rKIEgwT~>ALHt|zc13a($o9rcdrI*bAx8uyCzoeCII2R#S|ZN+A7qp zqA&vGhyK345*6ej{)B{;XI;-$K@1qKcxw>NckP3(}8Ma&q&ew?=r2M%F=A!&V zUaHYk3F$Nmf93au&j`X<^(lh~JMa^+Af86jDpbqFyIUH2!Djv8{bdJ8!?91#%E>LT zmkJ&}DqrcAjh|kR?Oc!SO@3>hwEcTdB|*}Hlea*V8fIZ49;v7~5^eZJf`)yFtMHb} z#v19;puS4r+`8<@DJCwqm|eeaMzER`Cn&{|>CK9wv~-BFuARUa(ugyZES3b-^d3*vt_1VS46e^#Zt!X0kkSnq+OCr3W;14v3tUbOgw!KeQN DZrWuS literal 0 HcmV?d00001 diff --git a/dracut/autoinstaller/autoinstall.cfg b/dracut/autoinstaller/autoinstall.cfg new file mode 100644 index 0000000..0951417 --- /dev/null +++ b/dracut/autoinstaller/autoinstall.cfg @@ -0,0 +1,76 @@ +#!/bin/sh +# Void Linux Automatic Install Configuration + +# === +# Disk Configuration +# === +# disk: the disk to install to +# default: the first disk that isn't the installer +#disk=/dev/hda + +# bootpartitionsize: controls how large the boot partition will be +# default: 500M +#bootpartitionsize=500M + +# swapsize: how large should the swap partition be +# default: equal to the installed physical memory +#swapsize= + +# === +# XBPS Configuration +# === +# xbpsrepository: which repo should the install pull from +# default: https://repo-default.voidlinux.org/current +#xbpsrepository="https://repo-default.voidlinux.org/current" + +# pkgs: additional packages to install into the target +# default: none +#pkgs="" + +# === +# Default User +# === +# username: the username of the user to be created +# default: voidlinux +#username="" + +# password: password to set for the new user +# default: unset (will prompt during install) +# Warning: This does not work in musl! +#password="" + +# === +# Misc. Options +# === +# timezone: Timezone in TZ format +# default: America/Chicago +#timezone="America/Chicago" + +# keymap: Keymap to use by default +# default: us +#keymap="us" + +# locale: initial glibc locale +# default: en_US.UTF-8 +#libclocale=en.US.UTF-8 + +# hostname: static hostname for the system +# default: derived from DNS +#hostname=VoidLinux + +# end_action: what to do at the end of the install +# default: shutdown +# alternate values: reboot, script, func +#end_action=shutdown + +# end_script: script to optionally run at end of install +# the user script must reside somewhere xbps-uhelper fetch +# can retrieve it from +# default: not set +#end_script="" + +# end_function: a function to optionally be run at +# the end of the install. +#end_function() { +# +#} diff --git a/dracut/autoinstaller/install.sh b/dracut/autoinstaller/install.sh new file mode 100755 index 0000000..1226420 --- /dev/null +++ b/dracut/autoinstaller/install.sh @@ -0,0 +1,300 @@ +#!/bin/sh + +type getargbool >/dev/null 2>&1 || . /lib/dracut-lib.sh + +# These functions pulled from void's excellent mklive.sh +VAI_info_msg() { + printf "\033[1m%s\n\033[m" "$@" +} + +VAI_print_step() { + CURRENT_STEP=$((CURRENT_STEP+1)) + VAI_info_msg "[${CURRENT_STEP}/${STEP_COUNT}] $*" +} + +# ----------------------- Install Functions ------------------------ + +VAI_welcome() { + clear + printf "=============================================================\n" + printf "================ Void Linux Auto-Installer ==================\n" + printf "=============================================================\n" +} + +VAI_get_address() { + mkdir -p /var/lib/dhclient + + # This will fork, but it means that over a slow link the DHCP + # lease will still be maintained. It also doesn't have a + # hard-coded privsep user in it like dhcpcd. + dhclient +} + +VAI_partition_disk() { + # Paritition Disk + sfdisk "${disk}" < "${target}/etc/sudoers.d/00-wheel" + chmod 0440 "${target}/etc/sudoers.d/00-wheel" +} + +VAI_correct_root_permissions() { + chroot "${target}" chown root:root / + chroot "${target}" chmod 755 / +} + +VAI_configure_hostname() { + # Set the hostname + echo "${hostname}" > "${target}/etc/hostname" +} + +VAI_configure_rc_conf() { + # Set the value of various tokens + sed -i "s:Europe/Madrid:${timezone}:" "${target}/etc/rc.conf" + sed -i "s:\"es\":\"${keymap}\":" "${target}/etc/rc.conf" + + # Activate various tokens + sed -i "s:#HARDWARECLOCK:HARDWARECLOCK:" "${target}/etc/rc.conf" + sed -i "s:#TIMEZONE:TIMEZONE:" "${target}/etc/rc.conf" + sed -i "s:#KEYMAP:KEYMAP:" "${target}/etc/rc.conf" +} + +VAI_add_user() { + chroot "${target}" useradd -m -s /bin/bash -U -G wheel,users,audio,video,cdrom,input "${username}" + if [ -z "${password}" ] ; then + chroot "${target}" passwd "${username}" + else + # For reasons that remain unclear, this does not work in musl + echo "${username}:${password}" | chpasswd -c SHA512 -R "${target}" +fi +} + +VAI_configure_grub() { + # Set hostonly + echo "hostonly=yes" > "${target}/etc/dracut.conf.d/hostonly.conf" + + # Choose the newest kernel + kernel_version="$(chroot "${target}" xbps-query linux | awk -F "[-_]" '/pkgver/ {print $2}')" + + # Install grub + chroot "${target}" grub-install "${disk}" + chroot "${target}" xbps-reconfigure -f "linux${kernel_version}" + + # Correct the grub install + chroot "${target}" update-grub +} + +VAI_configure_fstab() { + # Grab UUIDs + uuid1="$(blkid -s UUID -o value "${disk}1")" + uuid2="$(blkid -s UUID -o value "${disk}2")" + uuid3="$(blkid -s UUID -o value "${disk}3")" + + # Installl UUIDs into /etc/fstab + echo "UUID=$uuid3 / ext4 defaults,errors=remount-ro 0 1" >> "${target}/etc/fstab" + echo "UUID=$uuid1 /boot ext4 defaults 0 2" >> "${target}/etc/fstab" + if [ "${swapsize}" -ne 0 ] ; then + echo "UUID=$uuid2 swap swap defaults 0 0" >> "${target}/etc/fstab" + fi +} + +VAI_configure_locale() { + # Set the libc-locale iff glibc + case "${XBPS_ARCH}" in + *-musl) + VAI_info_msg "Glibc locales are not supported on musl" + ;; + *) + sed -i "/${libclocale}/s/#//" "${target}/etc/default/libc-locales" + + chroot "${target}" xbps-reconfigure -f glibc-locales + ;; + esac +} + +VAI_end_action() { + case $end_action in + reboot) + VAI_info_msg "Rebooting the system" + sync + umount -R "${target}" + reboot -f + ;; + shutdown) + VAI_info_msg "Shutting down the system" + sync + umount -R "${target}" + poweroff -f + ;; + script) + VAI_info_msg "Running user provided script" + xbps-uhelper fetch "${end_script}>/script" + chmod +x /script + target=${target} xbpsrepository=${xbpsrepository} /script + ;; + func) + VAI_info_msg "Running user provided function" + end_function + ;; + esac +} + +VAI_configure_autoinstall() { + # -------------------------- Setup defaults --------------------------- + bootpartitionsize="500M" + disk="$(lsblk -ipo NAME,TYPE,MOUNTPOINT | awk '{if ($2=="disk") {disks[$1]=0; last=$1} if ($3=="/") {disks[last]++}} END {for (a in disks) {if(disks[a] == 0){print a; break}}}')" + hostname="$(ip -4 -o -r a | awk -F'[ ./]' '{x=$7} END {print x}')" + # XXX: Set a manual swapsize here if the default doesn't fit your use case + swapsize="$(awk -F"\n" '/MemTotal/ {split($0, b, " "); print b[2] }' /proc/meminfo)"; + target="/mnt" + timezone="America/Chicago" + keymap="us" + libclocale="en_US.UTF-8" + username="voidlinux" + end_action="shutdown" + end_script="/bin/true" + + XBPS_ARCH="$(xbps-uhelper arch)" + case $XBPS_ARCH in + *-musl) + xbpsrepository="https://repo-default.voidlinux.org/current/musl" + ;; + *) + xbpsrepository="https://repo-default.voidlinux.org/current" + ;; + esac + + # --------------- Pull config URL out of kernel cmdline ------------------------- + set +e + if getargbool 0 autourl ; then + set -e + xbps-uhelper fetch "$(getarg autourl)>/etc/autoinstall.cfg" + + else + set -e + mv /etc/autoinstall.default /etc/autoinstall.cfg + fi + + # Read in the resulting config file which we got via some method + if [ -f /etc/autoinstall.cfg ] ; then + VAI_info_msg "Reading configuration file" + . ./etc/autoinstall.cfg + fi + + # Bail out if we didn't get a usable disk + if [ -z "$disk" ] ; then + die "No valid disk!" + fi +} + +VAI_main() { + CURRENT_STEP=0 + STEP_COUNT=16 + + VAI_welcome + + VAI_print_step "Bring up the network" + VAI_get_address + + VAI_print_step "Configuring installer" + VAI_configure_autoinstall + + VAI_print_step "Configuring disk using scheme 'Atomic'" + VAI_partition_disk + VAI_format_disk + + VAI_print_step "Mounting the target filesystems" + VAI_mount_target + + VAI_print_step "Installing XBPS keys" + VAI_install_xbps_keys + + VAI_print_step "Installing the base system" + VAI_install_base_system + + VAI_print_step "Granting sudo to default user" + VAI_configure_sudo + + VAI_print_step "Setting hostname" + VAI_configure_hostname + + VAI_print_step "Configure rc.conf" + VAI_configure_rc_conf + + VAI_print_step "Preparing the chroot" + VAI_prepare_chroot + + VAI_print_step "Fix ownership of /" + VAI_correct_root_permissions + + VAI_print_step "Adding default user" + VAI_add_user + + VAI_print_step "Configuring GRUB" + VAI_configure_grub + + VAI_print_step "Configuring /etc/fstab" + VAI_configure_fstab + + VAI_print_step "Configuring libc-locales" + VAI_configure_locale + + VAI_print_step "Performing end-action" + VAI_end_action +} + +# If we are using the autoinstaller, launch it +if getargbool 0 auto ; then + set -e + VAI_main + # Very important to release this before returning to dracut code + set +e +fi + diff --git a/dracut/autoinstaller/module-setup.sh b/dracut/autoinstaller/module-setup.sh new file mode 100644 index 0000000..b73568c --- /dev/null +++ b/dracut/autoinstaller/module-setup.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + return 255 +} + +depends() { + echo network +} + +install() { + inst /usr/bin/awk + inst /usr/bin/chmod + inst /usr/bin/chroot + inst /usr/bin/clear + inst /usr/bin/cp + inst /usr/bin/chpasswd + inst /usr/bin/dhclient + inst /usr/bin/dhclient-script + inst /usr/bin/halt + inst /usr/bin/install + inst /usr/bin/lsblk + inst /usr/bin/mkdir + inst /usr/bin/mkfs.ext4 + inst /usr/bin/mkswap + inst /usr/bin/mount + inst /usr/bin/resolvconf + inst /usr/bin/sfdisk + inst /usr/bin/sync + inst /usr/bin/xbps-install + inst /usr/bin/xbps-uhelper + inst /usr/bin/xbps-query + + inst_multiple /var/db/xbps/keys/* + inst_multiple /usr/share/xbps.d/* + + inst_multiple /etc/ssl/certs/* + inst /etc/ssl/certs.pem + + inst_hook pre-mount 01 "$moddir/install.sh" + inst "$moddir/autoinstall.cfg" /etc/autoinstall.default +} diff --git a/dracut/netmenu/module-setup.sh b/dracut/netmenu/module-setup.sh new file mode 100644 index 0000000..5ba5318 --- /dev/null +++ b/dracut/netmenu/module-setup.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + return 255 +} + +depends() { + echo network +} + +install() { + inst /usr/bin/awk + inst /usr/bin/basename + inst /usr/bin/bash + inst /usr/bin/cat + inst /usr/bin/cfdisk + inst /usr/bin/chroot + inst /usr/bin/clear + inst /usr/bin/cut + inst /usr/bin/cp + inst /usr/bin/dhcpcd + inst /usr/bin/dialog + inst /usr/bin/echo + inst /usr/bin/env + inst /usr/bin/find + inst /usr/bin/find + inst /usr/bin/grep + inst /usr/bin/head + inst /usr/bin/id + inst /usr/bin/ln + inst /usr/bin/ls + inst /usr/bin/lsblk + inst /usr/bin/mke2fs + inst /usr/bin/mkfs.btrfs + inst /usr/bin/mkfs.f2fs + inst /usr/bin/mkfs.vfat + inst /usr/bin/mkfs.xfs + inst /usr/bin/mkswap + inst /usr/bin/mktemp + inst /usr/bin/mount + inst /usr/bin/reboot + inst /usr/bin/rm + inst /usr/bin/sed + inst /usr/bin/sh + inst /usr/bin/sort + inst /usr/bin/sync + inst /usr/bin/stdbuf + inst /usr/bin/sleep + inst /usr/bin/touch + inst /usr/bin/xargs + inst /usr/bin/xbps-install + inst /usr/bin/xbps-reconfigure + inst /usr/bin/xbps-remove + inst /usr/bin/xbps-uhelper + + inst /usr/libexec/dhcpcd-hooks/20-resolv.conf + inst /usr/libexec/dhcpcd-run-hooks + inst /usr/libexec/coreutils/libstdbuf.so + + inst_multiple /var/db/xbps/keys/* + inst_multiple /usr/share/xbps.d/* + inst_multiple /usr/share/zoneinfo/*/* + + inst_multiple /etc/ssl/certs/* + inst /etc/ssl/certs.pem + + inst /etc/default/libc-locales + inst /etc/group + + # We need to remove a choice here since the installer's initrd + # can't function as a local source. Strictly we shouldn't be + # doing this from dracut's installation function, but this is the + # last place that file really exists 'on disk' in the sense that + # we can modify it, so this change is applied here. + sed -i '/Packages from ISO image/d' "$moddir/installer.sh" + + # The system doesn't have a real init up so the reboot is going to + # be rough, we make it an option though if the end user wants to + # do this... + sed -i "s:shutdown -r now:sync && reboot -f:" "$moddir/installer.sh" + + inst "$moddir/installer.sh" /usr/bin/void-installer + inst_hook pre-mount 05 "$moddir/netmenu.sh" +} diff --git a/dracut/netmenu/netmenu.sh b/dracut/netmenu/netmenu.sh new file mode 100755 index 0000000..a873b1c --- /dev/null +++ b/dracut/netmenu/netmenu.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +dialog --colors --keep-tite --no-shadow --no-mouse \ + --backtitle "\Zb\Z7Void Linux installation -- https://www.voidlinux.org\Zn" \ + --cancel-label "Reboot" --aspect 20 \ + --menu "Select an Action:" 10 50 2 \ + "Install" "Run void-installer" \ + "Shell" "Run dash" \ + 2>/tmp/netmenu.action + +if [ ! $? ] ; then + reboot -f +fi + +case $(cat /tmp/netmenu.action) in + "Install") /usr/bin/void-installer ; exec sh ;; + "Shell") exec sh ;; +esac diff --git a/dracut/vmklive/59-mtd.rules b/dracut/vmklive/59-mtd.rules new file mode 100644 index 0000000..d81a6ad --- /dev/null +++ b/dracut/vmklive/59-mtd.rules @@ -0,0 +1,8 @@ +SUBSYSTEM!="block", GOTO="ps_end" +ACTION!="add|change", GOTO="ps_end" +# Also don't process disks that are slated to be a multipath device +ENV{DM_MULTIPATH_DEVICE_PATH}=="?*", GOTO="ps_end" + +KERNEL=="mtdblock[0-9]*", IMPORT BLKID + +LABEL="ps_end" diff --git a/dracut/vmklive/61-mtd.rules b/dracut/vmklive/61-mtd.rules new file mode 100644 index 0000000..0711d3a --- /dev/null +++ b/dracut/vmklive/61-mtd.rules @@ -0,0 +1,20 @@ +SUBSYSTEM!="block", GOTO="pss_end" +ACTION!="add|change", GOTO="pss_end" +# Also don't process disks that are slated to be a multipath device +ENV{DM_MULTIPATH_DEVICE_PATH}=="?*", GOTO="pss_end" + +ACTION=="change", KERNEL=="dm-[0-9]*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="do_pss" +KERNEL=="mtdblock*", GOTO="do_pss" + +GOTO="pss_end" + +LABEL="do_pss" +# by-path (parent device path) +ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="", DEVPATH!="*/virtual/*", IMPORT PATH_ID +ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}" +ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n" + +# by-label/by-uuid links (filesystem metadata) +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" +ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" +LABEL="pss_end" diff --git a/dracut/vmklive/accessibility.sh b/dracut/vmklive/accessibility.sh new file mode 100644 index 0000000..8f231d9 --- /dev/null +++ b/dracut/vmklive/accessibility.sh @@ -0,0 +1,10 @@ +#!/bin/sh -x +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getargbool >/dev/null 2>&1 || . /lib/dracut-lib.sh + +if getargbool 0 live.accessibility; then + [ -d "${NEWROOT}/etc/sv/espeakup" ] && ln -s "/etc/sv/espeakup" "${NEWROOT}/etc/runit/runsvdir/current/" + [ -d "${NEWROOT}/etc/sv/brltty" ] && ln -s "/etc/sv/brltty" "${NEWROOT}/etc/runit/runsvdir/current/" +fi diff --git a/dracut/vmklive/adduser.sh b/dracut/vmklive/adduser.sh new file mode 100644 index 0000000..68d94b2 --- /dev/null +++ b/dracut/vmklive/adduser.sh @@ -0,0 +1,57 @@ +#!/bin/sh -x +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +if ! type getarg >/dev/null 2>&1 && ! type getargbool >/dev/null 2>&1; then + . /lib/dracut-lib.sh +fi + +echo void-live > ${NEWROOT}/etc/hostname + +USERNAME=$(getarg live.user) +USERSHELL=$(getarg live.shell) + +[ -z "$USERNAME" ] && USERNAME=anon +[ -x $NEWROOT/bin/bash -a -z "$USERSHELL" ] && USERSHELL=/bin/bash +[ -z "$USERSHELL" ] && USERSHELL=/bin/sh + +# Create /etc/default/live.conf to store USER. +echo "USERNAME=$USERNAME" >> ${NEWROOT}/etc/default/live.conf +chmod 644 ${NEWROOT}/etc/default/live.conf + +if ! grep -q ${USERSHELL} ${NEWROOT}/etc/shells ; then + echo ${USERSHELL} >> ${NEWROOT}/etc/shells +fi + +# Create new user and remove password. We'll use autologin by default. +chroot ${NEWROOT} useradd -m -c $USERNAME -G audio,video,wheel -s $USERSHELL $USERNAME +chroot ${NEWROOT} passwd -d $USERNAME >/dev/null 2>&1 + +# Setup default root/user password (voidlinux). +chroot ${NEWROOT} sh -c 'echo "root:voidlinux" | chpasswd -c SHA512' +chroot ${NEWROOT} sh -c "echo "$USERNAME:voidlinux" | chpasswd -c SHA512" + +# Enable sudo permission by default. +if [ -f ${NEWROOT}/etc/sudoers ]; then + echo "${USERNAME} ALL=(ALL:ALL) NOPASSWD: ALL" > "${NEWROOT}/etc/sudoers.d/99-void-live" +fi + +if [ -d ${NEWROOT}/etc/polkit-1 ]; then + # If polkit is installed allow users in the wheel group to run anything. + cat > ${NEWROOT}/etc/polkit-1/rules.d/void-live.rules <<_EOF +polkit.addAdminRule(function(action, subject) { + return ["unix-group:wheel"]; +}); + +polkit.addRule(function(action, subject) { + if (subject.isInGroup("wheel")) { + return polkit.Result.YES; + } +}); +_EOF + chroot ${NEWROOT} chown polkitd:polkitd /etc/polkit-1/rules.d/void-live.rules +fi + +if getargbool 0 live.autologin; then + sed -i "s,GETTY_ARGS=\"--noclear\",GETTY_ARGS=\"--noclear -a $USERNAME\",g" ${NEWROOT}/etc/sv/agetty-tty1/conf +fi diff --git a/dracut/vmklive/display-manager-autologin.sh b/dracut/vmklive/display-manager-autologin.sh new file mode 100644 index 0000000..60e5c5e --- /dev/null +++ b/dracut/vmklive/display-manager-autologin.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +USERNAME=$(getarg live.user) +[ -z "$USERNAME" ] && USERNAME=anon + +# Configure GDM autologin +if [ -d ${NEWROOT}/etc/gdm ]; then + GDMCustomFile=${NEWROOT}/etc/gdm/custom.conf + AutologinParameters="AutomaticLoginEnable=true\nAutomaticLogin=$USERNAME" + + # Prevent from updating if parameters already present (persistent usb key) + if ! `grep -qs 'AutomaticLoginEnable' $GDMCustomFile` ; then + if ! `grep -qs '\[daemon\]' $GDMCustomFile` ; then + echo '[daemon]' >> $GDMCustomFile + fi + sed -i "s/\[daemon\]/\[daemon\]\n$AutologinParameters/" $GDMCustomFile + fi +fi + +# Configure sddm autologin for the kde iso. +if [ -x ${NEWROOT}/usr/bin/sddm ]; then + cat > ${NEWROOT}/etc/sddm.conf <<_EOF +[Autologin] +User=${USERNAME} +Session=plasma.desktop +_EOF +fi + +# Configure lightdm autologin. +if [ -r "${NEWROOT}/etc/lightdm/lightdm.conf" ]; then + sed -i -e "s|^\#\(autologin-user=\).*|\1$USERNAME|" \ + "${NEWROOT}/etc/lightdm/lightdm.conf" + sed -i -e "s|^\#\(autologin-user-timeout=\).*|\10|" \ + "${NEWROOT}/etc/lightdm/lightdm.conf" + sed -i -e "s|^\#\(autologin-session=\).*|\1$(cat "${NEWROOT}/etc/lightdm/.session")|" \ + "${NEWROOT}/etc/lightdm/lightdm.conf" +fi + +# Configure lxdm autologin. +if [ -r ${NEWROOT}/etc/lxdm/lxdm.conf ]; then + sed -e "s,.*autologin.*=.*,autologin=$USERNAME," -i ${NEWROOT}/etc/lxdm/lxdm.conf + if [ -x ${NEWROOT}/usr/bin/enlightenment_start ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/enlightenment_start," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/startxfce4 ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/startxfce4," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/mate-session ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/mate-session," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/cinnamon-session ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/cinnamon-session," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/i3 ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/i3," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/startlxde ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/startlxde," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/startlxqt ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/startlxqt," -i ${NEWROOT}/etc/lxdm/lxdm.conf + elif [ -x ${NEWROOT}/usr/bin/startfluxbox ]; then + sed -e "s,.*session.*=.*,session=/usr/bin/startfluxbox," -i ${NEWROOT}/etc/lxdm/lxdm.conf + fi +fi diff --git a/dracut/vmklive/getty-serial.sh b/dracut/vmklive/getty-serial.sh new file mode 100644 index 0000000..6761f54 --- /dev/null +++ b/dracut/vmklive/getty-serial.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +CONSOLE=$(getarg console) +case "$CONSOLE" in +*ttyS0*) + ln -s /etc/sv/agetty-ttyS0 ${NEWROOT}/etc/runit/runsvdir/default/ + ;; +*hvc0*) + ln -s /etc/sv/agetty-hvc0 ${NEWROOT}/etc/runit/runsvdir/default/ + ;; +*hvsi0*) + ln -s /etc/sv/agetty-hvsi0 ${NEWROOT}/etc/runit/runsvdir/default/ + ;; +esac diff --git a/dracut/vmklive/locale.sh b/dracut/vmklive/locale.sh new file mode 100644 index 0000000..4ba1dd2 --- /dev/null +++ b/dracut/vmklive/locale.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +LOCALE=$(getarg locale.LANG) +[ -z "$LOCALE" ] && LOCALE="en_US.UTF-8" + +# also enable this locale in newroot. +echo "LANG=$LOCALE" > $NEWROOT/etc/locale.conf +echo "LC_COLLATE=C" >> $NEWROOT/etc/locale.conf + +# set keymap too. +KEYMAP=$(getarg vconsole.keymap) +[ -z "$KEYMAP" ] && KEYMAP="us" + +if [ -f ${NEWROOT}/etc/vconsole.conf ]; then + sed -e "s,^KEYMAP=.*,KEYMAP=$KEYMAP," -i $NEWROOT/etc/vconsole.conf +elif [ -f ${NEWROOT}/etc/rc.conf ]; then + sed -e "s,^#KEYMAP=.*,KEYMAP=$KEYMAP," -i $NEWROOT/etc/rc.conf +fi diff --git a/dracut/vmklive/module-setup.sh b/dracut/vmklive/module-setup.sh new file mode 100644 index 0000000..a95701d --- /dev/null +++ b/dracut/vmklive/module-setup.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + return 255 +} + +depends() { + echo dmsquash-live +} + +install() { + inst /usr/bin/chroot + inst /usr/bin/chmod + inst /usr/bin/sed + + if [ -e /usr/bin/memdiskfind ]; then + inst /usr/bin/memdiskfind + instmods mtdblock phram + inst_rules "$moddir/59-mtd.rules" "$moddir/61-mtd.rules" + prepare_udev_rules 59-mtd.rules 61-mtd.rules + inst_hook pre-udev 01 "$moddir/mtd.sh" + fi + + inst_hook pre-pivot 01 "$moddir/adduser.sh" + inst_hook pre-pivot 02 "$moddir/display-manager-autologin.sh" + inst_hook pre-pivot 02 "$moddir/getty-serial.sh" + inst_hook pre-pivot 03 "$moddir/locale.sh" + inst_hook pre-pivot 04 "$moddir/accessibility.sh" +} diff --git a/dracut/vmklive/mtd.sh b/dracut/vmklive/mtd.sh new file mode 100755 index 0000000..1d94a4e --- /dev/null +++ b/dracut/vmklive/mtd.sh @@ -0,0 +1,7 @@ +#!/bin/sh +MEMDISK=$(memdiskfind) +if [ "$MEMDISK" ]; then + modprobe phram phram=memdisk,$MEMDISK + modprobe mtdblock + printf 'KERNEL=="mtdblock0", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/dmsquash-live-root /dev/mtdblock0"\n' >> /etc/udev/rules.d/99-live-squash.rules +fi diff --git a/grub/grub.cfg b/grub/grub.cfg new file mode 100644 index 0000000..c5ab087 --- /dev/null +++ b/grub/grub.cfg @@ -0,0 +1,15 @@ +insmod usbms +insmod usb_keyboard +insmod part_gpt +insmod part_msdos +insmod fat +insmod iso9660 +insmod udf +insmod ext2 +insmod reiserfs +insmod ntfs +insmod hfsplus +insmod linux +insmod chain +search --file --no-floppy --set=voidlive "/boot/grub/grub_void.cfg" +source "(${voidlive})/boot/grub/grub_void.cfg" diff --git a/grub/grub_void.cfg.in b/grub/grub_void.cfg.in new file mode 100644 index 0000000..7d82de4 --- /dev/null +++ b/grub/grub_void.cfg.in @@ -0,0 +1,96 @@ + +set pager="1" +set locale_dir="(${voidlive})/boot/grub/locale" + +if [ -e "${prefix}/${grub_cpu}-${grub_platform}/all_video.mod" ]; then + insmod all_video +else + insmod efi_gop + insmod efi_uga + insmod video_bochs + insmod video_cirrus +fi + +insmod font + +if loadfont "(${voidlive})/boot/grub/fonts/unicode.pf2" ; then + insmod gfxterm + set gfxmode="auto" + + terminal_input console + terminal_output gfxterm + + insmod png + background_image "(${voidlive})/boot/isolinux/@@SPLASHIMAGE@@" +fi + +# Set default menu entry +default=linux +timeout=15 +timeout_style=menu + +# GRUB init tune for accessibility +play 600 988 1 1319 4 + +if [ cpuid -l ]; then + menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@)" --id "linux" { + set gfxpayload="keep" + linux (${voidlive})/boot/vmlinuz \ + root=live:CDLABEL=VOID_LIVE ro init=/sbin/init \ + rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \ + vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \ + locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ + initrd (${voidlive})/boot/initrd + } + menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) (RAM)" --id "linuxram" { + set gfxpayload="keep" + linux (${voidlive})/boot/vmlinuz \ + root=live:CDLABEL=VOID_LIVE ro init=/sbin/init \ + rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \ + vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \ + locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ rd.live.ram + initrd (${voidlive})/boot/initrd + } + menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) with speech" --hotkey s --id "linuxa11y" { + set gfxpayload="keep" + linux (${voidlive})/boot/vmlinuz \ + root=live:CDLABEL=VOID_LIVE ro init=/sbin/init \ + rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \ + vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \ + locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin + initrd (${voidlive})/boot/initrd + } + menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) with speech (RAM)" --hotkey r --id "linuxa11yram" { + set gfxpayload="keep" + linux (${voidlive})/boot/vmlinuz \ + root=live:CDLABEL=VOID_LIVE ro init=/sbin/init \ + rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \ + vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \ + locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin rd.live.ram + initrd (${voidlive})/boot/initrd + } + if [ "${grub_platform}" == "efi" ]; then + menuentry "Run Memtest86+ (RAM test)" --id memtest { + set gfxpayload="keep" + linux (${voidlive})/boot/memtest.efi + } + menuentry 'UEFI Firmware Settings' --id uefifw { + fwsetup + } + else + menuentry "Run Memtest86+ (RAM test)" --id memtest { + set gfxpayload="keep" + linux (${voidlive})/boot/memtest.bin + } + fi + + menuentry "System restart" --id restart { + echo "System rebooting..." + reboot + } + + menuentry "System shutdown" --id poweroff { + echo "System shutting down..." + halt + } +fi diff --git a/include-i686/home/anon/.bashrc b/include-i686/home/anon/.bashrc new file mode 100644 index 0000000..7864d0d --- /dev/null +++ b/include-i686/home/anon/.bashrc @@ -0,0 +1 @@ +sudo diff --git a/include-i686/home/anon/.profile b/include-i686/home/anon/.profile new file mode 100644 index 0000000..705963a --- /dev/null +++ b/include-i686/home/anon/.profile @@ -0,0 +1 @@ +bash diff --git a/include-i686/root/.bashrc b/include-i686/root/.bashrc new file mode 100644 index 0000000..fb9a43e --- /dev/null +++ b/include-i686/root/.bashrc @@ -0,0 +1 @@ +bash -c "evolution-installer" diff --git a/include-i686/root/.profile b/include-i686/root/.profile new file mode 100644 index 0000000..58b8a62 --- /dev/null +++ b/include-i686/root/.profile @@ -0,0 +1,2 @@ +evolution-installer +bash diff --git a/include-i686/usr/bin/evolution-installer b/include-i686/usr/bin/evolution-installer new file mode 100755 index 0000000..9c1aa2d --- /dev/null +++ b/include-i686/usr/bin/evolution-installer @@ -0,0 +1,1533 @@ +#!/bin/bash + +#- +# Copyright (c) 2012-2015 Juan Romero Pardines . +# 2012 Dave Elusive . +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +# Make sure we don't inherit these from env. +SOURCE_DONE= +HOSTNAME_DONE= +KEYBOARD_DONE= +LOCALE_DONE= +TIMEZONE_DONE= +ROOTPASSWORD_DONE= +USERLOGIN_DONE= +USERPASSWORD_DONE= +USERNAME_DONE= +USERGROUPS_DONE= +USERACCOUNT_DONE= +BOOTLOADER_DONE= +PARTITIONS_DONE= +NETWORK_DONE= +FILESYSTEMS_DONE= + +TARGETDIR=/mnt/target +LOG=/dev/tty8 +CONF_FILE=/tmp/.void-installer.conf +if [ ! -f $CONF_FILE ]; then + touch -f $CONF_FILE +fi +ANSWER=$(mktemp -t vinstall-XXXXXXXX || exit 1) +TARGET_FSTAB=$(mktemp -t vinstall-fstab-XXXXXXXX || exit 1) + +trap "DIE" INT TERM QUIT + +# disable printk +if [ -w /proc/sys/kernel/printk ]; then + echo 0 >/proc/sys/kernel/printk +fi + +# Detect if this is an EFI system. +if [ -e /sys/firmware/efi/systab ]; then + EFI_SYSTEM=1 + EFI_FW_BITS=$(cat /sys/firmware/efi/fw_platform_size) + if [ $EFI_FW_BITS -eq 32 ]; then + EFI_TARGET=i386-efi + else + EFI_TARGET=x86_64-efi + fi +fi + +# dialog colors +BLACK="\Z0" +RED="\Z1" +GREEN="\Z2" +YELLOW="\Z3" +BLUE="\Z4" +MAGENTA="\Z5" +CYAN="\Z6" +WHITE="\Z7" +BOLD="\Zb" +REVERSE="\Zr" +UNDERLINE="\Zu" +RESET="\Zn" + +# Properties shared per widget. +MENULABEL="${BOLD}Use UP and DOWN keys to navigate \ +menus. Use TAB to switch between buttons and ENTER to select.${RESET}" +MENUSIZE="14 60 0" +INPUTSIZE="8 60" +MSGBOXSIZE="8 70" +YESNOSIZE="$INPUTSIZE" +WIDGET_SIZE="10 70" + +DIALOG() { + rm -f $ANSWER + dialog --colors --keep-tite --no-shadow --no-mouse \ + --backtitle "${BOLD}${WHITE}EvolutionOS installation -- https://tracker-friendly.github.io" \ + --cancel-label "Back" --aspect 20 "$@" 2>$ANSWER + return $? +} + +INFOBOX() { + # Note: dialog --infobox and --keep-tite don't work together + dialog --colors --no-shadow --no-mouse \ + --backtitle "${BOLD}${WHITE}EvolutionOS installation -- https://tracker-friendly.github.io" \ + --title "${TITLE}" --aspect 20 --infobox "$@" +} + +DIE() { + rval=$1 + [ -z "$rval" ] && rval=0 + clear + rm -f $ANSWER $TARGET_FSTAB + # reenable printk + if [ -w /proc/sys/kernel/printk ]; then + echo 4 >/proc/sys/kernel/printk + fi + umount_filesystems + exit $rval +} + +set_option() { + if grep -Eq "^${1}.*" $CONF_FILE; then + sed -i -e "/^${1}.*/d" $CONF_FILE + fi + echo "${1} ${2}" >>$CONF_FILE +} + +get_option() { + echo $(grep -E "^${1}.*" $CONF_FILE|sed -e "s|${1}||") +} + +# ISO-639 language names for locales +iso639_language() { + case "$1" in + aa) echo "Afar" ;; + af) echo "Afrikaans" ;; + an) echo "Aragonese" ;; + ar) echo "Arabic" ;; + ast) echo "Asturian" ;; + be) echo "Belgian" ;; + bg) echo "Bulgarian" ;; + bhb) echo "Bhili" ;; + br) echo "Breton" ;; + bs) echo "Bosnian" ;; + ca) echo "Catalan" ;; + cs) echo "Czech" ;; + cy) echo "Welsh" ;; + da) echo "Danish" ;; + de) echo "German" ;; + el) echo "Greek" ;; + en) echo "English" ;; + es) echo "Spanish" ;; + et) echo "Estonian" ;; + eu) echo "Basque" ;; + fi) echo "Finnish" ;; + fo) echo "Faroese" ;; + fr) echo "French" ;; + ga) echo "Irish" ;; + gd) echo "Scottish Gaelic" ;; + gl) echo "Galician" ;; + gv) echo "Manx" ;; + he) echo "Hebrew" ;; + hr) echo "Croatian" ;; + hsb) echo "Upper Sorbian" ;; + hu) echo "Hungarian" ;; + id) echo "Indonesian" ;; + is) echo "Icelandic" ;; + it) echo "Italian" ;; + iw) echo "Hebrew" ;; + ja) echo "Japanese" ;; + ka) echo "Georgian" ;; + kk) echo "Kazakh" ;; + kl) echo "Kalaallisut" ;; + ko) echo "Korean" ;; + ku) echo "Kurdish" ;; + kw) echo "Cornish" ;; + lg) echo "Ganda" ;; + lt) echo "Lithuanian" ;; + lv) echo "Latvian" ;; + mg) echo "Malagasy" ;; + mi) echo "Maori" ;; + mk) echo "Macedonian" ;; + ms) echo "Malay" ;; + mt) echo "Maltese" ;; + nb) echo "Norwegian Bokmål" ;; + nl) echo "Dutch" ;; + nn) echo "Norwegian Nynorsk" ;; + oc) echo "Occitan" ;; + om) echo "Oromo" ;; + pl) echo "Polish" ;; + pt) echo "Portugese" ;; + ro) echo "Romanian" ;; + ru) echo "Russian" ;; + sk) echo "Slovak" ;; + sl) echo "Slovenian" ;; + so) echo "Somali" ;; + sq) echo "Albanian" ;; + st) echo "Southern Sotho" ;; + sv) echo "Swedish" ;; + tcy) echo "Tulu" ;; + tg) echo "Tajik" ;; + th) echo "Thai" ;; + tl) echo "Tagalog" ;; + tr) echo "Turkish" ;; + uk) echo "Ukrainian" ;; + uz) echo "Uzbek" ;; + wa) echo "Walloon" ;; + xh) echo "Xhosa" ;; + yi) echo "Yiddish" ;; + zh) echo "Chinese" ;; + zu) echo "Zulu" ;; + *) echo "$1" ;; + esac +} + +# ISO-3166 country codes for locales +iso3166_country() { + case "$1" in + AD) echo "Andorra" ;; + AE) echo "United Arab Emirates" ;; + AL) echo "Albania" ;; + AR) echo "Argentina" ;; + AT) echo "Austria" ;; + AU) echo "Australia" ;; + BA) echo "Bonsia and Herzegovina" ;; + BE) echo "Belgium" ;; + BG) echo "Bulgaria" ;; + BH) echo "Bahrain" ;; + BO) echo "Bolivia" ;; + BR) echo "Brazil" ;; + BW) echo "Botswana" ;; + BY) echo "Belarus" ;; + CA) echo "Canada" ;; + CH) echo "Switzerland" ;; + CL) echo "Chile" ;; + CN) echo "China" ;; + CO) echo "Colombia" ;; + CR) echo "Costa Rica" ;; + CY) echo "Cyprus" ;; + CZ) echo "Czech Republic" ;; + DE) echo "Germany" ;; + DJ) echo "Djibouti" ;; + DK) echo "Denmark" ;; + DO) echo "Dominican Republic" ;; + DZ) echo "Algeria" ;; + EC) echo "Ecuador" ;; + EE) echo "Estonia" ;; + EG) echo "Egypt" ;; + ES) echo "Spain" ;; + FI) echo "Finland" ;; + FO) echo "Faroe Islands" ;; + FR) echo "France" ;; + GB) echo "Great Britain" ;; + GE) echo "Georgia" ;; + GL) echo "Greenland" ;; + GR) echo "Greece" ;; + GT) echo "Guatemala" ;; + HK) echo "Hong Kong" ;; + HN) echo "Honduras" ;; + HR) echo "Croatia" ;; + HU) echo "Hungary" ;; + ID) echo "Indonesia" ;; + IE) echo "Ireland" ;; + IL) echo "Israel" ;; + IN) echo "India" ;; + IQ) echo "Iraq" ;; + IS) echo "Iceland" ;; + IT) echo "Italy" ;; + JO) echo "Jordan" ;; + JP) echo "Japan" ;; + KE) echo "Kenya" ;; + KR) echo "Korea, Republic of" ;; + KW) echo "Kuwait" ;; + KZ) echo "Kazakhstan" ;; + LB) echo "Lebanon" ;; + LT) echo "Lithuania" ;; + LU) echo "Luxembourg" ;; + LV) echo "Latvia" ;; + LY) echo "Libya" ;; + MA) echo "Morocco" ;; + MG) echo "Madagascar" ;; + MK) echo "Macedonia" ;; + MT) echo "Malta" ;; + MX) echo "Mexico" ;; + MY) echo "Malaysia" ;; + NI) echo "Nicaragua" ;; + NL) echo "Netherlands" ;; + NO) echo "Norway" ;; + NZ) echo "New Zealand" ;; + OM) echo "Oman" ;; + PA) echo "Panama" ;; + PE) echo "Peru" ;; + PH) echo "Philippines" ;; + PL) echo "Poland" ;; + PR) echo "Puerto Rico" ;; + PT) echo "Portugal" ;; + PY) echo "Paraguay" ;; + QA) echo "Qatar" ;; + RO) echo "Romania" ;; + RU) echo "Russian Federation" ;; + SA) echo "Saudi Arabia" ;; + SD) echo "Sudan" ;; + SE) echo "Sweden" ;; + SG) echo "Singapore" ;; + SI) echo "Slovenia" ;; + SK) echo "Slovakia" ;; + SO) echo "Somalia" ;; + SV) echo "El Salvador" ;; + SY) echo "Syria" ;; + TH) echo "Thailand" ;; + TJ) echo "Tajikistan" ;; + TN) echo "Tunisia" ;; + TR) echo "Turkey" ;; + TW) echo "Taiwan" ;; + UA) echo "Ukraine" ;; + UG) echo "Uganda" ;; + US) echo "United States of America" ;; + UY) echo "Uruguay" ;; + UZ) echo "Uzbekistan" ;; + VE) echo "Venezuela" ;; + YE) echo "Yemen" ;; + ZA) echo "South Africa" ;; + ZW) echo "Zimbabwe" ;; + *) echo "$1" ;; + esac +} + +show_disks() { + local dev size sectorsize gbytes + + # IDE + for dev in $(ls /sys/block|grep -E '^hd'); do + if [ "$(cat /sys/block/$dev/device/media)" = "disk" ]; then + # Find out nr sectors and bytes per sector; + echo "/dev/$dev" + size=$(cat /sys/block/$dev/size) + sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + fi + done + # SATA/SCSI and Virtual disks (virtio) + for dev in $(ls /sys/block|grep -E '^([sv]|xv)d|mmcblk|nvme'); do + echo "/dev/$dev" + size=$(cat /sys/block/$dev/size) + sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + done + # cciss(4) devices + for dev in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]$'); do + echo "/dev/cciss/$dev" + size=$(cat /sys/block/cciss\!$dev/size) + sectorsize=$(cat /sys/block/cciss\!$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + done +} + +get_partfs() { + # Get fs type from configuration if available. This ensures + # that the user is shown the proper fs type if they install the system. + local part="$1" + local default="${2:-none}" + local fstype=$(grep "MOUNTPOINT ${part}" "$CONF_FILE"|awk '{print $3}') + echo "${fstype:-$default}" +} + +show_partitions() { + local dev fstype fssize p part + + set -- $(show_disks) + while [ $# -ne 0 ]; do + disk=$(basename $1) + shift 2 + # ATA/SCSI/SATA + for p in /sys/block/$disk/$disk*; do + if [ -d $p ]; then + part=$(basename $p) + fstype=$(lsblk -nfr /dev/$part|awk '{print $2}'|head -1) + [ "$fstype" = "iso9660" ] && continue + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/$part|awk '{print $4}'|head -1) + echo "/dev/$part" + echo "size:${fssize:-unknown};fstype:$(get_partfs "/dev/$part")" + fi + done + done + # Device Mapper + for p in /dev/mapper/*; do + part=$(basename $p) + [ "${part}" = "live-rw" ] && continue + [ "${part}" = "live-base" ] && continue + [ "${part}" = "control" ] && continue + + fstype=$(lsblk -nfr $p|awk '{print $2}'|head -1) + fssize=$(lsblk -nr $p|awk '{print $4}'|head -1) + echo "${p}" + echo "size:${fssize:-unknown};fstype:$(get_partfs "$p")" + done + # Software raid (md) + for p in $(ls -d /dev/md* 2>/dev/null|grep '[0-9]'); do + part=$(basename $p) + if cat /proc/mdstat|grep -qw $part; then + fstype=$(lsblk -nfr /dev/$part|awk '{print $2}') + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/$part|awk '{print $4}') + echo "$p" + echo "size:${fssize:-unknown};fstype:$(get_partfs "$p")" + fi + done + # cciss(4) devices + for part in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]p[0-9]+'); do + fstype=$(lsblk -nfr /dev/cciss/$part|awk '{print $2}') + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/cciss/$part|awk '{print $4}') + echo "/dev/cciss/$part" + echo "size:${fssize:-unknown};fstype:$(get_partfs "/dev/cciss/$part")" + done + if [ -e /sbin/lvs ]; then + # LVM + lvs --noheadings|while read lvname vgname perms size; do + echo "/dev/mapper/${vgname}-${lvname}" + echo "size:${size};fstype:$(get_partfs "/dev/mapper/${vgname}-${lvname}" lvm)" + done + fi +} + +menu_filesystems() { + local dev fstype fssize mntpoint reformat + + while true; do + DIALOG --ok-label "Change" --cancel-label "Done" \ + --title " Select the partition to edit " --menu "$MENULABEL" \ + ${MENUSIZE} $(show_partitions) + [ $? -ne 0 ] && return + + dev=$(cat $ANSWER) + DIALOG --title " Select the filesystem type for $dev " \ + --menu "$MENULABEL" ${MENUSIZE} \ + "btrfs" "Oracle's Btrfs" \ + "ext2" "Linux ext2 (no journaling)" \ + "ext3" "Linux ext3 (journal)" \ + "ext4" "Linux ext4 (journal)" \ + "f2fs" "Flash-Friendly Filesystem" \ + "swap" "Linux swap" \ + "vfat" "FAT32" \ + "xfs" "SGI's XFS" + if [ $? -eq 0 ]; then + fstype=$(cat $ANSWER) + else + continue + fi + if [ "$fstype" != "swap" ]; then + DIALOG --inputbox "Please specify the mount point for $dev:" ${INPUTSIZE} + if [ $? -eq 0 ]; then + mntpoint=$(cat $ANSWER) + elif [ $? -eq 1 ]; then + continue + fi + else + mntpoint=swap + fi + DIALOG --yesno "Do you want to create a new filesystem on $dev?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + reformat=1 + elif [ $? -eq 1 ]; then + reformat=0 + else + continue + fi + fssize=$(lsblk -nr $dev|awk '{print $4}') + set -- "$fstype" "$fssize" "$mntpoint" "$reformat" + if [ -n "$1" -a -n "$2" -a -n "$3" -a -n "$4" ]; then + local bdev=$(basename $dev) + local ddev=$(basename $(dirname $dev)) + if [ "$ddev" != "dev" ]; then + sed -i -e "/^MOUNTPOINT \/dev\/${ddev}\/${bdev}.*/d" $CONF_FILE + else + sed -i -e "/^MOUNTPOINT \/dev\/${bdev}.*/d" $CONF_FILE + fi + echo "MOUNTPOINT $dev $1 $2 $3 $4" >>$CONF_FILE + fi + done + FILESYSTEMS_DONE=1 +} + +menu_partitions() { + DIALOG --title " Select the disk to partition " \ + --menu "$MENULABEL" ${MENUSIZE} $(show_disks) + if [ $? -eq 0 ]; then + local device=$(cat $ANSWER) + + DIALOG --title " Select the software for partitioning " \ + --menu "$MENULABEL" ${MENUSIZE} \ + "cfdisk" "Easy to use" \ + "fdisk" "More advanced" + if [ $? -eq 0 ]; then + local software=$(cat $ANSWER) + + DIALOG --title "Modify Partition Table on $device" --msgbox "\n +${BOLD}${software} will be executed in disk $device.${RESET}\n\n +For BIOS systems, MBR or GPT partition tables are supported.\n +To use GPT on PC BIOS systems an empty partition of 1MB must be added\n +at the first 2GB of the disk with the TOGGLE \`bios_grub' enabled.\n +${BOLD}NOTE: you don't need this on EFI systems.${RESET}\n\n +For EFI systems GPT is mandatory and a FAT32 partition with at least\n +100MB must be created with the TOGGLE \`boot', this will be used as\n +EFI System Partition. This partition must have mountpoint as \`/boot/efi'.\n\n +At least 1 partition is required for the rootfs (/).\n +For swap, RAM*2 must be really enough. For / 600MB are required.\n\n +${BOLD}WARNING: /usr is not supported as a separate partition.${RESET}\n +${RESET}\n" 18 80 + if [ $? -eq 0 ]; then + while true; do + clear; $software $device; PARTITIONS_DONE=1 + break + done + else + return + fi + fi + fi +} + +menu_keymap() { + local _keymaps="$(find /usr/share/kbd/keymaps/ -type f -iname "*.map.gz" -printf "%f\n" | sed 's|.map.gz||g' | sort)" + local _KEYMAPS= + + for f in ${_keymaps}; do + _KEYMAPS="${_KEYMAPS} ${f} -" + done + while true; do + DIALOG --title " Select your keymap " --menu "$MENULABEL" 14 70 14 ${_KEYMAPS} + if [ $? -eq 0 ]; then + set_option KEYMAP "$(cat $ANSWER)" + loadkeys "$(cat $ANSWER)" + KEYBOARD_DONE=1 + break + else + return + fi + done +} + +set_keymap() { + local KEYMAP=$(get_option KEYMAP) + + if [ -f /etc/vconsole.conf ]; then + sed -i -e "s|KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/vconsole.conf + else + sed -i -e "s|#\?KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/rc.conf + fi +} + +menu_locale() { + local _locales="$(grep -E '\.UTF-8' /etc/default/libc-locales|awk '{print $1}'|sed -e 's/^#//')" + local LOCALES ISO639 ISO3166 + local TMPFILE=$(mktemp -t vinstall-XXXXXXXX || exit 1) + INFOBOX "Scanning locales ..." 4 60 + for f in ${_locales}; do + eval $(echo $f | awk 'BEGIN { FS="." } \ + { FS="_"; split($1, a); printf "ISO639=%s ISO3166=%s\n", a[1], a[2] }') + echo "$f|$(iso639_language $ISO639) ($(iso3166_country $ISO3166))|" >> $TMPFILE + done + clear + # Sort by ISO-639 language names + LOCALES=$(sort -t '|' -k 2 < $TMPFILE | xargs | sed -e's/| /|/g') + rm -f $TMPFILE + while true; do + (IFS="|"; DIALOG --title " Select your locale " --menu "$MENULABEL" 18 70 18 ${LOCALES}) + if [ $? -eq 0 ]; then + set_option LOCALE "$(cat $ANSWER)" + LOCALE_DONE=1 + break + else + return + fi + done +} + +set_locale() { + if [ -f $TARGETDIR/etc/default/libc-locales ]; then + local LOCALE="$(get_option LOCALE)" + : "${LOCALE:=C.UTF-8}" + sed -i -e "s|LANG=.*|LANG=$LOCALE|g" $TARGETDIR/etc/locale.conf + # Uncomment locale from /etc/default/libc-locales and regenerate it. + sed -e "/${LOCALE}/s/^\#//" -i $TARGETDIR/etc/default/libc-locales + echo "Running xbps-reconfigure -f glibc-locales ..." >$LOG + chroot $TARGETDIR xbps-reconfigure -f glibc-locales >$LOG 2>&1 + fi +} + +menu_timezone() { + local areas=(Africa America Antarctica Arctic Asia Atlantic Australia Europe Indian Pacific) + + local area locations location + while (IFS='|'; DIALOG ${area:+--default-item|"$area"} --title " Select area " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${areas[@]}")); do + area=$(cat $ANSWER) + read -a locations -d '\n' < <(find /usr/share/zoneinfo/$area -type f -printf '%P\n' | sort) + if (IFS='|'; DIALOG --title " Select location (${area}) " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${locations[@]//_/ }")); then + location=$(tr ' ' '_' < $ANSWER) + set_option TIMEZONE "$area/$location" + TIMEZONE_DONE=1 + return 0 + else + continue + fi + done + return 1 +} + +set_timezone() { + local TIMEZONE="$(get_option TIMEZONE)" + + ln -sf "/usr/share/zoneinfo/${TIMEZONE}" "${TARGETDIR}/etc/localtime" +} + +menu_hostname() { + while true; do + DIALOG --inputbox "Set the machine hostname:" ${INPUTSIZE} + if [ $? -eq 0 ]; then + set_option HOSTNAME "$(cat $ANSWER)" + HOSTNAME_DONE=1 + break + else + return + fi + done +} + +set_hostname() { + local hostname="$(get_option HOSTNAME)" + echo "${hostname:-void}" > $TARGETDIR/etc/hostname +} + +menu_rootpassword() { + local _firstpass _secondpass _again _desc + + while true; do + if [ -z "${_firstpass}" ]; then + _desc="Enter the root password" + else + _again=" again" + fi + DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE} + if [ $? -eq 0 ]; then + if [ -z "${_firstpass}" ]; then + _firstpass="$(cat $ANSWER)" + else + _secondpass="$(cat $ANSWER)" + fi + if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then + if [ "${_firstpass}" != "${_secondpass}" ]; then + INFOBOX "Passwords do not match! Please enter again." 6 60 + unset _firstpass _secondpass _again + sleep 2 && clear && continue + fi + set_option ROOTPASSWORD "${_firstpass}" + ROOTPASSWORD_DONE=1 + break + fi + else + return + fi + done +} + +set_rootpassword() { + echo "root:$(get_option ROOTPASSWORD)" | chroot $TARGETDIR chpasswd -c SHA512 +} + +menu_useraccount() { + local _firstpass _secondpass _desc _again + local _groups _status _group _checklist + local _preset _userlogin + + while true; do + _preset=$(get_option USERLOGIN) + [ -z "$_preset" ] && _preset="evolution" + DIALOG --inputbox "Enter a primary login name:" ${INPUTSIZE} "$_preset" + if [ $? -eq 0 ]; then + _userlogin="$(cat $ANSWER)" + # based on useradd(8) § Caveats + if [ "${#_userlogin}" -le 32 ] && [[ "${_userlogin}" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then + set_option USERLOGIN "${_userlogin}" + USERLOGIN_DONE=1 + break + else + INFOBOX "Invalid login name! Please try again." 6 60 + unset _userlogin + sleep 2 && clear && continue + fi + else + return + fi + done + + while true; do + _preset=$(get_option USERNAME) + [ -z "$_preset" ] && _preset="Evolution User" + DIALOG --inputbox "Enter a display name for login '$(get_option USERLOGIN)' :" \ + ${INPUTSIZE} "$_preset" + if [ $? -eq 0 ]; then + set_option USERNAME "$(cat $ANSWER)" + USERNAME_DONE=1 + break + else + return + fi + done + + while true; do + if [ -z "${_firstpass}" ]; then + _desc="Enter the password for login '$(get_option USERLOGIN)'" + else + _again=" again" + fi + DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE} + if [ $? -eq 0 ]; then + if [ -z "${_firstpass}" ]; then + _firstpass="$(cat $ANSWER)" + else + _secondpass="$(cat $ANSWER)" + fi + if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then + if [ "${_firstpass}" != "${_secondpass}" ]; then + INFOBOX "Passwords do not match! Please enter again." 6 60 + unset _firstpass _secondpass _again + sleep 2 && clear && continue + fi + set_option USERPASSWORD "${_firstpass}" + USERPASSWORD_DONE=1 + break + fi + else + return + fi + done + + _groups="wheel,audio,video,floppy,cdrom,optical,kvm,xbuilder" + while true; do + _desc="Select group membership for login '$(get_option USERLOGIN)':" + for _group in $(cat /etc/group); do + _gid="$(echo ${_group} | cut -d: -f3)" + _group="$(echo ${_group} | cut -d: -f1)" + _status="$(echo ${_groups} | grep -w ${_group})" + if [ -z "${_status}" ]; then + _status=off + else + _status=on + fi + # ignore the groups of root, existing users, and package groups + if [[ "${_gid}" -ge 1000 || "${_group}" = "_"* || "${_group}" = "root" ]]; then + continue + fi + if [ -z "${_checklist}" ]; then + _checklist="${_group} ${_group}:${_gid} ${_status}" + else + _checklist="${_checklist} ${_group} ${_group}:${_gid} ${_status}" + fi + done + DIALOG --no-tags --checklist "${_desc}" 20 60 18 ${_checklist} + if [ $? -eq 0 ]; then + set_option USERGROUPS $(cat $ANSWER | sed -e's| |,|g') + USERGROUPS_DONE=1 + break + else + return + fi + done +} + +set_useraccount() { + [ -z "$USERACCOUNT_DONE" ] && return + chroot $TARGETDIR useradd -m -G "$(get_option USERGROUPS)" \ + -c "$(get_option USERNAME)" "$(get_option USERLOGIN)" + echo "$(get_option USERLOGIN):$(get_option USERPASSWORD)" | \ + chroot $TARGETDIR chpasswd -c SHA512 +} + +menu_bootloader() { + while true; do + DIALOG --title " Select the disk to install the bootloader" \ + --menu "$MENULABEL" ${MENUSIZE} $(show_disks) none "Manage bootloader otherwise" + if [ $? -eq 0 ]; then + set_option BOOTLOADER "$(cat $ANSWER)" + BOOTLOADER_DONE=1 + break + else + return + fi + done + while true; do + DIALOG --yesno "Use a graphical terminal for the boot loader?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + set_option TEXTCONSOLE 0 + break + elif [ $? -eq 1 ]; then + set_option TEXTCONSOLE 1 + break + else + return + fi + done +} + +set_bootloader() { + local dev=$(get_option BOOTLOADER) grub_args= + + if [ "$dev" = "none" ]; then return; fi + + # Check if it's an EFI system via efivars module. + if [ -n "$EFI_SYSTEM" ]; then + grub_args="--target=$EFI_TARGET --efi-directory=/boot/efi --bootloader-id=void_grub --recheck" + fi + echo "Running grub-install $grub_args $dev..." >$LOG + chroot $TARGETDIR grub-install $grub_args $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to install GRUB to $dev!\nCheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + echo "Running grub-mkconfig on $TARGETDIR..." >$LOG + chroot $TARGETDIR grub-mkconfig -o /boot/grub/grub.cfg >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR${RESET}: \ +failed to run grub-mkconfig!\nCheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi +} + +test_network() { + # Reset the global variable to ensure that network is accessible for this test. + NETWORK_DONE= + + rm -f otime && \ + xbps-uhelper fetch https://repo-default.voidlinux.org/current/otime >$LOG 2>&1 + local status=$? + rm -f otime + + if [ "$status" -eq 0 ]; then + DIALOG --msgbox "Network is working properly!" ${MSGBOXSIZE} + NETWORK_DONE=1 + return 1 + fi + if [ "$1" = "nm" ]; then + DIALOG --msgbox "Network Manager is enabled but network is inaccessible, please set it up externally with nmcli, nmtui, or the Network Manager tray applet." ${MSGBOXSIZE} + else + DIALOG --msgbox "Network is inaccessible, please set it up properly." ${MSGBOXSIZE} + fi +} + +configure_wifi() { + local dev="$1" ssid enc pass _wpasupconf=/etc/wpa_supplicant/wpa_supplicant.conf + + DIALOG --form "Wireless configuration for ${dev}\n(encryption type: wep or wpa)" 0 0 0 \ + "SSID:" 1 1 "" 1 16 30 0 \ + "Encryption:" 2 1 "" 2 16 4 3 \ + "Password:" 3 1 "" 3 16 63 0 || return 1 + readarray -t values <<<$(cat $ANSWER) + ssid="${values[0]}"; enc="${values[1]}"; pass="${values[2]}" + + if [ -z "$ssid" ]; then + DIALOG --msgbox "Invalid SSID." ${MSGBOXSIZE} + return 1 + elif [ -z "$enc" -o "$enc" != "wep" -a "$enc" != "wpa" ]; then + DIALOG --msgbox "Invalid encryption type (possible values: wep or wpa)." ${MSGBOXSIZE} + return 1 + elif [ -z "$pass" ]; then + DIALOG --msgbox "Invalid AP password." ${MSGBOXSIZE} + fi + + # reset the configuration to the default, if necessary + # otherwise backup the configuration + if [ -f ${_wpasupconf}.orig ]; then + cp -f ${_wpasupconf}.orig ${_wpasupconf} + else + cp -f ${_wpasupconf} ${_wpasupconf}.orig + fi + if [ "$enc" = "wep" ]; then + cat << EOF >> ${_wpasupconf} +network={ + ssid="$ssid" + wep_key0="$pass" + wep_tx_keyidx=0 + auth_alg=SHARED +} +EOF + else + wpa_passphrase "$ssid" "$pass" >> ${_wpasupconf} + fi + + sv restart wpa_supplicant + configure_net_dhcp $dev + return $? +} + +configure_net() { + local dev="$1" rval + + DIALOG --yesno "Do you want to use DHCP for $dev?" ${YESNOSIZE} + rval=$? + if [ $rval -eq 0 ]; then + configure_net_dhcp $dev + elif [ $rval -eq 1 ]; then + configure_net_static $dev + fi +} + +iface_setup() { + ip addr show dev $1 | grep -q -e 'inet ' -e 'inet6 ' + return $? +} + +configure_net_dhcp() { + local dev="$1" + + iface_setup $dev + if [ $? -eq 1 ]; then + sv restart dhcpcd 2>&1 | tee $LOG | \ + DIALOG --progressbox "Initializing $dev via DHCP..." ${WIDGET_SIZE} + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to run dhcpcd. See $LOG for details." ${MSGBOXSIZE} + return 1 + fi + export -f iface_setup + timeout 10s bash -c "while true; do iface_setup $dev; sleep 0.25; done" + if [ $? -eq 1 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} DHCP request failed for $dev. Check $LOG for errors." ${MSGBOXSIZE} + return 1 + fi + fi + test_network + if [ $? -eq 1 ]; then + set_option NETWORK "${dev} dhcp" + fi +} + +configure_net_static() { + local ip gw dns1 dns2 dev=$1 + + DIALOG --form "Static IP configuration for $dev:" 0 0 0 \ + "IP address:" 1 1 "192.168.0.2" 1 21 20 0 \ + "Gateway:" 2 1 "192.168.0.1" 2 21 20 0 \ + "DNS Primary" 3 1 "8.8.8.8" 3 21 20 0 \ + "DNS Secondary" 4 1 "8.8.4.4" 4 21 20 0 || return 1 + + set -- $(cat $ANSWER) + ip=$1; gw=$2; dns1=$3; dns2=$4 + echo "running: ip link set dev $dev up" >$LOG + ip link set dev $dev up >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to bring $dev interface." ${MSGBOXSIZE} + return 1 + fi + echo "running: ip addr add $ip dev $dev" >$LOG + ip addr add $ip dev $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to set ip to the $dev interface." ${MSGBOXSIZE} + return 1 + fi + ip route add default via $gw >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to setup your gateway." ${MSGBOXSIZE} + return 1 + fi + echo "nameserver $dns1" >/etc/resolv.conf + echo "nameserver $dns2" >>/etc/resolv.conf + test_network + if [ $? -eq 1 ]; then + set_option NETWORK "${dev} static $ip $gw $dns1 $dns2" + fi +} + +menu_network() { + local dev addr f DEVICES + + if [ -e /var/service/NetworkManager ]; then + test_network nm + return + fi + + for f in $(ls /sys/class/net); do + [ "$f" = "lo" ] && continue + addr=$(cat /sys/class/net/$f/address) + DEVICES="$DEVICES $f $addr" + done + DIALOG --title " Select the network interface to configure " \ + --menu "$MENULABEL" ${MENUSIZE} ${DEVICES} + if [ $? -eq 0 ]; then + dev=$(cat $ANSWER) + if $(echo $dev|egrep -q "^wl.*" 2>/dev/null); then + configure_wifi $dev + else + configure_net $dev + fi + fi +} + +validate_useraccount() { + # don't check that USERNAME has been set because it can be empty + local USERLOGIN=$(get_option USERLOGIN) + local USERPASSWORD=$(get_option USERPASSWORD) + local USERGROUPS=$(get_option USERGROUPS) + + if [ -n "$USERLOGIN" ] && [ -n "$USERPASSWORD" ] && [ -n "$USERGROUPS" ]; then + USERACCOUNT_DONE=1 + fi +} + +validate_filesystems() { + local mnts dev size fstype mntpt mkfs rootfound fmt + local usrfound efi_system_partition + local bootdev=$(get_option BOOTLOADER) + + unset TARGETFS + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE) + set -- ${mnts} + while [ $# -ne 0 ]; do + fmt="" + dev=$2; fstype=$3; size=$4; mntpt="$5"; mkfs=$6 + shift 6 + + if [ "$mntpt" = "/" ]; then + rootfound=1 + elif [ "$mntpt" = "/usr" ]; then + usrfound=1 + elif [ "$fstype" = "vfat" -a "$mntpt" = "/boot/efi" ]; then + efi_system_partition=1 + fi + if [ "$mkfs" -eq 1 ]; then + fmt="NEW FILESYSTEM: " + fi + if [ -z "$TARGETFS" ]; then + TARGETFS="${fmt}$dev ($size) mounted on $mntpt as ${fstype}\n" + else + TARGETFS="${TARGETFS}${fmt}${dev} ($size) mounted on $mntpt as ${fstype}\n" + fi + done + if [ -z "$rootfound" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +the mount point for the root filesystem (/) has not yet been configured." ${MSGBOXSIZE} + return 1 + elif [ -n "$usrfound" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +/usr mount point has been configured but is not supported, please remove it to continue." ${MSGBOXSIZE} + return 1 + elif [ -n "$EFI_SYSTEM" -a "$bootdev" != "none" -a -z "$efi_system_partition" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +The EFI System Partition has not yet been configured, please create it\n +as FAT32, mountpoint /boot/efi and at least with 100MB of size." ${MSGBOXSIZE} + return 1 + fi + FILESYSTEMS_DONE=1 +} + +create_filesystems() { + local mnts dev mntpt fstype fspassno mkfs size rv uuid + + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE | sort -k 5) + set -- ${mnts} + while [ $# -ne 0 ]; do + dev=$2; fstype=$3; mntpt="$5"; mkfs=$6 + shift 6 + + # swap partitions + if [ "$fstype" = "swap" ]; then + swapoff $dev >/dev/null 2>&1 + if [ "$mkfs" -eq 1 ]; then + mkswap $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to create swap on ${dev}!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + fi + swapon $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to activate swap on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + # Add entry for target fstab + uuid=$(blkid -o value -s UUID "$dev") + echo "UUID=$uuid none swap defaults 0 0" >>$TARGET_FSTAB + continue + fi + + if [ "$mkfs" -eq 1 ]; then + case "$fstype" in + btrfs) MKFS="mkfs.btrfs -f"; modprobe btrfs >$LOG 2>&1;; + ext2) MKFS="mke2fs -F"; modprobe ext2 >$LOG 2>&1;; + ext3) MKFS="mke2fs -F -j"; modprobe ext3 >$LOG 2>&1;; + ext4) MKFS="mke2fs -F -t ext4"; modprobe ext4 >$LOG 2>&1;; + f2fs) MKFS="mkfs.f2fs -f"; modprobe f2fs >$LOG 2>&1;; + vfat) MKFS="mkfs.vfat -F32"; modprobe vfat >$LOG 2>&1;; + xfs) MKFS="mkfs.xfs -f -i sparse=0"; modprobe xfs >$LOG 2>&1;; + esac + TITLE="Check $LOG for details ..." + INFOBOX "Creating filesystem $fstype on $dev for $mntpt ..." 8 60 + echo "Running $MKFS $dev..." >$LOG + $MKFS $dev >$LOG 2>&1; rv=$? + if [ $rv -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to create filesystem $fstype on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + fi + # Mount rootfs the first one. + [ "$mntpt" != "/" ] && continue + mkdir -p $TARGETDIR + echo "Mounting $dev on $mntpt ($fstype)..." >$LOG + mount -t $fstype $dev $TARGETDIR >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to mount $dev on ${mntpt}! check $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + # Add entry to target fstab + uuid=$(blkid -o value -s UUID "$dev") + if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then + fspassno=0 + else + fspassno=1 + fi + echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB + done + + # mount all filesystems in target rootfs + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE | sort -k 5) + set -- ${mnts} + while [ $# -ne 0 ]; do + dev=$2; fstype=$3; mntpt="$5" + shift 6 + [ "$mntpt" = "/" -o "$fstype" = "swap" ] && continue + mkdir -p ${TARGETDIR}${mntpt} + echo "Mounting $dev on $mntpt ($fstype)..." >$LOG + mount -t $fstype $dev ${TARGETDIR}${mntpt} >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to mount $dev on $mntpt! check $LOG for errors." ${MSGBOXSIZE} + DIE + fi + # Add entry to target fstab + uuid=$(blkid -o value -s UUID "$dev") + if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then + fspassno=0 + else + fspassno=2 + fi + echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB + done +} + +mount_filesystems() { + for f in sys proc dev; do + [ ! -d $TARGETDIR/$f ] && mkdir $TARGETDIR/$f + echo "Mounting $TARGETDIR/$f..." >$LOG + mount --rbind /$f $TARGETDIR/$f >$LOG 2>&1 + done +} + +umount_filesystems() { + local mnts="$(grep -E '^MOUNTPOINT.*swap.*$' $CONF_FILE | sort -r -k 5)" + set -- ${mnts} + while [ $# -ne 0 ]; do + local dev=$2; local fstype=$3 + shift 6 + if [ "$fstype" = "swap" ]; then + echo "Disabling swap space on $dev..." >$LOG + swapoff $dev >$LOG 2>&1 + continue + fi + done + echo "Unmounting $TARGETDIR..." >$LOG + umount -R $TARGETDIR >$LOG 2>&1 +} + +log_and_count() { + local progress whole tenth + while read line; do + echo "$line" >$LOG + copy_count=$((copy_count + 1)) + progress=$((1000 * copy_count / copy_total)) + if [ "$progress" != "$copy_progress" ]; then + whole=$((progress / 10)) + tenth=$((progress % 10)) + printf "Progress: %d.%d%% (%d of %d files)\n" $whole $tenth $copy_count $copy_total + copy_progress=$progress + fi + done +} + +copy_rootfs() { + local _grub= _syspkg= + + if [ -n "$EFI_SYSTEM" ]; then + if [ $EFI_FW_BITS -eq 32 ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi + else + _grub="grub" + fi + + _syspkg="base-system" + + mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share + cp -a /usr/share/xbps.d $TARGETDIR/usr/share/ + cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys + mkdir -p $TARGETDIR/boot/grub + + _arch=$(xbps-uhelper arch) + + stdbuf -oL env XBPS_ARCH=${_arch} \ + xbps-install -r $TARGETDIR -y --repository=/var/cache/xbps/ ${_syspkg} ${_grub} 2>&1 | \ + DIALOG --title "Installing base system packages..." \ + --programbox 24 80 + if [ $? -ne 0 ]; then + DIE 1 + fi + xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1 + chroot $TARGETDIR xbps-reconfigure -fa +} + +install_packages() { + local _grub= _syspkg= + + if [ -n "$EFI_SYSTEM" ]; then + if [ $EFI_FW_BITS -eq 32 ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi + else + _grub="grub" + fi + + _syspkg="base-system" + + mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share + cp -a /usr/share/xbps.d $TARGETDIR/usr/share/ + cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys + mkdir -p $TARGETDIR/boot/grub + + _arch=$(xbps-uhelper arch) + + stdbuf -oL env XBPS_ARCH=${_arch} \ + xbps-install -r $TARGETDIR -SyU ${_syspkg} ${_grub} 2>&1 | \ + DIALOG --title "Installing base system packages..." \ + --programbox 24 80 + if [ $? -ne 0 ]; then + DIE 1 + fi + xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1 + chroot $TARGETDIR xbps-reconfigure -fa +} + +enable_service() { + ln -sf /etc/sv/$1 $TARGETDIR/etc/runit/runsvdir/default/$1 +} + +menu_install() { + ROOTPASSWORD_DONE="$(get_option ROOTPASSWORD)" + BOOTLOADER_DONE="$(get_option BOOTLOADER)" + + if [ -z "$ROOTPASSWORD_DONE" ]; then + DIALOG --msgbox "${BOLD}The root password has not been configured, \ +please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + elif [ -z "$BOOTLOADER_DONE" ]; then + DIALOG --msgbox "${BOLD}The disk to install the bootloader has not been \ +configured, please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + fi + + # Validate filesystems after making sure bootloader is done, + # so that specific checks can be made based on the selection + validate_filesystems || return 1 + + if [ -z "$FILESYSTEMS_DONE" ]; then + DIALOG --msgbox "${BOLD}Required filesystems were not configured, \ +please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + fi + + # Validate useraccount. All parameters must be set (name, password, login name, groups). + validate_useraccount + + if [ -z "$USERACCOUNT_DONE" ]; then + DIALOG --yesno "${BOLD}The user account is not set up properly.${RESET}\n\n +${BOLD}${RED}WARNING: no user will be created. You will only be able to login \ +with the root user in your new system.${RESET}\n\n +${BOLD}Do you want to continue?${RESET}" 10 60 || return + fi + + DIALOG --yesno "${BOLD}The following operations will be executed:${RESET}\n\n +${BOLD}${TARGETFS}${RESET}\n +${BOLD}${RED}WARNING: data on partitions will be COMPLETELY DESTROYED for new \ +filesystems.${RESET}\n\n +${BOLD}Do you want to continue?${RESET}" 20 80 || return + unset TARGETFS + + # Create and mount filesystems + create_filesystems + + SOURCE_DONE="$(get_option SOURCE)" + # If source not set use defaults. + if [ "$(get_option SOURCE)" = "local" -o -z "$SOURCE_DONE" ]; then + mount_filesystems + copy_rootfs + else + # mount required fs + mount_filesystems + # network install, use packages. + install_packages + fi + + INFOBOX "Applying installer settings..." 4 60 + + # copy target fstab. + install -Dm644 $TARGET_FSTAB $TARGETDIR/etc/fstab + # Mount /tmp as tmpfs. + echo "tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TARGETDIR/etc/fstab + + + # set up keymap, locale, timezone, hostname, root passwd and user account. + set_keymap + set_locale + set_timezone + set_hostname + set_rootpassword + set_useraccount + + # Copy /etc/skel files for root. + cp $TARGETDIR/etc/skel/.[bix]* $TARGETDIR/root + + NETWORK_DONE="$(get_option NETWORK)" + # network settings for target + if [ -n "$NETWORK_DONE" ]; then + local net="$(get_option NETWORK)" + set -- ${net} + local _dev="$1" _type="$2" _ip="$3" _gw="$4" _dns1="$5" _dns2="$6" + if [ -z "$_type" ]; then + # network type empty??!!! + : + elif [ "$_type" = "dhcp" ]; then + if $(echo $_dev|egrep -q "^wl.*" 2>/dev/null); then + cp /etc/wpa_supplicant/wpa_supplicant.conf $TARGETDIR/etc/wpa_supplicant + ln -sf /etc/sv/wpa_supplicant $TARGETDIR/etc/runit/runsvdir/default/wpa_supplicant + fi + enable_service dhcpcd + elif [ -n "$_dev" -a "$_type" = "static" ]; then + # static IP through dhcpcd. + mv $TARGETDIR/etc/dhcpcd.conf $TARGETDIR/etc/dhcpcd.conf.orig + echo "# Static IP configuration set by the void-installer for $_dev." \ + >$TARGETDIR/etc/dhcpcd.conf + echo "interface $_dev" >>$TARGETDIR/etc/dhcpcd.conf + echo "static ip_address=$_ip" >>$TARGETDIR/etc/dhcpcd.conf + echo "static routers=$_gw" >>$TARGETDIR/etc/dhcpcd.conf + echo "static domain_name_servers=$_dns1 $_dns2" >>$TARGETDIR/etc/dhcpcd.conf + enable_service dhcpcd + fi + fi + + if [ -d $TARGETDIR/etc/sudoers.d ]; then + USERLOGIN="$(get_option USERLOGIN)" + if [ -z "$(echo $(get_option USERGROUPS) | grep -w wheel)" -a -n "$USERLOGIN" ]; then + # enable sudo for primary user USERLOGIN who is not member of wheel + echo "# Enable sudo for login '$USERLOGIN'" > "$TARGETDIR/etc/sudoers.d/$USERLOGIN" + echo "$USERLOGIN ALL=(ALL:ALL) ALL" >> "$TARGETDIR/etc/sudoers.d/$USERLOGIN" + else + # enable the sudoers entry for members of group wheel + echo "%wheel ALL=(ALL:ALL) ALL" > "$TARGETDIR/etc/sudoers.d/wheel" + fi + unset USERLOGIN + fi + + # clean up polkit rule - it's only useful in live systems + rm -f $TARGETDIR/etc/polkit-1/rules.d/void-live.rules + + # enable text console for grub if chosen + if [ "$(get_option TEXTCONSOLE)" = "1" ]; then + sed -i $TARGETDIR/etc/default/grub \ + -e 's|#\(GRUB_TERMINAL_INPUT\).*|\1=console|' \ + -e 's|#\(GRUB_TERMINAL_OUTPUT\).*|\1=console|' + fi + + # install bootloader. + set_bootloader + sync && sync && sync + + # unmount all filesystems. + umount_filesystems + + # installed successfully. + DIALOG --yesno "${BOLD}EvolutionOS has been installed successfully!${RESET}\n +Do you want to reboot the system?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + shutdown -r now + else + return + fi +} + +menu_source() { + local src= + + DIALOG --title " Select installation source " \ + --menu "$MENULABEL" 8 70 0 \ + "Local" "Packages from ISO image" \ + "Network" "Base system only, downloaded from official repository" + case "$(cat $ANSWER)" in + "Local") src="local";; + "Network") src="net"; + if [ -z "$NETWORK_DONE" ]; then + if test_network; then + menu_network + fi + fi;; + *) return 1;; + esac + SOURCE_DONE=1 + set_option SOURCE $src +} + +menu() { + local AFTER_HOSTNAME + if [ -z "$DEFITEM" ]; then + DEFITEM="Keyboard" + fi + + if xbps-uhelper arch | grep -qe '-musl$'; then + AFTER_HOSTNAME="Timezone" + DIALOG --default-item $DEFITEM \ + --extra-button --extra-label "Settings" \ + --title " EvolutionOS installation menu " \ + --menu "$MENULABEL" 10 70 0 \ + "Keyboard" "Set system keyboard" \ + "Network" "Set up the network" \ + "Source" "Set source installation" \ + "Hostname" "Set system hostname" \ + "Timezone" "Set system time zone" \ + "RootPassword" "Set system root password" \ + "UserAccount" "Set primary user name and password" \ + "BootLoader" "Set disk to install bootloader" \ + "Partition" "Partition disk(s)" \ + "Filesystems" "Configure filesystems and mount points" \ + "Install" "Start installation with saved settings" \ + "Exit" "Exit installation" + else + AFTER_HOSTNAME="Locale" + DIALOG --default-item $DEFITEM \ + --extra-button --extra-label "Settings" \ + --title " EvolutionOS installation menu " \ + --menu "$MENULABEL" 10 70 0 \ + "Keyboard" "Set system keyboard" \ + "Network" "Set up the network" \ + "Source" "Set source installation" \ + "Hostname" "Set system hostname" \ + "Locale" "Set system locale" \ + "Timezone" "Set system time zone" \ + "RootPassword" "Set system root password" \ + "UserAccount" "Set primary user name and password" \ + "BootLoader" "Set disk to install bootloader" \ + "Partition" "Partition disk(s)" \ + "Filesystems" "Configure filesystems and mount points" \ + "Install" "Start installation with saved settings" \ + "Exit" "Exit installation" + fi + + if [ $? -eq 3 ]; then + # Show settings + cp $CONF_FILE /tmp/conf_hidden.$$; + sed -i "s/^ROOTPASSWORD.*/ROOTPASSWORD <-hidden->/" /tmp/conf_hidden.$$ + sed -i "s/^USERPASSWORD.*/USERPASSWORD <-hidden->/" /tmp/conf_hidden.$$ + DIALOG --title "Saved settings for installation" --textbox /tmp/conf_hidden.$$ 14 60 + rm /tmp/conf_hidden.$$ + return + fi + + case $(cat $ANSWER) in + "Keyboard") menu_keymap && [ -n "$KEYBOARD_DONE" ] && DEFITEM="Network";; + "Network") menu_network && [ -n "$NETWORK_DONE" ] && DEFITEM="Source";; + "Source") menu_source && [ -n "$SOURCE_DONE" ] && DEFITEM="Hostname";; + "Hostname") menu_hostname && [ -n "$HOSTNAME_DONE" ] && DEFITEM="$AFTER_HOSTNAME";; + "Locale") menu_locale && [ -n "$LOCALE_DONE" ] && DEFITEM="Timezone";; + "Timezone") menu_timezone && [ -n "$TIMEZONE_DONE" ] && DEFITEM="RootPassword";; + "RootPassword") menu_rootpassword && [ -n "$ROOTPASSWORD_DONE" ] && DEFITEM="UserAccount";; + "UserAccount") menu_useraccount && [ -n "$USERLOGIN_DONE" ] && [ -n "$USERPASSWORD_DONE" ] \ + && DEFITEM="BootLoader";; + "BootLoader") menu_bootloader && [ -n "$BOOTLOADER_DONE" ] && DEFITEM="Partition";; + "Partition") menu_partitions && [ -n "$PARTITIONS_DONE" ] && DEFITEM="Filesystems";; + "Filesystems") menu_filesystems && [ -n "$FILESYSTEMS_DONE" ] && DEFITEM="Install";; + "Install") menu_install;; + "Exit") DIE;; + *) DIALOG --yesno "Abort Installation?" ${YESNOSIZE} && DIE + esac +} + +if ! command -v dialog >/dev/null; then + echo "ERROR: missing dialog command, exiting..." + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "evolution-installer must run as root" 1>&2 + exit 1 +fi + +# +# main() +# +DIALOG --title "${BOLD}${RED} EvolutionOS Installer ${RESET}" --msgbox "\n +Welcome to the EvolutionOS installer. A simple and minimal \ +Linux distribution built to be as fast as possible.\n\n +The installation should be pretty straightforward.\n\n +${BOLD}https://tracker-friendly.github.io${RESET}\n\n" 16 80 + +while true; do + menu +done + +exit 0 +# vim: set ts=4 sw=4 et: diff --git a/include-i686/usr/bin/evolution-installer-beta b/include-i686/usr/bin/evolution-installer-beta new file mode 100755 index 0000000..38adb84 --- /dev/null +++ b/include-i686/usr/bin/evolution-installer-beta @@ -0,0 +1,239 @@ +#!/bin/bash + +if [[ $(id -u) -eq 0 ]]; then + : +else + dialog --title "Run as root" --msgbox "Please run the installer as root!" 0 0 + exit 1 +fi + +if [[ -x /sys/firmware/efi ]]; then + uefi=true +else + uefi=false +fi + +dialog --clear --title "Launguage" --menu "Select a language:" 15 50 10 "en_GB" "English UK" "en_US" "English US" + +if [[ $? = 1 ]]; then + exit 1 +fi + +dialog --title "Welcome" --msgbox "Welcome to the EvolutionOS installer! \n\nThis installer is meant to be straightforward, no need for technical skill. \n\nPress enter to select buttons, tab to move between text boxes, and left / right to move between buttons." 0 0 + +get_disk_type() { + local disk_name="$1" + + if [[ "$disk_name" =~ ^sd.$ ]]; then + echo "Hard Disk $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^emmc.+$ ]]; then + echo "Internal Memory $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^nvme.+$ ]]; then + echo "SSD $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^fd.+$ ]]; then + echo "Floppy Disk $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^sr.$ ]]; then + echo "Disk Drive $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + else + echo "Unknown" + fi +} + +# Getting the disk names using lsblk and awk + +disk_names=$(lsblk --list --nodeps -o NAME | awk 'NR>1') + +# Function to check if the disk is writable +is_disk_writable() { + local disk_name="$1" + touch "/mnt/$disk_name" &>/dev/null + local writable=$? + rm "/mnt/$disk_name" &>/dev/null + return $writable +} + +# Loop through each disk name and determine its type +while true; do + # Creating the list for dialog + list=() + for disk_name in $disk_names; do + disk_type=$(get_disk_type "$disk_name") + list+=( "$disk_name" "$disk_type" ) + done + + # Using dialog to display the list + dialog --clear --title "Disk List" --menu "Select a disk:" 15 50 10 "${list[@]}" 2>/tmp/disk_choice + + if [[ $? = 1 ]]; then + exit 1 + fi + + # Reading the choice made by the user + choice=$(cat /tmp/disk_choice) + rm /tmp/disk_choice + + # Check if the disk is writable + if ! is_disk_writable "$choice"; then + dialog --title "Disk Not Writable" --msgbox "The selected disk is not writable. Please choose another disk." 8 50 + continue + fi + + # Check if the disk has partitions + partitions=$(lsblk "/dev/$choice" | grep -c "part") + if [ "$partitions" -gt 0 ]; then + dialog --title "Disk with Partitions" --yesno "The selected disk contains data. Do you want to wipe the disk?" 8 50 + response=$? + if [ "$response" -eq 0 ]; then + # User chose Yes, proceed to wipe the disk + # Add your wipe disk command here + echo "Ok, continuing with: $choice" + break + else + # User chose No, return to the selection menu + continue + fi + else + # Disk has no partitions, continue with further actions + echo "Ok, continuing with: $choice" + # Add your additional actions here + # ... + fi + + # Break out of the loop if the user didn't choose to wipe the disk and there are no partitions + break +done + +for i in $(lsblk --list -o NAME /dev/$choice | awk 'NR>2'); do + umount /dev/$i +done + +sfdisk --delete /dev/$choice +wipefs -a /dev/$choice +sgdisk -Z /dev/$choice + +dialog --yesno "Would you like to use the recommended disk partitioning?" 0 0 +if [[ $? = 0 ]]; then + dialog --msgbox "Starting partitioning..." 0 0 + if [[ $uefi = true ]]; then + sfdisk -X gpt -W always /dev/$choice </tmp/fileselect + if [[ $? = 1 ]]; then + dialog --msgbox "Operation cancled" + exit 1 + fi + filesystem=$(cat /tmp/fileselect) + mkfs.$filesystem /dev/$part2 | dialog --title "Creating file system..." --programbox 24 80 + mount /dev/$part2 /mnt + mkdir -p /mnt/boot/efi + mount /dev/$part1 /mnt/boot/efi + else + echo -e "o\nw" | fdisk /dev/$choice + sfdisk -X mbr -W always /dev/$choice </tmp/fileselect + if [[ $? = 1 ]]; then + dialog --msgbox "Operation cancled" + exit 1 + fi + filesystem=$(cat /tmp/fileselect) + partmpt1=$(lsblk -n -o NAME --list /dev/$choice | sed -n '2p') + mkfs.$filesystem /dev/$part1 | dialog --title "Creating file system..." --programbox 24 80 + fi +else + dialog --msgbox "Ok, you will be dropped into a CLI. Please mount the filesystem, when done, at \"/mnt/\". Note that anything except the default partition disk (ESP, Optional Swap, RootFS) is not offically supported and may not work. Enter exit when you are done." 0 0 + bash + dialog --msgbox "Welcome back! Continuing installation..." 0 0 +fi + +for f in sys proc dev; do + [ ! -d /mnt/$f ] && mkdir /mnt/$f + echo "Mounting /mnt/$f..." + mount --rbind /$f /mnt/$f +done + +dialog --clear --title "Select install type" --menu "Which installation type would you like to you:" 0 0 0 "local" "Install without internet" "network" "Download from internet" 2>/tmp/installtype +installtype=$(cat /tmp/installtype) + +if [ $uefi = true ]; then + if [ $(uname -m) = "i686" ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi +else + _grub="grub" +fi + +mkdir -p /mnt/var/db/xbps/keys /mnt/usr/share +cp -a /usr/share/xbps.d /mnt/usr/share/ +cp /var/db/xbps/keys/*.plist /mnt/var/db/xbps/keys +mkdir -p /mnt/boot/grub + +if [[ $installtype = "local" ]]; then + xbps-install -S -y -r /mnt -i -R /var/cache/xbps/ base-system $_grub | dialog --title "Installing base system..." --programbox 24 80 +else + xbps-install -S -y -r /mnt -R https://evolution-linux.github.io/pkg base-system $_grub | dialog --title "Installing base system..." --programbox 24 80 +fi + +xbps-reconfigure -r /mnt -f base-system +chroot /mnt xbps-reconfigure -fa | dialog --title "Reconfiguring packages..." --programbox 24 80 + +while true; do + dialog --title "Password" --clear --insecure --passwordbox "Enter Admin (root) password. For security reasons, you cannot log in as admin. Press enter to submit." 0 0 2>/tmp/rootpasswd + rootpasswd="$(cat /tmp/rootpasswd)" + passwd -R /mnt </tmp/usershort + shusername="$(cat /tmp/usershort)" + chroot /mnt "useradd -m $shusername" + if [[ $? = 1 ]]; then + dialog --title "Illegal characters" --msgbox "You cannot have those characters in a shorthand username. Please enter a new one." + continue + else + break + fi +done + +dialog --title "Username" --clear --inputbox "Enter display username." 0 0 2>/tmp/dpusername +dpusername=$(cat /tmp/dpusername) +while true; do + dialog --title "Password" --clear --insecure --passwordbox "Enter user password" 0 0 2>/tmp/userpasswd + userpasswd="$(cat /tmp/userpasswd)" + passwd -R /mnt < + + + + public-key + LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF3ay9lR3dKMjRFczBLd3lMSXZqVApjWEtLYjlqR0NwTWZhaTJxQThhVTRLY250TjRWVFFQVDNrc0lsbEZueXFsUURFYlA3MmxtZGVrOUJjaXZTWjNXCmJ1SlNpeEpqL3hyeTF0ZW9qNSsyb3hxdTNHNUNIdEtjVzVwYnlGeUtzaGV6a2gvbk0wRHZlMXI5WndXdkgrbEoKMnRvWXMya2pYY2Irc21pSHJSQUxwRTZHaExxZGVjQnVLNGxXdHhqVWJYQmhLN29YR2NqOXo1MDNlcEFHaHkwbgpVVVAwcjdhTmNINDBiUC9vTXpSSTh5eUV6bnh6OE56VG5EVnVlc3BCR1VrK2J2VzdoZXUrV3lDamZ6QXJLY2tWCm5vQ0xDSVdoYVZPcEw2TTVZVkVRS1lZTUFzZ3VNRVVWSWpwRCtldlpXMUs1QmRjWjdyWG54YVdpWTVKOVdBaVYKVmtJaDkvc3BTNUFGTzU4RkgrejRrOU82SEYvQytTc0d6eVhDVWJaY0UrWUtubVdVYUdXMnl2OFA1S0tDWnZkZApFNW55UTZvS3gvWjhiT1VUV2JOSktpbXZSRHNmRmxhZDZSM0VqWWJUbkFiQTFsNkg0NWhGTmdxdmkrQnprUDlUCmJsU2NFSWRkNU40YXRPek1HclhkQm0yUW44b0NrOWZ3K0ZJVmJkYjZkV1cxQkhaMmFiUmtJcW94b0traWRNQUwKcFVBQ2s4NXpzWXZ5TllsVmp2MEl5VStKMUx6bUZsWWRYemswUGdBZ2J0UlFOMWg3S2t3d3NrSVMwWnlwekMregplMnRQRjZLMUwzUGZrQXZsUE43amJVSGxKUzRTM3FscTJpUlhyRU5ZNkd5cm9vTkxNaXcveUlDWEUvSjlscnNBCjBmejNTamREeUU5R1hQUUJ2aXNCaE1rQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= + public-key-size + 4096 + signature-by + Tracker-Friendly + + diff --git a/include/home/anon/.bashrc b/include/home/anon/.bashrc new file mode 100644 index 0000000..7864d0d --- /dev/null +++ b/include/home/anon/.bashrc @@ -0,0 +1 @@ +sudo diff --git a/include/home/anon/.profile b/include/home/anon/.profile new file mode 100644 index 0000000..705963a --- /dev/null +++ b/include/home/anon/.profile @@ -0,0 +1 @@ +bash diff --git a/include/root/.bashrc b/include/root/.bashrc new file mode 100644 index 0000000..fb9a43e --- /dev/null +++ b/include/root/.bashrc @@ -0,0 +1 @@ +bash -c "evolution-installer" diff --git a/include/root/.profile b/include/root/.profile new file mode 100644 index 0000000..58b8a62 --- /dev/null +++ b/include/root/.profile @@ -0,0 +1,2 @@ +evolution-installer +bash diff --git a/include/usr/bin/evolution-installer b/include/usr/bin/evolution-installer new file mode 100755 index 0000000..9c1aa2d --- /dev/null +++ b/include/usr/bin/evolution-installer @@ -0,0 +1,1533 @@ +#!/bin/bash + +#- +# Copyright (c) 2012-2015 Juan Romero Pardines . +# 2012 Dave Elusive . +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +# Make sure we don't inherit these from env. +SOURCE_DONE= +HOSTNAME_DONE= +KEYBOARD_DONE= +LOCALE_DONE= +TIMEZONE_DONE= +ROOTPASSWORD_DONE= +USERLOGIN_DONE= +USERPASSWORD_DONE= +USERNAME_DONE= +USERGROUPS_DONE= +USERACCOUNT_DONE= +BOOTLOADER_DONE= +PARTITIONS_DONE= +NETWORK_DONE= +FILESYSTEMS_DONE= + +TARGETDIR=/mnt/target +LOG=/dev/tty8 +CONF_FILE=/tmp/.void-installer.conf +if [ ! -f $CONF_FILE ]; then + touch -f $CONF_FILE +fi +ANSWER=$(mktemp -t vinstall-XXXXXXXX || exit 1) +TARGET_FSTAB=$(mktemp -t vinstall-fstab-XXXXXXXX || exit 1) + +trap "DIE" INT TERM QUIT + +# disable printk +if [ -w /proc/sys/kernel/printk ]; then + echo 0 >/proc/sys/kernel/printk +fi + +# Detect if this is an EFI system. +if [ -e /sys/firmware/efi/systab ]; then + EFI_SYSTEM=1 + EFI_FW_BITS=$(cat /sys/firmware/efi/fw_platform_size) + if [ $EFI_FW_BITS -eq 32 ]; then + EFI_TARGET=i386-efi + else + EFI_TARGET=x86_64-efi + fi +fi + +# dialog colors +BLACK="\Z0" +RED="\Z1" +GREEN="\Z2" +YELLOW="\Z3" +BLUE="\Z4" +MAGENTA="\Z5" +CYAN="\Z6" +WHITE="\Z7" +BOLD="\Zb" +REVERSE="\Zr" +UNDERLINE="\Zu" +RESET="\Zn" + +# Properties shared per widget. +MENULABEL="${BOLD}Use UP and DOWN keys to navigate \ +menus. Use TAB to switch between buttons and ENTER to select.${RESET}" +MENUSIZE="14 60 0" +INPUTSIZE="8 60" +MSGBOXSIZE="8 70" +YESNOSIZE="$INPUTSIZE" +WIDGET_SIZE="10 70" + +DIALOG() { + rm -f $ANSWER + dialog --colors --keep-tite --no-shadow --no-mouse \ + --backtitle "${BOLD}${WHITE}EvolutionOS installation -- https://tracker-friendly.github.io" \ + --cancel-label "Back" --aspect 20 "$@" 2>$ANSWER + return $? +} + +INFOBOX() { + # Note: dialog --infobox and --keep-tite don't work together + dialog --colors --no-shadow --no-mouse \ + --backtitle "${BOLD}${WHITE}EvolutionOS installation -- https://tracker-friendly.github.io" \ + --title "${TITLE}" --aspect 20 --infobox "$@" +} + +DIE() { + rval=$1 + [ -z "$rval" ] && rval=0 + clear + rm -f $ANSWER $TARGET_FSTAB + # reenable printk + if [ -w /proc/sys/kernel/printk ]; then + echo 4 >/proc/sys/kernel/printk + fi + umount_filesystems + exit $rval +} + +set_option() { + if grep -Eq "^${1}.*" $CONF_FILE; then + sed -i -e "/^${1}.*/d" $CONF_FILE + fi + echo "${1} ${2}" >>$CONF_FILE +} + +get_option() { + echo $(grep -E "^${1}.*" $CONF_FILE|sed -e "s|${1}||") +} + +# ISO-639 language names for locales +iso639_language() { + case "$1" in + aa) echo "Afar" ;; + af) echo "Afrikaans" ;; + an) echo "Aragonese" ;; + ar) echo "Arabic" ;; + ast) echo "Asturian" ;; + be) echo "Belgian" ;; + bg) echo "Bulgarian" ;; + bhb) echo "Bhili" ;; + br) echo "Breton" ;; + bs) echo "Bosnian" ;; + ca) echo "Catalan" ;; + cs) echo "Czech" ;; + cy) echo "Welsh" ;; + da) echo "Danish" ;; + de) echo "German" ;; + el) echo "Greek" ;; + en) echo "English" ;; + es) echo "Spanish" ;; + et) echo "Estonian" ;; + eu) echo "Basque" ;; + fi) echo "Finnish" ;; + fo) echo "Faroese" ;; + fr) echo "French" ;; + ga) echo "Irish" ;; + gd) echo "Scottish Gaelic" ;; + gl) echo "Galician" ;; + gv) echo "Manx" ;; + he) echo "Hebrew" ;; + hr) echo "Croatian" ;; + hsb) echo "Upper Sorbian" ;; + hu) echo "Hungarian" ;; + id) echo "Indonesian" ;; + is) echo "Icelandic" ;; + it) echo "Italian" ;; + iw) echo "Hebrew" ;; + ja) echo "Japanese" ;; + ka) echo "Georgian" ;; + kk) echo "Kazakh" ;; + kl) echo "Kalaallisut" ;; + ko) echo "Korean" ;; + ku) echo "Kurdish" ;; + kw) echo "Cornish" ;; + lg) echo "Ganda" ;; + lt) echo "Lithuanian" ;; + lv) echo "Latvian" ;; + mg) echo "Malagasy" ;; + mi) echo "Maori" ;; + mk) echo "Macedonian" ;; + ms) echo "Malay" ;; + mt) echo "Maltese" ;; + nb) echo "Norwegian Bokmål" ;; + nl) echo "Dutch" ;; + nn) echo "Norwegian Nynorsk" ;; + oc) echo "Occitan" ;; + om) echo "Oromo" ;; + pl) echo "Polish" ;; + pt) echo "Portugese" ;; + ro) echo "Romanian" ;; + ru) echo "Russian" ;; + sk) echo "Slovak" ;; + sl) echo "Slovenian" ;; + so) echo "Somali" ;; + sq) echo "Albanian" ;; + st) echo "Southern Sotho" ;; + sv) echo "Swedish" ;; + tcy) echo "Tulu" ;; + tg) echo "Tajik" ;; + th) echo "Thai" ;; + tl) echo "Tagalog" ;; + tr) echo "Turkish" ;; + uk) echo "Ukrainian" ;; + uz) echo "Uzbek" ;; + wa) echo "Walloon" ;; + xh) echo "Xhosa" ;; + yi) echo "Yiddish" ;; + zh) echo "Chinese" ;; + zu) echo "Zulu" ;; + *) echo "$1" ;; + esac +} + +# ISO-3166 country codes for locales +iso3166_country() { + case "$1" in + AD) echo "Andorra" ;; + AE) echo "United Arab Emirates" ;; + AL) echo "Albania" ;; + AR) echo "Argentina" ;; + AT) echo "Austria" ;; + AU) echo "Australia" ;; + BA) echo "Bonsia and Herzegovina" ;; + BE) echo "Belgium" ;; + BG) echo "Bulgaria" ;; + BH) echo "Bahrain" ;; + BO) echo "Bolivia" ;; + BR) echo "Brazil" ;; + BW) echo "Botswana" ;; + BY) echo "Belarus" ;; + CA) echo "Canada" ;; + CH) echo "Switzerland" ;; + CL) echo "Chile" ;; + CN) echo "China" ;; + CO) echo "Colombia" ;; + CR) echo "Costa Rica" ;; + CY) echo "Cyprus" ;; + CZ) echo "Czech Republic" ;; + DE) echo "Germany" ;; + DJ) echo "Djibouti" ;; + DK) echo "Denmark" ;; + DO) echo "Dominican Republic" ;; + DZ) echo "Algeria" ;; + EC) echo "Ecuador" ;; + EE) echo "Estonia" ;; + EG) echo "Egypt" ;; + ES) echo "Spain" ;; + FI) echo "Finland" ;; + FO) echo "Faroe Islands" ;; + FR) echo "France" ;; + GB) echo "Great Britain" ;; + GE) echo "Georgia" ;; + GL) echo "Greenland" ;; + GR) echo "Greece" ;; + GT) echo "Guatemala" ;; + HK) echo "Hong Kong" ;; + HN) echo "Honduras" ;; + HR) echo "Croatia" ;; + HU) echo "Hungary" ;; + ID) echo "Indonesia" ;; + IE) echo "Ireland" ;; + IL) echo "Israel" ;; + IN) echo "India" ;; + IQ) echo "Iraq" ;; + IS) echo "Iceland" ;; + IT) echo "Italy" ;; + JO) echo "Jordan" ;; + JP) echo "Japan" ;; + KE) echo "Kenya" ;; + KR) echo "Korea, Republic of" ;; + KW) echo "Kuwait" ;; + KZ) echo "Kazakhstan" ;; + LB) echo "Lebanon" ;; + LT) echo "Lithuania" ;; + LU) echo "Luxembourg" ;; + LV) echo "Latvia" ;; + LY) echo "Libya" ;; + MA) echo "Morocco" ;; + MG) echo "Madagascar" ;; + MK) echo "Macedonia" ;; + MT) echo "Malta" ;; + MX) echo "Mexico" ;; + MY) echo "Malaysia" ;; + NI) echo "Nicaragua" ;; + NL) echo "Netherlands" ;; + NO) echo "Norway" ;; + NZ) echo "New Zealand" ;; + OM) echo "Oman" ;; + PA) echo "Panama" ;; + PE) echo "Peru" ;; + PH) echo "Philippines" ;; + PL) echo "Poland" ;; + PR) echo "Puerto Rico" ;; + PT) echo "Portugal" ;; + PY) echo "Paraguay" ;; + QA) echo "Qatar" ;; + RO) echo "Romania" ;; + RU) echo "Russian Federation" ;; + SA) echo "Saudi Arabia" ;; + SD) echo "Sudan" ;; + SE) echo "Sweden" ;; + SG) echo "Singapore" ;; + SI) echo "Slovenia" ;; + SK) echo "Slovakia" ;; + SO) echo "Somalia" ;; + SV) echo "El Salvador" ;; + SY) echo "Syria" ;; + TH) echo "Thailand" ;; + TJ) echo "Tajikistan" ;; + TN) echo "Tunisia" ;; + TR) echo "Turkey" ;; + TW) echo "Taiwan" ;; + UA) echo "Ukraine" ;; + UG) echo "Uganda" ;; + US) echo "United States of America" ;; + UY) echo "Uruguay" ;; + UZ) echo "Uzbekistan" ;; + VE) echo "Venezuela" ;; + YE) echo "Yemen" ;; + ZA) echo "South Africa" ;; + ZW) echo "Zimbabwe" ;; + *) echo "$1" ;; + esac +} + +show_disks() { + local dev size sectorsize gbytes + + # IDE + for dev in $(ls /sys/block|grep -E '^hd'); do + if [ "$(cat /sys/block/$dev/device/media)" = "disk" ]; then + # Find out nr sectors and bytes per sector; + echo "/dev/$dev" + size=$(cat /sys/block/$dev/size) + sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + fi + done + # SATA/SCSI and Virtual disks (virtio) + for dev in $(ls /sys/block|grep -E '^([sv]|xv)d|mmcblk|nvme'); do + echo "/dev/$dev" + size=$(cat /sys/block/$dev/size) + sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + done + # cciss(4) devices + for dev in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]$'); do + echo "/dev/cciss/$dev" + size=$(cat /sys/block/cciss\!$dev/size) + sectorsize=$(cat /sys/block/cciss\!$dev/queue/hw_sector_size) + gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))" + echo "size:${gbytes}GB;sector_size:$sectorsize" + done +} + +get_partfs() { + # Get fs type from configuration if available. This ensures + # that the user is shown the proper fs type if they install the system. + local part="$1" + local default="${2:-none}" + local fstype=$(grep "MOUNTPOINT ${part}" "$CONF_FILE"|awk '{print $3}') + echo "${fstype:-$default}" +} + +show_partitions() { + local dev fstype fssize p part + + set -- $(show_disks) + while [ $# -ne 0 ]; do + disk=$(basename $1) + shift 2 + # ATA/SCSI/SATA + for p in /sys/block/$disk/$disk*; do + if [ -d $p ]; then + part=$(basename $p) + fstype=$(lsblk -nfr /dev/$part|awk '{print $2}'|head -1) + [ "$fstype" = "iso9660" ] && continue + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/$part|awk '{print $4}'|head -1) + echo "/dev/$part" + echo "size:${fssize:-unknown};fstype:$(get_partfs "/dev/$part")" + fi + done + done + # Device Mapper + for p in /dev/mapper/*; do + part=$(basename $p) + [ "${part}" = "live-rw" ] && continue + [ "${part}" = "live-base" ] && continue + [ "${part}" = "control" ] && continue + + fstype=$(lsblk -nfr $p|awk '{print $2}'|head -1) + fssize=$(lsblk -nr $p|awk '{print $4}'|head -1) + echo "${p}" + echo "size:${fssize:-unknown};fstype:$(get_partfs "$p")" + done + # Software raid (md) + for p in $(ls -d /dev/md* 2>/dev/null|grep '[0-9]'); do + part=$(basename $p) + if cat /proc/mdstat|grep -qw $part; then + fstype=$(lsblk -nfr /dev/$part|awk '{print $2}') + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/$part|awk '{print $4}') + echo "$p" + echo "size:${fssize:-unknown};fstype:$(get_partfs "$p")" + fi + done + # cciss(4) devices + for part in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]p[0-9]+'); do + fstype=$(lsblk -nfr /dev/cciss/$part|awk '{print $2}') + [ "$fstype" = "crypto_LUKS" ] && continue + [ "$fstype" = "LVM2_member" ] && continue + fssize=$(lsblk -nr /dev/cciss/$part|awk '{print $4}') + echo "/dev/cciss/$part" + echo "size:${fssize:-unknown};fstype:$(get_partfs "/dev/cciss/$part")" + done + if [ -e /sbin/lvs ]; then + # LVM + lvs --noheadings|while read lvname vgname perms size; do + echo "/dev/mapper/${vgname}-${lvname}" + echo "size:${size};fstype:$(get_partfs "/dev/mapper/${vgname}-${lvname}" lvm)" + done + fi +} + +menu_filesystems() { + local dev fstype fssize mntpoint reformat + + while true; do + DIALOG --ok-label "Change" --cancel-label "Done" \ + --title " Select the partition to edit " --menu "$MENULABEL" \ + ${MENUSIZE} $(show_partitions) + [ $? -ne 0 ] && return + + dev=$(cat $ANSWER) + DIALOG --title " Select the filesystem type for $dev " \ + --menu "$MENULABEL" ${MENUSIZE} \ + "btrfs" "Oracle's Btrfs" \ + "ext2" "Linux ext2 (no journaling)" \ + "ext3" "Linux ext3 (journal)" \ + "ext4" "Linux ext4 (journal)" \ + "f2fs" "Flash-Friendly Filesystem" \ + "swap" "Linux swap" \ + "vfat" "FAT32" \ + "xfs" "SGI's XFS" + if [ $? -eq 0 ]; then + fstype=$(cat $ANSWER) + else + continue + fi + if [ "$fstype" != "swap" ]; then + DIALOG --inputbox "Please specify the mount point for $dev:" ${INPUTSIZE} + if [ $? -eq 0 ]; then + mntpoint=$(cat $ANSWER) + elif [ $? -eq 1 ]; then + continue + fi + else + mntpoint=swap + fi + DIALOG --yesno "Do you want to create a new filesystem on $dev?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + reformat=1 + elif [ $? -eq 1 ]; then + reformat=0 + else + continue + fi + fssize=$(lsblk -nr $dev|awk '{print $4}') + set -- "$fstype" "$fssize" "$mntpoint" "$reformat" + if [ -n "$1" -a -n "$2" -a -n "$3" -a -n "$4" ]; then + local bdev=$(basename $dev) + local ddev=$(basename $(dirname $dev)) + if [ "$ddev" != "dev" ]; then + sed -i -e "/^MOUNTPOINT \/dev\/${ddev}\/${bdev}.*/d" $CONF_FILE + else + sed -i -e "/^MOUNTPOINT \/dev\/${bdev}.*/d" $CONF_FILE + fi + echo "MOUNTPOINT $dev $1 $2 $3 $4" >>$CONF_FILE + fi + done + FILESYSTEMS_DONE=1 +} + +menu_partitions() { + DIALOG --title " Select the disk to partition " \ + --menu "$MENULABEL" ${MENUSIZE} $(show_disks) + if [ $? -eq 0 ]; then + local device=$(cat $ANSWER) + + DIALOG --title " Select the software for partitioning " \ + --menu "$MENULABEL" ${MENUSIZE} \ + "cfdisk" "Easy to use" \ + "fdisk" "More advanced" + if [ $? -eq 0 ]; then + local software=$(cat $ANSWER) + + DIALOG --title "Modify Partition Table on $device" --msgbox "\n +${BOLD}${software} will be executed in disk $device.${RESET}\n\n +For BIOS systems, MBR or GPT partition tables are supported.\n +To use GPT on PC BIOS systems an empty partition of 1MB must be added\n +at the first 2GB of the disk with the TOGGLE \`bios_grub' enabled.\n +${BOLD}NOTE: you don't need this on EFI systems.${RESET}\n\n +For EFI systems GPT is mandatory and a FAT32 partition with at least\n +100MB must be created with the TOGGLE \`boot', this will be used as\n +EFI System Partition. This partition must have mountpoint as \`/boot/efi'.\n\n +At least 1 partition is required for the rootfs (/).\n +For swap, RAM*2 must be really enough. For / 600MB are required.\n\n +${BOLD}WARNING: /usr is not supported as a separate partition.${RESET}\n +${RESET}\n" 18 80 + if [ $? -eq 0 ]; then + while true; do + clear; $software $device; PARTITIONS_DONE=1 + break + done + else + return + fi + fi + fi +} + +menu_keymap() { + local _keymaps="$(find /usr/share/kbd/keymaps/ -type f -iname "*.map.gz" -printf "%f\n" | sed 's|.map.gz||g' | sort)" + local _KEYMAPS= + + for f in ${_keymaps}; do + _KEYMAPS="${_KEYMAPS} ${f} -" + done + while true; do + DIALOG --title " Select your keymap " --menu "$MENULABEL" 14 70 14 ${_KEYMAPS} + if [ $? -eq 0 ]; then + set_option KEYMAP "$(cat $ANSWER)" + loadkeys "$(cat $ANSWER)" + KEYBOARD_DONE=1 + break + else + return + fi + done +} + +set_keymap() { + local KEYMAP=$(get_option KEYMAP) + + if [ -f /etc/vconsole.conf ]; then + sed -i -e "s|KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/vconsole.conf + else + sed -i -e "s|#\?KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/rc.conf + fi +} + +menu_locale() { + local _locales="$(grep -E '\.UTF-8' /etc/default/libc-locales|awk '{print $1}'|sed -e 's/^#//')" + local LOCALES ISO639 ISO3166 + local TMPFILE=$(mktemp -t vinstall-XXXXXXXX || exit 1) + INFOBOX "Scanning locales ..." 4 60 + for f in ${_locales}; do + eval $(echo $f | awk 'BEGIN { FS="." } \ + { FS="_"; split($1, a); printf "ISO639=%s ISO3166=%s\n", a[1], a[2] }') + echo "$f|$(iso639_language $ISO639) ($(iso3166_country $ISO3166))|" >> $TMPFILE + done + clear + # Sort by ISO-639 language names + LOCALES=$(sort -t '|' -k 2 < $TMPFILE | xargs | sed -e's/| /|/g') + rm -f $TMPFILE + while true; do + (IFS="|"; DIALOG --title " Select your locale " --menu "$MENULABEL" 18 70 18 ${LOCALES}) + if [ $? -eq 0 ]; then + set_option LOCALE "$(cat $ANSWER)" + LOCALE_DONE=1 + break + else + return + fi + done +} + +set_locale() { + if [ -f $TARGETDIR/etc/default/libc-locales ]; then + local LOCALE="$(get_option LOCALE)" + : "${LOCALE:=C.UTF-8}" + sed -i -e "s|LANG=.*|LANG=$LOCALE|g" $TARGETDIR/etc/locale.conf + # Uncomment locale from /etc/default/libc-locales and regenerate it. + sed -e "/${LOCALE}/s/^\#//" -i $TARGETDIR/etc/default/libc-locales + echo "Running xbps-reconfigure -f glibc-locales ..." >$LOG + chroot $TARGETDIR xbps-reconfigure -f glibc-locales >$LOG 2>&1 + fi +} + +menu_timezone() { + local areas=(Africa America Antarctica Arctic Asia Atlantic Australia Europe Indian Pacific) + + local area locations location + while (IFS='|'; DIALOG ${area:+--default-item|"$area"} --title " Select area " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${areas[@]}")); do + area=$(cat $ANSWER) + read -a locations -d '\n' < <(find /usr/share/zoneinfo/$area -type f -printf '%P\n' | sort) + if (IFS='|'; DIALOG --title " Select location (${area}) " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${locations[@]//_/ }")); then + location=$(tr ' ' '_' < $ANSWER) + set_option TIMEZONE "$area/$location" + TIMEZONE_DONE=1 + return 0 + else + continue + fi + done + return 1 +} + +set_timezone() { + local TIMEZONE="$(get_option TIMEZONE)" + + ln -sf "/usr/share/zoneinfo/${TIMEZONE}" "${TARGETDIR}/etc/localtime" +} + +menu_hostname() { + while true; do + DIALOG --inputbox "Set the machine hostname:" ${INPUTSIZE} + if [ $? -eq 0 ]; then + set_option HOSTNAME "$(cat $ANSWER)" + HOSTNAME_DONE=1 + break + else + return + fi + done +} + +set_hostname() { + local hostname="$(get_option HOSTNAME)" + echo "${hostname:-void}" > $TARGETDIR/etc/hostname +} + +menu_rootpassword() { + local _firstpass _secondpass _again _desc + + while true; do + if [ -z "${_firstpass}" ]; then + _desc="Enter the root password" + else + _again=" again" + fi + DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE} + if [ $? -eq 0 ]; then + if [ -z "${_firstpass}" ]; then + _firstpass="$(cat $ANSWER)" + else + _secondpass="$(cat $ANSWER)" + fi + if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then + if [ "${_firstpass}" != "${_secondpass}" ]; then + INFOBOX "Passwords do not match! Please enter again." 6 60 + unset _firstpass _secondpass _again + sleep 2 && clear && continue + fi + set_option ROOTPASSWORD "${_firstpass}" + ROOTPASSWORD_DONE=1 + break + fi + else + return + fi + done +} + +set_rootpassword() { + echo "root:$(get_option ROOTPASSWORD)" | chroot $TARGETDIR chpasswd -c SHA512 +} + +menu_useraccount() { + local _firstpass _secondpass _desc _again + local _groups _status _group _checklist + local _preset _userlogin + + while true; do + _preset=$(get_option USERLOGIN) + [ -z "$_preset" ] && _preset="evolution" + DIALOG --inputbox "Enter a primary login name:" ${INPUTSIZE} "$_preset" + if [ $? -eq 0 ]; then + _userlogin="$(cat $ANSWER)" + # based on useradd(8) § Caveats + if [ "${#_userlogin}" -le 32 ] && [[ "${_userlogin}" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then + set_option USERLOGIN "${_userlogin}" + USERLOGIN_DONE=1 + break + else + INFOBOX "Invalid login name! Please try again." 6 60 + unset _userlogin + sleep 2 && clear && continue + fi + else + return + fi + done + + while true; do + _preset=$(get_option USERNAME) + [ -z "$_preset" ] && _preset="Evolution User" + DIALOG --inputbox "Enter a display name for login '$(get_option USERLOGIN)' :" \ + ${INPUTSIZE} "$_preset" + if [ $? -eq 0 ]; then + set_option USERNAME "$(cat $ANSWER)" + USERNAME_DONE=1 + break + else + return + fi + done + + while true; do + if [ -z "${_firstpass}" ]; then + _desc="Enter the password for login '$(get_option USERLOGIN)'" + else + _again=" again" + fi + DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE} + if [ $? -eq 0 ]; then + if [ -z "${_firstpass}" ]; then + _firstpass="$(cat $ANSWER)" + else + _secondpass="$(cat $ANSWER)" + fi + if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then + if [ "${_firstpass}" != "${_secondpass}" ]; then + INFOBOX "Passwords do not match! Please enter again." 6 60 + unset _firstpass _secondpass _again + sleep 2 && clear && continue + fi + set_option USERPASSWORD "${_firstpass}" + USERPASSWORD_DONE=1 + break + fi + else + return + fi + done + + _groups="wheel,audio,video,floppy,cdrom,optical,kvm,xbuilder" + while true; do + _desc="Select group membership for login '$(get_option USERLOGIN)':" + for _group in $(cat /etc/group); do + _gid="$(echo ${_group} | cut -d: -f3)" + _group="$(echo ${_group} | cut -d: -f1)" + _status="$(echo ${_groups} | grep -w ${_group})" + if [ -z "${_status}" ]; then + _status=off + else + _status=on + fi + # ignore the groups of root, existing users, and package groups + if [[ "${_gid}" -ge 1000 || "${_group}" = "_"* || "${_group}" = "root" ]]; then + continue + fi + if [ -z "${_checklist}" ]; then + _checklist="${_group} ${_group}:${_gid} ${_status}" + else + _checklist="${_checklist} ${_group} ${_group}:${_gid} ${_status}" + fi + done + DIALOG --no-tags --checklist "${_desc}" 20 60 18 ${_checklist} + if [ $? -eq 0 ]; then + set_option USERGROUPS $(cat $ANSWER | sed -e's| |,|g') + USERGROUPS_DONE=1 + break + else + return + fi + done +} + +set_useraccount() { + [ -z "$USERACCOUNT_DONE" ] && return + chroot $TARGETDIR useradd -m -G "$(get_option USERGROUPS)" \ + -c "$(get_option USERNAME)" "$(get_option USERLOGIN)" + echo "$(get_option USERLOGIN):$(get_option USERPASSWORD)" | \ + chroot $TARGETDIR chpasswd -c SHA512 +} + +menu_bootloader() { + while true; do + DIALOG --title " Select the disk to install the bootloader" \ + --menu "$MENULABEL" ${MENUSIZE} $(show_disks) none "Manage bootloader otherwise" + if [ $? -eq 0 ]; then + set_option BOOTLOADER "$(cat $ANSWER)" + BOOTLOADER_DONE=1 + break + else + return + fi + done + while true; do + DIALOG --yesno "Use a graphical terminal for the boot loader?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + set_option TEXTCONSOLE 0 + break + elif [ $? -eq 1 ]; then + set_option TEXTCONSOLE 1 + break + else + return + fi + done +} + +set_bootloader() { + local dev=$(get_option BOOTLOADER) grub_args= + + if [ "$dev" = "none" ]; then return; fi + + # Check if it's an EFI system via efivars module. + if [ -n "$EFI_SYSTEM" ]; then + grub_args="--target=$EFI_TARGET --efi-directory=/boot/efi --bootloader-id=void_grub --recheck" + fi + echo "Running grub-install $grub_args $dev..." >$LOG + chroot $TARGETDIR grub-install $grub_args $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to install GRUB to $dev!\nCheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + echo "Running grub-mkconfig on $TARGETDIR..." >$LOG + chroot $TARGETDIR grub-mkconfig -o /boot/grub/grub.cfg >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR${RESET}: \ +failed to run grub-mkconfig!\nCheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi +} + +test_network() { + # Reset the global variable to ensure that network is accessible for this test. + NETWORK_DONE= + + rm -f otime && \ + xbps-uhelper fetch https://repo-default.voidlinux.org/current/otime >$LOG 2>&1 + local status=$? + rm -f otime + + if [ "$status" -eq 0 ]; then + DIALOG --msgbox "Network is working properly!" ${MSGBOXSIZE} + NETWORK_DONE=1 + return 1 + fi + if [ "$1" = "nm" ]; then + DIALOG --msgbox "Network Manager is enabled but network is inaccessible, please set it up externally with nmcli, nmtui, or the Network Manager tray applet." ${MSGBOXSIZE} + else + DIALOG --msgbox "Network is inaccessible, please set it up properly." ${MSGBOXSIZE} + fi +} + +configure_wifi() { + local dev="$1" ssid enc pass _wpasupconf=/etc/wpa_supplicant/wpa_supplicant.conf + + DIALOG --form "Wireless configuration for ${dev}\n(encryption type: wep or wpa)" 0 0 0 \ + "SSID:" 1 1 "" 1 16 30 0 \ + "Encryption:" 2 1 "" 2 16 4 3 \ + "Password:" 3 1 "" 3 16 63 0 || return 1 + readarray -t values <<<$(cat $ANSWER) + ssid="${values[0]}"; enc="${values[1]}"; pass="${values[2]}" + + if [ -z "$ssid" ]; then + DIALOG --msgbox "Invalid SSID." ${MSGBOXSIZE} + return 1 + elif [ -z "$enc" -o "$enc" != "wep" -a "$enc" != "wpa" ]; then + DIALOG --msgbox "Invalid encryption type (possible values: wep or wpa)." ${MSGBOXSIZE} + return 1 + elif [ -z "$pass" ]; then + DIALOG --msgbox "Invalid AP password." ${MSGBOXSIZE} + fi + + # reset the configuration to the default, if necessary + # otherwise backup the configuration + if [ -f ${_wpasupconf}.orig ]; then + cp -f ${_wpasupconf}.orig ${_wpasupconf} + else + cp -f ${_wpasupconf} ${_wpasupconf}.orig + fi + if [ "$enc" = "wep" ]; then + cat << EOF >> ${_wpasupconf} +network={ + ssid="$ssid" + wep_key0="$pass" + wep_tx_keyidx=0 + auth_alg=SHARED +} +EOF + else + wpa_passphrase "$ssid" "$pass" >> ${_wpasupconf} + fi + + sv restart wpa_supplicant + configure_net_dhcp $dev + return $? +} + +configure_net() { + local dev="$1" rval + + DIALOG --yesno "Do you want to use DHCP for $dev?" ${YESNOSIZE} + rval=$? + if [ $rval -eq 0 ]; then + configure_net_dhcp $dev + elif [ $rval -eq 1 ]; then + configure_net_static $dev + fi +} + +iface_setup() { + ip addr show dev $1 | grep -q -e 'inet ' -e 'inet6 ' + return $? +} + +configure_net_dhcp() { + local dev="$1" + + iface_setup $dev + if [ $? -eq 1 ]; then + sv restart dhcpcd 2>&1 | tee $LOG | \ + DIALOG --progressbox "Initializing $dev via DHCP..." ${WIDGET_SIZE} + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to run dhcpcd. See $LOG for details." ${MSGBOXSIZE} + return 1 + fi + export -f iface_setup + timeout 10s bash -c "while true; do iface_setup $dev; sleep 0.25; done" + if [ $? -eq 1 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} DHCP request failed for $dev. Check $LOG for errors." ${MSGBOXSIZE} + return 1 + fi + fi + test_network + if [ $? -eq 1 ]; then + set_option NETWORK "${dev} dhcp" + fi +} + +configure_net_static() { + local ip gw dns1 dns2 dev=$1 + + DIALOG --form "Static IP configuration for $dev:" 0 0 0 \ + "IP address:" 1 1 "192.168.0.2" 1 21 20 0 \ + "Gateway:" 2 1 "192.168.0.1" 2 21 20 0 \ + "DNS Primary" 3 1 "8.8.8.8" 3 21 20 0 \ + "DNS Secondary" 4 1 "8.8.4.4" 4 21 20 0 || return 1 + + set -- $(cat $ANSWER) + ip=$1; gw=$2; dns1=$3; dns2=$4 + echo "running: ip link set dev $dev up" >$LOG + ip link set dev $dev up >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to bring $dev interface." ${MSGBOXSIZE} + return 1 + fi + echo "running: ip addr add $ip dev $dev" >$LOG + ip addr add $ip dev $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to set ip to the $dev interface." ${MSGBOXSIZE} + return 1 + fi + ip route add default via $gw >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to setup your gateway." ${MSGBOXSIZE} + return 1 + fi + echo "nameserver $dns1" >/etc/resolv.conf + echo "nameserver $dns2" >>/etc/resolv.conf + test_network + if [ $? -eq 1 ]; then + set_option NETWORK "${dev} static $ip $gw $dns1 $dns2" + fi +} + +menu_network() { + local dev addr f DEVICES + + if [ -e /var/service/NetworkManager ]; then + test_network nm + return + fi + + for f in $(ls /sys/class/net); do + [ "$f" = "lo" ] && continue + addr=$(cat /sys/class/net/$f/address) + DEVICES="$DEVICES $f $addr" + done + DIALOG --title " Select the network interface to configure " \ + --menu "$MENULABEL" ${MENUSIZE} ${DEVICES} + if [ $? -eq 0 ]; then + dev=$(cat $ANSWER) + if $(echo $dev|egrep -q "^wl.*" 2>/dev/null); then + configure_wifi $dev + else + configure_net $dev + fi + fi +} + +validate_useraccount() { + # don't check that USERNAME has been set because it can be empty + local USERLOGIN=$(get_option USERLOGIN) + local USERPASSWORD=$(get_option USERPASSWORD) + local USERGROUPS=$(get_option USERGROUPS) + + if [ -n "$USERLOGIN" ] && [ -n "$USERPASSWORD" ] && [ -n "$USERGROUPS" ]; then + USERACCOUNT_DONE=1 + fi +} + +validate_filesystems() { + local mnts dev size fstype mntpt mkfs rootfound fmt + local usrfound efi_system_partition + local bootdev=$(get_option BOOTLOADER) + + unset TARGETFS + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE) + set -- ${mnts} + while [ $# -ne 0 ]; do + fmt="" + dev=$2; fstype=$3; size=$4; mntpt="$5"; mkfs=$6 + shift 6 + + if [ "$mntpt" = "/" ]; then + rootfound=1 + elif [ "$mntpt" = "/usr" ]; then + usrfound=1 + elif [ "$fstype" = "vfat" -a "$mntpt" = "/boot/efi" ]; then + efi_system_partition=1 + fi + if [ "$mkfs" -eq 1 ]; then + fmt="NEW FILESYSTEM: " + fi + if [ -z "$TARGETFS" ]; then + TARGETFS="${fmt}$dev ($size) mounted on $mntpt as ${fstype}\n" + else + TARGETFS="${TARGETFS}${fmt}${dev} ($size) mounted on $mntpt as ${fstype}\n" + fi + done + if [ -z "$rootfound" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +the mount point for the root filesystem (/) has not yet been configured." ${MSGBOXSIZE} + return 1 + elif [ -n "$usrfound" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +/usr mount point has been configured but is not supported, please remove it to continue." ${MSGBOXSIZE} + return 1 + elif [ -n "$EFI_SYSTEM" -a "$bootdev" != "none" -a -z "$efi_system_partition" ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +The EFI System Partition has not yet been configured, please create it\n +as FAT32, mountpoint /boot/efi and at least with 100MB of size." ${MSGBOXSIZE} + return 1 + fi + FILESYSTEMS_DONE=1 +} + +create_filesystems() { + local mnts dev mntpt fstype fspassno mkfs size rv uuid + + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE | sort -k 5) + set -- ${mnts} + while [ $# -ne 0 ]; do + dev=$2; fstype=$3; mntpt="$5"; mkfs=$6 + shift 6 + + # swap partitions + if [ "$fstype" = "swap" ]; then + swapoff $dev >/dev/null 2>&1 + if [ "$mkfs" -eq 1 ]; then + mkswap $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to create swap on ${dev}!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + fi + swapon $dev >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to activate swap on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + # Add entry for target fstab + uuid=$(blkid -o value -s UUID "$dev") + echo "UUID=$uuid none swap defaults 0 0" >>$TARGET_FSTAB + continue + fi + + if [ "$mkfs" -eq 1 ]; then + case "$fstype" in + btrfs) MKFS="mkfs.btrfs -f"; modprobe btrfs >$LOG 2>&1;; + ext2) MKFS="mke2fs -F"; modprobe ext2 >$LOG 2>&1;; + ext3) MKFS="mke2fs -F -j"; modprobe ext3 >$LOG 2>&1;; + ext4) MKFS="mke2fs -F -t ext4"; modprobe ext4 >$LOG 2>&1;; + f2fs) MKFS="mkfs.f2fs -f"; modprobe f2fs >$LOG 2>&1;; + vfat) MKFS="mkfs.vfat -F32"; modprobe vfat >$LOG 2>&1;; + xfs) MKFS="mkfs.xfs -f -i sparse=0"; modprobe xfs >$LOG 2>&1;; + esac + TITLE="Check $LOG for details ..." + INFOBOX "Creating filesystem $fstype on $dev for $mntpt ..." 8 60 + echo "Running $MKFS $dev..." >$LOG + $MKFS $dev >$LOG 2>&1; rv=$? + if [ $rv -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to create filesystem $fstype on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + fi + # Mount rootfs the first one. + [ "$mntpt" != "/" ] && continue + mkdir -p $TARGETDIR + echo "Mounting $dev on $mntpt ($fstype)..." >$LOG + mount -t $fstype $dev $TARGETDIR >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to mount $dev on ${mntpt}! check $LOG for errors." ${MSGBOXSIZE} + DIE 1 + fi + # Add entry to target fstab + uuid=$(blkid -o value -s UUID "$dev") + if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then + fspassno=0 + else + fspassno=1 + fi + echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB + done + + # mount all filesystems in target rootfs + mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE | sort -k 5) + set -- ${mnts} + while [ $# -ne 0 ]; do + dev=$2; fstype=$3; mntpt="$5" + shift 6 + [ "$mntpt" = "/" -o "$fstype" = "swap" ] && continue + mkdir -p ${TARGETDIR}${mntpt} + echo "Mounting $dev on $mntpt ($fstype)..." >$LOG + mount -t $fstype $dev ${TARGETDIR}${mntpt} >$LOG 2>&1 + if [ $? -ne 0 ]; then + DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \ +failed to mount $dev on $mntpt! check $LOG for errors." ${MSGBOXSIZE} + DIE + fi + # Add entry to target fstab + uuid=$(blkid -o value -s UUID "$dev") + if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then + fspassno=0 + else + fspassno=2 + fi + echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB + done +} + +mount_filesystems() { + for f in sys proc dev; do + [ ! -d $TARGETDIR/$f ] && mkdir $TARGETDIR/$f + echo "Mounting $TARGETDIR/$f..." >$LOG + mount --rbind /$f $TARGETDIR/$f >$LOG 2>&1 + done +} + +umount_filesystems() { + local mnts="$(grep -E '^MOUNTPOINT.*swap.*$' $CONF_FILE | sort -r -k 5)" + set -- ${mnts} + while [ $# -ne 0 ]; do + local dev=$2; local fstype=$3 + shift 6 + if [ "$fstype" = "swap" ]; then + echo "Disabling swap space on $dev..." >$LOG + swapoff $dev >$LOG 2>&1 + continue + fi + done + echo "Unmounting $TARGETDIR..." >$LOG + umount -R $TARGETDIR >$LOG 2>&1 +} + +log_and_count() { + local progress whole tenth + while read line; do + echo "$line" >$LOG + copy_count=$((copy_count + 1)) + progress=$((1000 * copy_count / copy_total)) + if [ "$progress" != "$copy_progress" ]; then + whole=$((progress / 10)) + tenth=$((progress % 10)) + printf "Progress: %d.%d%% (%d of %d files)\n" $whole $tenth $copy_count $copy_total + copy_progress=$progress + fi + done +} + +copy_rootfs() { + local _grub= _syspkg= + + if [ -n "$EFI_SYSTEM" ]; then + if [ $EFI_FW_BITS -eq 32 ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi + else + _grub="grub" + fi + + _syspkg="base-system" + + mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share + cp -a /usr/share/xbps.d $TARGETDIR/usr/share/ + cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys + mkdir -p $TARGETDIR/boot/grub + + _arch=$(xbps-uhelper arch) + + stdbuf -oL env XBPS_ARCH=${_arch} \ + xbps-install -r $TARGETDIR -y --repository=/var/cache/xbps/ ${_syspkg} ${_grub} 2>&1 | \ + DIALOG --title "Installing base system packages..." \ + --programbox 24 80 + if [ $? -ne 0 ]; then + DIE 1 + fi + xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1 + chroot $TARGETDIR xbps-reconfigure -fa +} + +install_packages() { + local _grub= _syspkg= + + if [ -n "$EFI_SYSTEM" ]; then + if [ $EFI_FW_BITS -eq 32 ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi + else + _grub="grub" + fi + + _syspkg="base-system" + + mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share + cp -a /usr/share/xbps.d $TARGETDIR/usr/share/ + cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys + mkdir -p $TARGETDIR/boot/grub + + _arch=$(xbps-uhelper arch) + + stdbuf -oL env XBPS_ARCH=${_arch} \ + xbps-install -r $TARGETDIR -SyU ${_syspkg} ${_grub} 2>&1 | \ + DIALOG --title "Installing base system packages..." \ + --programbox 24 80 + if [ $? -ne 0 ]; then + DIE 1 + fi + xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1 + chroot $TARGETDIR xbps-reconfigure -fa +} + +enable_service() { + ln -sf /etc/sv/$1 $TARGETDIR/etc/runit/runsvdir/default/$1 +} + +menu_install() { + ROOTPASSWORD_DONE="$(get_option ROOTPASSWORD)" + BOOTLOADER_DONE="$(get_option BOOTLOADER)" + + if [ -z "$ROOTPASSWORD_DONE" ]; then + DIALOG --msgbox "${BOLD}The root password has not been configured, \ +please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + elif [ -z "$BOOTLOADER_DONE" ]; then + DIALOG --msgbox "${BOLD}The disk to install the bootloader has not been \ +configured, please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + fi + + # Validate filesystems after making sure bootloader is done, + # so that specific checks can be made based on the selection + validate_filesystems || return 1 + + if [ -z "$FILESYSTEMS_DONE" ]; then + DIALOG --msgbox "${BOLD}Required filesystems were not configured, \ +please do so before starting the installation.${RESET}" ${MSGBOXSIZE} + return 1 + fi + + # Validate useraccount. All parameters must be set (name, password, login name, groups). + validate_useraccount + + if [ -z "$USERACCOUNT_DONE" ]; then + DIALOG --yesno "${BOLD}The user account is not set up properly.${RESET}\n\n +${BOLD}${RED}WARNING: no user will be created. You will only be able to login \ +with the root user in your new system.${RESET}\n\n +${BOLD}Do you want to continue?${RESET}" 10 60 || return + fi + + DIALOG --yesno "${BOLD}The following operations will be executed:${RESET}\n\n +${BOLD}${TARGETFS}${RESET}\n +${BOLD}${RED}WARNING: data on partitions will be COMPLETELY DESTROYED for new \ +filesystems.${RESET}\n\n +${BOLD}Do you want to continue?${RESET}" 20 80 || return + unset TARGETFS + + # Create and mount filesystems + create_filesystems + + SOURCE_DONE="$(get_option SOURCE)" + # If source not set use defaults. + if [ "$(get_option SOURCE)" = "local" -o -z "$SOURCE_DONE" ]; then + mount_filesystems + copy_rootfs + else + # mount required fs + mount_filesystems + # network install, use packages. + install_packages + fi + + INFOBOX "Applying installer settings..." 4 60 + + # copy target fstab. + install -Dm644 $TARGET_FSTAB $TARGETDIR/etc/fstab + # Mount /tmp as tmpfs. + echo "tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TARGETDIR/etc/fstab + + + # set up keymap, locale, timezone, hostname, root passwd and user account. + set_keymap + set_locale + set_timezone + set_hostname + set_rootpassword + set_useraccount + + # Copy /etc/skel files for root. + cp $TARGETDIR/etc/skel/.[bix]* $TARGETDIR/root + + NETWORK_DONE="$(get_option NETWORK)" + # network settings for target + if [ -n "$NETWORK_DONE" ]; then + local net="$(get_option NETWORK)" + set -- ${net} + local _dev="$1" _type="$2" _ip="$3" _gw="$4" _dns1="$5" _dns2="$6" + if [ -z "$_type" ]; then + # network type empty??!!! + : + elif [ "$_type" = "dhcp" ]; then + if $(echo $_dev|egrep -q "^wl.*" 2>/dev/null); then + cp /etc/wpa_supplicant/wpa_supplicant.conf $TARGETDIR/etc/wpa_supplicant + ln -sf /etc/sv/wpa_supplicant $TARGETDIR/etc/runit/runsvdir/default/wpa_supplicant + fi + enable_service dhcpcd + elif [ -n "$_dev" -a "$_type" = "static" ]; then + # static IP through dhcpcd. + mv $TARGETDIR/etc/dhcpcd.conf $TARGETDIR/etc/dhcpcd.conf.orig + echo "# Static IP configuration set by the void-installer for $_dev." \ + >$TARGETDIR/etc/dhcpcd.conf + echo "interface $_dev" >>$TARGETDIR/etc/dhcpcd.conf + echo "static ip_address=$_ip" >>$TARGETDIR/etc/dhcpcd.conf + echo "static routers=$_gw" >>$TARGETDIR/etc/dhcpcd.conf + echo "static domain_name_servers=$_dns1 $_dns2" >>$TARGETDIR/etc/dhcpcd.conf + enable_service dhcpcd + fi + fi + + if [ -d $TARGETDIR/etc/sudoers.d ]; then + USERLOGIN="$(get_option USERLOGIN)" + if [ -z "$(echo $(get_option USERGROUPS) | grep -w wheel)" -a -n "$USERLOGIN" ]; then + # enable sudo for primary user USERLOGIN who is not member of wheel + echo "# Enable sudo for login '$USERLOGIN'" > "$TARGETDIR/etc/sudoers.d/$USERLOGIN" + echo "$USERLOGIN ALL=(ALL:ALL) ALL" >> "$TARGETDIR/etc/sudoers.d/$USERLOGIN" + else + # enable the sudoers entry for members of group wheel + echo "%wheel ALL=(ALL:ALL) ALL" > "$TARGETDIR/etc/sudoers.d/wheel" + fi + unset USERLOGIN + fi + + # clean up polkit rule - it's only useful in live systems + rm -f $TARGETDIR/etc/polkit-1/rules.d/void-live.rules + + # enable text console for grub if chosen + if [ "$(get_option TEXTCONSOLE)" = "1" ]; then + sed -i $TARGETDIR/etc/default/grub \ + -e 's|#\(GRUB_TERMINAL_INPUT\).*|\1=console|' \ + -e 's|#\(GRUB_TERMINAL_OUTPUT\).*|\1=console|' + fi + + # install bootloader. + set_bootloader + sync && sync && sync + + # unmount all filesystems. + umount_filesystems + + # installed successfully. + DIALOG --yesno "${BOLD}EvolutionOS has been installed successfully!${RESET}\n +Do you want to reboot the system?" ${YESNOSIZE} + if [ $? -eq 0 ]; then + shutdown -r now + else + return + fi +} + +menu_source() { + local src= + + DIALOG --title " Select installation source " \ + --menu "$MENULABEL" 8 70 0 \ + "Local" "Packages from ISO image" \ + "Network" "Base system only, downloaded from official repository" + case "$(cat $ANSWER)" in + "Local") src="local";; + "Network") src="net"; + if [ -z "$NETWORK_DONE" ]; then + if test_network; then + menu_network + fi + fi;; + *) return 1;; + esac + SOURCE_DONE=1 + set_option SOURCE $src +} + +menu() { + local AFTER_HOSTNAME + if [ -z "$DEFITEM" ]; then + DEFITEM="Keyboard" + fi + + if xbps-uhelper arch | grep -qe '-musl$'; then + AFTER_HOSTNAME="Timezone" + DIALOG --default-item $DEFITEM \ + --extra-button --extra-label "Settings" \ + --title " EvolutionOS installation menu " \ + --menu "$MENULABEL" 10 70 0 \ + "Keyboard" "Set system keyboard" \ + "Network" "Set up the network" \ + "Source" "Set source installation" \ + "Hostname" "Set system hostname" \ + "Timezone" "Set system time zone" \ + "RootPassword" "Set system root password" \ + "UserAccount" "Set primary user name and password" \ + "BootLoader" "Set disk to install bootloader" \ + "Partition" "Partition disk(s)" \ + "Filesystems" "Configure filesystems and mount points" \ + "Install" "Start installation with saved settings" \ + "Exit" "Exit installation" + else + AFTER_HOSTNAME="Locale" + DIALOG --default-item $DEFITEM \ + --extra-button --extra-label "Settings" \ + --title " EvolutionOS installation menu " \ + --menu "$MENULABEL" 10 70 0 \ + "Keyboard" "Set system keyboard" \ + "Network" "Set up the network" \ + "Source" "Set source installation" \ + "Hostname" "Set system hostname" \ + "Locale" "Set system locale" \ + "Timezone" "Set system time zone" \ + "RootPassword" "Set system root password" \ + "UserAccount" "Set primary user name and password" \ + "BootLoader" "Set disk to install bootloader" \ + "Partition" "Partition disk(s)" \ + "Filesystems" "Configure filesystems and mount points" \ + "Install" "Start installation with saved settings" \ + "Exit" "Exit installation" + fi + + if [ $? -eq 3 ]; then + # Show settings + cp $CONF_FILE /tmp/conf_hidden.$$; + sed -i "s/^ROOTPASSWORD.*/ROOTPASSWORD <-hidden->/" /tmp/conf_hidden.$$ + sed -i "s/^USERPASSWORD.*/USERPASSWORD <-hidden->/" /tmp/conf_hidden.$$ + DIALOG --title "Saved settings for installation" --textbox /tmp/conf_hidden.$$ 14 60 + rm /tmp/conf_hidden.$$ + return + fi + + case $(cat $ANSWER) in + "Keyboard") menu_keymap && [ -n "$KEYBOARD_DONE" ] && DEFITEM="Network";; + "Network") menu_network && [ -n "$NETWORK_DONE" ] && DEFITEM="Source";; + "Source") menu_source && [ -n "$SOURCE_DONE" ] && DEFITEM="Hostname";; + "Hostname") menu_hostname && [ -n "$HOSTNAME_DONE" ] && DEFITEM="$AFTER_HOSTNAME";; + "Locale") menu_locale && [ -n "$LOCALE_DONE" ] && DEFITEM="Timezone";; + "Timezone") menu_timezone && [ -n "$TIMEZONE_DONE" ] && DEFITEM="RootPassword";; + "RootPassword") menu_rootpassword && [ -n "$ROOTPASSWORD_DONE" ] && DEFITEM="UserAccount";; + "UserAccount") menu_useraccount && [ -n "$USERLOGIN_DONE" ] && [ -n "$USERPASSWORD_DONE" ] \ + && DEFITEM="BootLoader";; + "BootLoader") menu_bootloader && [ -n "$BOOTLOADER_DONE" ] && DEFITEM="Partition";; + "Partition") menu_partitions && [ -n "$PARTITIONS_DONE" ] && DEFITEM="Filesystems";; + "Filesystems") menu_filesystems && [ -n "$FILESYSTEMS_DONE" ] && DEFITEM="Install";; + "Install") menu_install;; + "Exit") DIE;; + *) DIALOG --yesno "Abort Installation?" ${YESNOSIZE} && DIE + esac +} + +if ! command -v dialog >/dev/null; then + echo "ERROR: missing dialog command, exiting..." + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "evolution-installer must run as root" 1>&2 + exit 1 +fi + +# +# main() +# +DIALOG --title "${BOLD}${RED} EvolutionOS Installer ${RESET}" --msgbox "\n +Welcome to the EvolutionOS installer. A simple and minimal \ +Linux distribution built to be as fast as possible.\n\n +The installation should be pretty straightforward.\n\n +${BOLD}https://tracker-friendly.github.io${RESET}\n\n" 16 80 + +while true; do + menu +done + +exit 0 +# vim: set ts=4 sw=4 et: diff --git a/include/usr/bin/evolution-installer-beta b/include/usr/bin/evolution-installer-beta new file mode 100755 index 0000000..38adb84 --- /dev/null +++ b/include/usr/bin/evolution-installer-beta @@ -0,0 +1,239 @@ +#!/bin/bash + +if [[ $(id -u) -eq 0 ]]; then + : +else + dialog --title "Run as root" --msgbox "Please run the installer as root!" 0 0 + exit 1 +fi + +if [[ -x /sys/firmware/efi ]]; then + uefi=true +else + uefi=false +fi + +dialog --clear --title "Launguage" --menu "Select a language:" 15 50 10 "en_GB" "English UK" "en_US" "English US" + +if [[ $? = 1 ]]; then + exit 1 +fi + +dialog --title "Welcome" --msgbox "Welcome to the EvolutionOS installer! \n\nThis installer is meant to be straightforward, no need for technical skill. \n\nPress enter to select buttons, tab to move between text boxes, and left / right to move between buttons." 0 0 + +get_disk_type() { + local disk_name="$1" + + if [[ "$disk_name" =~ ^sd.$ ]]; then + echo "Hard Disk $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^emmc.+$ ]]; then + echo "Internal Memory $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^nvme.+$ ]]; then + echo "SSD $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^fd.+$ ]]; then + echo "Floppy Disk $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + elif [[ "$disk_name" =~ ^sr.$ ]]; then + echo "Disk Drive $(echo "${disk_name: -1}" | tr '[:lower:]' '[:upper:]')" + else + echo "Unknown" + fi +} + +# Getting the disk names using lsblk and awk + +disk_names=$(lsblk --list --nodeps -o NAME | awk 'NR>1') + +# Function to check if the disk is writable +is_disk_writable() { + local disk_name="$1" + touch "/mnt/$disk_name" &>/dev/null + local writable=$? + rm "/mnt/$disk_name" &>/dev/null + return $writable +} + +# Loop through each disk name and determine its type +while true; do + # Creating the list for dialog + list=() + for disk_name in $disk_names; do + disk_type=$(get_disk_type "$disk_name") + list+=( "$disk_name" "$disk_type" ) + done + + # Using dialog to display the list + dialog --clear --title "Disk List" --menu "Select a disk:" 15 50 10 "${list[@]}" 2>/tmp/disk_choice + + if [[ $? = 1 ]]; then + exit 1 + fi + + # Reading the choice made by the user + choice=$(cat /tmp/disk_choice) + rm /tmp/disk_choice + + # Check if the disk is writable + if ! is_disk_writable "$choice"; then + dialog --title "Disk Not Writable" --msgbox "The selected disk is not writable. Please choose another disk." 8 50 + continue + fi + + # Check if the disk has partitions + partitions=$(lsblk "/dev/$choice" | grep -c "part") + if [ "$partitions" -gt 0 ]; then + dialog --title "Disk with Partitions" --yesno "The selected disk contains data. Do you want to wipe the disk?" 8 50 + response=$? + if [ "$response" -eq 0 ]; then + # User chose Yes, proceed to wipe the disk + # Add your wipe disk command here + echo "Ok, continuing with: $choice" + break + else + # User chose No, return to the selection menu + continue + fi + else + # Disk has no partitions, continue with further actions + echo "Ok, continuing with: $choice" + # Add your additional actions here + # ... + fi + + # Break out of the loop if the user didn't choose to wipe the disk and there are no partitions + break +done + +for i in $(lsblk --list -o NAME /dev/$choice | awk 'NR>2'); do + umount /dev/$i +done + +sfdisk --delete /dev/$choice +wipefs -a /dev/$choice +sgdisk -Z /dev/$choice + +dialog --yesno "Would you like to use the recommended disk partitioning?" 0 0 +if [[ $? = 0 ]]; then + dialog --msgbox "Starting partitioning..." 0 0 + if [[ $uefi = true ]]; then + sfdisk -X gpt -W always /dev/$choice </tmp/fileselect + if [[ $? = 1 ]]; then + dialog --msgbox "Operation cancled" + exit 1 + fi + filesystem=$(cat /tmp/fileselect) + mkfs.$filesystem /dev/$part2 | dialog --title "Creating file system..." --programbox 24 80 + mount /dev/$part2 /mnt + mkdir -p /mnt/boot/efi + mount /dev/$part1 /mnt/boot/efi + else + echo -e "o\nw" | fdisk /dev/$choice + sfdisk -X mbr -W always /dev/$choice </tmp/fileselect + if [[ $? = 1 ]]; then + dialog --msgbox "Operation cancled" + exit 1 + fi + filesystem=$(cat /tmp/fileselect) + partmpt1=$(lsblk -n -o NAME --list /dev/$choice | sed -n '2p') + mkfs.$filesystem /dev/$part1 | dialog --title "Creating file system..." --programbox 24 80 + fi +else + dialog --msgbox "Ok, you will be dropped into a CLI. Please mount the filesystem, when done, at \"/mnt/\". Note that anything except the default partition disk (ESP, Optional Swap, RootFS) is not offically supported and may not work. Enter exit when you are done." 0 0 + bash + dialog --msgbox "Welcome back! Continuing installation..." 0 0 +fi + +for f in sys proc dev; do + [ ! -d /mnt/$f ] && mkdir /mnt/$f + echo "Mounting /mnt/$f..." + mount --rbind /$f /mnt/$f +done + +dialog --clear --title "Select install type" --menu "Which installation type would you like to you:" 0 0 0 "local" "Install without internet" "network" "Download from internet" 2>/tmp/installtype +installtype=$(cat /tmp/installtype) + +if [ $uefi = true ]; then + if [ $(uname -m) = "i686" ]; then + _grub="grub-i386-efi" + else + _grub="grub-x86_64-efi" + fi +else + _grub="grub" +fi + +mkdir -p /mnt/var/db/xbps/keys /mnt/usr/share +cp -a /usr/share/xbps.d /mnt/usr/share/ +cp /var/db/xbps/keys/*.plist /mnt/var/db/xbps/keys +mkdir -p /mnt/boot/grub + +if [[ $installtype = "local" ]]; then + xbps-install -S -y -r /mnt -i -R /var/cache/xbps/ base-system $_grub | dialog --title "Installing base system..." --programbox 24 80 +else + xbps-install -S -y -r /mnt -R https://evolution-linux.github.io/pkg base-system $_grub | dialog --title "Installing base system..." --programbox 24 80 +fi + +xbps-reconfigure -r /mnt -f base-system +chroot /mnt xbps-reconfigure -fa | dialog --title "Reconfiguring packages..." --programbox 24 80 + +while true; do + dialog --title "Password" --clear --insecure --passwordbox "Enter Admin (root) password. For security reasons, you cannot log in as admin. Press enter to submit." 0 0 2>/tmp/rootpasswd + rootpasswd="$(cat /tmp/rootpasswd)" + passwd -R /mnt </tmp/usershort + shusername="$(cat /tmp/usershort)" + chroot /mnt "useradd -m $shusername" + if [[ $? = 1 ]]; then + dialog --title "Illegal characters" --msgbox "You cannot have those characters in a shorthand username. Please enter a new one." + continue + else + break + fi +done + +dialog --title "Username" --clear --inputbox "Enter display username." 0 0 2>/tmp/dpusername +dpusername=$(cat /tmp/dpusername) +while true; do + dialog --title "Password" --clear --insecure --passwordbox "Enter user password" 0 0 2>/tmp/userpasswd + userpasswd="$(cat /tmp/userpasswd)" + passwd -R /mnt < + + + + public-key + LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF3ay9lR3dKMjRFczBLd3lMSXZqVApjWEtLYjlqR0NwTWZhaTJxQThhVTRLY250TjRWVFFQVDNrc0lsbEZueXFsUURFYlA3MmxtZGVrOUJjaXZTWjNXCmJ1SlNpeEpqL3hyeTF0ZW9qNSsyb3hxdTNHNUNIdEtjVzVwYnlGeUtzaGV6a2gvbk0wRHZlMXI5WndXdkgrbEoKMnRvWXMya2pYY2Irc21pSHJSQUxwRTZHaExxZGVjQnVLNGxXdHhqVWJYQmhLN29YR2NqOXo1MDNlcEFHaHkwbgpVVVAwcjdhTmNINDBiUC9vTXpSSTh5eUV6bnh6OE56VG5EVnVlc3BCR1VrK2J2VzdoZXUrV3lDamZ6QXJLY2tWCm5vQ0xDSVdoYVZPcEw2TTVZVkVRS1lZTUFzZ3VNRVVWSWpwRCtldlpXMUs1QmRjWjdyWG54YVdpWTVKOVdBaVYKVmtJaDkvc3BTNUFGTzU4RkgrejRrOU82SEYvQytTc0d6eVhDVWJaY0UrWUtubVdVYUdXMnl2OFA1S0tDWnZkZApFNW55UTZvS3gvWjhiT1VUV2JOSktpbXZSRHNmRmxhZDZSM0VqWWJUbkFiQTFsNkg0NWhGTmdxdmkrQnprUDlUCmJsU2NFSWRkNU40YXRPek1HclhkQm0yUW44b0NrOWZ3K0ZJVmJkYjZkV1cxQkhaMmFiUmtJcW94b0traWRNQUwKcFVBQ2s4NXpzWXZ5TllsVmp2MEl5VStKMUx6bUZsWWRYemswUGdBZ2J0UlFOMWg3S2t3d3NrSVMwWnlwekMregplMnRQRjZLMUwzUGZrQXZsUE43amJVSGxKUzRTM3FscTJpUlhyRU5ZNkd5cm9vTkxNaXcveUlDWEUvSjlscnNBCjBmejNTamREeUU5R1hQUUJ2aXNCaE1rQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= + public-key-size + 4096 + signature-by + Tracker-Friendly + + diff --git a/isolinux/isolinux.cfg.in b/isolinux/isolinux.cfg.in new file mode 100644 index 0000000..8535322 --- /dev/null +++ b/isolinux/isolinux.cfg.in @@ -0,0 +1,58 @@ +UI vesamenu.c32 +PROMPT 0 +TIMEOUT 150 +ONTIMEOUT linux + +MENU TABMSG Press ENTER to boot or TAB to edit a menu entry +MENU AUTOBOOT BIOS default device boot in # second{,s}... +MENU BACKGROUND @@SPLASHIMAGE@@ +MENU WIDTH 78 +MENU MARGIN 1 +MENU ROWS 9 +MENU VSHIFT 2 +MENU TIMEOUTROW 13 +MENU TABMSGROW 2 +MENU CMDLINEROW 16 +MENU HELPMSGROW 20 +MENU HELPMSGENDROW 34 + +MENU COLOR title * #FF5255FF * +MENU COLOR border * #00000000 #00000000 none +MENU COLOR sel * #ffffffff #FF5255FF * + +LABEL linux +MENU LABEL @@BOOT_TITLE@@ @@KERNVER@@ @@ARCH@@ +KERNEL /boot/vmlinuz +APPEND initrd=/boot/initrd root=live:CDLABEL=VOID_LIVE init=/sbin/init ro rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ + +LABEL linuxram +MENU LABEL @@BOOT_TITLE@@ @@KERNVER@@ @@ARCH@@ (RAM) +KERNEL /boot/vmlinuz +APPEND initrd=/boot/initrd root=live:CDLABEL=VOID_LIVE init=/sbin/init ro rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ rd.live.ram + +LABEL linuxa11y +MENU LABEL @@BOOT_TITLE@@ @@KERNVER@@ @@ARCH@@ with ^speech +KERNEL /boot/vmlinuz +APPEND initrd=/boot/initrd root=live:CDLABEL=VOID_LIVE init=/sbin/init ro rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin + +LABEL linuxa11yram +MENU LABEL @@BOOT_TITLE@@ @@KERNVER@@ @@ARCH@@ with speech (^RAM) +KERNEL /boot/vmlinuz +APPEND initrd=/boot/initrd root=live:CDLABEL=VOID_LIVE init=/sbin/init ro rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin rd.live.ram + +LABEL c +MENU LABEL Boot first HD found by BIOS +COM32 chain.c32 +APPEND hd0 + +LABEL memtest +MENU LABEL Run Memtest86+ (RAM test) +LINUX /boot/memtest.bin + +LABEL reboot +MENU LABEL Reboot +COM32 reboot.c32 + +LABEL poweroff +MENU LABEL Power Off +COM32 poweroff.c32 diff --git a/keys/3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist b/keys/3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist new file mode 100644 index 0000000..41bc2cb --- /dev/null +++ b/keys/3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist @@ -0,0 +1,12 @@ + + + + + public-key + LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFvM1Nrc2p5N01PMmc4UWxsZjdCVQp1aXhFUWlqN3FOSVJrU0hrWWw4SGxxd1hOczFnK1FzbzhGV3dSbDNMbUpTVW5wT1BaOG1sdVdSajd4Y2pLbnVJCnhPRjBtQS8vM0lzTnVId2dYV2RLL0JiT29wNzFLZmt4aEE0WjhwK0hRbmhLMThxUkFPbG9xOGJ6WXZhaGI2NmEKemdWVTVFM1JzRDU4V0M2ZTFOUVdSSGpiMG1TM2h6M1NxVWVWZFVMT20zVzZBRTdYdWlVQVJOSEdyY1ljMXkyKwpxNjBKWHMrVk5sRlMwaGdDdnpqS3phMVg5cWtzQndzTmdaRlhBcXN1MGFKRndYSTEvM2R4ZWxBcUZFbnRMWVFSCjA4NHpaTDFmWDVRMWlacGNEaHVhTWZVREVZQjA4UzdKTTBYKytibkxxVnphVTZzc0RXdGtzbFJaNjNaVStISTUKemk5a0pyc25LcU5Pa3BKSnJTUkRyMGFvRjV2RDRwN20vYWdZKzdTRk5aaDZzOUJ5V0x3NDVFdytwalVVUmp5aQp6T01TSFhEM3YzczhFdzZkV29wbTVQTGUvUEgzZWFiMEVnbG9yVDZhYmRwaCtaVG4zaUxMWVVkSGNmQ1FDN01GCkNmVGl1TWt4SkJpaCtoOEhKaUlBdmpDZjVxdjZiaFpEUHpGRzAwbEpYRUZwNHRpbGp6eTFmbitiMkdLY3BDOWQKUUs4TEc3M0RFaXhacHBmU09IU09MMWYxVlBzZTBRdnl6d2RWc0xzR0dqV0FaZkw4WUdVZDl4Y20yeW5tVzFuNgpKTjl6NE9oZ3lRa21mNUFFUXpYSUxQR0d1MlREUVh5c05IRG0vUnRMMHJPN3cxbFVKSTVYOW1kbEZYd0xUWHI3ClYrU25aK3U5VCtFREg1NTV6WDJDZTgwQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= + public-key-size + 4096 + signature-by + Void Linux + + diff --git a/keys/60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist b/keys/60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist new file mode 100644 index 0000000..c1e82a7 --- /dev/null +++ b/keys/60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist @@ -0,0 +1,12 @@ + + + + + public-key + LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF2clN6QlpNdmd2T0NJM0FYYk9qYQoycktSa0pTVE0zYy9FalRJZ0NnRFhndW05M0JQQ3RZOE1jRlZvQ1U0T2lYSEdmVG1xMzlCVk5wTHZMSEw5S2sxCnAyNzhTQmhYVk90YkIyRVZtREtudmZJREVUbGRMR3plN3JaTlJKZHR1TjJtWi9UVnJVQjlTMHlRYytJdWY0aHYKMytEOTdWSWRUSkhBN0FTcjA0MjhwcEVHSkd3U1NoWTJYSm05RDVJMEV1R1JXYzE0TUVHN2RJS0ppWWlNMG5FNAp0WW8yL3ZINElGVEhkblZBM2dZaVp5RG5idUNBUi84RVNmVVRVMTNTTkNPZGJ1ZGYzRDVCY3krVWlNREpJM1llCjRNRktCclQ5WmhaK0dzWEJaWTQ4MmxxaVppNkNMNXB0YzlJUUZmOC9lS1phOGphdGtpVkZWZ3JLZU5Sak9UeE4KZldTdTJua3hHTlgrYmhYWXRoaUdXbUpFWThjQ0FQeUZOK0x2NVJldEsyNTZnZGNiMnNrbUVxZWZ2MnpQQyt3VgpXQmJkSDViRDRiWmpuME42Wmw4MXJ2NVJ6RHZudmYrdkQxNGFGVWJaOFFGcXU3NVBiTDR3Nm1ZTTRsZE0vZzBSCjZOWEU4QXo5Qnd4MnREZlllS3V1dHcxRXBQbTJZdkZ5VFViMWNveUF1VEdSeUFhcDFVVEh2ZzlsaFBJSm1oRlEKSjVrQ2cxcUQ3QTMxV2wwUmxuZTZoZ0dvMFpaTko1Y0pNL3YvelNUS0pjdUZnd283SDBoT0dpbDZEZm84OUI0agpHOTZBQ3lQUytEVktQRlhSWXdqL0FrYkhwYVEyZjFGTUFvU3BCcXVEcUhoM3VrazcxS1g2ajE5dDBpRjhEUUxyCnZ0RlNTZElqREEwMmx3ZVY5TmFRcFdzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= + public-key-size + 4096 + signature-by + Void Linux + + diff --git a/lib.sh b/lib.sh new file mode 100755 index 0000000..899614c --- /dev/null +++ b/lib.sh @@ -0,0 +1,354 @@ +#!/bin/sh + +# This contains the COMPLETE list of binaries that this script needs +# to function. The only exception is the QEMU binary since it is not +# known in advance which one wil be required. +readonly LIBTOOLS="cp echo cat printf which mountpoint mount umount modprobe" +readonly HOSTARCH=$(xbps-uhelper arch) + +is_target_native() { + # Because checking whether the target is runnable is ugly, stuff + # it into a single function. That makes it easy to check anywhere. + local target_arch + + target_arch="$1" + # this will cover most + if [ "${target_arch%-musl}" = "${HOSTARCH%-musl}" ]; then + return 0 + fi + + case "$HOSTARCH" in + # ppc64le has no 32-bit variant, only runs its own stuff + ppc64le*) return 1 ;; + # x86_64 also runs i686 + x86_64*) test -z "${target_arch##*86*}" ;; + # aarch64 also runs armv* + aarch64*) test -z "${target_arch##armv*}" ;; + # bigendian ppc64 also runs ppc + ppc64*) test "${target_arch%-musl}" = "ppc" ;; + # anything else is just their own + *) return 1 ;; + esac + + return $? +} + +version() ( + set +u + [ -n "$PROGNAME" ] && printf "%s " "$PROGNAME" + echo "$(cat ./version) ${MKLIVE_REV:-"$(git -c safe.directory="$(pwd)" rev-parse --short HEAD 2> /dev/null)"}" +) + +info_msg() { + # This function handles the printing that is bold within all + # scripts. This is a convenience function so that the rather ugly + # looking ASCII escape codes live in only one place. + printf "\033[1m%s\n\033[m" "$@" +} + +die() { + # This function is registered in all the scripts to make sure that + # the important mounts get cleaned up and the $ROOTFS location is + # removed. + printf "FATAL: %s\n" "$@" + umount_pseudofs + [ -d "$ROOTFS" ] && rm -rf "$ROOTFS" + exit 1 +} + +check_tools() { + # All scripts within mklive declare the tools they will use in a + # variable called "REQTOOLS". This function checks that these + # tools are available and prints out the path to each tool that + # will be used. This can be useful to figure out what is broken + # if a different version of something is used than was expected. + for tool in $LIBTOOLS $REQTOOLS ; do + if ! which "$tool" > /dev/null ; then + die "Required tool $tool is not available on this system!" + fi + done + + info_msg "The following tools will be used:" + for tool in $LIBTOOLS $REQTOOLS ; do + which "$tool" + done +} + +mount_pseudofs() { + # This function ensures that the psuedofs mountpoints are present + # in the chroot. Strictly they are not necessary to have for many + # commands, but bind-mounts are cheap and it isn't too bad to just + # mount them all the time. + for f in dev proc sys; do + # In a naked chroot there is nothing to bind the mounts to, so + # we need to create directories for these first. + [ ! -d "$ROOTFS/$f" ] && mkdir -p "$ROOTFS/$f" + if ! mountpoint -q "$ROOTFS/$f" ; then + # It is VERY important that this only happen if the + # pseudofs isn't already mounted. If it already is then + # this is virtually impossible to troubleshoot because it + # looks like the subsequent umount just isn't working. + mount -r --rbind /$f "$ROOTFS/$f" --make-rslave + fi + done + if ! mountpoint -q "$ROOTFS/tmp" ; then + mkdir -p "$ROOTFS/tmp" + mount -o mode=0755,nosuid,nodev -t tmpfs tmpfs "$ROOTFS/tmp" + fi +} + +umount_pseudofs() { + # This function cleans up the mounts in the chroot. Failure to + # clean up these mounts will prevent the tmpdir from being + # deletable instead throwing the error "Device or Resource Busy". + # The '-f' option is passed to umount to account for the + # contingency where the psuedofs mounts are not present. + if [ -d "${ROOTFS}" ]; then + for f in dev proc sys; do + umount -R -f "$ROOTFS/$f" >/dev/null 2>&1 + done + fi + umount -f "$ROOTFS/tmp" >/dev/null 2>&1 +} + +run_cmd_target() { + info_msg "Running $* for target $XBPS_TARGET_ARCH ..." + if is_target_native "$XBPS_TARGET_ARCH"; then + # This is being run on the same architecture as the host, + # therefore we should set XBPS_ARCH. + if ! eval XBPS_ARCH="$XBPS_TARGET_ARCH" "$@" ; then + die "Could not run command $*" + fi + else + # This is being run on a foriegn arch, therefore we should set + # XBPS_TARGET_ARCH. In this case XBPS will not attempt + # certain actions and will require reconfiguration later. + if ! eval XBPS_TARGET_ARCH="$XBPS_TARGET_ARCH" "$@" ; then + die "Could not run command $*" + fi + fi +} + +run_cmd() { + # This is a general purpose function to run commands that a user + # may wish to see. For example its useful to see the tar/xz + # pipeline to not need to delve into the scripts to see what + # options its set up with. + info_msg "Running $*" + eval "$@" +} + +run_cmd_chroot() { + # General purpose chroot function which makes sure the chroot is + # prepared. This function takes 2 arguments, the location to + # chroot to and the command to run. + + # This is an idempotent function, it is safe to call every time + # before entering the chroot. This has the advantage of making + # execution in the chroot appear as though it "Just Works(tm)". + register_binfmt + + # Before we step into the chroot we need to make sure the + # pseudo-filesystems are ready to go. Not all commands will need + # this, but its still a good idea to call it here anyway. + mount_pseudofs + + # With assurance that things will run now we can jump into the + # chroot and run stuff! + chroot "$1" sh -c "$2" +} + +cleanup_chroot() { + # This function cleans up the chroot shims that are used by QEMU + # to allow builds on alien platforms. It takes no arguments but + # expects the global $ROOTFS variable to be set. + + # Un-Mount the pseudofs mounts if they were mounted + umount_pseudofs +} + +register_binfmt() { + # This function sets up everything that is needed to be able to + # chroot into a ROOTFS and be able to run commands there. This + # really matters on platforms where the host architecture is + # different from the target, and you wouldn't be able to run + # things like xbps-reconfigure -a. This function is idempotent + # (You can run it multiple times without modifying state). This + # function takes no arguments, but does expect the global variable + # $XBPS_TARGET_ARCH to be set. + + # This select sets up the "magic" bytes in /proc that let the + # kernel select an alternate interpreter. More values for this + # map can be obtained from here: + # https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh + + # If the XBPS_TARGET_ARCH is unset but the PLATFORM is known, it + # may be possible to set the architecture from the static + # platforms map. + if [ -z "$XBPS_TARGET_ARCH" ] && [ ! -z "$PLATFORM" ] ; then + set_target_arch_from_platform + fi + + # In the special case where the build is native we can return + # without doing anything else + # This is only a basic check for identical archs, with more careful + # checks below for cases like ppc64 -> ppc and x86_64 -> i686. + _hostarch="${HOSTARCH%-musl}" + _targetarch="${XBPS_TARGET_ARCH%-musl}" + if [ "$_hostarch" = "$_targetarch" ] ; then + return + fi + + case "${_targetarch}" in + armv*) + # TODO: detect aarch64 hosts that run 32 bit ARM without qemu (some cannot) + if ( [ "${_targetarch}" = "armv6l" ] && [ "${_hostarch}" = "armv7l" ] ) ; then + return + fi + if [ "${_targetarch}" = "armv5tel" -a \ + \( "${_hostarch}" = "armv6l" -o "${_hostarch}" = "armv7l" \) ] ; then + return + fi + _cpu=arm + _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" + ;; + aarch64) + _cpu=aarch64 + _magic="\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff" + ;; + ppc64le) + _cpu=ppc64le + _magic="\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00" + ;; + ppc64) + _cpu=ppc64 + _magic="\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff" + ;; + ppc) + if [ "$_hostarch" = "ppc64" ] ; then + return + fi + _cpu=ppc + _magic="\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff" + ;; + mipsel) + if [ "$_hostarch" = "mips64el" ] ; then + return + fi + _cpu=mipsel + _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00" + _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" + ;; + x86_64) + _cpu=x86_64 + _magic="\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" + _mask="\xff\xff\xff\xff\xff\xfe\xfe\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" + ;; + i686) + if [ "$_hostarch" = "x86_64" ] ; then + return + fi + _cpu=i386 + _magic="\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00" + _mask="\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" + ;; + *) + die "Unknown target architecture!" + ;; + esac + + # For builds that do not match the host architecture, the correct + # qemu binary will be required. + QEMU_BIN="qemu-${_cpu}-static" + if ! $QEMU_BIN -version >/dev/null 2>&1; then + die "$QEMU_BIN binary is missing in your system, exiting." + fi + + # In order to use the binfmt system the binfmt_misc mountpoint + # must exist inside of proc + if ! mountpoint -q /proc/sys/fs/binfmt_misc ; then + modprobe -q binfmt_misc + mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null + fi + + # Only register if the map is incomplete + if [ ! -f /proc/sys/fs/binfmt_misc/qemu-$_cpu ] ; then + echo ":qemu-$_cpu:M::$_magic:$_mask:/usr/bin/$QEMU_BIN:F" > /proc/sys/fs/binfmt_misc/register 2>/dev/null + fi +} + +set_target_arch_from_platform() { + # This function maintains a lookup from platform to target + # architecture. This is required for scripts that need to know + # the target architecture, but don't necessarily need to know it + # internally (i.e. only run_cmd_chroot). + case "$PLATFORM" in + bananapi*) XBPS_TARGET_ARCH="armv7l";; + beaglebone*) XBPS_TARGET_ARCH="armv7l";; + cubieboard2*|cubietruck*) XBPS_TARGET_ARCH="armv7l";; + odroid-u2*) XBPS_TARGET_ARCH="armv7l";; + odroid-c2*) XBPS_TARGET_ARCH="aarch64";; + rpi-aarch64*) XBPS_TARGET_ARCH="aarch64";; + rpi-armv7l*) XBPS_TARGET_ARCH="armv7l";; + rpi-armv6l*) XBPS_TARGET_ARCH="armv6l";; + ci20*) XBPS_TARGET_ARCH="mipsel";; + i686*) XBPS_TARGET_ARCH="i686";; + x86_64*) XBPS_TARGET_ARCH="x86_64";; + GCP*) XBPS_TARGET_ARCH="x86_64";; + pinebookpro*) XBPS_TARGET_ARCH="aarch64";; + pinephone*) XBPS_TARGET_ARCH="aarch64";; + rock64*) XBPS_TARGET_ARCH="aarch64";; + *) die "$PROGNAME: Unable to compute target architecture from platform";; + esac + + if [ -z "${PLATFORM##*-musl}" ] ; then + XBPS_TARGET_ARCH="${XBPS_TARGET_ARCH}-musl" + fi +} + +set_dracut_args_from_platform() { + # In rare cases it is necessary to set platform specific dracut + # args. This is mostly the case on ARM platforms. + case "$PLATFORM" in + *) ;; + esac +} + +set_cachedir() { + # The package artifacts are cacheable, but they need to be isolated + # from the host cache. + : "${XBPS_CACHEDIR:=--cachedir=$PWD/xbps-cache/${XBPS_TARGET_ARCH}}" +} + +rk33xx_flash_uboot() { + local dir="$1" + local dev="$2" + dd if="${dir}/idbloader.img" of="${dev}" seek=64 conv=notrunc,fsync >/dev/null 2>&1 + dd if="${dir}/u-boot.itb" of="${dev}" seek=16384 conv=notrunc,fsync >/dev/null 2>&1 +} + +# These should all resolve even if they won't have the appropriate +# repodata files for the selected architecture. +: "${XBPS_REPOSITORY:=--repository=https://repo-default.voidlinux.org/current \ + --repository=https://repo-default.voidlinux.org/current/musl \ + --repository=https://repo-default.voidlinux.org/current/aarch64}" + + + +# This library is the authoritative source of the platform map, +# because of this we may need to get this information from the command +# line. This select allows us to get that information out. This +# fails silently if the toolname isn't known since this script is +# sourced. +case $1 in + platform2arch) + PLATFORM=$2 + set_target_arch_from_platform + echo "$XBPS_TARGET_ARCH" + ;; +esac diff --git a/mkimage.sh b/mkimage.sh new file mode 100755 index 0000000..a1565aa --- /dev/null +++ b/mkimage.sh @@ -0,0 +1,409 @@ +#!/bin/sh +#- +# Copyright (c) 2013-2016 Juan Romero Pardines. +# Copyright (c) 2017 Google +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +readonly PROGNAME=$(basename "$0") +readonly ARCH=$(uname -m) + +trap 'printf "\nInterrupted! exiting...\n"; cleanup; exit 0' INT TERM HUP + +# This source pulls in all the functions from lib.sh. This set of +# functions makes it much easier to work with chroots and abstracts +# away all the problems with running binaries with QEMU. +# shellcheck source=./lib.sh +. ./lib.sh + +# This script has a special cleanup() function since it needs to +# unmount the rootfs as mounted on a loop device. This function is +# defined after sourcing the library functions to ensure it is the +# last one defined. +cleanup() { + umount_pseudofs + umount -f "${ROOTFS}/boot" 2>/dev/null + umount -f "${ROOTFS}" 2>/dev/null + if [ -e "$LOOPDEV" ]; then + partx -d "$LOOPDEV" 2>/dev/null + losetup -d "$LOOPDEV" 2>/dev/null + fi + + [ -d "$ROOTFS" ] && rmdir "$ROOTFS" +} + + +# This script is designed to take in a complete platformfs and spit +# out an image that is suitable for writing with dd. The image is +# configurable in terms of the filesystem layout, but not in terms of +# the installed system itself. Customization to the installed system +# should be made during the mkplatformfs step. +usage() { + cat <<_EOF +Usage: $PROGNAME [options] + +The argument expects a tarball generated by void-mkrootfs. +The platform is guessed automatically by its name. + +Accepted sizes suffixes: KiB, MiB, GiB, TiB, EiB. + +OPTIONS + -b Set /boot filesystem type (defaults to FAT) + -B Set /boot filesystem size (defaults to 64MiB) + -r Set / filesystem type (defaults to EXT4) + -s Set total image size (defaults to 2GB) + -o Set image filename (guessed automatically) + -x Use threads to compress the image (dynamic if unset) + -h Show this help + -V Show version + +Resulting image will have 2 partitions, /boot and /. +_EOF + exit 0 +} + +# ######################################## +# SCRIPT EXECUTION STARTS HERE +# ######################################## + +while getopts "b:B:o:r:s:x:h:V" opt; do + case $opt in + b) BOOT_FSTYPE="$OPTARG";; + B) BOOT_FSSIZE="$OPTARG";; + o) FILENAME="$OPTARG";; + r) ROOT_FSTYPE="$OPTARG";; + s) IMGSIZE="$OPTARG";; + x) COMPRESSOR_THREADS="$OPTARG" ;; + V) version; exit 0;; + *) usage;; + esac +done +shift $((OPTIND - 1)) +ROOTFS_TARBALL="$1" + +if [ -z "$ROOTFS_TARBALL" ]; then + usage +elif [ ! -r "$ROOTFS_TARBALL" ]; then + # In rare cases the tarball can wind up owned by the wrong user. + # This leads to confusing failures if execution is allowed to + # proceed. + die "Cannot read rootfs tarball: $ROOTFS_TARBALL" +fi + +# Setup the platform variable. Here we want just the name and +# optionally -musl if this is the musl variant. +PLATFORM="${ROOTFS_TARBALL#void-}" +PLATFORM="${PLATFORM%-PLATFORMFS*}" + +# Be absolutely certain the platform is supported before continuing +case "$PLATFORM" in + bananapi|beaglebone|cubieboard2|cubietruck|odroid-c2|odroid-u2|rpi-armv6l|rpi-armv7l|rpi-aarch64|GCP|pinebookpro|pinephone|rock64|*-musl);; + *) die "The $PLATFORM is not supported, exiting..." +esac + +# Default for bigger boot partion on rk33xx devices since it needs to +# fit at least 2 Kernels + initramfs +case "$PLATFORM" in + pinebookpro*|rock64*) + : "${BOOT_FSSIZE:=256MiB}" + ;; +esac +# By default we build all platform images with a 64MiB boot partition +# formated FAT16, and an approximately 1.9GiB root partition formated +# ext4. More exotic combinations are of course possible, but this +# combination works on all known platforms. +: "${IMGSIZE:=2G}" +: "${BOOT_FSTYPE:=vfat}" +: "${BOOT_FSSIZE:=64MiB}" +: "${ROOT_FSTYPE:=ext4}" + +# Verify that the required tooling is available +readonly REQTOOLS="sfdisk partx losetup mount truncate mkfs.${BOOT_FSTYPE} mkfs.${ROOT_FSTYPE}" +check_tools + +# This is an awful hack since the script isn't using privesc +# mechanisms selectively. This is a TODO item. +if [ "$(id -u)" -ne 0 ]; then + die "need root perms to continue, exiting." +fi + +# Set the default filename if none was provided above. The default +# will include the platform the image is being built for and the date +# on which it was built. +if [ -z "$FILENAME" ]; then + FILENAME="void-${PLATFORM}-$(date -u +%Y%m%d).img" +fi + +# Create the base image. This was previously accomplished with dd, +# but truncate is markedly faster. +info_msg "Creating disk image ($IMGSIZE) ..." +truncate -s "${IMGSIZE}" "$FILENAME" >/dev/null 2>&1 + +# Grab a tmpdir for the rootfs. If this fails we need to halt now +# because otherwise things will go very badly for the host system. +ROOTFS=$(mktemp -d) || die "Could not create tmpdir for ROOTFS" + +info_msg "Creating disk image partitions/filesystems ..." +if [ "$BOOT_FSTYPE" = "vfat" ]; then + # The mkfs.vfat program tries to make some "intelligent" choices + # about the type of filesystem it creates. Instead we set options + # if the type is vfat to ensure that the same options will be used + # every time. + _args="-I -F16" +fi + +case "$PLATFORM" in + cubieboard2|cubietruck|ci20*|odroid-c2*) + # These platforms use a single partition for the entire filesystem. + sfdisk "${FILENAME}" <<_EOF +label: dos +2048,,L +_EOF + LOOPDEV=$(losetup --show --find --partscan "$FILENAME") + mkfs.${ROOT_FSTYPE} -O '^64bit,^extra_isize,^has_journal' "${LOOPDEV}p1" >/dev/null 2>&1 + mount "${LOOPDEV}p1" "$ROOTFS" + ROOT_UUID=$(blkid -o value -s UUID "${LOOPDEV}p1") + ;; + *) + # These platforms use a partition layout with a small boot + # partition (64M by default) and the rest of the space as the + # root filesystem. This is the generally preferred disk + # layout for new platforms. + case "$PLATFORM" in + pinebookpro*|rock64*) + # rk33xx devices use GPT and need more space reserved + sfdisk "$FILENAME" <<_EOF +label: gpt +unit: sectors +first-lba: 32768 +name=BootFS, size=${BOOT_FSSIZE}, type=L, bootable, attrs="LegacyBIOSBootable" +name=RootFS, type=L +_EOF + ;; + *) + # The rest use MBR and need less space reserved + sfdisk "${FILENAME}" <<_EOF +label: dos +2048,${BOOT_FSSIZE},b,* +,+,L +_EOF + ;; + esac + LOOPDEV=$(losetup --show --find --partscan "$FILENAME") + # Normally we need to quote to prevent argument splitting, but + # we explicitly want argument splitting here. + # shellcheck disable=SC2086 + mkfs.${BOOT_FSTYPE} $_args "${LOOPDEV}p1" >/dev/null + case "$ROOT_FSTYPE" in + # Because the images produced by this script are generally + # either on single board computers using flash memory or + # in cloud environments that already provide disk + # durability, we shut off the journal for ext filesystems. + # For flash memory this greatly extends the life of the + # memory and for cloud images this lowers the overhead by + # a small amount. + ext[34]) disable_journal="-O ^has_journal";; + esac + mkfs.${ROOT_FSTYPE} ${disable_journal:+"$disable_journal"} "${LOOPDEV}p2" >/dev/null 2>&1 + mount "${LOOPDEV}p2" "$ROOTFS" + mkdir -p "${ROOTFS}/boot" + mount "${LOOPDEV}p1" "${ROOTFS}/boot" + BOOT_UUID=$(blkid -o value -s UUID "${LOOPDEV}p1") + ROOT_UUID=$(blkid -o value -s UUID "${LOOPDEV}p2") + ROOT_PARTUUID=$(blkid -o value -s PARTUUID "${LOOPDEV}p2") + ;; +esac + +# This step unpacks the platformfs tarball made by mkplatformfs.sh. +info_msg "Unpacking rootfs tarball ..." +if [ "$PLATFORM" = "beaglebone" ]; then + # The beaglebone requires some special extra handling. The MLO + # program is a special first stage boot loader that brings up + # enough of the processor to then load u-boot which loads the rest + # of the system. The noauto option also prevents /boot from being + # mounted during system startup. + fstab_args=",noauto" + tar xfp "$ROOTFS_TARBALL" -C "$ROOTFS" ./boot/MLO + tar xfp "$ROOTFS_TARBALL" -C "$ROOTFS" ./boot/u-boot.img + touch "$ROOTFS/boot/uEnv.txt" + umount "$ROOTFS/boot" +fi + +# In the general case, its enough to just unpack the ROOTFS_TARBALL +# onto the ROOTFS. This will get a system that is ready to boot, save +# for the bootloader which is handled later. +tar xfp "$ROOTFS_TARBALL" --xattrs --xattrs-include='*' -C "$ROOTFS" + +# For f2fs the system should not attempt an fsck at boot. This +# filesystem is in theory self healing and does not use the standard +# mechanisms. All other filesystems should use fsck at boot. +fspassno="1" +if [ "$ROOT_FSTYPE" = "f2fs" ]; then + fspassno="0" +fi + +# Void images prefer uuids to nodes in /dev since these are not +# dependent on the hardware layout. On a single board computer this +# may not matter much but it makes the cloud images easier to manage. +echo "UUID=$ROOT_UUID / $ROOT_FSTYPE defaults 0 ${fspassno}" >> "${ROOTFS}/etc/fstab" +if [ -n "$BOOT_UUID" ]; then + echo "UUID=$BOOT_UUID /boot $BOOT_FSTYPE defaults${fstab_args} 0 2" >> "${ROOTFS}/etc/fstab" +fi + +# Images are shipped with root as the only user by default, so we need to +# ensure ssh login is possible for headless setups. +sed -i "${ROOTFS}/etc/ssh/sshd_config" -e 's|^#\(PermitRootLogin\) .*|\1 yes|g' + +# This section does final configuration on the images. In the case of +# SBCs this writes the bootloader to the image or sets up other +# required binaries to boot. In the case of images destined for a +# Cloud, this sets up the services that the cloud will expect to be +# running and a suitable bootloader. When adding a new platform, +# please add a comment explaining what the steps you are adding do, +# and where information about your specific platform's boot process +# can be found. +info_msg "Configuring image for platform $PLATFORM" +case "$PLATFORM" in +bananapi*|cubieboard2*|cubietruck*) + dd if="${ROOTFS}/boot/u-boot-sunxi-with-spl.bin" of="${LOOPDEV}" bs=1024 seek=8 >/dev/null 2>&1 + ;; +odroid-c2*) + dd if="${ROOTFS}/boot/bl1.bin.hardkernel" of="${LOOPDEV}" bs=1 count=442 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/bl1.bin.hardkernel" of="${LOOPDEV}" bs=512 skip=1 seek=1 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/u-boot.bin" of="${LOOPDEV}" bs=512 seek=97 >/dev/null 2>&1 + ;; +odroid-u2*) + dd if="${ROOTFS}/boot/E4412_S.bl1.HardKernel.bin" of="${LOOPDEV}" seek=1 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/bl2.signed.bin" of="${LOOPDEV}" seek=31 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/u-boot.bin" of="${LOOPDEV}" seek=63 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/E4412_S.tzsw.signed.bin" of="${LOOPDEV}" seek=2111 >/dev/null 2>&1 + ;; +ci20*) + dd if="${ROOTFS}/boot/u-boot-spl.bin" of="${LOOPDEV}" obs=512 seek=1 >/dev/null 2>&1 + dd if="${ROOTFS}/boot/u-boot.img" of="${LOOPDEV}" obs=1K seek=14 >/dev/null 2>&1 + ;; +rock64*) + rk33xx_flash_uboot "${ROOTFS}/usr/lib/rock64-uboot" "$LOOPDEV" + # populate the extlinux.conf file + cat >"${ROOTFS}/etc/default/extlinux" <<_EOF +TIMEOUT=10 +# Defaults to current kernel cmdline if left empty +CMDLINE="panic=10 coherent_pool=1M console=ttyS2,1500000 root=UUID=${ROOT_UUID} rw" +# set this to use a DEVICETREEDIR line in place of an FDT line +USE_DEVICETREEDIR="yes" +# relative dtb path supplied to FDT line, as long as above is unset +DTBPATH="" +_EOF + mkdir -p "${ROOTFS}/boot/extlinux" + run_cmd_chroot "${ROOTFS}" "/etc/kernel.d/post-install/60-extlinux" + cleanup_chroot + ;; +pinebookpro*) + rk33xx_flash_uboot "${ROOTFS}/usr/lib/pinebookpro-uboot" "$LOOPDEV" + run_cmd_chroot "${ROOTFS}" "xbps-reconfigure -f pinebookpro-kernel" + cleanup_chroot + ;; +pinephone*) + sed -i "s/CMDLINE=\"\(.*\)\"\$/CMDLINE=\"\1 root=PARTUUID=${ROOT_PARTUUID}\"/" "${ROOTFS}/etc/default/pinephone-uboot-config" + dd if="${ROOTFS}/boot/u-boot-sunxi-with-spl.bin" of="${LOOPDEV}" bs=1024 seek=8 conv=notrunc,fsync >/dev/null 2>&1 + run_cmd_chroot "${ROOTFS}" "xbps-reconfigure -f pinephone-kernel" + cleanup_chroot + ;; +GCP*) + # Google Cloud Platform image configuration for Google Cloud + # Engine. The steps below are built in reference to the + # documentation on building custom images available here: + # https://cloud.google.com/compute/docs/images/import-existing-image + # The images produced by this script are ready to upload and boot. + + # Setup GRUB + mount_pseudofs + run_cmd_chroot "${ROOTFS}" "grub-install ${LOOPDEV}" + sed -i "s:page_poison=1:page_poison=1 console=ttyS0,38400n8d:" "${ROOTFS}/etc/default/grub" + run_cmd_chroot "${ROOTFS}" update-grub + + # Setup the GCP Guest services + for _service in dhcpcd sshd agetty-console nanoklogd socklog-unix GCP-Guest-Initialization GCP-accounts GCP-clock-skew GCP-ip-forwarding ; do + run_cmd_chroot "${ROOTFS}" "ln -sv /etc/sv/$_service /etc/runit/runsvdir/default/$_service" + done + + # Turn off the agetty's since we can't use them anyway + rm -v "${ROOTFS}/etc/runit/runsvdir/default/agetty-tty"* + + # Disable root login over ssh and lock account + sed -i "s:PermitRootLogin yes:PermitRootLogin no:" "${ROOTFS}/etc/ssh/sshd_config" + run_cmd_chroot "${ROOTFS}" "passwd -l root" + + # Set the Timezone + run_cmd_chroot "${ROOTFS}" "ln -svf /usr/share/zoneinfo/UTC /etc/localtime" + + # Generate glibc-locales if necessary (this is a noop on musl) + if [ "$PLATFORM" = GCP ] ; then + run_cmd_chroot "${ROOTFS}" "xbps-reconfigure -f glibc-locales" + fi + + # Remove SSH host keys (these will get rebuilt on first boot) + rm -f "${ROOTFS}/etc/ssh/*key*" + rm -f "${ROOTFS}/etc/ssh/moduli" + + # Force the hostname since this isn't read from DHCP + echo void-GCE > "${ROOTFS}/etc/hostname" + + # Cleanup the chroot from anything that was setup for the + # run_cmd_chroot commands + cleanup_chroot + ;; +esac + +# Release all the mounts, deconfigure the loop device, and remove the +# rootfs mountpoint. Since this was just a mountpoint it should be +# empty. If it contains stuff we bail out here since something went +# very wrong. +umount -R "$ROOTFS" +losetup -d "$LOOPDEV" +rmdir "$ROOTFS" || die "$ROOTFS not empty!" + +# We've been working with this as root for a while now, so this makes +# sure the permissions are sane. +chmod 644 "$FILENAME" + +# The standard images are ready to go, but the cloud images require +# some minimal additional post processing. +case "$PLATFORM" in + GCP*) + # This filename is mandated by the Google Cloud Engine import + # process, the archive name is not. + mv "$FILENAME" disk.raw + info_msg "Compressing disk.raw" + tar Sczf "${FILENAME%.img}.tar.gz" disk.raw + # Since this process just produces something that can be + # uploaded, we remove the original disk image. + rm disk.raw + info_msg "Sucessfully created ${FILENAME%.img}.tar.gz image." + ;; + *) + info_msg "Compressing $FILENAME with xz (level 9 compression)" + xz "-T${COMPRESSOR_THREADS:-0}" -9 "$FILENAME" + info_msg "Successfully created $FILENAME image." + ;; +esac diff --git a/mklive.sh b/mklive.sh new file mode 100755 index 0000000..a83bbae --- /dev/null +++ b/mklive.sh @@ -0,0 +1,453 @@ +#!/bin/bash +# +# vim: set ts=4 sw=4 et: +# +#- +# Copyright (c) 2009-2015 Juan Romero Pardines. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- +trap 'error_out $? $LINENO' INT TERM 0 +umask 022 + +. ./lib.sh + +readonly REQUIRED_PKGS="base-files libgcc dash coreutils sed tar gawk syslinux grub-i386-efi grub-x86_64-efi memtest86+ squashfs-tools xorriso" +readonly INITRAMFS_PKGS="binutils xz device-mapper dhclient dracut-network openresolv" +readonly PROGNAME=$(basename "$0") +declare -a INCLUDE_DIRS=() + +info_msg() { + printf "\033[1m$@\n\033[m" +} +die() { + info_msg "ERROR: $@" + error_out 1 $LINENO +} +print_step() { + CURRENT_STEP=$((CURRENT_STEP+1)) + info_msg "[${CURRENT_STEP}/${STEP_COUNT}] $@" +} +mount_pseudofs() { + for f in sys dev proc; do + mkdir -p "$ROOTFS"/$f + mount --rbind /$f "$ROOTFS"/$f + done +} +umount_pseudofs() { + umount -R -f "$ROOTFS"/sys >/dev/null 2>&1 + umount -R -f "$ROOTFS"/dev >/dev/null 2>&1 + umount -R -f "$ROOTFS"/proc >/dev/null 2>&1 +} +error_out() { + umount_pseudofs + [ -d "$BUILDDIR" -a -z "$KEEP_BUILDDIR" ] && rm -rf "$BUILDDIR" + exit "${1:=0}" +} + +usage() { + cat <<_EOF +Usage: $PROGNAME [options] + +Options: + -a Set XBPS_ARCH (do not use it unless you know what it is) + -b Set an alternative base-system package (defaults to base-system). + -r Use this XBPS repository (may be specified multiple times). + -c Use this XBPS cache directory (a subdirectory of current +directory if unset). + -k Default keymap to use (us if unset) + -l Default locale to use (en_US.UTF-8 if unset). + -i Compression type for the initramfs image (xz if unset). + -s Compression type for the squashfs image (xz if unset) + -o Output file name for the ISO image (auto if unset). + -p "pkg pkgN ..." Install additional packages into the ISO image. + -I Include directory structure under given path into rootfs + -S "service serviceN ..." Services to enable + + -C "cmdline args" Add additional kernel command line arguments. + -T "title" Modify the bootloader title. + -v linux Install a custom Linux version on ISO image (linux meta-package if unset). + -K Do not remove builddir. + +The $PROGNAME script generates a live image of the Void Linux distribution. +This ISO image can be written to a CD/DVD-ROM or any USB stick. +_EOF + exit 1 +} + +copy_void_keys() { + mkdir -p "$1"/var/db/xbps/keys + cp keys/*.plist "$1"/var/db/xbps/keys +} + +copy_dracut_files() { + mkdir -p "$1"/usr/lib/dracut/modules.d/01vmklive + cp dracut/vmklive/* "$1"/usr/lib/dracut/modules.d/01vmklive/ +} + +copy_autoinstaller_files() { + mkdir -p "$1"/usr/lib/dracut/modules.d/01autoinstaller + cp dracut/autoinstaller/* "$1"/usr/lib/dracut/modules.d/01autoinstaller/ +} + +install_prereqs() { + XBPS_ARCH=$ARCH "$XBPS_INSTALL_CMD" -r "$VOIDHOSTDIR" ${XBPS_REPOSITORY} \ + -c "$XBPS_HOST_CACHEDIR" -y $REQUIRED_PKGS + [ $? -ne 0 ] && die "Failed to install required software, exiting..." +} + +install_packages() { + XBPS_ARCH=$BASE_ARCH "${XBPS_INSTALL_CMD}" -r "$ROOTFS" \ + ${XBPS_REPOSITORY} -c "$XBPS_CACHEDIR" -yn $PACKAGE_LIST $INITRAMFS_PKGS + [ $? -ne 0 ] && die "Missing required binary packages, exiting..." + + mount_pseudofs + + LANG=C XBPS_ARCH=$BASE_ARCH "${XBPS_INSTALL_CMD}" -U -r "$ROOTFS" \ + ${XBPS_REPOSITORY} -c "$XBPS_CACHEDIR" -y $PACKAGE_LIST $INITRAMFS_PKGS + [ $? -ne 0 ] && die "Failed to install $PACKAGE_LIST" + + xbps-reconfigure -r "$ROOTFS" -f base-files >/dev/null 2>&1 + chroot "$ROOTFS" env -i xbps-reconfigure -f base-files + + # Enable choosen UTF-8 locale and generate it into the target rootfs. + if [ -f "$ROOTFS"/etc/default/libc-locales ]; then + sed -e "s/\#\(${LOCALE}.*\)/\1/g" -i "$ROOTFS"/etc/default/libc-locales + fi + chroot "$ROOTFS" env -i xbps-reconfigure -a + + # Cleanup and remove useless stuff. + rm -rf "$ROOTFS"/var/cache/* "$ROOTFS"/run/* "$ROOTFS"/var/run/* +} + +enable_services() { + SERVICE_LIST="$*" + for service in $SERVICE_LIST; do + if ! [ -e $ROOTFS/etc/sv/$service ]; then + die "service $service not in /etc/sv" + fi + ln -sf /etc/sv/$service $ROOTFS/etc/runit/runsvdir/default/ + done +} + +copy_include_directories() { + for includedir in "${INCLUDE_DIRS[@]}"; do + info_msg "=> copying include directory '$includedir' ..." + find "$includedir" -mindepth 1 -maxdepth 1 -exec cp -rfpPv {} "$ROOTFS"/ \; + done +} + +generate_initramfs() { + local _args + + copy_dracut_files "$ROOTFS" + copy_autoinstaller_files "$ROOTFS" + chroot "$ROOTFS" env -i /usr/bin/dracut -N --"${INITRAMFS_COMPRESSION}" \ + --add-drivers "ahci" --force-add "vmklive autoinstaller" --omit systemd "/boot/initrd" $KERNELVERSION + [ $? -ne 0 ] && die "Failed to generate the initramfs" + + mv "$ROOTFS"/boot/initrd "$BOOT_DIR" + cp "$ROOTFS"/boot/vmlinuz-$KERNELVERSION "$BOOT_DIR"/vmlinuz +} + +cleanup_rootfs() { + for f in ${INITRAMFS_PKGS}; do + revdeps=$(xbps-query -r "$ROOTFS" -X $f) + if [ -n "$revdeps" ]; then + xbps-pkgdb -r "$ROOTFS" -m auto $f + else + xbps-remove -r "$ROOTFS" -Ry ${f} >/dev/null 2>&1 + fi + done + rm -r "$ROOTFS"/usr/lib/dracut/modules.d/01vmklive + rm -r "$ROOTFS"/usr/lib/dracut/modules.d/01autoinstaller +} + +generate_isolinux_boot() { + cp -f "$SYSLINUX_DATADIR"/isolinux.bin "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/ldlinux.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/libcom32.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/vesamenu.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/libutil.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/chain.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/reboot.c32 "$ISOLINUX_DIR" + cp -f "$SYSLINUX_DATADIR"/poweroff.c32 "$ISOLINUX_DIR" + cp -f isolinux/isolinux.cfg.in "$ISOLINUX_DIR"/isolinux.cfg + cp -f ${SPLASH_IMAGE} "$ISOLINUX_DIR" + + sed -i -e "s|@@SPLASHIMAGE@@|$(basename "${SPLASH_IMAGE}")|" \ + -e "s|@@KERNVER@@|${KERNELVERSION}|" \ + -e "s|@@KEYMAP@@|${KEYMAP}|" \ + -e "s|@@ARCH@@|$BASE_ARCH|" \ + -e "s|@@LOCALE@@|${LOCALE}|" \ + -e "s|@@BOOT_TITLE@@|${BOOT_TITLE}|" \ + -e "s|@@BOOT_CMDLINE@@|${BOOT_CMDLINE}|" \ + "$ISOLINUX_DIR"/isolinux.cfg + + # include memtest86+ + cp -f "$VOIDHOSTDIR"/boot/memtest.bin "$BOOT_DIR" +} + +generate_grub_efi_boot() { + cp -f grub/grub.cfg "$GRUB_DIR" + cp -f grub/grub_void.cfg.in "$GRUB_DIR"/grub_void.cfg + sed -i -e "s|@@SPLASHIMAGE@@|$(basename "${SPLASH_IMAGE}")|" \ + -e "s|@@KERNVER@@|${KERNELVERSION}|" \ + -e "s|@@KEYMAP@@|${KEYMAP}|" \ + -e "s|@@ARCH@@|$BASE_ARCH|" \ + -e "s|@@BOOT_TITLE@@|${BOOT_TITLE}|" \ + -e "s|@@BOOT_CMDLINE@@|${BOOT_CMDLINE}|" \ + -e "s|@@LOCALE@@|${LOCALE}|" "$GRUB_DIR"/grub_void.cfg + mkdir -p "$GRUB_DIR"/fonts + cp -f "$GRUB_DATADIR"/unicode.pf2 "$GRUB_DIR"/fonts + + modprobe -q loop || : + + # Create EFI vfat image. + truncate -s 32M "$GRUB_DIR"/efiboot.img >/dev/null 2>&1 + mkfs.vfat -F12 -S 512 -n "grub_uefi" "$GRUB_DIR/efiboot.img" >/dev/null 2>&1 + + GRUB_EFI_TMPDIR="$(mktemp --tmpdir="$HOME" -d)" + LOOP_DEVICE="$(losetup --show --find "${GRUB_DIR}"/efiboot.img)" + mount -o rw,flush -t vfat "${LOOP_DEVICE}" "${GRUB_EFI_TMPDIR}" >/dev/null 2>&1 + + cp -a "$IMAGEDIR"/boot "$VOIDHOSTDIR" + xbps-uchroot "$VOIDHOSTDIR" grub-mkstandalone -- \ + --directory="/usr/lib/grub/i386-efi" \ + --format="i386-efi" \ + --output="/tmp/bootia32.efi" \ + "boot/grub/grub.cfg" + if [ $? -ne 0 ]; then + umount "$GRUB_EFI_TMPDIR" + losetup --detach "${LOOP_DEVICE}" + die "Failed to generate EFI loader" + fi + mkdir -p "${GRUB_EFI_TMPDIR}"/EFI/BOOT + cp -f "$VOIDHOSTDIR"/tmp/bootia32.efi "${GRUB_EFI_TMPDIR}"/EFI/BOOT/BOOTIA32.EFI + xbps-uchroot "$VOIDHOSTDIR" grub-mkstandalone -- \ + --directory="/usr/lib/grub/x86_64-efi" \ + --format="x86_64-efi" \ + --output="/tmp/bootx64.efi" \ + "boot/grub/grub.cfg" + if [ $? -ne 0 ]; then + umount "$GRUB_EFI_TMPDIR" + losetup --detach "${LOOP_DEVICE}" + die "Failed to generate EFI loader" + fi + cp -f "$VOIDHOSTDIR"/tmp/bootx64.efi "${GRUB_EFI_TMPDIR}"/EFI/BOOT/BOOTX64.EFI + umount "$GRUB_EFI_TMPDIR" + losetup --detach "${LOOP_DEVICE}" + rm -rf "$GRUB_EFI_TMPDIR" + + # include memtest86+ + cp -f "$VOIDHOSTDIR"/boot/memtest.efi "$BOOT_DIR" +} + +generate_squashfs() { + umount_pseudofs + + # Find out required size for the rootfs and create an ext3fs image off it. + ROOTFS_SIZE=$(du --apparent-size -sm "$ROOTFS"|awk '{print $1}') + mkdir -p "$BUILDDIR/tmp/LiveOS" + truncate -s "$((ROOTFS_SIZE+ROOTFS_SIZE))M" \ + "$BUILDDIR"/tmp/LiveOS/ext3fs.img >/dev/null 2>&1 + mkdir -p "$BUILDDIR/tmp-rootfs" + mkfs.ext3 -F -m1 "$BUILDDIR/tmp/LiveOS/ext3fs.img" >/dev/null 2>&1 + mount -o loop "$BUILDDIR/tmp/LiveOS/ext3fs.img" "$BUILDDIR/tmp-rootfs" + cp -a "$ROOTFS"/* "$BUILDDIR"/tmp-rootfs/ + umount -f "$BUILDDIR/tmp-rootfs" + mkdir -p "$IMAGEDIR/LiveOS" + + "$VOIDHOSTDIR"/usr/bin/mksquashfs "$BUILDDIR/tmp" "$IMAGEDIR/LiveOS/squashfs.img" \ + -comp "${SQUASHFS_COMPRESSION}" || die "Failed to generate squashfs image" + chmod 444 "$IMAGEDIR/LiveOS/squashfs.img" + + # Remove rootfs and temporary dirs, we don't need them anymore. + rm -rf "$ROOTFS" "$BUILDDIR/tmp-rootfs" "$BUILDDIR/tmp" +} + +generate_iso_image() { + "$VOIDHOSTDIR"/usr/bin/xorriso -as mkisofs \ + -iso-level 3 -rock -joliet \ + -max-iso9660-filenames -omit-period \ + -omit-version-number -relaxed-filenames -allow-lowercase \ + -volid "VOID_LIVE" \ + -eltorito-boot boot/isolinux/isolinux.bin \ + -eltorito-catalog boot/isolinux/boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + -eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot \ + -isohybrid-mbr "$SYSLINUX_DATADIR"/isohdpfx.bin \ + -output "$OUTPUT_FILE" "$IMAGEDIR" || die "Failed to generate ISO image" +} + +# +# main() +# +while getopts "a:b:r:c:C:T:Kk:l:i:I:S:s:o:p:v:Vh" opt; do + case $opt in + a) BASE_ARCH="$OPTARG";; + b) BASE_SYSTEM_PKG="$OPTARG";; + r) XBPS_REPOSITORY="--repository=$OPTARG $XBPS_REPOSITORY";; + c) XBPS_CACHEDIR="$OPTARG";; + K) readonly KEEP_BUILDDIR=1;; + k) KEYMAP="$OPTARG";; + l) LOCALE="$OPTARG";; + i) INITRAMFS_COMPRESSION="$OPTARG";; + I) INCLUDE_DIRS+=("$OPTARG");; + S) SERVICE_LIST="$SERVICE_LIST $OPTARG";; + s) SQUASHFS_COMPRESSION="$OPTARG";; + o) OUTPUT_FILE="$OPTARG";; + p) PACKAGE_LIST="$PACKAGE_LIST $OPTARG";; + C) BOOT_CMDLINE="$OPTARG";; + T) BOOT_TITLE="$OPTARG";; + v) LINUX_VERSION="$OPTARG";; + V) version; exit 0;; + *) usage;; + esac +done +shift $((OPTIND - 1)) +XBPS_REPOSITORY="$XBPS_REPOSITORY --repository=https://repo-default.voidlinux.org/current --repository=https://repo-default.voidlinux.org/current/musl" + +# Configure dracut to use overlayfs for the writable overlay. +BOOT_CMDLINE="$BOOT_CMDLINE rd.live.overlay.overlayfs=1 " + +ARCH=$(xbps-uhelper arch) + +# Set defaults +: ${BASE_ARCH:=$(xbps-uhelper arch 2>/dev/null || uname -m)} +: ${XBPS_CACHEDIR:="$(pwd -P)"/xbps-cachedir-${BASE_ARCH}} +: ${XBPS_HOST_CACHEDIR:="$(pwd -P)"/xbps-cachedir-${ARCH}} +: ${KEYMAP:=us} +: ${LOCALE:=en_US.UTF-8} +: ${INITRAMFS_COMPRESSION:=xz} +: ${SQUASHFS_COMPRESSION:=xz} +: ${BASE_SYSTEM_PKG:=base-system} +: ${BOOT_TITLE:="Void Linux"} + +case $BASE_ARCH in + x86_64*|i686*) ;; + *) >&2 echo architecture $BASE_ARCH not supported by mklive.sh; exit 1;; +esac + +# Required packages in the image for a working system. +PACKAGE_LIST="$BASE_SYSTEM_PKG $PACKAGE_LIST" + +# Check for root permissions. +if [ "$(id -u)" -ne 0 ]; then + die "Must be run as root, exiting..." +fi + +if [ -n "$ROOTDIR" ]; then + BUILDDIR=$(mktemp --tmpdir="$ROOTDIR" -d) +else + BUILDDIR=$(mktemp --tmpdir="$(pwd -P)" -d) +fi +BUILDDIR=$(readlink -f "$BUILDDIR") +IMAGEDIR="$BUILDDIR/image" +ROOTFS="$IMAGEDIR/rootfs" +VOIDHOSTDIR="$BUILDDIR/void-host" +BOOT_DIR="$IMAGEDIR/boot" +ISOLINUX_DIR="$BOOT_DIR/isolinux" +GRUB_DIR="$BOOT_DIR/grub" +CURRENT_STEP=0 +STEP_COUNT=10 +[ "${#INCLUDE_DIRS[@]}" -gt 0 ] && STEP_COUNT=$((STEP_COUNT+1)) + +: ${SYSLINUX_DATADIR:="$VOIDHOSTDIR"/usr/lib/syslinux} +: ${GRUB_DATADIR:="$VOIDHOSTDIR"/usr/share/grub} +: ${SPLASH_IMAGE:=data/splash.png} +: ${XBPS_INSTALL_CMD:=xbps-install} +: ${XBPS_REMOVE_CMD:=xbps-remove} +: ${XBPS_QUERY_CMD:=xbps-query} +: ${XBPS_RINDEX_CMD:=xbps-rindex} +: ${XBPS_UHELPER_CMD:=xbps-uhelper} +: ${XBPS_RECONFIGURE_CMD:=xbps-reconfigure} + +mkdir -p "$ROOTFS" "$VOIDHOSTDIR" "$ISOLINUX_DIR" "$GRUB_DIR" + +print_step "Synchronizing XBPS repository data..." +copy_void_keys "$ROOTFS" +copy_void_keys "$VOIDHOSTDIR" +XBPS_ARCH=$BASE_ARCH $XBPS_INSTALL_CMD -r "$ROOTFS" ${XBPS_REPOSITORY} -S +XBPS_ARCH=$ARCH $XBPS_INSTALL_CMD -r "$VOIDHOSTDIR" ${XBPS_REPOSITORY} -S + +# Get linux version for ISO +# If linux version option specified use +if [ -n "$LINUX_VERSION" ]; then + if ! echo "$LINUX_VERSION" | grep "linux[0-9._]\+"; then + die "-v option must be in format linux" + fi + + _linux_series="$LINUX_VERSION" + PACKAGE_LIST="$PACKAGE_LIST $LINUX_VERSION" +else # Otherwise find latest stable version from linux meta-package + _linux_series=$(XBPS_ARCH=$BASE_ARCH $XBPS_QUERY_CMD -r "$ROOTFS" ${XBPS_REPOSITORY:=-R} -x linux | grep 'linux[0-9._]\+') +fi + +_kver=$(XBPS_ARCH=$BASE_ARCH $XBPS_QUERY_CMD -r "$ROOTFS" ${XBPS_REPOSITORY:=-R} -p pkgver ${_linux_series}) +KERNELVERSION=$($XBPS_UHELPER_CMD getpkgversion ${_kver}) + +if [ "$?" -ne "0" ]; then + die "Failed to find kernel package version" +fi + +: ${OUTPUT_FILE="void-live-${BASE_ARCH}-${KERNELVERSION}-$(date -u +%Y%m%d).iso"} + +print_step "Installing software to generate the image: ${REQUIRED_PKGS} ..." +install_prereqs + +mkdir -p "$ROOTFS"/etc +[ -s data/motd ] && cp data/motd "$ROOTFS"/etc +[ -s data/issue ] && cp data/issue "$ROOTFS"/etc + +print_step "Installing void pkgs into the rootfs: ${PACKAGE_LIST} ..." +install_packages + +: ${DEFAULT_SERVICE_LIST:=agetty-tty1 agetty-tty2 agetty-tty3 agetty-tty4 agetty-tty5 agetty-tty6 udevd} +print_step "Enabling services: ${SERVICE_LIST} ..." +enable_services ${DEFAULT_SERVICE_LIST} ${SERVICE_LIST} + +if [ "${#INCLUDE_DIRS[@]}" -gt 0 ];then + print_step "Copying directory structures into the rootfs ..." + copy_include_directories +fi + +print_step "Generating initramfs image ($INITRAMFS_COMPRESSION)..." +generate_initramfs + +print_step "Generating isolinux support for PC-BIOS systems..." +generate_isolinux_boot + +print_step "Generating GRUB support for EFI systems..." +generate_grub_efi_boot + +print_step "Cleaning up rootfs..." +cleanup_rootfs + +print_step "Generating squashfs image ($SQUASHFS_COMPRESSION) from rootfs..." +generate_squashfs + +print_step "Generating ISO image..." +generate_iso_image + +hsize=$(du -sh "$OUTPUT_FILE"|awk '{print $1}') +info_msg "Created $(readlink -f "$OUTPUT_FILE") ($hsize) successfully." diff --git a/mknet.sh b/mknet.sh new file mode 100755 index 0000000..8932b38 --- /dev/null +++ b/mknet.sh @@ -0,0 +1,275 @@ +#!/bin/sh +# +# vim: set ts=4 sw=4 et: +# +#- +# Copyright (c) 2009-2015 Juan Romero Pardines. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +readonly PROGNAME=$(basename "$0") +readonly REQTOOLS="xbps-install tar" + +# This script needs to jump around, so we'll remember where we started +# so that we can get back here +readonly CURDIR="$(pwd)" + +# This source pulls in all the functions from lib.sh. This set of +# functions makes it much easier to work with chroots and abstracts +# away all the problems with running binaries with QEMU. +# shellcheck source=./lib.sh +. ./lib.sh + +# Die is a function provided in lib.sh which handles the cleanup of +# the mounts and removal of temporary directories if the running +# program exists unexpectedly. +trap 'bailout' INT TERM + +bailout() { + [ -d "$BOOT_DIR" ] && rm -rf "$BOOT_DIR" + die "An unchecked exception has occured!" +} + +usage() { + cat <<_EOF +Usage: $PROGNAME [options] + +Options: + -r Use this XBPS repository (may be specified multiple times). + -c Use this XBPS cache directory. + -i Compression type for the initramfs image (xz if unset). + -o Output file name for the netboot tarball (auto if unset). + -K Use instead of 'linux' to build the image. + + -k Console keymap to set (us if unset) + -l Locale to set (en_US.UTF-8 if unset) + + -C "cmdline args" Add additional kernel command line arguments. + -T "title" Modify the bootloader title. + -S "splash image" Set a custom splash image for the bootloader + +The $PROGNAME script generates a network-bootable tarball of Void Linux +_EOF + exit 1 +} + +# ######################################## +# SCRIPT EXECUTION STARTS HERE +# ######################################## + +while getopts "r:c:C:T:K:i:o:k:l:Vh" opt; do + case $opt in + r) XBPS_REPOSITORY="--repository=$OPTARG $XBPS_REPOSITORY";; + c) XBPS_CACHEDIR="--cachedir=$OPTARG";; + i) INITRAMFS_COMPRESSION="$OPTARG";; + K) KERNELPKG="$OPTARG";; + o) OUTPUT_FILE="$OPTARG";; + k) KEYMAP="$OPTARG";; + l) LOCALE="$OPTARG";; + C) BOOT_CMDLINE="$OPTARG";; + T) BOOT_TITLE="$OPTARG";; + S) SPLASH_IMAGE="OPTARG";; + V) version; exit 0;; + *) usage;; + esac +done +shift $((OPTIND - 1)) + +BASE_TARBALL="$1" + +# We need to infer the target architecture from the filename. All +# other scripts are able to get this from the platforms map because a +# platform is manually specified. Since the netboot tarballs target +# only architectures, its necessary to pull this information from the +# filename. +XBPS_TARGET_ARCH=${BASE_TARBALL%%-ROOTFS*} +XBPS_TARGET_ARCH=${XBPS_TARGET_ARCH##void-} + +# Knowing the target arch, we can set the cache up if it hasn't +# already been set +set_cachedir + +# This is an aweful hack since the script isn't using privesc +# mechanisms selectively. This is a TODO item. +if [ "$(id -u)" -ne 0 ]; then + die "need root perms to continue, exiting." +fi + +# Before going any further, check that the tools that are needed are +# present. If we delayed this we could check for the QEMU binary, but +# its a reasonable tradeoff to just bail out now. +check_tools + +# We need to operate on a tempdir, if this fails to create, it is +# absolutely crucial to bail out so that we don't hose the system that +# is running the script. +ROOTFS=$(mktemp -d) || die "failed to create ROOTFS tempdir, exiting..." +BOOT_DIR=$(mktemp -d) || die "failed to create BOOT_DIR tempdir, exiting..." +PXELINUX_DIR="$BOOT_DIR/pxelinux.cfg" + +# Now that we have a directory for the ROOTFS, we can expand the +# existing base filesystem into the directory +info_msg "Expanding base tarball $BASE_TARBALL into $ROOTFS for $PLATFORM build." +tar xf "$BASE_TARBALL" -C "$ROOTFS" + +info_msg "Install additional dracut modules" +# This section sets up the dracut modules that need to be present on +# the ROOTFS to build the PXE tarball. This includes the netmenu +# module and the autoinstaller +mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/05netmenu" +cp dracut/netmenu/* "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/" + +# The netmenu can directly launch the manual installer from the +# initrd. This is the same installer that's on the live media with +# all its quirks, oddities, and wierdness. It's included here for +# places where you might have a lab network and need to run manual +# installs from the network. +cp installer.sh "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/" + +# Of course with a PXE environment unattended installs are the norm. +# The autoinstaller is loaded as a very high priority dracut module +# and will fail the build if it can't be installed. +mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller" +cp dracut/autoinstaller/* "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller/" + +info_msg "Install kernel and additional required netboot packages" +# The rootfs has no kernel in it, so it needs to have at the very +# least dracut, syslinux, and linux installed. binutils provides +# /usr/bin/strip which lets us shrink down the size of the initrd +# dracut-network provides the in-initrd network stack dialog is needed +# by the install environment. ${INITRAMFS_COMPRESSION} is the name of +# the compressor we want to use (lz4 by default). +if [ -z "${XBPS_TARGET_ARCH##*86*}" ] ; then + # This platform is x86 or compatible, we should use + # syslinux/pxelinux to boot the system. + info_msg "Selecting syslinux bootloader" + bootloader_pkg=syslinux +else + # This is likely an arm platform of some kind. In general these + # either have u-boot or a u-boot compatible loader, so we'll use + # that to produce a uImage and a uInitrd + info_msg "Selecting u-boot bootloader" + bootloader_pkg=uboot-mkimage +fi +run_cmd_target "xbps-install $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -Sy ${KERNELPKG-linux} dracut binutils dracut-network dialog ${INITRAMFS_COMPRESSION-xz} ${bootloader_pkg}" +run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a" + +# Dracut needs to know the kernel version that will be using this +# initrd so that it can install the kernel drivers in it. Normally +# this check is quite complex, but since this is a clean rootfs and we +# just installed exactly one kernel, this check can get by with a +# really naive command to figure out the kernel version +KERNELVERSION=$(ls "$ROOTFS/usr/lib/modules/") + +# Now that things are setup, we can call dracut and build the initrd. +# This will pretty much step through the normal process to build +# initrd with the exception that the autoinstaller and netmenu are +# force added since no module depends on them. +info_msg "Building initrd for kernel version $KERNELVERSION" +run_cmd_chroot "$ROOTFS" "env -i /usr/bin/dracut \ + -N \ + --${INITRAMFS_COMPRESSION-xz} \ + --add-drivers ahci \ + --force-add 'autoinstaller netmenu' \ + --omit systemd \ + /boot/initrd \ + $KERNELVERSION" +[ $? -ne 0 ] && die "Failed to generate the initramfs" + +info_msg "Collect netboot components" +if [ ${bootloader_pkg} = "syslinux" ] ; then + # The whole point of this endeavor is to get the files needed for PXE. + # Now that they have been generated, we copy them out of the doomed + # ROOTFS and into the $BOOT_DIR where we're staging the rest of the + # tarball + mv -v "$ROOTFS/boot/initrd" "$BOOT_DIR" + cp -v "$ROOTFS/boot/vmlinuz-$KERNELVERSION" "$BOOT_DIR/vmlinuz" + + # The initrd has *very* restrictive permissions by default. To + # prevent some SysAdmin down the road having a very frustrating time + # debugging this, we just fix this here and now. + chmod 0644 "$BOOT_DIR/initrd" + + # Now we need to grab the rest of the files that go in the tarball. + # Some of these are always required, some of these are canonical, and + # some of this list is from trial and error. Either way, this is the + # minimum needed to get Void up and booting on metal from the network. + for prog in pxelinux.0 ldlinux.c32 libcom32.c32 vesamenu.c32 libutil.c32 chain.c32 ; do + cp -v "$ROOTFS/usr/lib/syslinux/$prog" "$BOOT_DIR" + done + + # Lastly we need the default pxelinux config and the splash image. + # This is user configurable, but if that isn't set then we'll use the + # one from data/splash.png instead + mkdir -p "$PXELINUX_DIR" + cp -f pxelinux.cfg/pxelinux.cfg.in "$PXELINUX_DIR/default" + cp -f "${SPLASH_IMAGE-data/splash.png}" "$BOOT_DIR" + + # This sets all the variables in the default config file + info_msg "Configuring pxelinux.0 default boot menu" + sed -i -e "s|@@SPLASHIMAGE@@|$(basename "${SPLASH_IMAGE-splash.png}")|" \ + -e "s|@@KERNVER@@|${KERNELVERSION}|" \ + -e "s|@@KEYMAP@@|${KEYMAP-us}|" \ + -e "s|@@ARCH@@|$XBPS_TARGET_ARCH|" \ + -e "s|@@LOCALE@@|${LOCALE-en_US.UTF-8}|" \ + -e "s|@@BOOT_TITLE@@|${BOOT_TITLE-Void Linux}|" \ + -e "s|@@BOOT_CMDLINE@@|${BOOT_CMDLINE}|" \ + "$PXELINUX_DIR/default" +else + # u-boot has far far fewer components, but u-boot artifacts do + # require some pre-processing + + if [ ! -f "$ROOTFS/boot/uImage" ] ; then + + # Build the uImage, this is really just the kernel with a wrapper + # to make u-boot happy. It also sets the load and entry + # addresses, though in general these are overriden by the u-boot + # configuration. + run_cmd_chroot "$ROOTFS" "env -i /usr/bin/mkimage -A arm -O linux -T kernel -C none -a 0x00000000 -e 0x00000000 -n 'Void Kernel' -d /boot/zImage /boot/uImage" + + # Build the uInitrd which is similarly just a copy of the real + # initrd in a format that u-boot is willing to ingest. + run_cmd_chroot "$ROOTFS" "env -i /usr/bin/mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n 'Void Installer Initrd' -d /boot/initrd /boot/uInitrd" + + # Copy out the artifacts that are worth keeping + cp "$ROOTFS/boot/uImage" "$BOOT_DIR" + cp "$ROOTFS/boot/uInitrd" "$BOOT_DIR" + cp -r "$ROOTFS/boot/dtbs" "$BOOT_DIR" + else + # Copy the existing uImage out + cp "$ROOTFS/boot/uImage" "$BOOT_DIR" + fi +fi + +# Compress the artifacts for distribution +OUTPUT_FILE="void-${XBPS_TARGET_ARCH}-NETBOOT-$(date -u +%Y%m%d).tar.gz" +info_msg "Compressing results to $OUTPUT_FILE" +cd "$BOOT_DIR" || die "Could not enter image dir" +tar -zcvf "$CURDIR/$OUTPUT_FILE" . +cd "$CURDIR" || die "Could not return to working directory" + +# As a final cleanup step, remove the ROOTFS and the expanded BOOT_DIR +info_msg "Cleaning up and removing build directories" +cleanup_chroot +[ -d "$ROOTFS" ] && rm -rf "$ROOTFS" +[ -d "$BOOT_DIR" ] && rm -rf "$BOOT_DIR" diff --git a/mkplatformfs.sh b/mkplatformfs.sh new file mode 100755 index 0000000..397085e --- /dev/null +++ b/mkplatformfs.sh @@ -0,0 +1,241 @@ +#!/bin/sh +#- +# Copyright (c) 2017 Google +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +readonly PROGNAME=$(basename "$0") +readonly ARCH=$(uname -m) +readonly REQTOOLS="xbps-install xbps-reconfigure tar xz" + +# This source pulls in all the functions from lib.sh. This set of +# functions makes it much easier to work with chroots and abstracts +# away all the problems with running binaries with QEMU. +# shellcheck source=./lib.sh +. ./lib.sh + +# Die is a function provided in lib.sh which handles the cleanup of +# the mounts and removal of temporary directories if the running +# program exists unexpectedly. +trap 'die "Interrupted! exiting..."' INT TERM HUP + +# Even though we only support really one target for most of these +# architectures this lets us refer to these quickly and easily by +# XBPS_ARCH. This makes it a lot more obvious what is happening later +# in the script, and it makes it easier to consume the contents of +# these down the road in later scripts. +usage() { + cat <<_EOF +Usage: $PROGNAME [options] + +Supported platforms: i686, x86_64, GCP, bananapi, beaglebone, + cubieboard2, cubietruck, odroid-c2, odroid-u2, + rpi-armv6l, rpi-armv7l, rpi-aarch64, ci20, + pinebookpro, pinephone, rock64 + +Options + -b Set an alternative base-system package (defaults to base-system) + -p Additional packages to install into the rootfs (separated by blanks) + -k Call "cmd " after building the rootfs + -c

Set XBPS cache directory (defaults to \$PWD/xbps-cachedir-) + -C Full path to the XBPS configuration file + -r Set XBPS repository (may be set multiple times) + -x Use threads to compress the image (dynamic if unset) + -o Filename to write the PLATFORMFS archive to + -n Do not compress the image, instead print out the rootfs directory + -h Show this help + -V Show version +_EOF +} + +# ######################################## +# SCRIPT EXECUTION STARTS HERE +# ######################################## + +BASEPKG=base-system +COMPRESSION="y" + +while getopts "b:p:k:c:C:r:x:o:nhV" opt; do + case $opt in + b) BASEPKG="$OPTARG" ;; + p) EXTRA_PKGS="$OPTARG" ;; + k) POST_CMD="$OPTARG" ;; + c) XBPS_CACHEDIR="--cachedir=$OPTARG" ;; + C) XBPS_CONFFILE="-C $OPTARG" ;; + r) XBPS_REPOSITORY="--repository=$OPTARG $XBPS_REPOSITORY" ;; + x) COMPRESSOR_THREADS="$OPTARG" ;; + o) FILENAME="$OPTARG" ;; + n) COMPRESSION="n" ;; + V) version; exit 0;; + *) usage; exit 0 ;; + esac +done +shift $((OPTIND - 1)) +PLATFORM="$1" +BASE_TARBALL="$2" + +# This is an aweful hack since the script isn't using privesc +# mechanisms selectively. This is a TODO item. +if [ "$(id -u)" -ne 0 ]; then + die "need root perms to continue, exiting." +fi + +# Before going any further, check that the tools that are needed are +# present. If we delayed this we could check for the QEMU binary, but +# its a reasonable tradeoff to just bail out now. +check_tools + +# Most platforms have a base system package that includes specific +# packages for bringing up the hardware. In the case of the cloud +# platforms the base package includes the components needed to inject +# SSH keys and user accounts. The base platform packages are always +# noarch though, so we strip off the -musl extention if it was +# provided. +case "$PLATFORM" in + bananapi*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + beaglebone*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + cubieboard2*|cubietruck*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + odroid-u2*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + odroid-c2*) PKGS="$BASEPKG ${PLATFORM%-musl}-base" ;; + rpi*) PKGS="$BASEPKG rpi-base" ;; + ci20*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + i686*) PKGS="$BASEPKG" ;; + x86_64*) PKGS="$BASEPKG" ;; + GCP*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + pinebookpro*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + pinephone*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + rock64*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + *) die "$PROGNAME: invalid platform!";; +esac + +# Derive the target architecture using the static map +set_target_arch_from_platform + +# And likewise set the cache +set_cachedir + +# Append any additional packages if they were requested +if [ -n "$EXTRA_PKGS" ] ; then + PKGS="$PKGS $EXTRA_PKGS" +fi + +# We need to operate on a tempdir, if this fails to create, it is +# absolutely crucial to bail out so that we don't hose the system that +# is running the script. +ROOTFS=$(mktemp -d) || die "failed to create tempdir, exiting..." + +# Now that we have a directory for the ROOTFS, we can expand the +# existing base filesystem into the directory +if [ ! -e "$BASE_TARBALL" ]; then + die "no valid base tarball given, exiting." +fi + +info_msg "Expanding base tarball $BASE_TARBALL into $ROOTFS for $PLATFORM build." +tar xf "$BASE_TARBALL" --xattrs --xattrs-include='*' -C "$ROOTFS" + +# This will install, but not configure, the packages specified by +# $PKGS. After this step we will do an xbps-reconfigure -f $PKGS +# under the correct architecture to ensure the system is setup +# correctly. +run_cmd_target "xbps-install -SU $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -y $PKGS" + +# Now that the packages are installed, we need to chroot in and +# reconfigure. This needs to be done as the right architecture. +# Since this is the only thing we're doing in the chroot, we clean up +# right after. +run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a" + +# Before final cleanup the ROOTFS needs to be checked to make sure it +# contains an initrd and if its a platform with arch 'arm*' it needs +# to also have a uInitrd. For this to work the system needs to have +# the uboot-mkimage package installed. Base system packages that do +# not provide this must provide the uInitrd pre-prepared if they are +# arm based. x86 images will have this built using native dracut +# using post unpacking steps for platforms that consume the x86 +# tarballs. This check is very specific and ensures that applicable +# tooling is present before proceeding. +if [ ! -f "$ROOTFS/boot/uInitrd" ] || + [ ! -f "$ROOTFS/boot/initrd" ] && + [ -z "${XBPS_TARGET_ARCH##*arm*}" ] && + [ -x "$ROOTFS/usr/bin/dracut" ] && + [ -x "$ROOTFS/usr/bin/mkimage" ]; then + + # Dracut needs to know the kernel version that will be using this + # initrd so that it can install the kernel drivers in it. Normally + # this check is quite complex, but since this is a clean rootfs and we + # just installed exactly one kernel, this check can get by with a + # really niave command to figure out the kernel version + KERNELVERSION=$(ls "$ROOTFS/usr/lib/modules/") + + # Some platforms also have special arguments that need to be set + # for dracut. This allows us to kludge around issues that may + # exist on certain specific platforms we build for. + set_dracut_args_from_platform + + # Now that things are setup, we can call dracut and build the initrd. + # This will pretty much step through the normal process to build + # initrd with the exception that the autoinstaller and netmenu are + # force added since no module depends on them. + info_msg "Building initrd for kernel version $KERNELVERSION" + run_cmd_chroot "$ROOTFS" "env -i /usr/bin/dracut $dracut_args /boot/initrd $KERNELVERSION" + [ $? -ne 0 ] && die "Failed to generate the initramfs" + + run_cmd_chroot "$ROOTFS" "env -i /usr/bin/mkimage -A arm -O linux -T ramdisk -C gzip -a 0 -e 0 -n 'Void Linux' -d /boot/initrd /boot/uInitrd" +fi + +cleanup_chroot + +# The cache isn't that useful since by the time the ROOTFS will be +# used it is likely to be out of date. Rather than shipping it around +# only for it to be out of date, we remove it now. +rm -rf "$ROOTFS/var/cache/*" 2>/dev/null + +# Now we can run the POST_CMD script. This user-supplied script gets the +# $ROOTFS as a parameter. +if [ -n "$POST_CMD" ]; then + info_msg "Running user supplied command: $POST_CMD" + run_cmd $POST_CMD $ROOTFS +fi + + +# Compress the tarball or just print out the path? +if [ "$COMPRESSION" = "y" ]; then + # Finally we can compress the tarball, the name will include the + # platform and the date on which the tarball was built. + tarball=${FILENAME:-void-${PLATFORM}-PLATFORMFS-$(date -u '+%Y%m%d').tar.xz} + run_cmd "tar cp --posix --xattrs --xattrs-include='*' -C $ROOTFS . | xz -T${COMPRESSOR_THREADS:-0} -9 > $tarball " + [ $? -ne 0 ] && die "Failed to compress tarball" + + # Now that we have the tarball we don't need the rootfs anymore, so we + # can get rid of it. + rm -rf "$ROOTFS" + + # Last thing to do before closing out is to let the user know that + # this succeeded. This also ensures that there's something visible + # that the user can look for at the end of the script, which can make + # it easier to see what's going on if something above failed. + info_msg "Successfully created $tarball ($PLATFORM)" +else + # User requested just printing out the path to the rootfs, here it comes. + info_msg "Successfully created rootfs under $ROOTFS" +fi diff --git a/mkrootfs.sh b/mkrootfs.sh new file mode 100755 index 0000000..8e77e4f --- /dev/null +++ b/mkrootfs.sh @@ -0,0 +1,224 @@ +#!/bin/sh +#- +# Copyright (c) 2013-2015 Juan Romero Pardines. +# Copyright (c) 2017 Google +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#- + +readonly PROGNAME=$(basename "$0") +readonly ARCH=$(uname -m) +readonly REQTOOLS="xbps-install xbps-reconfigure tar xz" + +# This source pulls in all the functions from lib.sh. This set of +# functions makes it much easier to work with chroots and abstracts +# away all the problems with running binaries with QEMU. +# shellcheck source=./lib.sh +. ./lib.sh + +# Die is a function provided in lib.sh which handles the cleanup of +# the mounts and removal of temporary directories if the running +# program exists unexpectedly. +trap 'die "Interrupted! exiting..."' INT TERM HUP + +# Even though we only support really one target for most of these +# architectures this lets us refer to these quickly and easily by +# XBPS_ARCH. This makes it a lot more obvious what is happening later +# in the script, and it makes it easier to consume the contents of +# these down the road in later scripts. +usage() { + cat <<_EOF +Usage: $PROGNAME [options] + +Supported architectures: i686, i686-musl, x86_64, x86_64-musl, + armv5tel, armv5tel-musl, armv6l, armv6l-musl, armv7l, armv7l-musl + aarch64, aarch64-musl, + mipsel, mipsel-musl + ppc, ppc-musl + ppc64le, ppc64le-musl, ppc64, ppc64-musl + + +Options + -b Set an alternative base-system package (defaults to base-voidstrap) + -c Set XBPS cache directory (defaults to \$PWD/xbps-cachedir-) + -C Full path to the XBPS configuration file + -h Show this help + -r Set XBPS repository (may be set multiple times) + -x Use threads to compress the image (dynamic if unset) + -o Filename to write the ROOTFS archive to + -V Show version +_EOF +} + +# ######################################## +# SCRIPT EXECUTION STARTS HERE +# ######################################## + +# Set the default system package. +SYSPKG="base-voidstrap" + +# Boilerplate option parsing. This script supports the bare minimum +# needed to build an image. +while getopts "b:C:c:hr:x:o:V" opt; do + case $opt in + b) SYSPKG="$OPTARG";; + C) XBPS_CONFFILE="-C $OPTARG";; + c) XBPS_CACHEDIR="--cachedir=$OPTARG";; + r) XBPS_REPOSITORY="$XBPS_REPOSITORY --repository=$OPTARG";; + x) COMPRESSOR_THREADS="$OPTARG" ;; + o) FILENAME="$OPTARG" ;; + V) version; exit 0;; + *) usage; exit 0;; + esac +done +shift $((OPTIND - 1)) +XBPS_TARGET_ARCH="$1" + +# Set the XBPS cache +set_cachedir + +# This is an aweful hack since the script isn't using privesc +# mechanisms selectively. This is a TODO item. +if [ "$(id -u)" -ne 0 ]; then + die "need root perms to continue, exiting." +fi + +# Before going any further, check that the tools that are needed are +# present. If we delayed this we could check for the QEMU binary, but +# its a reasonable tradeoff to just bail out now. +check_tools + +# If the arch wasn't set let's bail out now, nothing else in this +# script will work without knowing what we're trying to build for. +if [ -z "$XBPS_TARGET_ARCH" ]; then + echo "$PROGNAME: arch was not set!" + usage; exit 1 +fi + +# We need to operate on a tempdir, if this fails to create, it is +# absolutely crucial to bail out so that we don't hose the system that +# is running the script. +ROOTFS=$(mktemp -d) || die "failed to create tempdir, exiting..." + +# This maintains the chain of trust, the keys in the repo are known to +# be good and so we copy those. Why don't we just use the ones on the +# host system? That's a good point, but there's no promise that the +# system running the script is Void, or that those keys haven't been +# tampered with. Its much easier to use these since the will always +# exist. +mkdir -p "$ROOTFS/var/db/xbps/keys" +cp keys/*.plist "$ROOTFS/var/db/xbps/keys" + +# This sets up files that are important for XBPS to work on the new +# filesystem. It does not actually install anything. +run_cmd_target "xbps-install -S $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS" + +# Later scripts expect the permissions on / to be the canonical 755, +# so we set this here. +chmod 755 "$ROOTFS" + +# The binfmt setup and pseudofs mountpoints are needed for the qemu +# support in cases where we are running things that aren't natively +# executable. +register_binfmt +mount_pseudofs + +# With everything setup, we can now run the install to load the +# system package into the rootfs. This will not produce a +# bootable system but will instead produce a base component that can +# be quickly expanded to perform other actions on. +run_cmd_target "xbps-install -SU $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -y $SYSPKG" + +# Enable en_US.UTF-8 locale and generate it into the target ROOTFS. +# This is a bit of a hack since some glibc stuff doesn't really work +# correctly without a locale being generated. While some could argue +# that this is an arbitrary or naive choice to enable the en_US +# locale, most people using Void are able to work with the English +# language at least enough to enable thier preferred locale. If this +# truly becomes an issue in the future this hack can be revisited. +if [ -e "$ROOTFS/etc/default/libc-locales" ]; then + LOCALE=en_US.UTF-8 + sed -e "s/\#\(${LOCALE}.*\)/\1/g" -i "$ROOTFS/etc/default/libc-locales" +fi + +# The reconfigure step needs to execute code that's been compiled for +# the target architecture. Since the target isn't garanteed to be the +# same as the host, this needs to be done via qemu. +info_msg "Reconfiguring packages for ${XBPS_TARGET_ARCH} ..." + +# This step sets up enough of the base-files that the chroot will work +# and they can be reconfigured natively. Without this step there +# isn't enough configured for ld to work. This step runs as the host +# architecture, but we may need to set up XBPS_ARCH for the target +# architecture (but only when compatible). +if is_target_native "$XBPS_TARGET_ARCH"; then + run_cmd_target "xbps-reconfigure --rootdir $ROOTFS base-files" +else + run_cmd "xbps-reconfigure --rootdir $ROOTFS base-files" +fi + +# Now running as the target system, this step reconfigures the +# base-files completely. Certain things just won't work in the first +# pass, so this cleans up any issues that linger. +run_cmd_chroot "$ROOTFS" "env -i xbps-reconfigure -f base-files" + +# Once base-files is configured and functional its possible to +# configure the rest of the system. +run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a" + +# Set the default password. Previous versions of this script used a +# chroot to do this, but that is unnecessary since chpasswd +# understands how to operate on chroots without actually needing to be +# chrooted. We also remove the lock file in this step to clean up the +# lock on the passwd database, lest it be left in the system and +# propogated to other points. +info_msg "Setting the default root password ('voidlinux')" +if [ ! -f "$ROOTFS/etc/shadow" ] ; then + run_cmd_chroot "$ROOTFS" pwconv +fi +echo root:voidlinux | run_cmd_chroot "$ROOTFS" "chpasswd -c SHA512" || die "Could not set default credentials" +rm -f "$ROOTFS/etc/.pwd.lock" + +# At this point we're done running things in the chroot and we can +# clean up the shims. Failure to do this can result in things hanging +# when we try to delete the tmpdir. +cleanup_chroot + +# The cache isn't that useful since by the time the ROOTFS will be +# used it is likely to be out of date. Rather than shipping it around +# only for it to be out of date, we remove it now. +rm -rf "$ROOTFS/var/cache/*" 2>/dev/null + +# Finally we can compress the tarball, the name will include the +# architecture and the date on which the tarball was built. +: "${FILENAME:=void-${XBPS_TARGET_ARCH}-ROOTFS-$(date -u '+%Y%m%d').tar.xz}" +run_cmd "tar cp --posix --xattrs --xattrs-include='*' -C $ROOTFS . | xz -T${COMPRESSOR_THREADS:-0} -9 > $FILENAME " + +# Now that we have the tarball we don't need the rootfs anymore, so we +# can get rid of it. +rm -rf "$ROOTFS" + +# Last thing to do before closing out is to let the user know that +# this succeeded. This also ensures that there's something visible +# that the user can look for at the end of the script, which can make +# it easier to see what's going on if something above failed. +info_msg "Successfully created $FILENAME ($XBPS_TARGET_ARCH)" diff --git a/packer/.gitignore b/packer/.gitignore new file mode 100644 index 0000000..9ff404c --- /dev/null +++ b/packer/.gitignore @@ -0,0 +1,6 @@ +output_* +packer_cache +crash.log +*.box +templates/ +cloud-generic diff --git a/packer/hcl2/build-cloud-generic.pkr.hcl b/packer/hcl2/build-cloud-generic.pkr.hcl new file mode 100644 index 0000000..e471b22 --- /dev/null +++ b/packer/hcl2/build-cloud-generic.pkr.hcl @@ -0,0 +1,37 @@ +build { + name = "cloud-generic-x86_64" + + source "source.qemu.x86_64" { + boot_command = [ + "", + "auto autourl=http://{{.HTTPIP}}:{{.HTTPPort}}/x86_64.cfg", + "" + ] + vm_name = "voidlinux-x86_64" + output_directory = "cloud-generic-x86_64" + } + + provisioner "shell" { + script = "scripts/cloud.sh" + execute_command = "echo 'void' | {{.Vars}} sudo -E -S bash '{{.Path}}'" + } +} + +build { + name = "cloud-generic-x86_64-musl" + + source "source.qemu.x86_64" { + boot_command = [ + "", + "auto autourl=http://{{.HTTPIP}}:{{.HTTPPort}}/x86_64-musl.cfg", + "" + ] + vm_name = "voidlinux-x86_64-musl" + output_directory = "cloud-generic-x86_64-musl" + } + + provisioner "shell" { + script = "scripts/cloud.sh" + execute_command = "echo 'void' | {{.Vars}} sudo -E -S bash '{{.Path}}'" + } +} diff --git a/packer/hcl2/build-vagrant.pkr.hcl b/packer/hcl2/build-vagrant.pkr.hcl new file mode 100644 index 0000000..db6e95c --- /dev/null +++ b/packer/hcl2/build-vagrant.pkr.hcl @@ -0,0 +1,45 @@ +build { + name = "vagrant-virtualbox-x86_64" + + source "source.virtualbox-iso.x86_64" { + boot_command = [ + "", + "auto autourl=http://{{.HTTPIP}}:{{.HTTPPort}}/x86_64.cfg", + "" + ] + vm_name = "voidlinux-x86_64" + output_directory = "vagrant-virtualbox-x86_64" + } + + provisioner "shell" { + script = "scripts/vagrant.sh" + execute_command = "echo 'void' | {{.Vars}} sudo -E -S bash '{{.Path}}'" + } + + post-processor "vagrant" { + output = "vagrant-virtualbox-x86_64.box" + } +} + +build { + name = "vagrant-virtualbox-x86_64-musl" + + source "source.virtualbox-iso.x86_64" { + boot_command = [ + "", + "auto autourl=http://{{.HTTPIP}}:{{.HTTPPort}}/x86_64-musl.cfg", + "" + ] + vm_name = "voidlinux-x86_64-musl" + output_directory = "vagrant-virtualbox-x86_64-musl" + } + + provisioner "shell" { + script = "scripts/vagrant.sh" + execute_command = "echo 'void' | {{.Vars}} sudo -E -S bash '{{.Path}}'" + } + + post-processor "vagrant" { + output = "vagrant-virtualbox-x86_64-musl.box" + } +} diff --git a/packer/hcl2/source-qemu.pkr.hcl b/packer/hcl2/source-qemu.pkr.hcl new file mode 100644 index 0000000..5d2b5db --- /dev/null +++ b/packer/hcl2/source-qemu.pkr.hcl @@ -0,0 +1,13 @@ +source "qemu" "x86_64" { + accelerator = "kvm" + boot_wait = "5s" + disk_interface = "virtio" + disk_size = "2000M" + format = "qcow2" + http_directory = "http" + iso_checksum = "sha256:5507fe41f54719e78db7b0f9c685f85b063616d913b14f815dd481b5ea66e397" + iso_url = "https://repo-default.voidlinux.org/live/20221001/void-live-x86_64-20221001-base.iso" + ssh_password = "void" + ssh_timeout = "20m" + ssh_username = "void" +} diff --git a/packer/hcl2/source-virtualbox-ose.pkr.hcl b/packer/hcl2/source-virtualbox-ose.pkr.hcl new file mode 100644 index 0000000..58e0cce --- /dev/null +++ b/packer/hcl2/source-virtualbox-ose.pkr.hcl @@ -0,0 +1,16 @@ +source "virtualbox-iso" "x86_64" { + guest_os_type = "Linux_64" + iso_url = "https://repo-default.voidlinux.org/live/20221001/void-live-x86_64-20221001-base.iso" + iso_checksum = "sha256:5507fe41f54719e78db7b0f9c685f85b063616d913b14f815dd481b5ea66e397" + ssh_username = "void" + ssh_password = "void" + http_directory = "http" + ssh_timeout = "20m" + guest_additions_mode = "disable" + + vboxmanage = [ + ["modifyvm", "{{.Name}}", "--nictype1", "virtio"], + ] + + boot_wait = "5s" +} diff --git a/packer/hcl2/vagrant/build-vagrant.pkr.hcl b/packer/hcl2/vagrant/build-vagrant.pkr.hcl new file mode 120000 index 0000000..d9fcd0c --- /dev/null +++ b/packer/hcl2/vagrant/build-vagrant.pkr.hcl @@ -0,0 +1 @@ +../build-vagrant.pkr.hcl \ No newline at end of file diff --git a/packer/hcl2/vagrant/source-virtualbox-ose.pkr.hcl b/packer/hcl2/vagrant/source-virtualbox-ose.pkr.hcl new file mode 120000 index 0000000..04de266 --- /dev/null +++ b/packer/hcl2/vagrant/source-virtualbox-ose.pkr.hcl @@ -0,0 +1 @@ +../source-virtualbox-ose.pkr.hcl \ No newline at end of file diff --git a/packer/http/cloud.cfg b/packer/http/cloud.cfg new file mode 100644 index 0000000..708f7be --- /dev/null +++ b/packer/http/cloud.cfg @@ -0,0 +1,39 @@ +#!/bin/sh +# Void Linux Automatic Install Configuration + +export username="void" +export password="void" + +export end_action=func +end_function() { + printf "Linking default services" + chroot "$target" ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/dhcpcd + chroot "$target" ln -s /etc/sv/sshd /etc/runit/runsvdir/default/sshd + + sync + reboot -f +} + + +VAI_partition_disk() { + # Paritition Disk + sfdisk "${disk}" <> "${target}/etc/fstab" +} diff --git a/packer/http/x86_64-musl.cfg b/packer/http/x86_64-musl.cfg new file mode 100644 index 0000000..4d5639c --- /dev/null +++ b/packer/http/x86_64-musl.cfg @@ -0,0 +1,42 @@ +#!/bin/sh +# Void Linux Automatic Install Configuration + +export username="void" +export password="void" + +export XBPS_ARCH=x86_64-musl +export xbpsrepository=https://repo-default.voidlinux.org/current/musl + +export end_action=func +end_function() { + printf "Linking default services" + chroot "$target" ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/dhcpcd + chroot "$target" ln -s /etc/sv/sshd /etc/runit/runsvdir/default/sshd + + sync + reboot -f +} + + +VAI_partition_disk() { + # Paritition Disk + sfdisk "${disk}" <> "${target}/etc/fstab" +} diff --git a/packer/http/x86_64.cfg b/packer/http/x86_64.cfg new file mode 100644 index 0000000..708f7be --- /dev/null +++ b/packer/http/x86_64.cfg @@ -0,0 +1,39 @@ +#!/bin/sh +# Void Linux Automatic Install Configuration + +export username="void" +export password="void" + +export end_action=func +end_function() { + printf "Linking default services" + chroot "$target" ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/dhcpcd + chroot "$target" ln -s /etc/sv/sshd /etc/runit/runsvdir/default/sshd + + sync + reboot -f +} + + +VAI_partition_disk() { + # Paritition Disk + sfdisk "${disk}" <> "${target}/etc/fstab" +} diff --git a/packer/scripts/cloud.sh b/packer/scripts/cloud.sh new file mode 100644 index 0000000..e942f87 --- /dev/null +++ b/packer/scripts/cloud.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +echo "void ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/99-void +echo "Defaults:void !requiretty" >> /etc/sudoers.d/99-void +chmod 0440 /etc/sudoers.d/99-void +mv /etc/sudoers.d/{,10-}wheel + +xbps-fetch -o /usr/bin/growpart https://raw.githubusercontent.com/canonical/cloud-utils/ubuntu/0.31-22-g37d4e32a-0ubuntu1/bin/growpart +chmod +x /usr/bin/growpart + +xbps-install -Sy util-linux coreutils sed shinit +ln -s /etc/sv/shinit /var/service/ + +cat <<'EOF' > /etc/runit/core-services/10-resize-root.sh +#!/bin/sh +rpart=$(findmnt -r -o SOURCE -v -n /) +rnum=$(cat /sys/class/block/$(basename $rpart)/partition) + +/usr/bin/growpart ${rpart%%$rnum} $rnum +resize2fs $rpart +EOF + +passwd -dl void +passwd -dl root + +rm -rf /var/cache/xbps +rm -f /etc/ssh/ssh_host* + +shutdown -P now diff --git a/packer/scripts/vagrant.sh b/packer/scripts/vagrant.sh new file mode 100644 index 0000000..a272e72 --- /dev/null +++ b/packer/scripts/vagrant.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +useradd -m -s /bin/bash vagrant + +# Set up sudo +echo '%vagrant ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/vagrant +echo 'Defaults:vagrant !requiretty' >> /etc/sudoers.d/vagrant +chmod 0440 /etc/sudoers.d/vagrant + +gpasswd -d vagrant wheel + +sudo xbps-install -Sy wget + +# Installing vagrant keys +mkdir /home/vagrant/.ssh +chmod 700 /home/vagrant/.ssh +cd /home/vagrant/.ssh +wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' -O authorized_keys +chmod 600 /home/vagrant/.ssh/authorized_keys +chown -R vagrant /home/vagrant/.ssh + +# Install NFS for Vagrant +xbps-install -Sy nfs-utils + +passwd -dl vagrant +passwd -dl void +passwd -dl root + +rm -rf /var/cache/xbps + +shutdown -P now diff --git a/pxelinux.cfg/pxelinux.cfg.in b/pxelinux.cfg/pxelinux.cfg.in new file mode 100644 index 0000000..63456ae --- /dev/null +++ b/pxelinux.cfg/pxelinux.cfg.in @@ -0,0 +1,36 @@ +UI vesamenu.c32 +PROMPT 0 +TIMEOUT 100 +ONTIMEOUT c + +MENU TABMSG Press ENTER to boot or TAB to edit a menu entry +MENU AUTOBOOT BIOS default device boot in # second{,s}... +MENU BACKGROUND @@SPLASHIMAGE@@ +MENU WIDTH 78 +MENU MARGIN 1 +MENU ROWS 4 +MENU VSHIFT 2 +MENU TIMEOUTROW 8 +MENU TABMSGROW 2 +MENU CMDLINEROW 11 +MENU HELPMSGROW 16 +MENU HELPMSGENDROW 29 + +MENU COLOR title * #FF5255FF * +MENU COLOR border * #00000000 #00000000 none +MENU COLOR sel * #ffffffff #FF5255FF * + +LABEL menu +MENU LABEL Interactive Session [@@BOOT_TITLE@@] (@@KERNVER@@ @@ARCH@@) +KERNEL vmlinuz +APPEND initrd=initrd root=/dev/null loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ + +LABEL auto +MENU LABEL AutoInstall [@@BOOT_TITLE@@] (@@KERNVER@@ @@ARCH@@) +KERNEL vmlinuz +APPEND initrd=initrd root=/dev/null auto loglevel=4 vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ + +LABEL c +MENU LABEL Boot first HD found by BIOS +COM32 chain.c32 +APPEND hd0 diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..62e3c99 --- /dev/null +++ b/release.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +set -e + +usage() { + echo "release.sh start [-l LIVE_ARCHS] [-f LIVE_VARIANTS] [-a ROOTFS_ARCHS]" + echo " [-p PLATFORMS] [-i SBC_IMGS] [-d DATE] [-r REPOSITORY] -- [gh args...]" + echo "release.sh dl [gh args...]" + echo "release.sh sign DATE SHASUMFILE" + exit 1 +} + +check_programs() { + for prog; do + if ! type $prog &>/dev/null; then + echo "missing program: $prog" + exit 1 + fi + done +} + +start_build() { + check_programs gh + ARGS=() + while getopts "a:d:f:i:l:p:r:" opt; do + case $opt in + a) ARGS+=(-f rootfs="$OPTARG") ;; + d) ARGS+=(-f datecode="$OPTARG") ;; + f) ARGS+=(-f live_flavors="$OPTARG") ;; + i) ARGS+=(-f sbc_imgs="$OPTARG") ;; + l) ARGS+=(-f live_archs="$OPTARG") ;; + p) ARGS+=(-f platformfs="$OPTARG") ;; + r) ARGS+=(-f mirror="$OPTARG") ;; + ?) usage;; + esac + done + shift $((OPTIND - 1)) + gh workflow run gen-images.yml "${ARGS[@]}" "$@" +} + +# this assumes that the latest successful build is the one to download +# wish it could be better but alas: +# https://github.com/cli/cli/issues/4001 +download_build() { + check_programs gh + run="$(gh run list -s success -w gen-images.yml --json databaseId -q '.[].databaseId' "$@" | sort -r | head -1)" + echo "Downloading artifacts from run ${run} [this may take a while] ..." + gh run download "$run" -p 'void-live*' "$@" + echo "Done." +} + +sign_build() { + check_programs pwgen signify + DATE="$1" + SUMFILE="$2" + mkdir -p release + KEYFILE="release/void-release-$DATE.key" + pwgen -cny 25 1 > "$KEYFILE" + signify -G -p "${KEYFILE//key/pub}" -s "${KEYFILE//key/sec}" -c "This key is only valid for images with date $DATE." + signify -S -e -s "${KEYFILE//key/sec}" -m "$SUMFILE" -x "${SUMFILE//txt/sig}" +} + +case "$1" in + st*) shift; start_build "$@" ;; + d*) shift; download_build "$@" ;; + si*) shift; sign_build "$@" ;; + *) usage ;; +esac diff --git a/version b/version new file mode 100644 index 0000000..fd137eb --- /dev/null +++ b/version @@ -0,0 +1 @@ +0.24