2525#include < stdio.h>
2626#include < stdlib.h>
2727#include < string.h>
28+ #include < sys/klog.h>
2829#include < sys/stat.h>
2930#include < sys/types.h>
3031#include < time.h>
@@ -76,6 +77,8 @@ static const char *CACHE_ROOT = "/cache";
7677static const char *SDCARD_ROOT = " /sdcard" ;
7778static const char *TEMPORARY_LOG_FILE = " /tmp/recovery.log" ;
7879static const char *TEMPORARY_INSTALL_FILE = " /tmp/last_install" ;
80+ static const char *LAST_KMSG_FILE = " /cache/recovery/last_kmsg" ;
81+ #define KLOG_DEFAULT_LEN (64 * 1024 )
7982
8083#define KEEP_LOG_COUNT 10
8184
@@ -259,6 +262,44 @@ set_sdcard_update_bootloader_message() {
259262 set_bootloader_message (&boot);
260263}
261264
265+ // read from kernel log into buffer and write out to file
266+ static void
267+ save_kernel_log (const char *destination) {
268+ int n;
269+ char *buffer;
270+ int klog_buf_len;
271+ FILE *log;
272+
273+ klog_buf_len = klogctl (KLOG_SIZE_BUFFER, 0 , 0 );
274+ if (klog_buf_len <= 0 ) {
275+ LOGE (" Error getting klog size (%s), using default\n " , strerror (errno));
276+ klog_buf_len = KLOG_DEFAULT_LEN;
277+ }
278+
279+ buffer = (char *)malloc (klog_buf_len);
280+ if (!buffer) {
281+ LOGE (" Can't alloc %d bytes for klog buffer\n " , klog_buf_len);
282+ return ;
283+ }
284+
285+ n = klogctl (KLOG_READ_ALL, buffer, klog_buf_len);
286+ if (n < 0 ) {
287+ LOGE (" Error in reading klog (%s)\n " , strerror (errno));
288+ free (buffer);
289+ return ;
290+ }
291+
292+ log = fopen_path (destination, " w" );
293+ if (log == NULL ) {
294+ LOGE (" Can't open %s\n " , destination);
295+ free (buffer);
296+ return ;
297+ }
298+ fwrite (buffer, n, 1 , log);
299+ check_and_fclose (log, destination);
300+ free (buffer);
301+ }
302+
262303// How much of the temp log we have copied to the copy in cache.
263304static long tmplog_offset = 0 ;
264305
@@ -306,8 +347,11 @@ copy_logs() {
306347 copy_log_file (TEMPORARY_LOG_FILE, LOG_FILE, true );
307348 copy_log_file (TEMPORARY_LOG_FILE, LAST_LOG_FILE, false );
308349 copy_log_file (TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false );
350+ save_kernel_log (LAST_KMSG_FILE);
309351 chmod (LOG_FILE, 0600 );
310352 chown (LOG_FILE, 1000 , 1000 ); // system user
353+ chmod (LAST_KMSG_FILE, 0600 );
354+ chown (LAST_KMSG_FILE, 1000 , 1000 ); // system user
311355 chmod (LAST_LOG_FILE, 0640 );
312356 chmod (LAST_INSTALL_FILE, 0644 );
313357 sync ();
@@ -695,15 +739,26 @@ static void file_to_ui(const char* fn) {
695739}
696740
697741static void choose_recovery_file (Device* device) {
698- int i;
742+ unsigned int i;
743+ unsigned int n;
699744 static const char ** title_headers = NULL ;
700745 char *filename;
701746 const char * headers[] = { " Select file to view" ,
702747 " " ,
703748 NULL };
704- char * entries[KEEP_LOG_COUNT + 2 ];
749+ // "Go back" + LAST_KMSG_FILE + KEEP_LOG_COUNT + terminating NULL entry
750+ char * entries[KEEP_LOG_COUNT + 3 ];
705751 memset (entries, 0 , sizeof (entries));
706752
753+ n = 0 ;
754+ entries[n++] = strdup (" Go back" );
755+
756+ // Add kernel kmsg file if available
757+ if ((ensure_path_mounted (LAST_KMSG_FILE) == 0 ) && (access (LAST_KMSG_FILE, R_OK) == 0 )) {
758+ entries[n++] = strdup (LAST_KMSG_FILE);
759+ }
760+
761+ // Add LAST_LOG_FILE + LAST_LOG_FILE.x
707762 for (i = 0 ; i < KEEP_LOG_COUNT; i++) {
708763 char *filename;
709764 if (asprintf (&filename, (i==0 ) ? LAST_LOG_FILE : (LAST_LOG_FILE " .%d" ), i) == -1 ) {
@@ -712,13 +767,12 @@ static void choose_recovery_file(Device* device) {
712767 }
713768 if ((ensure_path_mounted (filename) != 0 ) || (access (filename, R_OK) == -1 )) {
714769 free (filename);
715- entries[i+ 1 ] = NULL ;
770+ entries[n++ ] = NULL ;
716771 break ;
717772 }
718- entries[i+ 1 ] = filename;
773+ entries[n++ ] = filename;
719774 }
720775
721- entries[0 ] = strdup (" Go back" );
722776 title_headers = prepend_title ((const char **)headers);
723777
724778 while (1 ) {
@@ -727,7 +781,7 @@ static void choose_recovery_file(Device* device) {
727781 file_to_ui (entries[chosen_item]);
728782 }
729783
730- for (i = 0 ; i < KEEP_LOG_COUNT + 1 ; i++) {
784+ for (i = 0 ; i < ( sizeof (entries) / sizeof (*entries)) ; i++) {
731785 free (entries[i]);
732786 }
733787}
0 commit comments