33// Copyright OXIDOS AUTOMOTIVE 2024.
44
55use byteorder:: { ByteOrder , LittleEndian } ;
6- use probe_rs:: { Core , MemoryInterface } ;
7- use tokio_serial:: SerialStream ;
86
9- use crate :: bootloader_serial:: { issue_command, Command , Response } ;
107use crate :: errors:: { AttributeParseError , TockError , TockloaderError } ;
8+ use crate :: IO ;
119
1210use super :: decode:: { bytes_to_string, decode_attribute} ;
1311
@@ -50,29 +48,27 @@ impl SystemAttributes {
5048 }
5149 }
5250
53- /// Read system attributes using a probe-rs connection. A bootloader must be
51+ /// Read system attributes using a generalized connection. A bootloader must be
5452 /// present on this board for this function to work properly.
5553 ///
5654 /// # Parameters
57- /// - `board_core` : Core access, obtained from a
58- /// [ProbeRSConnection](crate::connection::ProbeRSConnection)
55+ /// - `conn` : Either a SerialConnection or a ProbeRSConnection
5956 ///
6057 /// # Returns
6158 /// - Ok(result): if attributes were read successfully
6259 /// - Err(TockloaderError::MisconfiguredBoard): if no start address is found or valid
6360 /// - Err(TockloaderError::MisconfiguredBoard): if attributes don't follow the UTF-8 format
64- /// - Err(TockloaderError::ProbeRsReadError): if reading fails
65- pub ( crate ) fn read_system_attributes_probe (
66- board_core : & mut Core ,
67- ) -> Result < Self , TockloaderError > {
61+ /// - Err(TockloaderError::ProbeRsReadError): if reading fails on ProbeRS
62+ /// - Err(TockloaderError::SerialReadError): if reading fails on Serial
63+ pub ( crate ) async fn read_system_attributes (
64+ conn : & mut dyn IO ,
65+ ) -> Result < SystemAttributes , TockloaderError > {
6866 let mut result = SystemAttributes :: new ( ) ;
6967 // System attributes start at 0x600 and up to 0x9FF. See:
7068 // https://book.tockos.org/doc/memory_layout#flash-1
7169 let address = 0x600 ;
72- // Each attribute is 64 bytes exactly, and there are 16 slots
73- let mut buf = [ 0u8 ; 64 * 16 ] ;
7470
75- board_core . read ( address, & mut buf ) ?;
71+ let buf = conn . read ( address, 64 * 16 ) . await ?;
7672
7773 let mut data = buf. chunks ( 64 ) ;
7874
@@ -125,9 +121,8 @@ impl SystemAttributes {
125121 // TODO(george-cosma): separate kernel attributes from kernel flags.
126122
127123 let address = 0x40E ;
128- let mut buf = [ 0u8 ; 8 ] ;
129124
130- board_core . read_8 ( address, & mut buf ) ?;
125+ let buf = conn . read ( address, 8 ) . await ?;
131126
132127 let string = String :: from_utf8 ( buf. to_vec ( ) )
133128 . map_err ( |e| TockError :: AttributeParsing ( AttributeParseError :: InvalidString ( e) ) ) ?;
@@ -137,151 +132,11 @@ impl SystemAttributes {
137132 result. bootloader_version = Some ( string. to_owned ( ) ) ;
138133
139134 // The 100 bytes prior to the application start address are reserved for the kernel attributes and flags
140- let mut kernel_attr_binary = [ 0u8 ; 100 ] ;
141135 let kernel_attr_addr = result
142136 . appaddr
143137 . ok_or ( TockError :: MissingAttribute ( "appaddr" . to_owned ( ) ) ) ?
144138 - 100 ;
145- board_core. read ( kernel_attr_addr, & mut kernel_attr_binary) ?;
146-
147- let sentinel = bytes_to_string ( & kernel_attr_binary[ 96 ..100 ] ) ;
148- let kernel_version = LittleEndian :: read_uint ( & kernel_attr_binary[ 95 ..96 ] , 1 ) ;
149-
150- let app_memory_len = LittleEndian :: read_u32 ( & kernel_attr_binary[ 84 ..92 ] ) ;
151- let app_memory_start = LittleEndian :: read_u32 ( & kernel_attr_binary[ 80 ..84 ] ) ;
152-
153- let kernel_binary_start = LittleEndian :: read_u32 ( & kernel_attr_binary[ 68 ..72 ] ) ;
154- let kernel_binary_len = LittleEndian :: read_u32 ( & kernel_attr_binary[ 72 ..76 ] ) ;
155-
156- result. sentinel = Some ( sentinel) ;
157- result. kernel_version = Some ( kernel_version) ;
158- result. app_mem_start = Some ( app_memory_start) ;
159- result. app_mem_len = Some ( app_memory_len) ;
160- result. kernel_bin_start = Some ( kernel_binary_start) ;
161- result. kernel_bin_len = Some ( kernel_binary_len) ;
162-
163- Ok ( result)
164- }
165-
166- /// Read system attributes using a serial connection. A bootloader must be
167- /// present on this board for this function to work properly.
168- ///
169- /// # Parameters
170- /// - `port`: Serial access, obtained from a
171- /// [SerialConnection](crate::connection::SerialConnection)
172- ///
173- /// # Returns
174- /// - Ok(result): if attributes were read successfully
175- /// - Err(TockloaderError::MisconfiguredBoard): if no start address is found or valid
176- /// - Err(TockloaderError::MisconfiguredBoard): if attributes don't follow the UTF-8 format
177- /// - Err(TockloaderError::SerialReadError): if reading fails
178- pub ( crate ) async fn read_system_attributes_serial (
179- port : & mut SerialStream ,
180- ) -> Result < Self , TockloaderError > {
181- let mut result = SystemAttributes :: new ( ) ;
182-
183- // System attributes start at 0x600 and up to 0x9FF. See:
184- // https://book.tockos.org/doc/memory_layout#flash-1
185- let mut pkt = ( 0x600_u32 ) . to_le_bytes ( ) . to_vec ( ) ;
186- // Each attribute is 64 bytes exactly, and there are 16 slots
187- let length = ( 1024_u16 ) . to_le_bytes ( ) . to_vec ( ) ;
188- for i in length {
189- pkt. push ( i) ;
190- }
191-
192- // Read the kernel attributes
193- let ( _, buf) = issue_command (
194- port,
195- Command :: ReadRange ,
196- pkt,
197- true ,
198- 64 * 16 ,
199- Response :: ReadRange ,
200- )
201- . await ?;
202-
203- let mut data = buf. chunks ( 64 ) ;
204-
205- for current_slot in 0 ..data. len ( ) {
206- let slot_data = match data. next ( ) {
207- Some ( data) => data,
208- None => break ,
209- } ;
210-
211- if let Some ( decoded_attributes) = decode_attribute ( slot_data) {
212- match current_slot {
213- 0 => {
214- result. board = Some ( decoded_attributes. value . to_string ( ) ) ;
215- }
216- 1 => {
217- result. arch = Some ( decoded_attributes. value . to_string ( ) ) ;
218- }
219- 2 => {
220- // Parse hex string like "0x40000" into actual u64 value
221- result. appaddr = Some (
222- u64:: from_str_radix (
223- decoded_attributes
224- . value
225- . to_string ( )
226- . trim_start_matches ( "0x" ) ,
227- 16 ,
228- )
229- . map_err ( |e| {
230- TockError :: AttributeParsing ( AttributeParseError :: InvalidNumber ( e) )
231- } ) ?,
232- ) ;
233- }
234- 3 => {
235- result. boothash = Some ( decoded_attributes. value . to_string ( ) ) ;
236- }
237- _ => { }
238- }
239- } else {
240- continue ;
241- }
242- }
243-
244- // TODO(george-cosma): separate kernel attributes from kernel flags.
245-
246- let mut pkt = ( 0x40E_u32 ) . to_le_bytes ( ) . to_vec ( ) ;
247- let length = ( 8_u16 ) . to_le_bytes ( ) . to_vec ( ) ;
248- for i in length {
249- pkt. push ( i) ;
250- }
251-
252- // Read bootloader version
253- let ( _, buf) =
254- issue_command ( port, Command :: ReadRange , pkt, true , 8 , Response :: ReadRange ) . await ?;
255-
256- let string = String :: from_utf8 ( buf)
257- . map_err ( |e| TockError :: AttributeParsing ( AttributeParseError :: InvalidString ( e) ) ) ?;
258-
259- // Strip null bytes
260- let string = string. trim_matches ( char:: from ( 0 ) ) ;
261- result. bootloader_version = Some ( string. to_owned ( ) ) ;
262-
263- // The 100 bytes prior to the application start address are reserved
264- // for the kernel attributes and flags
265- let kernel_attr_addr = ( result
266- . appaddr
267- . ok_or ( TockError :: MissingAttribute ( "appaddr" . to_owned ( ) ) ) ?
268- - 100 ) as u32 ;
269- let mut pkt = kernel_attr_addr. to_le_bytes ( ) . to_vec ( ) ;
270- let length = ( 100_u16 ) . to_le_bytes ( ) . to_vec ( ) ;
271- for i in length {
272- pkt. push ( i) ;
273- }
274-
275- // Read kernel flags
276- let ( _, kernel_attr_binary) = issue_command (
277- port,
278- Command :: ReadRange ,
279- pkt,
280- true ,
281- 100 ,
282- Response :: ReadRange ,
283- )
284- . await ?;
139+ let kernel_attr_binary = conn. read ( kernel_attr_addr, 100 ) . await ?;
285140
286141 let sentinel = bytes_to_string ( & kernel_attr_binary[ 96 ..100 ] ) ;
287142 let kernel_version = LittleEndian :: read_uint ( & kernel_attr_binary[ 95 ..96 ] , 1 ) ;
0 commit comments