Friday, 2 November 2018

Memory Layout

In our previous example we have seen that, MBR (Master Boot Record or first sector) is loaded at the memory location 0x7C00. To understand the reason behind loading MBR at 0x7C00 we need to understand the memory layout of the x86 architecture.

Minimum requirement for DOS version 1.0 was 32KB (0x0000 to 0x7FFF). when we subtract 1KB (1024 bytes) from 32KB we will ge the value 0x7C00. Even though the length of MBR is 512 bytes, the reason for keeping 1024 bytes for MBR is to have extra memory for Stack/Data area of MBR. For more details on memory location 0x7C00 please check the link: https://www.glamenv-septzen.net/en/view/6

Now let us understand the memory architecture after boot.

Early version of x86 has the memory architecture was like below:



In the modern system memory architecture has little modification. As many peripherals are added and more memory is available, the memory architecture will look like below:



0xXXXXXX is the last memory address in a given microprocessor. It depends on the size of the memory in any given microprocessor.

An example demonstrating the initial address of the Boot Sector can be found here: https://github.com/bvbasavaraju/os_dev/blob/dev/src/boot_sector/3_boot_sector_memory.asm

In the modern CPUs just to make sure that MBR is loaded in the correct memory location 0x7C00, developer can make use of the Assembly Keyword "org" in the beginning of the Boot Sector program like below:
[org 0x7C00]

Note: Try to add the [org 0x7C00] at the beginning of the program and check the difference in output.

Saturday, 29 September 2018

Understanding BIOS with interrupt

In the previous post we had seen how to create a simple boot sector or boot block. Boot sector or Boot loader is essential for any operating system to load. It is the boot loader or boot sector which loads the operating system kernel and operating system essentials before giving control to the operating system.

It is the BIOS which will look for boot sector or boot loader of length 512 bytes in floppy disc or hard drive or CD/DVD or pen drive. From the previous post we know that, BIOS will identify the boot block of boot sector with the key word 0xaa55 as the end of 512 bytes. Now let us understand BIOS and just use the BIOS to play around by displaying some information on the screen.

BIOS (basic input/output system) is the is a piece of software which is implemented by the motherboard manufacturer to detect hardware connected to the motherboard and do some basic tests to check if the hardware connected is working as intended. When the simple tests for hardware failed or hardware not detected, BIOS will print the ERROR or WARNING information before proceeding with booting operating system. Error like "KEYBOARD NOT DETECTED" etc. Which means, BIOS has already detected hardware, after this BIOS will look for the boot loader or boot sector to load the operating system. Before writing actual boot loader to load operating system kernel etc, to understand the BIOS in depth, we can make use of some of the BIOS functionality. Displaying something on the screen is easiest thing to recognise that our code written in boot loader is working.

So, here I am planning to write word "HELLO" on screen using boot loader and BIOS. To do that we need to know how BIOS can help us to display word "HELLO" on the screen. As we are sure that BIOS has already detected display driver (as it displayed some information on the screen), BIOS can help us in displaying the word "HELLO" on screen.

BIOS uses the interrupt calls to do certain things. These interrupts can also be used by operating system for certain things using kernel. The BIOS interrupt calls details can be found in the link: https://en.wikipedia.org/wiki/BIOS_interrupt_call. As we are trying to print word "HELLO" on the screen, our interest is in "Video Service" related interrupt call (0x10), and we want use the Display driver in TTY/TeleType mode (print a character on screen and move the cursor to the next position). Interrupt can be triggered using assembly instruction INT. For Video service, we have to use INT 0x10. To use the INT 0x10 in TTY mode, the ah register should be assigned with value "0x0e". Now we need to know how to print each letter from word "HELLO" on the screen.

In x86 family there are CPU registers which will be used for many purposes. Some of the General purpose registers are AX, BX, CX and DX. Each of these are 16 bit registers. These 16 bit registers can be accessed in byte format like for ex: ah - higher byte of AX register and al - lower byte of AX register. These registers can be used in Real Mode which can be used by BIOS (Note: Before loading the Kernel BIOS will switch to Protected Mode. Click here to know the details or Real Mode and Protected Mode). There are 32 bit and 64 bit registers as well. For more details on x86 CPU registers follow this link: https://en.wikibooks.org/wiki/X86_Assembly/16_32_and_64_Bits.

We have seen above that, to use display in TTY mode using interrupt call, we have to assign "0x0e" in ah register (Higher byte of AX register). The video service interrupt (INT 0x10) works is, it will look for the mode in ah register, if it is a TTY mode (0x0e) it will print the value in al register when interrupt has be called. So to print the word "HELLO", we have to load ah register with value 0x0e, and we have load letter by letter to al register and call interrupt using assembly instruction INT 0x10h.

So, assembly code to print word "HELLO" is (actual assembly file can be found here):

mov ah, 0x0e  ;    Teletype (TTY) mode.
mov al, 'H'       ;    letter 'H'
int 0x10           ;    Raise the interrupt
mov al, 'E'
int 0x10
mov al, 'L'
int 0x10
int 0x10          ;    here the register 'al' already has the value 'L'
mov al, 'O'
int 0x10

loop:
      jmp loop

times 510-($-$$) db 0
dw 0xaa55

The hex dump of the above assembly code is:
00000000  b4 0e b0 48 cd 10 b0 45  cd 10 b0 4c cd 10 cd 10      |...H...E...L....|
00000010  b0 4f cd 10 eb fe 00 00  00 00 00 00 00 00 00 00      |.O..............|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    |................|
*                                (appended with 0's)
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa     |..............U.|

Screen shot of HELLO message on screen is:


Sunday, 9 September 2018

Boot Sector or First Boot Block!


Operating System is just a software which has to be loaded on the hardware. This Software will be loaded with the help of BIOS (Basic Input/Output Software). When hardware starts BIOS kicks in initialises and tests critical hardware components like keyboard, memory etc. and look for the boot sector (typically it is located in Cylinder 0, Head 0, Sector 0 - It is the way to address the memory). As there could be multiple sectors, there should be a way to identify a sector which is a boot sector. BIOS will identify any sector as a boot sector when it finds the magic number (0xaa55) at the end of sector.
Note: Size of a sector is 512 bytes.

After finding boot sector, BIOS will load boot sector which intern loads the operating system. This boot sector should have never ending loop otherwise soon after loading the sector hardware will shut down. Operating System is a never ending software unless triggered with Shutdown and/or Restart option.

There are 2 ways to write boot block.
+ Hex bytes using Hex/binary file editor. - writing actual machine code instructions (this is CPU specific)
+ Assembly code and building it into binary.

To write 512 bytes using any editor is not an easy task. We should know how to keep never ending loop for any given hardware architecture and we should have exact 512 bytes in length. So here I have opted for writing the Assembly code. Below boot_block.asm is the file which contains the assembly code.

boot_block.asm:
;never ending loop
loop:
      jmp loop
; padding with 0's
times 510-($-$$) db 0
; MAGIC_NUMBER , to indicate this sector is boot sector
dw 0xaa55
Note: except never ending loop and MAGIC_NUMBER (0xaa55), everything else is padded with 0's

This can be compiled to binary with the help of nasm assembler tool using
nasm boot_block.asm -f bin -o <output_file_name>.bin

When we print the <output_file_name>.bin using
od -t x1 -A n <output_file_name>.bin or using hexdump using hexdump -C <output_file_name>.bin it will look like,

 eb fe 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa

we can notice the MAGIC_NUMBER is stored as 55 aa. This is because Intel x86 is BigEndian architecture. Most Significant Byte (MSB) will be stored last in the memory (0xaa55, 0xaa will be stored last)
0xeb 0xfe ==> are the machine code instructions to perform the infinite/never ending loop. This is defined by CPU manufacturer.

Written boot sector can be tested in multiple ways
+ using Virtual box - Writing/Flashing <output_file_name>.bin to CD-Drive/USB/Floppy Disk/Hard disk image
+ using qemu - Qick Emulator

For now I have used qemu with the help of following command:
qemu-system-x86_64 <output_file_name>.bin

Our boot sector is loaded by BIOS of specified architecture in the command (x86_64) and it will look like below:

Loading boot block using qemu


It says, "Booting from Hard Disk..." but, for now there is nothing to boot from hard disk.
As we progress we can add stuffs here to load our operating system!

Next - Printing something by writing some stuffs in Boot sector.

Before it begins!

Before it begins, I would like you to know how it all started and what is the purpose of this!

I am an Engineer from more than 10 years now. As an Engineer, by nature I tend to solve the problem(s) or create some technology for betterment of society or nature. To do so, Engineers should know many concepts before doing anything. Ex, Teachers cannot teach in school/college without the knowledge of chapter they are teaching! In simple terms they should understand what they are dealing with. An Engineer should know many things depending on type of work.

As an Embedded developer (an Engineer who will write a software(s) to make hardware/chip/controller/processor communicating with other hardware/chip/controller/processor), I should know type of hardware I am dealing with, what software already present in that (like, OS/RTOS if any), how it will work, how it should work, etc...

As its is more than 10 years now, I have good understanding of the Operating System. In my personal opinion and experience, theoretical knowledge and practical knowledge are 2 different things. And I believe in the "Reinventing Wheel" to have better understanding of anything! From business point of view it has no value add. From individual point of view it is a great value add. So, Engineers should put extra effort outside office hours to learn anything! now you know why Engineers has to spend more time related to work!

Purpose: "Reinventing Wheel" in this case "re-writing operating system" is to deepen my understanding.

There is no hidden work going on here. I am starting this as an hobby, not sure where it goes. I know it is not an easy task and cannot be completed in few days/months. It will be one of the longest running hobby project that I ever worked on or will work on! Not sure who long I can keep up. I will try my best for sure.

Interested people can check out my actual development work in here: https://github.com/bvbasavaraju/os_dev
If anyone would like to contribute, please feel free to mail me first. With that we can decide on which module one can take up or work on!
If you find a bug in my work please feel free to log the same.

Programming Language(s):
+ C/C++ and Assembly
To write an Operating System one should know C/C++ and assembly language depending on the language opted for writing an Operating System. Reason for using C/C++ is, these are close to low level programming and easy to understand. Assembly is much better, but not easy to understand. So, I have opted for C/C++ programming language. Some places assembly language is a unavoidable. From my experience I am relatively good at these programming languages.

Architecture:
+ Intel x86 architecture - this operating system will be written for Intel x86 Architecture.

Tools:
+ ubuntu 18.04 - Host operating system in which operating system is developed
+ nasm - Netwide Assembler for Intel x86 Architecture.
+ qemu - Quick Emulator for emulating processor (similar to Virtual Box or VMWare). It is used for testing operating system. I Will move to virtual box in future.

References (Many would be listed as and when I refer the same):
+ http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
+ https://github.com/cfenollosa/os-tutorial
+ https://wiki.osdev.org/Main_Page

Let's get started!...