summaryrefslogtreecommitdiffstats
path: root/installers/pc.sh
diff options
context:
space:
mode:
Diffstat (limited to 'installers/pc.sh')
-rwxr-xr-xinstallers/pc.sh299
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 "${@}"