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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! User program startup and runtime support.
//!
//! This crate provides runtime infrastructure for booting vexide programs from Rust code. This
//! infrastructure includes a more optimized heap allocator, differential uploading support, and a
//! panic hook that draws panic messages to the screen and captures backtraces.
//!
//! - User code begins at an assembly routine called `_vexide_boot`, which sets up the stack section
//! before jumping to the `_start` routine defined in libstd, which then calls the `main`
//! function.
//!
//! - From there, consumers must call the [`startup`] function to finish the startup process by
//! applying differential upload patches, claiming heap space, and setting up this crate's custom
//! panic hook.
//!
//! This crate does NOT provide a `libc` [crt0 implementation]. No `libc`-style global constructors
//! are called. This means that the [`__libc_init_array`] function must be explicitly called if you
//! wish to link to C libraries.
//!
//! [crt0 implementation]: https://en.wikipedia.org/wiki/Crt0
//! [`__libc_init_array`]: https://maskray.me/blog/2021-11-07-init-ctors-init-array
//!
//! # Example
//!
//! This is an example of a minimal user program that boots without using the main vexide runtime or
//! the `#[vexide::main]` macro.
//!
//! ```
//! use vexide_core::program::{CodeSignature, ProgramOptions, ProgramOwner, ProgramType};
//!
//! // SAFETY: This symbol is unique and is being used to start the runtime.
//! fn main() {
//! // Setup the heap, zero bss, apply patches, etc...
//! unsafe {
//! vexide_startup::startup();
//! }
//!
//! // Rust code goes here!
//! }
//!
//! // Program header (placed at the first 20 bytes on the binary).
//! #[unsafe(link_section = ".code_signature")]
//! #[used] // This is needed to prevent the linker from removing this object in release builds
//! static CODE_SIG: CodeSignature = CodeSignature::new(
//! ProgramType::User,
//! ProgramOwner::Partner,
//! ProgramOptions::empty(),
//! );
//! ```
// Linkerscript Symbols
//
// All of these external symbols are defined by either Rust's armv7a-vex-v5 linkerscript, our ours
// (see link/vexide.ld). These symbols don't have real types or values, but a pointer to them points
// to the address of their location defined in the linkerscript.
unsafe extern "C"
/// vexide's first-stage boot routine.
///
/// This is the true entrypoint of vexide, containing the first instructions of user code executed
/// before anything else. This is written in assembly to ensure that it stays the same across
/// compilations (a requirement of the patcher),
///
/// This routine loads the stack pointer to the stack region specified in our linkerscript, makes a
/// copy of program memory for the patcher if needed, then branches to the Rust entrypoint (_start)
/// defined in libstd.
unsafe extern "C"
/// vexide runtime initialization.
///
/// This function performs some prerequisites to allow vexide programs to properly run. It must be
/// called once at startup before any heap allocation is done. When using `vexide`, this function is
/// already called for you by the `#[vexide::main]` macro, so there's no need to call it yourself
/// (doing so would cause **undefined behavior**).
///
/// This function does the following initialization:
///
/// - Sets up the global heap allocator by [claiming](crate::allocator::claim) the default heap
/// region if the `allocator` feature is specified.
/// - Applies [differential upload patches] to the program if a patch file exists in memory and
/// restarts the program if necessary.
/// - Registers a custom [panic hook] to allow panic messages to be drawn to the screen and
/// backtrace to be collected. This can be enabled/disabled using the `panic-hook` and `backtrace`
/// features.
///
/// [differential upload patches]: https://vexide.dev/docs/building-uploading/#uploading-strategies
/// [panic hook]: https://doc.rust-lang.org/std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```
/// // Not using the `#[vexide::main]` macro here.
/// fn main() {
/// unsafe {
/// vexide_startup::startup(); // Call this once at the start of main.
/// }
///
/// println!("Hi.");
/// }
/// ```
///
/// # Safety
///
/// Must be called *once and only once* at the start of program execution.
pub unsafe