Build Your Own OS #3

Interacting with the Hardware

The Frame buffer

0x000B8000 + 16 = 0x000B8010
fb[0] = 'A';
fb[1] = 0x28;
#ifndef INCLUDE_IO_H
#define INCLUDE_IO_H
/** outb:
* Sends the given data to the given I/O port. Defined in io.s
*
* @param port The I/O port to send the data to
* @param data The data to send to the I/O port
*/
void outb(unsigned short port, unsigned char data);
/* in file io.h *//** inb:
* Read a byte from an I/O port.
*
* @param port The address of the I/O port
* @return The read byte
*/
unsigned char inb(unsigned short port);
#endif /* INCLUDE_IO_H */
#ifndef INCLUDE_FB_H
#define INCLUDE_FB_H
#include “io.h”/* The I/O ports */
#define FB_COMMAND_PORT 0x3D4
#define FB_DATA_PORT 0x3D5
/* The I/O port commands */
#define FB_HIGH_BYTE_COMMAND 14
#define FB_LOW_BYTE_COMMAND 15
#define FB_GREEN 2
#define FB_DARK_GREY 8
char *fb = (char *) 0x00B8000;/** fb_write_cell:
* Writes a character with the given foreground and background to position i
* in the framebuffer.
*
* @param i The location in the framebuffer
* @param c The character
* @param fg The foreground color
* @param bg The background color
*/
void fb_write_cell(unsigned int i, char c, unsigned char fg, unsigned char bg)
{
fb[i*2] = c;
fb[i*2 + 1] = ((fg & 0x0F) << 4) | (bg & 0x0F);
}
/** fb_move_cursor:
* Moves the cursor of the framebuffer to the given position
*
* @param pos The new position of the cursor
*/
void fb_move_cursor(unsigned short pos)
{
outb(FB_COMMAND_PORT, FB_HIGH_BYTE_COMMAND);
outb(FB_DATA_PORT, ((pos >> 8) & 0x00FF));
outb(FB_COMMAND_PORT, FB_LOW_BYTE_COMMAND);
outb(FB_DATA_PORT, pos & 0x00FF);
}
int write(char *buf, unsigned int len)
{
unsigned int i = 0;
for ( i = 0; i < len; i++)
{
fb_write_cell(i, buf[i], FB_GREEN, FB_DARK_GREY);
}
return 0;
}
#endif

The Serial Ports

Configuring the Serial Port

  • The speed used for sending data (bit or baud rate)
  • If any error checking should be used for the data (parity bit, stop bits)
  • The number of bits that represent a unit of data (data bits)

Configuring the Line

#ifndef INCLUDE_SERIAL_PORT_H
#define INCLUDE_SERIAL_PORT_H
#include “io.h” /* io.h is implement in the section “Moving the cursor” *//* The I/O port com1: enabled=1, mode=file, dev=com1.outs */
/* All the I/O ports are calculated relative to the data port. This is because
* all serial ports (COM1, COM2, COM3, COM4) have their ports in the same
* order, but they start at different values.
*/
#define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */#define SERIAL_DATA_PORT(base) (base)
#define SERIAL_FIFO_COMMAND_PORT(base) (base + 2)
#define SERIAL_LINE_COMMAND_PORT(base) (base + 3)
#define SERIAL_MODEM_COMMAND_PORT(base) (base + 4)
#define SERIAL_LINE_STATUS_PORT(base) (base + 5)
/* The I/O port commands *//* SERIAL_LINE_ENABLE_DLAB:
* Tells the serial port to expect first the highest 8 bits on the data port,
* then the lowest 8 bits will follow
*/
#define SERIAL_LINE_ENABLE_DLAB 0x80
void serial_configure_baud_rate(unsigned short com, unsigned short divisor) {
/* Tell the serial port to first expect the highest 8 bits, then the lowest
* 8 bits. This is done by sending 0x80 to the line command port
*/
outb(SERIAL_LINE_COMMAND_PORT(com), SERIAL_LINE_ENABLE_DLAB);
outb(SERIAL_DATA_PORT(com), (divisor >> 8) & 0x00FF);
outb(SERIAL_DATA_PORT(com), divisor & 0x00FF);
}
void serial_configure_line(unsigned short com) {
/* Bit: | 7 | 6 | 5 4 3 | 2 | 1 0 |
* Content: | d | b | prty | s | dl |
* Value: | 0 | 0 | 0 0 0 | 0 | 1 1 | = 0x03
* data length of 8 bits, one stop bit, no parity bit, break control
* disabled and DLAB disabled
*/
outb(SERIAL_LINE_COMMAND_PORT(com), 0x03);
}
void serial_configure_fifo_buffer(unsigned short com) {
/* Bit: | 7 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* Content: | lvl | bs | r | dma | clt | clr | e |
* Value: | 1 1 | 0 | 0 | 0 | 1 | 1 | 1 | = 0xC7
*/
outb(SERIAL_FIFO_COMMAND_PORT(com), 0xC7);
}
void serial_configure_modem(unsigned short com) {
/* Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* Content: | r | r | af | lb | ao2 | ao1 | rts | dtr |
* Value: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | = 0x03
*/
outb(SERIAL_MODEM_COMMAND_PORT(com), 0x03);
}
int serial_is_transmit_fifo_empty(unsigned short com) {
/* 0x20 = 0010 0000 */
return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20;
}
void serial_configure(unsigned short port, unsigned short baudRate) {
serial_configure_baud_rate(port, baudRate);
serial_configure_line(port);
serial_configure_fifo_buffer(port);
serial_configure_modem(port);
}
void serial_write_byte(unsigned short port, char byteData) {
outb(port, byteData);
}
int serial_write(unsigned short com, char *buf, unsigned int len) {
unsigned int indexToBuffer = 0;
while (indexToBuffer < len) {
if (serial_is_transmit_fifo_empty(com)) {
serial_write_byte(com, buf[indexToBuffer]);
indexToBuffer++;
}
}
return 0;
}
#endif
global outb ; make the label outb visible outside this file; outb — send a byte to an I/O port
; stack: [esp + 8] the data byte
; [esp + 4] the I/O port
; [esp ] return address
outb:
mov al, [esp + 8] ; move the data to be sent into the al register
mov dx, [esp + 4] ; move the address of the I/O port into the dx register
out dx, al ; send the data to the I/O port
ret ; return to the calling function
global inb; inb — returns a byte from the given I/O port
; stack: [esp + 4] The address of the I/O port
; [esp ] The return address
inb:
mov dx, [esp + 4] ; move the address of the I/O port to the dx register
in al, dx ; read a byte from the I/O port and store it in the al register
ret ; return the read byte
#include “io.h”
#include “fb.h”
#include “serial_port.h”
void run(){
char c[] = “Welcome”;
write(c, 9);
serial_write(SERIAL_COM1_BASE, c, 7);
}
global loader ; the entry symbol for ELFMAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant
FLAGS equ 0x0 ; multiboot flags
CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum
; (magic number + checksum + flags should equal 0)
KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes
section .bss
align 4 ; align at 4 bytes
kernel_stack: ; label points to beginning of memory
resb KERNEL_STACK_SIZE ; reserve stack for the kernel
section .text: ; start of the text (code) section
align 4 ; the code must be 4 byte aligned
dd MAGIC_NUMBER ; write the magic number to the machine code,
dd FLAGS ; the flags,
dd CHECKSUM ; and the checksum
loader: ; the loader label (defined as entry point in linker script)
mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax
mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the
; stack (end of memory area)
; Calling C code
extern run
call run
.loop:
jmp .loop ; loop forever
OBJECTS = loader.o kmain.o io.o
CC = gcc
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
-nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c
LDFLAGS = -T link.ld -m elf_i386
AS = nasm
ASFLAGS = -f elf
all: kernel.elfkernel.elf: $(OBJECTS)
ld $(LDFLAGS) $(OBJECTS) -o kernel.elf
baseOS.iso: kernel.elf
cp kernel.elf iso/boot/kernel.elf
genisoimage -R \
-b boot/grub/stage2_eltorito \
-no-emul-boot \
-boot-load-size 4 \
-A os \
-input-charset utf8 \
-quiet \
-boot-info-table \
-o baseOS.iso \
iso
run: baseOS.iso
bochs -f bochsrc.txt -q
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
%.o: %.s
$(AS) $(ASFLAGS) $< -o $@
clean:
rm -rf *.o kernel.elf baseOS.iso
megs: 32
display_library: sdl
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=baseOS.iso, status=inserted
boot: cdrom
log: bochslog.txt
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000
com1: enabled=1, mode=file, dev=com1.out

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

AWS Lambda and SQS: What Nobody Tells You About Their Mix!

Developing serverless event-driven solutions using AWS Lambda and SQS

SQLServer Docker Development Environment on M1 MacOS

Save time, make a Garageband🎸 Template for your podcast recordings ✨how-to guide✨

CSS Custom Properties are here.

One Platform. Full-stack. Full-Lifecycle.

DreamMaker Metaverse Update III:  Avatar 3D yang mengikat tulang

Zoom SDK; leave meeting when tab is closed.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Niroshan Pushparaj

Niroshan Pushparaj

More from Medium

How to get Deep Sleep

How to import mySQL database from cPanel to Amazon RDS

Week of 24 Jan — 30 Jan

Nessus Basics Tutorial: Vulnerability Management