You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/// Structure used to package an app's header and footer data.
16
+
/// This structure is used to package together all relevant information like metadata about an app.
17
+
/// The information is usually stored within a [TbfHeader], and one or more [TbfFooters](TbfFooterV2Credentials).
18
+
/// For more details see <https://book.tockos.org/doc/tock_binary_format>
15
19
#[derive(Debug)]
16
20
pubstructAppAttributes{
17
21
pubtbf_header:TbfHeader,
18
22
pubtbf_footers:Vec<TbfFooter>,
19
23
}
20
24
25
+
/// Structure used to package a footers credential data and the size of the footer.
26
+
/// This is where credentials of the footer is stored
21
27
#[derive(Debug)]
22
28
pubstructTbfFooter{
23
29
pubcredentials:TbfFooterV2Credentials,
@@ -39,8 +45,29 @@ impl AppAttributes {
39
45
tbf_footers: footers_data,
40
46
}
41
47
}
42
-
43
-
// TODO: Document this function
48
+
/// The function below is used to retrieve header and footer data
49
+
///
50
+
/// Starting from the 0x40000 address,
51
+
/// using the ['parse_tbf_header_lengths'] function, we read the very first 8 bytes to determine:
52
+
///
53
+
/// - tbf-version
54
+
/// - header_size
55
+
/// - total_size
56
+
///
57
+
/// Afterwards, with the 'header_size' we just read,
58
+
/// we read the the rest of the header information using the same function
59
+
/// then, we save our binary app which marks the total size of the app and move on to the the footer.
60
+
///
61
+
/// Now, we calculate the total size of the footer.
62
+
///
63
+
/// Then, we compute the exact offset of the current footer.
64
+
///
65
+
/// Using it, we read the correct number of bytes from memory,
66
+
/// construct a 'TbfFooter' struct from the raw bytes, and store it.
67
+
///
68
+
/// Once all footers for an app are gathered,
69
+
/// we wrap the header, footers, and other metadata into an `AppAttributes` struct,
70
+
/// and push it into the apps_details vector, which holds info for all flashed applications
44
71
pub(crate)fnread_apps_data_probe(
45
72
board_core:&mutCore,
46
73
addr:u64,
@@ -63,7 +90,7 @@ impl AppAttributes {
63
90
matchparse_tbf_header_lengths(
64
91
&appdata
65
92
.try_into()
66
-
.expect("Buffer length must be at least 8 bytes long."),
93
+
.expect("Buffer length must be at least 8 bytes long."),// All attributes always add up to 8 bytes.
67
94
){
68
95
Ok(data) => {
69
96
tbf_version = data.0;
@@ -81,16 +108,19 @@ impl AppAttributes {
81
108
let header = parse_tbf_header(&header_data, tbf_version)
82
109
.map_err(TockloaderError::ParsingError)?;
83
110
84
-
let binary_end_offset = header.get_binary_end();
111
+
let binary_end_offset = header.get_binary_end();// the end of the header marks the beginning of the footer
85
112
113
+
// 1. Calculate the total size of all footers by subtracting the binary's end offset (`binary_end_offset`) from the total application size (`total_size`).
114
+
// 2. Initialize the reading offset (`footer_offset`) to the start of the footers (right after the binary ends).
115
+
// 3. Loop until we've read all footers (when `footer_offset` reaches `total_size`):
86
116
letmut footers:Vec<TbfFooter> = vec![];
87
117
let total_footers_size = total_size - binary_end_offset;
vec![0u8;(total_footers_size - (footer_offset - binary_end_offset))asusize];// we take the size of the whole footer initially then decrease it by the size of the previous one as we don't know the size of the footer we are reading
footer_offset += footer_info.1 + 4;// the next footer begins using this relation: (footer_offset = binary_end_offset) += summation of (previous_footer_size + 4)
106
136
107
137
if footer_offset == total_size {
108
-
break;
138
+
break;// all footers have been processed.
109
139
}
110
140
}
111
141
@@ -117,7 +147,18 @@ impl AppAttributes {
117
147
}
118
148
}
119
149
120
-
// TODO: Document this function
150
+
/// This reads application metadata and footers from a device just like the previous function except it's done via serial.
151
+
///
152
+
/// Starting at the given address, this function:
153
+
///
154
+
/// 1. Reads the initial 8 bytes of the app header to get version and size info.
155
+
/// 2. Reads the full app header based on that size.
156
+
/// 3. Reads and parses all app footers following the app binary.
157
+
/// 4. Collects and returns all app attributes found sequentially in memory.
158
+
///
159
+
/// Communicates using the Tockloader protocol’s `ReadRange` command and handles multiple apps until no more are found.
160
+
///
161
+
/// Returns a vector of app attributes or an error on failure.
letmut pkt = (appaddr asu32).to_le_bytes().to_vec();// the tockloader protocol only supports up to 32 bytes, hence we converted acquiring 4 byte little endians.
172
+
let length = (8_u16).to_le_bytes().to_vec();// 2 byte little endians
132
173
for i in length {
133
174
pkt.push(i);
134
175
}
135
176
136
-
let(_, appdata) =
177
+
// This sends a `ReadRange` command to the microcontroller to read 8 bytes of memory starting at `appaddr`,
178
+
// and receives the result over the serial connection.
179
+
// The microcontroller receives the command, checks the Command ID (`0x06` for `ReadRange`),
180
+
// then reads the 1-byte payload length and the actual payload:
181
+
// 4 bytes for the address (little-endian), and 2 bytes for the length to read (also little-endian).
182
+
// The microcontroller processes incoming bytes using a state machine like this:
183
+
// enum SerialState {
184
+
// WaitingForCommand, // Awaiting the 1-byte command ID
185
+
// WaitingForLength, // Awaiting the 1-byte payload length
0 commit comments