Kernel panic on attempted OS load

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
BetaWar
Posts: 12
Joined: Thu May 28, 2009 11:23 pm

Kernel panic on attempted OS load

Post 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
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Kernel panic on attempted OS load

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Jvac
Member
Member
Posts: 58
Joined: Fri Mar 11, 2011 9:51 pm
Location: Bronx, NY

Re: Kernel panic on attempted OS load

Post 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.
"The best way to prepare for programming is to write programs, and
to study great programs that other people have written." - Bill Gates


Think beyond Windows ReactOS®
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Kernel panic on attempted OS load

Post 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
If you have seen bad English in my words, tell me what's wrong, please.
Post Reply