#!@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= local b4= local b3= local b2= local b1= 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}src/prokit" install \ -a "${host_arch}" -p "${host_plat}" \ ${mirror:+-m} ${mirror} 'dev/trunk' "${mountpoint}" printf '\nInstalling boot loader' printf '\n======================\n\n' read b4 b3 b2 b1 <<-EOF $(od -An -tx1 -v -j 440 -N 4 "/dev/${dev}") EOF # This ln command won't be needed once lilo 24.1-1 is uploaded. ln "${mountpoint}/boot/vmlinuz" "${mountpoint}/boot/vmlinuz.old" "${0%installers/pc}src/prokit" shell "${mountpoint}" \ install-lilo "/dev/${dev}" "PARTUUID=${b1}${b2}${b3}${b4}-01" umount_fs "${mountpoint}" } print_usage() { printf 'Usage: %s [-m ]\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 "${@}"