3.1. Debugging with print_str()

As stated in the previous chapter, the machine starts to boot, but nothing happens. At least, nothing that we can see. The screen is blank and no kernel messages appear. At this point, you have to ask yourself, is it really booting?

Since the console wouldn't start, and ICE died real fast, we had no choice. We had to debug somehow, and the oldest way is good here - printing to the screen. Obviously, we couldn't use printk(), so we wrote a short function which pushes characters straight into the serial port. We used the boot process "map" shown in the previous section, and inserted some prints along the way. This helped us to know at what stage we are completing and where we're dying. The following piece of code prints a single character to the serial port, by polling it and waiting for it to be free.

                                 /* tx holding reg empty or tx    */
#define LSR_THREMPTY 0x20        /* fifo is empty (in fifo mode ) */
#define THR_REG      0x00        /* Transmit holding reg */
#define LSR_REG      0x05        /* Line status reg */
#define COM1_ADDRESS 0xFF600300  /* == replace with your UART address */

void print_char (char ch) {
	volatile  unsigned char status = 0;
	/* wait until txempty */
	while ((status & LSR_THREMPTY ) == 0)
		status = *((volatile unsigned char *)(COM1_ADDRESS + LSR_REG));

	*((volatile unsigned char *)(COM1_ADDRESS + THR_REG)) = ch;
}

Note

There's a better code for printing directly to the serial port, however, it's a bit more complicated. You can find it in arch/ppc/boot/common/misc-common.c, using puts() or putc().