WVB Operating System(Third Stage)
Welcome back to the Operating system article series. In the last articles, I have discussed how to jump into C language in order to grow up the further implementation of OS. At the end of the last article, We were able to call the simple C function using the “loader.s” file. Along with that, In this article, we are going to play with the input and the outputs of the operating system.
The main two implementations that we discuss in this article would be,
1.Display text on the console
This part creates a driver for the “frame buffer” to be able to display text on the console.
2.Writing data to the serial port
This part shows how to create a driver for the serial port.
When we are going to handle the inputs and outputs, We have to directly interact with the Hardware. Memory-mapped I/O and I/O ports are the two most common ways to interact with hardware. If the hardware uses memory-mapped I/O then you can write to a specific memory address and the hardware will be updated with the new data. If the hardware uses I/O ports then the assembly code instructions “out” and “in” must be used to communicate with the hardware.
1. Display text on the console
The frame buffer is a hardware device that is capable of displaying a buffer of memory on the screen. Writing text to the console via the frame buffer is done with memory-mapped I/O. The starting address of the memory-mapped I/O for the framebuffer is
0x000B8000.The memory is divided into 16-bit cells, with the 16 bits determining the character as well as the foreground and background colors.
Bit: | 15 14 13 12 11 10 9 8 | 7 6 5 4 | 3 2 1 0 |
Content: | ASCII | FG | BG |
Therefore, As an example, in order to write the character ‘A; with a green foreground (2) and dark grey background (8) at the place (0,0), the following assembly code instruction is used.
mov [0x000B8000], 0x4128
The available colors are shown below.
Writing to the framebuffer can also be done in C by treating the address
0x000B8000 as a char pointer,
char *fb = (char *) 0x000B8000.
The following code shows how this can be wrapped into a function and can be used in C code like below.
Moving the Cursor
Moving the cursor of the frame buffer is done via two different I/O ports. The frame buffer has two I/O ports, one for accepting the data, and one for describing the data being received. By storing this function in a file called
io.s Assembly file and also creating a header
io.h,C file, the
out assembly code instruction can be conveniently accessed from C.
Then, Moving the cursor can now be wrapped in a C function like this and it can be called using “kmain. C”. As well as we need to update Makefile by including “io. o” in the Object section.
For further usage, We do not save all the C functions in the “kmain.C” file . we create a “frame_buffer.h” file in order to include all the above C functions like below.
2. Writing data to the serial port
The serial port is an interface for communicating between hardware devices and although it is available on almost all motherboards. The serial ports are completely controlled via I/O ports. In order to write the data into serial ports, we need to create a “serial_port.h” file like below.
Then we need to Update the “io.s” Assembly code file from the below code.
Next, we have to Update the “io. h” file using the below code.
Then We can call the serial_write function from the “ kmain.c” by including the “serial_port” header. In order to get the result of serial port writing, we have to update the “bochsrc.txt” file using the below code.
com1: enabled=1, mode=file, dev=com1.out
As a Final result, the “com1.out” file will be created and the output from the serial port would be stored in that file.