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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2022 repnop
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at https://mozilla.org/MPL/2.0/.
use crate::{ecall2, SbiError};
/// System reset extension ID
pub const EXTENSION_ID: usize = 0x53525354;
/// The type of reset to perform
#[derive(Debug, Clone, Copy)]
pub enum ResetType {
/// Shutdown the system
Shutdown,
/// Power off all hardware and perform a cold boot
ColdReboot,
/// Reset processors and some hardware
WarmReboot,
/// Platform specific reset type. The variant value is a value within the
/// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
/// clamped to the maximum possible valid value for this reset type.
PlatformSpecific(u32),
}
impl ResetType {
fn to_u32(self) -> u32 {
match self {
ResetType::Shutdown => 0,
ResetType::ColdReboot => 1,
ResetType::WarmReboot => 2,
ResetType::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
}
}
}
/// The reason for performing the reset
#[derive(Debug, Clone, Copy)]
pub enum ResetReason {
/// No reason for reset
NoReason,
/// System failure
SystemFailure,
/// SBI implementation specific reset reason. The variant value is a value
/// within the range `0x00000000..=0x0FFFFFFF`. A value outside of that
/// range will be clamped to the maximum possible valid value for this reset
/// reason type.
SbiSpecific(u32),
/// Platform specific reset reason. The variant value is a value within the
/// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
/// clamped to the maximum possible valid value for this reset reason type.
PlatformSpecific(u32),
}
impl ResetReason {
fn to_u32(self) -> u32 {
match self {
ResetReason::NoReason => 0,
ResetReason::SystemFailure => 1,
ResetReason::SbiSpecific(n) => n.min(0x0FFFFFFF) + 0xE0000000,
ResetReason::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
}
}
}
/// Attempt to reset the system in the provided method, with a reason for the
/// reset.
///
/// ### Possible errors
///
/// [`SbiError::NotSupported`]: The [`ResetType`] is valid but not implemented.
///
/// [`SbiError::Failed`]: The system reset request failed for an unknown reason.
pub fn system_reset(
kind: ResetType,
reason: ResetReason,
) -> Result<core::convert::Infallible, SbiError> {
match unsafe {
ecall2(
kind.to_u32() as usize,
reason.to_u32() as usize,
EXTENSION_ID,
0,
)
} {
Ok(_) => unreachable!("SBI returned `Ok` after a system reset call"),
Err(e) => Err(e),
}
}