source: SVN/rincon/u-boot/common/cmd_log.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 7.4 KB
Line 
1/*
2 * (C) Copyright 2002-2007
3 * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
4 *
5 * Code used from linux/kernel/printk.c
6 * Copyright (C) 1991, 1992  Linus Torvalds
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 *
26 * Comments:
27 *
28 * After relocating the code, the environment variable "loglevel" is
29 * copied to console_loglevel.  The functionality is similar to the
30 * handling in the Linux kernel, i.e. messages logged with a priority
31 * less than console_loglevel are also output to stdout.
32 *
33 * If you want messages with the default level (e.g. POST messages) to
34 * appear on stdout also, make sure the environment variable
35 * "loglevel" is set at boot time to a number higher than
36 * default_message_loglevel below.
37 */
38
39/*
40 * Logbuffer handling routines
41 */
42
43#include <common.h>
44#include <command.h>
45#include <devices.h>
46#include <post.h>
47#include <logbuff.h>
48
49DECLARE_GLOBAL_DATA_PTR;
50
51/* Local prototypes */
52static void logbuff_putc (const char c);
53static void logbuff_puts (const char *s);
54static int logbuff_printk(const char *line);
55
56static char buf[1024];
57
58/* This combination will not print messages with the default loglevel */
59static unsigned console_loglevel = 3;
60static unsigned default_message_loglevel = 4;
61static unsigned log_version = 1;
62#ifdef CONFIG_ALT_LB_ADDR
63static volatile logbuff_t *log;
64#else
65static logbuff_t *log;
66#endif
67static char *lbuf;
68
69unsigned long __logbuffer_base(void)
70{
71        return CFG_SDRAM_BASE + gd->bd->bi_memsize - LOGBUFF_LEN;
72}
73unsigned long logbuffer_base (void) __attribute__((weak, alias("__logbuffer_base")));
74
75void logbuff_init_ptrs (void)
76{
77        unsigned long tag, post_word;
78        char *s;
79
80#ifdef CONFIG_ALT_LB_ADDR
81        log = (logbuff_t *)CONFIG_ALT_LH_ADDR;
82        lbuf = (char *)CONFIG_ALT_LB_ADDR;
83#else
84        log = (logbuff_t *)(logbuffer_base ()) - 1;
85        lbuf = (char *)log->buf;
86#endif
87
88        /* Set up log version */
89        if ((s = getenv ("logversion")) != NULL)
90                log_version = (int)simple_strtoul (s, NULL, 10);
91
92        if (log_version == 2)
93                tag = log->v2.tag;
94        else
95                tag = log->v1.tag;
96        post_word = post_word_load();
97#ifdef CONFIG_POST
98        /* The post routines have setup the word so we can simply test it */
99        if (tag != LOGBUFF_MAGIC || (post_word & POST_COLDBOOT)) {
100                logbuff_reset ();
101        }
102#else
103        /* No post routines, so we do our own checking                    */
104        if (tag != LOGBUFF_MAGIC || post_word != LOGBUFF_MAGIC) {
105                logbuff_reset ();
106                post_word_store (LOGBUFF_MAGIC);
107        }
108#endif
109        if (log_version == 2 && (long)log->v2.start > (long)log->v2.con)
110                log->v2.start = log->v2.con;
111
112        /* Initialize default loglevel if present */
113        if ((s = getenv ("loglevel")) != NULL)
114                console_loglevel = (int)simple_strtoul (s, NULL, 10);
115
116        gd->flags |= GD_FLG_LOGINIT;
117}
118
119void logbuff_reset (void)
120{
121#ifndef CONFIG_ALT_LB_ADDR
122        memset (log, 0, sizeof (logbuff_t));
123#endif
124        if (log_version == 2) {
125                log->v2.tag = LOGBUFF_MAGIC;
126#ifdef CONFIG_ALT_LB_ADDR
127                log->v2.start = 0;
128                log->v2.con = 0;
129                log->v2.end = 0;
130                log->v2.chars = 0;
131#endif
132        } else {
133                log->v1.tag = LOGBUFF_MAGIC;
134#ifdef CONFIG_ALT_LB_ADDR
135                log->v1.dummy = 0;
136                log->v1.start = 0;
137                log->v1.size = 0;
138                log->v1.chars = 0;
139#endif
140        }
141}
142
143int drv_logbuff_init (void)
144{
145        device_t logdev;
146        int rc;
147
148        /* Device initialization */
149        memset (&logdev, 0, sizeof (logdev));
150
151        strcpy (logdev.name, "logbuff");
152        logdev.ext   = 0;                       /* No extensions */
153        logdev.flags = DEV_FLAGS_OUTPUT;        /* Output only */
154        logdev.putc  = logbuff_putc;            /* 'putc' function */
155        logdev.puts  = logbuff_puts;            /* 'puts' function */
156
157        rc = device_register (&logdev);
158
159        return (rc == 0) ? 1 : rc;
160}
161
162static void logbuff_putc (const char c)
163{
164        char buf[2];
165        buf[0] = c;
166        buf[1] = '\0';
167        logbuff_printk (buf);
168}
169
170static void logbuff_puts (const char *s)
171{
172        logbuff_printk (s);
173}
174
175void logbuff_log(char *msg)
176{
177        if ((gd->flags & GD_FLG_LOGINIT)) {
178                logbuff_printk (msg);
179        } else {
180                /* Can happen only for pre-relocated errors as logging */
181                /* at that stage should be disabled                    */
182                puts (msg);
183        }
184}
185
186/*
187 * Subroutine:  do_log
188 *
189 * Description: Handler for 'log' command..
190 *
191 * Inputs:      argv[1] contains the subcommand
192 *
193 * Return:      None
194 *
195 */
196int do_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
197{
198        char *s;
199        unsigned long i, start, size;
200
201        if (strcmp(argv[1],"append") == 0) {
202                /* Log concatenation of all arguments separated by spaces */
203                for (i=2; i<argc; i++) {
204                        logbuff_printk (argv[i]);
205                        logbuff_putc ((i<argc-1) ? ' ' : '\n');
206                }
207                return 0;
208        }
209
210        switch (argc) {
211
212        case 2:
213                if (strcmp(argv[1],"show") == 0) {
214                        if (log_version == 2) {
215                                start = log->v2.start;
216                                size = log->v2.end - log->v2.start;
217                        }
218                        else {
219                                start = log->v1.start;
220                                size = log->v1.size;
221                        }
222                        for (i=0; i < (size&LOGBUFF_MASK); i++) {
223                                s = lbuf+((start+i)&LOGBUFF_MASK);
224                                putc (*s);
225                        }
226                        return 0;
227                } else if (strcmp(argv[1],"reset") == 0) {
228                        logbuff_reset ();
229                        return 0;
230                } else if (strcmp(argv[1],"info") == 0) {
231                        printf ("Logbuffer   at  %08lx\n", (unsigned long)lbuf);
232                        if (log_version == 2) {
233                                printf ("log_start    =  %08lx\n", log->v2.start);
234                                printf ("log_end      =  %08lx\n", log->v2.end);
235                                printf ("logged_chars =  %08lx\n", log->v2.chars);
236                        }
237                        else {
238                                printf ("log_start    =  %08lx\n", log->v1.start);
239                                printf ("log_size     =  %08lx\n", log->v1.size);
240                                printf ("logged_chars =  %08lx\n", log->v1.chars);
241                        }
242                        return 0;
243                }
244                printf ("Usage:\n%s\n", cmdtp->usage);
245                return 1;
246
247        default:
248                printf ("Usage:\n%s\n", cmdtp->usage);
249                return 1;
250        }
251}
252
253U_BOOT_CMD(
254        log,     255,   1,      do_log,
255        "log     - manipulate logbuffer\n",
256        "info   - show pointer details\n"
257        "log reset  - clear contents\n"
258        "log show   - show contents\n"
259        "log append <msg> - append <msg> to the logbuffer\n"
260);
261
262static int logbuff_printk(const char *line)
263{
264        int i;
265        char *msg, *p, *buf_end;
266        int line_feed;
267        static signed char msg_level = -1;
268
269        strcpy (buf + 3, line);
270        i = strlen (line);
271        buf_end = buf + 3 + i;
272        for (p = buf + 3; p < buf_end; p++) {
273                msg = p;
274                if (msg_level < 0) {
275                        if (
276                                p[0] != '<' ||
277                                p[1] < '0' ||
278                                p[1] > '7' ||
279                                p[2] != '>'
280                        ) {
281                                p -= 3;
282                                p[0] = '<';
283                                p[1] = default_message_loglevel + '0';
284                                p[2] = '>';
285                        } else
286                                msg += 3;
287                        msg_level = p[1] - '0';
288                }
289                line_feed = 0;
290                for (; p < buf_end; p++) {
291                        if (log_version == 2) {
292                                lbuf[log->v2.end & LOGBUFF_MASK] = *p;
293                                log->v2.end++;
294                                if (log->v2.end - log->v2.start > LOGBUFF_LEN)
295                                        log->v2.start++;
296                                log->v2.chars++;
297                        }
298                        else {
299                                lbuf[(log->v1.start + log->v1.size) &
300                                         LOGBUFF_MASK] = *p;
301                                if (log->v1.size < LOGBUFF_LEN)
302                                        log->v1.size++;
303                                else
304                                        log->v1.start++;
305                                log->v1.chars++;
306                        }
307                        if (*p == '\n') {
308                                line_feed = 1;
309                                break;
310                        }
311                }
312                if (msg_level < console_loglevel) {
313                        printf("%s", msg);
314                }
315                if (line_feed)
316                        msg_level = -1;
317        }
318        return i;
319}
Note: See TracBrowser for help on using the repository browser.