Message ID | 1332188824-5447-2-git-send-email-sjg@chromium.org |
---|---|
State | New, archived |
Headers | show |
Hi Simon, On Tue, Mar 20, 2012 at 7:27 AM, Simon Glass <sjg@chromium.org> wrote: > This patch adds support for console output in the event of a panic() before > the console is inited. The main purpose of this is to deal with a very early > panic() which would otherwise cause a silent hang. > > A new board_pre_console_panic() function is added to the board API. If > provided by the board it will be called in the event of a panic before the > console is ready. This function should turn on all available UARTs and > output the string (plus a newline) if it possibly can. > > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > void panic(const char *fmt, ...) > { > + char str[CONFIG_SYS_PBSIZE]; > va_list args; > + > va_start(args, fmt); > - vprintf(fmt, args); > - putc('\n'); > + vsnprintf(str, sizeof(str), fmt, args); > va_end(args); > + > + if (gd->have_console) { > + puts(str); > + putc('\n'); > + } else { > + board_pre_console_panic(str); > + } > + Would there be benefit in including an option to dump the pre-console buffer (if one is enabled) - I think it's contents could be rather useful in debugging what went wrong... And something is nagging at me that the API is just 'not right'. I don't know exactly why, but I really don't like how this is plumbed panic() calls putc() which, if we do not have a console (and we won't in the case of the early panic case we are dealing with), will be put into the pre console buffer (if enabled) So having panic() call a board specific function to dump the pre console buffer after the vprintf() / putc() would achieve the same result (but you need pre console buffer enabled) So, if CONFIG_PRE_CONSOLE_BUFFER is defined, we could simply add a call to dump_pre_console_buffer() at the end of panic(). But we already have a function to do that - print_pre_console_buffer(). If we added an argument to print_pre_console_buffer() which is a pointer to a 'putc()' type function (NULL meaning the standard putc()) and that function lived in the board files then life would be good. We could also add a call to a setup function so we are not setting up the UARTS every putc (not that performance is a priority at this stage, but some boards might quibble about hitting certain registers continuously) But what to do if pre console buffer is not defined? The panic message needs to be sent directly to the 'panic UARTS'... OK, so what about in panic(): - If gd->have_console is not set: o call the board specific setup_panic_uarts() o call print_pre_console_buffer() passing panic_putc() o call panic_putc() for all characters in str[] - If gd->have_console is set: o call putc() for all characters in str[] setup_panic_uarts() and panic_putc() are overriden in the board files Regards, Graeme
Hi Graeme, On Tue, Mar 20, 2012 at 3:26 PM, Graeme Russ <graeme.russ@gmail.com> wrote: > Hi Simon, > > On Tue, Mar 20, 2012 at 7:27 AM, Simon Glass <sjg@chromium.org> wrote: >> This patch adds support for console output in the event of a panic() before >> the console is inited. The main purpose of this is to deal with a very early >> panic() which would otherwise cause a silent hang. >> >> A new board_pre_console_panic() function is added to the board API. If >> provided by the board it will be called in the event of a panic before the >> console is ready. This function should turn on all available UARTs and >> output the string (plus a newline) if it possibly can. >> >> Signed-off-by: Simon Glass <sjg@chromium.org> >> --- > >> void panic(const char *fmt, ...) >> { >> + char str[CONFIG_SYS_PBSIZE]; >> va_list args; >> + >> va_start(args, fmt); >> - vprintf(fmt, args); >> - putc('\n'); >> + vsnprintf(str, sizeof(str), fmt, args); >> va_end(args); >> + >> + if (gd->have_console) { >> + puts(str); >> + putc('\n'); >> + } else { >> + board_pre_console_panic(str); >> + } >> + > > Would there be benefit in including an option to dump the pre-console > buffer (if one is enabled) - I think it's contents could be rather useful > in debugging what went wrong... > > And something is nagging at me that the API is just 'not right'. I don't > know exactly why, but I really don't like how this is plumbed > > panic() calls putc() which, if we do not have a console (and we won't in > the case of the early panic case we are dealing with), will be put into > the pre console buffer (if enabled) > > So having panic() call a board specific function to dump the pre console > buffer after the vprintf() / putc() would achieve the same result (but > you need pre console buffer enabled) > > So, if CONFIG_PRE_CONSOLE_BUFFER is defined, we could simply add a call to > dump_pre_console_buffer() at the end of panic(). But we already have a > function to do that - print_pre_console_buffer(). If we added an argument > to print_pre_console_buffer() which is a pointer to a 'putc()' type > function (NULL meaning the standard putc()) and that function lived in the > board files then life would be good. We could also add a call to a setup > function so we are not setting up the UARTS every putc (not that > performance is a priority at this stage, but some boards might quibble > about hitting certain registers continuously) > > But what to do if pre console buffer is not defined? The panic message > needs to be sent directly to the 'panic UARTS'... > > OK, so what about in panic(): > - If gd->have_console is not set: > o call the board specific setup_panic_uarts() > o call print_pre_console_buffer() passing panic_putc() > o call panic_putc() for all characters in str[] > - If gd->have_console is set: > o call putc() for all characters in str[] > > setup_panic_uarts() and panic_putc() are overriden in the board files I think this is where we got to last time. The act of calling this pre-console panic function is destructive - it may hang the board and output data to UARTs. I think I understand the scheme you propose. But setup_panic_uarts() puts the board into a funny state (e.g. may set up or change clocks and pinmux). You then need a board_pre_console_putc() to actually output the characters - you don't mention that. That was the patch that I reverted :-( Yes I understand that you can separate out the UART init from the part that outputs the characters, but does that really help? To put it another way, I think we need to stick with the idea that this is a panic, not a normal situation. That means that return from the board panic output function may be difficult or impossible, and so a putc() arrangement is not a good idea. For example, I have another board on which there are two possible oscillator clock settings - and we don't know which to use, and the arch clock code has not yet been called! In that case I want the board_pre_console_panic() function to output the string using both options, so that one will produce a message for the user (the other will likely produce just a few characters of garbage because the baud rate is wrong). If we output only a single character then the garbage and good characters will be interspersed. So, can we get away from the idea that this is a reliable and stable way of outputting characters before the console is ready? If you want the pre-console output, I'm sure we can provide a way of accessing it which the board pre-console panic function can use. Regards, Simon > > Regards, > > Graeme
Hi Simon, On Wed, Mar 21, 2012 at 10:22 AM, Simon Glass <sjg@chromium.org> wrote: > Hi Graeme, > > On Tue, Mar 20, 2012 at 3:26 PM, Graeme Russ <graeme.russ@gmail.com> wrote: >> Hi Simon, >> >> >> OK, so what about in panic(): >> - If gd->have_console is not set: >> o call the board specific setup_panic_uarts() >> o call print_pre_console_buffer() passing panic_putc() >> o call panic_putc() for all characters in str[] >> - If gd->have_console is set: >> o call putc() for all characters in str[] >> >> setup_panic_uarts() and panic_putc() are overriden in the board files > > I think this is where we got to last time. > > The act of calling this pre-console panic function is destructive - it > may hang the board and output data to UARTs. > > I think I understand the scheme you propose. But setup_panic_uarts() > puts the board into a funny state (e.g. may set up or change clocks > and pinmux). You then need a board_pre_console_putc() to actually > output the characters - you don't mention that. That was the patch That's panic_putc() > that I reverted :-( Yes I understand that you can separate out the > UART init from the part that outputs the characters, but does that > really help? > > To put it another way, I think we need to stick with the idea that > this is a panic, not a normal situation. That means that return from Agreed > the board panic output function may be difficult or impossible, and so > a putc() arrangement is not a good idea. > > For example, I have another board on which there are two possible > oscillator clock settings - and we don't know which to use, and the > arch clock code has not yet been called! In that case I want the > board_pre_console_panic() function to output the string using both > options, so that one will produce a message for the user (the other > will likely produce just a few characters of garbage because the baud > rate is wrong). If we output only a single character then the garbage > and good characters will be interspersed. Ouch! > So, can we get away from the idea that this is a reliable and stable > way of outputting characters before the console is ready? If you want > the pre-console output, I'm sure we can provide a way of accessing it > which the board pre-console panic function can use. OK, add a function to 'normalise' the pre console buffer by moving the characters so the string starts at the beginning of the buffer and then add an extra format tot he start of the panic string :) - But now the panic buffer needs to be bigger :( OK, maybe leave it up to the board code to dump the pre-console buffer... I dunno - It all seems a bit 'wrong' somehow Regards, Graeme
Hi Graeme, On Tue, Mar 20, 2012 at 4:43 PM, Graeme Russ <graeme.russ@gmail.com> wrote: > Hi Simon, > > On Wed, Mar 21, 2012 at 10:22 AM, Simon Glass <sjg@chromium.org> wrote: >> Hi Graeme, >> >> On Tue, Mar 20, 2012 at 3:26 PM, Graeme Russ <graeme.russ@gmail.com> wrote: >>> Hi Simon, >>> > >>> >>> OK, so what about in panic(): >>> - If gd->have_console is not set: >>> o call the board specific setup_panic_uarts() >>> o call print_pre_console_buffer() passing panic_putc() >>> o call panic_putc() for all characters in str[] >>> - If gd->have_console is set: >>> o call putc() for all characters in str[] >>> >>> setup_panic_uarts() and panic_putc() are overriden in the board files >> >> I think this is where we got to last time. >> >> The act of calling this pre-console panic function is destructive - it >> may hang the board and output data to UARTs. >> >> I think I understand the scheme you propose. But setup_panic_uarts() >> puts the board into a funny state (e.g. may set up or change clocks >> and pinmux). You then need a board_pre_console_putc() to actually >> output the characters - you don't mention that. That was the patch > > That's panic_putc() > >> that I reverted :-( Yes I understand that you can separate out the >> UART init from the part that outputs the characters, but does that >> really help? >> >> To put it another way, I think we need to stick with the idea that >> this is a panic, not a normal situation. That means that return from > > Agreed > >> the board panic output function may be difficult or impossible, and so >> a putc() arrangement is not a good idea. >> >> For example, I have another board on which there are two possible >> oscillator clock settings - and we don't know which to use, and the >> arch clock code has not yet been called! In that case I want the >> board_pre_console_panic() function to output the string using both >> options, so that one will produce a message for the user (the other >> will likely produce just a few characters of garbage because the baud >> rate is wrong). If we output only a single character then the garbage >> and good characters will be interspersed. > > Ouch! Indeed. > >> So, can we get away from the idea that this is a reliable and stable >> way of outputting characters before the console is ready? If you want >> the pre-console output, I'm sure we can provide a way of accessing it >> which the board pre-console panic function can use. > > OK, add a function to 'normalise' the pre console buffer by moving the > characters so the string starts at the beginning of the buffer and then > add an extra format tot he start of the panic string :) - But now the > panic buffer needs to be bigger :( > > OK, maybe leave it up to the board code to dump the pre-console buffer... Yes I think it is simpler for now, until we have a better framework. Both the kernel and U-Boot need early access to information that either might not arrive, or will only arrive later. This business and the current hacks in the zImage wrapper are examples of problems that need solving properly IMO. I am looking at these problems for the U-Boot SPL case, so at some point this will get nicer in U-Boot. Not sure about the kernel yet, but hope to avoid zImage for our next iteration partly because of this nastiness. > > I dunno - It all seems a bit 'wrong' somehow I think you are looking for a unified panic architecture with a board-specific putc(). That was my previous patch and I just don't think it works. This new one does solve the problem, avoids Wolfgangs concerns about dangerous UART output, and is pretty simple to implement. I believe there is a better way, but we are in the very early days with device tree, life goes on, and this does work... Regards, Simon > > Regards, > > Graeme
On 03/20/2012 05:22 PM, Simon Glass wrote: > On Tue, Mar 20, 2012 at 3:26 PM, Graeme Russ <graeme.russ@gmail.com> wrote: ... >> OK, so what about in panic(): >> - If gd->have_console is not set: >> o call the board specific setup_panic_uarts() >> o call print_pre_console_buffer() passing panic_putc() >> o call panic_putc() for all characters in str[] >> - If gd->have_console is set: >> o call putc() for all characters in str[] >> >> setup_panic_uarts() and panic_putc() are overriden in the board files > > I think this is where we got to last time. > > The act of calling this pre-console panic function is destructive - it > may hang the board and output data to UARTs. Why would it hang? Well, I assume you're talking about hanging before actually emitting the panic text, rather than looping afterwards as a deliberate choice. I'd consider an accidental hang that prevented the message being seen as a bug.
Hi Stephen, On Tue, Mar 20, 2012 at 5:34 PM, Stephen Warren <swarren@wwwdotorg.org> wrote: > On 03/20/2012 05:22 PM, Simon Glass wrote: >> On Tue, Mar 20, 2012 at 3:26 PM, Graeme Russ <graeme.russ@gmail.com> wrote: > ... >>> OK, so what about in panic(): >>> - If gd->have_console is not set: >>> o call the board specific setup_panic_uarts() >>> o call print_pre_console_buffer() passing panic_putc() >>> o call panic_putc() for all characters in str[] >>> - If gd->have_console is set: >>> o call putc() for all characters in str[] >>> >>> setup_panic_uarts() and panic_putc() are overriden in the board files >> >> I think this is where we got to last time. >> >> The act of calling this pre-console panic function is destructive - it >> may hang the board and output data to UARTs. > > Why would it hang? Well, I assume you're talking about hanging before > actually emitting the panic text, rather than looping afterwards as a > deliberate choice. I'd consider an accidental hang that prevented the > message being seen as a bug. No I would hope it would output the data first. I was merely pointing out that the board function may decide to hang rather than return (although I feel it is safe to return since it is being called from panic() anyway). Regards, Simon
Dear Simon Glass, In message <1332188824-5447-2-git-send-email-sjg@chromium.org> you wrote: > This patch adds support for console output in the event of a panic() before > the console is inited. The main purpose of this is to deal with a very early > panic() which would otherwise cause a silent hang. > > A new board_pre_console_panic() function is added to the board API. If > provided by the board it will be called in the event of a panic before the > console is ready. This function should turn on all available UARTs and > output the string (plus a newline) if it possibly can. In addition to the more constructive comments made already by Grame, I object against this patch because I dislike the whole concept. > +- Pre-console panic(): > + Prior to the console being initialised, console output is > + normally silently discarded. This can be annoying if a > + panic() happens in this time. One reason for this might be True. This is the reason why it has always been an important design rule for U-Boot to initialize the console port as soon as possible. > + that you have CONFIG_OF_CONTROL defined but have not > + provided a valid device tree for U-Boot. In general U-Boot's > + console code cannot resolve this problem, since the console > + has not been set up, and it may not be known which UART is > + the console anyway (for example if this information is in > + the device tree). Please make up your mind: either you CAN initialize the console, then you can use it to output messages in a regular way, or you CANNOT initialize it, in which case you cannot print anything. There is no third option. > + The solution is to define a function called > + board_pre_console_panic() for your board, which alerts the > + user however it can. Hopefuly this will involve displaying > + a message on available UARTs, or perhaps at least flashing If you have "available UARTs", you could use this as console, right? In the previous discussion you explained the situation differently - you were talking about _any_ UARTs that might be present on the hardware, without caring about twhat these might actually be used for. I explained that such an approach is highly dangerous. I do not want you toi set a precedent for such stle and code. > + an LED. The function should be very careful to only output > + to UARTs that are known to be unused for peripheral > + interfaces, and change GPIOs that will have no ill effect > + on the board. That said, it is fine to do something > + destructive that will prevent the board from continuing to > + boot, since it isn't going to... Sorry, but this is bogus. Either you know the console port, or you don't. If there is a free UART, it might be attached to custome hardware you have no idea about. Ditto for GPIOs. Please do not meddle with device state in arbitrary ways. If there are LED ports on that board that are intended to signalize status information then it makes sense to use these - but do not use any other ports that might be present on the hardware. > + The function will need to output serial data directly, > + since the console code is not functional yet. Note that if This is broken design. If you can initialize the UART as console, then doi so and use it in the regular way. > + the panic happens early enough, then it is possible that > + board_init_f() (or even arch_cpu_init() on ARM) has not > + been called yet. You should init all clocks, GPIOs, etc. > + that are needed to get the string out. Baud rates will need > + to default to something sensible. Again, this is broken design. We cannot try to catch errors sooner and sooner and soner, and if needed initialization steps have not been executed yet, provide additional code for emergency initialization. We have regular console code, and now we have pre_console_*() stuff, and soon we will have pre_pre_pre_pre_pre_pre_pre_pre_console_*() stuff ? NAK. Just stick to the design principles, and make sure there is as few stuff that could possibly go wrong before console initialization as possible. Than all this crap (excuse me, but I don;t find a better word) will not be needed. I also dislike the modifications to the common code. I think you are trying to solve an unsolvable problem. If you cannot accept that the board gets stuck without printing anything on the debug console port because there are situations when you don't know which port this is, then you simply should _define_ and _document_ a single port as debug console port. Then initialize and use this in the regular way. If later information (like from a loaded device tree) means the console gets switched to anothe rport, that's OK. That's what Linux will do as well if you assign another console port there. Best regards, Wolfgang Denk
Hi Wolfgang, On Wed, Mar 21, 2012 at 2:02 AM, Wolfgang Denk <wd@denx.de> wrote: > Dear Simon Glass, > > In message <1332188824-5447-2-git-send-email-sjg@chromium.org> you wrote: >> This patch adds support for console output in the event of a panic() before >> the console is inited. The main purpose of this is to deal with a very early >> panic() which would otherwise cause a silent hang. >> >> A new board_pre_console_panic() function is added to the board API. If >> provided by the board it will be called in the event of a panic before the >> console is ready. This function should turn on all available UARTs and >> output the string (plus a newline) if it possibly can. > > In addition to the more constructive comments made already by Grame, I > object against this patch because I dislike the whole concept. Well I don't disagree :-) > >> +- Pre-console panic(): >> + Prior to the console being initialised, console output is >> + normally silently discarded. This can be annoying if a >> + panic() happens in this time. One reason for this might be > > True. This is the reason why it has always been an important design > rule for U-Boot to initialize the console port as soon as possible. > >> + that you have CONFIG_OF_CONTROL defined but have not >> + provided a valid device tree for U-Boot. In general U-Boot's >> + console code cannot resolve this problem, since the console >> + has not been set up, and it may not be known which UART is >> + the console anyway (for example if this information is in >> + the device tree). > > Please make up your mind: either you CAN initialize the console, then > you can use it to output messages in a regular way, or you CANNOT > initialize it, in which case you cannot print anything. There is no > third option. Well that is very clear - we cannot. We hit panic() before console_ready() is called. > >> + The solution is to define a function called >> + board_pre_console_panic() for your board, which alerts the >> + user however it can. Hopefuly this will involve displaying >> + a message on available UARTs, or perhaps at least flashing > > If you have "available UARTs", you could use this as console, right? Yes, if we knew which it was. > > In the previous discussion you explained the situation differently - > you were talking about _any_ UARTs that might be present on the > hardware, without caring about twhat these might actually be used for. Yes, basically the only difference with this series is that the board file can control what UARTs are used. > > I explained that such an approach is highly dangerous. I do not want > you toi set a precedent for such stle and code. OK > >> + an LED. The function should be very careful to only output >> + to UARTs that are known to be unused for peripheral >> + interfaces, and change GPIOs that will have no ill effect >> + on the board. That said, it is fine to do something >> + destructive that will prevent the board from continuing to >> + boot, since it isn't going to... > > Sorry, but this is bogus. Either you know the console port, or you > don't. If there is a free UART, it might be attached to custome > hardware you have no idea about. Ditto for GPIOs. Please do not > meddle with device state in arbitrary ways. If there are LED ports on > that board that are intended to signalize status information then it > makes sense to use these - but do not use any other ports that might > be present on the hardware. Yes that is true. The board file should know what is safe, but when we share board files among different hardware variants, we have exactly this problem. > >> + The function will need to output serial data directly, >> + since the console code is not functional yet. Note that if > > This is broken design. If you can initialize the UART as console, > then doi so and use it in the regular way. > >> + the panic happens early enough, then it is possible that >> + board_init_f() (or even arch_cpu_init() on ARM) has not >> + been called yet. You should init all clocks, GPIOs, etc. >> + that are needed to get the string out. Baud rates will need >> + to default to something sensible. > > Again, this is broken design. We cannot try to catch errors sooner > and sooner and soner, and if needed initialization steps have not been > executed yet, provide additional code for emergency initialization. > We have regular console code, and now we have pre_console_*() stuff, > and soon we will have pre_pre_pre_pre_pre_pre_pre_pre_console_*() > stuff ? NAK. > > Just stick to the design principles, and make sure there is as few > stuff that could possibly go wrong before console initialization as > possible. Than all this crap (excuse me, but I don;t find a better > word) will not be needed. Fair enough, and agreed. Thanks for looking at this and providing this info. We know we won't get to console init in this case - there is a panic() that happens first. So the existing pre-console putc() becomes our route to displaying a message. The problem with that is only that the board init hasn't happened yet, so either the pre-console putc() must init the UARTs or we need a separate init function. > > > I also dislike the modifications to the common code. > > > I think you are trying to solve an unsolvable problem. If you cannot > accept that the board gets stuck without printing anything on the > debug console port because there are situations when you don't know > which port this is, then you simply should _define_ and _document_ a > single port as debug console port. Then initialize and use this in > the regular way. If later information (like from a loaded device > tree) means the console gets switched to anothe rport, that's OK. > That's what Linux will do as well if you assign another console port > there. Yes we are certainly trying to solve an unsolvable problem. There are some things that will result in a bricked board and we can't solve all of them. I would be very happy to just accept that. We have the pre-console stuff which boards can use to do their best, and that should be good enough for those that care enough. I actually prefer a pre-console panic to a pre-console putc(), for reasons I went into at length, but no matter, it's not that important. So the existing pre-console putc() can be used, if we can sort out how to make UART init work. Graeme suggested an approach here - I will see if I can make that work. Regards, Simon > > > Best regards, > > Wolfgang Denk > > -- > DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de > Gods don't like people not doing much work. People who aren't busy > all the time might start to _think_. - Terry Pratchett, _Small Gods_
Dear Simon, In message <CAPnjgZ1TBN+Ro8f0nDubAYRi54UAV0LxjrdFz-AW5qBgue1+Fw@mail.gmail.com> you wrote: > > > Please make up your mind: either you CAN initialize the console, then > > you can use it to output messages in a regular way, or you CANNOT > > initialize it, in which case you cannot print anything. There is no > > third option. > > Well that is very clear - we cannot. We hit panic() before > console_ready() is called. OK - but this means that no output to a serial console port can be done, no matter what you try. > > If you have "available UARTs", you could use this as console, right? > > Yes, if we knew which it was. This is a design issue. If there are several similar boards that shall be handled with the same binary, then you must agree on some common sub-set of features, like on UART port that is available on all of these, and use this as (early) console port. > We know we won't get to console init in this case - there is a panic() > that happens first. So the existing pre-console putc() becomes our > route to displaying a message. The problem with that is only that the No. When you cannot initialize the console, you cannot output anything to the console. Period. If there is a way to do some initialization and output charatcers, than make this your regular console init code, and use it always, without any special warts. > board init hasn't happened yet, so either the pre-console putc() must > init the UARTs or we need a separate init function. This makes no sense to me. > So the existing pre-console putc() can be used, if we can sort out how > to make UART init work. Graeme suggested an approach here - I will see > if I can make that work. I don't think I will accept any "pre-console putc()". This is such a dirty hack. Either you can initialize and use putc, then use the normal console mechanism for it, or you cannot. And "cannot" means "cannot" here. Best regards, Wolfgang Denk
Dear Simon, In message <20120321224801.2C000202A4D@gemini.denx.de> I wrote: > > > So the existing pre-console putc() can be used, if we can sort out how > > to make UART init work. Graeme suggested an approach here - I will see > > if I can make that work. > > I don't think I will accept any "pre-console putc()". This is such a > dirty hack. Either you can initialize and use putc, then use the > normal console mechanism for it, or you cannot. And "cannot" means > "cannot" here. Sorry, this was not what I meant. My fingers were faster than my brain. The existing code around CONFIG_PRE_CONSOLE_BUFFER (i. e. storage in a temporary buffer until console bcomes available) is of course OK with me. What I meant was: I do not want to have any "pre console UART output" code. Best regards, Wolfgang Denk
diff --git a/README b/README index 84757a5..38ce52a 100644 --- a/README +++ b/README @@ -638,6 +638,40 @@ The following options need to be configured: 'Sane' compilers will generate smaller code if CONFIG_PRE_CON_BUF_SZ is a power of 2 +- Pre-console panic(): + Prior to the console being initialised, console output is + normally silently discarded. This can be annoying if a + panic() happens in this time. One reason for this might be + that you have CONFIG_OF_CONTROL defined but have not + provided a valid device tree for U-Boot. In general U-Boot's + console code cannot resolve this problem, since the console + has not been set up, and it may not be known which UART is + the console anyway (for example if this information is in + the device tree). + + The solution is to define a function called + board_pre_console_panic() for your board, which alerts the + user however it can. Hopefuly this will involve displaying + a message on available UARTs, or perhaps at least flashing + an LED. The function should be very careful to only output + to UARTs that are known to be unused for peripheral + interfaces, and change GPIOs that will have no ill effect + on the board. That said, it is fine to do something + destructive that will prevent the board from continuing to + boot, since it isn't going to... + + The function will need to output serial data directly, + since the console code is not functional yet. Note that if + the panic happens early enough, then it is possible that + board_init_f() (or even arch_cpu_init() on ARM) has not + been called yet. You should init all clocks, GPIOs, etc. + that are needed to get the string out. Baud rates will need + to default to something sensible. + + If your function returns, then the normal panic processing + will occur (it will either hang or reset depending on + CONFIG_PANIC_HANG). + - Safe printf() functions Define CONFIG_SYS_VSNPRINTF to compile in safe versions of the printf() functions. These are defined in diff --git a/include/common.h b/include/common.h index b588410..9db3a6a 100644 --- a/include/common.h +++ b/include/common.h @@ -285,6 +285,14 @@ extern ulong monitor_flash_len; int mac_read_from_eeprom(void); extern u8 _binary_dt_dtb_start[]; /* embedded device tree blob */ +/* + * Called during a panic() when no console is available. The board should do + * its best to get a message to the user any way it can. This function should + * return if it can, in which case the system will either hang or reset. + * See panic(). + */ +void board_pre_console_panic(const char *str); + /* common/flash.c */ void flash_perror (int); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e38a4b7..a478ff5ab 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -33,6 +33,9 @@ const char hex_asc[] = "0123456789abcdef"; #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] +DECLARE_GLOBAL_DATA_PTR; + + static inline char *pack_hex_byte(char *buf, u8 byte) { *buf++ = hex_asc_hi(byte); @@ -777,13 +780,31 @@ int sprintf(char * buf, const char *fmt, ...) return i; } +/* Provide a default function for when no console is available */ +static void __board_pre_console_panic(const char *msg) +{ + /* Just return since we can't access the console */ +} + +void board_pre_console_panic(const char *msg) __attribute__((weak, + alias("__board_pre_console_panic"))); + void panic(const char *fmt, ...) { + char str[CONFIG_SYS_PBSIZE]; va_list args; + va_start(args, fmt); - vprintf(fmt, args); - putc('\n'); + vsnprintf(str, sizeof(str), fmt, args); va_end(args); + + if (gd->have_console) { + puts(str); + putc('\n'); + } else { + board_pre_console_panic(str); + } + #if defined (CONFIG_PANIC_HANG) hang(); #else
This patch adds support for console output in the event of a panic() before the console is inited. The main purpose of this is to deal with a very early panic() which would otherwise cause a silent hang. A new board_pre_console_panic() function is added to the board API. If provided by the board it will be called in the event of a panic before the console is ready. This function should turn on all available UARTs and output the string (plus a newline) if it possibly can. Signed-off-by: Simon Glass <sjg@chromium.org> --- README | 34 ++++++++++++++++++++++++++++++++++ include/common.h | 8 ++++++++ lib/vsprintf.c | 25 +++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-)