Add SecureAccess enum
Introduce SecureAccess enum to describe read/write access instead of
using a pair of booleans. This makes caller code more readable and
simplifies storage of access rights.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: Idbb675790043b5816325fe8132b021cd3a00a01d
diff --git a/src/lib.rs b/src/lib.rs
index 551dea9..b12ea45 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,7 +17,7 @@
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
pub use crate::fail::{FailAccessDirection, FailControlRegister, FailIDRegister, TzcFail};
-pub use crate::region::{RegionAttributes, RegionIDAccess, TzcRegion, TzcRegionMut};
+pub use crate::region::{RegionAttributes, RegionIDAccess, SecureAccess, TzcRegion, TzcRegionMut};
use crate::{
fail::FailRegisters,
region::RegionRegisters,
diff --git a/src/region.rs b/src/region.rs
index b79de3e..921f619 100644
--- a/src/region.rs
+++ b/src/region.rs
@@ -1,5 +1,7 @@
// SPDX-FileCopyrightText: Copyright The arm-tzc Contributors.
// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use bitflags::bitflags;
use safe_mmio::{SharedMmioPointer, UniqueMmioPointer, field, field_shared, fields::ReadPureWrite};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -10,6 +12,27 @@
const REGION_ALIGNMENT_MASK: u64 = 0xfff;
+/// Controls access to a region from the secure world.
+#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
+#[repr(transparent)]
+pub struct SecureAccess(u32);
+
+bitflags! {
+ impl SecureAccess: u32 {
+ /// Denies all access from secure world.
+ const NONE = 0;
+
+ /// Enables read access from secure world.
+ const R = 1 << 30;
+
+ /// Enables write access from secure world.
+ const W = 1 << 31;
+
+ /// Enables read-write access from secure world.
+ const RW = Self::R.bits() | Self::W.bits();
+ }
+}
+
#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
/// Each region has a region attributes register which controls the permissions for Region 0 and,
/// for all other regions, the permissions and target filter region enables.
@@ -19,13 +42,10 @@
impl RegionAttributes {
/// Creates a fresh value for a `RegionAttributes`.
///
- /// - `write`: whether the region should allow write access from the Secure World.
- /// - `read`: whether the region should allow red access from the Secure World.
+ /// - `secure_access`: controls read/write access from the Secure World.
/// - `filters`: the id of the filters to enable for this region.
- pub const fn new(write: bool, read: bool, filters: &[usize]) -> Self {
- let mut s = Self(0);
- s.set_write_enabled(write);
- s.set_read_enabled(read);
+ pub const fn new(secure_access: SecureAccess, filters: &[usize]) -> Self {
+ let mut s = Self(secure_access.bits());
for_in_slice! {
f in filters,
@@ -35,26 +55,15 @@
s
}
- /// Whether Secure writes are permitted in this region.
- pub const fn is_write_enabled(&self) -> bool {
- get_bit(self.0, 31)
+ /// Gets secure access attributes of the region.
+ pub const fn secure_access(&self) -> SecureAccess {
+ SecureAccess::from_bits_truncate(self.0)
}
- /// Secure global write enable. This control bit defines the permissions for the Secure writes
- /// in the region.
- pub const fn set_write_enabled(&mut self, enabled: bool) {
- set_bit(&mut self.0, 31, enabled);
- }
-
- /// Whether Secure reads are permitted in this region.
- pub const fn is_read_enabled(&self) -> bool {
- get_bit(self.0, 30)
- }
-
- /// Secure global read enable. This control bit defines the permissions for the Secure reads in
- /// the region.
- pub const fn set_read_enabled(&mut self, enabled: bool) {
- set_bit(&mut self.0, 30, enabled);
+ /// Sets secure access attributes of the region.
+ pub const fn set_secure_access(&mut self, secure_access: SecureAccess) {
+ self.0 &= !SecureAccess::RW.bits();
+ self.0 |= secure_access.bits();
}
/// Whether the filter `index` is enabled for this region.
@@ -80,6 +89,9 @@
pub struct RegionIDAccess(u32);
impl RegionIDAccess {
+ /// Denies non-secure access to the region.
+ pub const NONE: Self = Self::new(&[], &[]);
+
/// Creates a new instance of `RegionIDAccess`.
///
/// - `writes`: all the NSA indexes that should be allowed to write into this region.
@@ -268,7 +280,8 @@
#[cfg(test)]
mod tests {
- use crate::{region::REGION_ALIGNMENT_MASK, tests::FakeTZCRegisters, *};
+ use super::*;
+ use crate::{region::REGION_ALIGNMENT_MASK, tests::FakeTZCRegisters};
#[test]
fn region_0_address() {
@@ -390,29 +403,25 @@
let att2 = tzc.region(2).unwrap().region_attributes();
let att3 = tzc.region(3).unwrap().region_attributes();
- assert!(!att0.is_read_enabled());
- assert!(!att0.is_write_enabled());
+ assert_eq!(SecureAccess::NONE, att0.secure_access());
assert!(att0.is_filter_enabled(0));
assert!(!att0.is_filter_enabled(1));
assert!(att0.is_filter_enabled(2));
assert!(!att0.is_filter_enabled(3));
- assert!(att1.is_read_enabled());
- assert!(!att1.is_write_enabled());
+ assert_eq!(SecureAccess::R, att1.secure_access());
assert!(!att1.is_filter_enabled(0));
assert!(att1.is_filter_enabled(1));
assert!(!att1.is_filter_enabled(2));
assert!(!att1.is_filter_enabled(3));
- assert!(!att2.is_read_enabled());
- assert!(att2.is_write_enabled());
+ assert_eq!(SecureAccess::W, att2.secure_access());
assert!(att2.is_filter_enabled(0));
assert!(att2.is_filter_enabled(1));
assert!(att2.is_filter_enabled(2));
assert!(att2.is_filter_enabled(3));
- assert!(att3.is_read_enabled());
- assert!(att3.is_write_enabled());
+ assert_eq!(SecureAccess::RW, att3.secure_access());
assert!(!att3.is_filter_enabled(0));
assert!(!att3.is_filter_enabled(1));
assert!(!att3.is_filter_enabled(2));
@@ -429,17 +438,17 @@
let mut reg0 = tzc.region_mut(0).unwrap();
let mut att0 = reg0.region_attributes();
- att0.set_write_enabled(true);
+ att0.set_secure_access(SecureAccess::W);
att0.set_filter_status(0, false);
reg0.set_region_attributes(att0);
let mut reg1 = tzc.region_mut(1).unwrap();
let mut att1 = reg1.region_attributes();
- att1.set_read_enabled(false);
+ att1.set_secure_access(SecureAccess::NONE);
att1.set_filter_status(1, false);
reg1.set_region_attributes(att1);
- let att2 = RegionAttributes::new(true, true, &[0, 1, 2, 3]);
+ let att2 = RegionAttributes::new(SecureAccess::RW, &[0, 1, 2, 3]);
tzc.region_mut(2).unwrap().set_region_attributes(att2);
assert_eq!(
regs.reg_read(0x110),