Mahesh Kallelil | 9e2bbf3 | 2024-08-14 14:52:29 -0700 | [diff] [blame^] | 1 | // Copyright 2024 Google LLC |
| 2 | |
| 3 | //! The dump_modem binary is used to capture kernel/userspace logs in bugreport |
| 4 | |
| 5 | use std::fs; |
| 6 | |
| 7 | const MODEM_STAT: &str = "/data/vendor/modem_stat/debug.txt"; |
| 8 | const SSRDUMP_DIR: &str = "/data/vendor/ssrdump"; |
| 9 | const RFSD_ERR_LOG_DIR: &str = "/data/vendor/log/rfsd"; |
| 10 | const WAKEUP_EVENTS: &str = "/sys/devices/platform/cpif/wakeup_events"; |
| 11 | const CPIF_LOGBUFFER: &str = "/dev/logbuffer_cpif"; |
| 12 | const PCIE_EVENT_STATS: &str = "/sys/devices/platform/cpif/modem/pcie_event_stats"; |
| 13 | |
| 14 | fn handle_io_error(file: &str, err: std::io::Error) { |
| 15 | match err.kind() { |
| 16 | std::io::ErrorKind::NotFound => println!("{file} not found!"), |
| 17 | std::io::ErrorKind::PermissionDenied => println!("Permission denied to access {file}"), |
| 18 | _ => println!("I/O error accessing {file}: {err}"), |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | fn print_file(file: &str) -> Result<(), std::io::Error> { |
| 23 | fs::metadata(file)?; |
| 24 | |
| 25 | let data = fs::read_to_string(file)?; |
| 26 | |
| 27 | if data.is_empty() { |
| 28 | println!("{file} is empty"); |
| 29 | } else { |
| 30 | print!("{data}"); |
| 31 | } |
| 32 | |
| 33 | Ok(()) |
| 34 | } |
| 35 | |
| 36 | fn print_file_and_handle_error(file: &str) { |
| 37 | if let Err(err) = print_file(file) { |
| 38 | handle_io_error(file, err); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | fn print_matching_files_in_dir(dir: &str, filename: &str) { |
| 43 | let Ok(entries) = fs::read_dir(dir) else { |
| 44 | return println!("Cannot open directory {dir}"); |
| 45 | }; |
| 46 | |
| 47 | for entry in entries { |
| 48 | let Ok(entry) = entry else { |
| 49 | continue; |
| 50 | }; |
| 51 | if entry.path().is_file() && entry.file_name().to_string_lossy().starts_with(filename) { |
| 52 | if let Some(path_str) = entry.path().to_str() { |
| 53 | println!("{}", path_str); |
| 54 | print_file_and_handle_error(path_str); |
| 55 | } |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | // Capture modem stat log if it exists |
| 61 | fn modem_stat() { |
| 62 | println!("------ Modem Stat ------"); |
| 63 | print_file_and_handle_error(MODEM_STAT); |
| 64 | println!(); |
| 65 | } |
| 66 | |
| 67 | // Capture crash signatures from all modem crashes |
| 68 | fn modem_ssr_history() { |
| 69 | println!("------ Modem SSR history ------"); |
| 70 | print_matching_files_in_dir(SSRDUMP_DIR, "crashinfo_modem"); |
| 71 | println!(); |
| 72 | } |
| 73 | |
| 74 | // Capture rfsd error logs from all existing log files |
| 75 | fn rfsd_error_log() { |
| 76 | println!("------ RFSD error log ------"); |
| 77 | print_matching_files_in_dir(RFSD_ERR_LOG_DIR, "rfslog"); |
| 78 | println!(); |
| 79 | } |
| 80 | |
| 81 | // Capture modem wakeup events if the sysfs attribute exists |
| 82 | fn wakeup_events() { |
| 83 | println!("------ Wakeup event counts ------"); |
| 84 | print_file_and_handle_error(WAKEUP_EVENTS); |
| 85 | println!(); |
| 86 | } |
| 87 | |
| 88 | // Capture kernel driver logbuffer if it exists |
| 89 | fn cpif_logbuffer() { |
| 90 | println!("------ CPIF Logbuffer ------"); |
| 91 | print_file_and_handle_error(CPIF_LOGBUFFER); |
| 92 | println!(); |
| 93 | } |
| 94 | |
| 95 | // Capture modem pcie stats if the sysfs attribute exists |
| 96 | fn pcie_event_stats() { |
| 97 | println!("------ PCIe event stats ------"); |
| 98 | print_file_and_handle_error(PCIE_EVENT_STATS); |
| 99 | println!(); |
| 100 | } |
| 101 | |
| 102 | fn main() { |
| 103 | modem_stat(); |
| 104 | modem_ssr_history(); |
| 105 | rfsd_error_log(); |
| 106 | wakeup_events(); |
| 107 | cpif_logbuffer(); |
| 108 | pcie_event_stats(); |
| 109 | } |