1/************************************************************************ 2 * flight_recorder.c 3 ************************************************************************ 4 * This code supports the a generic flight recorder. * 5 * Copyright (C) 20yy <Allan H Trautman> <IBM Corp> * 6 * * 7 * This program is free software; you can redistribute it and/or modify * 8 * it under the terms of the GNU General Public License as published by * 9 * the Free Software Foundation; either version 2 of the License, or * 10 * (at your option) any later version. * 11 * * 12 * This program is distributed in the hope that it will be useful, * 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 * GNU General Public License for more details. * 16 * * 17 * You should have received a copy of the GNU General Public License * 18 * along with this program; if not, write to the: * 19 * Free Software Foundation, Inc., * 20 * 59 Temple Place, Suite 330, * 21 * Boston, MA 02111-1307 USA * 22 ************************************************************************ 23 * This is a simple text based flight recorder. Useful for logging 24 * information the you may want to retreive at a latter time. Errors or 25 * debug inforamtion are good examples. A good method to dump the 26 * information is via the proc file system. 27 * 28 * To use. 29 * 1. Create the flight recorder object. Passing a NULL pointer will 30 * kmalloc the space for you. If it is too early for kmalloc, create 31 * space for the object. Beware, don't lie about the size, you will 32 * pay for that later. 33 * FlightRecorder* TestFr = alloc_Flight_Recorder(NULL,"TestFr",4096); 34 * 35 * 2. Log any notable events, initialzation, error conditions, etc. 36 * LOGFR(TestFr,"5. Stack Variable(10) %d",StackVariable); 37 * 38 * 3. Dump the information to a buffer. 39 * fr_Dump(TestFr, proc_file_buffer, proc_file_buffer_size); 40 * 41 ************************************************************************/ 42#include <stdarg.h> 43#include <linux/kernel.h> 44#include <linux/rtc.h> 45#include <linux/slab.h> 46#include <asm/string.h> 47#include <asm/time.h> 48#include <asm/flight_recorder.h> 49 50static char LogText[512]; 51static int LogTextIndex; 52static int LogCount = 0; 53static spinlock_t Fr_Lock; 54 55/************************************************************************ 56 * Build the log time prefix based on Flags. 57 * 00 = No time prefix 58 * 01 = Date(mmddyy) Time(hhmmss) prefix 59 * 02 = Day(dd) Time(hhmmss) prefix 60 * 03 = Time(hhmmss) prefix 61 ************************************************************************/ 62static void fr_Log_Time(FlightRecorder* Fr) 63{ 64 struct timeval TimeClock; 65 struct rtc_time LogTime; 66 67 do_gettimeofday(&TimeClock); 68 to_tm(TimeClock.tv_sec, &LogTime); 69 70 if (Fr->Flags == 1) { 71 LogTextIndex = sprintf(LogText,"%02d%02d%02d %02d%02d%02d ", 72 LogTime.tm_mon, LogTime.tm_mday, LogTime.tm_year-2000, 73 LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); 74 } 75 else if (Fr->Flags == 2) { 76 LogTextIndex = sprintf(LogText,"%02d %02d%02d%02d ", 77 LogTime.tm_mday, 78 LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); 79 } 80 81 else if (Fr->Flags == 3) { 82 LogTextIndex = sprintf(LogText,"%02d%02d%02d ", 83 LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); 84 } 85 else { 86 ++LogCount; 87 LogTextIndex = sprintf(LogText,"%04d. ",LogCount); 88 } 89} 90 91/************************************************************************/ 92/* Log entry into buffer, */ 93/* ->If entry is going to wrap, log "WRAP" and start at the top. */ 94/************************************************************************/ 95static void fr_Log_Data(FlightRecorder* Fr) 96{ 97 int TextLen = strlen(LogText); 98 int Residual = ( Fr->EndPointer - Fr->NextPointer)-15; 99 if (TextLen > Residual) { 100 strcpy(Fr->NextPointer,"WRAP"); 101 Fr->WrapPointer = Fr->NextPointer + 5; 102 Fr->NextPointer = Fr->StartPointer; 103 } 104 strcpy(Fr->NextPointer,LogText); 105 Fr->NextPointer += TextLen+1; 106 strcpy(Fr->NextPointer,"<="); 107} 108/************************************************************************ 109 * Build the log text, support variable args. 110 ************************************************************************/ 111void fr_Log_Entry(struct flightRecorder* LogFr, const char *fmt, ...) 112{ 113 va_list arg_ptr; 114 spin_lock(&Fr_Lock); 115 116 fr_Log_Time(LogFr); 117 va_start(arg_ptr, fmt); 118 vsprintf(LogText+LogTextIndex, fmt, arg_ptr); 119 va_end(arg_ptr); 120 fr_Log_Data(LogFr); 121 122 spin_unlock(&Fr_Lock); 123 124} 125/************************************************************************ 126 * Dump Flight Recorder into buffer. 127 * -> Handles the buffer wrapping. 128 ************************************************************************/ 129int fr_Dump(FlightRecorder* Fr, char *Buffer, int BufferLen) 130{ 131 int LineLen = 0; 132 char* StartEntry; 133 char* EndEntry; 134 spin_lock(&Fr_Lock); 135 /**************************************************************** 136 * If Buffer has wrapped, find last usable entry to start with. 137 ****************************************************************/ 138 if (Fr->WrapPointer != NULL) { 139 StartEntry = Fr->NextPointer+3; 140 StartEntry += strlen(StartEntry)+1; 141 EndEntry = Fr->WrapPointer; 142 143 while (EndEntry > StartEntry && LineLen < BufferLen) { 144 LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry); 145 StartEntry += strlen(StartEntry) + 1; 146 } 147 } 148 149 /**************************************************************** 150 * Dump from the beginning to the last logged entry 151 ****************************************************************/ 152 StartEntry = Fr->StartPointer; 153 EndEntry = Fr->NextPointer; 154 while (EndEntry > StartEntry && LineLen < BufferLen) { 155 LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry); 156 StartEntry += strlen(StartEntry) + 1; 157 } 158 spin_unlock(&Fr_Lock); 159 return LineLen; 160} 161 162/************************************************************************ 163 * Allocate and Initialized the Flight Recorder 164 * -> If no FlightRecorder pointer is passed, the space is kmalloc. 165 ************************************************************************/ 166FlightRecorder* alloc_Flight_Recorder(FlightRecorder* FrPtr, char* Signature, int SizeOfFr) 167{ 168 FlightRecorder* Fr = FrPtr; /* Pointer to Object */ 169 int FrSize = (SizeOfFr/16)*16; /* Could be static */ 170 if (Fr == NULL) 171 Fr = (FlightRecorder*)kmalloc(SizeOfFr, GFP_KERNEL); 172 memset(Fr,0,SizeOfFr); 173 strcpy(Fr->Signature,Signature); 174 Fr->Size = FrSize; 175 Fr->Flags = 0; 176 Fr->StartPointer = (char*)&Fr->Buffer; 177 Fr->EndPointer = (char*)Fr + Fr->Size; 178 Fr->NextPointer = Fr->StartPointer; 179 180 fr_Log_Entry(Fr,"Initialized."); 181 return Fr; 182} 183