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
handle_io_error(file: &str, err: std::io::Error)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
print_file(file: &str) -> Result<(), std::io::Error>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
print_file_and_handle_error(file: &str)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
print_matching_files_in_dir(dir: &str, filename: &str)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
modem_stat()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
modem_ssr_history()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
rfsd_error_log()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
wakeup_events()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
cpif_logbuffer()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
pcie_event_stats()96 fn pcie_event_stats() {
97 println!("------ PCIe event stats ------");
98 print_file_and_handle_error(PCIE_EVENT_STATS);
99 println!();
100 }
101
main()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 }
110