diff --git a/.github/workflows/build-examples.yml b/.github/workflows/build-examples.yml new file mode 100644 index 0000000..eff4e5b --- /dev/null +++ b/.github/workflows/build-examples.yml @@ -0,0 +1,38 @@ +name: Build Examples +on: + workflow_dispatch: + pull_request: +jobs: + build-mock: + runs-on: ubuntu-latest + container: mbedos/mbed-os-env:latest + steps: + # Checkout the repo and download it to the runner + - name: Checkout + uses: actions/checkout@v2 + # Install the venv module + - name: Install dependencies + run: | + apt-get update -y + apt-get install -y python3-venv + # Run the fota build tool with mock as the option + - name: Build example + run: ./scripts/fota.sh -e=mock + + build-mcuboot: + runs-on: ubuntu-latest + container: mbedos/mbed-os-env:latest + steps: + # Checkout the repo and download it to the runner + - name: Checkout + uses: actions/checkout@v2 + # jq is a command-line JSON processor + - name: Install dependencies + run: | + apt-get update -y + apt-get install -y jq python3-venv + # Pipe "yes" into the script to select the appropriate option + # More information about this in the documentation + # Run the fota build tool with mcuboot as the option + - name: Build example + run: yes | ./scripts/fota.sh -e=mcuboot diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69bdc60 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# macOS Desktop Services Store +.DS_Store + +# Virtual environment directory +venv/ + +# IDE-specific directories +.vscode/ +.idea/ + +# Example application dependencies +mcuboot/target/application/mbed-os-experimental-ble-services/ +mcuboot/target/application/mbed-os/ +mcuboot/target/application/mcuboot/ +mcuboot/target/bootloader/dist/ +mcuboot/target/bootloader/imgtool.egg-info/ +mcuboot/target/bootloader/mbed-os/ +mcuboot/target/bootloader/mcuboot/ +mock/target/mbed-os-experimental-ble-services/ +mock/target/mbed-os/ + +# CMake build directory +**/cmake_build + +# Example application build files +mcuboot/target/application/BUILD/ +mcuboot/target/bootloader/application.hex +mcuboot/target/bootloader/build/ +mcuboot/target/bootloader/merged.hex +mcuboot/target/bootloader/signed_application.hex +mcuboot/target/bootloader/signed_update.bin +mcuboot/target/bootloader/signed_update.hex +mcuboot/target/bootloader/signing-keys.pem +mcuboot/target/bootloader/signing_keys.c + +# .mbed files +mcuboot/target/application/.mbed +mcuboot/target/bootloader/.mbed diff --git a/MCUboot/README.md b/mcuboot/README.md similarity index 100% rename from MCUboot/README.md rename to mcuboot/README.md diff --git a/MCUboot/client/client.py b/mcuboot/client/client.py similarity index 100% rename from MCUboot/client/client.py rename to mcuboot/client/client.py diff --git a/MCUboot/client/logging.conf b/mcuboot/client/logging.conf similarity index 100% rename from MCUboot/client/logging.conf rename to mcuboot/client/logging.conf diff --git a/MCUboot/target/application/.mbed b/mcuboot/target/application/.mbed similarity index 100% rename from MCUboot/target/application/.mbed rename to mcuboot/target/application/.mbed diff --git a/MCUboot/target/application/mbed-os-experimental-ble-services.lib b/mcuboot/target/application/mbed-os-experimental-ble-services.lib similarity index 100% rename from MCUboot/target/application/mbed-os-experimental-ble-services.lib rename to mcuboot/target/application/mbed-os-experimental-ble-services.lib diff --git a/MCUboot/target/application/mbed-os.lib b/mcuboot/target/application/mbed-os.lib similarity index 100% rename from MCUboot/target/application/mbed-os.lib rename to mcuboot/target/application/mbed-os.lib diff --git a/MCUboot/target/application/mbed_app.json b/mcuboot/target/application/mbed_app.json similarity index 100% rename from MCUboot/target/application/mbed_app.json rename to mcuboot/target/application/mbed_app.json diff --git a/MCUboot/target/application/mcuboot.lib b/mcuboot/target/application/mcuboot.lib similarity index 100% rename from MCUboot/target/application/mcuboot.lib rename to mcuboot/target/application/mcuboot.lib diff --git a/MCUboot/target/application/source/BlockDeviceFOTAEventHandler.cpp b/mcuboot/target/application/source/BlockDeviceFOTAEventHandler.cpp similarity index 100% rename from MCUboot/target/application/source/BlockDeviceFOTAEventHandler.cpp rename to mcuboot/target/application/source/BlockDeviceFOTAEventHandler.cpp diff --git a/MCUboot/target/application/source/BlockDeviceFOTAEventHandler.h b/mcuboot/target/application/source/BlockDeviceFOTAEventHandler.h similarity index 100% rename from MCUboot/target/application/source/BlockDeviceFOTAEventHandler.h rename to mcuboot/target/application/source/BlockDeviceFOTAEventHandler.h diff --git a/MCUboot/target/application/source/PeriodicBlockDeviceEraser.cpp b/mcuboot/target/application/source/PeriodicBlockDeviceEraser.cpp similarity index 100% rename from MCUboot/target/application/source/PeriodicBlockDeviceEraser.cpp rename to mcuboot/target/application/source/PeriodicBlockDeviceEraser.cpp diff --git a/MCUboot/target/application/source/PeriodicBlockDeviceEraser.h b/mcuboot/target/application/source/PeriodicBlockDeviceEraser.h similarity index 100% rename from MCUboot/target/application/source/PeriodicBlockDeviceEraser.h rename to mcuboot/target/application/source/PeriodicBlockDeviceEraser.h diff --git a/MCUboot/target/application/source/main.cpp b/mcuboot/target/application/source/main.cpp similarity index 100% rename from MCUboot/target/application/source/main.cpp rename to mcuboot/target/application/source/main.cpp diff --git a/MCUboot/target/bootloader/.mbed b/mcuboot/target/bootloader/.mbed similarity index 100% rename from MCUboot/target/bootloader/.mbed rename to mcuboot/target/bootloader/.mbed diff --git a/MCUboot/target/bootloader/default_bd.cpp b/mcuboot/target/bootloader/default_bd.cpp similarity index 100% rename from MCUboot/target/bootloader/default_bd.cpp rename to mcuboot/target/bootloader/default_bd.cpp diff --git a/MCUboot/target/bootloader/enc_key.c b/mcuboot/target/bootloader/enc_key.c similarity index 100% rename from MCUboot/target/bootloader/enc_key.c rename to mcuboot/target/bootloader/enc_key.c diff --git a/MCUboot/target/bootloader/mbed-os.lib b/mcuboot/target/bootloader/mbed-os.lib similarity index 100% rename from MCUboot/target/bootloader/mbed-os.lib rename to mcuboot/target/bootloader/mbed-os.lib diff --git a/MCUboot/target/bootloader/mbed_app.json b/mcuboot/target/bootloader/mbed_app.json similarity index 100% rename from MCUboot/target/bootloader/mbed_app.json rename to mcuboot/target/bootloader/mbed_app.json diff --git a/MCUboot/target/bootloader/mcuboot.lib b/mcuboot/target/bootloader/mcuboot.lib similarity index 100% rename from MCUboot/target/bootloader/mcuboot.lib rename to mcuboot/target/bootloader/mcuboot.lib diff --git a/Mock/README.md b/mock/README.md similarity index 100% rename from Mock/README.md rename to mock/README.md diff --git a/Mock/client/client.py b/mock/client/client.py similarity index 100% rename from Mock/client/client.py rename to mock/client/client.py diff --git a/Mock/client/logging.conf b/mock/client/logging.conf similarity index 100% rename from Mock/client/logging.conf rename to mock/client/logging.conf diff --git a/Mock/target/CMakeLists.txt b/mock/target/CMakeLists.txt similarity index 100% rename from Mock/target/CMakeLists.txt rename to mock/target/CMakeLists.txt diff --git a/Mock/target/mbed-os-experimental-ble-services.lib b/mock/target/mbed-os-experimental-ble-services.lib similarity index 100% rename from Mock/target/mbed-os-experimental-ble-services.lib rename to mock/target/mbed-os-experimental-ble-services.lib diff --git a/Mock/target/mbed-os.lib b/mock/target/mbed-os.lib similarity index 100% rename from Mock/target/mbed-os.lib rename to mock/target/mbed-os.lib diff --git a/Mock/target/mbed_app.json b/mock/target/mbed_app.json similarity index 100% rename from Mock/target/mbed_app.json rename to mock/target/mbed_app.json diff --git a/Mock/target/source/BlockDeviceFOTAEventHandler.cpp b/mock/target/source/BlockDeviceFOTAEventHandler.cpp similarity index 100% rename from Mock/target/source/BlockDeviceFOTAEventHandler.cpp rename to mock/target/source/BlockDeviceFOTAEventHandler.cpp diff --git a/Mock/target/source/BlockDeviceFOTAEventHandler.h b/mock/target/source/BlockDeviceFOTAEventHandler.h similarity index 100% rename from Mock/target/source/BlockDeviceFOTAEventHandler.h rename to mock/target/source/BlockDeviceFOTAEventHandler.h diff --git a/Mock/target/source/PeriodicBlockDeviceEraser.cpp b/mock/target/source/PeriodicBlockDeviceEraser.cpp similarity index 100% rename from Mock/target/source/PeriodicBlockDeviceEraser.cpp rename to mock/target/source/PeriodicBlockDeviceEraser.cpp diff --git a/Mock/target/source/PeriodicBlockDeviceEraser.h b/mock/target/source/PeriodicBlockDeviceEraser.h similarity index 100% rename from Mock/target/source/PeriodicBlockDeviceEraser.h rename to mock/target/source/PeriodicBlockDeviceEraser.h diff --git a/Mock/target/source/main.cpp b/mock/target/source/main.cpp similarity index 100% rename from Mock/target/source/main.cpp rename to mock/target/source/main.cpp diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..96a457a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +bleak==0.12.1 +cmake==3.20.5 +mbed-cli==1.10.5 +mbed-tools==7.28.1 +mercurial==5.8 +ninja==1.10.0.post2 diff --git a/scripts/fota.sh b/scripts/fota.sh new file mode 100755 index 0000000..040cb9d --- /dev/null +++ b/scripts/fota.sh @@ -0,0 +1,201 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Author's Note: +# The fota cli tool is used to setup and build the ble fota examples in this repository. The tool takes in as +# arguments the example, target board, mount point of the target board, and toolchain. Note that if the mount point +# is not provided (it could be the case that an end-user is trying to build without the board connected), then the +# target binary is not flashed. In the case of the MCUboot example, the "factory firmware" is saved and would require +# manual transfer when the board is indeed connected. In either case, the demonstration step would be the only part +# that requires manual intervention. +# +# Important: The tool assumes the target board and toolchain unless otherwise specified by the end-user. However, +# currently, the only board and toolchain supported are NRF52840_DK and GCC_ARM respectively. + +set -e +trap 'cleanup $?' SIGINT SIGTERM ERR EXIT + +source scripts/utils.sh +source scripts/mock.sh +source scripts/mcuboot.sh + +# Display a neatly formatted message on how to use this tool +usage () { + cat </dev/null && pwd -P) + + setup_formatting + parse_options "$@" || fail "Unrecognised option" "Please use -h or --help for usage" + + check_usage + setup_virtualenv + install_requirements + build_example +} + +main "$@" +exit diff --git a/scripts/mcuboot.sh b/scripts/mcuboot.sh new file mode 100644 index 0000000..fa74f22 --- /dev/null +++ b/scripts/mcuboot.sh @@ -0,0 +1,205 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Prompt the end-user on whether they'd like the script to automatically update the application version number in the +# mbed_app.json file. This is especially useful for the CI workflow where "yes" would be piped into the script. +prompt_auto_update () { + while true; do + read -rp "Do you wish to auto-update the version number in application/mbed_app.json? " response + case $response in + [Yy]*) auto_update=1 ; break ;; + [Nn]*) auto_update=0 ; break ;; + *) say message "Please answer yes or no." ;; + esac + done +} + +# Builds the mcuboot example and flashes the binaries if a mount is provided. +# Please refer to the commented steps for more information +# Pre: Arguments passed here are all valid +mcuboot_build () { + toolchain=$1; board=$2; mount=$3; skip=$4; root=$5 + + # Paths to application and bootloader + application=$root/mcuboot/target/application + bootloader=$root/mcuboot/target/bootloader + + say message "Installing/updating example-specific dependencies..." + # 1. Install application dependencies - mbed-os (silently) + # shellcheck disable=SC2015 + cd "$application" && mbed-tools deploy > /dev/null 2>&1 || \ + fail "Unable to install application dependencies" \ + "Please check mcuboot.lib, mbed-os.lib, and mbed-os-experimental-ble-services.lib" + + # 2. Install bootloader dependencies (silently) + # shellcheck disable=SC2015 + cd "$bootloader" && mbed-tools deploy > /dev/null 2>&1 || \ + fail "Unable to install bootloader dependencies" \ + "Please check mcuboot.lib and mbed-os.lib" + + # 3. Install mbed-os python dependencies (silently) + pip install -q -r mbed-os/requirements.txt || \ + fail "Unable to install mbed-os requirements" "Please take a look at mbed-os/requirements.txt" + + # A short message addressing the known Click dependency conflict - this should be removed once resolved. + say note "Click dependency conflict" \ + "This is a known issue and does not hinder the build process" \ + "Refer to the documentation for more information" + + # 4. Install mcuboot requirements (silently) + pip install -q -r mcuboot/scripts/requirements.txt || \ + fail "Unable to install mcuboot requirements" "Please take a look at mcuboot/scripts/requirements.txt" + + # 5. Run mcuboot setup script (silently) + python mcuboot/scripts/setup.py install > /dev/null 2>&1 || \ + fail "MCUboot setup script failed" + + say success "Example requirements installed/updated" + say message "Creating the signing keys and building the bootloader..." + + # 6. Create the signing keys (silently) + # Note: This does not silence errors. + # shellcheck disable=SC2015 + mcuboot/scripts/imgtool.py keygen -k signing-keys.pem -t rsa-2048 >/dev/null && \ + mcuboot/scripts/imgtool.py getpub -k signing-keys.pem >> signing_keys.c || \ + fail "Unable to create the signing keys" + + # 7. Build the bootloader using the old mbed-cli + # Note: This does not silence errors + mbed compile -t "$toolchain" -m "$board" >/dev/null || \ + fail "Failed to compile the bootloader" "Please check the sources" + + say success "Created signing keys and built the bootloader" + say message "Building and signing the primary application..." + + # 8. Build the primary application using the old mbed-cli + # Note: This does not silence errors + # shellcheck disable=SC2015 + cd "$application" && mbed compile -t "$toolchain" -m "$board" >/dev/null || \ + fail "Failed to compile the bootloader" "Please check the sources" + + # shellcheck disable=SC2015 + cp "BUILD/$board/$toolchain/application.hex" "$bootloader" && cd "$bootloader" && \ + mcuboot/scripts/imgtool.py sign -k signing-keys.pem \ + --align 4 -v 0.1.0 --header-size 4096 --pad-header -S 0xC0000 \ + --pad application.hex signed_application.hex || \ + fail "Unable to sign the primary application" + + say success "Built and signed the primary application" + say message "Deactivating virtual environment to setup a new one..." + say note "PyYAML dependency conflict" \ + "pyocd and mbed-os confict in their version requirements of PyYAML" \ + "Refer to the documentation for more information." + + # 9. Deactivate the primary virtual environment + deactivate + + say message "Creating temporary virtual environment..." + + # 10. Create a new, temporary virtual environment just for pyocd and intelhex + # shellcheck disable=SC2015 + mkdir venv && python3 -m venv venv || \ + fail "Virtual environment creation failed!" "Tip: Check your python installation!" + + # 11. Activate temporary virtual environment + source venv/bin/activate + + say success "Temporary virtual environment activated" + say message "Installing requirements (pyocd and intelhex) silently..." + + # 12. Install requirements (pyocd and intelhex) for temporary environment (silently) + # shellcheck disable=SC2015 + pip install -q --upgrade pip && pip install -q pyocd==0.30.3 intelhex==2.3.0 || \ + fail "Unable to install temporary venv requirements" "Please check scripts/mcuboot.sh" + + say success "Requirements installed/updated" + + # 13. Create the factory firmware + hexmerge.py -o merged.hex --no-start-addr "BUILD/$board/$toolchain/bootloader.hex" signed_application.hex || \ + fail "Unable to create factory firmware" + + # 14. Flash the board with the binary (if skip is 0) + if [[ "$skip" -eq 0 ]]; then + pyocd erase --chip && cp merged.hex "$mount" \\ + fail "Unable to flash firmware!" "Please ensure the board is connected" + say success "Factory firmware flashed" + else + say message "Factory firmware at $root/mcuboot/target/bootloader/merged.hex" + fi + + # 15. Deactivate and restore virtual environment + deactivate && rm -rf venv && source "$root/venv/bin/activate" + + # 16. Creating the update binary + # This involves changing the application's version number in mbed_app.json to 0.1.1 and rebuilding it, copying the + # hex file into the bootloader folder, signing the updated application with the RSA-2048 keys and generating the raw + # binary file from the signed_update.hex so that it can be transported over BLE. + prompt_auto_update + + if [[ "$auto_update" -eq 0 ]]; then + # User updates the binary manually, in which case we wait for them to do so + say message "Please update the app version number in application/mbed_app.json" \ + "Once done, press ENTER to continue..." + while read -r -n 1 key + do + # if input == ENTER key + [ -z "$key" ] && break + done + else + # Use jq to update the binary + # shellcheck disable=SC2015 + cd "$application" && \ + jq '."config"."version-number"."value" = "\"0.1.1\""' --indent 4 mbed_app.json > tmp.$$.json \ + && mv tmp.$$.json mbed_app.json || \ + fail "Failed in updating application/mbed_app.json" "Please check scripts/mcuboot.sh" + fi + + say message "Creating the update binary..." + + # shellcheck disable=SC2015 + cd "$application" && mbed compile -t "$toolchain" -m "$board" >/dev/null || \ + fail "Failed to compile the application" "Please check the sources" + + # shellcheck disable=SC2015 + cp "BUILD/$board/$toolchain/application.hex" "$bootloader" && cd "$bootloader" && \ + mcuboot/scripts/imgtool.py sign -k signing-keys.pem \ + --align 4 -v 0.1.1 --header-size 4096 --pad-header -S 0x55000 \ + application.hex signed_update.hex || \ + fail "Unable to sign the updated application" + + arm-none-eabi-objcopy -I ihex -O binary signed_update.hex signed_update.bin || \ + fail "Failed to extract binary from elf" "Tip: Check if arm-none-eabi-objcopy is in your path" + + say message "Update binary at $root/mcuboot/target/bootloader/signed_update.hex" + say success "Build Complete" "Please refer to the documentation for demonstration instructions" +} + +# Clean build files and dependencies specific to this example +# Pre: root is valid +mcuboot_clean () { + root=$1 + application="$root/mcuboot/target/application" + bootloader="$root/mcuboot/target/bootloader" + + # Remove generated files and folders in bootloader folder + rm -rf "$bootloader"/sign* "$bootloader/application.hex" "$bootloader/merged.hex" + rm -rf "$bootloader/build" "$bootloader/dist" "$bootloader/imgtool.egg-info" + + # Remove bootloader dependencies + rm -rf "$bootloader/mbed-os" "$bootloader/mcuboot" + + # Remove application build folder and dependencies + rm -rf "$application/BUILD" "$application/mbed-os" "$application/mbed-os-experimental-ble-services" "$application/mcuboot" +} \ No newline at end of file diff --git a/scripts/mock.sh b/scripts/mock.sh new file mode 100644 index 0000000..17b47f4 --- /dev/null +++ b/scripts/mock.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source scripts/utils.sh + +# Builds the mock example and flashes the binary if a mount point is provided +# Please refer to the commented steps for more information +# Pre: Arguments passed here are all valid +mock_build () { + toolchain=$1; board=$2; mount=$3; skip=$4; root=$5 + + say message "Installing/updating example-specific dependencies..." + # 1. Install mbed-os and mbed-os experimental-ble-services (silently) + # shellcheck disable=SC2015 + cd "$root/mock/target" && mbed-tools deploy > /dev/null 2>&1 || \ + fail "Unable to install mbed-os or mbed-os-experimental-ble-services dependency" + + # 2. Install mbed-os python dependencies + pip install -q -r mbed-os/requirements.txt || \ + fail "Unable to install mbed-os requirements" "Please take a look at mbed-os/requirements.txt" + + # A short message addressing the known Click dependency conflict - this should be removed once resolved. + say note "Click dependency conflict" \ + "This is a known issue and does not hinder the build process" \ + "Refer to the documentation for more information" + say success "Example requirements installed/updated" + + out="cmake_build/$board/develop/$toolchain" + # 3. Compile the example with the target board and toolchain + # Note: This does not silence errors. + mbed-tools compile -t "$toolchain" -m "$board" >/dev/null || \ + fail "Failed to compile the example" "Please check the sources" + + # 4. Convert the output .elf executable to a .bin as it's what NRF52840_DK requires + arm-none-eabi-objcopy -O binary "$out/BLE_GattServer_FOTAService.elf" "$out/BLE_GattServer_FOTAService.bin" || \ + fail "Failed to extract binary from elf" "Tip: Check if arm-none-eabi-objcopy is in your path" + + # 5. Flash the board with the binary (if skip is 0) + # shellcheck disable=SC2015 + if [[ "$skip" -eq 0 ]]; then + cp "$out/BLE_GattServer_FOTAService.bin" "$mount" || \ + fail "Unable to flash binary!" "Please ensure the board is connected" + say success "Binary flashed" + else + say message "Binary at $root/mock/target/$out/BLE_GattServer_FOTAService.bin" + fi + + say success "Build Complete" "Please refer to the documentation for demonstration instructions" +} + +# Clean build files and dependencies specific to this example +# Pre: root is valid +mock_clean () { + root=$1 + rm -rf "$root/mock/target/cmake_build" + rm -rf "$root/mock/target/mbed-os" + rm -rf "$root/mock/target/mbed-os-experimental-ble-services" +} \ No newline at end of file diff --git a/scripts/utils.sh b/scripts/utils.sh new file mode 100755 index 0000000..3ffba59 --- /dev/null +++ b/scripts/utils.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Author's Note: +# This shell script contains utility functions for use in the main fota script +# as well as the setup and build scripts of the examples. + +# Constants for text formatting: +setup_formatting () { + _clear='\e[0m' + _bold='\e[1m' + _red='\e[31m' + _green='\e[32m' + _yellow='\e[33m' +} + +# Says (i.e. prints) a message to the console with formatting based on the selected formatting mode. +say () { + case $1 in + error) + # The first line of the message is treated as the message heading and is marked in bold red along with an "ERROR:" + # prefix. Subsequent message lines are presented with default formatting unless otherwise formatted beforehand. + # All output is directed to stderr. + heading=${2-"ERROR"} + printf "%b\n" \ + "${_bold}${_red}ERROR: $heading${_clear}" \ + "${@:3}" >&2 + ;; + success) + heading=${2-"SUCCESS"} + printf "%b\n" \ + "${_bold}${_green}SUCCESS: $heading${_clear}" \ + "${@:3}" + ;; + message) + printf "%b\n" "${@:2}" + ;; + note) + heading=${2-"NOTE"} + printf "%b\n" \ + "${_bold}${_yellow}NOTE: $heading${_clear}" \ + "${@:3}" + ;; + *) # Unknown error + ;; + esac +} + +# Prints an error message to stderr and exits (or returns) with a code of 1 +fail () { + say error "$@" + exit 1 +} \ No newline at end of file