Me, Operating Systems, Technology, Sun Microsystems and Stuff!

MouthOS gets kmem_alloc()…

June 8th, 2008 Michael Clarke

At last it has happened! I have been putting off writing my memory allocator for MouthOS for some time. Up to now I’ve been able to survive without one by simply not having any ‘undefined’ data structures - everything in the kernel was a known, static size.

So after a interesting Solaris Advanced Crash Dump Analysis course last week (which has really put me back into my OS development mood) I decided it was time to make a move and I spent a large portion of Friday night working out how to allocate memory without overwriting the existing kernel, and at last by about 2am in the morning having messed around with the linker and some cleverly placed assembly labels I finally was able to kmem_alloc() some memory.

At this point I decided I was finished and went to bed. The next morning I awoke, pleased to have kmem_alloc() working, or so I thought. However, as the day progressed and I allocated more and more pages of memory I started to see some strange things happening. Why did that character on screen just go red? I never put a start on the screen…

After a fair amount of time debugging the issue I managed to isolate the problem. My array of free_pages_t structures were located, not at the end of the kernel stack as I thought (which is currently 8K), but in the last 1K of the stack. Ultimately the problem was a off by one (er, or 1024 depending on how you look at it) error in my programming. At last I was able to kmem_alloc() pretty much as much memory as  I wanted - but how to free.

This proved to be very easy. I simply modified my page_map_t structure to contain a grouping id. As such, when we call kmem_free(void *) we do the following to first make sure that the address we got was on a page boundary.

	while ( (addr % (PAGE_SIZE * 1024) != 0 )
		addr--;
	while ( page->addr != addr )
		page = page->next;

Now we’re on a page boundary we can just loop through the pages whilst the alloc_id’s are equal and set the flags to PAGE_FREE…

	int alloc_id = page->alloc_id;

	while ( page->alloc_id == alloc_id ) {
		page->alloc_id = 0;
		page->flags &= PAGE_FREE;
		page = page->next;
	}

With that working I then spent a bit more time perfecting and tweaking and now MouthOS is pretty good at allocating and freeing memory - at least, I think it is anyway. In the end it turned out not to be so difficult - you just have to get your head around the whole idea of allocating memory, before you have an allocator. When I thought about it this ended up not to be such an issue after-all….  Here is how we can do it.

  1. You know the point where your kernel loads.
  2. You can work out where your kernel ends by putting a label in its own section, and then using the linker to put that section at the end of the kernel.
  3. You now know (from the placed label) where a safe place in the memory is to write without overwriting the existing kernel, so write all your required memory structures, of which you can calculate how many you need from the amount of memory in the system.
  4. Finally,go back to your memory structures that you’ve just written and mark all the kernel space as allocated, including the space the memory structures take - which you know as you know the size of a memory struct, you know where it starts, and you know how many you’ve got.

Easy :) You can find the code for the new MouthOS memory allocator at: http://www.michael-clarke-blog.com/trac/MouthOS  -  if you’re remotely interested :p

Until next time.

MouthOS Trac Website

May 16th, 2008 Michael Clarke

It’s taken me some time to gather the enthusiasm to do this - but I’ve finally moved my MouthOS source over to my web server and installed trac. So, you can view the MouthOS wiki and source at:

http://www.michael-clarke-blog.com/trac/MouthOS

The older versions are in /proto. Kernel version 0.0.1, 0.0.2 and 0.0.3 are broken with some pretty big bugs (for such small programs) such as triple faults and Kernel panics.

The most stable version at the moment is version 0.0.03 in /releases.

The stuff in /trunk is the current development with all the new HAL (Hardware Abstraction Layer) stuff. I’m still in the process of porting a lot of the proto-0.0.3 and releases-0.0.3 stuff to /trunk - so this is pretty useless at the moment :( But you’ll get the general idea as to where the project is heading from /trunk in terms of the HAL, Memory Management etc.

At some point I’m also going to add anonymous svn access so you’ll all be able to checkout the source code and have a play - but at least for the moment you can view the code, the wiki etc.

For the moment - enjoy :)

Paging support for MouthOS

March 12th, 2008 Michael Clarke

This week I’ve been on the Solaris Internals course at work and I’ve already learnt an awful lot about how Solaris deals with processes (including threads and light weight processes), system calls, scheduling, memory management (hardware and software), paging and swapping! All of this and it’s only 3 days in.

However, one of the things about this is I’ve very quickly realised how far I’ve still got to go with MouthOS and how much I’ve still got to learn. A great example of this is in regards to memory management… Intel, it would appear, offer two different methods of dealing with memory - segmentation and paging. It was my impression that you could basically choose which you wanted to use when writing your OS and so I decided to use segmentation for MouthOS initially.

Unfortunately the Solaris Internals course has given me a bit of a rude awaking - I’ve realised that in order to use Paging you must first enable Segmentation. However, there are many different ways you can section off your RAM before you even get to paging….

Flat Model (which is what I’m going to be changing to) is where you basically say all of the address space (i.e. 32Bit address space is 4GBytes, even if you system only has 2GBytes) can be used for anything with no restrictions on who can do what - i.e. there is no hardware translation of memory accesses in regards to segments. When I say ‘no translation’ that’s not strictly true… because you still have to specific a segment in the GDT the processor will basically prefix every memory address with 0, so the effect is that there is no ‘translation’ but at the same time there is!

There is obviously a problem with this - if I have a process running, and paging isn’t enabled, and I try and access more than 2GBytes of memory from my process it won’t actually physically exist. However, because there are no checks - no exceptions will be raised and your system is likely to fall over pretty quickly. If you’ve got paging going on then there is no problem, a page fault will be generated and the kernel can load in the appropriate page somewhere else.

Protected Flat Model (which is what Solaris, Linux etc use) is where you limit the segment size to the size of the Physical Memory. In other words, instead of providing your processes with the fully available address space, you provide them with an address space that matches the amount of physical RAM. As such, if anything tries to access a memory address greater than the physically available memory a general protection exception will fire and the kernel will be able to deal with it.

Generally when using the Protected Flat Model you would have 4 sections. 2 of these sections will be in Ring 0 and two will be in Ring 3. Ring 0 is the Kernel ring and the two sections will define the text and data sections. It will start at memory location 0 and proceed to the maximum memory location available in physical memory. I.e. 0 -> 2MBytes. The LDT in Ring 3 (user space) will start at 0 + size of kernel and will end at the maximum memory location available in memory.

For example, assuming the Kernel is 2MBytes and the available RAM is 2GBytes, the LDTs would be along the following lines:

Section            Ring		Protection            Base            Offset
TEXT                0  		r-x                   0               2GBytes
DATA                0           rwx                   0               2GBytes
TEXT                3           r-x                   2MBytes         2GBytes
DATA                3           rwx                   2MBytes         2GBytes

This prevents anything which runs in Ring 3 from ever touching the first 2MBytes of memory where the Kernel is stored, however, the Kernel running in Ring 0 can access its own structures and text, and that of Ring 3 also.

Multi-Segment Model basically uses a similar principle to the protected flat model except it adds yet more sections, this time as many as you could care to imagine - each one defining text, data, bss, stacks, heap sections which are available for individual processes and even thread within a process.

Once you’ve sorted out your segmentation, reading my ‘Intel 64 and IA-32 Architectures Software Developer’s Manual’, enabling paging seems to be relatively simple. From what I can tell I need to setup a page directory, pass the memory location of this page directory to cr3 (control register 3 - which actually acts as a context register) and then set bit31 of cr0 (control register 0) to 1… dah da! Oh, and then of course I’ll have to sort out all the other entertaining things such as a page_fault() handler for when we get a request for a page that isn’t currently in memory - however, for the moment I think I’ve got quite enough to be getting on with.

So far my beautiful “proc_enable_paging” assembly routine is looking a little bare….

  proc_enable_paging:
                mov eax, cr0
                and eax, 0x80000000 ; Set bit 31 (PE) = 1.
                mov cr0, eax
                ret

MouthOS Development Environment

February 12th, 2008 Michael Clarke

After my French explorations I booked Friday off and went home for the weekend. I had a nice time back in sunny Wales except for the fact that my family had literally managed to break every single computer in the house - and when I say break, I don’t just mean a few viruses or malfunctions, I literally mean motherboards broken, screens damaged, graphics cards frizzled and who knows whatever else. By the end of the weekend I’d managed to pull the few working parts remaining into two systems - the server (which for the most part was working to begin with except that it wouldn’t boot because it couldn’t find the floppy disk drive) and a computer upstairs for everything else. To be fair I think they’ve had some kind of power surge as one computers PSU fuse had blown along with the fuse in the plug… I think they now plan on buying a few surge protectors :p

When I returned today Paul (my boss) asked for a quick chat in the office. He had some not so great news and some excellent news for me. The first bit of news was that the presentation he and I were going to do at Sheffield university had been taken over by some other guys in the office. This turned out not to be so bad after all as I realised that it was the 29th February anyway - at which point I’m back off home anyway for my sisters 5th birthday. However, the good news (which is very good indeed) is that he has managed to get one of the guys in the Solaris Kernel Engineering department (who works with DTrace) to mentor me (after showing him some of the stuff I’d been doing with MouthOS) for my last two years at university. During this time I will be doing things like fixing DTrace bugs via the Open Solaris community - opening some real possibilities for when I finish to come back and work for Sun in their Solaris engineering department! I’ve got a meeting at 11am tomorrow morning with Jonathan, my mentor to be, which I’m really looking forward to as I’m raring to go and I really can’t wait now until the 10th March when I will be going on the Solaris Internals course - thanks Paul :)

So, what else has happened over the last few days? On Thursday I got another phone call from ‘Private’ offering me a new phone. I keep telling these people that “I’m not interested and that I’ll deal with Orange directly thank you very much.” However, this prompted me to actually ring Orange and see if I really was entitled to a new phone. The answer was no, not really, but we’ll give you one anyway. Apparently these companies will ring you up, offer you a contract and then (only then) contact Orange to see if it’s going to be alright! The cheek!

Whilst I was on the phone I did say I wanted the Nokia N95. However, they wanted £89 for it. Instead I said I’d have the LG Shine (http://www.lgbloggers.com/)… this was fine except it was out of stock. In the end I decided on the Nokia 6500 Slide (in black which is apparently a Orange exclusive). So far I have been most impressed with the phone. However, as with all new gadgets it’s a requirement to test out every feature it has to offer, one of these features being the camera. I decided that it would be a good idea to take a couple of pictures of the MouthOS development centre (i.e. my desk)…

My desk

The books on my desk...

I have to admit that whilst I would love to be able to say that all of those books are mine, only the top C book and the bottom three Intel books are truly mine - the others are on loan from my house mate and friend Robin. However, I highly suspect that I will be buying my own copies before I have to give them back to him as they have been really useful for ideas and all that malarkey during the development of MouthOS so far - I think another thank you is in order - thanks Robin.

The FAT File System and PrePay Credit Cards

January 21st, 2008 Michael Clarke

I’m sure that if you’ve read the title for this entry you’re most confused as to what the FAT file system has to do with PrePay Credit Cards. I have to admit that if I were in your position I would also be confused, indeed I have now confused myself in an attempt to see if there are any similarities, the answer to which I have concluded to be that there are none, other than perhaps they are both mentioned in this entry and have already taken up far too much space - having successfully distracted me totally from the originally point of this blog entry.  Good Oh!

I suppose I ought to explain. Last week I decided, in my infinite wisdom, that it might be a good idea to get one of these ‘PrePay Credit Card things’ that seem to be taking off. The idea is very simple. You buy a card (Visa, MasterCard or Maestro) and top it up with money online, via another credit/debit card, in the post office, or using top-up points in shops. Having done this you go out and spend all your money in places where normal debit cards are not accepted - one such example being hotel and flight reservations etc. As far as everyone who views and uses the card is concerned you’ve got a bog standard, normal credit card… as far as you’re concerned it’s the best credit card ever as you don’t have to pay anything back!

I think there are a number of focus groups for these cards. Those people with poor credit history who can’t get a credit card. Those people who don’t want a credit card - but need an alternative for paying for hotels, flights, hire cars etc, and teenagers who want a more ‘modern’ way of dealing with their pocket money/paper round wages. Personally I decided that getting one of these cards would be an excellent way to sort out my hotels and stuff in France without having to increase my real credit card limit - and so far I have been most impressed. My only gripe with the card that I got (but this could just be a Virgin Money thing) is that, instead of having embossed numbers it has printed numbers meaning that the card says “ELECTRONIC USE ONLY” on the front in small letters. Basically this means the card can’t be used in one of those old machines where they used to take a carbon copy of your card. Ah well, gone are the good old days I suppose.

Anyway - enough about PrePay cards. I spent this weekend programming some more stuff for MouthOS. Specifically I fixed a few bugs in my floppy disk driver (which now fully supports writing and reading of whole disk sectors) and started to implement my FAT file system driver.

I was truly amazed at how easy it was to start writing a FAT driver. Microsoft have for once (and I thought I would never ever say this) done something right and released a lovely (well, fairly good) document (found here)  which details  everything you could ever want to know about the FAT file system. Whilst FAT may be a bit antiquated nowadays it’s a nice simple file system that people writing Operating Systems can easily and quickly adapt so they don’t have to (initially) think about designing their own file system. Furthermore, because GRUB supports the FAT file system it means that you don’t have to go through all the hassle of partitioning a floppy disk into a FAT and a “MouthFS” partition… for the moment anyway.

Anyway. It’s now getting on a bit and I fear that if I don’t get to bed soon I shall have trouble getting up in the morning. Until my next post I bid you all good bye…

OS Development: Video Memory and putchar…

January 15th, 2008 Michael Clarke

Well folks, as promised here is my next exciting installment of the ‘OS Development’ series!

Continuing on from my last post, ‘OS Development: Where to start?’, I’m now going to go over some simple things such as implementing a simple putchar(char c) function which you can then use to implement your printf function. This, apart from my boot-loader, was the first thing I developed in MouthOS. It’s a really good place to start as once you’ve got it sorted you can start printing out debug information such as stack traces, the CPU registers etc.

So, onto the theory! In order to put stuff on the screen you’re going to need to have access to the video memory. On the x86 architecture the video memory is found between 0×000A0000 and 0×000C7FFF. It is split up as follows:

0×000A0000 - 0×000BFFFF: Video RAM Memory.
0×000B0000 - 0×000B7777: Monochrome Video Memory (multiple pages).
0×000B8000 - 0×000BFFFF: Colour Video Memory (multiple pages).
0×000C0000 - 0×000C7FFF: Video ROM Memory.

To begin with the simplest thing to do would be to use the monochrome video memory. However, this is a bit boring as you may want to highlight things in different colours etc. As such the best place to start is to write to the Colour Video Memory.

When writing to the Colour Video Memory you should note that for every character you need two bytes worth of data. The first byte is the character to be displayed and the second is the colour to be used. To start with I just created a header file (video.h) with all my colours and video memory locations defined as below.

 	video.h
	/* Colours are defined as FOREGROUND_BACKGROUND */
	#define BLACK_WHITE             0×0
	#define BLUE_BLACK              0×1
	#define GREEN_BLACK             0×2
	#define CYAN_BLACK              0×3
	#define RED_BLACK               0×4
	#define MAGENTA_BLACK           0×5
	#define BROWN_BLACK             0×6
	#define GRAY_BLACK              0×7
	#define DARK_GRAY_BLACK         0×8
	#define BRIGHT_BLUE_BLACK       0×9
	#define BRIGHT_GREEN_BLACK      0xA
	#define BRIGHT_CYAN_BLACK       0xB
	#define PINK_BLACK              0xC
	#define BRIGHT_MAGENTA_BLACK    0xD
	#define YELLOW_BLACK            0xE
	#define WHITE_BLACK             0xF
	/* Locations for Video Memory. */
	#define VIDEO_MEM_RAM	0x000A0000
	#define VIDEO_MEM_MON	0x000B0000
	#define VIDEO_MEM_COL	0x000B8000
	#define VIDEO_MEM_ROM	0x000C0000
	/* Define the maximum rows and columns available on screen. */
	#define X_MAX	80
	#define Y_MAX	25
	/* Functions in video.c that the rest of the kernel is allowed to use. */
	extern void init_video(void);
	extern void cls(void);
	extern void setcolour(int _colour);
	extern void putchar(const char c);

With that done I started to implement my functions. The first one was the init_video(void) function. The aim of this function was two fold. Firstly it was to gain access to the video memory via a pointer and secondly it was to clear the contents of the video memory (as all the BIOS and/or GRUB loading information is still in video memory). On the whole this is a really simple function…

	video.c
	#include “video.h”

	unsigned char vidmemptr*;
	int colour, crsx, csry;	

	void move_csr(int _x, int _y);

	void init_video(void) {
		vidmemptr = (unsigned char *) VIDEO_MEM_COL;
		colour = WHITE_BLACK;
		cls();
	}

With this completed the next step was to implement the cls(void) function to clear the video memory. This simply involved moving along the entire video memory setting the characters to be equal to ‘ ‘ and the colour to be the currently selected colour (in this case WHITE_BLACK)…

	void cls(void) {
		int i;
		int j = Y_MAX * ( X_MAX * 2 );
		for ( i = 0; i < j; i++ ) {
			vidmemptr[i] = ' ';
			i++;
			vidmemptr[i] = colour;
		}

		move_csr(0, 0);

	}

As can be seen this still won’t compile as the function move_csr(int _x, int _y) still doesn’t exist. This function is used to position the cursor to a specific x, y co-ordinate. It is very simple in my implementation below, simply checking that the given values are not out of bounds of the screen and then setting csrx and csry. However in my full implementation in MouthOS it also sets the blinking cursor and calls another function ’scroll’ to scroll the text up the screen. Unfortunately adding the implementation of these functions to this blog entry would make it twice it’s current size - perhaps for my next entry I’ll go over implementing these extra functions. However for now here is a simple move_csr(int _x, int _y) function.

	void move_csr(int _x, int _y) {
		if ( _x <= X_MAX && _y <= Y_MAX ) {
			csrx = _x;
			csry = _y;
		}
	}

Having implemented move_csr there are two functions left. The first is the setcolour(int colour) function. This is a simple ’setter’ function…

	void setcolour(int _colour) {
		colour = _colour;
	}

Leaving the function you’ve all been waiting for - putchar(const char c)

	void putchar(const char c) {

		int position =  ( csrx * ( X_MAX * 2 ) ) + ( csrx * 2);
		int i;

		if ( c == '\n') {

			move_csr(0, csry + 1);
		} else {
			vidmemptr[position] = c;
			position++;
			vidmemptr[position] - colour;
			move_csr(csrx + 1, csry);
		}

	}

From here there are many places you could branch to. I implemented a scroll() function to scroll the text up as the screen got full. This also required me to implement a memcpy(src, dest, size) function. I also made some modifications to the move_csr(int _x, int _y) function to move the blinking cursor to where the text was appearing and I then went on to write printf(fmt, args) which required the implementation of the va_start, va_arg and va_end macros. As they say the sky is the limit.

MouthOS gains a RSOD as France Approaches…

January 13th, 2008 Michael Clarke

I’ve not had much chance recently to work on MouthOS or to write anything on my blog as I’ve been busy getting prepared for my trip to France at the end of the month. However, I’ve now finally booked my Euro Star tickets (at a very reasonable price of 49.00 return) and my hotel - “Hotel De L’exposition - Tour Eiffel”.

With this done I’ve spent some time this weekend working on MouthOS and I’ve made some excellent progress. I’ve written a new printf function which complies with the ANSI C standard (which also included implementing variable length argument function macros). I’ve also managed to get MouthOS to identify how much RAM a system has - putting me well on the way to finishing my memory manager.

However, the highlight has got to be the new “RSOD” or Red Screen of Death! Since I’ve now got a good printf I was able to start printing out the status of the CPU registers etc, and this has lead to the ability to add a lot of debug information to my panic() function…

MouthOS Red Screen of Death

Don’t worry folks - you shouldn’t see this too often. Also it should be noted that the exception was caused by a deliberate division by zero at the end of main() to test the panic function… I’m not that bad a coder - honestly!

	printf("\n   --> Low Memory:   %iK", _LOW_MEM);
	printf("\n   --> High Memory:  %iK\n", _HIGH_MEM);

	int i = 6 / 0;

Anyway, I think it’s time for an episode of ‘Allo ‘Allo before bed.

OS Development: Where to start?

December 27th, 2007 Michael Clarke

As most people who read this blog will know I’m currently developing a small 32Bit Multi-tasking Operating System called ‘MouthOS’. I figured that I’d start sharing my thoughts and ideas of the development with you all so that, should you be a fool like me, you can write your own OS!

The hardest part of writing an Operating System is where to start! Many people will say ’start wherever you like’. Others will give you warnings about trying to develop ‘Graphical User Interfaces’ straight away. Others will suggest that you do a lot of reading of books relating to Operating System design theory. This is all good advice, and whilst I don’t pretend to be an expert, in my opinion there are three even more important things to consider when starting to develop an Operating System:

  1. What do you want your Operating System to achieve? Many will say be realistic here - don’t be thinking graphical user interfaces and to a certain extent they are correct. However, if you do want to have a graphical user interface this will effect your initial development - you will have to think about interrupts etc. Also this will affect your architecture - is your OS for a washing machine or is it for a fully blown desktop computer?
  2. This brings me onto the next thing - do you know the architecture that you’re going to be developing for? This means understanding what the registers do on your chosen CPU, how the CPU deals with interrupts, what extra features the CPU may or may not have, how the CPU starts execution (where does it get its first instruction from?), how much RAM can it address, and also knowing the assembly language for your chosen architecture.
  3. Once you know your architecture this leads to my final question - what language are you going to develop in? Pure assembly, C, Java, Python? If you’re planning on using Java or Python (or any other interpreted language) you’re going to have to go back to the drawing board - it simply won’t work.

Once you’re comfortable with what your OS is going to achieve, what language its going to be written in, and what it will run on you can start with the boot-loader. In x86 the boot-loader takes over from BIOS. In SPARC the boot-loader takes over from OBP etc. Boot-loaders can be as simple or as complex as you like.

In x86 (as MouthOS is coded in) your boot-loader could directly start calling kernel code, or it could setup the environment, for example setting up the GDT (Global Descriptor Table), IDT (Interrupt Descriptor Table), enable the A20 line and entering into 32Bit Protected Mode. This really depends on what you want your OS to do. If it’s just print some text on screen then there is little point with memory management and 32Bit instructions. However, if you’re planning on having graphics, multiple applications, and if you want to be able to address more than 65K of memory then 32Bit (or even 64Bit) is the way to go. There is loads of information available on the Internet relating to boot-loaders. However, if you’re struggling to find it a good place to start is the wiki and forums at OSDev.Org.

Personally I decided, after the second write of MouthOS, that I was going to use GRUB as my boot-loader. Using GRUB provided a nice way to get into my kernel as GRUB deals with all the above mentioned tasks such as enabling the A20 line, setting up the GDT, getting into 32Bit Protected Mode etc - in essence it puts the system into a known state ready for the kernel. However, even if you’re going to use GRUB at some point (and best sooner than later) you need to re-write the GDT, IDT etc. The reason for this is that you don’t know what GRUB has used for these values and so you could have various things such as users applications overwriting your kernel etc.

This is where I’m going to leave it for now. However, in my next few posts relating to OS development I plan to go over some x86 specific questions like how to implement simple putchar, puts, memcpy functions for your C library. I’ll also cover some other things that you, as budding OS developers, should know - such as how paging and virtual memory work, and where to being when writing a scheduler.

equery - a tool I didn’t know about…

December 23rd, 2007 Michael Clarke

As I was browsing the Gentoo forums earlier today I found a tool that I’ve not used before which looks really useful. Quite often I wonder what packages depend on others in the portage tree…. but no longer.

mikes-computer ~ # equery depends graphviz
[ Searching for packages depending on graphviz… ]
app-doc/doxygen-1.5.4 (!nodot? >=media-gfx/graphviz-2.6)
media-gfx/imagemagick-6.3.5.10 (graphviz? >=media-gfx/graphviz-2.6)
media-libs/libdvbpsi-0.1.5 (doc? media-gfx/graphviz)

Other cool things this little tool does include:

Listing all the packages that own a given file… For example, if I run the following on /usr/bin/gvim I get the following results telling me that the package app-editor/gvim-7.1.164 owns the file /usr/bin/gvim.

mikes-computer ~ # equery belongs /usr/bin/gvim
[ Searching for file(s) /usr/bin/gvim in *… ]
app-editors/gvim-7.1.164 (/usr/bin/gvim)

Another example is if I do a equery belongs on /etc/resolv.conf which doesn’t belong to any particular package:

mikes-computer ~ # equery belongs /etc/resolv.conf
[ Searching for file(s) /etc/resolv.conf in *… ]

Another useful feature of this tool is the ability to find out what files a package owns….

mikes-computer ~ # equery files gvim
[ Searching for packages matching gvim… ]
* Contents of app-editors/gvim-7.1.164:
/etc
/etc/vim
/etc/vim/gvimrc
/usr
/usr/bin
/usr/bin/eview -> gvim
/usr/bin/evim -> gvim
/usr/bin/gview -> gvim
/usr/bin/gvim
/usr/bin/gvimdiff -> gvim
/usr/bin/rgview -> gvim
/usr/bin/rgvim -> gvim
/usr/share
/usr/share/applications
/usr/share/applications/gvim.desktop
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/gview.1.bz2 -> vim.1.bz2
/usr/share/man/man1/gvim.1.bz2 -> vim.1.bz2
/usr/share/man/man1/gvimdiff.1.bz2 -> vimdiff.1.bz2
/usr/share/pixmaps
/usr/share/pixmaps/gvim.xpm

I have to admit that I’ve been most impressed with this tool. It can also do a few other things such as listing all the packages with a given use flag:

mikes-computer ~ # equery hasuse mmx
[ Searching for USE flag mmx in all categories among: ]
 * installed packages
[I–] [ ~] net-misc/asterisk-1.2.21.1-r1 (0)
[I–] [ ~] media-sound/mpg123-1.0_rc2 (0)
[I–] [ ~] media-video/ffmpeg-0.4.9_p20070616-r2 (0)
[I–] [ ~] media-video/mplayer-1.0_rc2_p24929 (0)
[I–] [ ~] media-gfx/inkscape-0.45.1-r1 (0)
[I–] [ ~] media-gfx/gimp-2.4.2 (2)
[I–] [  ] media-tv/xawtv-3.95-r1 (0)

Overall this is a really great tool, and if you don’t have it then you can get it by emerging the gentoolkit…. which I found out by:

mikes-computer ~ # which equery
/usr/bin/equery

mikes-computer ~ # equery belongs /usr/bin/equery
[ Searching for file(s) /usr/bin/equery in *… ]
app-portage/gentoolkit-0.2.4_pre8 (/usr/bin/equery)

Gentoo ‘emerge –deep –newuse –update world’ issues…

December 22nd, 2007 Michael Clarke

Many people tell me that they have issues when running a emerge world on Gentoo to keep their system up to date. I have long argued that the problems are simply because they don’t run the updates regularly enough, and if they were to run updates every week they wouldn’t have these problems.

Unfortunately I have fallen foul of my own advice and haven’t run updates in a couple of weeks. This is now resulting in the following error:

 * ERROR: gnome-extra/evolution-data-server-1.12.2-r1 failed.
 * Call stack:
 *               ebuild.sh, line   46:  Called src_compile
 *             environment, line 3397:  Called gnome2_src_compile
 *             environment, line 2573:  Called die
 * The specific snippet of code:
 *       emake || diefunc “$FUNCNAME” “$LINENO” “$?” “compile failure”
 *  The die message:
 *   compile failure
 *
 * If you need support, post the topmost build error, and the call stack if
 * relevant.
 * A complete build log is located at ‘/var/tmp/portage/gnome-extra/evolution
 * -data-server-1.12.2-r1/temp/build.log’.
 * The ebuild environment file is located at ‘/var/tmp/portage/gnome-extra/
 * evolution-data-server-1.12.2-r1/temp/environment’.

When you hit errors like this there are a number of things that should and can easily be done which 99% of the time will fix the problem. The first is to actually check the logs! The number of times I read the Gentoo forums and people don’t post the true topmost build error is unbelievable. Read the error and read the logs:

 michaelfclarke@mikes-computer ~ $
 cat /var/tmp/portage/gnome-extra/evolution-data-server-1.12.2-r1/temp/build.log \
 | grep -i error
 checking for library containing strerror… none required
  mode, hide preprocessor errors, passes: stubs skels common headers
  mode, hide preprocessor errors, passes: stubs skels common headers
 /bin/sh ../../libtool –tag=CC   –mode=compile x86_64-pc-linux-gnu-gcc
 -DHAVE_CONFIG_H -I. -I../.. -I../.. -I../../src -I../../src -I../../src/libical
 -I../../src/libical -I. -DPACKAGE_DATA_DIR=\”"/usr/share/evolution-data-server-1.12″\”
 -I/usr/include/db4.5  -O2 -pipe -MT icalerror.lo -MD -MP -MF .deps/icalerror.Tpo -c
 -o icalerror.lo icalerror.c
 x86_64-pc-linux-gnu-gcc -DHAVE_CONFIG_H -I. -I../.. -I../.. -I../../src -I../../src
 -I../../src/libical -I../../src/libical -I.
 -DPACKAGE_DATA_DIR=\”/usr/share/evolution-data-server-1.12\” -I/usr/include/db4.5
 -O2 -pipe -MT icalerror.lo -MD -MP -MF .deps/icalerror.Tpo -c icalerror.c  -fPIC -DPIC
 -o .libs/icalerror.o
 mv -f .deps/icalerror.Tpo .deps/icalerror.Plo
 /bin/sh ../../libtool –tag=CC   –mode=link x86_64-pc-linux-gnu-gcc  -O2 -pipe
 -version-info 0:0:0 -o libical-evolution.la   icalderivedparameter.lo
 icalderivedproperty.lo icalrestriction.lo icalderivedvalue.lo icalarray.lo icalattach.lo
 icalcomponent.lo icalenums.lo icalerror.lo icalmemory.lo icalmime.lo icalparameter.lo
 icalparser.lo icalproperty.lo icalrecur.lo icaltime.lo icaltz-util.lo icaltimezone.lo
 icalduration.lo icalperiod.lo icaltypes.lo icalvalue.lo pvl.lo sspm.lo vsnprintf.lo
 icallangbind.lo caldate.lo -lpthread
 x86_64-pc-linux-gnu-ar cru .libs/libical-evolution.a .libs/icalderivedparameter.o
 .libs/icalderivedproperty.o .libs/icalrestriction.o .libs/icalderivedvalue.o
 .libs/icalarray.o .libs/icalattach.o .libs/icalcomponent.o .libs/icalenums.o
 .libs/icalerror.o .libs/icalmemory.o .libs/icalmime.o .libs/icalparameter.o
 .libs/icalparser.o .libs/icalproperty.o .libs/icalrecur.o .libs/icaltime.o
 .libs/icaltz-util.o .libs/icaltimezone.o .libs/icalduration.o .libs/icalperiod.o
 .libs/icaltypes.o .libs/icalvalue.o .libs/pvl.o .libs/sspm.o .libs/vsnprintf.o
 .libs/icallangbind.o .libs/caldate.o
 x86_64-pc-linux-gnu-gcc -DHAVE_CONFIG_H -I. -I.. -I. -I.. -I../src -I../src
 -I../src/libical -I../src/libical -I/usr/include/db4.5  -O2 -pipe -MT errors.o
 -MD -MP -MF .deps/errors.Tpo -c -o errors.o errors.c
 mv -f .deps/errors.Tpo .deps/errors.Po
 /bin/sh ../libtool –tag=CC   –mode=link x86_64-pc-linux-gnu-gcc  -O2 -pipe
 -o doesnothing access_components.o
 access_properties_and_parameters.o errors.o main.o parse_text.o
 ../src/libical/libical-evolution.la ../src/libicalss/libicalss-evolution.la
 ../src/libicalvcal/libicalvcal-evolution.la -lpthread
 x86_64-pc-linux-gnu-gcc -O2 -pipe -o doesnothing access_components.o
 access_properties_and_parameters.o errors.o
 main.o parse_text.o  ../src/libical/.libs/libical-evolution.a
 ../src/libicalss/.libs/libicalss-evolution.a
 ../src/libicalvcal/.libs/libicalvcal-evolution.a -lpthread
  mode, hide preprocessor errors, passes: stubs skels common headers
  mode, hide preprocessor errors, passes: stubs skels common headers
 x86_64-pc-linux-gnu-gcc -O2 -pipe -Wall -Wmissing-prototypes -Wno-sign-compare
 -o .libs/create-account create-account.o
 -pthread -Wl,-R/usr/lib64/nspr  ../../libedataserver/.libs/libedataserver-1.2.so
 -L/usr/lib64/nspr -L/usr/lib64/lib
 /usr/lib64/libdb-4.5.so /usr/lib64/libsoup-2.2.so -L/usr/lib64 -lnsl
 /usr/lib64/libgnutls.so /usr/lib64/libtasn1.so
 /usr/lib64/libgcrypt.so /usr/lib64/libgpg-error.so /usr/lib64/libxml2.so -lz
 -lm /usr/lib64/libbonobo-2.so
 /usr/lib64/libbonobo-activation.so /usr/lib64/libORBitCosNaming-2.so
 /usr/lib64/libgconf-2.so /usr/lib64/libORBit-2.so /usr/lib64/libgmodule-2.0.so
 /usr/lib64/libgthread-2.0.so -lrt /usr/lib64/libgobject-2.0.so /usr/lib64/libglib-2.0.so
 -lplds4 -lplc4 -lnspr4 -ldl -lpthread
 x86_64-pc-linux-gnu-gcc -O2 -pipe -Wall -Wmissing-prototypes -Wno-sign-compare
 -o .libs/soap-test soap-test.o -pthread -Wl,-R/usr/lib64/nspr  -L/usr/lib64
 ./.libs/libegroupwise-1.2.so -L/usr/lib64/nspr /usr/lib64/libsoup-2.2.so -lnsl
 /usr/lib64/libgnutls.so /usr/lib64/libtasn1.so /usr/lib64/libgcrypt.so
 /usr/lib64/libgpg-error.so /usr/lib64/libxml2.so -lz -lm /usr/lib64/libbonobo-2.so
 /usr/lib64/libbonobo-activation.so /usr/lib64/libORBitCosNaming-2.so
 /usr/lib64/libgconf-2.so /usr/lib64/libORBit-2.so /usr/lib64/libgmodule-2.0.so
 /usr/lib64/libgthread-2.0.so -lrt /usr/lib64/libgobject-2.0.so /usr/lib64/libglib-2.0.so
 -lplds4 -lplc4 -lnspr4 -ldl -lpthread
 make[4]: *** [create-account] Error 1
 make[4]: *** [soap-test] Error 1
 make[3]: *** [all] Error 2
 make[2]: *** [all-recursive] Error 1
 make[1]: *** [all-recursive] Error 1
 make: *** [all] Error 2
 * ERROR: gnome-extra/evolution-data-server-1.12.2-r1 failed.
 * If you need support, post the topmost build error, and the call stack if relevant.
 michaelfclarke@mikes-computer ~ $

Reading the above nothing stood out that much so I decided to do a grep for warning instead…

 michaelfclarke@mikes-computer ~ $
 cat /var/tmp/portage/gnome-extra/evolution-data-server-1.12.2-r1/temp/build.log \
 |grep -i warning
 configure: WARNING: krb5 support disabled
 checking what warning flags to pass to the C compiler… -Wall -W missing-prototypes
 e-data-server-module.c:86: warning: dereferencing type-punned pointer will break strict-aliasing rules
 e-data-server-module.c:89: warning: dereferencing type-punned pointer will break strict-aliasing rules
 e-data-server-module.c:92: warning: dereferencing type-punned pointer will break strict-aliasing rules
 broken-date-parser.c:125: warning: pointer targets in assignment differ in signedness
 …
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/../../../../x86_64-pc-linux-gnu/bin/ld: warning: libgnutls.so.13,
 needed by /usr/lib64/libsoup-2.2.so, not found (try using -rpath or -rpath-link)

Ah! The last line of the output seemed to be the problem. My first idea was to simply create a symlink and see what happens:

  ln -s /usr/lib64/libgnutls.so.26 /usr/lib64/libgnutls.so.13

This failed to work. Instead I then tried to re-emerge libsoup. This worked and my original emerge then proceeded with no errors :)

>>> /usr/share/doc/evolution-data-server-1.12.2-r1/TODO.bz2
 * Installing GNOME 2 GConf schemas
 * Reloading GConf schemas …                                          [ ok ]
 * Updating desktop mime database …
 * Updating shared mime info database …
 * Updating icons cache …                                             [ ok ]
>>> Regenerating /etc/ld.so.cache…
>>> gnome-extra/evolution-data-server-1.12.2-r1 merged.

>>> No packages selected for removal by clean

The upshot of all this is - keep your system up to date and remember to read the log files.