| # Copyright 2017 The ChromiumOS Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| description "Hammer firmware updater task" | |
| author "chromium-os-dev@chromium.org" | |
| # When the hammer device is plugged, udev emits hammer-device-added signal. | |
| # The example rule file: hammerd/udev/99-hammerd.rules.example | |
| # Additionally, start hammerd when ash gets initialized. Ash observes | |
| # signals from hammerd and, if needed, notifies the user of connected hammer | |
| # state. This means that hammerd should be rerun to ensure ash has received | |
| # relavant signals, in case ash missed signals emitted when hammer device was | |
| # added (e.g. if ash had restarted after hammer device addition due to user | |
| # session restart). | |
| # NOTE: ash-initialized signal is emitted by session manager on request from | |
| # the browser process once ash initialization completes. | |
| start on hammer-device-added or ash-initialized | |
| # If the device pairs correctly, expose hammer's sysfs path for other | |
| # applications to use. Store sysfs path file in a separate directory | |
| # to allow for metrics sandboxing. | |
| env WRITE_SYSFS_PATH="/run/metrics/external/hammer/hammer_sysfs_path" | |
| # Arguments should be empty here and overridden at `hammerd.override` or | |
| # retrieved via chromeos-config (cros_config). | |
| env EC_IMAGE_PATH= | |
| env TOUCHPAD_IMAGE_PATH= | |
| env VENDOR_ID= | |
| env PRODUCT_ID= | |
| env USB_PATH= | |
| env AUTOSUSPEND_DELAY_MS="1000" | |
| # These variables may be passed when the job gets started from | |
| # hammerd-at-boot.sh. | |
| import AT_BOOT | |
| import UPDATE_IF | |
| # Set the argument to True when triggering at boot. | |
| env AT_BOOT="false" | |
| # The argument to determine the update condition. | |
| # Valid values are "never", "mismatch", and "always". | |
| env UPDATE_IF="never" | |
| # This belongs to CrOS daemons that are needed to auto-update, but can restart. | |
| oom score -900 | |
| task | |
| pre-start script | |
| # Because the upstart job `boot-update-firmware` will force invoking hammerd | |
| # once before UI is started, we need to make sure hammerd isn't invoked by | |
| # udev before boot-update-firmware gets to run. | |
| if [ "${UPSTART_EVENTS}" = 'hammer-device-added' ] && \ | |
| ! initctl status boot-update-firmware | grep -q "start/running"; then | |
| logger -t "${UPSTART_JOB}" \ | |
| "boot-update-firmware hasn't started yet, ignore." | |
| stop | |
| fi | |
| sysfs_parent_dir="$(dirname "${WRITE_SYSFS_PATH}")" | |
| mkdir -p "${sysfs_parent_dir}" | |
| # Change ownership so that both metrics and hammerd can have write access. | |
| chown hammerd:metrics "${sysfs_parent_dir}" | |
| chmod 770 "${sysfs_parent_dir}" | |
| end script | |
| # Trigger hammerd process. | |
| # Note: minijail0 "-N" argument (cgroup namespace) is only supported on | |
| # kernel >= 3.14. Remove if the hammerd runs on kernel < 3.14. | |
| script | |
| # If reacting to ash-initialized event, verify that the base is actually | |
| # connected before proceeding - hammerd expects the base to be connected, | |
| # which is not guaranteed on ash initialization signal (unlike on | |
| # hammerd-device-added). | |
| if [ "${UPSTART_EVENTS}" = 'ash-initialized' ]; then | |
| HAMMERD_DETECTOR_SCRIPT='/usr/share/cros/init/hammerd-base-detector.sh' | |
| if [ -e "${HAMMERD_DETECTOR_SCRIPT}" ]; then | |
| # Import base_connected function. | |
| . "${HAMMERD_DETECTOR_SCRIPT}" | |
| if ! base_connected "${UPSTART_JOB}"; then | |
| logger -t "${UPSTART_JOB}" \ | |
| "Base not connected during ash initialization" | |
| exit 0 | |
| fi | |
| else | |
| logger -t "${UPSTART_JOB}" "hammerd-base-detector script not found." | |
| fi | |
| fi | |
| # Adopt chromeos-config. | |
| ec_name="$(cros_config /detachable-base ec-image-name)" || true | |
| # If we find the unibuild config, then override the config. | |
| if [ -n "${ec_name}" ]; then | |
| EC_IMAGE_PATH="/lib/firmware/${ec_name}" | |
| VENDOR_ID="$(cros_config /detachable-base vendor-id)" || true | |
| PRODUCT_ID="$(cros_config /detachable-base product-id)" || true | |
| USB_PATH="$(cros_config /detachable-base usb-path)" || true | |
| I2C_PATH="$(cros_config /detachable-base i2c-path)" || true | |
| # Touchpad FW is optional | |
| tp_name="$(cros_config /detachable-base touch-image-name)" || true | |
| [ -n "${tp_name}" ] && TOUCHPAD_IMAGE_PATH="/lib/firmware/${tp_name}" | |
| else | |
| logger -t ${UPSTART_JOB} \ | |
| "Cannot get detachable base info via cros_config." \ | |
| "using the overrided values." | |
| fi | |
| # Ensure no empty config. Touchpad FW is optional so it's ignored. | |
| missing_conf= | |
| [ -z "${EC_IMAGE_PATH}" ] && missing_conf="$missing_conf EC_IMAGE_PATH" | |
| [ -z "${VENDOR_ID}" ] && missing_conf="$missing_conf VENDOR_ID" | |
| [ -z "${PRODUCT_ID}" ] && missing_conf="$missing_conf PRODUCT_ID" | |
| if [ -z "${USB_PATH}" -a -z "${I2C_PATH}" ]; then | |
| missing_conf="$missing_conf USB_PATH I2C_PATH" | |
| fi | |
| if [ -n "${missing_conf}" ]; then | |
| logger -t ${UPSTART_JOB} "Following configs are missing:${missing_conf}" | |
| exit 1 | |
| fi | |
| path_arg= | |
| if [ -n "${USB_PATH}" ]; then | |
| path_arg="--usb_path=${USB_PATH}" | |
| device_path="/sys/bus/usb/devices/${USB_PATH}" | |
| else | |
| path_arg="--i2c_path=${I2C_PATH}" | |
| device_path="/sys/bus/i2c/devices/${I2C_PATH}" | |
| fi | |
| exit_status=0 | |
| /sbin/minijail0 -e -N -p -l -u hammerd -g hammerd -c 0002 \ | |
| /usr/bin/hammerd --ec_image_path="${EC_IMAGE_PATH}" \ | |
| --touchpad_image_path="${TOUCHPAD_IMAGE_PATH}" \ | |
| --vendor_id="${VENDOR_ID}" \ | |
| --product_id="${PRODUCT_ID}" \ | |
| "${path_arg}" \ | |
| --autosuspend_delay_ms="${AUTOSUSPEND_DELAY_MS}" \ | |
| --at_boot="${AT_BOOT}" \ | |
| --update_if="${UPDATE_IF}" || exit_status="$?" | |
| if [ "${exit_status}" -eq 0 ]; then | |
| if ! echo "${device_path}" > "${WRITE_SYSFS_PATH}"; then | |
| logger -t ${UPSTART_JOB} \ | |
| "FAILED to write into sysfs tag file: ${WRITE_SYSFS_PATH}" | |
| exit 1 # Exit status for "unknown error" in hammerd. | |
| fi | |
| else | |
| logger -t "${UPSTART_JOB}" "FAILED to exit hammerd properly. Check the log." | |
| rm "${WRITE_SYSFS_PATH}" || true | |
| fi | |
| exit "${exit_status}" | |
| end script |