Showing posts with label Boot Sector. Show all posts
Showing posts with label Boot Sector. Show all posts

Friday, 1 July 2011

Copying Your Bootsector to a Floppy

Copying Your Bootsector to a Floppy

NOTE: The version of partCopy used in this tutorial uses different parameters than the newer versions.

So you've made a bootsector and now you want to copy it to a floppy. Before we get to that, you need to make sure of 3 things:
  1. Your bootsector is exactly 512 bytes long.
  2. Your bootsector ends with 0xAA55.
  3. Your bootsector is compiled as a flat binary.
To do the first two steps in NASM, simply end your bootsector with this bit of code:

times 512-($-$$)-2 db 0
dw 0AA55h


For the last step, compile(using NASM) with:

nasm yourbootsector.asm -f bin -o bootsec.bin Now let's get your bootsector onto a floppy.
I'm assuming that your are using Windows. For Windows your need  PartCopy. For Linux you will need to use dd(anyone interested in writting a tutorial on dd?). Now, you need to copy your bootsector to the first 512 bytes of the floppy disk. To just test a bootsector(in this example calledbootsec.bin) use PartCopy like this:

partcopy bootsec.bin 0 200 -f0

That copies bytes 0-512(PartCopy uses hex, 0x200=512) of bootsec.bin to the first floppy drive(-f0). Note that after -f0 we could put a destination offset, but since the bootsector has to be at the start of the floppy we just leave out a destination offset(PartCopy's default is 0).
If your bootsector has no bugs, the floppy will be bootable. One thing that you will notice however, is that if you try and read the floppy in Windows/DOS/Linux you are told that the floppy isn't formated. This is because of the way in which we just copied our bootsector to the floppy. The way we did it we overwrote some important information.
To not overwrite this information(the "DOS boot record") we need to add some more code to our bootsector. At the start of your bootsector(right after your org 0x7C00) do this:

start:
jmp short begin
nop
times 0x3B db 0

begin:
the rest of your code goes here

Now, this time it will take 2 steps to copy your boot sector to a floppy(if you're using the previous, be sure to format it first):

partcopy bootsec.bin 0 3 -f0
partcopy bootsec.bin 3e 1c2 -f0 3e

And there you have it. A bootable floppy disk with your own bootsector on it!
Download an example with full source code.

Using GRUB

Using GRUB

The GRUB homepage can be found at http://www.gnu.org/software/grub/grub.en.html.
This tutorial was written by Chris Giese and is also availible at his site.

================================================================
References
================================================================
This information was gleaned from my own experiments with GRUB
and from the following posts to alt.os.development:

Subject: Re: generic bootloader question
Newsgroups: alt.os.development
From: "Marv"
Date: Sat, 7 Apr 2001 23:35:20 +0100
References:
Message-ID:

Subject: Re: Grub multiboot example
Newsgroups: alt.os.development
From: "Marv"
Date: Mon, 4 Jun 2001 17:21:17 +0100
References:
Message-ID:

Subject: Re: Grub multiboot example
Newsgroups: alt.os.development
From: "Mike Wimpy"
Date: Thu, 7 Jun 2001 22:17:51 -0700
References:
Message-ID:

Subject: Re: grub coff (solved it!)
Newsgroups: alt.os.development
From: "Mark & Candice White"
Date: Sun, 16 Sep 2001 10:57:34 GMT
References:
Message-ID:

================================================================
Getting GRUB
================================================================
Source code:
ftp://alpha.gnu.org/gnu/grub/grub-0.90.tar.gz

Binaries:
ftp://alpha.gnu.org/gnu/grub/grub-0.90-i386-pc.tar.gz

DOS and Windows users will need PARTCOPY or RAWRITE:
http://www.execpc.com/~geezer/johnfine/index.htm#zero
http://uranus.it.swin.edu.au/~jn/linux/rawwrite.htm
http://www.tux.org/pub/dos/rawrite/

================================================================
Building GRUB
================================================================
UNIX
----
configure ; make
(...I think...)

DOS and Windows
---------------
(ha! forget it)

================================================================
Installing GRUB on a floppy with no filesystem
================================================================
1. Get the GRUB binaries (files "stage1" and "stage2")

2. Concatenate the files "stage1" and "stage2" into one file:

(DOS) copy /b stage1 + stage2 boot

(UNIX) cat stage1 stage2 >boot

3. Write the file "boot" directly to the floppy disk:

(DOS) rawrite boot a:
-OR-
(DOS) partcopy boot 0 168000 -f0

(UNIX) cat boot >/dev/fd0

PARTCOPY will give an error message because the file "boot"
is much shorter than 0x168000 bytes, but this is OK.

================================================================
Installing GRUB on a floppy with a filesystem
================================================================
1. Make a bootable GRUB floppy with no filesystem, as described
above.

2. Copy the files "stage1" and "stage2" to a second floppy disk,
one formatted with a filesystem that GRUB recognizes. To use
the GRUB "setup" command, these files must be stored in
subdirectory "/boot/grub":

(DOS) mkdir a:\boot
mkdir a:\boot\grub
copy stage1 a:\boot\grub
copy stage2 a:\boot\grub

(UNIX) mount /dev/fd0 /mnt
mkdir /mnt/boot
mkdir /mnt/boot/grub
cp stage1 /mnt/boot/grub
cp stage2 /mnt/boot/grub

3. After GRUB is installed on floppy disk #2, the file "stage2"
must not be modified, deleted, defragged, or moved. If it
is modified in any way, the disk will no longer be bootable.
To prevent this, make the file read-only:

(DOS) attrib +r +s stage2

(UNIX) chmod a-w stage2

The DOS command above makes "stage2" a System file as
well as Read-only. This is needed to protect against DEFRAG.

NOTE: File "stage1" will be copied into the bootsector. If
this file is moved or deleted after GRUB is installed, the
disk will still be bootable.

4. Boot your computer from the floppy with GRUB but no
filesystem. At the GRUB prompt, eject this floppy and insert
the formatted floppy disk (with the filesystem and "stage1"
and "stage2" files, possibly in directory "/boot/grub".

5a. If files "stage1" and "stage2" are stored in "/boot/grub" on
disk #2, you can install GRUB on disk #2 simply by typing:

setup (fd0)

This is apparently equivalent to this single command line:

install /boot/grub/stage1 d (fd0) /boot/grub/stage2 p
/boot/grub/menu.lst

5b. If files "stage1" and "stage2" are stored elsewhere, e.g. in
subdirectory "/foo", install GRUB on the second floppy disk
like this (this is also a single command line):

install=(fd0)/foo/stage1 (fd0) (fd0)/foo/stage2 0x8000 p
(fd0)/foo/menu.lst

Floppy disk #2 (the disk with the filesystem) is now bootable.

xxx - Boot from disk #2, copy new/modified "stage2", and re-run
"setup" or "install"? Will this work? (xxx - GRUB is not a
shell -- it can't copy files, or list directories -- can it?)

xxx - install syntax:
0x8000
This value gets embedded into the bootsector
of the floppy to indicate the address that
stage2 should be loaded into memory.

p
Modifies stage2, to report to the kernel the partition
that stage 2 was found on (I think).

(fd0)/boot/grub/menu.lst
Modifies stage2, and tells it where to load the
menu.lst (bootmenu) configuration file from.

================================================================
Making a Multiboot kernel
================================================================
Multiboot header
----------------
Whatever its file format, your kernel MUST have a Multiboot
header. This header
1. must be aligned on a dword (4-byte) boundary, and
2. must appear in the first 8K of the kernel file.

*** NOTE: An address within the first 8K of the .text section
is not necessarily within 8K of the start of the file.

ELF kernels
-----------
GRUB understands the ELF file format directly. If your kernel
is ELF, you can use the simple Multiboot header shown here:

MULTIBOOT_PAGE_ALIGN equ 1http://www.multimania.com/placr/binutils.html

(xxx - this server is often difficult to reach. Someone should
mirror these tools. I'm near my disk quota :)

I recommend building a regular COFF kernel, then doing this:
objcopy-elf -O elf32-i386 krnl.cof krnl.elf

Failing this, you can make GRUB load a COFF kernel by using the
"aout kludge". This uses additional fields at the end of the
Multiboot header, like this:

MULTIBOOT_PAGE_ALIGN equ 1
...
int main(multiboot_info_t *boot_info)
{ if(boot_info->flags & 2)
{ kprintf("the command line is:\n'%s'\n",
(char *)boot_info->cmdline); }
...

xxx - more info

================================================================
Making a boot menu (file "menu.lst")
================================================================
Example 1:
# Entry 0:
title WildMagnolia
root (fd0)
kernel /boot/kernel.elf
module /boot/mod_a
module /boot/mod_b

Example 2:
#
# Sample boot menu configuration file
#

# default - boot the first entry.
default 0

# if have problem - boot the second entry.
fallback 1

# after 30 sec boot default.
timeout 30

# GNU Hurd
title GNU/Hurd
root (hd0,0)
kernel /boot/gnumach.gz root=hd0s1
module /boot/serverboot.gz

# Linux - boot ot second HDD
title GNU/Linux
kernel (hd1,0)/vmlinuz root=/dev/hdb1

# booting Mach - get kernel from floppy
title Utah Mach4 multiboot
root (hd0,2)
pause Insert the diskette now

Copying Your Bootsector to a Harddrive

Copying Your Bootsector to a Harddrive

First, you should read the Copying Your Bootsector to a Floppy Disk tutorial if you haven't yet.
The requirements for a bootsector that's installed on a harddrive are the same as those for a bootsector on a floppy:
  1. Your bootsector is exactly 512 bytes long.
  2. Your bootsector ends with 0xAA55.
  3. Your bootsector is compiled as a flat binary.
Now, the BIOS(Basic Input Output Sytem) will look only on the first harddrive for a bootsector(most BIOSes do this, though apperently some allow you to chose which harddrive to look on) so we need to copy our bootsector to the first harddrive. In Linux, the first harddrive is/dev/hda and in PartCopy, it is h0. 

Copying Under Windows With PartCopy

This is is pretty much the same as copying a bootsector to a floppy disk with PartCopy(in this example the bootsector is called bootsec.bin):
partcopy bootsec.bin 0 200 -h0 
We start at the very beginning of the first harddrive(the first harddrive is specified with the -h0) and continue to the 512 byte mark(512 bytes = 0x200).
Before you do that, you might want to back up the old bootsector so that you can restore it. The command below saves the old bootsector into a file called oldboot.bin:
partcopy -h0 0 200 oldboot.bin

Copying Under Linux With dd

First, our bootsector is called bootsec.bin. Under Linux, the first harddrive is /dev/hda. We want to write our bootsector as one block of 512 bytes. bs=512 sets up the size of 1 block and count=1specifies that we want to only write 1 block:
dd if=bootsec.bin of=/dev/hda bs=512 count=1 Before you do that, you might want to back up the old bootsector so that you can restore it. The command below saves the old bootsector into a file called oldboot.bin:
dd if=/dev/hda of=oldboot.bin bs=512 count=1

The booting process

The booting process

by J.Vinoth Kumar

Things that are good to know...

So, you want to make your own OS, but has no clue where to start?! First, you need to find the right tools. I use mixed assembly and C-code to make MuOS. The tools I use are: 
  • For assembly: Nasm
  • For C-code: Gcc (I use Djgpp, but that's because I do my work on the Win32-platform, although, everything should work on any platform)
  • For PC-emulation: Bochs (You don't want to reboot every time you want to test something)
Now, on to the good stuff =). The aim for our OS is to be 32-bit. For those who now thinks: 'Hey?! Isn't every 386+, 32-bits processors? Why aim lower that a 386?': - There's a reason!
Back when the 386 was introduced, the 32-bits were a brand new feature. For all thoses people who spent many $$$ for their 16-bit programs, backwards compability was a must. Intel decided to make the 386 start in 16-bit mode and if the Operating System supported 32-bits, it would have to change from 16-bit mode to 32-bit mode manually. And everybody lived happily ever after... Okay, present day. Computers still boot in 16-bit compability mode. There are hardly any 16-bit operating systems left (DOS is 16-bit, and there are still users, so I can't say that there are none).
There are a few things that change dramatically when 32-bit mode are activated and it's just because of these reasons that we want to have a 32-bit OS (some of the features can be accessed in 16-bit mode, but it requires some special techniques to be used):
  • Access to 4 GB of memory - At startup, the processor is in a so called Real mode (16-bit). This limits the memory access to about 1 MB. Howevery, in Protected mode (32-bit), memory up to 4 GB(!) can be accessed. That's a lot more than 1 MB =).
  • Memory protection - The Protected mode makes reason for its name in memory protection. Memory can be write-protected so that critical sections cannot be touched (OS parts or other application's data for example).
  • Multitasking - The processor has built-in support for task switching. Multitasking is not accually parallell processes, but scheduled processing time. This feature saves the state of the registers and loads it with the next task's register values. (This can be done with software, but it's faster in hardware most of the time)
There are more features, but these are the most important ones (if you ask me). That should cover the basics you'll need to know. On to the good stuff - Writing a boot sector!

The fun and dangerous part!

Create a plain text file called 'booting.asm'. The first thing we should do, is to tell the compiler, we're compiling to 16-bit instructions. Remember, at the start-up, the computer operates in Real mode (16-bit).
[BITS 16]
Then we tell the compiler, where in the memory our program is resident. In Nasm, this is done by the ORG command. 'Why does the compiler need to know that?', you ask. Take a look at this piece of code:
[ORG 0x7C00]
mov ax, [label]
label:
dw 0
The mov instruction is assembled into 'mov ax, 0x7C03', instead of 'mov ax, 0x0003'. This had not been necessary if our program was a 'normal' application, but now, we're making a boot sector. The number I picked, 0x7C00, is the memory address the BIOS puts the boot sector it finds in, so this is where our programs is resident. This adds the line:
[ORG 0x7C00]
Now we want to write a message on the screen. To make it simple, we use the BIOS interrupts available in Real mode. Int 10h has all the functionallity we need. If we put 0Eh into the AH register, we tell the BIOS that we want to put a single character onto the screen. The BIOS then takes the ASCII value of AL, combineds this with the color information in BH and prints the character. The BL register is used to set a page number, but we're not using this, so just set it to 0 and ignore it. Now our code for this:
mov ah, 0Eh
mov al, 'A'
mov bh, 0Fh
mov bl, 0
int 10h
The BH register holds, as said before, the color attribute for the character. I didn't explain why I put 0Fh in BH, but it holds the color code for the character. This seems not to be supported by all BIOSes, but give it a try if you want to (doesn't work in Bochs). The color codes are as follows:
ValueColorValueColor
00hBlack08hDark gray
01hBlue09hBright blue
02hGreen0AhBright green
03hCyan0BhBright cyan
04hRed0ChPink
05hMagenta0DhBright magenta
06hBrown0EhYellow
07hGray0FhWhite
To get more information about BIOS interrupts, there's a complete listing made by Ralf Brown. You'll find his interrupt list here.
After we displayed our 'A' we just hang... This is done by making a jump to a jump, to a jump, to a jump, etc...:
hang:
jmp hang
To get the BIOS to recognize the file as a valid boot sector, the word at address 0x510 must be set to 55AAh. First we fill up the rest of the file with zeros and then we add our word. This is done by adding the lines:
times 510-($-$$) db 0
dw AA55h

Putting it together

Now we have a valid boot sector, but we must only compile it first. To compile it to a plain binary file, which the BIOS can read, we use nasm (or nasmw on windows) with the switches:
nasm -f bin booting.asm -o booting.bin
The '-f bin' specifies the format to plain binary. You can choose a different output name, but I chose 'booting.bin', because it was a logical name =). Now we are all set to test it. Copy the file into Bochs' directory and run it with the booting.bin as a floppy and we're done!
Here's a screenshot from Bochs, running the tutorial's code:

Download the complete source for this tutorial.
Download my example configuration file for Bochs (paths to the BIOS may have to be changed, if you're using another distributions than Win32 1.4.1).

 
Related Posts Plugin for WordPress, Blogger...