| # Copyright 2019 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| description "Updates devices using fwupdtool" |
| author "chromium-os-dev@chromium.org" |
| |
| # This job is started by udev via custom events. |
| # Job duration is expected to be O(minutes) depending on the number of |
| # devices with pending updates. |
| start on fwupdtool-update |
| task |
| oom score -100 # Very unlikely. |
| instance $GUID-$AT_BOOT |
| |
| # Device GUID to be updated by fwupdtool update invocation. |
| import GUID |
| # FWUPD plugin to be used by fwupdtool update invokation. |
| import PLUGIN |
| # Are we running at boot time. |
| import AT_BOOT |
| # Update .cab file. Used to allow downgrades. |
| import FIRMWARE_FILE |
| |
| env LANG=en_US.UTF-8 |
| env CACHE_DIRECTORY="/var/cache/fwupd" |
| |
| env AT_BOOT="false" |
| env FILTER="usable-during-update" |
| env REGEX="^[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}$" |
| # TODO(259354228): Remove once resolv.conf migration to dns-proxy is done. |
| # Need access to /run/shill to download from LVFS mirror (DNS resolution). |
| # Need access to /run/dns-proxy to download from LVFS mirror (DNS resolution). |
| env MINIJAIL_ARGS="--profile=minimalistic-mountns --uts -l -p -N \ |
| -k /run,/run,tmpfs -b /run/dbus -b /run/shill -b /run/dns-proxy \ |
| -u fwupd -g fwupd" |
| env MINIJAIL_ARGS_TOOL="--uts -l -p -N \ |
| -v -P /mnt/empty -b / -b /proc -r -t -b /dev,,1 -k run,/run,tmpfs \ |
| -k /var,/var,tmpfs -b /var/cache/fwupd,,1 -b /var/lib/fwupd,,1 \ |
| -b /run/lock,,1 -b /sys,,1 -u fwupd -g fwupd -G" |
| env FWUPD_PATH="/usr/bin/fwupdmgr" |
| env FWUPD_ARGS="" |
| env FWUPD_RET=0 |
| |
| tmpfiles /usr/lib/tmpfiles.d/fwupd.conf |
| |
| pre-start script |
| # Abort if the rootfs is on removable media. e.g. It's on a USB stick. |
| . /usr/share/misc/chromeos-common.sh |
| . /usr/sbin/write_gpt.sh |
| load_base_vars |
| if rootdev_removable; then |
| logger -p warn -t "${UPSTART_JOB}" "Attempting update from removable media" |
| stop |
| exit 0 |
| fi |
| |
| for guid in ${GUID}; do |
| if [ $(expr "${guid}" : "${REGEX}") -eq 0 ]; then |
| logger -p err -t "${UPSTART_JOB}" "Invalid GUID: ${guid}" |
| exit 1 |
| fi |
| done |
| for plugin in ${PLUGIN}; do |
| if ! minijail0 ${MINIJAIL_ARGS} -- "${FWUPD_PATH}" get-plugins \ |
| | grep -x -F "${plugin}:"; then |
| logger -p err -t "${UPSTART_JOB}" "Unsupported plugin: ${plugin}" |
| exit 1 |
| fi |
| done |
| end script |
| |
| script |
| for plugin in ${PLUGIN}; do |
| case "${plugin}" in "nvme") |
| # Grant cap_sys_admin for nvme plugin to issue admin ioctl commands. |
| MINIJAIL_ARGS="${MINIJAIL_ARGS_TOOL} -c cap_dac_override,cap_sys_admin+e" |
| FWUPD_PATH="/usr/bin/fwupdtool" |
| esac |
| done |
| |
| if [ -n "${FIRMWARE_FILE}" ]; then |
| # Grant access to /run/imageloader if the firmware file path starts with |
| # that prefix. |
| case "${FIRMWARE_FILE}" in /run/imageloader/*) |
| MINIJAIL_ARGS="${MINIJAIL_ARGS} \ |
| -k /run/imageloader,/run/imageloader,none,MS_BIND|MS_REC" |
| esac |
| FWUPD_ARGS="install ${FIRMWARE_FILE} ${GUID} --allow-older" |
| else |
| FWUPD_ARGS="update ${GUID}" |
| fi |
| |
| # Do not filter un-usable devices during boot time. |
| if [ "${AT_BOOT}" = "true" ]; then |
| FILTER= |
| fi |
| |
| CURRENT_TIME="$(date +%s)" |
| syslog-cat --identifier="${UPSTART_JOB}" -- minijail0 ${MINIJAIL_ARGS} \ |
| -- "${FWUPD_PATH}" ${FWUPD_ARGS} --filter="${FILTER}" || FWUPD_RET=$? |
| ELAPSED_TIME="$(($(date +%s) - ${CURRENT_TIME} + 1))" |
| |
| metrics_client -e Platform.Fwupd.UpdateStatus "${FWUPD_RET}" 2 |
| if [ "${FWUPD_RET}" -eq 0 ]; then |
| metrics_client Platform.Fwupd.UpdateDuration "${ELAPSED_TIME}" 0 7200 10 |
| fi |
| |
| # If there is a pending update we will delay until next boot. |
| if [ "${AT_BOOT}" = "false" ]; then |
| if minijail0 ${MINIJAIL_ARGS} \ |
| -- "${FWUPD_PATH}" get-updates ${GUID} --filter=~"${FILTER}"; then |
| for guid in ${GUID}; do |
| echo "${PLUGIN}" > /var/lib/fwupd/pending/${guid} |
| done |
| fi |
| fi |
| end script |