2013-09-26

2013-09-26 The Command Interpreter and stdin.

I've linked the C library into the kernel so that I can use the standard C library functions in the kernel to simplify development and moving code from the kernel to programs.  I've written a routine to tie up all the kernel API calls so that the kernel doesn't have to use system calls to resolve its own symbols like a lowly program.

I've pulled the command interpreter out of a previous test kernel (this one dates back to 2005, wow) and started to rewrite it to use the standard C library functions.  That way it can be in the kernel for now, then be pulled out into a separate program later.

For the console, I obviously need a keyboard handler and a way to "open" the keyboard.  It might be worth setting up a proper file descriptor table and pulling the DOS layer from the DriveAccess kernel (circa. 2010) and actually making it a proper device that can be opened by name.

2013-09-22

2013-09-22 It says "Hello World!"

After spending quite a bit of time debugging the ELF loading, the test program being loaded into the kernel is able to output to the stdout stream and to have that written to the screen.

I finally managed to debug all the relocation gubbins and track down all the stupid mistakes (which were stupid).  From the forgotten "ret" at the end of "_start" (which made it try to run the program again), to the loop in write() which accidentally printed the characters backwards.  It's all been ironed out

I know it seems as if it's taken a long time to get the Hello World! stage, but the way that it's showing the Hello World is very complete as far as how finished kernels do it.

The Hello World program itself is identical to a Hello World program in C for any other OS.  This conversely means that any program that only outputs text to the screen can be compiled up against my C library and run on my OS now.

With a little bit more work, the kernel is now able to pass command-line arguments to the program, so I can make an Echo program as well.

Of course, the set of programs that only output text to the screen is fairly limited, so my next task is to get the keyboard wired up to stdin in some way so things can be a bit more interactive.

2013-09-15

2013-09-15 Displaying Images in 16 Colours

I've added a new page that discusses colour mapping and error diffusion to a 16 colour palette.  This is based on a test kernel I developed back in 2011.

After posting the page, I did notice that there are some strange data errors in the output images (a line of incorrect pixels toward the bottom right corner) but I'm reasonably certain that's just Bochs and I disagreeing on who should be using that memory.  The same problem is not exhibited on real hardware.


2013-09-14

libc, crt0, and What Executables Do When They Start?

One of the articles I found while I was investigating bootstrapping executables was Hello from a libc-free world!.

This article gets a special mention because of how detailed and well-written it is, and how it's one of very few articles I was able to find which actually discusses this topic in detail with worked examples and explanations.

If anything here is interesting, then that article is definitely worth a read.

2013-09-13

2013-09-13 ELF Relocatable Executables

Last night I added an article about ELF Relocatable Executables, and as I was talking through it with Pink today, we came to the conclusion that getting the arbitrarily linked executable with relocation information (the one generated by --emit-relocs) was the best way to go.  If I take this approach, as I load each section, I need only store a single value for each which indicates the difference in memory address between where it was supposed to be loaded and where it ended up.  With this table, I could then parse the relocation table and just add the offset for the corresponding section to each relocation value.  Things are slightly more complicated for relocations which are Program Counter Relative in the code, but not hugely so.

Working on the ELF loader some more.   Originally it was a COFF loader which worked on the premise of there being one text section, one data section, and one BSS section, which is what DJGPP was generating for me at the time.  I'm now rewotking it to be less of a COFF-loader-adapted-to-ELF and more ELF friendly.

I've had to change a number of elements to change what was an ELF library loader to load executable files with relocation information in them.  After many hours of stepping through each section as I was modifying it, it has completed a first attempt.  All the signs look good that it loaded the executable, and performed the relocation to correct the file for where it was loaded, and called into the entry point.  The System Call interrupt handler fired, now just to see why it didn't seem to print the message.

libs_libraryDefinition at 0x40003C
LibraryNode: 0x0
LibraryName: 0x0
LibraryVersion: 0x0
LibraryLength: 0x0
SymbolTable: 0x4000CC
SymbolCount: 0x13
StringTable: 0x4001B0
EntryPoint: 0x4002B0
SectionCount: 0x16
  Section[0]: 0x0   Section[1]: 0x400294   Section[2]: 0x0
  Section[3]: 0x4004A1   Section[4]: 0x4004C0   Section[5]: 0x0
  Section[6]: 0x400670   Section[7]: 0x400670
--------------------------------------------------------------------------------
Interrupt 48 at 0x40044F
--------------------------------------------------------------------------------
0x10B8C0                                       B5 BE 02 00                µ¾..
0x10B8D0   B4 BE 02 00 38 B9 10 00 EC B8 10 00 20 BD 02 00    ´¾..8¹..ì¸.. ½..
0x10B8E0   D5 03 00 00 03 00 00 00 00 00 00 00 30 00 00 00    Õ...........0...
0x10B8F0   00 00 00 00 4F 04 40 00 08 00 00 00 06 02 00 00    ....O.@.........
0x10B900   D1 1D 10 00 88 42 10 00                            Ñ...ˆB..
SysCall
--------------------------------------------------------------------------------
-- Fin --

Ok, I've confirmed that it's gotten the resolve() function, and called it get the read, write and lseek API functions.  write() is then being called, but it's being called twice, once with a gibberish file descriptor, and once with 0.

I've put in the code to initialise the stdout FILE structure (oops), but it's still not calling write() with the correct parameters, and seems to sometimes spin off into the weeds.

There's probably something wrong with the relocation, maybe if I dump the RAM from the emulator and disassemble it to see if everything ended up as it should.  But probably tomorrow.

So as I've now fixed up the FILE structure for stdout, this has created relocations for the .data section.  What are the chances I'm not processing them?

2013-09-05

2013-09-05 Loading ELFs (Elves?)

So I copied the ELF loader from a previous kernel into this one, compile errors akimbo because it was already there, n00b!

The previous loader loaded the ELF binary and maintained a symbol table so that I could resolve library symbols.  Because I want it to load executables, I added a wrapper function to load the ELF binary as a library, then call the entry point, then free the memory.  It's crude, but it'll demonstrate loading the elf file.

First attempt threw an interrupt 13 (general protection fault), which is odd as there shouldn't be any protection on the memory (and my code should all work first time anyway).  This showed two problems, malloc() returned 0 (which I wasn't trapping) and I hadn't loaded the GDT so it was running with whatever GRUB loaded.

Got the GDT loading code from the earlier kernel ("DriveAccess") and got that part fixed.

Now back to the malloc.  Oh, wait, maybe I should use the kmalloc(), rather than the unimplemented libc malloc() (which is hard-coded to return 0 currently) ... sad face.

Ok, stupid errors fixed up, it claims to be loading the ELF file ...

2013-09-04

2013-09-04 Command Line Tools

While I'm developing the helloworld executable as a project inside NetBeans, I did start to wonder if each of the commands I want to implement in the basic command set would be projects in their own right.  Most of them are only going to be a main.c file with a few functions, so I could just create a c file for each one under a project called Commands or something, then customise the makefile to build each into a separate executable.  Not sure what NetBeans would think of this though.

Looking through the list of commands available in standard command line interpreters, I think I'll need to consider implementing the following commands (probably in this order):

helloworld - :D
echo - Tests command line arguments
type - Tests reading files

ls - Tests reading directory information
more - Tests command piping and buffering
screen - Combines the command interpreter and more
touch - Tests creating a file
copy - Combines type and touch
join - Combines type and touch
mkdir - Tests creating a directory
rm - Tests deleting a file
move - Combines copy and rm
head - Extends more
tail - Extends more
od - Gives a more consistent for my memdmp() function.

Next step is to remove all the reference to the libc stuff from the kernel so that I can link in the single libc.  This will mean I need to add some form of define so that when the library is linked with the kernel, it uses a special function to associate the various kernel functions (read, write, etc.) directly, rather than using the method that executables use.