Skip to content

Commit

Permalink
Added support in "Basic" Mode for MCUboot Bootloader Update
Browse files Browse the repository at this point in the history
In Basic Mode, we now support ZIP files with multiple bootloader images. This change also adds "Bootloader Slot" to the Device Status list.
  • Loading branch information
dinesharjani committed Jan 8, 2025
1 parent f2d812d commit b00be8f
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 17 deletions.
130 changes: 115 additions & 15 deletions Example/Example/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions Example/Example/View Controllers/Manager/BaseViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ protocol DeviceStatusDelegate: AnyObject {
func connectionStateDidChange(_ state: PeripheralState)
func bootloaderNameReceived(_ name: String)
func bootloaderModeReceived(_ mode: BootloaderInfoResponse.Mode)
func bootloaderSlotReceived(_ slot: UInt64)
func appInfoReceived(_ output: String)
func mcuMgrParamsReceived(buffers: Int, size: Int)
}
Expand All @@ -32,6 +33,9 @@ final class BaseViewController: UITabBarController {
if let bootloaderMode {
deviceStatusDelegate?.bootloaderModeReceived(bootloaderMode)
}
if let bootloaderSlot {
deviceStatusDelegate?.bootloaderSlotReceived(bootloaderSlot)
}
if let appInfoOutput {
deviceStatusDelegate?.appInfoReceived(appInfoOutput)
}
Expand Down Expand Up @@ -71,6 +75,13 @@ final class BaseViewController: UITabBarController {
}
}
}
private var bootloaderSlot: UInt64? {
didSet {
if let bootloaderSlot {
deviceStatusDelegate?.bootloaderSlotReceived(bootloaderSlot)
}
}
}
private var appInfoOutput: String? {
didSet {
if let appInfoOutput {
Expand Down Expand Up @@ -132,6 +143,10 @@ extension BaseViewController: PeripheralDelegate {
defaultManager.bootloaderInfo(query: .mode) { [weak self] response, error in
self?.bootloaderMode = response?.mode
}

defaultManager.bootloaderInfo(query: .slot) { [weak self] response, error in
self?.bootloaderSlot = response?.activeSlot
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class DeviceController: UITableViewController, UITextFieldDelegate {
@IBOutlet weak var mcuMgrParams: UILabel!
@IBOutlet weak var bootloaderName: UILabel!
@IBOutlet weak var bootloaderMode: UILabel!
@IBOutlet weak var bootloaderSlot: UILabel!
@IBOutlet weak var kernel: UILabel!
@IBOutlet weak var actionSend: UIButton!
@IBOutlet weak var message: UITextField!
Expand Down Expand Up @@ -145,6 +146,10 @@ extension DeviceController: DeviceStatusDelegate {
bootloaderMode.text = mode.description
}

func bootloaderSlotReceived(_ slot: UInt64) {
bootloaderSlot.text = "\(slot)"
}

func appInfoReceived(_ output: String) {
kernel.text = output
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class FilesController: UITableViewController {
@IBOutlet weak var mcuMgrParams: UILabel!
@IBOutlet weak var bootloaderName: UILabel!
@IBOutlet weak var bootloaderMode: UILabel!
@IBOutlet weak var bootloaderSlot: UILabel!
@IBOutlet weak var kernel: UILabel!

var fileDownloadViewController: FileDownloadViewController!
Expand Down Expand Up @@ -105,6 +106,10 @@ extension FilesController: DeviceStatusDelegate {
bootloaderMode.text = mode.description
}

func bootloaderSlotReceived(_ slot: UInt64) {
bootloaderSlot.text = "\(slot)"
}

func appInfoReceived(_ output: String) {
kernel.text = output
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ final class FirmwareUpgradeViewController: UIViewController, McuMgrViewControlle
// (We use modes in the code only, but SUIT has no concept of upload modes)
startFirmwareUpgrade(package: package)
} else {
selectMode(for: package)
if package.images.count > 1, package.images.contains(where: { $0.content == .mcuboot }) {
// Force user to select which 'image' to use for bootloader update.
selectBootloaderImage(for: package)
} else {
selectMode(for: package)
}
}
}

Expand Down Expand Up @@ -157,6 +162,8 @@ final class FirmwareUpgradeViewController: UIViewController, McuMgrViewControlle
updateEraseApplicationSettings(to: sender.isOn)
}

// MARK: selectMode(for:)

private func selectMode(for package: McuMgrPackage) {
let alertController = UIAlertController(title: "Select Mode", message: nil, preferredStyle: .actionSheet)
FirmwareUpgradeMode.allCases.forEach { upgradeMode in
Expand All @@ -170,6 +177,21 @@ final class FirmwareUpgradeViewController: UIViewController, McuMgrViewControlle
present(alertController, addingCancelAction: true)
}

// MARK: selectBootloaderImage(for:)

private func selectBootloaderImage(for package: McuMgrPackage) {
let alertController = buildSelectImageController()
for image in package.images {
alertController.addAction(UIAlertAction(title: image.imageName(), style: .default) { [weak self]
action in
self?.dfuManagerConfiguration.eraseAppSettings = false
self?.dfuManagerConfiguration.upgradeMode = .confirmOnly
self?.startFirmwareUpgrade(images: [image])
})
}
present(alertController, animated: true)
}

// MARK: updateEstimatedSwapTime(to:)

private func updateEstimatedSwapTime(to numberOfSeconds: Int, updatingUserDefaults: Bool = true) {
Expand Down Expand Up @@ -223,6 +245,8 @@ final class FirmwareUpgradeViewController: UIViewController, McuMgrViewControlle
present(alertViewController, animated: true)
}

// MARK: startFirmwareUpgrade

private func startFirmwareUpgrade(package: McuMgrPackage) {
do {
try dfuManager.start(package: package, using: dfuManagerConfiguration)
Expand All @@ -232,6 +256,16 @@ final class FirmwareUpgradeViewController: UIViewController, McuMgrViewControlle
actionStart.isEnabled = false
}
}

private func startFirmwareUpgrade(images: [ImageManager.Image]) {
do {
try dfuManager.start(images: images, using: dfuManagerConfiguration)
} catch {
status.textColor = .systemRed
status.text = error.localizedDescription
actionStart.isEnabled = false
}
}
}

// MARK: - UserDefaults Keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class ImageController: UITableViewController {
@IBOutlet weak var connectionStatus: UILabel!
@IBOutlet weak var mcuMgrParams: UILabel!
@IBOutlet weak var bootloaderName: UILabel!
@IBOutlet weak var bootloaderMode: UILabel!
@IBOutlet weak var bootloaderMode: UILabel!
@IBOutlet weak var bootloaderSlot: UILabel!
@IBOutlet weak var kernel: UILabel!
/// Instance if Images View Controller, required to get its
/// height when data are obtained and height changes.
Expand Down Expand Up @@ -112,6 +113,10 @@ extension ImageController: DeviceStatusDelegate {
bootloaderMode.text = mode.description
}

func bootloaderSlotReceived(_ slot: UInt64) {
bootloaderSlot.text = "\(slot)"
}

func appInfoReceived(_ output: String) {
kernel.text = output
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class LogsStatsController: UITableViewController {
@IBOutlet weak var mcuMgrParams: UILabel!
@IBOutlet weak var bootloaderName: UILabel!
@IBOutlet weak var bootloaderMode: UILabel!
@IBOutlet weak var bootloaderSlot: UILabel!
@IBOutlet weak var kernel: UILabel!
@IBOutlet weak var stats: UILabel!
@IBOutlet weak var refreshAction: UIButton!
Expand Down Expand Up @@ -98,6 +99,10 @@ extension LogsStatsController: DeviceStatusDelegate {
bootloaderMode.text = mode.description
}

func bootloaderSlotReceived(_ slot: UInt64) {
bootloaderSlot.text = "\(slot)"
}

func appInfoReceived(_ output: String) {
kernel.text = output
}
Expand Down

0 comments on commit b00be8f

Please sign in to comment.