update/
revert.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::{Context, Error};
use fidl_fuchsia_hardware_power_statecontrol::{AdminMarker, AdminProxy, RebootReason};
use fidl_fuchsia_paver::{BootManagerMarker, BootManagerProxy, PaverMarker};
use fuchsia_component::client::connect_to_protocol;
use zx::Status;

/// Connects to FIDL services and reverts the update.
pub async fn handle_revert() -> Result<(), Error> {
    let admin = connect_to_protocol::<AdminMarker>().context("while connecting to admin")?;

    let paver = connect_to_protocol::<PaverMarker>().context("while connecting to paver")?;
    let (boot_manager, server_end) = fidl::endpoints::create_proxy::<BootManagerMarker>();
    let () = paver.find_boot_manager(server_end).context("while connecting to boot manager")?;

    println!("Reverting the update.");
    handle_revert_impl(&admin, &boot_manager).await
}

/// Reverts the update using the passed in FIDL proxies.
async fn handle_revert_impl(
    admin: &AdminProxy,
    boot_manager: &BootManagerProxy,
) -> Result<(), Error> {
    let current_config = boot_manager
        .query_current_configuration()
        .await
        .context("while calling query_current_configuration")?
        .map_err(Status::from_raw)
        .context("query_current_configuration responded with")?;

    let () = Status::ok(
        boot_manager
            .set_configuration_unbootable(current_config)
            .await
            .context("while calling set_configuration_unbootable")?,
    )
    .context("set_configuration_unbootable responded with")?;

    let () = Status::ok(boot_manager.flush().await.context("while calling flush")?)
        .context("flush responded with")?;

    admin
        .reboot(RebootReason::UserRequest)
        .await
        .context("while performing reboot call")?
        .map_err(Status::from_raw)
        .context("reboot responded with")
}