Page 1 of 1

Following James's Kernel Tutorials on Mac OS X

Posted: Thu Jan 10, 2013 1:54 pm
by Kirk
I just started with kernel development and James's kernel development tutorials are great, easy to read and easy to follow, many thanks for that. However, the makefiles, linker scripts etc.. are all designed to work on linux. I used to do the development on my linux virtual machine. However I no longer found that statisfying so I thought I'd try doing this on mac os x. It took a lot of work to make everything work but now I did. I here by share what I've learned. This might be useful for others.

The first problem is that Mac OS X executables have Mach-O header and Linux executables have an ELF header. Also, Mac OS X is a 64-bit operating system and James's tutorials are based on x86. The linker that is installed by default is not the GNU Linker and thus does not support various options such as -T.

To fix this we should first install Mac Ports to make installing some ports a bit easier. Mac ports can be found here:

http://www.macports.org/

Now we need to install i386-elf-gcc and i386-elf-ld by issuing the following command:

Code: Select all

sudo port install i386-elf-gcc i386-elf-ld
Note: These are installed to /opt/local/bin

We now need to modify the makefile:

Code: Select all

SOURCES=boot.o main.o

CC=i386-elf-gcc-4.3.2
CFLAGS=-nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -c
LDFLAGS=-Tlink.ld -melf_i386
ASFLAGS=-felf

all: $(SOURCES) link

clean:
	-rm *.o kernel

link:
	i386-elf-ld $(LDFLAGS) -o kernel $(SOURCES)

.s.o:
	nasm $(ASFLAGS) $<
The second problem is that the losetup command used in the two bash scripts is not available on Mac OS X. Update update_image.sh as following:

Code: Select all

loc=`hdid -nomount ../bin/floppy.img`
`sudo mount -t fuse-ext2 $loc /mnt2`
cp ../bin/kernel /mnt2/kernel
umount /mnt2
And run_bochs.sh:

Code: Select all

loc=`hdid -nomount ../bin/floppy.img`
`sudo mount -t fuse-ext2 $loc /mnt2`
sudo bochs -f bochsrc.txt
Now you might have noticed the use of fuse-ext2. Mac OS X does not come with ext2 drivers by default (And the floppy from Jame's tutorial is formatted with ext2). I used fuse-ext2 from here:

Code: Select all

http://sourceforge.net/projects/fuse-ext2/
Now there's another problem because read-write support is not enabled by default for fuse-ext2, to fix this open /System/Library/Filesystems/fuse-ext2.fs/fuse-ext2.util in any text editor and scroll down to line 207:

Code: Select all

OPTIONS="auto_xattr,defer_permissions"
and change this to:

Code: Select all

OPTIONS="auto_xattr,defer_permissions,rw+"
The final thing to do is update the bochsrc.txt:

Code: Select all

memory: guest=32, host=32
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-elpin-2.40
floppya: 1_44=floppy.img, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
clock: sync=realtime
cpu: ips=500000
However make sure you have BIOS-bochs-latest and VGABIOS-elpin-2.40 in those locations. Big chance you don't have them, you can download the them from git hub:

https://github.com/larsr/bochs/tree/master/bios

If you are using Mac OS X Mountain Lion (10.8) you should install XQuartz as a replacement for x-11:

Code: Select all

http://xquartz.macosforge.org/landing/
I hope this information is useful to somebody. On a site note to James, the bochsrc.txt configuration used in your tutorial is a bit outdated.
Instead of using /dev/loop0 you could also refer directly to the floppy image. Also vgaromimage: must start with file=. And megs is outdated and is
replaced by memory.

Re: Following James's Kernel Tutorials on Mac OS X

Posted: Thu Jan 10, 2013 2:06 pm
by sortie
I would recommend that you build your cross-compiler yourself - it's a good learning experience (how do I build a compiler?) and you don't depend on your distribution (macports) shipping the right version. It may be wiser to build a cross-compiler for i686 (or i585 if you still target those) since older machines are becoming rare. It'll allow the compiler to use some useful instruction that simply did not exist back in the day of i386.

Code: Select all

-nostdinc -fno-builtin
Add back -fno-builtin immediately! GCC provides a lot of builtins and it's _good_ to have them around. I don't recall whether -nostdinc also surpressed some compiler-provided headers, such as <stdint.h>. Personally, I don't pass -nostdinc because my kernel actually relies on my homemade libc (a cut-down version of it). (-nostdlib is fine, for the record)

Code: Select all

-m32
This is not needed since i386-elf-gcc already defaults to 32-bit.

Code: Select all

-melf_i386
This shouldn't be needed either.

Note that his tutorial doesn't use a real cross-compiler, which is why he adds these awful flags to the command line. You don't need all of them when cross-compiling properly. Please correct me if I am wrong, I don't do Mac development myself.

Re: Following James's Kernel Tutorials on Mac OS X

Posted: Thu Jan 10, 2013 3:30 pm
by Kirk
While I was posting this I just started reading the article on building a cross-compiler on the wiki and I'm halfway trough now :) Anyways thanks for the tip, it's better of course.

I don't exactly know what you mean with:
Add back -fno-builtin immediately!
Do you mean I should drop those flags or keep them? I would like to note that they are exactly the same as in James's tutorials, the Makefile is a direct copy.

Ah thanks for the tip on dropping the -m32 and -melf_i386 flags, should be obvious why.

Re: Following James's Kernel Tutorials on Mac OS X

Posted: Thu Jan 10, 2013 5:43 pm
by sortie
Whoops, the negation in -fno confused me. I meant that you should not pass -fno-builtin (and -fno-stdinc is up to discussion, but since it can't really go wrong with a cross-compiler, I'd leave it out).

Yep, copying the makefile blindly is a bit bad in this case, because the author is not using a cross-compiler and uses some special flags that's not needed (and potentially create problems). Also, if you are doing a cross-compiler, be sure to build libgcc as well. It should work out of the box on freestanding platforms and GCC uses it to off-load some things (such as 64-bit division on 32-bit platforms, and more!).

I see that you are using nasm. Note that if you build a real cross-toolchain (cross-binutils and cross-gcc), you get a cross GNU assembler as well. It also doesn't need to be given any extra flags to make it emit for the desired architecture (as told by --target at configure time). Some people prefer the Intel syntax (NASM, ...) and others prefer the AT&T assembler syntax (GNU as). While it doesn't matter much which you are using, try have a look at both and see what you favor. Note that the GNU assembler works well with the rest of the toolchain (gcc, objdump, ...) and all of those use the same assembler syntax (AT&T).

Re: Following James's Kernel Tutorials on Mac OS X

Posted: Fri Jan 11, 2013 12:57 pm
by Kirk
I chose for NASM (At&t syntax), simply because I find it easier to read.

Re: Following James's Kernel Tutorials on Mac OS X

Posted: Fri Jan 11, 2013 3:19 pm
by Griwes
NASM is Intel, not AT&T; you got it backwards.