vexide_core/
program.rs

1//! User program state.
2
3use bitflags::bitflags;
4use vex_sdk::vexSystemLinkAddrGet;
5
6/// Identifies the type of binary to VEXos.
7#[derive(Debug, Clone, Copy, Eq, PartialEq)]
8#[repr(u32)]
9#[non_exhaustive]
10pub enum ProgramType {
11    /// User program binary.
12    User = 0,
13}
14
15/// The owner (originator) of the user program
16#[derive(Debug, Clone, Copy, Eq, PartialEq)]
17#[repr(u32)]
18pub enum ProgramOwner {
19    /// Program is a system binary.
20    System = 0,
21
22    /// Program originated from VEX.
23    Vex = 1,
24
25    /// Program originated from a partner developer.
26    Partner = 2,
27}
28
29bitflags! {
30    /// Program Startup Options
31    ///
32    /// These bitflags are part of the [`CodeSignature`] and determine some small aspects of program
33    /// behavior when running under VEXos. This struct contains the flags with publicly documented
34    /// behavior.
35    #[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
36    pub struct ProgramOptions: u32 {
37        /// Inverts the background color to pure white.
38        const INVERT_DEFAULT_GRAPHICS = 1 << 0;
39
40        /// VEXos scheduler simple tasks will be killed when the program requests exit.
41        const KILL_TASKS_ON_EXIT = 1 << 1;
42
43        /// If VEXos is using the Light theme, inverts the background color to pure white.
44        const THEMED_DEFAULT_GRAPHICS = 1 << 2;
45    }
46}
47
48/// Program Code Signature
49///
50/// The first 16 bytes of a VEX user program contains a code signature header, which has some basic
51/// metadata and startup flags for the program. This signature must be at the start of the binary
52/// for VExos to recognize our binary as a program.
53///
54/// A static instance of this type can be passed to the `code_sig` argument of the `#[vexide::main]`
55/// macro to override the default code signature, or may be placed into the `.code_signature` linker
56/// section if not using the macro.
57#[derive(Debug, Clone, Copy, Eq, PartialEq)]
58#[repr(C)]
59pub struct CodeSignature(vex_sdk::vcodesig, [u32; 4]);
60
61impl CodeSignature {
62    /// Creates a new signature given a program type, owner, and flags.
63    #[must_use]
64    pub const fn new(
65        program_type: ProgramType,
66        owner: ProgramOwner,
67        options: ProgramOptions,
68    ) -> Self {
69        Self(
70            vex_sdk::vcodesig {
71                magic: vex_sdk::V5_SIG_MAGIC,
72                r#type: program_type as _,
73                owner: owner as _,
74                options: options.bits(),
75            },
76            [0; 4],
77        )
78    }
79
80    /// Returns the program owner specified by this signature.
81    ///
82    /// See [`ProgramOwner`] for more info.
83    #[must_use]
84    pub const fn owner(&self) -> ProgramOwner {
85        match self.0.owner {
86            0 => ProgramOwner::System,
87            1 => ProgramOwner::Vex,
88            2 => ProgramOwner::Partner,
89            _ => unreachable!(),
90        }
91    }
92
93    /// Returns the program type specified by this signature.
94    ///
95    /// See [`ProgramType`] for more info.
96    #[must_use]
97    pub const fn program_type(&self) -> ProgramType {
98        match self.0.r#type {
99            0 => ProgramType::User,
100            _ => unreachable!(),
101        }
102    }
103
104    /// Returns the program startup options specified by this signature.
105    ///
106    /// See [`ProgramOptions`] for more info.
107    #[must_use]
108    pub const fn options(&self) -> ProgramOptions {
109        ProgramOptions::from_bits_retain(self.0.options)
110    }
111}
112
113/// Returns the code signature of the currently running program.
114#[inline]
115#[must_use]
116pub fn code_signature() -> CodeSignature {
117    #[cfg(target_os = "vexos")]
118    {
119        unsafe extern "C" {
120            // Defined in https://github.com/rust-lang/rust/blob/master/compiler/rustc_target/src/spec/targets/armv7a_vex_v5_linker_script.ld.
121            static __user_ram_start: CodeSignature;
122        }
123
124        unsafe { core::ptr::read(&raw const __user_ram_start) }
125    }
126
127    // TODO: Return real data on non-vexos targets, either through some special symbol name or a
128    // linker section.
129    #[cfg(not(target_os = "vexos"))]
130    {
131        unsafe extern "C" {
132            safe static __VEXIDE_CODE_SIGNATURE: CodeSignature;
133        }
134
135        __VEXIDE_CODE_SIGNATURE
136    }
137}
138
139/// Returns a raw pointer to the currently linked file.
140///
141/// If no file is linked to the current program, this function will return a null pointer.
142#[inline]
143#[must_use]
144pub fn linked_file() -> *mut () {
145    unsafe { vexSystemLinkAddrGet() as *mut () }
146}