make.sh: Introduce DEFAULT_PARALLELISM
[ipfire-2.x.git] / src / installer / install-bootloader
1 #!/bin/bash
2 ############################################################################
3 #                                                                          #
4 # This file is part of the IPFire Firewall.                                #
5 #                                                                          #
6 # IPFire is free software; you can redistribute it and/or modify           #
7 # it under the terms of the GNU General Public License as published by     #
8 # the Free Software Foundation; either version 2 of the License, or        #
9 # (at your option) any later version.                                      #
10 #                                                                          #
11 # IPFire is distributed in the hope that it will be useful,                #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of           #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
14 # GNU General Public License for more details.                             #
15 #                                                                          #
16 # You should have received a copy of the GNU General Public License        #
17 # along with IPFire; if not, write to the Free Software                    #
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA #
19 #                                                                          #
20 # Copyright (C) 2014 IPFire Team <info@ipfire.org>.                        #
21 #                                                                          #
22 ############################################################################
23
24 GRUB_INSTALL_ARGS="--no-floppy --recheck --force"
25
26 function find_bootloader_device() {
27         local mp
28         for mp in /boot /; do
29                 if find_device "${mp}"; then
30                         return 0
31                 fi
32         done
33
34         return 1
35 }
36
37 function find_device() {
38         local mountpoint="${1}"
39
40         local root
41         local dev mp fs flags rest
42         while read -r dev mp fs flags rest; do
43                 # Skip unwanted entries
44                 [ "${dev}" = "rootfs" ] && continue
45
46                 if [ "${mp}" = "${mountpoint}" ] && [ -b "${dev}" ]; then
47                         root="$(basename "${dev}")"
48                         break
49                 fi
50         done < /proc/mounts
51
52         # Get the actual device from the partition that holds /
53         while [ -n "${root}" ]; do
54                 if [ -e "/sys/block/${root}" ]; then
55                         echo "/dev/${root}"
56                         return 0
57                 fi
58
59                 # Remove last character
60                 root="${root::-1}"
61         done
62
63         return 1
64 }
65
66 function device_is_mdraid() {
67         local device="${1}"
68
69         [ -d "/sys/block/${device/\/dev/}/md" ]
70 }
71
72 function mdraid_get_slaves() {
73         local device="${1}"
74
75         local slave
76         for slave in /sys/block/${device/\/dev/}/slaves/*; do
77                 echo "/dev/$(basename "${slave}")"
78         done 2>/dev/null
79 }
80
81 function grub_update_config() {
82         echo "Updating configuration..."
83
84         if ! grub-mkconfig -o /boot/grub/grub.cfg &>/dev/null; then
85                 echo "Could not update configuration. Aborting." >&2
86                 return 1
87         fi
88
89         return 0
90 }
91
92 function grub_install() {
93         local device="${1}"
94
95         echo "Installing GRUB on ${device}..."
96
97         if [ ! -b "${device}" ]; then
98                 echo "${device} does not exist or is not a block device" >&2
99                 return 1
100         fi
101
102         local arches
103         case "$(uname -m)" in
104                 aarch64)
105                         arches="arm64-efi"
106                         ;;
107                 i?86)
108                         arches="i386-pc"
109                         ;;
110                 x86_64)
111                         arches="i386-pc x86_64-efi"
112                         ;;
113         esac
114
115         local arch
116         for arch in ${arches}; do
117                 local args="--target=${arch}"
118
119                 case "${arch}" in
120                         *-efi)
121                                 # Skip all EFI architectures if no EFI partition exists
122                                 if [ ! -d "/boot/efi" ]; then
123                                         continue
124                                 fi
125
126                                 args="${args} --efi-directory=/boot/efi"
127
128                                 # Don't try to modify the BIOS when we are
129                                 # not running on EFI right now
130                                 if [ ! -d "/sys/firmware/efi" ]; then
131                                         args="${args} --no-nvram"
132                                 fi
133                                 ;;
134                 esac
135
136                 local removable
137                 for removable in "" "--removable"; do
138                         if ! grub-install ${GRUB_INSTALL_ARGS} ${args} \
139                                         ${removable} "${device}" &>/dev/null; then
140                                 echo "Could not install GRUB on ${device}" >&2
141                                 return 1
142                         fi
143
144                         # Do not try to install with --removable for non-efi architectures
145                         [[ "${arch}" =~ \-efi$ ]] || break
146                 done
147         done
148
149         return 0
150 }
151
152 function main() {
153         local device="${1}"
154
155         # Find the root device
156         if [ -z "${device}" ]; then
157                 device="$(find_bootloader_device)"
158                 if [ -z "${device}" ]; then
159                         echo "Could not find root device. Aborting." >&2
160                         return 1
161                 fi
162
163                 echo "Found bootloader device: ${device}"
164         fi
165
166         if [ ! -b "${device}" ]; then
167                 echo "${device} does not exist" >&2
168                 return 2
169         fi
170
171         # Update configuration files
172         grub_update_config || return $?
173
174         # Handle mdraid devices
175         if device_is_mdraid "${device}"; then
176                 local slave
177                 for slave in $(mdraid_get_slaves "${device}"); do
178                         grub_install "${slave}"
179                 done
180
181         # Handle normal block devices
182         else
183                 grub_install "${device}"
184         fi
185
186         return 0
187 }
188
189 # Run main function
190 main "$@" || exit $?