Autor Thema: PowerPC  (Gelesen 2418 mal)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« am: 01. June 2009, 14:14 »
Hat zufällig irgendeiner von euch schonmal versucht, einen Kernel für PowerPC zu schreiben und war dabei möglicherweise sogar halbwegs erfolgreich? Ich will mir das schon eine ganze Weile mal näher anschauen (immer nur x86 ist schließlich langweilig), aber ich komme mir ungefähr genauso hilflos vor wie damals als Anfänger. Okay, das ist etwas geschwindelt, von x86 hatte ich nämlich davor schon mehr Ahnung...

Im qemu habe ich immerhin mal ein "Hello World" auf die serielle Konsole rausbekommen, aber selbst dieser Code ist kaputt, weil ich einfach die MMIO-Adresse hartkodiert habe, wo die serielle Schnittstelle unter qemu eben liegt. Theoretisch müsste ich von der Open Firmware rauskriegen, was ich wirklich machen sollte. Wenn mir irgendjemand ersparen könnte, selbst endlos Texte zu wälzen, wäre ich dankbar. ;)

Und ich glaube entsprechend der aktuellen Mode schreibe ich jetzt erstmal ein Tutorial, wie man unter PPC in qemu Hello World ausgibt, basierend auf diesem revolutionären Code:
.global _start
_start:
    lis r3, str@h
    ori r3, r3, str@l
    lis r4, 0x8089
    ori r4, r4, 0x3030
putc:
    lbz r5, 0x0(r3)
    cmpwi r5, 0x0
    beq loop
    stb r5, 0x0(r4)
    addi r3, r3, 1
    b putc
loop:
    b loop

str:
    .ascii "Hello World\n\0"

Bin ich gut oder bin ich gut? :-D
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #1 am: 02. June 2009, 10:36 »
Ich hab da mal ein Bisschen was zusammengefrickelt, mit viel rumprobieren und Code wälzen tut es schliesslich was ich möchte. Wie korrekt es ist, weiss ich aber nicht... ;-)

/* Libc und so... */
#define NULL ((void*) 0)
void* memcpy(void* dest, const void* src, int len);
void* memset(void* dest, int c, int len);
int strlen(char* str);


/** Struktur, die bei OFW-Aufrufen uebergeben wird */
struct ofw_args
{
  const char* func;
  int arg_count;
  int ret_count;
  void* args[10];
} __attribute__((packed));

/** Zeiger auf den OFW-Entrypoint */
int (*ofw_call)(struct ofw_args* args);

/* Nette Openfirmware-Funktionen */
int ofw_finddevice(char* name)
{
    struct ofw_args args_chosen = {
        .func = "finddevice",
        .arg_count = 1,
        .ret_count = 1,
        .args = {
            name
        }
    };
    ofw_call(&args_chosen);
    return (int) args_chosen.args[1];
}

void ofw_getprop(int device, char* prop, void* buf, int len)
{
    struct ofw_args args_getprop = {
        .func = "getprop",
        .arg_count = 4,
        .ret_count = 1,
        .args = {
            (void*) device,
            prop,
            buf,
            (void*) len
        }
    };
    ofw_call(&args_getprop);
}

void ofw_write(int handle, void* buf, int len)
{
    struct ofw_args args_write = {
        .func = "write",
        .arg_count = 3,
        .ret_count = 1,
        .args = {
            (void*) handle,
            buf,
            (void*) len
        }
    };
    ofw_call(&args_write);
}

int ofw_read(int handle, void* buf, int len)
{
    struct ofw_args args_read = {
        .func = "read",
        .arg_count = 3,
        .ret_count = 1,
        .args = {
            (void*) handle,
            buf,
            (void*) len
        }
    };
    ofw_call(&args_read);
    return (int) args_read.args[3];
}

void ofw_exit()
{
    struct ofw_args args_exit = {
        .func = "exit",
        .arg_count = 0,
        .ret_count = 0,
    };
    ofw_call(&args_exit);
}

void ofw_puts(char* str)
{
    int handle;
    ofw_getprop(ofw_finddevice("/chosen"), "stdout", &handle, sizeof(handle));
    ofw_write(handle, str, strlen(str));
}

char ofw_getc(void)
{
    int handle;
    char c;
    ofw_getprop(ofw_finddevice("/chosen"), "stdin", &handle, sizeof(handle));
    if (ofw_read(handle, &c, 1) == 0) return 0;
}



/* Hier wird in unser "Kernel" gesprungen */
void _start(unsigned long r3, unsigned long r4, unsigned long r5)
{
    ofw_call = (void*) r5;

    ofw_puts("Hello World!\r\n");
    ofw_puts("Willst du EXIT druckst du Taste...\r\n");
    while (ofw_getc() == 0);
    ofw_exit();
}



/* Tolle Libc */
void* memcpy(void* dest, const void* src, int len)
{
    char* dc = dest;
    const char* sc = src;
    while (len--) *dc++ = *sc++;
    return dest;
}
void* memset(void* dest, int c, int len)
{
    char* dc = dest;
    while (len--) *dc++ = c;
    return dest;
}
int strlen(char* str)
{
    int len = 0;
    while (*str++) len++;
    return len;
}

 

Einloggen