Part 3: Development Environment




Overview

Compile and run a basic kernel to display "Hello World!"







With your cross-development tools in hand, it's time to start coding. Fortunately, Sun has done a lot of the work for you here. Unlike i386s, SPARC computers have a complete printf function in their PROMs! This is very handy to say the least.

The name of your entry point can be whatever you want it to be. I call mine kernel_start. Make sure that it is the first function in the source file and that it is before any variable declarations. The only thing that may come before the definition of your entry point are function prototypes. If anything else is before it, the GNU linker will not produce correct code. Another quirk with the linker (I've got the feeling that it could use some work) is that it expects the C symbol __main to be defined somewhere. I have no idea why, but nothing will link without one. A third oddity is that it mangles names by prepending underscores to all C symbols, so anything declared in a C file that gets referenced in an assembly file needs to have an underscore prepended to its name.

For interfacing with the PROM, you will want a copy of OpenBSD's bsd_openprom.h. Note that this file is under the BSD licence. To that file, you will want to add

typedef char *caddr_t;
typedef unsigned int u_int;

The thing that you will quickly become intimately familiar with and grow to love is this structure called the PROM vector. Known as `struct promvec' in the OpenBSD header file, it provides all sorts of data and function pointers to neat things in the PROM. Read the file for details, although I will discuss some points later.

My bootloader will pass the PROM vector and address of the SBBB image (always 0x4000, but code to an interface, not an implementation! [Gamma1995]) when calling your entry point. These are parameters if your entry point is in C. If your entry point is in assembly, they will be in %o0 and %o1. Minimally, you will need something resembling this in C:

#include "openprom.h"
#include "sbbb.h"

/* these don't count as variable declarations since they are extern */
extern struct PromVec *PromVec;
extern struct BootDir *BootDir;

int main ();

/* entry point */
void kernel_start (struct PromVec *P, struct BootDir *BD)
{
  PromVec = P;
  BootDir = BD;
  main ();
}

/* silly GNU linker */
void __main ()
{
}

struct PromVec *PromVec;
struct BootDir *BootDir;

int main ()
{
  PromVec->printf ("Hello World!\n");
  return 0; /* to please GCC */
}
To compile and link this bohemoth, you will want to write an appropriate Makefile. See the SigOps tutorial for one for i386. Mine is too complex to give here, but assuming you called the above file start.c, from the shell you would do
$ sun4-gcc -I. -nostdinc -Wall -c start.c
$ sun4-ld -o kernel.tmp -e _kernel_start -N -Ttext 0x5000 -x start.o
$ dd if=kernel.tmp of=vmsteak-sparc bs=32 skip=1 2> /dev/null
The third step strips off the a.out header. It is not strictly necessary right now, but beware that your entry point will be at 0x5020 if you don't remove it. You may as well get used to doing it now since a very good reason for doing so will be given in the next section. This procedure should leave you with an executable called vmsteak-sparc. Package this up with Brian Swetland's uBoot system, and you're ready to fly. The image should be called vmsteak since that is the filename my bootloader will look for. If you don't like that name, change it in boot.c and recompile the second-stage.

If you need to use an entry point other than the beginning of the file (0x5000) you will need to give a ventry parameter in your bootmaker configuration file. My bootloader will grab that from the SBBB directory, swap bytes to big endian order, and jump to your offset. Note that the data in the directory are stored in little endian byte order, so you have to swap bytes when you read it later on.

Let's boot this bad boy, assuming my setup as usual:

$ cp vmsteak /xdev
$ su
# halt
ok boot sd(,,3)          -- or `boot disk:d' or `boot /sbus/esp/sd@0,0:d'
                            depending on your PROM version
Assuming everything goes well, you should see something resembling the following:
Booting from: sd(0,0,3)                                                         
>> SigOps BOOT 1.0
Booting vmsteak @ 0x4000
Loaded 0x2000 bytes
Executing KERN:vmsteak at 0x5000

Hello World!
Program terminated
ok
Congratulations, you're an OS coder.


Writing an Operating System for SPARC-Based Computers is Copyright © 1998 by Sidney Cammeresi in its entirety. All rights reserved.

Permission is granted to make verbatim copies of this tutorial for non-commercial use provided this notice remains intact on all copies.