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
50 static char LogText[512];
51 static int LogTextIndex;
52 static int LogCount = 0;
53 static 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 ************************************************************************/
fr_Log_Time(FlightRecorder * Fr)62 static 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 /************************************************************************/
fr_Log_Data(FlightRecorder * Fr)95 static 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 ************************************************************************/
fr_Log_Entry(struct flightRecorder * LogFr,const char * fmt,...)111 void 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 ************************************************************************/
fr_Dump(FlightRecorder * Fr,char * Buffer,int BufferLen)129 int 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 ************************************************************************/
alloc_Flight_Recorder(FlightRecorder * FrPtr,char * Signature,int SizeOfFr)166 FlightRecorder* 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