#!/usr/bin/python3 import os import sys import glob import subprocess import tempfile import shutil import re import functools # http://elinux.org/RPi_U-Boot parameters = dict( release='testing', #mirror='http://fr.archive.ubuntu.com/ubuntu/', mirror='http://httpredir.debian.org/debian', arch='armhf', packages=''' aptitude bash bash-completion bind9-host bmon busybox bzip2 curl htop iftop ifupdown iotop iperf iproute2 iptables iputils-ping less lftp linux-image-armmp-lpae locales ncdu ncurses-base ncurses-term net-tools netbase netcat nload openssh-client openssh-server psmisc python3 ranger rsync screen sed socat strace tar tcpdump telnet tmux tree tzdata vim vim-nox vim-runtime w3m wget zsh '''.split(), ) open8 = functools.partial(open, encoding='utf8') numerical_sort = lambda y: [int(x) if x.isdigit() else x for x in re.split('(\d+)', y)] def mlstrip(s): return re.sub(r'^\s*', '', s, flags=re.MULTILINE) def run(*l, **kw): print('run:', *l) return subprocess.run(*l, **kw) def reexec_root(): # run as root if os.geteuid() != 0: os.execvp("sudo", ["sudo"] + sys.argv) def system_customization(rootdir): os.unlink(rootdir + '/etc/localtime') open8(rootdir + '/etc/zoneinfo', 'w').write('Europe/Paris\n') shutil.copy(rootdir + '/usr/share/zoneinfo/Europe/Paris', rootdir + '/etc/localtime') open8(rootdir + '/etc/network/interfaces', 'w').write(mlstrip( '''\ auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp ''')) open8(rootdir + '/etc/hosts', 'w').write(mlstrip( '''\ 127.0.0.1 localhost localhost.localdomain debian # the following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters ''')) open8(rootdir + '/etc/hostname', 'w').write('debian\n') os.makedirs(rootdir + '/boot/firmware', mode=0o755) open8(rootdir + '/etc/fstab', 'w').write(mlstrip( '''\ # /dev/mmcblk0p2 / ext4 errors=remount-ro,relatime 0 1 /dev/mmcblk0p1 /boot/firmware vfat errors=remount-ro,relatime 0 2 ''')) # activate serial console run([ 'ln', '-s', '/lib/systemd/system/serial-getty@.service', rootdir + '/etc/systemd/system/getty.target.wants/serial-getty@ttyAMA0.service', ], check=True) os.makedirs(rootdir + '/etc/systemd/system/serial-getty@ttyAMA0.service.d', mode=0o755) open8(rootdir + '/etc/systemd/system/serial-getty@ttyAMA0.service.d/autologin.conf', 'w').write(mlstrip( '''\ [Service] ExecStart= ExecStart=-/sbin/agetty --autologin root --login-pause --noclear %I 115200,38400,9600 vt102 ''')) open8(rootdir + '/etc/default/keyboard', 'w').write(mlstrip( '''\ XKBMODEL="pc105" XKBLAYOUT="fr" XKBVARIANT="bepo" XKBOPTIONS="" ''')) open8(rootdir + '/etc/default/locale', 'w').write(mlstrip( '''\ LANG="en_US.UTF-8" LC_TIME="en_DK.UTF-8" LC_PAPER="en_GB.UTF-8" LC_MEASUREMENT="en_GB.UTF-8" ''')) for locale in ['fr_FR', 'en_US', 'en_GB', 'en_DK', 'de_DE']: run([ 'localedef', '--prefix={}'.format(rootdir), '-f', 'UTF-8', '-i', locale, '{}.UTF-8'.format(locale) ], check=True) open8(rootdir + '/etc/bash.bashrc', 'a').write(mlstrip( '''\ # enable bash completion in interactive shells if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi alias ls="ls --color=aut" alias l="ls -CF" alias ll="l -lh" alias la="l -a" alias e="vim" alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' export PAGER=less export EDITOR=vim export VISUAL=vim ''')) open8(rootdir + '/etc/vim/vimrc', 'w').write(mlstrip( '''\ set nocompatible au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif filetype plugin indent on set autoindent set background=dark set backspace=2 set hidden set hlsearch set ignorecase set incsearch set laststatus=2 set modelines=0 set nobackup set nowritebackup set ruler set scrolloff=3 set shiftwidth=4 set showcmd set showmatch set statusline=%<%f%h%m%r%=%l,%c\ %P set ts=4 set whichwrap=<,>,[,] set wildmode=list:full syntax on ''')) #kernel_params = 'ro text console=ttyAMA0,115200n8' #kernel_params += ' console=tty0 net.ifnames=0' #open8(rootdir + '/boot/grub/grub.cfg', 'w').write(mlstrip( # '''\ # terminal_output console # serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 # set default=0 # set timeout=3 # menuentry 'default' {{ # search --set=root --file /boot/grub/grub.cfg --hint hd0,gpt2 # linux /vmlinuz root=PARTUUID={rid} {kp} # initrd /initrd.img # }} # '''.format(rid=rootpartuuid, kp=kernel_params))) def main(): reexec_root() rootdir = 'debootstrapdir' os.makedirs(rootdir, mode=0o755) run([ 'qemu-debootstrap', '--arch=' + parameters['arch'], '--include=' + ','.join(parameters['packages']), '--components=main,contrib', parameters['release'], rootdir, parameters['mirror'], ], check=True) system_customization(rootdir) if __name__ == '__main__': main()