old-www/LDP/LG/issue77/krishnakumar.html

311 lines
14 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Writing Your Own Toy OS (Part I) LG #77</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<CENTER>
<A HREF="http://www.linuxgazette.com/">
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
WIDTH="600" HEIGHT="124" border="0"></A>
<BR>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="kollar.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue77/krishnakumar.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lechnyr.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<P>
</CENTER>
<!--endcut ============================================================-->
<H4 ALIGN="center">
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">Writing Your Own Toy OS (Part I)</font></H1>
<H4>By <a href="mailto:krishnakumar_r@bharatmail.com">Krishnakumar R.</a></H4>
</center>
<P> <HR> <P>
<!-- END header -->
<EM> This article is a hands-on tutorial for building a small boot
sector. The first section provides the theory behind what happens at the
time the computer is switched on. It also explains our plan. The second
section tells all the things you should have on hand before proceeding
further, and the third section deals with the programs. Our little startup
program won't actually boot Linux, but it will display something on the screen.</EM>
<HR>
<H2><A NAME="s1">1. Background</A></H2>
<H2>1.1 The Fancy Dress</H2>
<P>The microprocessor controls the computer. At startup, every
microprocessor is just another 8086. Even though you may have a brand
new Pentium, it will only have the capabilities of an 8086. From this
point, we can use some software and switch processor to the infamous
<EM>protected mode </EM>. Only then can we utilize the processor's full power.
<H2>1.2 Our Role</H2>
<P>Initially, control is in the hands of the <EM>BIOS</EM>. This is
nothing but a collection of programs that are stored in ROM. BIOS
performs the <EM>POST</EM> (Power On Self Test). This checks the
integrity of the computer (whether the peripherals are working properly,
whether the keyboard is connected, etc.). This is when you hear those beeps
from the computer. If everything is okay, BIOS selects a boot device. It
copies the first sector (boot sector) from the device,
to address location <EM>0x7C00</EM>. The control is then transferred
to this location. The boot device may be a floppy disk, CD-ROM, hard
disk or some device of your choice. Here we will take the boot device to be
a floppy disk. If we had written some code into the boot sector of the
floppy, our code would be executed now. Our role is clear: just write
some programs to the boot sector of the floppy.
<H2>1.3 The Plan</H2>
<P>First write a small program in 8086 assembly (don't be frightened;
I will teach you how to write it), and copy it to the boot sector of the
floppy. To copy, we will code a C program. Boot the computer with that
floppy, and then enjoy.
<P>
<H2><A NAME="s2">2. Things You Should Have</A></H2>
<P>
<DL>
<DT><B>as86</B><DD><P>This is an assembler. The assembly code we write
is converted to an object file by this tool.
<DT><B>ld86</B><DD><P>This is the linker. The object code generated by
as86 is converted to actual machine language code by this tool. Machine
language will be in a form that 8086 understands.
<DT><B>gcc</B><DD><P>The C compiler. For now we need to write a C program to transfer our OS to the floppy.
<DT><B>A free floppy</B><DD><P>A floppy will be used to store our
operating system. This also is our boot device.
<DT><B>Good Old Linux box</B><DD><P>You know what this is for.
</DL>
as86 and ld86 will be in most of the standard distributions. If not, you
can always get them from the site
<A
HREF="http://www.cix.co.uk/~mayday/">http://www.cix.co.uk/~mayday/</A>.
Both of them are included in single package, bin86. Good documentation is available at
<A HREF="http://www.linux.org/docs/ldp/howto/Assembly-HOWTO/as86.html">www.linux.org/docs/ldp/howto/Assembly-HOWTO/as86.html</A>.
<H2><A NAME="s3">3. 1, 2, 3, Start!</A></H2>
<H2>3.1 The Boot Sector </H2>
<P>Grab your favourite editor and type in these few lines.
<BLOCKQUOTE><CODE>
<PRE>
entry start
start:
mov ax,#0xb800
mov es,ax
seg es
mov [0],#0x41
seg es
mov [1],#0x1f
loop1: jmp loop1
</PRE>
</CODE></BLOCKQUOTE>
<P>This is an assembly language that as86 will understand. The first
statement specifies the entry point where the control should enter
the program. We are stating that control should initially go to label
<EM><CODE>start</CODE></EM>. The 2nd line depicts the location of the label
<EM><CODE>start</CODE></EM> (don't forget to put ":" after the start). The
first statement that will be executed in this program is the
statement just after <EM>start</EM>.
<P>0xb800 is the address of the video memory. The # is for representing
an immediate value. After the execution of
<BLOCKQUOTE><CODE>
<PRE>
mov ax,#0xb800
</PRE>
</CODE></BLOCKQUOTE>
register ax will contain the value 0xb800, that is, the address of the
video memory.
Now we move this value to the <EM><CODE>es</CODE></EM>
register. <EM><CODE>es</CODE></EM> stands for the extra segment
register. Remember that 8086 has a segmented architecture. It has segments
like code segments, data segments, extra segments, etc.--hence the segment
registers cs, ds, es. Actually, we have made the video memory our extra
segment, so anything written to extra segment would go to video memory.
<P>To display any character on the screen, you need to write two bytes
to the video memory. The first is the ascii value you are going to
display. The second is the attribute of the character. Attribute has
to do with which colour should be used as the foreground, which for the
background, should the char blink and so on. <EM><CODE>seg es</CODE></EM>
is actually a prefix that tells which instruction is to be executed next with
reference to <EM><CODE>es</CODE></EM> segment. So, we move value 0x41,
which is the ascii value of character A, into the first byte of the
video memory. Next we need to move the attribute of the character to
the next byte. Here we enter 0x1f, which is the value for representing a white
character on a blue background. So if we execute this program, we get a
white A on a blue background. Finally, there is the loop. We need to stop the
execution after the display of the character, or we have a loop that
loops forever. Save the file as <EM><CODE>boot.s</CODE></EM>.
<P>The idea of video memory may not be very clear, so let me explain
further. Suppose we assume the screen consists of 80 columns and 25
rows. So for each line we need 160 bytes, one for each character and one
for each character's attribute. If we need to write some character to
column 3 then we need to skip bytes 0 and 1 as they is for the 1st column;
2 and 3 as they are for the 2nd column; and then write our ascii value
to the 4th byte and its attribute to the 5th location in the video memory.
<H2>3.2 Writing Boot Sector to Floppy</H2>
<P>We have to write a C program that copies our code (OS code) to first
sector of the floppy disk. Here it is:
<BLOCKQUOTE><CODE>
<PRE>
#include &lt;sys/types.h> /* unistd.h needs this */
#include &lt;unistd.h> /* contains read/write */
#include &lt;fcntl.h>
int main()
{
char boot_buf[512];
int floppy_desc, file_desc;
file_desc = open("./boot", O_RDONLY);
read(file_desc, boot_buf, 510);
close(file_desc);
boot_buf[510] = 0x55;
boot_buf[511] = 0xaa;
floppy_desc = open("/dev/fd0", O_RDWR);
lseek(floppy_desc, 0, SEEK_CUR);
write(floppy_desc, boot_buf, 512);
close(floppy_desc);
}
</PRE>
</CODE></BLOCKQUOTE>
<P>First, we open the file <EM><CODE>boot</CODE></EM> in read-only
mode, and copy the file descripter of the opened file to variable
<EM><CODE>file_desc</CODE></EM>. Read from the file 510 characters or
until the file ends. Here the code is small, so the latter case occurs. Be
decent; close the file.
<P>The last four lines of code open the floppy disk device (which mostly
would be /dev/fd0). It brings the head to the beginning of the file using
<EM><CODE>lseek</CODE></EM>, then writes the 512 bytes from the buffer
to floppy.
<P>The man pages of read, write, open and lseek (refer to man 2) would give
you enough information on what the other parameters of those functions
are and how to use them. There are two lines in between, which may be
slightly mysterious. The lines:
<P>
<BLOCKQUOTE><CODE>
<PRE>
boot_buf[510] = 0x55;
boot_buf[511] = 0xaa;
</PRE>
</CODE></BLOCKQUOTE>
This information is for BIOS. If BIOS is to recognize a device as a
bootable device, then the device should have the values 0x55 and 0xaa
at the 510th and 511th location. Now we are done. The program reads the
file <EM><CODE>boot</CODE></EM> to a buffer named boot_buf. It makes the
required changes to 510th and 511th bytes and then writes boot_buf
to floppy disk. If we execute the code, the first 512 bytes
of the floppy disk will contain our boot code. Save the file as
<EM><CODE>write.c</CODE></EM>.
<H2>3.3 Let's Do It All</H2>
<P>To make executables out of this file you need to type the following
at the Linux bash prompt.
<BLOCKQUOTE><CODE>
<PRE>
as86 boot.s -o boot.o
ld86 -d boot.o -o boot
cc write.c -o write
</PRE>
</CODE></BLOCKQUOTE>
<P>First, we assemble the <CODE><EM>boot.s</EM></CODE> to form an object
file <EM><CODE>boot.o</CODE></EM>. Then we link this file to get the
final file <EM><CODE>boot</CODE></EM>. The <EM><CODE>-d</CODE></EM> for
ld86 is for removing all headers and producing pure binary. Reading
man pages for as86 and ld86 will clear any doubts. We then compile the C program
to form an executable named <EM><CODE>write</CODE></EM>.
<P>Insert a blank floppy into the floppy drive and type
<BLOCKQUOTE><CODE>
<PRE>
./write
</PRE>
</CODE></BLOCKQUOTE>
Reset the machine. Enter the BIOS setup and make floppy the first boot
device. Put the floppy in the drive and watch the computer boot from your
boot floppy.
<P> Then you will see an 'A' (with white foreground color on a blue
background). That means that the system has booted from the boot floppy we
have made and then executed the boot sector program we wrote. It is now in the
infinite loop we had written at the end of our boot sector. We must now reboot
the computer and remove the our boot floppy to boot into Linux.
<P> From here, we'll want to insert more code into our boot sector program, to
make it do more complex things (like using BIOS interrupts, protected-mode
switching, etc). The later parts (PART II, PART III etc. ) of this article will
guide you on further improvements. Till then GOOD BYE !
<!-- *** BEGIN bio *** -->
<P>
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Krishnakumar R.</H4>
<EM>Krishnakumar is a final year B.Tech student at Govt. Engg. College Thrissur,
Kerala, India. His journey into the land of Operating systems started with
module programming in linux . He has built a routing operating system by name
GROS.(Details available at his home page:
<A HREF="http://www.askus.way.to">www.askus.way.to</A> ) His other
interests include Networking, Device drivers, Compiler Porting and Embedded systems.</EM>
<!-- *** END bio *** -->
<!-- *** BEGIN copyright *** -->
<P> <hr> <!-- P -->
<H5 ALIGN=center>
Copyright &copy; 2002, Krishnakumar R..<BR>
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 77 of <i>Linux Gazette</i>, April 2002</H5>
<!-- *** END copyright *** -->
<!--startcut ==========================================================-->
<HR><P>
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="kollar.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue77/krishnakumar.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lechnyr.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->