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}