Re: [DOC] Debugging early kernel hangs

From: Martin J. Bligh (mbligh@us.ibm.com)
Date: Thu Sep 28 2000 - 12:20:55 EST


> If a kernel hangs early in the boot process (before the console has
> been initialized) then printk is no use because you never see the
> output. There is a technique for using the video display to indicate
> boot progress so you can localize the problem. Reporting "my kernel
> hangs during boot at line nnn in routine xyz" is a lot better than "my
> kernel hangs during boot".

I was doing some similar debug work, and stole some code from the
early boot decompress stuff, and munged it. It's a nasty hack that only
works on x86 (probably), and hardcodes video addresses, etc. But you
might find it useful to print out addresses, etc with.

There are routines to print things, scroll the screen, clear the screen,
and spin for a specified number of seconds (so that you can actually
read the output ;-) )

Martin.

/* Martin J. Bligh <mbligh@us.ibm.com> */

#define VIDMEMBUF 0xB800

int orig_x = 0;
int orig_y = 0;
int vidport = 0x3d4;

void early_scroll(void)
{
        int i, cols = 80, lines = 25;
        unsigned char *vidmem = phys_to_virt(VIDMEMBUF);

        memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
        for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
                vidmem[i] = ' ';
}

void clearvidmem(void)
{
        int x, y, pos = 0;
        unsigned char *vidmem = phys_to_virt(VIDMEMBUF);

        for (x = 0; x < 80; x++) {
                for (y = 0; y < 25; y++) {
                        vidmem [ ( x + 80 * y ) * 2 ] = ' ';
                }
        }
        orig_x = 0;
        orig_y = 0;

        /* Update cursor position */
        outb_p(14, vidport);
        outb_p(0xff & (pos >> 9), vidport+1);
        outb_p(15, vidport);
        outb_p(0xff & (pos >> 1), vidport+1);
}

void pokevidmem(int x, int y, char c)
{
        unsigned char *vidmem = phys_to_virt(VIDMEMBUF);

        vidmem [ ( x + 80 * y ) * 2 ] = c;
}

void spin_on_me(int howlong)
{
        int i, j;

        for (i=0; i<howlong; ++i)
                for (j=0; j<10000; ++j) /* spin 1 sec */
                        udelay(100);
}

void early_puts(const char *s)
{
        int x,y,pos, cols = 80, lines = 25;
        char c;

        x = orig_x;
        y = orig_y;

        while ( ( c = *s++ ) != '\0' ) {
                if ( c == '\n' ) {
                        x = 0;
                        if ( ++y >= lines ) {
                                early_scroll();
                                y--;
                        }
                } else {
                        pokevidmem (x, y, c);
                        if ( ++x >= cols ) {
                                x = 0;
                                if ( ++y >= lines ) {
                                        early_scroll();
                                        y--;
                                }
                        }
                }
        }

        orig_x = x;
        orig_y = y;

        pos = (x + cols * y) * 2; /* Update cursor position */
        outb_p(14, vidport);
        outb_p(0xff & (pos >> 9), vidport+1);
        outb_p(15, vidport);
        outb_p(0xff & (pos >> 1), vidport+1);
}

void early_printk(const char *fmt, ...)
{
        va_list args;
        int i;
        char buf[1024];

        va_start(args, fmt);
        i = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf)-4 */
        va_end(args);
        early_puts(buf);
        printk(buf);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 30 2000 - 21:00:22 EST