|< << 3 of 3 >> >|

Brief update on Metta

I've been working on toolchain building script, now at least on Macs it's possible to build a standalone toolchain for building Metta and you can download it and try to build it yourself. All necessary details are descibed on SourceCheckout wiki page. There is followup work to remove dependency on binutils and gcc (gcc will probably go first, then once lld is mature enough I could get rid of ld/gold).

Another update is about type system. The operations on type system are implemented now, I can successfully register type information and query it - some examples of that are in the recently released iso image R925. Next up is fixing some of naming context operations so I can actually create and operate hierarchical naming contexts.

Type systems and introspection

Since I've decided to approach the system development from both low-level and high-level perspectives, one of the applications I have in mind for demo purposes is a little console tool which lets you activate various parts of the system, list available services and call operations on available interfaces.

Imagine a little tool that allows you to pick a video file, seek it to a particular time and play it frame by frame, then run face recognition on each frame and make a database of recognized faces. Being able to make such applications "mashup style" by just fiddling with text and pictures in the command line should enable people to create more and more interesting tools from the basic building blocks presented by the system.

This tool would need to inspect installed interfaces and types of the running components and be able to construct calls to these components directly from the command line. This requires introspection, or the ability to describe structure of objects in the system.

At the moment I'm working on the extension of meddler that allows to generate introspection data from the interface IDL. It is generally simple and then the next step would be to somehow register this information in the system when a new interface type is introduced. This is harder and requires some design effort. In the first approach of course only boot image is loaded, so registering types is very simple.

Next up is actual introspection interface - how to know what format a particular data type is and how to marshal/unmarshal it for the purpose of interchange and operations calls on interfaces.

See this little script for the possible demo storyboard.

Sending network packets

A little sidetrack into the world of PCI probing and NE2000 network card emulation.

Wanted to have a taste of sending and receiving network packets inside my little OS, so I went and implemented PCI scanning (extremely simple) and NE2000 card driver (fairly simple too, their doc is quite good although misses some crucial points).

So, after some fiddling I was able to send a packet and receive it through the bochs virtual network card. I've then connected bochs to the host network card and stared at network packets for a while. Cool stuff.

Here's the screen dump of the sent and then received broadcast packet.

IRQ11 enabled.
Finished initializing NE2000 with MAC b0:c4:20:00:00:00.
Received irq: 0x0000000b
Packet transmitted.
Packet received.
Received packet with status 33 of length 68, next packet at 82

0x004f0064  ff ff ff ff ff ff 28 cf  da 00 99 f5 00 10 48 65  ......(.......He
0x004f0074  6c 6c 6f 20 6e 65 74 20  77 6f 72 6c 64 21 00 00  llo net world!..
0x004f0094  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................

sjlj and exception handling

Of course, the clang's implementation of setjmp is very generic and uses quite an abstraction of program state, which makes it hardly suitable for the ad-hoc local exception support I'm using. Since my requirements for setjmp were quite simple (just give me back my damn registers and stack frame), I went and implemented a very custom-tailored versions __sjljeh_setjmp and __sjljeh_longjmp which do just what I need.

With that stuff out of the way, my entire boot sequence now works and I can finally fiddle with more interesting stuff. Type system and introspection, here we go.

Bret Victor's Kill Math

Bret Victors Kill Math

How to stop worrying and love your visualization tools.

Optimizations

The reason for not booting was simple - Clang, seeing that target is Pentium 4 and above, optimized some memmoves into SSE operations. Bochs didn't expect that.

Now everything boots up until exceptions, at which point I believe the __builtin_longjmp primitive fails. Debugging it.

Clanged now

Anyway, I've done doing the craziest port of recent times - at the same time GCC to Clang and from waf 1.5 to 1.6.

Quite a bit of quirks to work around.

waf has changed a lot internally, and from occasional backtraces I still see that I'm using compatibility mode somewhere. Oh well, one day when I'm bored…

Clang is also full of quirks. First, I had to build a cross-gcc for it anyway, because otherwise it totally refuses to link or assemble anything. Second, the freestanding standard C headers are not quite finished it seems - stdint.h for example spits out about 20-30 warnings about redefined macros, so I had to disable -Werror for now just to get it to compile. Third, the generated code, obviously, doesn't run. I got only first couple functions of kickstart bootloader to work in bochs, after that it just GPFs. Now if it keeps raining tomorrow like today, I'll certainly will go and look what happens there, otherwise it might have to wait until next weekend (actually, in two weeks).

Magic Ink

Magic Ink

Highly recommend this read to all programmers and designers. Very inspirational.

It intersects with Metta's ideas of supporting creativity freedom, and is written a lot better than I could ever dream to write myself.

Font rasterization theory and techniques

Font rasterization theory and techniques

Metta MMU module init

MMU initialisation

First off, we start by loading the needed modules - mmu_mod, frames_mod and heap_mod.

mmu_mod will allocate and map the first chunk of memory to use. It does so without knowing much about memory allocation - just takes a first fit chunk from the physical memory map, passed to us by the bootloader. Parts of this memory will be used by frames_mod and heap_mod as well, so we need a way to know how much memory they would need.

Read more →

A historical moment

OMAP3 beagleboard.org # mmcinit
OMAP3 beagleboard.org # fatload mmc 0 0x82000000 kernel.bin
reading kernel.bin
640 bytes read
OMAP3 beagleboard.org # go 0x8200024c
## Starting application at 0x8200024C ...
hello, world!
## Application terminated, rc = 0x0

Metta progress report one

I have cleaned up the booting mess more or less and now my loader is able to enter the root domain - the startup component, which initialises all other components in order and passes control on to userspace loader component, which is supposed to finish system initialisation by starting up all user interface services.

Now there are pretty many loaders here already - there's a first stage loader which is either GRUB or some other kind of boot loader, next there is second stage loader which understands boot protocol, be it multiboot or Linux-style boot or something else and converts all information to format understood by kernel startup, which in turn parses the info from bootinfo page and sets necessary flags, configures necessary platform hardware, prepares memory structures like IDT and GDT and then launches the root domain, which in turn loads all startup modules, initialises them and passes control on to userspace startup component. This is 5 startup stages in all.

Now the design decision in modular system with C++ implementation is separation of component architecture and OO implementation. In component system, nothing is known about component implementation outside of the component and C++ implementation details break at component interface boundary - we want to confine implementation details inside component and expose only a C++ representation of public interface.

Therefore, C++ implementation breaks down to 3 essential parts: C++ implementation, in whatever level of detail we want, from very simple to complex elaborate designs, this is invisible to client code. Second is a thin C-style component interface layer. It is so thin, that I do not want to mess with it manually and it is generated by the IDL stub compiler, meddler. It is also able to generate the third piece - C++ wrapper around C interface that can be used in appropriate way by C++ clients.

Since meddler is still in the works, I generated some C interfaces manually for testing and now implement the memory management components behind those interfaces. Seems to be fairly interesting, since in pre-component design the C++ interfaces were directly exposed to client code and it was fairly easy to change public interface by simply declaring new methods public or private. It was also fairly easy to screw things up, because C++ exposes way too much to clients by default. This is different in component world, you have to be careful with how much of API you expose to clients - what is exposed once remains with this version of interface and has to be supported. Thankfully, I have versioned interfaces and this liability is not forever. On the bright side, only what you exposed will be seen - this makes client interface much thinner and cleaner.

Now on to MMU, frame allocator and stretch allocator implementations.

To remain the web weavers

To remain the web’s weavers and not its ensnared victims, we must merge with our electronic exocortex, wiring greater memory, thought processing and communication abilities directly into our brains.

James Hughen

|< << 3 of 3 >> >|