Need help: Making a bootloader

[beginner/ intermediate]

Page 1 of 1

10 Replies - 8045 Views - Last Post: 08 June 2009 - 01:46 PM

#1 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1695
  • View blog
  • Posts: 8,592
  • Joined: 07-September 06

Need help: Making a bootloader

Posted 18 May 2009 - 05:31 PM

Okay, so, as some of you may know, I have been looking into making an Operating System for a while. I have finally been able to start (as school is all but over for the year) and am having some trouble when it comes to creating and booting from a CD.

I am using Ubuntu Hardy to compile and code on, and a Windows 98 machine to test on (it hasn't got very far...)

I have been following this tutorial (just for getting started):
http://www.osdever.n.../cpp_kernel.pdf

Attached is all the code I have at this point (zipped), but here it is for anyone who wants to see it:
#ifndef VIDEO_HEADER
#define VIDEO_HEADER

class Video{
private:
	unsigned short* videoMemory;
	unsigned int row;
	unsigned int column;
public:
	Video();
//	~Video();
	void clear();
	void write(char* p);
	void put(char c);
};
#endif


#include "Video.h"
Video::Video(){
	row = column = 0;
	videoMemory = (unsigned short*)0xb800;
}
//Video::~Video(){
//}
void Video::clear(){
	for(unsigned int i=0; i<(80825); i++){
		videoMemory[i] = (unsigned char)' '|0x0700;
	}
	row = column = 0;
}
void Video::write(char* cp){
	char* str = cp;
	for(char* ch = str; *ch; ch++){
		put(*ch);
	}
}
void Video::put(char c){
	if(column >= 80 || c == '\n'){
		column = 0;
		row += 80;
	}
	if(row >= (80*25)){
		clear(); // scroll the screen later on.
	}
	videoMemory[row+column] = (unsigned char)c|0x0700;
	column++;
}


#include "Video.h"
int main(void){
	Video vid;
	vid.write("Welcome to ModOs v1.0a!");
}


[BITS 32] ; protected mode
[global start]
[extern main] ; this is in our c++ code
start:
call main ; call int main(void) in C++ file
cli; disables interrupts
hlt; halts the CPU


OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS{
	.text 0x100000 : {
		code = .; _code = .; __code = .;
		*(.text)
		. = ALIGN(4096);
	}
	.data : {
		date = .; _data = .; __data = .;
		*(.data)
		. = ALIGN(4096);
	}
	.bss : {
		bss = .; _bss = .; __bss = .;
		*(.bss)
		. = ALIGN(4096);
	}
	end = .; _end = .; __end = .;
}



The following code is copied from here:
http://code.google.c.../wiki/FirstStep
; Fat12 Bootloader

[BITS 16]                       ; We need 16-bit intructions for Real mode

[ORG 0x7C00]                    ; The BIOS loads the boot sector into memory location 0x7C00

jmp word load_kernel            ; Load the OS Kernel

;----------Fat 12 Header junk----------;

        db "ONYXDISK"           ; OEM Label String
        dw 512                  ; Bytes per sector
        db 1                    ; Sectors per FAT cluster
        dw 36                   ; Resered sector count
        db 2                    ; number of FATs
        dw 224                  ; Root dir entries
        dw 2880                 ; Total Sectors
        db 240                  ; Double sided, 18 sectors per track
        dw 9                    ; Sectors per FAT
        dw 18                   ; Sectors per track
        dw 2                    ; Head count (double sided)
        dd 0                    ; Hidden sector count 
        
drive db 0                      ; Used to store boot device
        
;----------Bootsector Code----------;
  
load_kernel:
        jmp read_disk           ; Load the OS into memory
        ;jmp get_ram             ; Get ram amount
        jmp enter_pm            ; Enter Protected Mode
        
read_disk:
        mov ah, 0               ; RESET-command
        int 13h                 ; Call interrupt 13h
        mov [drive], dl         ; Store boot disk
        or ah, ah               ; Check for error code
        jnz read_disk           ; Try again if ah != 0
        mov ax, 0
        mov ax, 0                               
        mov es, ax                              
        mov bx, 0x1000          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command
        mov al, 12h             ; Number of sectors to read (0x12 = 18 sectors)
        mov dl, [drive]         ; Load boot disk
        mov ch, 0               ; Cylinder = 0
        mov cl, 2               ; Starting Sector = 3
        mov dh, 0               ; Head = 1
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz load_kernel         ; Try again if ah != 0
        cli                     ; Disable interrupts, we want to be alone

enter_pm:
        xor ax, ax              ; Clear AX register
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor 
        
;----------Entering Protected Mode----------;
                
        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0     (0xFE = Real Mode)
        mov cr0, eax            ; Copy the contents of EAX into CR0
        
        jmp 08h:kernel_segments ; Jump to code segment, offset kernel_segments
        

[BITS 32]                       ; We now need 32-bit instructions
kernel_segments:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h
        
        jmp 08h:0x1000          ; Jump to section 08h (code), offset 01000h
        
;----------Global Descriptor Table----------;

gdt:                            ; Address for the GDT

gdt_null:                       ; Null Segment
        dd 0
        dd 0
        
        
KERNEL_CODE             equ $-gdt
gdt_kernel_code:
        dw 0FFFFh               ; Limit 0xFFFF
        dw 0                    ; Base 0:15
        db 0                    ; Base 16:23
        db 09Ah                 ; Present, Ring 0, Code, Non-conforming, Readable
        db 0CFh                 ; Page-granular
        db 0                    ; Base 24:31

KERNEL_DATA             equ $-gdt
gdt_kernel_data:                        
        dw 0FFFFh               ; Limit 0xFFFF
        dw 0                    ; Base 0:15
        db 0                    ; Base 16:23
        db 092h                 ; Present, Ring 0, Data, Expand-up, Writable
        db 0CFh                 ; Page-granular
        db 0                    ; Base 24:32

gdt_interrupts:
        dw 0FFFFh
        dw 01000h
        db 0
        db 10011110b
        db 11001111b
        db 0

gdt_end:                        ; Used to calculate the size of the GDT

gdt_desc:                       ; The GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                  ; Address of the GDT

times 510-($-$$) db 0          ; Fill up the file with zeros

dw 0AA55h                       ; Boot sector identifyer




Other commands I have used for compiling, linking and CD burning:
//Compile for assembly files:
nasm -f bin Bootloader.asm -o boot.bin
nasm -f aout loader.asm -o loader.o

//Compile for c++ files:
g++-2.95 -c Video.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
g++-2.95 -c Kernel.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions

//Linker commands:
ld -Ttext 0x1000 Link.ld -o Kernel.bin loader.o Kernel.o Video.o

//CD Write commands:
dd if=boot.bin of=os.img bs=512 count=1
dd if=Kernel.bin of=os.img bs=512 seek=1


So, I have no idea why this isn't working, does anyone know how to make this successful?

Attached files: [attachment=11989:attachment]

Any help would be greatly appreciated.

Is This A Good Question/Topic? 0
  • +

Replies To: Need help: Making a bootloader

#2 no2pencil   User is offline

  • Professor Snuggly Pants
  • member icon

Reputation: 6968
  • View blog
  • Posts: 31,958
  • Joined: 10-May 07

Re: Need help: Making a bootloader

Posted 18 May 2009 - 06:56 PM

I thought that the adddress 0x7C00 was specific to a bootable floppy. However I was unable to find the exact bootable address for a cdrom.

Still looking...
Was This Post Helpful? 0
  • +
  • -

#3 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1695
  • View blog
  • Posts: 8,592
  • Joined: 07-September 06

Re: Need help: Making a bootloader

Posted 28 May 2009 - 08:51 AM

Okay, after a it of tweeking (and a day of bashing my head against everything in sight) I have figured out that the problem is not with the cd/image file (though there was somethign wrong with that), but with the source and how I am compiling it (though I have no idea what the problem is...).

I managed to find a couple of floppy drives, so I am just using floppies for testing at this point.

I have modified things like so:

#include "Video.h"
int main(void){
        Video vid;
        vid.clear();
        vid.write("Hello world");
}


Compiling code (modifications):
//[CD] Image Write commands:
dd if=boot.bin of=os.img bs=512 count=1
dd if=Kernel.bin of=os.img bs=512 seek=1

//Floppy burn command:
dd if=os.img of=/dev/fd0


The computer I am testing on is successfully finding the image and believes it can boot from it, but when it begins booting it just stops and does nothing (though it should be clearing the video memory and outputting "Hello world").

Now, due to the issue it is having I believe the problem will lie in the bootloader.asm or loader.asm files. The only problem there is that I am a TOTAL noob when it comes to assembly, hence the reason I am trying to get to C++ control asap. Any ideas?
Was This Post Helpful? 0
  • +
  • -

#4 Korupt   User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 185
  • Joined: 22-June 08

Re: Need help: Making a bootloader

Posted 28 May 2009 - 11:43 AM

Try using grub: http://wiki.osdev.org/Bare_bones (scroll down to "Booting the kernel part");

One more thing, for your clear function, why are you doing the loop 80825 times? There only 25 row and 80 column making a total of 2000 spaces, where are you getting 80825 from?
Was This Post Helpful? 1
  • +
  • -

#5 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1695
  • View blog
  • Posts: 8,592
  • Joined: 07-September 06

Re: Need help: Making a bootloader

Posted 28 May 2009 - 12:46 PM

Quote

where are you getting 80825 from?

Typo, that is supposed to read 80*25, thanks for that :)
Was This Post Helpful? 0
  • +
  • -

#6 Tom9729   User is offline

  • Segmentation fault
  • member icon

Reputation: 181
  • View blog
  • Posts: 2,642
  • Joined: 30-December 07

Re: Need help: Making a bootloader

Posted 28 May 2009 - 09:16 PM

Why don't you test it in an x86 emulator like QEMU or Bochs? Both of them support debugging with gdb last time I checked, not to mention it's a lot faster than trying to boot it on a real machine.

Also I second Korupt's recommendation to just use GRUB. They have an example in the multiboot spec that gets you up and running with a pretty simple C kernel (in protected mode, with all the bells and whistles). Besides you can always go back later and write the bootloader if that's what you want. :)
Was This Post Helpful? 0
  • +
  • -

#7 polymath   User is offline

  • D.I.C Addict
  • member icon

Reputation: 54
  • View blog
  • Posts: 670
  • Joined: 04-April 08

Re: Need help: Making a bootloader

Posted 29 May 2009 - 04:41 AM

I agree with Tom. I've used grub for a long time to boot my "toy" kernel, and i find it sped my development to not have to deal with boot issues. Plus, if you are using GPL, you can use the code that GNU includes with the specification, specifically multiboot.h. I'm using BSD licensing, so i had to make my own header for the spec, which didn't take *too* long.

On a side note, don't you need to declare main() with extern "C" linkage? Otherwise you'll get name mangling issues. Perhaps you could do something like this:

kernel.h:
#ifndef KERNEL_H_INC
#define KERNEL_H_INC

extern int main();

#ifdef HAVE_ASM_USCORE
#define WITH_USCORE(sym) sym
#else
#define WITH_USCORE(sym) _sym
#endif

extern "C" {
   extern void WITH_USCORE(launch_main)();
}
#endif


kernel.c
#include "kernel.h"
void WITH_USCORE(launch_main)() {
   main();
}

int main() {
   //code
}


Then in you asm file, you could use call _launch_main. Or, you could give int main() an alias. Whatever you want to do. But the extern "C" method is pretty much compiler-independent.

As far as tutorials go, I used http://osdever.net/bkerndev/index.php to get started, and then http://www.osdev.org has all the references you need to go further. The tutorial is in C, but it is easy to mod it to be more cpp-esque. And C is backwards compatible in most ways, so...

This post has been edited by polymath: 29 May 2009 - 04:43 AM

Was This Post Helpful? 0
  • +
  • -

#8 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1695
  • View blog
  • Posts: 8,592
  • Joined: 07-September 06

Re: Need help: Making a bootloader

Posted 07 June 2009 - 11:24 PM

Well, I bet a lot of you thought I had forgotten about this, or given up. Not quite, I just haven't made any progress (though I have been able to take a step or 2 backwards... can't even get everything to compile anymore...).

I have found a ton or articles which people may find useful (or at least will be able to help them out more than they have me...). For the moment I am on my PC, so I don't have them all on this computer, but here is one in particular I did find intereting:
http://en.wikibooks....bly/Bootloaders

It offers a look at x86 bootloaders and has the source code for Linux v0.01 Bootloader (at the bottom) so I thought anyone interested in this type of thing would be interested in it.

Additionally, here is a link to another thread I have made (on an OS programming site), which has even more links:
http://forum.osdev.o...php?f=1&t=20172

Now, I do have a quick question, which may cause me to shoot myself for all eternity.

If I was to use GRUB to make this bootloader, would there by any way for me to burn the bootloader to the CD/ floppy along with the Kernel and run it on a machine which doesn't ahve GRUB installed? That is the main reason I haven't done anything with GRUB yet, I don't want to be stuck with getting people to install software before they can install Modos. I want it to be like any other respectable operating system, able to run on its own two feet.

I will post the other links when I am on my laptop tomorrow, but for the moment it is late and I need sleep.
Was This Post Helpful? 0
  • +
  • -

#9 Tom9729   User is offline

  • Segmentation fault
  • member icon

Reputation: 181
  • View blog
  • Posts: 2,642
  • Joined: 30-December 07

Re: Need help: Making a bootloader

Posted 08 June 2009 - 04:01 AM

View PostBetaWar, on 8 Jun, 2009 - 01:24 AM, said:

If I was to use GRUB to make this bootloader, would there by any way for me to burn the bootloader to the CD/ floppy along with the Kernel and run it on a machine which doesn't ahve GRUB installed? That is the main reason I haven't done anything with GRUB yet, I don't want to be stuck with getting people to install software before they can install Modos. I want it to be like any other respectable operating system, able to run on its own two feet.

http://www.osdever.n...orials/grub.php

A couple of remarks:
1) Yes you should be able to install GRUB on a CD/floppy/usb drive/hard drive.
2) Every respectable OS needs and installs it's own bootloader.
3) I'm guessing right now you're combining your boot loader and your kernel into one blob, but eventually you may wish to separate them and have the kernel on an actual partition. This will be MUCH easier to do with GRUB because GRUB supports a lot of file systems already.
4) You should probably concentrate on getting at least as far as virtual memory support before worrying about making things convenient for your "users".
Was This Post Helpful? 0
  • +
  • -

#10 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1695
  • View blog
  • Posts: 8,592
  • Joined: 07-September 06

Re: Need help: Making a bootloader

Posted 08 June 2009 - 09:32 AM

Okay, thanks for the clarification.

Here are those other links (look at my previous post if you are lost):
http://www.joelgompe...eOfContents.htm
http://www.staerk.de...ram_your_own_OS
http://www.dreaminco...h...er=all&st=0
Was This Post Helpful? 0
  • +
  • -

#11 Tom9729   User is offline

  • Segmentation fault
  • member icon

Reputation: 181
  • View blog
  • Posts: 2,642
  • Joined: 30-December 07

Re: Need help: Making a bootloader

Posted 08 June 2009 - 01:46 PM

There's also this.

http://www.dreaminco...wtopic97424.htm
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1