]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_log.c
* Add support for log buffer which can be passed to Linux kernel's
[karo-tx-uboot.git] / common / cmd_log.c
1 /*
2  * (C) Copyright 2002
3  * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Logbuffer handling routines
26  */
27
28 #include <common.h>
29 #include <command.h>
30 #include <devices.h>
31 #include <logbuff.h>
32
33 #if defined(CONFIG_LOGBUFFER)
34
35 #define LOG_BUF_LEN     (16384)
36 #define LOG_BUF_MASK    (LOG_BUF_LEN-1)
37
38 /* Local prototypes */
39 static void logbuff_putc (const char c);
40 static void logbuff_puts (const char *s);
41 static int logbuff_printk(const char *line);
42
43 static char buf[1024];
44
45 static unsigned console_loglevel = 3;
46 static unsigned default_message_loglevel = 4;
47 static unsigned long log_size;
48 static unsigned char *log_buf=NULL;
49 static unsigned long *ext_log_start, *ext_logged_chars;
50 #define log_start (*ext_log_start)
51 #define logged_chars (*ext_logged_chars)
52
53 /* Forced by code, eh! */
54 #define LOGBUFF_MAGIC 0xc0de4ced
55
56 int drv_logbuff_init (void)
57 {
58         device_t logdev;
59         int rc;
60
61         /* Device initialization */
62         memset (&logdev, 0, sizeof (logdev));
63
64         strcpy (logdev.name, "logbuff");
65         logdev.ext   = 0;                       /* No extensions */
66         logdev.flags = DEV_FLAGS_OUTPUT;        /* Output only */
67         logdev.putc  = logbuff_putc;            /* 'putc' function */
68         logdev.puts  = logbuff_puts;            /* 'puts' function */
69
70         rc = device_register (&logdev);
71
72         return (rc == 0) ? 1 : rc;
73 }
74
75 static void logbuff_putc (const char c)
76 {
77         char buf[2];
78         buf[0]=c;
79         buf[1]='\0';
80         logbuff_printk(buf);
81 }
82
83 static void logbuff_puts (const char *s)
84 {
85         char buf[512];
86
87         sprintf(buf, "%s\n", s);
88         logbuff_printk(buf);
89 }
90
91 void logbuff_log(char *msg)
92 {
93         DECLARE_GLOBAL_DATA_PTR;
94
95         if (gd->flags & GD_FLG_RELOC) {
96                 logbuff_printk(msg);
97         } else {
98                 puts(msg);
99         }
100 }
101
102 void logbuff_reset (void)
103 {
104         char *s;
105         unsigned long *ext_tag;
106
107         if ((s = getenv ("logstart")) != NULL) {
108                 log_buf = (unsigned char *)simple_strtoul(s, NULL, 16);
109                 ext_tag=(unsigned long *)(log_buf)-3;
110                 ext_log_start=(unsigned long *)(log_buf)-2;
111                 ext_logged_chars=(unsigned long *)(log_buf)-1;
112 //              if (*ext_tag!=LOGBUFF_MAGIC) {
113                         logged_chars=log_start=0;
114                         *ext_tag=LOGBUFF_MAGIC;
115 //              }
116                 log_size=logged_chars;
117         }
118 }
119
120 /*
121  * Subroutine:  do_log
122  *
123  * Description: Handler for 'log' command..
124  *
125  * Inputs:      argv[1] contains the subcommand
126  *
127  * Return:      None
128  *
129  */
130 int do_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
131 {
132         char *s;
133         unsigned long i;
134
135         if (log_buf==NULL) {
136                 printf ("No logbuffer defined!  Set 'logstart' to use this feature.\n");
137                 return 1;
138         }
139
140         switch (argc) {
141
142         case 2:
143                 if (strcmp(argv[1],"show") == 0) {
144                         for (i=0; i<logged_chars; i++) {
145                                 s=log_buf+((log_start+i)&LOG_BUF_MASK);
146                                 putc(*s);
147                         }
148                         return 0;
149                 } else if (strcmp(argv[1],"reset") == 0) {
150                         log_start=0;
151                         logged_chars=0;
152                         log_size=0;
153                         return 0;
154                 }
155                 printf ("Usage:\n%s\n", cmdtp->usage);
156                 return 1;
157
158         case 3:
159                 if (strcmp(argv[1],"append") == 0) {
160                         logbuff_puts(argv[2]);
161                         return 0;
162
163                 }
164                 printf ("Usage:\n%s\n", cmdtp->usage);
165                 return 1;
166
167         default:
168                 printf ("Usage:\n%s\n", cmdtp->usage);
169                 return 1;
170         }
171 }
172
173 static int logbuff_printk(const char *line)
174 {
175         int i;
176         char *msg, *p, *buf_end;
177         int line_feed;
178         static signed char msg_level = -1;
179
180         strcpy(buf + 3, line);
181         i = strlen(line);
182         buf_end = buf + 3 + i;
183         for (p = buf + 3; p < buf_end; p++) {
184                 msg = p;
185                 if (msg_level < 0) {
186                         if (
187                                 p[0] != '<' ||
188                                 p[1] < '0' ||
189                                 p[1] > '7' ||
190                                 p[2] != '>'
191                         ) {
192                                 p -= 3;
193                                 p[0] = '<';
194                                 p[1] = default_message_loglevel + '0';
195                                 p[2] = '>';
196                         } else
197                                 msg += 3;
198                         msg_level = p[1] - '0';
199                 }
200                 line_feed = 0;
201                 for (; p < buf_end; p++) {
202                         log_buf[(log_start+log_size) & LOG_BUF_MASK] = *p;
203                         if (log_size < LOG_BUF_LEN)
204                                 log_size++;
205                         else
206                                 log_start++;
207
208                         logged_chars++;
209                         if (*p == '\n') {
210                                 line_feed = 1;
211                                 break;
212                         }
213                 }
214                 if (msg_level < console_loglevel) {
215                         printf("%s", msg);
216                 }
217                 if (line_feed)
218                         msg_level = -1;
219         }
220         return i;
221 }
222
223 #endif /* (CONFIG_LOGBUFFER) */