Hi,
shervingav wrote:I am new to OS development and I don't know the best way to print output.
please help me out....
I typically have a "big string in RAM" as a log. Several functions (appendString, appendDecDword, appendHexDword, etc) just append characters to the big string; and there's a "flushLog" function that displays the log.
Initially during boot, the boot loader just uses firmware to display strings (either "int 0x10" for boot loaders designed for BIOS, or "EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL" for boot loaders designed for UEFI). Then boot loader sets up the log and appends any characters it already displayed onto it (so that the log contains everything, all the way back to the first things the first piece of code displayed). Boot loader starts another stage I call the "Boot Abstraction Layer" (BAL).
The BAL has an API and manages the log. Its "flushLog" function uses callbacks. When BAL is first started, the boot loader provides a callback that the "flushLog" function uses (so "flushLog" calls the boot loader, which uses either "int 0x10" or UEFI). Eventually (after video is setup properly, etc) the BAL loads "text output" modules which install their own callbacks and the boot loader's callback is removed. This allows me to have several modules for text output (one for sending output to a serial port, one for handling graphics mode frame-buffers, etc) where you can have none or more of these modules at the same time.
The "text output" modules initially talk directly to hardware. The BAL starts the kernel, and the kernel takes over management of the log. The "text output" modules become processes, and the callbacks end up being messages sent from kernel to these processes whenever the "flushLog" kernel API function is called. When appropriate driver/s are started the "text output" module/s stop talking to hardware directly and switch to using the device driver (and their permission to talk to hardware is revoked). Finally, when the OS is "ready" (all necessary device drivers, services, etc running) the log is written to a file; and any "text output" module/s are notified. It's up to them what they do after that (most "text output" modules would terminate themselves, but they could just keep running like a normal application if they want).
Of course what a "text output" module does depends on the "text output" module. For something that does serial port output, it might monitor the serial ports' "RTS" line (to detect if/when a dumb terminal is plugged in); and keep its own "pointer to last character in log sent" so that when characters are appended to the log it only sends the new characters. For something like video display, you might keep track of a "pointer to the previous line at the top of the screen", scan the log and advance the "top of screen" pointer if necessary; then put the characters from the last N lines of the log into a text buffer, convert data in the text buffer (using a built in font renderer) into pixels, then blit the pixel data to the video card's frame-buffer.
In the same way, you could have "text output" module that drives a Braille display, or uses the PC speaker or sound card (Morse code beeps? Speech synthesizer?), or sends it over a network (telnet?), or controls a flashing infra-red LED, or sends it to a printer, etc. You could even have a module that doesn't display it at all, but just sits there waiting until the OS is "ready" (and then maybe sends the log as an email to someone).
Cheers,
Brendan