Page 1 of 3

C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:14 pm
by NunoLava1998
I've finally did the Bare Bones tutorial and it's almost time to move into the Meaty Skeleton. How great. And without GRUB, i just wrote a simple assembler bootloader, as GRUB4DOS/Syslinux had problems on my PC.
I can boot it in real hardware, which is pretty good. But it reboots the PC. My BIOS menu is written in C, and rebooting from there normally gives a few frames of VESA/VGA garbage, then reboots properly. The same happens on the fulldisk.img i have created, suggesting the C code is rebooting for some reason. The assembly bootloader loads Protected mode and loads the GDTR, and then at the very end switches to 32 bit right before the jump to 0x07E00 instruction, which should make it protected mode 32 bit and NASM compiled it correctly. I do 0x13 before moving to 32bit protected mode, THEN jump to protected mode and go to 32bit code, then jump to the myos.bin/boot.asm. The A20 line is not enabled.
Here is the code:

Code: Select all

/* Surely you will remove the processor conditionals and this comment
   appropriately depending on whether or not you use C++. */
#if !defined(__cplusplus)
#include <stdbool.h> /* C doesn't have booleans by default. */
#endif
#include <stddef.h>
#include <stdint.h>
 
/* Check if the compiler thinks we are targeting the wrong operating system. */
#if defined(__linux__)
#error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif
 
/* This tutorial will only work for the 32-bit ix86 targets. */
#if !defined(__i386__)
#error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif
 
/* Hardware text mode color constants. */
enum vga_color {
	VGA_COLOR_BLACK = 0,
	VGA_COLOR_BLUE = 1,
	VGA_COLOR_GREEN = 2,
	VGA_COLOR_CYAN = 3,
	VGA_COLOR_RED = 4,
	VGA_COLOR_MAGENTA = 5,
	VGA_COLOR_BROWN = 6,
	VGA_COLOR_LIGHT_GREY = 7,
	VGA_COLOR_DARK_GREY = 8,
	VGA_COLOR_LIGHT_BLUE = 9,
	VGA_COLOR_LIGHT_GREEN = 10,
	VGA_COLOR_LIGHT_CYAN = 11,
	VGA_COLOR_LIGHT_RED = 12,
	VGA_COLOR_LIGHT_MAGENTA = 13,
	VGA_COLOR_LIGHT_BROWN = 14,
	VGA_COLOR_WHITE = 15,
};
 
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
	return fg | bg << 4;
}
 
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
	return (uint16_t) uc | (uint16_t) color << 8;
}
 
size_t strlen(const char* str) {
	size_t len = 0;
	while (str[len])
		len++;
	return len;
}
 
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
 
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t* terminal_buffer;
 
void terminal_initialize(void) {
	terminal_row = 0;
	terminal_column = 0;
	terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
	terminal_buffer = (uint16_t*) 0xB8000;
	for (size_t y = 0; y < VGA_HEIGHT; y++) {
		for (size_t x = 0; x < VGA_WIDTH; x++) {
			const size_t index = y * VGA_WIDTH + x;
			terminal_buffer[index] = vga_entry(' ', terminal_color);
		}
	}
}
 
void terminal_setcolor(uint8_t color) {
	terminal_color = color;
}
 
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
	const size_t index = y * VGA_WIDTH + x;
	terminal_buffer[index] = vga_entry(c, color);
}
 
void terminal_putchar(char c) {
	terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
	if (++terminal_column == VGA_WIDTH) {
		terminal_column = 0;
		if (++terminal_row == VGA_HEIGHT)
			terminal_row = 0;
	}
}
 
void terminal_write(const char* data, size_t size) {
	for (size_t i = 0; i < size; i++)
		terminal_putchar(data[i]);
}
 
void terminal_writestring(const char* data) {
	terminal_write(data, strlen(data));
}
 
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void kernel_main(void) {
	/* Initialize terminal interface */
	terminal_initialize();
 
	/* Newline support is left as an exercise. */
	terminal_writestring("C");
}
exactly the same as the suggested kernel.c in the bare bones tutorial, but instead of "Hello, Kernel World!\n" it's "C", without any newlines, so this should work, and it compiled fine.

Why is my hardware rebooting?
If you're even asking for the motherboard:
H81 model, GIGABYTE vendor, UEFI.
I don't have an option to boot from UEFI on the USB.

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:27 pm
by glauxosdever
Hi,


Your bootloader is probably faulty. Do you even load your kernel from your bootloader?

However, as I said in another thread, my recommendation is to write your own bootloader and boot specification only after you have gained some more experience and have seen in what ways current bootloaders and boot specifications are suboptimal. For now, you should use GRUB in order to know more about it and not to repeat its design mistakes.


Regards,
glauxosdever

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:27 pm
by Roman
What do you think myos.bin contains?

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:31 pm
by NunoLava1998
Roman wrote:What do you think myos.bin contains?
I looked at it on the hex editor and i see ELF code, and it compiled successfully. Likely not corrupt.

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:35 pm
by NunoLava1998
glauxosdever wrote:Hi,


Your bootloader is probably faulty. Do you even load your kernel from your bootloader?

However, as I said in another thread, my recommendation is to write your own bootloader and boot specification only after you have gained some more experience and have seen in what ways current bootloaders and boot specifications are suboptimal. For now, you should use GRUB in order to know more about it and not to repeat its design mistakes.


Regards,
glauxosdever
Yes. My bootloader changes to protected mode, 32 bit after a 0x13 disk read into memory which doesn't really read the code. After that, it jumps to 0x7e00:0x0000, aka the second sector. I cannot use GRUB since my system literally goes "i'm done, go to main HDD" with GRUB.
I do load my kernel, and my img file which i writed using Win32 Disk Imager into my USB has the bootloader at 0x7C00 (aka the literal first sector, in a hex editor it's the first sector indeed), and at 0x7E00, there is the ELF code. It starts at 200 in hex, aka 513 in decimal.

TL;DR yes, did what GRUB usually does.
It is probably not faulty since the reboot garbage only occurs when you're in higher-lower level languages (or just C), and not Assembly, which my bootloader is written in. A assembly reboot does not display the "garbage".

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:48 pm
by Ch4ozz
Get a VM and test your stuff there before throwing garbage at your real hardware.
Getting GRUB to work on a real machine should be a matter of seconds by changing the boot order to USB first, works perfectly fine on all of my machines at home.
Also GRUB is a way more powerful then your bootloader, you should only write a bootloader if you really need it in case of security or flexibility.

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 12:49 pm
by glauxosdever
Hi,


Please answer these questions first so we know that you know what are you doing.
  • Do you load the kernel from a filesystem, or is it hardcoded to be in some sector, or...?
  • Do you parse the ELF binary format?
  • Did you change your linker script to make the entry point at 0x00007E00?
  • Are you sure 0x200 == 513?
  • Is being unable to get GRUB to work really a reason to write your own bootloader?
Otherwise you have just proven you are not ready for OS development.


Regards,
glauxosdever

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 1:06 pm
by NunoLava1998
glauxosdever wrote:Hi,


Please answer these questions first so we know that you know what are you doing.
  • Do you load the kernel from a filesystem, or is it hardcoded to be in some sector, or...?
  • Do you parse the ELF binary format?
  • Did you change your linker script to make the entry point at 0x00007E00?
  • Are you sure 0x200 == 513?
  • Is being unable to get GRUB to work really a reason to write your own bootloader?
Otherwise you have just proven you are not ready for OS development.


Regards,
glauxosdever
1: Hardcoded at sector 2 and can be expanded to the other sectors.
2: If you mean "enabling 32BIT and enabling the PE byte", yes. If you mean if i compiled it correctly, obviously yes lmao, and if you mean something else, no.
3: No, but the myos.bin is located at 0x7E00, meaning it probably isn't needed. I used dd.
4: Assuming byte 0 doesn't exist, yes. If byte 0 does exist, no, and 0x200 = 512. Normally, 0x200 would be 512, as most devices have a byte 0.
5: I can't use GRUB, it's not possible, especially in Windows. So i decided to write my bootloader, as that was the first idea that came to mind. And it worked. I mean, if it restarts in C mode, it likely worked (and the linker worked).

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 1:07 pm
by NunoLava1998
Ch4ozz wrote:Get a VM and test your stuff there before throwing garbage at your real hardware.
Getting GRUB to work on a real machine should be a matter of seconds by changing the boot order to USB first, works perfectly fine on all of my machines at home.
Also GRUB is a way more powerful then your bootloader, you should only write a bootloader if you really need it in case of security or flexibility.
I use the boot menu, and i have already tried to change it to the first option. Still doesn't work.

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 1:25 pm
by glauxosdever
Hi,

NunoLava1998 wrote:
glauxosdever wrote:Do you load the kernel from a filesystem, or is it hardcoded to be in some sector, or...?
Hardcoded at sector 2 and can be expanded to the other sectors.
Good to know that you know how is the layout on the disk. You passed this question.
NunoLava1998 wrote:
glauxosdever wrote:Do you parse the ELF binary format?
If you mean "enabling 32BIT and enabling the PE byte", yes. If you mean if i compiled it correctly, obviously yes lmao, and if you mean something else, no.
I meant parsing the ELF format, that is extract different information from it and load each section to the appropriate address. Giving you another chance on this question.
NunoLava1998 wrote:
glauxosdever wrote:Did you change your linker script to make the entry point at 0x00007E00?
No, but the myos.bin is located at 0x7E00, meaning it probably isn't needed. I used dd.
You load it there, but jumps in your code have references as if it was loaded at 0x00100000. You failed on this question.
NunoLava1998 wrote:
glauxosdever wrote:Are you sure 0x200 == 513?
Assuming byte 0 doesn't exist, yes. If byte 0 does exist, no, and 0x200 = 512. Normally, 0x200 would be 512, as most devices have a byte 0.
It hasn't to do with indexing. 0x200 == 512, always. You failed on this question too.
NunoLava1998 wrote:
glauxosdever wrote:Is being unable to get GRUB to work really a reason to write your own bootloader?
I can't use GRUB, it's not possible, especially in Windows. So i decided to write my bootloader, as that was the first idea that came to mind. And it worked. I mean, if it restarts in C mode, it likely worked (and the linker worked).
It will take more time to get a working bootloader than to get GRUB to work. And no, your bootloader didn't work. You failed on yet another question.


I apologise for all of this bittering, but I think you need to realise you lack a lot of knowledge needed to write a bootloader and/or an operating system.


Regards,
glauxosdever

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 1:31 pm
by NunoLava1998
glauxosdever wrote:Hi,

NunoLava1998 wrote:
glauxosdever wrote:Do you load the kernel from a filesystem, or is it hardcoded to be in some sector, or...?
Hardcoded at sector 2 and can be expanded to the other sectors.
Good to know that you know how is the layout on the disk. You passed this question.
NunoLava1998 wrote:
glauxosdever wrote:Do you parse the ELF binary format?
If you mean "enabling 32BIT and enabling the PE byte", yes. If you mean if i compiled it correctly, obviously yes lmao, and if you mean something else, no.
I meant parsing the ELF format, that is extract different information from it and load each section to the appropriate address. Giving you another chance on this question.
NunoLava1998 wrote:
glauxosdever wrote:Did you change your linker script to make the entry point at 0x00007E00?
No, but the myos.bin is located at 0x7E00, meaning it probably isn't needed. I used dd.
You load it there, but jumps in your code have references as if it was loaded at 0x00100000. You failed on this question.
NunoLava1998 wrote:
glauxosdever wrote:Are you sure 0x200 == 513?
Assuming byte 0 doesn't exist, yes. If byte 0 does exist, no, and 0x200 = 512. Normally, 0x200 would be 512, as most devices have a byte 0.
It hasn't to do with indexing. 0x200 == 512, always. You failed on this question too.
NunoLava1998 wrote:
glauxosdever wrote:Is being unable to get GRUB to work really a reason to write your own bootloader?
I can't use GRUB, it's not possible, especially in Windows. So i decided to write my bootloader, as that was the first idea that came to mind. And it worked. I mean, if it restarts in C mode, it likely worked (and the linker worked).
It will take more time to get a working bootloader than to get GRUB to work. And no, your bootloader didn't work. You failed on yet another question.


I apologise for all of this bittering, but I think you need to realise you lack a lot of knowledge needed to write a bootloader and/or an operating system.


Regards,
glauxosdever
2: Probably not, maybe i will go assembly all the way and build a C interpreter later.
3: Except you do not need to do "ORG 0x0100" or something (that won't work). You need to do "ORG 0x0", which fortunately by default compilers do include, so it's a "yes", most likely.
4: I do know 0x200 is 512. And it is, you're correct, i was half correct.
5: Hey, the bootloader does work most likely.

Re: C code rebooting for no reason

Posted: Sun Oct 23, 2016 1:44 pm
by glauxosdever
Hi,

NunoLava1998 wrote:Probably not, maybe i will go assembly all the way and build a C interpreter later.
So you will use assembly just because you can't parse ELF (and you wouldn't need to do it if you used GRUB)? You can still request your toolchain to convert the ELF to a flat binary.
NunoLava1998 wrote:Except you do not need to do "ORG 0x0100" or something (that won't work). You need to do "ORG 0x0", which fortunately by default compilers do include, so it's a "yes", most likely.
And I was talking about the kernel code, which is linked to 0x00100000 according to the linker script, and not 0x00007E00 where you are loading it.
NunoLava1998 wrote:I do know 0x200 is 512. And it is, you're correct, i was half correct.
No, you were plain wrong. 0 can't not exist.
NunoLava1998 wrote:Hey, the bootloader does work most likely.
Can it successfully pass control to the kernel? No, therefore it does not work.


Regards,
glauxosdever

Re: C code rebooting for no reason

Posted: Mon Oct 24, 2016 1:17 am
by FusT
I'm with glauxosdever on this.

I really think you should put more effort in getting GRUB to work on your system, perhaps using a linux VM. Writing a (good) bootloader is like writing an operating system of it's own.
Also, get yourself an emulator/simulator with good debugging capabilities (like BOCHS) and actually check where your code reboots the machine/outputs garbage.

I'm not trying to sound condescending but I too really think you are missing some basic skills/knowledge to be able to write an operating system. The motivation is there but your current approach (shotgun debugging/copy-pasting from SO) is not going to get you anywhere fast.

Just my 2 cents

EDIT:
Thought i'd also be constructive on the problem.
I'm 99% sure it's not the C code that causes the reboot, but an error in your custom bootloader (e.g. one of the things glauxosdever pointed out on relocation and ELF parsing).

Re: C code rebooting for no reason

Posted: Mon Oct 24, 2016 2:19 am
by iansjack
Contrary to your subject heading, there is a reason why your code is rebooting. Accept that simple fact and you are on the way to solvng your problem.

A virtual machine and a debugger (Bochs or qemu + gdb) will be a great aid in helping you determine where the fault lies. Finding it may even teach you something.

Re: C code rebooting for no reason

Posted: Mon Oct 24, 2016 5:43 am
by Roman
I looked at it on the hex editor and i see ELF code, and it compiled successfully. Likely not corrupt.
So do you think an ELF file can be simply executed with JMP?

BTW, writing a C interpreter is comparable in complexity to writing an OS.