]>
Commit | Line | Data |
---|---|---|
82068881 MT |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # firmware-update - IPFire Firmware Update Tool # | |
5 | # Copyright (C) 2019 IPFire Development Team # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
96f10173 MT |
22 | shopt -s nullglob |
23 | ||
af9ef5f2 MT |
24 | PACKAGE_NAME="@PACKAGE_NAME@" |
25 | PACKAGE_VERSION="@PACKAGE_VERSION@" | |
26 | ||
96f10173 MT |
27 | FIRMWARE_DIR="@firmwaredir@" |
28 | ||
06d931fa MT |
29 | get_consent() { |
30 | local firmware="${1}" | |
31 | ||
32 | cat <<EOF | |
33 | ||
34 | You are going to flash the firmware on device. This is a dangerous operation | |
35 | that might potentially damage your device. | |
36 | ||
37 | Please do NOT TURN OFF the system while the update is in progress and do | |
38 | not abort the process. | |
39 | ||
40 | Firmware file: ${firmware} | |
41 | ||
42 | EOF | |
43 | ||
44 | local answer | |
45 | while [ -t 0 -a -t 1 -a -t 2 ]; do | |
46 | # Wait for user to type y | |
47 | printf "Do you want to proceed? [y/n] " | |
48 | read -r answer | |
49 | ||
50 | case "${answer}" in | |
51 | y|Y) | |
52 | return 0 | |
53 | ;; | |
54 | n|N) | |
55 | echo "Aborting." | |
56 | return 1 | |
57 | ;; | |
58 | esac | |
59 | done | |
60 | } | |
61 | ||
f2b32736 MT |
62 | read_dmi() { |
63 | local what="${1}" | |
64 | ||
65 | # Return an error when what is empty | |
66 | [ -z "${what}" ] && return 2 | |
67 | ||
68 | local file="/sys/class/dmi/id/${what}" | |
69 | ||
70 | # Read file | |
71 | if [ -r "${file}" ]; then | |
72 | printf "%s" "$(<${file})" | |
73 | return 0 | |
74 | fi | |
75 | ||
76 | # File could not be read | |
77 | return 1 | |
78 | } | |
79 | ||
96f10173 MT |
80 | board_vendor() { |
81 | read_dmi "board_vendor" | |
82 | } | |
83 | ||
84 | board_name() { | |
85 | read_dmi "board_name" | |
f2b32736 MT |
86 | } |
87 | ||
88 | board_version() { | |
89 | read_dmi "board_version" | |
90 | } | |
91 | ||
92 | board_serial() { | |
93 | read_dmi "board_serial" | |
94 | } | |
95 | ||
96 | bios_version() { | |
97 | read_dmi "bios_version" | |
98 | } | |
99 | ||
100 | bios_date() { | |
101 | read_dmi "bios_date" | |
102 | } | |
103 | ||
96f10173 MT |
104 | do_flashrom() { |
105 | echo "Flashing process is starting now..." | |
106 | echo "PLEASE DO NOT TURN OFF THE SYSTEM WHILE FLASHING!" | |
107 | ||
108 | if ! flashrom "$@"; then | |
109 | echo "Error: Flashing the firmware was not successful" >&2 | |
110 | return 1 | |
111 | fi | |
112 | ||
113 | echo "Flashing was successful! Please reboot." | |
114 | return 0 | |
115 | } | |
116 | ||
117 | find_firmware() { | |
118 | local path="${FIRMWARE_DIR}/${1}" | |
119 | ||
120 | # Expand globbing | |
121 | local files=( ${path} ) | |
122 | ||
123 | # Return file with highest order | |
124 | local file="${files[-1]}" | |
125 | ||
126 | # Check if we can read the file | |
127 | if [ ! -r "${file}" ]; then | |
128 | echo "Error: Cannot read firmware file: ${file}" >&2 | |
129 | return 1 | |
130 | fi | |
131 | ||
132 | echo "${file}" | |
133 | return 0 | |
134 | } | |
135 | ||
136 | # Returns true if a is greater than b | |
137 | version_is_gt() { | |
138 | local a="${1}" | |
139 | local b="${2}" | |
140 | ||
141 | # Check if a == b | |
142 | [ "${a}" = "${b}" ] && return 1 | |
143 | ||
144 | # Sort by version | |
145 | local sorted=( $(printf "${a}\n${b}\n" | sort -Vr) ) | |
146 | ||
147 | # If a comes first in the sorted order, it is largest | |
148 | [ "${a}" = "${sorted[0]}" ] && return 0 | |
149 | ||
150 | # Otherwise b is greater than a | |
151 | return 1 | |
152 | } | |
153 | ||
154 | update_pcengines_apu() { | |
155 | local board="${1}" | |
156 | local running_version="${2}" | |
157 | shift 2 | |
158 | ||
159 | # Find a new firmware file | |
160 | local firmware="$(find_firmware "pcengines/apu/${board}_*.rom")" | |
161 | if [ -z "${firmware}" ]; then | |
162 | echo "Error: No firmware found" >&2 | |
163 | return 1 | |
164 | fi | |
165 | ||
166 | # Get basename and remove suffix | |
167 | local new_version="$(basename "${firmware%.rom}")" | |
168 | new_version="${new_version#*_}" | |
169 | ||
170 | # Check if we actually have a new version | |
171 | if ! version_is_gt "${new_version}" "${running_version}"; then | |
172 | echo "We have ${new_version} and this board is already on ${running_version}" | |
173 | echo "No new firmware available. Aborting." | |
174 | return 1 | |
175 | fi | |
176 | ||
06d931fa MT |
177 | echo "New firmware version available: ${new_version}" |
178 | ||
96f10173 | 179 | # Perform update |
06d931fa MT |
180 | if get_consent "${firmware}"; then |
181 | do_flashrom -p "internal" -w "${firmware}" | |
182 | fi | |
96f10173 MT |
183 | } |
184 | ||
185 | do_update() { | |
186 | local vendor="$(board_vendor)" | |
187 | local board="$(board_name)" | |
188 | local bios_version="$(bios_version)" | |
189 | ||
190 | # Check if we could read the BIOS version | |
191 | if [ -z "${bios_version}" ]; then | |
192 | echo "Error: Could not detect BIOS version" >&2 | |
193 | return 1 | |
194 | fi | |
195 | ||
196 | echo "Detected ${vendor} ${board} running BIOS version ${bios_version}" | |
197 | ||
198 | case "${vendor},${board}" in | |
199 | "PC Engines",apu*) | |
200 | update_pcengines_apu "${board}" "${bios_version}" "$@" | |
201 | ;; | |
202 | ||
203 | *) | |
204 | echo "Unkown vendor: ${vendor}" >&2 | |
205 | echo "Support for this vendor might not have been implement, yet" >&2 | |
206 | return 1 | |
207 | ;; | |
208 | esac | |
209 | } | |
210 | ||
af9ef5f2 MT |
211 | main() { |
212 | local action="${1}" | |
213 | shift | |
214 | ||
215 | case "${action}" in | |
f2b32736 | 216 | info) |
96f10173 MT |
217 | printf "%-12s: %s %s\n" "Board" \ |
218 | "$(board_vendor)" "$(board_name)" | |
f2b32736 MT |
219 | printf "%-12s: %s\n" "HW Version" "$(board_version)" |
220 | printf "%-12s: %s\n" "Serial" "$(board_serial)" | |
221 | printf "%-12s: %s (%s)\n" "BIOS Version" \ | |
222 | "$(bios_version)" "$(bios_date)" | |
223 | return 0 | |
224 | ;; | |
225 | ||
96f10173 | 226 | update) |
92302596 | 227 | do_update "$@" |
96f10173 MT |
228 | ;; |
229 | ||
af9ef5f2 MT |
230 | version) |
231 | echo "${PACKAGE_NAME}: Version ${PACKAGE_VERSION}" | |
232 | return 0 | |
233 | ;; | |
babb073d MT |
234 | |
235 | "") | |
236 | echo "No command given" >&2 | |
237 | return 2 | |
238 | ;; | |
239 | ||
240 | *) | |
241 | echo "Invalid command: ${action}" >&2 | |
242 | return 2 | |
243 | ;; | |
af9ef5f2 MT |
244 | esac |
245 | } | |
246 | ||
247 | # Call main | |
babb073d | 248 | main "$@" || exit ${?} |