installer.sh.in 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. #!/bin/sh
  2. #-
  3. # Copyright (c) 2012-2014 Juan Romero Pardines <[email protected]>.
  4. # 2012 Dave Elusive <[email protected]>.
  5. # All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. # 1. Redistributions of source code must retain the above copyright
  11. # notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in the
  14. # documentation and/or other materials provided with the distribution.
  15. #
  16. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. #-
  27. # Make sure we don't inherit these from env.
  28. SOURCE_DONE=
  29. HOSTNAME_DONE=
  30. KEYBOARD_DONE=
  31. LOCALE_DONE=
  32. TIMEZONE_DONE=
  33. ROOTPASSWORD_DONE=
  34. BOOTLOADER_DONE=
  35. PARTITIONS_DONE=
  36. NETWORK_DONE=
  37. FILESYSTEMS_DONE=
  38. SYSTEMD_INIT=
  39. TARGETDIR=/mnt/target
  40. LOG=/dev/tty8
  41. CONF_FILE=/tmp/.void-installer.conf
  42. if [ ! -f $CONF_FILE ]; then
  43. touch -f $CONF_FILE
  44. fi
  45. ANSWER=$(mktemp -t vinstall-XXXXXXXX || exit 1)
  46. TARGET_FSTAB=$(mktemp -t vinstall-fstab-XXXXXXXX || exit 1)
  47. trap "DIE" INT TERM QUIT
  48. # disable printk
  49. if [ -w /proc/sys/kernel/printk ]; then
  50. echo 0 >/proc/sys/kernel/printk
  51. fi
  52. # Detect if this is an EFI system.
  53. if [ -e /sys/firmware/efi/systab ]; then
  54. EFI_SYSTEM=1
  55. fi
  56. # Detect if systemd is installed
  57. if [ "$(cat /proc/1/comm)" = "systemd" ]; then
  58. SYSTEMD_INIT=1
  59. fi
  60. # dialog colors
  61. BLACK="\Z0"
  62. RED="\Z1"
  63. GREEN="\Z2"
  64. YELLOW="\Z3"
  65. BLUE="\Z4"
  66. MAGENTA="\Z5"
  67. CYAN="\Z6"
  68. WHITE="\Z7"
  69. BOLD="\Zb"
  70. REVERSE="\Zr"
  71. UNDERLINE="\Zu"
  72. RESET="\Zn"
  73. # Properties shared per widget.
  74. MENULABEL="${BOLD}Use UP and DOWN keys to navigate \
  75. menus. Use TAB to switch between buttons and ENTER to select.${RESET}"
  76. MENUSIZE="14 60 0"
  77. INPUTSIZE="8 60"
  78. MSGBOXSIZE="8 70"
  79. YESNOSIZE="$INPUTSIZE"
  80. WIDGET_SIZE="10 70"
  81. DIALOG() {
  82. rm -f $ANSWER
  83. dialog --colors --keep-tite --no-shadow --no-mouse \
  84. --backtitle "${BOLD}${WHITE}Void Linux installation -- http://www.voidlinux.eu/ (@@MKLIVE_VERSION@@)${RESET}" \
  85. --cancel-label "Back" --aspect 20 "$@" 2>$ANSWER
  86. return $?
  87. }
  88. DIE() {
  89. rval=$1
  90. [ -z "$rval" ] && rval=0
  91. clear
  92. rm -f $ANSWER $TARGET_FSTAB
  93. # reenable printk
  94. if [ -w /proc/sys/kernel/printk ]; then
  95. echo 4 >/proc/sys/kernel/printk
  96. fi
  97. umount_filesystems
  98. exit $rval
  99. }
  100. set_option() {
  101. if grep -Eq "^${1}.*" $CONF_FILE; then
  102. sed -i -e "/^${1}.*/d" $CONF_FILE
  103. fi
  104. echo "${1} ${2}" >>$CONF_FILE
  105. }
  106. get_option() {
  107. echo $(grep -E "^${1}.*" $CONF_FILE|sed -e "s|${1}||")
  108. }
  109. show_disks() {
  110. local dev size sectorsize gbytes
  111. # IDE
  112. for dev in $(ls /sys/block|grep -E '^hd'); do
  113. if [ "$(cat /sys/block/$dev/device/media)" = "disk" ]; then
  114. # Find out nr sectors and bytes per sector;
  115. echo "/dev/$dev"
  116. size=$(cat /sys/block/$dev/size)
  117. sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size)
  118. gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))"
  119. echo "size:${gbytes}GB;sector_size:$sectorsize"
  120. fi
  121. done
  122. # SATA/SCSI and Virtual disks (virtio)
  123. for dev in $(ls /sys/block|grep -E '^([sv]|xv)d|mmcblk'); do
  124. echo "/dev/$dev"
  125. size=$(cat /sys/block/$dev/size)
  126. sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size)
  127. gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))"
  128. echo "size:${gbytes}GB;sector_size:$sectorsize"
  129. done
  130. }
  131. show_partitions() {
  132. local dev fstype fssize p part
  133. set -- $(show_disks)
  134. while [ $# -ne 0 ]; do
  135. disk=$(basename $1)
  136. shift 2
  137. # ATA/SCSI/SATA
  138. for p in /sys/block/$disk/$disk*; do
  139. if [ -d $p ]; then
  140. part=$(basename $p)
  141. fstype=$(lsblk -nfr /dev/$part|awk '{print $2}'|head -1)
  142. [ "$fstype" = "iso9660" ] && continue
  143. [ "$fstype" = "crypto_LUKS" ] && continue
  144. [ "$fstype" = "LVM2_member" ] && continue
  145. fssize=$(lsblk -nr /dev/$part|awk '{print $4}'|head -1)
  146. echo "/dev/$part"
  147. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  148. fi
  149. done
  150. done
  151. # Software raid (md)
  152. for p in $(ls -d /dev/md* 2>/dev/null|grep '[0-9]'); do
  153. part=$(basename $p)
  154. if cat /proc/mdstat|grep -qw $part; then
  155. fstype=$(lsblk -nfr /dev/$part|awk '{print $2}')
  156. [ "$fstype" = "crypto_LUKS" ] && continue
  157. [ "$fstype" = "LVM2_member" ] && continue
  158. fssize=$(lsblk -nr /dev/$part|awk '{print $4}')
  159. echo "$p"
  160. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  161. fi
  162. done
  163. if [ -e /sbin/lvs ]; then
  164. # LVM
  165. lvs --noheadings|while read lvname vgname perms size; do
  166. echo "/dev/mapper/${vgname}-${lvname}"
  167. echo "size:${size};fstype:lvm"
  168. done
  169. fi
  170. }
  171. menu_filesystems() {
  172. local dev fstype fssize mntpoint reformat
  173. while true; do
  174. DIALOG --title " Select the partition to edit " --menu "$MENULABEL" \
  175. ${MENUSIZE} $(show_partitions)
  176. [ $? -ne 0 ] && return
  177. dev=$(cat $ANSWER)
  178. DIALOG --title " Select the filesystem type for $dev " \
  179. --menu "$MENULABEL" ${MENUSIZE} \
  180. "btrfs" "Oracle's Btrfs" \
  181. "ext2" "Linux ext2 (no journaling)" \
  182. "ext3" "Linux ext3 (journal)" \
  183. "ext4" "Linux ext4 (journal)" \
  184. "f2fs" "Flash-Friendly Filesystem" \
  185. "swap" "Linux swap" \
  186. "vfat" "FAT32" \
  187. "xfs" "SGI's XFS"
  188. if [ $? -eq 0 ]; then
  189. fstype=$(cat $ANSWER)
  190. else
  191. continue
  192. fi
  193. if [ "$fstype" != "swap" ]; then
  194. DIALOG --inputbox "Please specify the mount point for $dev:" ${INPUTSIZE}
  195. if [ $? -eq 0 ]; then
  196. mntpoint=$(cat $ANSWER)
  197. elif [ $? -eq 1 ]; then
  198. continue
  199. fi
  200. else
  201. mntpoint=swap
  202. fi
  203. DIALOG --yesno "Do you want to create a new filesystem on $dev?" ${YESNOSIZE}
  204. if [ $? -eq 0 ]; then
  205. reformat=1
  206. elif [ $? -eq 1 ]; then
  207. reformat=0
  208. else
  209. continue
  210. fi
  211. fssize=$(lsblk -nr $dev|awk '{print $4}')
  212. set -- "$fstype" "$fssize" "$mntpoint" "$reformat"
  213. if [ -n "$1" -a -n "$2" -a -n "$3" -a -n "$4" ]; then
  214. local bdev=$(basename $dev)
  215. if grep -Eq "^MOUNTPOINT \/dev\/${bdev}.*" $CONF_FILE; then
  216. sed -i -e "/^MOUNTPOINT \/dev\/${bdev}.*/d" $CONF_FILE
  217. fi
  218. echo "MOUNTPOINT $dev $1 $2 $3 $4" >>$CONF_FILE
  219. fi
  220. done
  221. }
  222. menu_partitions() {
  223. DIALOG --title " Select the disk to partition " \
  224. --menu "$MENULABEL" ${MENUSIZE} $(show_disks)
  225. if [ $? -eq 0 ]; then
  226. local device=$(cat $ANSWER)
  227. DIALOG --title "Modify Partition Table on $device" --msgbox "\n
  228. ${BOLD}cfdisk will be executed in disk $device.${RESET}\n\n
  229. For BIOS systems, MBR or GPT partition tables are supported.\n
  230. To use GPT on PC BIOS systems an empty partition of 1MB must be added\n
  231. at the first 2GB of the disk with the TOGGLE \`bios_grub' enabled.\n
  232. ${BOLD}NOTE: you don't need this on EFI systems.${RESET}\n\n
  233. For EFI systems GPT is mandatory and a FAT32 partition with at least\n
  234. 100MB must be created with the TOGGLE \`boot', this will be used as\n
  235. EFI System Partition. This partition must have mountpoint as \`/boot/efi'.\n\n
  236. At least 1 partitions is required for the rootfs (/).\n
  237. For swap, RAM*2 must be really enough. For / 600MB are required.\n\n
  238. ${BOLD}WARNING: /usr is not supported as a separate partition.${RESET}\n
  239. ${RESET}\n" 18 80
  240. if [ $? -eq 0 ]; then
  241. while true; do
  242. clear; cfdisk $device; PARTITIONS_DONE=1
  243. break
  244. done
  245. else
  246. return
  247. fi
  248. fi
  249. }
  250. menu_keymap() {
  251. if [ -n "$SYSTEMD_INIT" ]; then
  252. local _keymaps="$(localectl --no-pager list-keymaps)"
  253. else
  254. local _keymaps="$(find /usr/share/kbd/keymaps/ -type f -iname "*.map.gz" -printf "%f\n" | sed 's|.map.gz||g' | sort)"
  255. fi
  256. local _KEYMAPS=
  257. for f in ${_keymaps}; do
  258. _KEYMAPS="${_KEYMAPS} ${f} -"
  259. done
  260. while true; do
  261. DIALOG --title " Select your keymap " --menu "$MENULABEL" 14 70 14 ${_KEYMAPS}
  262. if [ $? -eq 0 ]; then
  263. set_option KEYMAP "$(cat $ANSWER)"
  264. loadkeys "$(cat $ANSWER)"
  265. KEYBOARD_DONE=1
  266. break
  267. else
  268. return
  269. fi
  270. done
  271. }
  272. set_keymap() {
  273. local KEYMAP=$(get_option KEYMAP)
  274. if [ -f /etc/vconsole.conf ]; then
  275. sed -i -e "s|KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/vconsole.conf
  276. else
  277. sed -i -e "s|KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/rc.conf
  278. fi
  279. }
  280. menu_locale() {
  281. local _locales="$(grep -E '\.UTF-8' /etc/default/libc-locales|awk '{print $1}'|sed -e 's/^#//')"
  282. local _LOCALES=
  283. for f in ${_locales}; do
  284. _LOCALES="${_LOCALES} ${f} -"
  285. done
  286. while true; do
  287. DIALOG --title " Select your locale " --menu "$MENULABEL" 14 70 14 ${_LOCALES}
  288. if [ $? -eq 0 ]; then
  289. set_option LOCALE "$(cat $ANSWER)"
  290. LOCALE_DONE=1
  291. break
  292. else
  293. return
  294. fi
  295. done
  296. }
  297. set_locale() {
  298. local LOCALE=$(get_option LOCALE)
  299. sed -i -e "s|LANG=.*|LANG=$LOCALE|g" $TARGETDIR/etc/locale.conf
  300. # Uncomment locale from /etc/default/libc-locales and regenerate it.
  301. sed -e "/${LOCALE}/s/^\#//" -i $TARGETDIR/etc/default/libc-locales
  302. echo "Running xbps-reconfigure -f glibc-locales ..." >$LOG
  303. chroot $TARGETDIR xbps-reconfigure -f glibc-locales >$LOG 2>&1
  304. }
  305. menu_timezone() {
  306. if [ -n "$SYSTEMD_INIT" ]; then
  307. local _tzones="$(timedatectl --no-pager list-timezones)"
  308. else
  309. local _tzones="$(cd /usr/share/zoneinfo; find Africa/ America/ Antarctica/ Arctic/ Asia/ Atlantic/ Australia/ Europe/ Indian/ Pacific/ -type f | sort)"
  310. fi
  311. local _TIMEZONES=
  312. for f in ${_tzones}; do
  313. _TIMEZONES="${_TIMEZONES} ${f} -"
  314. done
  315. while true; do
  316. DIALOG --title " Select your timezone " --menu "$MENULABEL" 14 70 14 ${_TIMEZONES}
  317. if [ $? -eq 0 ]; then
  318. set_option TIMEZONE "$(cat $ANSWER)"
  319. TIMEZONE_DONE=1
  320. break
  321. else
  322. return
  323. fi
  324. done
  325. }
  326. set_timezone() {
  327. local TIMEZONE="$(get_option TIMEZONE)"
  328. if [ -z "$SYSTEMD_INIT" ]; then
  329. sed -i -e "s|#TIMEZONE=.*|TIMEZONE=$TIMEZONE|g" $TARGETDIR/etc/rc.conf
  330. else
  331. ln -sf /usr/share/zoneinfo/${TIMEZONE} $TARGETDIR/etc/localtime
  332. fi
  333. }
  334. menu_hostname() {
  335. while true; do
  336. DIALOG --inputbox "Set the machine hostname:" ${INPUTSIZE}
  337. if [ $? -eq 0 ]; then
  338. set_option HOSTNAME "$(cat $ANSWER)"
  339. HOSTNAME_DONE=1
  340. break
  341. else
  342. return
  343. fi
  344. done
  345. }
  346. set_hostname() {
  347. echo $(get_option HOSTNAME) > $TARGETDIR/etc/hostname
  348. }
  349. menu_rootpassword() {
  350. local _firstpass= _secondpass= _desc=
  351. while true; do
  352. if [ -n "${_firstpass}" ]; then
  353. _desc="Enter the root password again (password won't be displayed)"
  354. else
  355. _desc="Enter the root password (password won't be displayed)"
  356. fi
  357. DIALOG --passwordbox "${_desc}" ${MSGBOXSIZE}
  358. if [ $? -eq 0 ]; then
  359. if [ -z "${_firstpass}" ]; then
  360. _firstpass="$(cat $ANSWER)"
  361. else
  362. _secondpass="$(cat $ANSWER)"
  363. fi
  364. if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then
  365. if [ "${_firstpass}" != "${_secondpass}" ]; then
  366. DIALOG --infobox "Passwords do not match! please reenter it again" 6 80
  367. unset _firstpass _secondpass
  368. sleep 2 && continue
  369. fi
  370. set_option ROOTPASSWORD "${_firstpass}"
  371. ROOTPASSWORD_DONE=1
  372. break
  373. fi
  374. else
  375. return
  376. fi
  377. done
  378. }
  379. set_rootpassword() {
  380. echo "root:$(get_option ROOTPASSWORD)" | chpasswd -R $TARGETDIR -c SHA512
  381. }
  382. menu_bootloader() {
  383. while true; do
  384. DIALOG --title " Select the disk to install the bootloader" \
  385. --menu "$MENULABEL" ${MENUSIZE} $(show_disks) none "Manage bootloader otherwise"
  386. if [ $? -eq 0 ]; then
  387. set_option BOOTLOADER "$(cat $ANSWER)"
  388. BOOTLOADER_DONE=1
  389. break
  390. else
  391. return
  392. fi
  393. done
  394. }
  395. set_bootloader() {
  396. local dev=$(get_option BOOTLOADER) grub_args=
  397. if [ "$dev" = "none" ]; then return; fi
  398. # Check if it's an EFI system via efivars module.
  399. if [ -n "$EFI_SYSTEM" ]; then
  400. grub_args="--target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=void_grub --recheck"
  401. fi
  402. echo "Running grub-install $grub_args $dev..." >$LOG
  403. chroot $TARGETDIR grub-install $grub_args $dev >$LOG 2>&1
  404. if [ $? -ne 0 ]; then
  405. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  406. failed to install GRUB to $dev!\nCheck $LOG for errors." ${MSGBOXSIZE}
  407. DIE 1
  408. fi
  409. echo "Running grub-mkconfig on $TARGETDIR..." >$LOG
  410. chroot $TARGETDIR grub-mkconfig -o /boot/grub/grub.cfg >$LOG 2>&1
  411. if [ $? -ne 0 ]; then
  412. DIALOG --msgbox "${BOLD}${RED}ERROR${RESET}: \
  413. failed to run grub-mkconfig!\nCheck $LOG for errors." ${MSGBOXSIZE}
  414. DIE 1
  415. fi
  416. }
  417. test_network() {
  418. rm -f xtraeme.asc && \
  419. xbps-uhelper fetch http://repo.voidlinux.eu/live/xtraeme.asc >$LOG 2>&1
  420. if [ $? -eq 0 ]; then
  421. DIALOG --msgbox "Network is working properly!" ${MSGBOXSIZE}
  422. NETWORK_DONE=1
  423. return 1
  424. fi
  425. DIALOG --msgbox "Network is unaccessible, please setup it properly." ${MSGBOXSIZE}
  426. }
  427. configure_wifi() {
  428. local dev="$1" ssid enc pass _wpasupconf=/etc/wpa_supplicant/wpa_supplicant.conf
  429. DIALOG --form "Wireless configuration for ${dev}\n(encryption type: wep or wpa)" 0 0 0 \
  430. "SSID:" 1 1 "" 1 16 30 0 \
  431. "Encryption:" 2 1 "" 2 16 3 0 \
  432. "Password:" 3 1 "" 3 16 50 0 || return 1
  433. set -- $(cat $ANSWER)
  434. ssid="$1"; enc="$2"; pass="$3";
  435. if [ -z "$ssid" ]; then
  436. DIALOG --msgbox "Invalid SSID." ${MSGBOXSIZE}
  437. return 1
  438. elif [ -z "$enc" -o "$enc" != "wep" -a "$enc" != "wpa" ]; then
  439. DIALOG --msgbox "Invalid encryption type (possible values: wep or wpa)." ${MSXBOXSIZE}
  440. return 1
  441. elif [ -z "$pass" ]; then
  442. DIALOG --msgbox "Invalid AP password." ${MSGBOXSIZE}
  443. fi
  444. rm -f ${_wpasupconf%.conf}-${dev}.conf
  445. cp -f ${_wpasupconf} ${_wpasupconf%.conf}-${dev}.conf
  446. if [ "$enc" = "wep" ]; then
  447. echo "network={" >> ${_wpasupconf%.conf}-${dev}.conf
  448. echo " ssid=\"$ssid\"" >> ${_wpasupconf%.conf}-${dev}.conf
  449. echo " wep_key0=\"$pass\"" >> ${_wpasupconf%.conf}-${dev}.conf
  450. echo " wep_tx_keyidx=0" >> ${_wpasupconf%.conf}-${dev}.conf
  451. echo " auth_alg=SHARED" >> ${_wpasupconf%.conf}-${dev}.conf
  452. echo "}" >> ${_wpasupconf%.conf}-${dev}.conf
  453. else
  454. wpa_passphrase "$ssid" "$pass" >> ${_wpasupconf%.conf}-${dev}.conf
  455. fi
  456. configure_net_dhcp $dev
  457. return $?
  458. }
  459. configure_net() {
  460. local dev="$1" rval
  461. DIALOG --yesno "Do you want to use DHCP for $dev?" ${YESNOSIZE}
  462. rval=$?
  463. if [ $rval -eq 0 ]; then
  464. configure_net_dhcp $dev
  465. elif [ $rval -eq 1 ]; then
  466. configure_net_static $dev
  467. fi
  468. }
  469. iface_setup() {
  470. ip addr show dev $1|grep -q 'inet '
  471. return $?
  472. }
  473. configure_net_dhcp() {
  474. local dev="$1"
  475. iface_setup $dev
  476. if [ $? -eq 1 ]; then
  477. dhcpcd -t 10 -w -4 -L $dev -e "wpa_supplicant_conf=/etc/wpa_supplicant/wpa_supplicant-${dev}.conf" 2>&1 | tee $LOG | \
  478. DIALOG --progressbox "Initializing $dev via DHCP..." ${WIDGET_SIZE}
  479. if [ $? -ne 0 ]; then
  480. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to run dhcpcd. See $LOG for details." ${MSGBOXSIZE}
  481. return 1
  482. fi
  483. iface_setup $dev
  484. if [ $? -eq 1 ]; then
  485. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} DHCP request failed for $dev. Check $LOG for errors." ${MSGBOXSIZE}
  486. return 1
  487. fi
  488. fi
  489. test_network
  490. if [ $? -eq 1 ]; then
  491. set_option NETWORK "${dev} dhcp"
  492. fi
  493. }
  494. configure_net_static() {
  495. local ip gw dns1 dns2 dev=$1
  496. DIALOG --form "Static IP configuration for $dev:" 0 0 0 \
  497. "IP address:" 1 1 "192.168.0.2" 1 21 20 0 \
  498. "Gateway:" 2 1 "192.168.0.1" 2 21 20 0 \
  499. "DNS Primary" 3 1 "8.8.8.8" 3 21 20 0 \
  500. "DNS Secondary" 4 1 "8.8.4.4" 4 21 20 0 || return 1
  501. set -- $(cat $ANSWER)
  502. ip=$1; gw=$2; dns1=$3; dns2=$4
  503. echo "running: ip link set dev $dev up" >$LOG
  504. ip link set dev $dev up >$LOG 2>&1
  505. if [ $? -ne 0 ]; then
  506. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to bring $dev interface." ${MSGBOXSIZE}
  507. return 1
  508. fi
  509. echo "running: ip addr add $ip dev $dev"
  510. ip addr add $ip dev $dev >$LOG 2>&1
  511. if [ $? -ne 0 ]; then
  512. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to set ip to the $dev interface." ${MSGBOXSIZE}
  513. return 1
  514. fi
  515. ip route add $gw dev $dev >$LOG 2>&1
  516. if [ $? -ne 0 ]; then
  517. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to setup your gateway." ${MSGBOXSIZE}
  518. return 1
  519. fi
  520. echo "nameserver $dns1" >/etc/resolv.conf
  521. echo "nameserver $dns2" >>/etc/resolv.conf
  522. test_network
  523. if [ $? -eq 1 ]; then
  524. set_option NETWORK "${dev} static $ip $gw $dns1 $dns2"
  525. fi
  526. }
  527. menu_network() {
  528. local dev addr f DEVICES
  529. for f in $(ls /sys/class/net); do
  530. [ "$f" = "lo" ] && continue
  531. addr=$(cat /sys/class/net/$f/address)
  532. DEVICES="$DEVICES $f $addr"
  533. done
  534. DIALOG --title " Select the network interface to configure " \
  535. --menu "$MENULABEL" ${MENUSIZE} ${DEVICES}
  536. if [ $? -eq 0 ]; then
  537. dev=$(cat $ANSWER)
  538. if $(echo $dev|egrep -q "^wl.*" 2>/dev/null); then
  539. configure_wifi $dev
  540. else
  541. configure_net $dev
  542. fi
  543. fi
  544. }
  545. validate_filesystems() {
  546. local mnts dev size fstype mntpt mkfs rootfound fmt
  547. local usrfound efi_system_partition
  548. unset TARGETFS
  549. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  550. set -- ${mnts}
  551. while [ $# -ne 0 ]; do
  552. dev=$2; fstype=$3; size=$4; mntpt="$5"; mkfs=$6
  553. shift 6
  554. if [ "$mntpt" = "/" ]; then
  555. rootfound=1
  556. elif [ "$mntpt" = "/usr" ]; then
  557. usrfound=1
  558. elif [ "$fstype" = "vfat" -a "$mntpt" = "/boot/efi" ]; then
  559. efi_system_partition=1
  560. fi
  561. if [ "$mkfs" -eq 1 ]; then
  562. fmt="NEW FILESYSTEM: "
  563. fi
  564. if [ -z "$TARGETFS" ]; then
  565. TARGETFS="${fmt}$dev ($size) mounted on $mntpt as ${fstype}\n"
  566. else
  567. TARGETFS="${TARGETFS}${fmt}${dev} ($size) mounted on $mntpt as ${fstype}\n"
  568. fi
  569. done
  570. if [ -z "$rootfound" ]; then
  571. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  572. the mount point for the root filesystem (/) has not yet been configured." ${MSGBOXSIZE}
  573. return 1
  574. elif [ -n "$usrfound" ]; then
  575. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  576. /usr mount point has been configured but is not supported, please remove it to continue." ${MSGBOXSIZE}
  577. return 1
  578. elif [ -n "$EFI_SYSTEM" -a -z "$efi_system_partition" ]; then
  579. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  580. The EFI System Partition has not yet been configured, please create it\n
  581. as FAT32, mountpoint /boot/efi and at least with 100MB of size." ${MSGBOXSIZE}
  582. fi
  583. FILESYSTEMS_DONE=1
  584. }
  585. create_filesystems() {
  586. local mnts dev mntpt fstype fspassno mkfs size rv uuid
  587. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  588. set -- ${mnts}
  589. while [ $# -ne 0 ]; do
  590. dev=$2; fstype=$3; mntpt="$5"; mkfs=$6
  591. shift 6
  592. # swap partitions
  593. if [ "$fstype" = "swap" ]; then
  594. swapoff $dev >/dev/null 2>&1
  595. if [ "$mkfs" -eq 1 ]; then
  596. mkswap $dev >$LOG 2>&1
  597. if [ $? -ne 0 ]; then
  598. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  599. failed to create swap on ${dev}!\ncheck $LOG for errors." ${MSGBOXSIZE}
  600. DIE 1
  601. fi
  602. fi
  603. swapon $dev >$LOG 2>&1
  604. if [ $? -ne 0 ]; then
  605. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  606. failed to activate swap on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE}
  607. DIE 1
  608. fi
  609. # Add entry for target fstab
  610. uuid=$(blkid -o value -s UUID "$dev")
  611. echo "UUID=$uuid none swap sw 0 0" >>$TARGET_FSTAB
  612. continue
  613. fi
  614. if [ "$mkfs" -eq 1 ]; then
  615. case "$fstype" in
  616. btrfs) MKFS="mkfs.btrfs -f"; modprobe btrfs >$LOG 2>&1;;
  617. ext2) MKFS="mke2fs -F"; modprobe ext2 >$LOG 2>&1;;
  618. ext3) MKFS="mke2fs -F -j"; modprobe ext3 >$LOG 2>&1;;
  619. ext4) MKFS="mke2fs -F -t ext4"; modprobe ext4 >$LOG 2>&1;;
  620. f2fs) MKFS="mkfs.f2fs"; modprobe f2fs >$LOG 2>&1;;
  621. vfat) MKFS="mkfs.vfat -F32"; modprobe vfat >$LOG 2>&1;;
  622. xfs) MKFS="mkfs.xfs -f"; modprobe xfs >$LOG 2>&1;;
  623. esac
  624. DIALOG --infobox "Creating filesystem $fstype on $dev for $mntpt ..." 8 60
  625. echo "Running $MKFS $dev..." >$LOG
  626. $MKFS $dev >$LOG 2>&1; rv=$?
  627. if [ $rv -ne 0 ]; then
  628. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  629. failed to create filesystem $fstype on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE}
  630. DIE 1
  631. fi
  632. fi
  633. # Mount rootfs the first one.
  634. [ "$mntpt" != "/" ] && continue
  635. mkdir -p $TARGETDIR
  636. echo "Mounting $dev on $mntpt ($fstype)..." >$LOG
  637. mount -t $fstype $dev $TARGETDIR >$LOG 2>&1
  638. if [ $? -ne 0 ]; then
  639. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  640. failed to mount $dev on ${mntpt}! check $LOG for errors." ${MSGBOXSIZE}
  641. DIE 1
  642. fi
  643. # Add entry to target fstab
  644. uuid=$(blkid -o value -s UUID "$dev")
  645. if [ "$fstype" = "f2fs" ]; then
  646. fspassno=0
  647. else
  648. fspassno=1
  649. fi
  650. echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB
  651. done
  652. # mount all filesystems in target rootfs
  653. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  654. set -- ${mnts}
  655. while [ $# -ne 0 ]; do
  656. dev=$2; fstype=$3; mntpt="$5"
  657. shift 6
  658. [ "$mntpt" = "/" -o "$fstype" = "swap" ] && continue
  659. mkdir -p ${TARGETDIR}${mntpt}
  660. echo "Mounting $dev on $mntpt ($fstype)..." >$LOG
  661. mount -t $fstype $dev ${TARGETDIR}${mntpt} >$LOG 2>&1
  662. if [ $? -ne 0 ]; then
  663. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  664. failed to mount $dev on $mntpt! check $LOG for errors." ${MSGBOXSIZE}
  665. DIE
  666. fi
  667. # Add entry to target fstab
  668. uuid=$(blkid -o value -s UUID "$dev")
  669. echo "UUID=$uuid $mntpt $fstype defaults 0 2" >>$TARGET_FSTAB
  670. done
  671. }
  672. mount_filesystems() {
  673. for f in sys proc dev; do
  674. [ ! -d $TARGETDIR/$f ] && mkdir $TARGETDIR/$f
  675. echo "Mounting $TARGETDIR/$f..." >$LOG
  676. mount --bind /$f $TARGETDIR/$f >$LOG 2>&1
  677. done
  678. }
  679. umount_filesystems() {
  680. local f
  681. for f in sys/fs/fuse/connections sys proc dev; do
  682. echo "Unmounting $TARGETDIR/$f..." >$LOG
  683. umount $TARGETDIR/$f >$LOG 2>&1
  684. done
  685. local mnts="$(grep -E '^MOUNTPOINT.*$' $CONF_FILE)"
  686. set -- ${mnts}
  687. while [ $# -ne 0 ]; do
  688. local dev=$2; local fstype=$3; local mntpt=$5
  689. shift 6
  690. if [ "$fstype" = "swap" ]; then
  691. echo "Disabling swap space on $dev..." >$LOG
  692. swapoff $dev >$LOG 2>&1
  693. continue
  694. fi
  695. if [ "$mntpt" != "/" ]; then
  696. echo "Unmounting $TARGETDIR/$mntpt..." >$LOG
  697. umount $TARGETDIR/$mntpt >$LOG 2>&1
  698. fi
  699. done
  700. echo "Unmounting $TARGETDIR..." >$LOG
  701. umount $TARGETDIR >$LOG 2>&1
  702. }
  703. copy_rootfs() {
  704. DIALOG --title "Check $LOG for details" \
  705. --infobox "Copying live image to target rootfs, please wait ..." 4 60
  706. LANG=C cp -axvnu / $TARGETDIR >$LOG 2>&1
  707. if [ $? -ne 0 ]; then
  708. DIE 1
  709. fi
  710. }
  711. install_packages() {
  712. local _grub= _syspkg=
  713. if [ -n "$EFI_SYSTEM" ]; then
  714. _grub="grub-x86_64-efi"
  715. else
  716. _grub="grub"
  717. fi
  718. _syspkg="base-system"
  719. mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share
  720. cp -a /usr/share/xbps.d $TARGETDIR/usr/share/
  721. cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys
  722. mkdir -p $TARGETDIR/boot/grub
  723. _arch=$(xbps-uhelper arch)
  724. stdbuf -oL env XBPS_ARCH=${_arch} \
  725. xbps-install -r $TARGETDIR -Sy ${_syspkg} ${_grub} 2>&1 | \
  726. DIALOG --title "Installing base system packages..." \
  727. --programbox 24 80
  728. if [ $? -ne 0 ]; then
  729. DIE 1
  730. fi
  731. # If uname -m != _arch perform a reconfiguration.
  732. if [ "$(uname -m)" != "${_arch}" ]; then
  733. XBPS_ARCH=${_arch} xbps-reconfigure -r $TARGETDIR -a
  734. fi
  735. }
  736. enable_dhcpd() {
  737. if [ -n "$SYSTEMD_INIT" ]; then
  738. chroot $TARGETDIR systemctl enable dhcpcd.service >$LOG 2>&1
  739. else
  740. ln -s /etc/sv/dhcpcd $TARGETDIR/etc/runit/runsvdir/default/dhcpcd
  741. fi
  742. }
  743. menu_install() {
  744. # Don't continue if filesystems are not ready.
  745. validate_filesystems || return 1
  746. ROOTPASSWORD_DONE="$(get_option ROOTPASSWORD)"
  747. BOOTLOADER_DONE="$(get_option BOOTLOADER)"
  748. if [ -z "$FILESYSTEMS_DONE" ]; then
  749. DIALOG --msgbox "${BOLD}Required filesystems were not configured, \
  750. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  751. return 1
  752. elif [ -z "$ROOTPASSWORD_DONE" ]; then
  753. DIALOG --msgbox "${BOLD}The root password has not been configured, \
  754. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  755. return 1
  756. elif [ -z "$BOOTLOADER_DONE" ]; then
  757. DIALOG --msgbox "${BOLD}The disk to install the bootloader has not been \
  758. configured, please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  759. return 1
  760. fi
  761. DIALOG --yesno "${BOLD}The following operations will be executed:${RESET}\n\n
  762. ${BOLD}${TARGETFS}${RESET}\n
  763. ${BOLD}${RED}WARNING: data on partitions will be COMPLETELY DESTROYED for new \
  764. filesystems.${RESET}\n\n
  765. ${BOLD}Do you want to continue?${RESET}" 20 80 || return
  766. unset TARGETFS
  767. # Create and mount filesystems
  768. create_filesystems
  769. # If source not set use defaults.
  770. if [ "$(get_option SOURCE)" = "local" -o -z "$SOURCE_DONE" ]; then
  771. copy_rootfs
  772. . /etc/default/live.conf
  773. rm -f $TARGETDIR/etc/motd
  774. rm -f $TARGETDIR/etc/issue
  775. rm -f $TARGETDIR/usr/sbin/void-installer
  776. # Remove live user.
  777. echo "Removing $USERNAME live user from targetdir ..." >$LOG
  778. chroot $TARGETDIR userdel -r $USERNAME >$LOG 2>&1
  779. DIALOG --title "Check $LOG for details" \
  780. --infobox "Rebuilding initramfs for target ..." 4 60
  781. echo "Rebuilding initramfs for target ..." >$LOG
  782. # mount required fs
  783. mount_filesystems
  784. chroot $TARGETDIR dracut --no-hostonly --add-drivers "ahci" --force >>$LOG 2>&1
  785. DIALOG --title "Check $LOG for details" \
  786. --infobox "Removing temporary packages from target ..." 4 60
  787. echo "Removing temporary packages from target ..." >$LOG
  788. xbps-remove -r $TARGETDIR -Ry dialog >>$LOG 2>&1
  789. rmdir $TARGETDIR/mnt/target
  790. else
  791. # mount required fs
  792. mount_filesystems
  793. # network install, use packages.
  794. install_packages
  795. fi
  796. DIALOG --infobox "Applying installer settings..." 4 60
  797. # copy target fstab.
  798. install -Dm644 $TARGET_FSTAB $TARGETDIR/etc/fstab
  799. # Mount /tmp as tmpfs.
  800. echo "tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TARGETDIR/etc/fstab
  801. # set up keymap, locale, timezone, hostname and root passwd.
  802. set_keymap
  803. set_locale
  804. set_timezone
  805. set_hostname
  806. set_rootpassword
  807. # Copy /etc/skel files for root.
  808. cp $TARGETDIR/etc/skel/.[bix]* $TARGETDIR/root
  809. # network settings for target
  810. if [ -n "$NETWORK_DONE" ]; then
  811. local net="$(get_option NETWORK)"
  812. set -- ${net}
  813. local _dev="$1" _type="$2" _ip="$3" _gw="$4" _dns1="$5" _dns2="$6"
  814. if [ -z "$_type" ]; then
  815. # network type empty??!!!
  816. :
  817. elif [ "$_type" = "dhcp" ]; then
  818. if [ -f /etc/wpa_supplicant/wpa_supplicant-${_dev}.conf ]; then
  819. cp /etc/wpa_supplicant/wpa_supplicant-${_dev}.conf $TARGETDIR/etc/wpa_supplicant
  820. if [ -n "$SYSTEMD_INIT" ]; then
  821. chroot $TARGETDIR systemctl enable dhcpcd@${_dev}.service >$LOG 2>&1
  822. else
  823. ln -s /etc/sv/dhcpcd-${_dev} $TARGETDIR/etc/runit/runsvdir/default/dhcpcd-${_dev}
  824. fi
  825. else
  826. enable_dhcpd
  827. fi
  828. elif [ -n "$dev" -a -n "$type" = "static" ]; then
  829. # static IP through dhcpcd.
  830. mv $TARGETDIR/etc/dhcpcd.conf $TARGETDIR/etc/dhdpcd.conf.orig
  831. echo "# Static IP configuration set by the void-installer for $_dev." \
  832. >$TARGETDIR/etc/dhcpcd.conf
  833. echo "interface $_dev" >>$TARGETDIR/etc/dhcpcd.conf
  834. echo "static ip_address=$_ip" >>$TARGETDIR/etc/dhcpcd.conf
  835. echo "static routers=$_gw" >>$TARGETDIR/etc/dhcpcd.conf
  836. echo "static domain_name_servers=$_dns1 $_dns2" >>$TARGETDIR/etc/dhcpcd.conf
  837. enable_dhcpd
  838. fi
  839. fi
  840. # install bootloader.
  841. set_bootloader
  842. sync && sync && sync
  843. # unmount all filesystems.
  844. umount_filesystems
  845. # installed successfully.
  846. DIALOG --yesno "${BOLD}Void Linux has been installed successfully!${RESET}\n
  847. Do you want to reboot the system?" ${YESNOSIZE}
  848. if [ $? -eq 0 ]; then
  849. shutdown -r now
  850. else
  851. return
  852. fi
  853. }
  854. menu_source() {
  855. local src=
  856. DIALOG --title " Select installation source " \
  857. --menu "$MENULABEL" 8 70 0 \
  858. "Local" "Packages from ISO image" \
  859. "Network" "Packages from official remote reposity"
  860. case "$(cat $ANSWER)" in
  861. "Local") src="local";;
  862. "Network") src="net"; menu_network;;
  863. *) return 1;;
  864. esac
  865. SOURCE_DONE=1
  866. set_option SOURCE $src
  867. }
  868. menu() {
  869. if [ -z "$DEFITEM" ]; then
  870. DEFITEM="Keyboard"
  871. fi
  872. DIALOG --default-item $DEFITEM \
  873. --extra-button --extra-label "Settings" \
  874. --title " Void Linux installation menu " \
  875. --menu "$MENULABEL" 10 70 0 \
  876. "Keyboard" "Set system keyboard" \
  877. "Network" "Set up the network" \
  878. "Source" "Set source installation" \
  879. "Hostname" "Set system hostname" \
  880. "Locale" "Set system locale" \
  881. "Timezone" "Set system time zone" \
  882. "RootPassword" "Set system root password" \
  883. "BootLoader" "Set disk to install bootloader" \
  884. "Partition" "Partition disk(s)" \
  885. "Filesystems" "Configure filesystems and mount points" \
  886. "Install" "Start installation with saved settings" \
  887. "Exit" "Exit installation"
  888. if [ $? -eq 3 ]; then
  889. # Show settings
  890. cp $CONF_FILE /tmp/conf_hidden.$$;
  891. sed -i "s/^ROOTPASSWORD.*/ROOTPASSWORD <-hidden->/" /tmp/conf_hidden.$$
  892. DIALOG --title "Saved settings for installation" --textbox /tmp/conf_hidden.$$ 14 60
  893. rm /tmp/conf_hidden.$$
  894. return
  895. fi
  896. case $(cat $ANSWER) in
  897. "Keyboard") menu_keymap && [ -n "$KEYBOARD_DONE" ] && DEFITEM="Network";;
  898. "Network") menu_network && [ -n "$NETWORK_DONE" ] && DEFITEM="Source";;
  899. "Source") menu_source && [ -n "$SOURCE_DONE" ] && DEFITEM="Hostname";;
  900. "Hostname") menu_hostname && [ -n "$HOSTNAME_DONE" ] && DEFITEM="Locale";;
  901. "Locale") menu_locale && [ -n "$LOCALE_DONE" ] && DEFITEM="Timezone";;
  902. "Timezone") menu_timezone && [ -n "$TIMEZONE_DONE" ] && DEFITEM="RootPassword";;
  903. "RootPassword") menu_rootpassword && [ -n "$ROOTPASSWORD_DONE" ] && DEFITEM="BootLoader";;
  904. "BootLoader") menu_bootloader && [ -n "$BOOTLOADER_DONE" ] && DEFITEM="Partition";;
  905. "Partition") menu_partitions && [ -n "$PARTITIONS_DONE" ] && DEFITEM="Filesystems";;
  906. "Filesystems") menu_filesystems && [ -n "$FILESYSTEMS_DONE" ] && DEFITEM="Install";;
  907. "Install") menu_install;;
  908. "Exit") DIE;;
  909. *) DIALOG --yesno "Abort Installation?" ${YESNOSIZE} && DIE
  910. esac
  911. }
  912. if [ ! -x /bin/dialog ]; then
  913. echo "ERROR: missing dialog command, exiting..."
  914. exit 1
  915. fi
  916. #
  917. # main()
  918. #
  919. DIALOG --title "${BOLD}${RED} Enter the void ... ${RESET}" --msgbox "\n
  920. Welcome to the Void Linux installation. A simple and minimal \
  921. Linux distribution made from scratch and built from the source package tree \
  922. available for XBPS, a new alternative binary package system.\n\n
  923. The installation should be pretty straightforward, if you are in trouble \
  924. please join us at ${BOLD}#xbps on irc.freenode.org${RESET}.\n\n
  925. ${BOLD}http://www.voidlinux.eu${RESET}\n\n" 16 80
  926. while true; do
  927. menu
  928. done
  929. exit 0
  930. # vim: set ts=4 sw=4 et: