@@ -44,6 +44,7 @@ use std::{
4444mod syslog;
4545
4646const READ_BUFFER_SIZE : usize = 128 ;
47+ const UNPROCESSED_SIZE : usize = 16_777_216 ;
4748const POLL_TIMEOUT : c_int = 60_000 ;
4849const FIRMWARE_DIR : & str = "/lib/firmware" ;
4950
@@ -71,6 +72,9 @@ struct Opts {
7172 /// Log to standard output instead of syslog.
7273 #[ arg( short, long) ]
7374 foreground : bool ,
75+ /// Show malformed log messages.
76+ #[ arg( long) ]
77+ malformed : bool ,
7478 /// Gzipped ELF image of OpenEMC firmware.
7579 firmware_elf : Option < PathBuf > ,
7680 /// OpenEMC log file or device.
@@ -82,30 +86,46 @@ struct Opts {
8286 probe : bool ,
8387}
8488
85- /// Write defmt log message to Rust logger.
86- fn forward_to_logger ( frame : & Frame , loc : Option < & Location > , lines : bool ) {
87- let mut msg = String :: with_capacity ( 256 ) ;
89+ /// Log message for Rust logger.
90+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
91+ struct LogMsg {
92+ /// Log level.
93+ pub level : Level ,
94+ /// Message.
95+ pub msg : String ,
96+ }
8897
89- if let Some ( loc) = loc {
90- write ! ( msg, "[{}" , & loc. module) . unwrap ( ) ;
91- if lines {
92- write ! ( msg, " @ {}:{}" , loc. file. display( ) , loc. line) . unwrap ( ) ;
98+ impl LogMsg {
99+ /// Format defmt log message for Rust logger.
100+ pub fn from_defmt ( frame : & Frame , loc : Option < & Location > , lines : bool ) -> Self {
101+ let mut msg = String :: with_capacity ( 256 ) ;
102+
103+ if let Some ( loc) = loc {
104+ write ! ( msg, "[{}" , & loc. module) . unwrap ( ) ;
105+ if lines {
106+ write ! ( msg, " @ {}:{}" , loc. file. display( ) , loc. line) . unwrap ( ) ;
107+ }
108+ write ! ( msg, "] " ) . unwrap ( ) ;
93109 }
94- write ! ( msg, "] " ) . unwrap ( ) ;
95- }
96110
97- write ! ( msg, "{}" , frame. display_message( ) ) . unwrap ( ) ;
111+ write ! ( msg, "{}" , frame. display_message( ) ) . unwrap ( ) ;
98112
99- let level = match frame. level ( ) {
100- Some ( DefmtLevel :: Error ) => Level :: Error ,
101- Some ( DefmtLevel :: Warn ) => Level :: Warn ,
102- Some ( DefmtLevel :: Info ) => Level :: Info ,
103- Some ( DefmtLevel :: Debug ) => Level :: Debug ,
104- Some ( DefmtLevel :: Trace ) => Level :: Trace ,
105- None => Level :: Info ,
106- } ;
113+ let level = match frame. level ( ) {
114+ Some ( DefmtLevel :: Error ) => Level :: Error ,
115+ Some ( DefmtLevel :: Warn ) => Level :: Warn ,
116+ Some ( DefmtLevel :: Info ) => Level :: Info ,
117+ Some ( DefmtLevel :: Debug ) => Level :: Debug ,
118+ Some ( DefmtLevel :: Trace ) => Level :: Trace ,
119+ None => Level :: Info ,
120+ } ;
121+
122+ Self { level, msg }
123+ }
107124
108- log:: log!( level, "{msg}" ) ;
125+ /// Log the message to the Rust logger.
126+ pub fn log ( & self ) {
127+ log:: log!( self . level, "{}" , & self . msg) ;
128+ }
109129}
110130
111131/// Gets the log file or log device path.
@@ -314,6 +334,7 @@ fn perform(opts: &Opts) -> Result<bool> {
314334
315335 let mut buf = [ 0 ; READ_BUFFER_SIZE ] ;
316336 let mut stream_decoder = table. new_stream_decoder ( ) ;
337+ let mut unprocessed = 0 ;
317338
318339 while !STOP . load ( Ordering :: SeqCst ) {
319340 // Read from start of device file.
@@ -323,6 +344,7 @@ fn perform(opts: &Opts) -> Result<bool> {
323344
324345 // Read data.
325346 match log. read ( & mut buf) {
347+ Ok ( 0 ) if unprocessed > 0 => ( ) ,
326348 Ok ( 0 ) if is_dev && !opts. oneshot && !opts. bootloader => {
327349 // Wait for data to arrive.
328350 let log_fd = log. as_fd ( ) ;
@@ -334,7 +356,13 @@ fn perform(opts: &Opts) -> Result<bool> {
334356 }
335357 }
336358 Ok ( 0 ) => return Ok ( true ) ,
337- Ok ( n) => stream_decoder. received ( & buf[ ..n] ) ,
359+ Ok ( n) => {
360+ stream_decoder. received ( & buf[ ..n] ) ;
361+ unprocessed += n;
362+ if unprocessed < UNPROCESSED_SIZE {
363+ continue ;
364+ }
365+ }
338366 Err ( err) if is_dev && err. kind ( ) == ErrorKind :: BrokenPipe => {
339367 log:: warn!( "======== log data was lost ========" ) ;
340368 stream_decoder = table. new_stream_decoder ( ) ;
@@ -344,22 +372,32 @@ fn perform(opts: &Opts) -> Result<bool> {
344372 }
345373
346374 // Decode the received data.
375+ let mut log_msgs = Vec :: new ( ) ;
347376 loop {
348377 match stream_decoder. decode ( ) {
349378 Ok ( frame) => {
350379 let loc = locs. as_ref ( ) . and_then ( |locs| locs. get ( & frame. index ( ) ) ) ;
351- forward_to_logger ( & frame, loc, opts. lines ) ;
380+ let log_msg = LogMsg :: from_defmt ( & frame, loc, opts. lines ) ;
381+ log_msgs. push ( log_msg) ;
352382 }
353383 Err ( DecodeError :: UnexpectedEof ) => break ,
354384 Err ( DecodeError :: Malformed ) => {
355385 log:: warn!( "======== malformed log data ========" ) ;
356386 if !table. encoding ( ) . can_recover ( ) {
357387 return Err ( DecodeError :: Malformed . into ( ) ) ;
358388 }
359- break ;
389+ if !opts. malformed {
390+ log_msgs. clear ( ) ;
391+ }
360392 }
361393 }
362394 }
395+ unprocessed = 0 ;
396+
397+ // Log to system log.
398+ for log_msg in log_msgs {
399+ log_msg. log ( ) ;
400+ }
363401 }
364402
365403 Ok ( false )
0 commit comments