diff options
Diffstat (limited to 'installers/pc.sh')
-rwxr-xr-x | installers/pc.sh | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/installers/pc.sh b/installers/pc.sh new file mode 100755 index 0000000..bd83df7 --- /dev/null +++ b/installers/pc.sh @@ -0,0 +1,299 @@ +#!/bin/sh + +set -u + +# This should be maintained in order of compatibility, i.e. each arch can also +# run programs built for the arches before it. +ARCHES='i686 amd64' + +# Description CPU Plat +PLATS=' +Acer Aspire One AO751h i686 ao751h +Dell Dimension 2400 i686 dimension2400 +Lenovo ThinkPad X60/X60s/X60t i686 x60 +' + +main() +{ + local opt= + local mirror= + local install_arch= + local host_arch= + local host_plat= + local mountpoint= + + while getopts 'm:' opt; do + case ${opt} in + m) mirror="${OPTARG}";; + ?) + print_usage >&2 + exit 1 + ;; + esac + done + shift $(($OPTIND - 1)) + if [ ${#} -ne 0 ]; then + print_usage >&2 + exit 1 + fi + + install_arch="$(detect_arch)" + printf '\nSelect a platorm' + printf '\n================\n\n' + read host_arch host_plat <<-EOF + $(prompt_plat) + EOF + host_arch="${host_arch}-${install_arch#*-}" + check_arch_compat "${install_arch}" "${host_arch}" + + printf '\nSelect a block device' + printf '\n=====================\n\n' + dev="$(prompt_block_dev)" + + printf '\nMaking partition table and file system' + printf '\n======================================\n\n' + make_partition_and_fs "${dev}" + + printf '\nInstalling base system' + printf '\n======================\n\n' + + mountpoint="$(mount_fs "${dev}")" + "${0%installers/pc.sh}./miniprokit.sh" install \ + -a "${host_arch}" -P "${host_plat}" \ + ${mirror:+-m} ${mirror} "${mountpoint}" + mirror="$(printf '%s\n' "${mirror}" | \ + sed 's|^.*://||; s|^.*@||; s|/.*$||g;')" + printf '%s %s\n' "$(nslookup "${mirror}" | \ + sed -n '/Address: /{ s/Address: //; p; q; };')" \ + "${mirror}" >"${mountpoint}/etc/hosts" + "${0%installers/pc.sh}./miniprokit.sh" shell "${mountpoint}" \ + <"${0%pc.sh}data/pc.sh" + rm "${mountpoint}/etc/hosts" + umount_fs "${mountpoint}" +} + +print_usage() +{ + printf 'Usage: %s [-m <mirror>]\n' "${0}" +} + +error() +{ + local status=${1} + local fmt="${2}" + shift 2 + + printf "Error: ${fmt}\n" "${@}" >&2 + + exit ${status} +} + +_select() +{ + # Field width of the prompt numbers. + select_width=$(expr ${#} : '.*') + + select_i= + + while :; do + case "${select_i}" in + '') + select_i=0 + for select_word in "${@}"; do + select_i=$(expr ${select_i} + 1) + printf "%${select_width}d) %s\\n" \ + ${select_i} "${select_word}" \ + >&2 + done + ;; + *[!0-9]*) + printf 'Please enter a number in range.\n' >&2 + ;; + *) + if [ ${select_i} -gt 0 ] && \ + [ ${select_i} -le ${#} ]; then + shift $(expr $select_i - 1) + select_result="${1}" + break + fi + printf 'Please enter a number in range.\n' >&2 + ;; + esac + + # Prompt and read input. + printf '%s' "${PS3-#? }" >&2 + read -r select_i || exit + done +} + +detect_arch() +{ + local uname_m= + local uname_s= + local arch= + + uname_m="$( (uname -m) 2>/dev/null)" || uname_m='?' + uname_s="$( (uname -s) 2>/dev/null)" || uname_s='?' + case "${uname_m}:${uname_s}" in + 'i686:Linux') arch='i686-linux-glibc';; + 'x86_64:Linux') arch='amd64-linux-glibc';; + '?:?') error 2 'Architecture unknown';; + *) error 2 'Architecture unsupported';; + esac + + printf '%s\n' "${arch}" +} + +prompt_plat() +{ + local desc= + local arch= + local plat= + + set -- + while IFS=' ' read -r desc arch plat; do + [ "x${desc}" = 'x' ] && continue + set -- "${@}" "${desc}" + done <<-EOF + ${PLATS} + EOF + + printf 'Select a platform:\n' >&2 + _select "${@}" + + while IFS=' ' read -r desc arch plat; do + if [ "x${desc}" = "x${select_result}" ]; then + printf '%s %s\n' "${arch}" "${plat}" + break + fi + done <<-EOF + ${PLATS} + EOF +} + +check_arch_compat() +{ + local install_arch="${1}" + local host_arch="${2}" + local arches= + local install_cpu= + local host_cpu= + + if [ "x${install_arch}" = "x${host_arch}" ]; then + return 0 + fi + + arches="$(printf ' %s ' ${ARCHES})" + install_cpu="${install_arch%%-*}" + host_cpu="${host_arch%%-*}" + if [ "x${arches#* ${host_cpu} * ${install_cpu} }" = "x${arches}" ] + then + error 2 'Cannot install a system of architecture %s on %s %s' \ + "${host_arch}" 'a system of architecture' \ + "${install_arch}" + fi +} + +pretty_print_size_dec() +{ + local size="${1}" + + awk -v size=${size} 'BEGIN { + split("B KB MB GB TB", units, " "); + i=1; + while (size >= 1000) { + size /= 1000; + ++i; + }; + printf("%.2f %s\n", size, units[i]); }' +} + +pretty_print_size_bin() +{ + local size="${1}" + + awk -v size=${size} 'BEGIN { + split("B KiB MiB GiB TiB", units, " "); + i=1; + while (size >= 1024) { + size /= 1024; + ++i; + }; + printf("%.2f %s\n", size, units[i]); }' +} + +prompt_block_dev() +{ + local dev= + local vendor= + local model= + local name= + local size= + local size_s= + local desc= + local devs= + + set -- + for dev in /sys/block/*; do + dev="${dev#/sys/block/}" + case "${dev}" in + loop*|sr*) continue;; + esac + if [ -e "/sys/block/${dev}/device/vendor" ]; then + vendor="$(cat "/sys/block/${dev}/device/vendor")" + model="$(cat "/sys/block/${dev}/device/model")" + name="${vendor} ${model}" + else + name="$(cat "/sys/block/${dev}/device/name")" + fi + size="$(cat "/sys/block/${dev}/size")" + size="$(expr ${size} \* 512)" + size_s="$(pretty_print_size_dec "${size}")" + size_s="${size_s} ($(pretty_print_size_bin "${size}"))" + desc="$(printf '%s (%s) - %s\n' "${name}" "${dev}" "${size_s}")" + set -- "${@}" "${desc}" + devs="$(printf '%s\n%s\t%s\n' "${devs}" "${desc}" "${dev}")" + done + + printf 'Select a block device:\n' >&2 + _select "${@}" + + while IFS=' ' read -r desc dev; do + if [ "x${desc}" = "x${select_result}" ]; then + printf '%s\n' "${dev}" + fi + done <<-EOF + ${devs} + EOF +} + +make_partition_and_fs() +{ + local dev="${1}" + + dd if=/dev/zero of="/dev/${dev}" bs=512 count=1 + printf 'n\np\n1\n\n\nt\n83\na\n1\nw\n' | fdisk "/dev/${dev}" + mke2fs -t ext4 "/dev/${dev}1" +} + +mount_fs() +{ + local dev="${1}" + local mountpoint= + + mountpoint="$(mktemp -d)" + mount "/dev/${dev}1" "${mountpoint}" + printf '%s\n' "${mountpoint}" +} + +umount_fs() +{ + local mountpoint="${1}" + + while ! umount "${mountpoint}"; do + sleep 1 + done + rmdir "${mountpoint}" +} + +main "${@}" |