Page 1 of 1

Kernel panic on attempted OS load

Posted: Sat Oct 15, 2011 2:32 pm
by BetaWar
It is quite likely that nobody here remembers me, I haven't posted in over a year an a half at this point.

Some background first:
I am a Junior in CS specializing in Software Engineering. I have attempted to make an operating system before (1.5 years ago...) and that went to the stage of attempting to get a bootloader working. It didn't get anywhere and I decided that I didn't know enough to make it very far at that point. I am now back to attempt things again.

Basically, here is what I have: A basic C++ object-oriented kernel which (thanks to Bran's kernel dev tutorial) should be up to the point of printing a hello world message to the screen (I'll post code here in a second).

The problem: I can't for the life of me figure out how to make an ISO or grub-based floppy image which I can run (via GRUB) that will do anything. I have attempted to just put my image in the GRUB options and boot it on my dev machine but each attempt has resulted in a kernel panic (I will attempt to get the exact message here in a little bit).

So, I guess I am asking for any help people may have in getting my kernel booted successfully. Now for the code:

start.asm

Code: Select all

[BITS 32]
global start
start:
	mov esp, _sys_stack	 ; This points the stack to our new stack area
	jmp stublet

; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
ALIGN 4
mboot:
	; Multiboot macros to make a few lines later more readable
	MULTIBOOT_PAGE_ALIGN	equ 1<<0
	MULTIBOOT_MEMORY_INFO	equ 1<<1
	MULTIBOOT_AOUT_KLUDGE	equ 1<<16
	MULTIBOOT_HEADER_MAGIC	equ 0x1BADB002
	MULTIBOOT_HEADER_FLAGS	equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
	MULTIBOOT_CHECKSUM	equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
	EXTERN code, bss, end

	; This is the GRUB Multiboot header. A boot signature
	dd MULTIBOOT_HEADER_MAGIC
	dd MULTIBOOT_HEADER_FLAGS
	dd MULTIBOOT_CHECKSUM
	
	; AOUT kludge - must be physical addresses. Make a note of these:
	; The linker script fills in the data for these ones!
	dd mboot
	dd code
	dd bss
	dd end
	dd start

; This is an endless loop here. Make a note of this: Later on, we
; will insert an 'extern _main', followed by 'call _main', right
; before the 'jmp $'.
stublet:
	extern main
	call main
	jmp $


; Shortly we will add code for loading the GDT right here!


; In just a few pages in this tutorial, we will add our Interrupt
; Service Routines (ISRs) right here!



; Here is the definition of our BSS section. Right now, we'll use
; it just to store the stack. Remember that a stack actually grows
; downwards, so we declare the size of the data before declaring
; the identifier '_sys_stack'
SECTION .bss
	resb 8192			   ; This reserves 8KBytes of memory here
_sys_stack:
main.cpp

Code: Select all

#include "system.h"

int main(){
  TextMonitorDriver monitor;
  monitor.puts("Hello Modos!");
	for(;;); // infinite loop
	return 0;
}
system.h

Code: Select all

#ifndef SYSTEM_H
#define SYSTEM_H

#include "memory.h"
#include "port.h"
#include "TextMonitorDriver.h"

#endif
memory.h

Code: Select all

#ifndef MEMORY_H
#define MEMORY_H

unsigned char* memcpy(unsigned char* dest, const unsigned char* src, int count);
unsigned char* memset(unsigned char* dest, unsigned char val, int count);
unsigned short* memsetw(unsigned short* dest, unsigned short val, int count);
unsigned int strlen(const char* str);

#endif
memory.cpp

Code: Select all

#include "memory.h"

unsigned char* memcpy(unsigned char* dest, const unsigned char* src, int count){
	const char* sp = (const char*)src;
	char* dp = (char*)dest;
	for(; count != 0; count--){
		*dp = *sp;
		dp++;
		sp++;
	}
	return dest;
}

unsigned char* memset(unsigned char* dest, unsigned char val, int count){
	char* temp = (char*)dest;
	for(; count != 0; count--){
		*temp = val;
		temp++;
	}
	return dest;
}

unsigned short* memsetw(unsigned short* dest, unsigned short val, int count){
	unsigned short* temp = (unsigned short*)dest;
	for(; count != 0; count--){
		*temp = val;
		temp++;
	}
	return dest;
}

unsigned int strlen(const char* str){
	unsigned int count;
	for(count = 0; *str != '\0'; str++, count++);
	return count;
}
port.h

Code: Select all

#ifndef PORT_H
#define PORT_H

unsigned char inportb(unsigned short _port);
void outportb(unsigned short _port, unsigned char _data);

#endif
port.cpp

Code: Select all

#include "port.h"

unsigned char inportb(unsigned short _port){
	unsigned char rv;
	__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
	return rv;
}

void outportb(unsigned short _port, unsigned char _data){
	__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
TextMonitorDriver.h

Code: Select all

#ifndef TEXTMONITORDRIVER_H
#define TEXTMONITORDRIVER_H

#include "system.h"

class TextMonitorDriver{
private:
  unsigned short* textmemptr;
  int attrib;
  int x;
  int y;
public:
  TextMonitorDriver(void);
  void scroll(void);
  void move(void);
  void clear();
  void putch(unsigned char c);
  void puts(char* text);
  void settextcolor(unsigned char forecolor, unsigned char backcolor);
};

#endif
TextMonitorDriver.cpp

Code: Select all

#include "TextMonitorDriver.h"

TextMonitorDriver::TextMonitorDriver(void){
  x = y = 0;
  textmemptr = (unsigned short*)0xb8000;
  clear();
}
void TextMonitorDriver::scroll(void){
  unsigned blank = 0x20 | (attrib << 8);
  unsigned tmp;
  if(y >= 25){
    tmp = y - 24;
    memcpy((unsigned char*)textmemptr, (unsigned char*)(textmemptr + tmp * 80), (25 - tmp) * 80 * 2);
    memsetw(textmemptr + (25 - tmp) * 80, blank, 80);
    y = 24;
  }
}
void TextMonitorDriver::move(void){
  unsigned tmp = y * 80 + x;
  outportb(0x3D4, 14);
  outportb(0x3D5, tmp >> 8);
  outportb(0x3D4, 15);
  outportb(0x3D5, tmp);
}
void TextMonitorDriver::clear(){
  unsigned blank = 0x20 | (attrib << 8);
  int i;
  for(i = 0; i < 25; i++){
    memsetw(textmemptr + i * 80, blank, 80);
  }
  x = y = 0;
  move();
}
void TextMonitorDriver::putch(unsigned char c){
  unsigned short* where;
  unsigned att = attrib << 8;
  if(c == 0x08 && x != 0){
    x = 0;
  }
  else if(c == 0x09){
    x = (x + 8) & !7;
  }
  else if(c == '\r'){
    x = 0;
  }
  else if(c == '\n'){
    x = 0;
    y++;
  }
  else if(c >= ' '){
    where = textmemptr + (y * 80 + x);
    *where = c | att;
    x++;
  }
  if(x >= 80){
    x = 0;
    y++;
  }
  scroll();
  move();
}
void TextMonitorDriver::puts(char* text){
  for(unsigned int i = 0, len = strlen(text); i < len; i++){
    putch(text[i]);
  }
}
void TextMonitorDriver::settextcolor(unsigned char forecolor, unsigned char backcolor){
  attrib = (backcolor << 4) | (forecolor & 0x0f);
}
link.ld

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS{
	.text phys : AT(phys){
		code = .;
		*(.text)
		*(.rodata)
		. = ALIGN(4096);
	}
	.data : AT(phys + (data - code)){
		data = .;
		*(.data)
		. = ALIGN(4096);
	}
	.bss : AT(phys + (bss - code)){
		bss = .;
		*(.bss)
		. = ALIGN(4096);
	}
	end = .;
}
Makefile

Code: Select all

.asm.o:
	nasm -f aout -o $@ $^

.cpp.o:
	g++ -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -c -o $@ $^

kernel.bin:start.o memory.o port.o TextMonitorDriver.o main.o
	ld -T link.ld -o $@ $^

start.o:start.asm
	nasm -f aout -o start.o start.asm

clean:
	rm kernel.bin *.o
Now, as I said, I have attempted booting a floppy image that I made based on this page's floppy disk images section (http://wiki.osdev.org/Disk_Images) and I have placed both the standard bin and the floppy image in the /boot directory and pointed to them via the menu.lst file. It occurs to me that I don't know much about how GRUB actually works so it is quite possible (probable in fact) that the biggest issue here is that I don't know how to set it up properly.

Here is the relevant portion of the menu.lst file (if you want the rest I can post it):

Code: Select all

# (3) modOS
title  modOS
root   (hd0,0)
kernel /vmlinuz26 root=/dev/disk/by-uuid/2f85c905-e9c7-4318-be77-30d2a186f3f3 ro
initrd /modos.bin
Any help would be appreciated. As you can probably tell, I am relatively new to OS development. While I have taken the OS course my university offers it was just an overview and relatively worthless in anything other than theory.

Again, thanks for any and all help.
~ BetaWar

Re: Kernel panic on attempted OS load

Posted: Sat Oct 15, 2011 5:26 pm
by Combuster
You already mention a lot of gaps in your own knowledge, why don't you go exploring them? I can hardly suggest that you shouldn't. There are quite a few working examples on the wiki, most importantly the bare bones.

That said, linux is not a bootloader. You wrote a kernel, there is no point in lying to grub that it is something other than a kernel.

Re: Kernel panic on attempted OS load

Posted: Sat Oct 15, 2011 9:44 pm
by Jvac
Basically, here is what I have: A basic C++ object-oriented kernel which (thanks to Bran's kernel dev tutorial) should be up to the point of printing a hello world message to the screen (I'll post code here in a second).
What? I am working on this tutorial and it is based on a C kernel. Can you share the link for the basic C++ object-oriented kernel. Thanks

About your boottable image if you are working on a window machine and cygwin use mkisofs from command prompt to create your image:

mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot
-info-table -o bootable.iso isofiles


See the wiki for boottable iso here and see here for booting tutorials.

Re: Kernel panic on attempted OS load

Posted: Sun Oct 16, 2011 12:49 pm
by egos
BetaWar wrote:Now, as I said, I have attempted booting a floppy image that I made based on this page's floppy disk images section (http://wiki.osdev.org/Disk_Images) and I have placed both the standard bin and the floppy image in the /boot directory and pointed to them via the menu.lst file. It occurs to me that I don't know much about how GRUB actually works so it is quite possible (probable in fact) that the biggest issue here is that I don't know how to set it up properly.

Here is the relevant portion of the menu.lst file (if you want the rest I can post it):

Code: Select all

# (3) modOS
title  modOS
root   (hd0,0)
kernel /vmlinuz26 root=/dev/disk/by-uuid/2f85c905-e9c7-4318-be77-30d2a186f3f3 ro
initrd /modos.bin
To make floppy image with GRUB you can use fasm and my GrubOnFloppy sources (search on forum). I can't understand why you use Linux kernel instead yours in menu.lst. I can't understand too why you use disk partition instead floppy or CD/DVD as a boot drive. For example look at menu.lst to load my kernel from floppy by GRUB:

Code: Select all

color light-gray/blue black/light-gray

default 0
timeout 10

title Load Link kernel from floppy (variant 1)
root (fd0)
kernel /link.os
module /link.fs

title Load Link kernel from floppy (variant 2)
kernel (fd0)/link.os
module (fd0)/link.fs