pupa-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PowerPC port of PUPA


From: Marco Gerards
Subject: PowerPC port of PUPA
Date: 24 Jan 2004 01:35:30 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Hi,

(I hope you do not receive this mail twice, gnus is doing weird stuff
here..)

Here is a patch that makes it possible start PUPA on the new world
apple macintoshes (PPC).  It only adds support for the console (which
does not work correctly because of some Open Firmware weirdness) and
disk(+partition) support.

Some things still need to be done:

- Porting loaders.
- Write hfs.
- Write iso9660fs.
- Write a termcap.c that handles the terminal.
- Scan for consoles, make sure it works for Open Firmware versions
  without local console.
- Reading the RTC is not yet done (I can fix that really quickly).
- Test it on more Macs.
- Make a script to make a psim image for testing (Volunteers? :))
(Did I forget some stuff?)

A big part of the code (like it is mentioned in the changelog entry)
was written by Johan Rydberg.  Is it ok if I mention him in THANKS and
AUTHORS together with what he did?

I hope some people can test this patch for me.  I only have tested it
on my laptop.  If you want to test it in psim (PPC simulator, it is a
part of gdb), it can be done if you remove the "claim" in init. (In
that case the memory will not be properly allocated, but in psim that
works fine).

To test it you only have to build pupaof, which is an ELF binary that
can be loaded with open firmware.

I hope I did not break anything for the PC and that pupa-emu still
works on the PPC, I have not yet tested this. (I have to send this
mail now, otherwise I have to wait a while... :().

This patch should not be hard to read because there were no interfaces
changes, etc.  Just new files were added (minus a few fixes).  Please
have a close look at the powerpc-nwmac.rmk file, I have some doubts
here.

Thanks,
Marco

2004-01-24  Marco Gerards  <address@hidden>

        Add support for the newworld apple macintosh (PPC).  This has been
        tested on the powerbook 2000 only.  It only adds support for
        generic ieee1275 functions, console and disk support.
        
        * configure.ac: Accept the powerpc as host_cpu.  In the case of
        the powerpc cpu set the host_vendor to nwmac.  Make sure the i386
        specific tests are only executed while building for the i386.
        Inverse test for crosscompile.
        * genmk.rb (Utility): Allow assembler files.
        * normal/cmdline.c (pupa_tab_complete): Reset pupa_errno.
        * conf/powerpc-nwmac.rmk: New file.
        * disk/powerpc/nwmac/ofdisk.c: Likewise.
        * disk/powerpc/nwmac/partition.c: Likewise.
        * include/pupa/powerpc/nwmac/biosdisk.h: Likewise.
        * include/pupa/powerpc/nwmac/console.h: Likewise.
        * include/pupa/powerpc/nwmac/partition.h: Likewise.
        * include/pupa/powerpc/nwmac/time.h: Likewise.
        * include/pupa/powerpc/nwmac/util/biosdisk.h: Likewise.
        * include/pupa/powerpc/setjmp.h: Likewise.
        * include/pupa/powerpc/types.h: Likewise.
        * kern/powerpc/nwmac/init.c: Likewise.
        * kern/powerpc/nwmac/openfw.c: Likewise.
        * normal/cmdline.c: Likewise.
        * term/powerpc/nwmac/ofconsole.c: Likewise.

        These files were written by Johan Rydberg
        (address@hidden) and I only modified them slightly.
                
        * boot/powerpc/nwmac/cmain.c: New file.
        * boot/powerpc/nwmac/crt0.S: Likewise.
        * boot/powerpc/nwmac/ieee1275.c: Likewise.
        * include/pupa/powerpc/nwmac/ieee1275.h: Likewise.

diff -uprN ../pupa/boot/powerpc/nwmac/cmain.c ./boot/powerpc/nwmac/cmain.c
--- ../pupa/boot/powerpc/nwmac/cmain.c  1970-01-01 01:00:00.000000000 +0100
+++ ./boot/powerpc/nwmac/cmain.c        2004-01-23 23:05:57.000000000 +0100
@@ -0,0 +1,147 @@
+/* cmain.c - Startup code for the PowerPC.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <alloca.h>
+#include <stdint.h>
+
+#include "pupa/machine/ieee1275.h"
+
+struct module_info
+{
+  uint32_t start;
+  uint32_t end;
+};
+
+#define roundup(a, s) (((a) + ((s) - 1)) & ~((s) - 1))
+
+/* OpenFirmware entry point passed to us from the real bootloader.  */
+intptr_t (*pupa_ieee1275_entry_fn) (void *);
+
+
+/* Return a help text for this architecture.  */
+const char *
+help_arch (void)
+{
+  /* No special information.  */
+  return "";
+}
+
+
+/* Setup the argument vector and pass control over to the main
+   function.  */
+void
+cmain (uint32_t firmware_entry)
+{
+  char **argv, args[256];
+  pupa_ieee1275_phandle_t chosen;
+  int argc = 0, actual;
+  long batl, batu;
+
+  pupa_ieee1275_entry_fn = (intptr_t (*)(void *)) firmware_entry;
+
+  /* Initialize BAT registers to unmapped to not generate overlapping
+     mappings below.  */
+  asm volatile ("mtibatu 0,%0" :: "r"(0));
+  asm volatile ("mtibatu 1,%0" :: "r"(0));
+  asm volatile ("mtibatu 2,%0" :: "r"(0));
+  asm volatile ("mtibatu 3,%0" :: "r"(0));
+  asm volatile ("mtdbatu 0,%0" :: "r"(0));
+  asm volatile ("mtdbatu 1,%0" :: "r"(0));
+  asm volatile ("mtdbatu 2,%0" :: "r"(0));
+  asm volatile ("mtdbatu 3,%0" :: "r"(0));
+
+  /* Set up initial BAT table to only map the lowest 256 MB area.  */
+  batl = 0x00000000 | 0x10   | 0x02;
+  batu = 0x00000000 | 0x1ffc | 0x02;
+
+  /* IBAT0 used for initial 256 MB segment */
+  asm volatile ("mtibatl 3,%0; mtibatu 3,%1" :: "r" (batl), "r" (batu));
+  /* DBAT0 used similar */
+  asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1" :: "r" (batl), "r" (batu));
+  asm ("isync");
+
+  /* If any argument was passed to the kernel (us), they are
+     put in the bootargs property of /chosen.  The string can
+     be null (just the nul-character), so check that the size
+     is actually greater than one.  */
+
+  pupa_ieee1275_finddevice ("/chosen", &chosen);
+  if (pupa_ieee1275_get_property (chosen, "bootargs", args,
+                                 sizeof args, &actual) == 0
+      && actual > 1)
+    {
+      /* A command line was passed.  */
+      char *str = args;
+      int nr = 1;
+
+      /* First time around we count the number of arguments.  */
+      argc = 2;
+      while (*str && *str == ' ')
+       str++;
+
+      while (*str)
+       if (*(str++) == ' ')
+         {
+           while (*str && *str == ' ')
+             str++;
+           if (*str)
+             argc++;
+         }
+      argv = alloca (sizeof (char *) * (argc + 2));
+
+      /* The bootargs property does not contain the program
+        name, just the arguments.  */
+      argv[0] = "pupa";
+
+      /* Second time around we fill in the argv.  */
+      str = args;
+
+      while (*str && *str == ' ')
+       str++;
+      argv[nr++] = str;
+
+      while (*str)
+       {
+         if (*str == ' ')
+           {
+             *(str++) = '\0';
+             while (*str && *str == ' ')
+               str++;
+             if (*str)
+               argv[nr++] = str;
+           }
+         else
+           str++;
+       }
+      argv[nr] = 0;
+    }
+  else
+    {
+      argv = alloca (sizeof (char *) * 2);
+      argv[0] = "pupa";
+      argv[1] = 0;
+      argc = 1;
+    }
+  /* Now invoke the main function.  */
+  /* XXX: pupa_main does not parse arguments yet.  */
+  pupa_main ();
+
+  /* Never reached.  */
+}
diff -uprN ../pupa/boot/powerpc/nwmac/crt0.S ./boot/powerpc/nwmac/crt0.S
--- ../pupa/boot/powerpc/nwmac/crt0.S   1970-01-01 01:00:00.000000000 +0100
+++ ./boot/powerpc/nwmac/crt0.S 2004-01-23 23:06:02.000000000 +0100
@@ -0,0 +1,55 @@
+/* crt0.S - Startup code for the PowerPC.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+       .section ".note"
+       .align  2
+.note_section_header:
+       .long   8
+       .long   24
+       .long   0x1275
+       .string "PowerPC"
+.note_descriptor:
+       .long   0x0             /* real-mode */
+       .long   0xffffffff      /* real-base */
+       .long   0xffffffff      /* real-size */
+       .long   0xffffffff      /* virt-base */
+       .long   0xffffffff      /* virt-size */
+       .long   0x00030000      /* load-base */
+       
+       .text
+       .align  2
+       .globl  _start
+_start:        
+       lis     1, address@hidden
+       la      1, address@hidden(1)
+       addi    1, 1, -32
+
+       li      2, 0
+       li      13, 0
+       
+
+       mr      3, 5    
+       bl      cmain
+1:     b       1b
+
+       .section ".bss"
+       .lcomm  _ppc_init_stack, 4096*2, 16
+init_stack:
+
diff -uprN ../pupa/boot/powerpc/nwmac/ieee1275.c ./boot/powerpc/nwmac/ieee1275.c
--- ../pupa/boot/powerpc/nwmac/ieee1275.c       1970-01-01 01:00:00.000000000 
+0100
+++ ./boot/powerpc/nwmac/ieee1275.c     2004-01-23 22:06:31.000000000 +0100
@@ -0,0 +1,420 @@
+/* ieee1275.c - Access the Open Firmware client interface.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/ieee1275.h>
+
+
+#define IEEE1275_PHANDLE_ROOT          ((pupa_ieee1275_phandle_t) 0)
+#define IEEE1275_PHANDLE_INVALID       ((pupa_ieee1275_phandle_t) -1)
+
+intptr_t (*pupa_ieee1275_entry_fn) (void *);
+
+#ifndef IEEE1275_CALL_ENTRY_FN
+#define IEEE1275_CALL_ENTRY_FN(args) (*pupa_ieee1275_entry_fn) (args)
+#endif
+
+/* All backcalls to the firmware is done by calling an entry function 
+   which was passed to us from the bootloader.  When doing the backcall, 
+   a structure is passed which specifies what the firmware should do.  
+   NAME is the requested service.  NR_INS and NR_OUTS is the number of
+   passed arguments and the expected number of return values, resp. */
+struct pupa_ieee1275_common_hdr
+{
+  char *name;
+  int nr_ins;
+  int nr_outs;
+};
+
+#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
+  (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts
+
+/* FIXME is this function needed? */
+pupa_uint32_t
+pupa_ieee1275_decode_int_4 (unsigned char *p)
+{
+  pupa_uint32_t val = (*p++ << 8);
+  val = (val + *p++) << 8;
+  val = (val + *p++) << 8;
+  return (val + *p);
+}
+
+
+int
+pupa_ieee1275_finddevice (char *name, pupa_ieee1275_phandle_t *phandlep)
+{
+  struct find_device_args {
+    struct pupa_ieee1275_common_hdr common;
+    char *device;
+    pupa_ieee1275_phandle_t phandle;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "finddevice", 1, 1);
+  args.device = name;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *phandlep = args.phandle;
+  return 0;
+}
+
+int
+pupa_ieee1275_get_property (int handle, const char *property, void *buf,
+                           pupa_size_t size, pupa_size_t *actual)
+{
+  struct get_property_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t phandle;
+    const char *prop;
+    void *buf;
+    int buflen;
+    int size;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "getprop", 4, 1);
+  args.phandle = handle;
+  args.prop = property;
+  args.buf = buf;
+  args.buflen = size;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = args.size;
+  return 0;
+}
+
+int
+pupa_ieee1275_next_property (int handle, char *prev_prop, char *prop,
+                            int *flags)
+{
+  struct get_property_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t phandle;
+    char *prev_prop;
+    char *next_prop;
+    int flags;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "nextprop", 3, 1);
+  args.phandle = handle;
+  args.prev_prop = prev_prop;
+  args.next_prop = prop;
+  args.flags = -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (flags)
+    *flags = args.flags;
+  return 0;
+}
+
+int
+pupa_ieee1275_get_property_length (pupa_ieee1275_phandle_t handle, 
+                                  const char *prop, pupa_size_t *length)
+{
+  struct get_property_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t phandle;
+    const char *prop;
+    pupa_size_t length;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "getproplen", 2, 1);
+  args.phandle = handle;
+  args.prop = prop;
+  args.length = -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *length = args.length;
+  return 0;
+}
+
+int
+pupa_ieee1275_instance_to_package (pupa_ieee1275_ihandle_t ihandle,
+                                  pupa_ieee1275_phandle_t *phandlep)
+{
+  struct instance_to_package_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+    pupa_ieee1275_phandle_t phandle;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
+  args.ihandle = ihandle;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *phandlep = args.phandle;
+  return 0;
+}
+
+int
+pupa_ieee1275_package_to_path (pupa_ieee1275_phandle_t phandle,
+                              char *path, pupa_size_t len, pupa_size_t *actual)
+{
+  struct instance_to_package_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t phandle;
+    char *buf;
+    int buflen;
+    int actual;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "package-to-path", 3, 1);
+  args.phandle = phandle;
+  args.buf = path;
+  args.buflen = len;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = args.actual;
+  return 0;
+}
+
+int
+pupa_ieee1275_instance_to_path (pupa_ieee1275_ihandle_t ihandle,
+                               char *path, pupa_size_t len,
+                               pupa_size_t *actual)
+{
+  struct instance_to_package_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+    char *buf;
+    int buflen;
+    int actual;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "instance-to-path", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = path;
+  args.buflen = len;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = args.actual;
+  return 0;
+}
+
+int
+pupa_ieee1275_write (pupa_ieee1275_ihandle_t ihandle, void *buffer, 
+                    pupa_size_t len, pupa_size_t *actualp)
+{
+  struct write_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+    void *buf;
+    pupa_size_t len;
+    pupa_size_t actual;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "write", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = buffer;
+  args.len = len;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actualp)
+    *actualp = args.actual;
+  return 0;
+}
+
+int
+pupa_ieee1275_read (pupa_ieee1275_ihandle_t ihandle, void *buffer,
+                   pupa_size_t len, pupa_size_t *actualp)
+{
+  struct write_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+    void *buf;
+    pupa_size_t len;
+    pupa_size_t actual;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "read", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = buffer;
+  args.len = len;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actualp)
+    *actualp = args.actual;
+  return 0;
+}
+
+int
+pupa_ieee1275_seek (pupa_ieee1275_ihandle_t ihandle, int pos_hi,
+                   int pos_lo, int *result)
+{
+  struct write_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+    int pos_hi;
+    int pos_lo;
+    int result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1);
+  args.ihandle = ihandle;
+  args.pos_hi = pos_hi;
+  args.pos_lo = pos_lo;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  if (result)
+    *result = args.result;
+  return 0;
+}
+
+int
+pupa_ieee1275_peer (pupa_ieee1275_phandle_t node,
+                   pupa_ieee1275_phandle_t *result)
+{
+  struct peer_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t node;
+    pupa_ieee1275_phandle_t result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "peer", 1, 1);
+  args.node = node;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  return 0;
+}
+
+int
+pupa_ieee1275_child (pupa_ieee1275_phandle_t node,
+                    pupa_ieee1275_phandle_t *result)
+{
+  struct child_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t node;
+    pupa_ieee1275_phandle_t result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "child", 1, 1);
+  args.node = node;
+  args.result = IEEE1275_PHANDLE_INVALID;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  return 0;
+}
+
+int
+pupa_ieee1275_parent (pupa_ieee1275_phandle_t node,
+                     pupa_ieee1275_phandle_t *result)
+{
+  struct parent_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_phandle_t node;
+    pupa_ieee1275_phandle_t result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "parent", 1, 1);
+  args.node = node;
+  args.result = IEEE1275_PHANDLE_INVALID;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  return 0;
+}
+
+int
+pupa_ieee1275_exit (void)
+{
+  struct exit_args {
+    struct pupa_ieee1275_common_hdr common;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "exit", 0, 0);
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  return 0;
+}
+
+int
+pupa_ieee1275_open (char *node, pupa_ieee1275_ihandle_t *result)
+{
+  struct peer_args {
+    struct pupa_ieee1275_common_hdr common;
+    char *cstr;
+    pupa_ieee1275_ihandle_t result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "open", 1, 1);
+  args.cstr = node;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  return 0;
+}
+
+int
+pupa_ieee1275_close (pupa_ieee1275_ihandle_t ihandle)
+{
+  struct peer_args {
+    struct pupa_ieee1275_common_hdr common;
+    pupa_ieee1275_ihandle_t ihandle;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "close", 1, 0);
+  args.ihandle = ihandle;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return 0;
+}
+
+int
+pupa_ieee1275_claim (void *p, pupa_size_t size,
+                    unsigned int align, void **result)
+{
+  struct peer_args {
+    struct pupa_ieee1275_common_hdr common;
+    void *p;
+    pupa_size_t size;
+    unsigned int align;
+    void *addr;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "claim", 3, 1);
+  args.p = p;
+  args.size = size;
+  args.align = align;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.addr;
+  return 0;
+}
diff -uprN ../pupa/conf/powerpc-nwmac.rmk ./conf/powerpc-nwmac.rmk
--- ../pupa/conf/powerpc-nwmac.rmk      1970-01-01 01:00:00.000000000 +0100
+++ ./conf/powerpc-nwmac.rmk    2004-01-24 00:15:36.000000000 +0100
@@ -0,0 +1,49 @@
+
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin
+COMMON_CFLAGS = -fno-builtin
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/pupa/,$(kernel_img_HEADERS)) gensymlist.sh
+       sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
+
+kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) 
genkernsyms.sh
+       sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
+
+# Utilities.
+sbin_UTILITIES = pupaof
+bin_UTILITIES = pupa-emu
+noinst_UTILITIES = genmoddep
+
+# For pupa-emu
+pupa_emu_SOURCES = kern/main.c kern/device.c                           \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c          \
+        kern/misc.c kern/loader.c kern/rescue.c kern/term.c            \
+       disk/powerpc/nwmac/partition.c                                  \
+       util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c                      \
+       normal/cmdline.c normal/command.c normal/main.c normal/menu.c   \
+       util/console.c util/pupa-emu.c util/misc.c util/i386/pc/getroot.c
+pupa_emu_LDFLAGS = -lncurses
+
+pupaof_SOURCES = boot/powerpc/nwmac/cmain.c boot/powerpc/nwmac/ieee1275.c \
+       boot/powerpc/nwmac/crt0.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/powerpc/nwmac/init.c term/powerpc/nwmac/ofconsole.c \
+       kern/powerpc/nwmac/openfw.c fs/ext2.c normal/cmdline.c \
+       normal/command.c normal/main.c normal/menu.c \
+       disk/powerpc/nwmac/ofdisk.c disk/powerpc/nwmac/partition.c
+pupaof_HEADERS = pupa/powerpc/nwmac/ieee1275.h
+pupaof_CFLAGS = $(COMMON_CFLAGS)
+pupaof_ASFLAGS = $(COMMON_ASFLAGS)
+pupaof_LDFLAGS = -Wl,-Ttext,0x200000,-Bstatic
+
+# For genmoddep.
+genmoddep_SOURCES = util/genmoddep.c
+
+# Modules.
diff -uprN ../pupa/configure.ac ./configure.ac
--- ../pupa/configure.ac        2003-12-03 20:17:25.000000000 +0100
+++ ./configure.ac      2004-01-24 00:16:13.000000000 +0100
@@ -22,11 +22,13 @@ AC_CANONICAL_HOST
 
 case "$host_cpu" in
   i[[3456]]86) host_cpu=i386 ;;
+  powerpc) ;;
   *) AC_MSG_ERROR([unsupported CPU type]) ;;
 esac
 
 case "$host_cpu"-"$host_vendor" in
   i386-*) host_vendor=pc ;;
+  powerpc-*) host_vendor=nwmac ;;
   *) AC_MSG_ERROR([unsupported machine type]) ;;
 esac
 
@@ -80,9 +82,11 @@ AC_SUBST(CFLAGS)
 
 # Defined in aclocal.m4.
 pupa_ASM_USCORE
-pupa_CHECK_START_SYMBOL
-pupa_CHECK_BSS_START_SYMBOL
-pupa_CHECK_END_SYMBOL
+if test "x$host_cpu" = xi386; then
+  pupa_CHECK_START_SYMBOL
+  pupa_CHECK_BSS_START_SYMBOL
+  pupa_CHECK_END_SYMBOL
+fi
 
 if test "x$host_cpu" = xi386; then
   pupa_I386_ASM_PREFIX_REQUIREMENT
@@ -106,11 +110,11 @@ AC_PATH_PROG(RUBY, ruby)
 
 # For cross-compiling.
 if test "x$build" = "x$host"; then
-  BUILD_CC="$CC"
-  AC_SUBST(BUILD_CC)
-else
   AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc],
                 [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC 
manually.])])
+else
+  BUILD_CC="$CC"
+  AC_SUBST(BUILD_CC)
 fi
 
 # Test the C compiler for the build environment.
@@ -126,11 +130,13 @@ AC_C_BIGENDIAN
 AC_CHECK_SIZEOF(void *)
 AC_CHECK_SIZEOF(long)
 
-# Check LZO.
-AC_CHECK_LIB(lzo, __lzo_init2, ,
-            AC_MSG_ERROR([LZO library version 1.02 or later is required]))
-AC_CHECK_FUNC(lzo1x_999_compress, , 
-             [AC_MSG_ERROR([LZO1X-999 must be enabled])])
+# Check LZO when compiling for the i386.
+if test "x$host_cpu" = xi386; then
+  AC_CHECK_LIB(lzo, __lzo_init2, ,
+              AC_MSG_ERROR([LZO library version 1.02 or later is required]))
+  AC_CHECK_FUNC(lzo1x_999_compress, , 
+               [AC_MSG_ERROR([LZO1X-999 must be enabled])])
+fi
 
 CC="$tmp_CC"
 CFLAGS="$tmp_CFLAGS"
diff -uprN ../pupa/disk/powerpc/nwmac/ofdisk.c ./disk/powerpc/nwmac/ofdisk.c
--- ../pupa/disk/powerpc/nwmac/ofdisk.c 1970-01-01 01:00:00.000000000 +0100
+++ ./disk/powerpc/nwmac/ofdisk.c       2004-01-23 23:51:47.000000000 +0100
@@ -0,0 +1,161 @@
+/* ofdisk.c - Open Firmware disk access.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/misc.h>
+#include <pupa/disk.h>
+#include <pupa/mm.h>
+#include <pupa/machine/ieee1275.h>
+
+static int
+pupa_ofdisk_iterate (int (*hook) (const char *name))
+{
+  int dev_iterate (struct pupa_ieee1275_devalias *alias)
+    {
+      if (! pupa_strcmp (alias->type, "block"))
+       hook (alias->name);
+      return 0;
+    }
+
+  pupa_devalias_iterate (dev_iterate);
+  return 0;
+}
+
+static pupa_err_t
+pupa_ofdisk_open (const char *name, pupa_disk_t disk)
+{
+  pupa_ieee1275_phandle_t devalias;
+  pupa_ieee1275_phandle_t dev;
+  pupa_ieee1275_ihandle_t dev_ihandle = 0;
+  char *devpath = 0;
+  /* XXX: This should be large enough for any possible case.  */
+  char prop[64];
+  pupa_size_t pathlen;
+  int actual;
+
+  if (pupa_ieee1275_finddevice ("/aliases", &devalias))
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Can't read the aliases");
+  
+  pupa_ieee1275_get_property_length (devalias, name, &pathlen);
+  devpath = pupa_malloc (pathlen);
+  if (! devpath)
+    return pupa_errno;
+
+  if (pupa_ieee1275_get_property (devalias, name, devpath, pathlen, &actual))
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "No such device alias");
+
+  /* To access the complete disk add `:0'.  */
+  pupa_strcat (devpath, ":0");
+  pupa_ieee1275_open (devpath, &dev_ihandle);
+  if (! dev_ihandle)
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Can't open device");
+  
+  if (pupa_ieee1275_finddevice (devpath, &dev))
+    {
+      pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Can't read device properties");
+      goto fail;
+    }
+
+  if (pupa_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
+                                 &actual))
+    {
+      pupa_error (PUPA_ERR_BAD_DEVICE, "Can't read the device type");
+      goto fail;
+    }
+
+  if (pupa_strcmp (prop, "block"))
+    {
+      pupa_error (PUPA_ERR_BAD_DEVICE, "Not a block device");
+      goto fail;
+    }
+
+  /* XXX: There is no property to read the number of blocks.  There
+     should be a property `#blocks', but it is not there.  Perhaps it
+     is possible to use seek for this.  */
+  disk->total_sectors = 0xFFFFFFFFUL;
+
+  /* XXX: Is it ok to use this?  Perhaps it is better to use the path
+     or some property.  */
+  disk->id = dev;
+
+  /* XXX: Read this, somehow.  */
+  disk->has_partitions = 1;
+  disk->data = (void *) dev_ihandle;
+
+ fail:
+  if (pupa_errno)
+    pupa_ieee1275_close (dev_ihandle);
+  pupa_free (devpath);
+  return pupa_errno;
+}
+
+static void
+pupa_ofdisk_close (pupa_disk_t disk)
+{
+  pupa_ieee1275_close ((pupa_ieee1275_ihandle_t) disk->data);
+}
+
+static pupa_err_t
+pupa_ofdisk_read (pupa_disk_t disk, unsigned long sector,
+                 unsigned long size, char *buf)
+{
+  int status;
+  int actual;
+  unsigned long long pos;
+
+  pos = (unsigned long long) sector * 512UL;
+
+  pupa_ieee1275_seek ((pupa_ieee1275_ihandle_t) disk->data, (int) (pos >> 32),
+                     (int) pos & 0xFFFFFFFFUL, &status);
+  if (status != 0)
+    return pupa_error (PUPA_ERR_READ_ERROR,
+                      "Seek error, can't seek block %d", sector);
+  pupa_ieee1275_read ((pupa_ieee1275_ihandle_t) disk->data, buf,
+                     size * 512UL, &actual);
+  if (actual != actual)
+    return pupa_error (PUPA_ERR_READ_ERROR, "Read error on block: %d", sector);
+    
+  return 0;
+}
+
+static pupa_err_t
+pupa_ofdisk_write (pupa_disk_t disk __attribute ((unused)),
+                  unsigned long sector __attribute ((unused)),
+                  unsigned long size __attribute ((unused)),
+                  const char *buf __attribute ((unused)))
+{
+  return PUPA_ERR_NOT_IMPLEMENTED_YET;
+}
+
+static struct pupa_disk_dev pupa_ofdisk_dev =
+  {
+    .name = "ofdisk",
+    .iterate = pupa_ofdisk_iterate,
+    .open = pupa_ofdisk_open,
+    .close = pupa_ofdisk_close,
+    .read = pupa_ofdisk_read,
+    .write = pupa_ofdisk_write,
+    .next = 0
+  };
+
+void
+pupa_ofdisk_init (void)
+{
+  pupa_disk_dev_register (&pupa_ofdisk_dev);
+}
diff -uprN ../pupa/disk/powerpc/nwmac/partition.c 
./disk/powerpc/nwmac/partition.c
--- ../pupa/disk/powerpc/nwmac/partition.c      1970-01-01 01:00:00.000000000 
+0100
+++ ./disk/powerpc/nwmac/partition.c    2004-01-23 23:27:29.000000000 +0100
@@ -0,0 +1,120 @@
+/* partiton.c - Read macintosh partition tables.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/disk.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/machine/partition.h>
+
+pupa_err_t
+pupa_partition_iterate (pupa_disk_t disk,
+                       int (*hook) (const pupa_partition_t partition))
+{
+  struct pupa_partition part;
+  struct pupa_apple_part apart;
+  struct pupa_disk raw;
+  int partno = 0;
+  int pos = PUPA_DISK_SECTOR_SIZE * 2;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+
+  for (;;)
+    {
+      if (pupa_disk_read (&raw, pos / PUPA_DISK_SECTOR_SIZE,
+                     pos % PUPA_DISK_SECTOR_SIZE,
+                         sizeof (struct pupa_apple_part),  (char *) &apart))
+       return pupa_errno;
+
+      if (apart.magic !=  PUPA_APPLE_PART_MAGIC)
+       return PUPA_ERR_UNKNOWN_DEVICE;
+
+      part.start = apart.first_phys_block;
+      part.len = apart.blockcnt;
+      part.offset = pos;
+      part.index = partno;
+
+      if (hook (&part))
+       return pupa_errno;
+
+      if (apart.first_phys_block == PUPA_DISK_SECTOR_SIZE * 2)
+       return 0;
+
+      pos += sizeof (struct pupa_apple_part);
+      partno++;
+    }
+
+  return 0;
+}
+
+pupa_partition_t
+pupa_partition_probe (pupa_disk_t disk, const char *str)
+{
+  pupa_partition_t p;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  int find_func (const pupa_partition_t partition)
+    {
+      if (partnum == partition->index)
+       {
+         p = (pupa_partition_t) pupa_malloc (sizeof (*p));
+         if (! p)
+           return 1;
+         
+         pupa_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  /* Get the partition number.  */
+  partnum = pupa_strtoul (s, &s, 0);
+  if (pupa_errno)
+    {
+      pupa_error (PUPA_ERR_BAD_FILENAME, "invalid partition");
+      return 0;
+    }
+
+  if (pupa_partition_iterate (disk, find_func))
+    goto fail;
+  
+  return p;
+
+ fail:
+  pupa_free (p);
+  return 0;
+
+}
+
+char *
+pupa_partition_get_name (const pupa_partition_t p)
+{
+  char *name;
+
+  name = pupa_malloc (13);
+  if (! name)
+    return 0;
+
+  pupa_sprintf (name, "%d", p->index);
+  return name;
+}
diff -uprN ../pupa/genmk.rb ./genmk.rb
--- ../pupa/genmk.rb    2003-09-25 22:29:32.000000000 +0200
+++ ./genmk.rb  2004-01-03 21:23:43.000000000 +0100
@@ -170,7 +170,7 @@ class Utility
   def rule(sources)
     prefix = @name.to_var
     objs = sources.collect do |src|
-      raise "unknown source file `#{src}'" if /\.c$/ !~ src
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
       prefix + '-' + src.to_obj
     end
     objs_str = objs.join(' ');
diff -uprN ../pupa/include/pupa/powerpc/nwmac/biosdisk.h 
./include/pupa/powerpc/nwmac/biosdisk.h
--- ../pupa/include/pupa/powerpc/nwmac/biosdisk.h       1970-01-01 
01:00:00.000000000 +0100
+++ ./include/pupa/powerpc/nwmac/biosdisk.h     2004-01-03 21:24:55.000000000 
+0100
@@ -0,0 +1,47 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_BIOSDISK_MACHINE_HEADER
+#define PUPA_BIOSDISK_MACHINE_HEADER   1
+
+#define PUPA_BIOSDISK_FLAG_LBA 1
+
+struct pupa_biosdisk_data
+{
+  int drive;
+  unsigned long cylinders;
+  unsigned long heads;
+  unsigned long sectors;
+  unsigned long flags;
+};
+
+int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
+int pupa_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+                              int soff, int nsec, int segment);
+int pupa_biosdisk_check_int13_extensions (int drive);
+int pupa_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp);
+int pupa_biosdisk_get_diskinfo_standard (int drive,
+                                        unsigned long *cylinders,
+                                        unsigned long *heads,
+                                        unsigned long *sectors);
+int pupa_biosdisk_get_num_floppies (void);
+
+void pupa_biosdisk_init (void);
+
+#endif /* ! PUPA_BIOSDISK_MACHINE_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/nwmac/console.h 
./include/pupa/powerpc/nwmac/console.h
--- ../pupa/include/pupa/powerpc/nwmac/console.h        1970-01-01 
01:00:00.000000000 +0100
+++ ./include/pupa/powerpc/nwmac/console.h      2004-01-03 21:25:00.000000000 
+0100
@@ -0,0 +1,56 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <address@hidden>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_CONSOLE_MACHINE_HEADER
+#define PUPA_CONSOLE_MACHINE_HEADER    1
+
+/* Define scan codes.  */
+#define PUPA_CONSOLE_KEY_LEFT          0x4B00
+#define PUPA_CONSOLE_KEY_RIGHT         0x4D00
+#define PUPA_CONSOLE_KEY_UP            0x4800
+#define PUPA_CONSOLE_KEY_DOWN          0x5000
+#define PUPA_CONSOLE_KEY_IC            0x5200
+#define PUPA_CONSOLE_KEY_DC            0x5300
+#define PUPA_CONSOLE_KEY_BACKSPACE     0x0008
+#define PUPA_CONSOLE_KEY_HOME          0x4700
+#define PUPA_CONSOLE_KEY_END           0x4F00
+#define PUPA_CONSOLE_KEY_NPAGE         0x4900
+#define PUPA_CONSOLE_KEY_PPAGE         0x5100
+
+#ifndef ASM_FILE
+
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+
+/* These are global to share code between C and asm.  */
+extern pupa_uint8_t pupa_console_cur_color;
+void pupa_console_real_putchar (int c);
+int EXPORT_FUNC(pupa_console_checkkey) (void);
+int EXPORT_FUNC(pupa_console_getkey) (void);
+pupa_uint16_t pupa_console_getxy (void);
+void pupa_console_gotoxy (pupa_uint8_t x, pupa_uint8_t y);
+void pupa_console_cls (void);
+void pupa_console_setcursor (int on);
+
+/* Initialize the console system.  */
+void pupa_console_init (void);
+
+#endif
+
+#endif /* ! PUPA_CONSOLE_MACHINE_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/nwmac/ieee1275.h 
./include/pupa/powerpc/nwmac/ieee1275.h
--- ../pupa/include/pupa/powerpc/nwmac/ieee1275.h       1970-01-01 
01:00:00.000000000 +0100
+++ ./include/pupa/powerpc/nwmac/ieee1275.h     2004-01-23 22:06:11.000000000 
+0100
@@ -0,0 +1,91 @@
+/* ieee1275.h - Access the Open Firmware client interface.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_IEEE1275_MACHINE_HEADER
+#define PUPA_IEEE1275_MACHINE_HEADER   1
+
+#include <stdint.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+
+/* Maps a device alias to a pathname.  */
+struct pupa_ieee1275_devalias
+{
+  char *name;
+  char *path;
+  char *type;
+};
+
+struct pupa_ieee1275_mem_region 
+{
+  unsigned int start;
+  unsigned int size;
+};
+
+/* FIXME jrydberg: is this correct cell types? */
+typedef intptr_t pupa_ieee1275_ihandle_t;
+typedef intptr_t pupa_ieee1275_phandle_t;
+
+
+
+uint32_t EXPORT_FUNC(pupa_ieee1275_decode_int_4) (unsigned char *p);
+int EXPORT_FUNC(pupa_ieee1275_finddevice) (char *name,
+                                          pupa_ieee1275_phandle_t *phandlep);
+int EXPORT_FUNC(pupa_ieee1275_get_property) (int handle, const char *property,
+                                            void *buf, pupa_size_t size,
+                                            pupa_size_t *actual);
+int EXPORT_FUNC(pupa_ieee1275_next_property) (int handle, char *prev_prop,
+                                             char *prop, int *flags);
+int EXPORT_FUNC(pupa_ieee1275_get_property_length) 
+     (pupa_ieee1275_phandle_t handle, const char *prop, pupa_size_t *length);
+int EXPORT_FUNC(pupa_ieee1275_instance_to_package) 
+     (pupa_ieee1275_ihandle_t ihandle, pupa_ieee1275_phandle_t *phandlep);
+int EXPORT_FUNC(pupa_ieee1275_package_to_path) (pupa_ieee1275_phandle_t 
phandle,
+                                               char *path, pupa_size_t len,
+                                               pupa_size_t *actual);
+int EXPORT_FUNC(pupa_ieee1275_instance_to_path) 
+     (pupa_ieee1275_ihandle_t ihandle, char *path, pupa_size_t len,
+      pupa_size_t *actual);
+int EXPORT_FUNC(pupa_ieee1275_write) (pupa_ieee1275_ihandle_t ihandle,
+                                     void *buffer, pupa_size_t len,
+                                     pupa_size_t *actualp);
+int EXPORT_FUNC(pupa_ieee1275_read) (pupa_ieee1275_ihandle_t ihandle,
+                                    void *buffer, pupa_size_t len,
+                                    pupa_size_t *actualp);
+int EXPORT_FUNC(pupa_ieee1275_seek) (pupa_ieee1275_ihandle_t ihandle,
+                                    int pos_hi, int pos_lo, int *result);
+int EXPORT_FUNC(pupa_ieee1275_peer) (pupa_ieee1275_phandle_t node,
+                                    pupa_ieee1275_phandle_t *result);
+int EXPORT_FUNC(pupa_ieee1275_child) (pupa_ieee1275_phandle_t node,
+                                     pupa_ieee1275_phandle_t *result);
+int EXPORT_FUNC(pupa_ieee1275_parent) (pupa_ieee1275_phandle_t node,
+                                      pupa_ieee1275_phandle_t *result);
+int EXPORT_FUNC(pupa_ieee1275_exit) (void);
+int EXPORT_FUNC(pupa_ieee1275_open) (char *node,
+                                    pupa_ieee1275_ihandle_t *result);
+int EXPORT_FUNC(pupa_ieee1275_close) (pupa_ieee1275_ihandle_t ihandle);
+int EXPORT_FUNC(pupa_ieee1275_claim) (void *p, pupa_size_t size, unsigned int 
align,
+                                     void **result);
+
+pupa_err_t EXPORT_FUNC(pupa_devalias_iterate)
+     (int (*hook) (struct pupa_ieee1275_devalias *alias));
+
+
+#endif /* ! PUPA_IEEE1275_MACHINE_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/nwmac/partition.h 
./include/pupa/powerpc/nwmac/partition.h
--- ../pupa/include/pupa/powerpc/nwmac/partition.h      1970-01-01 
01:00:00.000000000 +0100
+++ ./include/pupa/powerpc/nwmac/partition.h    2004-01-24 00:07:28.000000000 
+0100
@@ -0,0 +1,141 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2004  Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_PARTITION_HEADER
+#define PUPA_PARTITION_HEADER  1
+
+#include <pupa/symbol.h>
+#include <pupa/types.h>
+#include <pupa/err.h>
+
+#define PUPA_APPLE_PART_MAGIC  0x504D
+
+struct pupa_apple_part
+{
+  /* The magic number to idenify this as a partition, it should have
+     the value `0x504D'.  */
+  pupa_uint16_t magic;
+
+  /* Reserved.  */
+  pupa_uint16_t reserved;
+
+  /* The size of the partition map in blocks.  */
+  pupa_uint32_t partmap_size;
+
+  /* The first physical block of the partition.  */
+  pupa_uint32_t first_phys_block;
+
+  /* The amount of blocks.  */
+  pupa_uint32_t blockcnt;
+
+  /* The partition name.  */
+  char partname[32];
+
+  /* The partition type.  */
+  char parttype[32];
+
+  /* The first datablock of the partition.  */
+  pupa_uint32_t datablocks_first;
+
+  /* The amount datablocks.  */
+  pupa_uint32_t datablocks_count;
+
+  /* The status of the partition. (???)  */
+  pupa_uint32_t status;
+
+  /* The first block on which the bootcode can be found.  */
+  pupa_uint32_t bootcode_pos;
+
+  /* The size of the bootcode in bytes.  */
+  pupa_uint32_t bootcode_size;
+
+  /* The load address of the bootcode.  */
+  pupa_uint32_t bootcode_loadaddr;
+
+  /* Reserved.  */
+  pupa_uint32_t reserved2;
+  
+  /* The entrypoint of the bootcode.  */
+  pupa_uint32_t bootcode_entrypoint;
+
+  /* Reserved.  */
+  pupa_uint32_t reserved3;
+
+  /* A checksum of the bootcode.  */
+  pupa_uint32_t bootcode_checksum;
+
+  /* The processor type.  */
+  char processor[16];
+
+  /* Padding.  */
+  pupa_uint16_t pad[187];
+};
+
+/* Partition description.  */
+struct pupa_partition
+{
+  /* The start sector.  */
+  unsigned long start;
+
+  /* The length in sector units.  */
+  unsigned long len;
+
+  /* The offset of the partition table.  */
+  unsigned long offset;
+
+  /* The index of this partition in the partition table.  */
+  int index;
+  
+  /* The DOS partition number.  */
+  int dos_part;
+
+  /* The BSD partition number (a == 0).  */
+  int bsd_part;
+
+  /* The DOS partition type.  */
+  int dos_type;
+
+  /* The BSD partition type.  */
+  int bsd_type;
+};
+typedef struct pupa_partition *pupa_partition_t;
+
+struct pupa_disk;
+
+pupa_partition_t EXPORT_FUNC(pupa_partition_probe) (struct pupa_disk *disk,
+                                                   const char *str);
+pupa_err_t EXPORT_FUNC(pupa_partition_iterate) (struct pupa_disk *disk,
+                                               int (*hook) (const 
pupa_partition_t partition));
+char *EXPORT_FUNC(pupa_partition_get_name) (const pupa_partition_t partition);
+
+
+static inline unsigned long
+pupa_partition_get_start (const pupa_partition_t p)
+{
+  return p->start;
+}
+
+static inline unsigned long
+pupa_partition_get_len (const pupa_partition_t p)
+{
+  return p->len;
+}
+
+#endif /* ! PUPA_PARTITION_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/nwmac/time.h 
./include/pupa/powerpc/nwmac/time.h
--- ../pupa/include/pupa/powerpc/nwmac/time.h   1970-01-01 01:00:00.000000000 
+0100
+++ ./include/pupa/powerpc/nwmac/time.h 2004-01-03 21:25:18.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003 Marco Gerards <address@hidden>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef KERNEL_TIME_HEADER
+#define KERNEL_TIME_HEADER     1
+
+#ifdef PUPA_UTIL
+# include <time.h>
+# define PUPA_TICKS_PER_SECOND CLOCKS_PER_SEC
+#else
+# define PUPA_TICKS_PER_SECOND 18
+#endif
+
+/* Return the real time in ticks.  */
+pupa_uint32_t pupa_get_rtc (void);
+
+#endif /* ! KERNEL_TIME_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/nwmac/util/biosdisk.h 
./include/pupa/powerpc/nwmac/util/biosdisk.h
--- ../pupa/include/pupa/powerpc/nwmac/util/biosdisk.h  1970-01-01 
01:00:00.000000000 +0100
+++ ./include/pupa/powerpc/nwmac/util/biosdisk.h        2004-01-03 
21:26:56.000000000 +0100
@@ -0,0 +1,28 @@
+/* biosdisk.h - emulate biosdisk */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_BIOSDISK_MACHINE_UTIL_HEADER
+#define PUPA_BIOSDISK_MACHINE_UTIL_HEADER      1
+
+void pupa_util_biosdisk_init (const char *dev_map);
+void pupa_util_biosdisk_fini (void);
+char *pupa_util_biosdisk_get_pupa_dev (const char *os_dev);
+
+#endif /* ! PUPA_BIOSDISK_MACHINE_UTIL_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/setjmp.h ./include/pupa/powerpc/setjmp.h
--- ../pupa/include/pupa/powerpc/setjmp.h       1970-01-01 01:00:00.000000000 
+0100
+++ ./include/pupa/powerpc/setjmp.h     2004-01-03 21:27:00.000000000 +0100
@@ -0,0 +1,25 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003  Yoshinori K. Okuji <address@hidden>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_SETJMP_CPU_HEADER
+#define PUPA_SETJMP_CPU_HEADER 1
+
+typedef unsigned long pupa_jmp_buf[6];
+
+#endif /* ! PUPA_SETJMP_CPU_HEADER */
diff -uprN ../pupa/include/pupa/powerpc/types.h ./include/pupa/powerpc/types.h
--- ../pupa/include/pupa/powerpc/types.h        1970-01-01 01:00:00.000000000 
+0100
+++ ./include/pupa/powerpc/types.h      2004-01-24 00:07:20.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_TYPES_CPU_HEADER
+#define PUPA_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define PUPA_HOST_SIZEOF_VOID_P        4
+
+/* The size of long.  */
+#define PUPA_HOST_SIZEOF_LONG  4
+
+/* powerpc is little-endian.  */
+#undef PUPA_HOST_WORDS_LITTLEENDIAN
+
+#endif /* ! PUPA_TYPES_CPU_HEADER */
diff -uprN ../pupa/kern/powerpc/nwmac/init.c ./kern/powerpc/nwmac/init.c
--- ../pupa/kern/powerpc/nwmac/init.c   1970-01-01 01:00:00.000000000 +0100
+++ ./kern/powerpc/nwmac/init.c 2004-01-23 23:46:56.000000000 +0100
@@ -0,0 +1,106 @@
+/*  init.c -- Initialize PUPA on the newworld mac (PPC).  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/kernel.h>
+#include <pupa/dl.h>
+#include <pupa/disk.h>
+#include <pupa/mm.h>
+#include <pupa/machine/partition.h>
+#include <pupa/machine/ieee1275.h>
+#include <pupa/normal.h>
+#include <pupa/fs.h>
+#include <pupa/setjmp.h>
+
+void pupa_ofdisk_init (void);
+void pupa_console_init (void);
+
+
+/* XXX: Modules are not yet supported.  */
+pupa_addr_t pupa_end_addr = -1;
+pupa_addr_t pupa_total_module_size = 0;
+
+void
+abort (void)
+{
+  for (;;);
+}
+
+void
+pupa_machine_init (void)
+{
+  void *mem;
+
+  if (pupa_ieee1275_claim ((void *) 0x300000, 0x100000, 0, &mem) == -1)
+    abort (); /* Damn, we are in trouble!  */
+  
+  /* The memory allocations were copied from yaboot.  */
+  pupa_mm_init_region ((void *) 0x300000, 0x100000);
+
+  /* XXX: Loadable modules are not supported.  */
+  pupa_dl_set_prefix ("");
+
+  pupa_ext2_init ();
+  pupa_ofdisk_init ();
+  pupa_console_init ();
+  pupa_normal_init ();
+}
+
+int
+pupa_arch_dl_check_header (void *ehdr __attribute ((unused)),
+                          pupa_size_t size __attribute ((unused)))
+{
+  return 0;
+}
+
+pupa_err_t
+pupa_arch_dl_relocate_symbols (pupa_dl_t mod __attribute ((unused)),
+                              void *ehdr __attribute ((unused)))
+{
+  return 0;
+}
+
+void
+pupa_stop (void)
+{
+  for (;;);
+}
+
+void
+pupa_register_exported_symbols (void)
+{
+}
+
+pupa_uint32_t
+pupa_get_rtc (void)
+{
+  return 0;
+}
+
+int
+pupa_setjmp (pupa_jmp_buf env __attribute ((unused)))
+{
+  return 0;
+}
+
+void
+pupa_longjmp (pupa_jmp_buf env __attribute ((unused)),
+             int val __attribute ((unused)))
+{
+}
diff -uprN ../pupa/kern/powerpc/nwmac/openfw.c ./kern/powerpc/nwmac/openfw.c
--- ../pupa/kern/powerpc/nwmac/openfw.c 1970-01-01 01:00:00.000000000 +0100
+++ ./kern/powerpc/nwmac/openfw.c       2004-01-23 21:59:54.000000000 +0100
@@ -0,0 +1,86 @@
+/*  openfw.c -- Open firmware support funtions.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/err.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/machine/ieee1275.h>
+
+/* Iterate through all device aliasses.  Thisfunction can be used to
+   find a device of a specific type.  */
+pupa_err_t
+pupa_devalias_iterate (int (*hook) (struct pupa_ieee1275_devalias *alias))
+{
+  pupa_ieee1275_phandle_t devalias;
+  char aliasname[32];
+  int actual;
+  struct pupa_ieee1275_devalias alias;
+
+  if (pupa_ieee1275_finddevice ("/aliases", &devalias))
+    return -1;
+
+  /* XXX: Is this the right way to find the first property?  */
+  aliasname[0] = '\0';
+
+  /* XXX: Are the while conditions correct?  */
+  while (pupa_ieee1275_next_property (devalias, aliasname, aliasname, &actual)
+        || actual)
+    {
+      pupa_ieee1275_phandle_t dev;
+      pupa_size_t pathlen;
+      char *devpath;
+      /* XXX: This should be large enough for any possible case.  */
+      char devtype[64];
+  
+      pupa_ieee1275_get_property_length (devalias, aliasname, &pathlen);
+      devpath = pupa_malloc (pathlen);
+      if (! devpath)
+       return pupa_errno;
+
+      if (pupa_ieee1275_get_property (devalias, aliasname, devpath, pathlen,
+                                     &actual))
+       {
+         pupa_free (devpath);
+         continue;
+       }
+
+      if (pupa_ieee1275_finddevice (devpath, &dev))
+       {
+         pupa_free (devpath);
+         continue;
+       }
+
+      if (pupa_ieee1275_get_property (dev, "device_type", devtype, sizeof 
devtype,
+                                     &actual))
+       {
+         pupa_free (devpath);
+         continue;
+       }
+
+      alias.name = aliasname;
+      alias.path= devpath;
+      alias.type = devtype;
+      hook (&alias);
+      
+      pupa_free (devpath);
+    }
+
+  return 0;
+}
diff -uprN ../pupa/normal/cmdline.c ./normal/cmdline.c
--- ../pupa/normal/cmdline.c    2003-12-03 20:17:27.000000000 +0100
+++ ./normal/cmdline.c  2004-01-24 00:09:08.000000000 +0100
@@ -1,8 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
- *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
  *  Copyright (C) 2003  Yoshinori K. Okuji <address@hidden>
- *  Copyright (C) 2003 Marco Gerards <address@hidden>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -289,6 +288,7 @@ pupa_tab_complete (char *buf, int *resto
            add_completion (devname, ")", "disks", print_simple_completion);
        }
 
+      pupa_errno = PUPA_ERR_NONE;
       return 0;
     }
 
diff -uprN ../pupa/term/powerpc/nwmac/ofconsole.c 
./term/powerpc/nwmac/ofconsole.c
--- ../pupa/term/powerpc/nwmac/ofconsole.c      1970-01-01 01:00:00.000000000 
+0100
+++ ./term/powerpc/nwmac/ofconsole.c    2004-01-23 21:59:42.000000000 +0100
@@ -0,0 +1,266 @@
+/*  ofconsole.c -- Open Firmware console for PUPA.  */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/console.h>
+#include <pupa/machine/ieee1275.h>
+#include <pupa/term.h>
+#include <pupa/types.h>
+#include <pupa/misc.h>
+
+static pupa_ieee1275_ihandle_t stdout_ihandle;
+static pupa_ieee1275_ihandle_t stdin_ihandle;
+
+static int pupa_curr_x;
+static int pupa_curr_y;
+
+static int pupa_keybuf;
+static int pupa_buflen;
+
+/* Write control characters to the console.  */
+static void
+pupa_ofconsole_writeesc (const char *str)
+{
+  while (*str)
+    {
+      char chr = *(str++);
+      pupa_ieee1275_write (stdout_ihandle, &chr, 1, 0);
+    }
+  
+}
+
+static void
+pupa_ofconsole_putchar (pupa_uint32_t c)
+{
+  char chr = c;
+  if (c == '\n')
+    {
+      pupa_curr_y++;
+      pupa_curr_x = 0;
+    }
+  else
+    pupa_curr_x++;
+  pupa_ieee1275_write (stdout_ihandle, &chr, 1, 0);
+}
+
+static void
+pupa_ofconsole_setcolorstate (pupa_term_color_state state)
+{
+  switch (state)
+    {
+    case PUPA_TERM_COLOR_STANDARD:
+      pupa_ofconsole_writeesc ("\e[0m");
+      break;
+    case PUPA_TERM_COLOR_NORMAL:
+      pupa_ofconsole_writeesc ("\e[0m");
+      break;
+    case PUPA_TERM_COLOR_HIGHLIGHT:
+      pupa_ofconsole_writeesc ("\e[7m");
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+pupa_ofconsole_setcolor (pupa_uint8_t normal_color __attribute ((unused)),
+                        pupa_uint8_t highlight_color __attribute ((unused)))
+{
+}
+
+static int
+pupa_ofconsole_readkey (int *key)
+{
+  char c;
+  int actual = 0;
+
+  pupa_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+
+  if (actual && c == '\e')
+    {
+      pupa_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+      if (! actual)
+       {
+         *key = '\e';
+         return 1;
+       }
+      
+      if (c != 91)
+       return 0;
+      
+      pupa_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+      if (! actual)
+       return 0;
+      
+      switch (c)
+       {
+       case 65:
+         /* Up: Ctrl-p.  */
+         c = 16; 
+         break;
+       case 66:
+         /* Down: Ctrl-n.  */
+         c = 14;
+         break;
+       case 67:
+         /* Right: Ctrl-f.  */
+         c = 6;
+         break;
+       case 68:
+         /* Left: Ctrl-b.  */
+         c = 2;
+         break;
+       }
+    }
+  
+  *key = c;
+  return actual;
+}
+
+static int
+pupa_ofconsole_checkkey (void)
+{
+  int key;
+  int read;
+  
+  if (pupa_buflen)
+    return 1;
+
+  read = pupa_ofconsole_readkey (&key);
+  if (read)
+    {
+      pupa_keybuf = key;
+      pupa_buflen = 1;
+      return 1;
+    }
+    
+  return 0;
+}
+
+static int
+pupa_ofconsole_getkey (void)
+{
+  int key;
+
+  if (pupa_buflen)
+    {
+      pupa_buflen  =0;
+      return pupa_keybuf;
+    }
+
+  while (! pupa_ofconsole_readkey (&key));
+  
+  return key;
+}
+
+static pupa_uint16_t
+pupa_ofconsole_getxy (void)
+{
+  return ((pupa_curr_x - 1) << 8) | pupa_curr_y;
+}
+
+static void
+pupa_ofconsole_gotoxy (pupa_uint8_t x, pupa_uint8_t y)
+{
+  char s[11]; /* 5 + 3 + 3.  */
+  pupa_curr_x = x;
+  pupa_curr_y = y;
+
+  pupa_sprintf (s, "\e[%d;%dH", y - 1, x + 1);
+  pupa_ofconsole_writeesc (s);
+}
+
+static void
+pupa_ofconsole_cls (void)
+{
+  /* Clear the screen.  */
+  pupa_ofconsole_writeesc ("");
+}
+
+static void
+pupa_ofconsole_setcursor (int on __attribute ((unused)))
+{
+  /* XXX: Not supported.  */
+}
+
+static void
+pupa_ofconsole_refresh (void)
+{
+}
+
+static pupa_err_t
+pupa_ofconsole_init (void)
+{
+  pupa_ieee1275_phandle_t chosen;
+  char data[4];
+  pupa_size_t actual;
+
+  if (pupa_ieee1275_finddevice ("/chosen", &chosen))
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Cannot find /chosen");
+
+  if (pupa_ieee1275_get_property (chosen, "stdout", data, sizeof data,
+                            &actual)
+      || actual != sizeof data)
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Cannot find stdout");
+
+  stdout_ihandle = pupa_ieee1275_decode_int_4 (data);
+  
+   if (pupa_ieee1275_get_property (chosen, "stdin", data, sizeof data,
+                            &actual)
+      || actual != sizeof data)
+    return pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "Cannot find stdin");
+
+  stdin_ihandle = pupa_ieee1275_decode_int_4 (data);
+
+  return 0;
+}
+
+static pupa_err_t
+pupa_ofconsole_fini (void)
+{
+  return 0;
+}
+
+
+
+static struct pupa_term pupa_ofconsole_term =
+  {
+    .name = "ofconsole",
+    .init = pupa_ofconsole_init,
+    .fini = pupa_ofconsole_fini,
+    .putchar = pupa_ofconsole_putchar,
+    .checkkey = pupa_ofconsole_checkkey,
+    .getkey = pupa_ofconsole_getkey,
+    .getxy = pupa_ofconsole_getxy,
+    .gotoxy = pupa_ofconsole_gotoxy,
+    .cls = pupa_ofconsole_cls,
+    .setcolorstate = pupa_ofconsole_setcolorstate,
+    .setcolor = pupa_ofconsole_setcolor,
+    .setcursor = pupa_ofconsole_setcursor,
+    .refresh = pupa_ofconsole_refresh,
+    .flags = 0,
+    .next = 0
+  };
+
+void
+pupa_console_init (void)
+{
+  pupa_term_register (&pupa_ofconsole_term);
+  pupa_term_set_current (&pupa_ofconsole_term);
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]