bootreason/
lib.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::Error;
6use fidl_fuchsia_feedback::{LastRebootInfoProviderMarker, RebootReason};
7use fuchsia_component::client::connect_to_protocol_sync;
8use log::{debug, info};
9
10/// Timeout for FIDL calls to LastRebootInfoProvider
11const LRIP_FIDL_TIMEOUT: zx::MonotonicDuration = zx::MonotonicDuration::INFINITE;
12
13/// Get an Android-compatible boot reason suitable to add to the cmdline or bootconfig.
14pub fn get_android_bootreason() -> Result<&'static str, Error> {
15    info!("Converting LastRebootInfo to an android-friendly bootreason.");
16    let reboot_info_proxy = connect_to_protocol_sync::<LastRebootInfoProviderMarker>()?;
17    let deadline = zx::MonotonicInstant::after(LRIP_FIDL_TIMEOUT);
18    let reboot_info = reboot_info_proxy.get(deadline)?;
19
20    match reboot_info.reason {
21        Some(RebootReason::Unknown) => return Ok("reboot,unknown"),
22        Some(RebootReason::Cold) => return Ok("reboot,cold"),
23        Some(RebootReason::BriefPowerLoss) => return Ok("reboot,hard_reset"),
24        Some(RebootReason::Brownout) => return Ok("reboot,undervoltage"),
25        Some(RebootReason::KernelPanic) => return Ok("kernel_panic"),
26        Some(RebootReason::SystemOutOfMemory) => return Ok("kernel_panic,oom"),
27        Some(RebootReason::HardwareWatchdogTimeout) => return Ok("watchdog"),
28        Some(RebootReason::SoftwareWatchdogTimeout) => return Ok("watchdog,sw"),
29        Some(RebootReason::RootJobTermination) => return Ok("kernel_panic"),
30        Some(RebootReason::UserRequest) => return Ok("reboot,userrequested"),
31        Some(RebootReason::DeveloperRequest) => return Ok("reboot,shell"),
32        Some(RebootReason::RetrySystemUpdate) => return Ok("reboot,ota"),
33        Some(RebootReason::HighTemperature) => return Ok("shutdown,thermal"),
34        Some(RebootReason::SessionFailure) => return Ok("kernel_panic"),
35        Some(RebootReason::SysmgrFailure) => return Ok("kernel_panic"),
36        Some(RebootReason::FactoryDataReset) => return Ok("reboot,factory_reset"),
37        Some(RebootReason::CriticalComponentFailure) => return Ok("kernel_panic"),
38        Some(RebootReason::ZbiSwap) => return Ok("reboot,normal"),
39        Some(RebootReason::SystemUpdate) => return Ok("reboot,ota"),
40        Some(RebootReason::NetstackMigration) => return Ok("reboot,normal"),
41        Some(RebootReason::AndroidUnexpectedReason) => return Ok("reboot,normal"),
42        Some(RebootReason::AndroidRescueParty) => return Ok("reboot,rescueparty"),
43        Some(RebootReason::AndroidCriticalProcessFailure) => return Ok("reboot,userspace_failed"),
44        Some(RebootReason::__SourceBreaking { .. }) => return Ok("reboot,normal"),
45        None => return Ok("reboot,unknown"),
46    }
47}
48
49/// Get contents for the pstore/console-ramoops* file.
50///
51/// In Linux it contains a limited amount of some of the previous boot's kernel logs.
52/// The ramoops won't be created after a normal reboot.
53pub fn get_console_ramoops() -> Option<Vec<u8>> {
54    debug!("Getting console-ramoops contents");
55    match get_android_bootreason() {
56        Ok(reason) => match reason {
57            "kernel_panic" | "watchdog" | "watchdog,sw" => {
58                // Placeholder while we figure out how to get the proper logs.
59                Some("Fuchsia Console Ramoops\n".as_bytes().to_vec())
60            }
61            _ => None,
62        },
63        Err(e) => {
64            info!("Failed to get android bootreason for console_ramoops: {:?}", e);
65            None
66        }
67    }
68}