[haiku-commits] haiku: hrev43262 - src/system/boot/platform/cfe src/system/boot/platform/cfe/arch/ppc headers/private/kernel/boot/platform/cfe

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 14 Nov 2011 01:36:12 +0100 (CET)

Revision:    hrev43262
Commit:      478dc9887eb692a6664ede1d833ea6d1d0c03a9b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=478dc98
Author:      François Revol <revol@xxxxxxx>
Date:        Mon Nov 14 00:31:50 2011 UTC

PPC: Preliminary untested boot support for Common Firmware Environment
CFE is used in the upcoming Amiga X-1000 dualcore PPC board.
* Largely inspired by the OF and U-Boot code.
* Still largely stubbed out.
* The loader builds but I don't have a machine to test it. Anyone interested?

............................................................................

 docs/develop/ports/ppc/cfe.txt                     |    7 +
 headers/private/kernel/boot/platform/cfe/cfe.h     |   54 ++
 .../kernel/boot/platform/cfe/platform_arch.h       |   38 +
 .../boot/platform/cfe/platform_kernel_args.h       |   24 +
 .../boot/platform/cfe/platform_stage2_args.h       |   15 +
 src/system/boot/platform/cfe/Handle.cpp            |   86 +++
 src/system/boot/platform/cfe/Handle.h              |   34 +
 src/system/boot/platform/cfe/Jamfile               |   37 +
 src/system/boot/platform/cfe/arch/Jamfile          |    3 +
 src/system/boot/platform/cfe/arch/ppc/Jamfile      |   19 +
 .../boot/platform/cfe/arch/ppc/arch_start_kernel.S |   49 ++
 src/system/boot/platform/cfe/arch/ppc/cpu.cpp      |   32 +
 src/system/boot/platform/cfe/arch/ppc/mmu.cpp      |  588 ++++++++++++++++
 src/system/boot/platform/cfe/cfe.cpp               |  264 +++++++
 src/system/boot/platform/cfe/console.cpp           |  170 +++++
 src/system/boot/platform/cfe/console.h             |   21 +
 src/system/boot/platform/cfe/debug.cpp             |   46 ++
 src/system/boot/platform/cfe/devices.cpp           |  138 ++++
 src/system/boot/platform/cfe/heap.cpp              |   48 ++
 src/system/boot/platform/cfe/menu.cpp              |   48 ++
 src/system/boot/platform/cfe/mmu.cpp               |   36 +
 src/system/boot/platform/cfe/start.cpp             |  177 +++++
 src/system/boot/platform/cfe/support.cpp           |   23 +
 src/system/boot/platform/cfe/support.h             |   17 +
 src/system/boot/platform/cfe/video.cpp             |   72 ++
 src/system/ldscripts/ppc/boot_loader_cfe.ld        |   45 ++
 26 files changed, 2091 insertions(+), 0 deletions(-)

diff --git a/docs/develop/ports/ppc/cfe.txt b/docs/develop/ports/ppc/cfe.txt
new file mode 100644
index 0000000..6648cb8
--- /dev/null
+++ b/docs/develop/ports/ppc/cfe.txt
@@ -0,0 +1,7 @@
+http://www.linux-mips.org/wiki/Common_Firmware_Environment
+http://www.broadcom.com/support/communications_processors/downloads.php
+http://www.broadcom.com/docs/SiByte/README-1.4.2.txt
+http://wiki.openwrt.org/doc/techref/bootloader/cfe
+http://amigaos.net/content/2/what%E2%80%99s-new
+http://lguohan.blogspot.com/2010/03/embedded-powerpc.html
+
diff --git a/headers/private/kernel/boot/platform/cfe/cfe.h 
b/headers/private/kernel/boot/platform/cfe/cfe.h
new file mode 100644
index 0000000..f81c420
--- /dev/null
+++ b/headers/private/kernel/boot/platform/cfe/cfe.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef KERNEL_BOOT_PLATFORM_CFE_CFE_H
+#define KERNEL_BOOT_PLATFORM_CFE_CFE_H
+
+
+#include <SupportDefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CFE_EPTSEAL    0x43464531      /* 'CFE1' */
+#define CFE_MAGIC      CFE_EPTSEAL
+
+// cfe/include/cfe_timer.h
+#define CFE_HZ         10
+
+/* CFE sources declare this separately in cfe_api.h */
+
+/* (let's hope it's always built-in,
+   unlike u-boot's API which never is... */
+
+#define CFE_FLG_COLDSTART              0x00000000
+#define CFE_FLG_WARMSTART              0x00000001
+
+#define CFE_STDHANDLE_CONSOLE  0
+
+int cfe_init(uint64 handle, uint64 entry);
+
+int cfe_exit(int32 warm, int32 status);
+uint64 cfe_getticks(void);
+
+int cfe_enumdev(int idx, char *name, int namelen);
+
+int cfe_getstdhandle(int flag);
+int cfe_open(const char *name);
+int cfe_close(int handle);
+
+int cfe_readblk(int handle, int64 offset, void *buffer, int length);
+int cfe_writeblk(int handle, int64 offset, const void *buffer, int length);
+
+#define CFE_OK                 0
+#define CFE_ERR                        -1
+
+status_t cfe_error(int32 err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* KERNEL_BOOT_PLATFORM_CFE_CFE_H */
diff --git a/headers/private/kernel/boot/platform/cfe/platform_arch.h 
b/headers/private/kernel/boot/platform/cfe/platform_arch.h
new file mode 100644
index 0000000..4f114db
--- /dev/null
+++ b/headers/private/kernel/boot/platform/cfe/platform_arch.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the OpenBeOS License.
+ */
+#ifndef KERNEL_BOOT_PLATFORM_CFE_ARCH_H
+#define KERNEL_BOOT_PLATFORM_CFE_ARCH_H
+
+
+#include <SupportDefs.h>
+
+struct kernel_args;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* memory management */
+       
+extern status_t arch_set_callback(void);
+extern void *arch_mmu_allocate(void *address, size_t size,
+       uint8 protection, bool exactAddress);
+extern status_t arch_mmu_free(void *address, size_t size);
+extern status_t arch_mmu_init(void);
+
+/* CPU */
+
+extern status_t boot_arch_cpu_init(void);
+
+/* kernel start */
+
+status_t arch_start_kernel(struct kernel_args *kernelArgs,
+       addr_t kernelEntry, addr_t kernelStackTop);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* KERNEL_BOOT_PLATFORM_CFE_ARCH_H */
diff --git a/headers/private/kernel/boot/platform/cfe/platform_kernel_args.h 
b/headers/private/kernel/boot/platform/cfe/platform_kernel_args.h
new file mode 100644
index 0000000..8cf75e8
--- /dev/null
+++ b/headers/private/kernel/boot/platform/cfe/platform_kernel_args.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the OpenBeOS License.
+ */
+#ifndef KERNEL_BOOT_PLATFORM_CFE_KERNEL_ARGS_H
+#define KERNEL_BOOT_PLATFORM_CFE_KERNEL_ARGS_H
+
+#ifndef KERNEL_BOOT_KERNEL_ARGS_H
+#      error This file is included from <boot/kernel_args.h> only
+#endif
+
+// must match SMP_MAX_CPUS in arch_smp.h
+#define MAX_BOOT_CPUS 4
+#define MAX_PHYSICAL_MEMORY_RANGE 4
+#define MAX_PHYSICAL_ALLOCATED_RANGE 8
+#define MAX_VIRTUAL_ALLOCATED_RANGE 32
+
+
+typedef struct {
+       uint64  cfe_entry;      // pointer but always 64bit
+       //XXX:char      rtc_path[128];
+} platform_kernel_args;
+
+#endif /* KERNEL_BOOT_PLATFORM_CFE_KERNEL_ARGS_H */
diff --git a/headers/private/kernel/boot/platform/cfe/platform_stage2_args.h 
b/headers/private/kernel/boot/platform/cfe/platform_stage2_args.h
new file mode 100644
index 0000000..46073c6
--- /dev/null
+++ b/headers/private/kernel/boot/platform/cfe/platform_stage2_args.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the OpenBeOS License.
+ */
+#ifndef KERNEL_BOOT_PLATFORM_CFE_STAGE2_ARGS_H
+#define KERNEL_BOOT_PLATFORM_CFE_STAGE2_ARGS_H
+
+#ifndef KERNEL_BOOT_STAGE2_ARGS_H
+#      error This file is included from <boot/stage2_args.h> only
+#endif
+
+struct platform_stage2_args {
+};
+
+#endif /* KERNEL_BOOT_PLATFORM_CFE_STAGE2_ARGS_H */
diff --git a/src/system/boot/platform/cfe/Handle.cpp 
b/src/system/boot/platform/cfe/Handle.cpp
new file mode 100644
index 0000000..b648df7
--- /dev/null
+++ b/src/system/boot/platform/cfe/Handle.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include "Handle.h"
+
+#include <SupportDefs.h>
+
+#include <boot/platform/cfe/cfe.h>
+#include <util/kernel_cpp.h>
+
+
+Handle::Handle(int handle, bool takeOwnership)
+       :
+       fHandle(handle),
+       fOwnHandle(takeOwnership)
+{
+}
+
+
+Handle::Handle(void)
+       :
+       fHandle(0)
+{
+}
+
+
+Handle::~Handle()
+{
+       if (fOwnHandle)
+               cfe_close(fHandle);
+}
+
+
+void
+Handle::SetHandle(int handle, bool takeOwnership)
+{
+       if (fHandle && fOwnHandle)
+               cfe_close(fHandle);
+
+       fHandle = handle;
+       fOwnHandle = takeOwnership;
+}
+
+
+ssize_t
+Handle::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
+{
+       int32 err;
+       if (pos == -1)
+               pos = 0;//XXX
+       err = cfe_readblk(fHandle, pos, buffer, bufferSize);
+
+       if (err < 0)
+               return cfe_error(err);
+
+       return err;
+}
+
+
+ssize_t
+Handle::WriteAt(void *cookie, off_t pos, const void *buffer,
+       size_t bufferSize)
+{
+       int32 err;
+       if (pos == -1)
+               pos = 0;//XXX
+       err = cfe_writeblk(fHandle, pos, buffer, bufferSize);
+
+       if (err < 0)
+               return cfe_error(err);
+
+       return err;
+}
+
+
+off_t 
+Handle::Size() const
+{
+       // ToDo: fix this!
+       return 1024LL * 1024 * 1024 * 1024;
+               // 1024 GB
+}
+
diff --git a/src/system/boot/platform/cfe/Handle.h 
b/src/system/boot/platform/cfe/Handle.h
new file mode 100644
index 0000000..937b801
--- /dev/null
+++ b/src/system/boot/platform/cfe/Handle.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef HANDLE_H
+#define HANDLE_H
+
+
+#include <boot/vfs.h>
+
+
+#ifdef __cplusplus
+
+class Handle : public ConsoleNode {
+       public:
+               Handle(int handle, bool takeOwnership = true);
+               Handle();
+               virtual ~Handle();
+
+               void SetHandle(int handle, bool takeOwnership = true);
+
+               virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 
size_t bufferSize);
+               virtual ssize_t WriteAt(void *cookie, off_t pos, const void 
*buffer, size_t bufferSize);
+
+               virtual off_t Size() const;
+
+       protected:
+               int             fHandle;
+               bool    fOwnHandle;
+};
+
+#endif /* __cplusplus */
+
+#endif /* HANDLE_H */
diff --git a/src/system/boot/platform/cfe/Jamfile 
b/src/system/boot/platform/cfe/Jamfile
new file mode 100644
index 0000000..8114492
--- /dev/null
+++ b/src/system/boot/platform/cfe/Jamfile
@@ -0,0 +1,37 @@
+SubDir HAIKU_TOP src system boot platform cfe ;
+
+SubDirC++Flags -D_BOOT_MODE -fno-rtti ;
+
+UsePrivateHeaders [ FDirName graphics common ] ;
+
+SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
+
+KernelMergeObject boot_platform_cfe.o :
+       console.cpp
+       debug.cpp
+       devices.cpp
+       Handle.cpp
+       heap.cpp
+       menu.cpp
+       mmu.cpp
+       #network.cpp
+       #real_time_clock.cpp
+       start.cpp
+       support.cpp
+       video.cpp
+
+       cfe.cpp
+       #cfe_devices.cpp
+
+       :
+       :
+       boot_platform_generic.a
+       boot_platform_cfe_$(TARGET_ARCH).a
+;
+
+SEARCH on [ FGristFiles $(genericPlatformSources) ]
+       = [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
+#SEARCH on [ FGristFiles cfe.cpp cfe_devices.cpp ]
+#      = [ FDirName $(HAIKU_TOP) src system kernel platform cfe ] ;
+
+SubInclude HAIKU_TOP src system boot platform cfe arch ;
diff --git a/src/system/boot/platform/cfe/arch/Jamfile 
b/src/system/boot/platform/cfe/arch/Jamfile
new file mode 100644
index 0000000..6212c17
--- /dev/null
+++ b/src/system/boot/platform/cfe/arch/Jamfile
@@ -0,0 +1,3 @@
+SubDir HAIKU_TOP src system boot platform cfe arch ;
+
+SubInclude HAIKU_TOP src system boot platform cfe arch $(TARGET_ARCH) ;
diff --git a/src/system/boot/platform/cfe/arch/ppc/Jamfile 
b/src/system/boot/platform/cfe/arch/ppc/Jamfile
new file mode 100644
index 0000000..14cc7e7
--- /dev/null
+++ b/src/system/boot/platform/cfe/arch/ppc/Jamfile
@@ -0,0 +1,19 @@
+SubDir HAIKU_TOP src system boot platform cfe arch ppc ;
+
+SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ;
+UsePrivateSystemHeaders ;
+UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] 
+       [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
+
+SubDirC++Flags -fno-rtti ;
+
+KernelStaticLibrary boot_platform_cfe_ppc :
+       arch_mmu.cpp
+       arch_cpu_asm.S
+       arch_start_kernel.S
+       cpu.cpp
+       mmu.cpp
+;
+
+SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ]
+    = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ;
diff --git a/src/system/boot/platform/cfe/arch/ppc/arch_start_kernel.S 
b/src/system/boot/platform/cfe/arch/ppc/arch_start_kernel.S
new file mode 100644
index 0000000..2156e1d
--- /dev/null
+++ b/src/system/boot/platform/cfe/arch/ppc/arch_start_kernel.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005, Ingo Weinhold <bonefish@xxxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#define FUNCTION(x) .global x; .type x,@function; x
+
+/*     status_t arch_start_kernel(struct kernel_args *kernelArgs,
+               addr_t kernelEntry, addr_t kernelStackTop);
+
+       r3      - kernelArgs
+       r4      - kernelEntry
+       r5      - kernelStackTop
+*/
+FUNCTION(arch_start_kernel):
+       // push a stack frame
+       stwu    %r1, -32(%r1)
+       mflr    %r0
+       stw             %r0, 36(%r1)
+
+       // save the old stack pointer in r29
+       stw             %r29, 20(%r1)
+       mr              %r29, %r1
+
+       // set up the kernel stack
+       subi    %r1, %r5, 16
+
+       // clear the pointer to the previous frame
+       li              %r0, 0
+       stw             %r0, 0(%r1)
+
+       // enter the kernel
+       mtlr    %r4
+       li              %r4, 0
+       blrl
+
+       /* Actually we should never get here, but at least for debugging 
purposes
+          it's quite nice to return in an orderly manner. */
+
+       // reset the boot loader stack
+       mr              %r1, %r29
+       lwz             %r29, 20(%r1)
+
+       // pop the stack frame
+       lwz             %r0, 36(%r1)
+       mtlr    %r0
+       addi    %r1, %r1, 32
+       blr
+
diff --git a/src/system/boot/platform/cfe/arch/ppc/cpu.cpp 
b/src/system/boot/platform/cfe/arch/ppc/cpu.cpp
new file mode 100644
index 0000000..05ffddd
--- /dev/null
+++ b/src/system/boot/platform/cfe/arch/ppc/cpu.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2005, Ingo Weinhold <bonefish@xxxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include <boot/platform/cfe/platform_arch.h>
+
+#include <stdio.h>
+
+#include <KernelExport.h>
+
+#include <boot/kernel_args.h>
+#include <boot/stage2.h>
+#include <kernel.h>
+//#include <platform/cfe/devices.h>
+#include <boot/platform/cfe/cfe.h>
+
+#define TRACE_CPU
+#ifdef TRACE_CPU
+#      define TRACE(x) dprintf x
+#else
+#      define TRACE(x) ;
+#endif
+
+
+status_t
+boot_arch_cpu_init(void)
+{
+#warning PPC:TODO
+       return B_ERROR;
+}
+
diff --git a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp 
b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp
new file mode 100644
index 0000000..b06114f
--- /dev/null
+++ b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Copyright 2003-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ *             Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ */
+
+
+#include <OS.h>
+
+#include <platform_arch.h>
+#include <boot/addr_range.h>
+#include <boot/kernel_args.h>
+#include <boot/platform.h>
+#include <boot/stage2.h>
+#include <boot/stdio.h>
+#include <boot/platform/cfe/cfe.h>
+#include <arch_cpu.h>
+#include <arch_mmu.h>
+#include <kernel.h>
+
+#include "support.h"
+
+
+// set protection to WIMGNPP: -----PP
+// PP: 00 - no access
+//             01 - read only
+//             10 - read/write
+//             11 - read only
+#define PAGE_READ_ONLY 0x01
+#define PAGE_READ_WRITE        0x02
+
+// NULL is actually a possible physical address...
+//#define PHYSINVAL ((void *)-1)
+#define PHYSINVAL NULL
+
+//#define TRACE_MMU
+#ifdef TRACE_MMU
+#   define TRACE(x...) dprintf(x)
+#else
+#   define TRACE(x...) ;
+#endif
+
+
+segment_descriptor sSegments[16];
+page_table_entry_group *sPageTable;
+uint32 sPageTableHashMask;
+
+
+// begin and end of the boot loader
+extern "C" uint8 __text_begin;
+extern "C" uint8 _end;
+
+
+static status_t
+insert_virtual_range_to_keep(void *start, uint32 size)
+{
+       return 
insert_address_range(gKernelArgs.arch_args.virtual_ranges_to_keep,
+               &gKernelArgs.arch_args.num_virtual_ranges_to_keep,
+               MAX_VIRTUAL_RANGES_TO_KEEP, (addr_t)start, size);
+}
+
+
+static status_t
+remove_virtual_range_to_keep(void *start, uint32 size)
+{
+       return 
remove_address_range(gKernelArgs.arch_args.virtual_ranges_to_keep,
+               &gKernelArgs.arch_args.num_virtual_ranges_to_keep,
+               MAX_VIRTUAL_RANGES_TO_KEEP, (addr_t)start, size);
+}
+
+
+static status_t
+find_physical_memory_ranges(size_t &total)
+{
+       int memory;
+       dprintf("checking for memory...\n");
+#warning PPC:TODO
+
+       return B_ERROR;
+}
+
+
+static bool
+is_virtual_allocated(void *address, size_t size)
+{
+       addr_t foundBase;
+       return !get_free_address_range(gKernelArgs.virtual_allocated_range,
+               gKernelArgs.num_virtual_allocated_ranges, (addr_t)address, size,
+               &foundBase) || foundBase != (addr_t)address;
+}
+
+
+static bool
+is_physical_allocated(void *address, size_t size)
+{
+       phys_addr_t foundBase;
+       return !get_free_physical_address_range(
+               gKernelArgs.physical_allocated_range,
+               gKernelArgs.num_physical_allocated_ranges, (addr_t)address, 
size,
+               &foundBase) || foundBase != (addr_t)address;
+}
+
+
+static bool
+is_physical_memory(void *address, size_t size)
+{
+       return 
is_physical_address_range_covered(gKernelArgs.physical_memory_range,
+               gKernelArgs.num_physical_memory_ranges, (addr_t)address, size);
+}
+
+
+static bool
+is_physical_memory(void *address)
+{
+       return is_physical_memory(address, 1);
+}
+
+
+static void
+fill_page_table_entry(page_table_entry *entry, uint32 virtualSegmentID,
+       void *virtualAddress, void *physicalAddress, uint8 mode, bool 
secondaryHash)
+{
+       // lower 32 bit - set at once
+       ((uint32 *)entry)[1]
+               = (((uint32)physicalAddress / B_PAGE_SIZE) << 12) | mode;
+       /*entry->physical_page_number = (uint32)physicalAddress / B_PAGE_SIZE;
+       entry->_reserved0 = 0;
+       entry->referenced = false;
+       entry->changed = false;
+       entry->write_through = (mode >> 6) & 1;
+       entry->caching_inhibited = (mode >> 5) & 1;
+       entry->memory_coherent = (mode >> 4) & 1;
+       entry->guarded = (mode >> 3) & 1;
+       entry->_reserved1 = 0;
+       entry->page_protection = mode & 0x3;*/
+       eieio();
+               // we need to make sure that the lower 32 bit were
+               // already written when the entry becomes valid
+
+       // upper 32 bit
+       entry->virtual_segment_id = virtualSegmentID;
+       entry->secondary_hash = secondaryHash;
+       entry->abbr_page_index = ((uint32)virtualAddress >> 22) & 0x3f;
+       entry->valid = true;
+}
+
+
+static void
+map_page(void *virtualAddress, void *physicalAddress, uint8 mode)
+{
+       uint32 virtualSegmentID
+               = sSegments[addr_t(virtualAddress) >> 28].virtual_segment_id;
+
+       uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID,
+               (uint32)virtualAddress);
+       page_table_entry_group *group = &sPageTable[hash & sPageTableHashMask];
+
+       for (int32 i = 0; i < 8; i++) {
+               // 8 entries in a group
+               if (group->entry[i].valid)
+                       continue;
+
+               fill_page_table_entry(&group->entry[i], virtualSegmentID,
+                       virtualAddress, physicalAddress, mode, false);
+               //TRACE("map: va = %p -> %p, mode = %d, hash = %lu\n",
+               //      virtualAddress, physicalAddress, mode, hash);
+               return;
+       }
+
+       hash = page_table_entry::SecondaryHash(hash);
+       group = &sPageTable[hash & sPageTableHashMask];
+
+       for (int32 i = 0; i < 8; i++) {
+               if (group->entry[i].valid)
+                       continue;
+
+               fill_page_table_entry(&group->entry[i], virtualSegmentID,
+                       virtualAddress, physicalAddress, mode, true);
+               //TRACE("map: va = %p -> %p, mode = %d, second hash = %lu\n",
+               //      virtualAddress, physicalAddress, mode, hash);
+               return;
+       }
+
+       panic("%s: out of page table entries!\n", __func__);
+}
+
+
+static void
+map_range(void *virtualAddress, void *physicalAddress, size_t size, uint8 mode)
+{
+       for (uint32 offset = 0; offset < size; offset += B_PAGE_SIZE) {
+               map_page((void *)(uint32(virtualAddress) + offset),
+                       (void *)(uint32(physicalAddress) + offset), mode);
+       }
+}
+
+
+static status_t
+find_allocated_ranges(void *oldPageTable, void *pageTable,
+       page_table_entry_group **_physicalPageTable, void **_exceptionHandlers)
+{
+       // we have to preserve the OpenFirmware established mappings
+       // if we want to continue to use its service after we've
+       // taken over (we will probably need less translations once
+       // we have proper driver support for the target hardware).
+       int mmu;
+#warning PPC:TODO
+       return B_ERROR;
+}
+
+
+/*!    Computes the recommended minimal page table size as
+       described in table 7-22 of the PowerPC "Programming
+       Environment for 32-Bit Microprocessors".
+       The page table size ranges from 64 kB (for 8 MB RAM)
+       to 32 MB (for 4 GB RAM).
+*/
+static size_t
+suggested_page_table_size(size_t total)
+{
+       uint32 max = 23;
+               // 2^23 == 8 MB
+
+       while (max < 32) {
+               if (total <= (1UL << max))
+                       break;
+
+               max++;
+       }
+
+       return 1UL << (max - 7);
+               // 2^(23 - 7) == 64 kB
+}
+
+
+static void *
+find_physical_memory_range(size_t size)
+{
+       for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
+               if (gKernelArgs.physical_memory_range[i].size > size)
+                       return (void 
*)gKernelArgs.physical_memory_range[i].start;
+       }
+       return PHYSINVAL;
+}
+
+
+static void *
+find_free_physical_range(size_t size)
+{
+       // just do a simple linear search at the end of the allocated
+       // ranges (dumb memory allocation)
+       if (gKernelArgs.num_physical_allocated_ranges == 0) {
+               if (gKernelArgs.num_physical_memory_ranges == 0)
+                       return PHYSINVAL;
+
+               return find_physical_memory_range(size);
+       }
+
+       for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) {
+               void *address = (void 
*)(gKernelArgs.physical_allocated_range[i].start
+                       + gKernelArgs.physical_allocated_range[i].size);
+               if (!is_physical_allocated(address, size)
+                       && is_physical_memory(address, size))
+                       return address;
+       }
+       return PHYSINVAL;
+}
+
+
+static void *
+find_free_virtual_range(void *base, size_t size)
+{
+       if (base && !is_virtual_allocated(base, size))
+               return base;
+
+       void *firstFound = NULL;
+       void *firstBaseFound = NULL;
+       for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
+               void *address = (void 
*)(gKernelArgs.virtual_allocated_range[i].start
+                       + gKernelArgs.virtual_allocated_range[i].size);
+               if (!is_virtual_allocated(address, size)) {
+                       if (!base)
+                               return address;
+
+                       if (firstFound == NULL)
+                               firstFound = address;
+                       if (address >= base
+                               && (firstBaseFound == NULL || address < 
firstBaseFound)) {
+                               firstBaseFound = address;
+                       }
+               }
+       }
+       return (firstBaseFound ? firstBaseFound : firstFound);
+}
+
+
+extern "C" void *
+arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 _protection,
+       bool exactAddress)
+{
+       // we only know page sizes
+       size = ROUNDUP(size, B_PAGE_SIZE);
+
+       uint8 protection = 0;
+       if (_protection & B_WRITE_AREA)
+               protection = PAGE_READ_WRITE;
+       else
+               protection = PAGE_READ_ONLY;
+
+       // If no address is given, use the KERNEL_BASE as base address, since
+       // that avoids trouble in the kernel, when we decide to keep the region.
+       void *virtualAddress = _virtualAddress;
+       if (!virtualAddress)
+               virtualAddress = (void*)KERNEL_BASE;
+
+       // find free address large enough to hold "size"
+       virtualAddress = find_free_virtual_range(virtualAddress, size);
+       if (virtualAddress == NULL)
+               return NULL;
+
+       // fail if the exact address was requested, but is not free
+       if (exactAddress && _virtualAddress && virtualAddress != 
_virtualAddress) {
+               dprintf("arch_mmu_allocate(): exact address requested, but 
virtual "
+                       "range (base: %p, size: %" B_PRIuSIZE ") is not 
free.\n",
+                       _virtualAddress, size);
+               return NULL;
+       }
+
+       // we have a free virtual range for the allocation, now
+       // have a look for free physical memory as well (we assume
+       // that a) there is enough memory, and b) failing is fatal
+       // so that we don't have to optimize for these cases :)
+
+       void *physicalAddress = find_free_physical_range(size);
+       if (physicalAddress == PHYSINVAL) {
+               dprintf("arch_mmu_allocate(base: %p, size: %" B_PRIuSIZE ") "
+                       "no free physical address\n", virtualAddress, size);
+               return NULL;
+       }
+
+       // everything went fine, so lets mark the space as used.
+
+       dprintf("mmu_alloc: va %p, pa %p, size %" B_PRIuSIZE "\n", 
virtualAddress,
+               physicalAddress, size);
+       insert_virtual_allocated_range((addr_t)virtualAddress, size);
+       insert_physical_allocated_range((addr_t)physicalAddress, size);
+
+       map_range(virtualAddress, physicalAddress, size, protection);
+
+       return virtualAddress;
+}
+
+
+extern "C" status_t
+arch_mmu_free(void *address, size_t size)
+{
+       // TODO: implement freeing a region!
+       return B_ERROR;
+}
+
+
+static inline void
+invalidate_tlb(void)
+{
+       //asm volatile("tlbia");
+               // "tlbia" is obviously not available on every CPU...
+
+       // Note: this flushes the whole 4 GB address space - it
+       //              would probably be a good idea to do less here
+
+       addr_t address = 0;
+       for (uint32 i = 0; i < 0x100000; i++) {
+               asm volatile("tlbie %0" : : "r" (address));
+               address += B_PAGE_SIZE;
+       }
+       tlbsync();
+}
+
+
+extern "C" status_t
+arch_set_callback(void)
+{
+       // XXX:do we need this for CFE?
+       return B_ERROR;
+}
+
+
+extern "C" status_t
+arch_mmu_init(void)
+{
+       // get map of physical memory (fill in kernel_args structure)
+
+       size_t total;
+       if (find_physical_memory_ranges(total) != B_OK) {
+               dprintf("Error: could not find physical memory ranges!\n");
+               return B_ERROR;
+       }
+       dprintf("total physical memory = %" B_PRId32 "MB\n", total / (1024 * 
1024));
+
+       // get OpenFirmware's current page table
+
+       page_table_entry_group *oldTable;
+       page_table_entry_group *table;
+       size_t tableSize;
+       ppc_get_page_table(&table, &tableSize);
+
+       oldTable = table;
+
+       bool realMode = false;
+
+       // TODO: read these values out of the OF settings
+       // NOTE: I've only ever seen -1 (0xffffffff) for these values in
+       //       OpenFirmware.. even after loading the bootloader -- Alex
+       addr_t realBase = 0;
+       addr_t realSize = 0x400000;
+
+       // can we just keep the page table?
+       size_t suggestedTableSize = suggested_page_table_size(total);
+       dprintf("suggested page table size = %" B_PRIuSIZE "\n",
+               suggestedTableSize);
+       if (tableSize < suggestedTableSize) {
+               // nah, we need a new one!
+               dprintf("need new page table, size = %" B_PRIuSIZE "!\n",
+                       suggestedTableSize);
+#if 0//OF
+               table = (page_table_entry_group *)of_claim(NULL, 
suggestedTableSize,
+                       suggestedTableSize);
+                       // KERNEL_BASE would be better as virtual address, but
+                       // at least with Apple's OpenFirmware, it makes no
+                       // difference - we will have to remap it later
+               if (table == (void *)OF_FAILED) {
+                       panic("Could not allocate new page table "
+                               "(size = %" B_PRIuSIZE ")!!\n", 
suggestedTableSize);
+                       return B_NO_MEMORY;
+               }
+#endif
+               if (table == NULL) {
+                       // work-around for the broken Pegasos OpenFirmware
+                       dprintf("broken OpenFirmware detected (claim doesn't 
work)\n");
+                       realMode = true;
+
+                       addr_t tableBase = 0;
+                       for (int32 i = 0; tableBase < realBase + realSize * 3; 
i++) {
+                               tableBase = suggestedTableSize * i;
+                       }
+
+                       table = (page_table_entry_group *)tableBase;
+               }
+
+               dprintf("new table at: %p\n", table);
+               sPageTable = table;
+               tableSize = suggestedTableSize;
+       } else {
+               // ToDo: we could check if the page table is much too large
+               //      and create a smaller one in this case (in order to save
+               //      memory).
+               sPageTable = table;
+       }
+
+       sPageTableHashMask = tableSize / sizeof(page_table_entry_group) - 1;
+       if (sPageTable != oldTable)
+               memset(sPageTable, 0, tableSize);
+
+       // turn off address translation via the page table/segment mechanism,
+       // identity map the first 256 MB (where our code/data reside)
+
+       dprintf("MSR: %p\n", (void *)get_msr());
+
+       #if 0
+       block_address_translation bat;
+
+       bat.length = BAT_LENGTH_256MB;
+       bat.kernel_valid = true;
+       bat.memory_coherent = true;
+       bat.protection = BAT_READ_WRITE;
+
+       set_ibat0(&bat);
+       set_dbat0(&bat);
+       isync();
+       #endif
+
+       // initialize segment descriptors, but don't set the registers
+       // until we're about to take over the page table - we're mapping
+       // pages into our table using these values
+
+       for (int32 i = 0; i < 16; i++)
+               sSegments[i].virtual_segment_id = i;
+
+       // find already allocated ranges of physical memory
+       // and the virtual address space
+
+       page_table_entry_group *physicalTable = NULL;
+       void *exceptionHandlers = (void *)-1;
+       if (find_allocated_ranges(oldTable, table, &physicalTable,
+                       &exceptionHandlers) != B_OK) {
+               dprintf("Error: find_allocated_ranges() failed\n");
+               return B_ERROR;
+       }
+
+#if 0
+       block_address_translation bats[8];
+       getibats(bats);
+       for (int32 i = 0; i < 8; i++) {
+               printf("page index %u, length %u, ppn %u\n", bats[i].page_index,
+                       bats[i].length, bats[i].physical_block_number);
+       }
+#endif
+
+       if (physicalTable == NULL) {
+               dprintf("%s: Didn't find physical address of page table\n", 
__func__);
+               if (!realMode)
+                       return B_ERROR;
+
+               // Pegasos work-around
+               #if 0
+               map_range((void *)realBase, (void *)realBase,
+                       realSize * 2, PAGE_READ_WRITE);
+               map_range((void *)(total - realSize), (void *)(total - 
realSize),
+                       realSize, PAGE_READ_WRITE);
+               map_range((void *)table, (void *)table, tableSize, 
PAGE_READ_WRITE);
+               #endif
+               insert_physical_allocated_range(realBase, realSize * 2);
+               insert_virtual_allocated_range(realBase, realSize * 2);
+               insert_physical_allocated_range(total - realSize, realSize);
+               insert_virtual_allocated_range(total - realSize, realSize);
+               insert_physical_allocated_range((addr_t)table, tableSize);
+               insert_virtual_allocated_range((addr_t)table, tableSize);
+
+               // QEMU OpenHackware work-around
+               insert_physical_allocated_range(0x05800000, 0x06000000 - 
0x05800000);
+               insert_virtual_allocated_range(0x05800000, 0x06000000 - 
0x05800000);
+
+               physicalTable = table;
+       }
+
+       if (exceptionHandlers == (void *)-1) {
+               // TODO: create mapping for the exception handlers
+               dprintf("Error: no mapping for the exception handlers!\n");
+       }
+
+       // Set the Open Firmware memory callback. From now on the Open Firmware
+       // will ask us for memory.
+       arch_set_callback();
+
+       // set up new page table and turn on translation again
+
+       for (int32 i = 0; i < 16; i++) {
+               ppc_set_segment_register((void *)(i * 0x10000000), 
sSegments[i]);
+                       // one segment describes 256 MB of memory
+       }
+
+       ppc_set_page_table(physicalTable, tableSize);
+       invalidate_tlb();
+
+       if (!realMode) {
+               // clear BATs
+               reset_ibats();
+               reset_dbats();
+               ppc_sync();
+               isync();
+       }
+
+       set_msr(MSR_MACHINE_CHECK_ENABLED | MSR_FP_AVAILABLE
+               | MSR_INST_ADDRESS_TRANSLATION | MSR_DATA_ADDRESS_TRANSLATION);
+
+       // set kernel args
+
+       dprintf("virt_allocated: %" B_PRIu32 "\n",
+               gKernelArgs.num_virtual_allocated_ranges);
+       dprintf("phys_allocated: %" B_PRIu32 "\n",
+               gKernelArgs.num_physical_allocated_ranges);
+       dprintf("phys_memory: %" B_PRIu32 "\n",
+               gKernelArgs.num_physical_memory_ranges);
+
+       gKernelArgs.arch_args.page_table.start = (addr_t)sPageTable;
+       gKernelArgs.arch_args.page_table.size = tableSize;
+
+       gKernelArgs.arch_args.exception_handlers.start = 
(addr_t)exceptionHandlers;
+       gKernelArgs.arch_args.exception_handlers.size = B_PAGE_SIZE;
+
+       return B_OK;
+}
+
diff --git a/src/system/boot/platform/cfe/cfe.cpp 
b/src/system/boot/platform/cfe/cfe.cpp
new file mode 100644
index 0000000..d73ee83
--- /dev/null
+++ b/src/system/boot/platform/cfe/cfe.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <string.h>
+#include <stdarg.h>
+
+#include <OS.h>
+
+#include <boot/platform.h>
+#include <boot/stage2.h>
+#include <boot/heap.h>
+#include <boot/platform/cfe/cfe.h>
+#include <platform_arch.h>
+
+typedef uint64 ptr64; // for clarity
+
+status_t cfe_error(int32 err)
+{
+       // not an error
+       if (err > 0)
+               return err;
+
+       switch (err) {
+               case CFE_OK:
+                       return B_OK;
+               case CFE_ERR:
+                       return B_ERROR;
+               //TODO:add cases
+               default:
+                       return B_ERROR;
+       }
+}
+
+#define CFE_CMD_FW_GETINFO             0
+#define CFE_CMD_FW_RESTART             1
+#define CFE_CMD_FW_BOOT                        2
+#define CFE_CMD_FW_CPUCTL              3
+#define CFE_CMD_FW_GETTIME             4
+#define CFE_CMD_FW_MEMENUM             5
+#define CFE_CMD_FW_FLUSHCACHE  6
+
+#define CFE_CMD_DEV_GETHANDLE  9
+#define CFE_CMD_DEV_ENUM               10
+#define CFE_CMD_DEV_OPEN               11
+#define CFE_CMD_DEV_READ               13
+#define CFE_CMD_DEV_WRITE              14
+#define CFE_CMD_DEV_CLOSE              16
+
+
+struct cfe_xiocb_s {
+       cfe_xiocb_s(uint64 fcode, int64 handle = 0, uint64 flags = 0);
+
+       uint64  xiocb_fcode;
+       int64   xiocb_status;
+       int64   xiocb_handle;
+       uint64  xiocb_flags;
+       uint64  xiocb_psize;
+       union {
+               struct {
+                       uint64  buf_offset;
+                       ptr64   buf_ptr;
+                       uint64  buf_length;
+                       uint64  buf_retlen;
+                       uint64  buf_ioctlcmd;
+               } xiocb_buffer;
+/*
+               struct {
+               } xiocb_inpstat;
+*/
+               struct {
+                       int64   enum_idx;
+                       ptr64   name_ptr;
+                       int64   name_length;
+                       ptr64   val_ptr;
+                       int64   val_length;
+               } xiocb_envbuf;
+/*
+               struct {
+               } xiocb_cpuctl;
+*/
+               struct {
+                       int64   ticks;
+               } xiocb_time;
+/*
+               struct {
+               } xiocb_meminfo;
+               struct {
+               } xiocb_fwinfo;
+*/
+               struct {
+                       int64   status;
+               } xiocb_exitstat;
+       } plist;
+};
+
+typedef struct cfe_xiocb_s cfe_xiocb_t;
+
+cfe_xiocb_s::cfe_xiocb_s(uint64 fcode, int64 handle, uint64 flags)
+       : xiocb_fcode(fcode),
+       xiocb_status(0),
+       xiocb_handle(handle),
+       xiocb_flags(flags),
+       xiocb_psize(0)
+{
+       switch (fcode) {
+               case CFE_CMD_FW_GETINFO:
+               case CFE_CMD_DEV_READ:
+               case CFE_CMD_DEV_WRITE:
+               case CFE_CMD_DEV_OPEN:
+                       xiocb_psize = sizeof(plist.xiocb_buffer);
+                       break;
+               case CFE_CMD_FW_RESTART:
+                       xiocb_psize = sizeof(plist.xiocb_exitstat);
+                       break;
+               case CFE_CMD_FW_GETTIME:
+                       xiocb_psize = sizeof(plist.xiocb_time);
+                       break;
+               case CFE_CMD_DEV_ENUM:
+                       xiocb_psize = sizeof(plist.xiocb_envbuf);
+                       break;
+               //XXX: some more...
+               default:
+                       break;
+       }
+       memset(&plist, 0, sizeof(plist));
+};
+
+
+// CFE handle
+static uint64 sCFEHandle;
+// CFE entry point
+static uint64 sCFEEntry;
+
+static int cfe_iocb_dispatch(cfe_xiocb_t *xiocb)
+{
+       static int (*dispfunc)(intptr_t handle, intptr_t xiocb);
+       dispfunc = (int(*)(intptr_t, intptr_t))(void *)sCFEEntry;
+       if (dispfunc == NULL)
+               return CFE_ERR;
+       return (*dispfunc)((intptr_t)sCFEHandle, (intptr_t)xiocb);
+}
+
+int
+cfe_init(uint64 handle, uint64 entry)
+{
+       sCFEHandle = handle;
+       sCFEEntry = entry;
+
+       return CFE_OK;
+}
+
+int
+cfe_exit(int32 warm, int32 status)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_FW_RESTART, 0,
+               warm ? CFE_FLG_WARMSTART : CFE_FLG_COLDSTART);
+       xiocb.plist.xiocb_exitstat.status = status;
+
+       cfe_iocb_dispatch(&xiocb);
+
+       return xiocb.xiocb_status;
+}
+
+
+int cfe_enumdev(int idx, char *name, int namelen)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_ENUM);
+       xiocb.plist.xiocb_envbuf.enum_idx = idx;
+       xiocb.plist.xiocb_envbuf.name_ptr = (uint64)name;
+       xiocb.plist.xiocb_envbuf.name_length = namelen;
+
+       cfe_iocb_dispatch(&xiocb);
+
+       return xiocb.xiocb_status;
+}
+
+
+int
+cfe_getstdhandle(int flag)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_GETHANDLE, 0, flag);
+
+       cfe_iocb_dispatch(&xiocb);
+
+       if (xiocb.xiocb_status < 0);
+               return xiocb.xiocb_status;
+       return xiocb.xiocb_handle;
+}
+
+
+int
+cfe_open(const char *name)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_OPEN);
+       xiocb.plist.xiocb_buffer.buf_offset = 0;
+       xiocb.plist.xiocb_buffer.buf_ptr = (uint64)name;
+       xiocb.plist.xiocb_buffer.buf_length = strlen(name);
+
+       cfe_iocb_dispatch(&xiocb);
+
+       if (xiocb.xiocb_status < 0);
+               return xiocb.xiocb_status;
+       return xiocb.xiocb_handle;
+}
+
+
+int
+cfe_close(int handle)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_CLOSE, handle);
+
+       cfe_iocb_dispatch(&xiocb);
+
+       return xiocb.xiocb_status;
+}
+
+
+uint64
+cfe_getticks(void)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_FW_GETTIME);
+
+       cfe_iocb_dispatch(&xiocb);
+
+       return xiocb.plist.xiocb_time.ticks;
+}
+
+
+int
+cfe_readblk(int handle, int64 offset, void *buffer, int length)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_READ, handle);
+       xiocb.plist.xiocb_buffer.buf_offset = offset;
+       xiocb.plist.xiocb_buffer.buf_ptr = (uint64)buffer;
+       xiocb.plist.xiocb_buffer.buf_length = length;
+
+       cfe_iocb_dispatch(&xiocb);
+
+       if (xiocb.xiocb_status < 0);
+               return xiocb.xiocb_status;
+       return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+
+
+
+int
+cfe_writeblk(int handle, int64 offset, const void *buffer, int length)
+{
+       cfe_xiocb_t xiocb(CFE_CMD_DEV_WRITE, handle);
+       xiocb.plist.xiocb_buffer.buf_offset = offset;
+       xiocb.plist.xiocb_buffer.buf_ptr = (uint64)buffer;
+       xiocb.plist.xiocb_buffer.buf_length = length;
+
+       cfe_iocb_dispatch(&xiocb);
+
+       if (xiocb.xiocb_status < 0);
+               return xiocb.xiocb_status;
+       return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+
+
diff --git a/src/system/boot/platform/cfe/console.cpp 
b/src/system/boot/platform/cfe/console.cpp
new file mode 100644
index 0000000..d11012b
--- /dev/null
+++ b/src/system/boot/platform/cfe/console.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "Handle.h"
+#include "console.h"
+
+#include <SupportDefs.h>
+#include <boot/platform/cfe/cfe.h>
+#include <boot/stage2.h>
+#include <util/kernel_cpp.h>
+
+#include <string.h>
+
+
+class Console : public Handle {
+       public:
+               Console();
+};
+
+class VTConsole : public Console {
+       public:
+               VTConsole();
+               void    ClearScreen();
+               void    SetCursor(int32 x, int32 y);
+               void    SetColor(int32 foreground, int32 background);
+};
+
+static VTConsole sInput, sOutput;
+FILE *stdin, *stdout, *stderr;
+
+
+//     #pragma mark -
+
+
+Console::Console()
+       : Handle()
+{
+}
+
+
+//     #pragma mark -
+
+
+VTConsole::VTConsole()
+       : Console()
+{
+}
+
+void
+VTConsole::ClearScreen()
+{
+       WriteAt(NULL, 0LL, "\033E", 2);
+}
+
+
+void
+VTConsole::SetCursor(int32 x, int32 y)
+{
+       char buff[] = "\033Y  ";
+       x = MIN(79,MAX(0,x));
+       y = MIN(24,MAX(0,y));
+       buff[3] += (char)x;
+       buff[2] += (char)y;
+       WriteAt(NULL, 0LL, buff, 4);
+}
+
+
+void
+VTConsole::SetColor(int32 foreground, int32 background)
+{
+       static const char cmap[] = {
+               15, 4, 2, 6, 1, 5, 3, 7,
+               8, 12, 10, 14, 9, 13, 11, 0 };
+       char buff[] = "\033b \033c ";
+
+       if (foreground < 0 && foreground >= 16)
+               return;
+       if (background < 0 && background >= 16)
+               return;
+
+       buff[2] += cmap[foreground];
+       buff[5] += cmap[background];
+       WriteAt(NULL, 0LL, buff, 6);
+}
+
+
+//     #pragma mark -
+
+
+void
+console_clear_screen(void)
+{
+       sOutput.ClearScreen();
+}
+
+
+int32
+console_width(void)
+{
+       return 80;
+}
+
+
+int32
+console_height(void)
+{
+       return 25;
+}
+
+
+void
+console_set_cursor(int32 x, int32 y)
+{
+       sOutput.SetCursor(x, y);
+}
+
+
+void
+console_show_cursor(void)
+{
+}
+
+
+void
+console_hide_cursor(void)
+{
+}
+
+
+void
+console_set_color(int32 foreground, int32 background)
+{
+       sOutput.SetColor(foreground, background);
+}
+
+
+int
+console_wait_for_key(void)
+{
+    return 0;
+}
+
+
+int
+console_check_for_key(void)
+{
+       return 0;
+}
+
+
+status_t
+console_init(void)
+{
+       stdin = (FILE *)&sInput;
+       stdout = stderr = (FILE *)&sOutput;
+
+       int handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+       if (handle < 0)
+               return cfe_error(handle);
+
+       sInput.SetHandle(handle);
+       sOutput.SetHandle(handle);
+
+       return B_OK;
+}
+
diff --git a/src/system/boot/platform/cfe/console.h 
b/src/system/boot/platform/cfe/console.h
new file mode 100644
index 0000000..eef30f7
--- /dev/null
+++ b/src/system/boot/platform/cfe/console.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved.
+ * Distributed under the terms of the Haiku License.
+ */
+#ifndef CONSOLE_H
+#define CONSOLE_H
+
+#include <boot/platform/generic/text_console.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern status_t console_init(void);
+extern int console_check_for_key(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONSOLE_H */
diff --git a/src/system/boot/platform/cfe/debug.cpp 
b/src/system/boot/platform/cfe/debug.cpp
new file mode 100644
index 0000000..84bd5db
--- /dev/null
+++ b/src/system/boot/platform/cfe/debug.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Copyright 2003-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <stdarg.h>
+
+#include <boot/platform.h>
+#include <boot/stdio.h>
+#include <boot/platform/cfe/cfe.h>
+
+
+extern "C" void
+panic(const char* format, ...)
+{
+       // TODO: this works only after console_init() was called.
+       va_list list;
+
+       puts("*** PANIC ***");
+
+       va_start(list, format);
+       vprintf(format, list);
+       va_end(list);
+
+       cfe_exit(CFE_FLG_WARMSTART, 2);
+}
+
+
+extern "C" void
+dprintf(const char* format, ...)
+{
+       va_list list;
+
+       va_start(list, format);
+       vprintf(format, list);
+       va_end(list);
+}
+
+
+char*
+platform_debug_get_log_buffer(size_t* _size)
+{
+       return NULL;
+}
diff --git a/src/system/boot/platform/cfe/devices.cpp 
b/src/system/boot/platform/cfe/devices.cpp
new file mode 100644
index 0000000..46a20ce
--- /dev/null
+++ b/src/system/boot/platform/cfe/devices.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2003-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Copyright 2010, Andreas Färber <andreas.faerber@xxxxxx>
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <string.h>
+
+#include <boot/platform.h>
+#include <boot/vfs.h>
+#include <boot/stdio.h>
+#include <boot/stage2.h>
+#include <boot/net/IP.h>
+#include <boot/net/iSCSITarget.h>
+#include <boot/net/NetStack.h>
+#include <boot/net/RemoteDisk.h>
+//#include <platform/cfe/devices.h>
+#include <boot/platform/cfe/cfe.h>
+#include <util/kernel_cpp.h>
+
+#include "Handle.h"
+
+
+char sBootPath[192];
+
+
+status_t 
+platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
+{
+#warning PPC:TODO
+       return B_ERROR;
+}
+
+
+status_t
+platform_get_boot_partition(struct stage2_args *args, Node *device,
+       NodeList *list, boot::Partition **_partition)
+{
+       NodeIterator iterator = list->GetIterator();
+       boot::Partition *partition = NULL;
+       while ((partition = (boot::Partition *)iterator.Next()) != NULL) {
+               // ToDo: just take the first partition for now
+               *_partition = partition;
+               return B_OK;
+       }
+
+       return B_ENTRY_NOT_FOUND;
+}
+
+
+#define DUMPED_BLOCK_SIZE 16
+
+void
+dumpBlock(const char *buffer, int size, const char *prefix)
+{
+       int i;
+       
+       for (i = 0; i < size;) {
+               int start = i;
+
+               printf(prefix);
+               for (; i < start+DUMPED_BLOCK_SIZE; i++) {
+                       if (!(i % 4))
+                               printf(" ");
+
+                       if (i >= size)
+                               printf("  ");
+                       else
+                               printf("%02x", *(unsigned char *)(buffer + i));
+               }
+               printf("  ");
+
+               for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
+                       if (i < size) {
+                               char c = buffer[i];
+
+                               if (c < 30)
+                                       printf(".");
+                               else
+                                       printf("%c", c);
+                       } else
+                               break;
+               }
+               printf("\n");
+       }
+}
+
+
+status_t
+platform_add_block_devices(stage2_args *args, NodeList *devicesList)
+{
+       // add all block devices to the list of possible boot devices
+
+       int cookie = 0;
+       char path[256];
+       int status;
+       for (; (status = cfe_enumdev(cookie, path, sizeof(path))) == B_OK;      
                        cookie++) {
+               if (!strcmp(path, sBootPath)) {
+                       // don't add the boot device twice
+                       continue;
+               }
+
+               printf("\t%s\n", path);
+
+               int handle = cfe_open(path);
+               if (handle < CFE_OK) {
+                       puts("\t\t(failed)");
+                       continue;
+               }
+
+               Handle *device = new(nothrow) Handle(handle);
+               printf("\t\t(could open device, handle = %d, node = %p)\n",
+                       handle, device);
+
+               devicesList->Add(device);
+       }
+       printf("\t(loop ended with %ld)\n", status);
+
+       return B_OK;
+}
+
+
+status_t 
+platform_register_boot_device(Node *device)
+{
+       disk_identifier disk;
+
+       disk.bus_type = UNKNOWN_BUS;
+       disk.device_type = UNKNOWN_DEVICE;
+       disk.device.unknown.size = device->Size();
+
+       gKernelArgs.boot_volume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE,
+               &disk, sizeof(disk_identifier));
+
+       return B_OK;
+}              
+
diff --git a/src/system/boot/platform/cfe/heap.cpp 
b/src/system/boot/platform/cfe/heap.cpp
new file mode 100644
index 0000000..1dff002
--- /dev/null
+++ b/src/system/boot/platform/cfe/heap.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <OS.h>
+
+#include <boot/platform.h>
+#include <boot/heap.h>
+#include <boot/stdio.h>
+#include <boot/platform/cfe/cfe.h>
+
+
+#define TRACE_HEAP 1
+#if TRACE_HEAP
+#      define TRACE(x) printf x
+#else
+#      define TRACE(x) ;
+#endif
+
+
+status_t
+platform_init_heap(stage2_args *args, void **_base, void **_top)
+{
+       TRACE(("platform_init_heap()\n"));
+
+       *_base = NULL;
+       status_t error = platform_allocate_region(_base, args->heap_size,
+               B_READ_AREA | B_WRITE_AREA, false);
+       if (error != B_OK)
+               return error;
+
+       printf("heap base = %p\n", *_base);
+       *_top = (void *)((int8 *)*_base + args->heap_size);
+       printf("heap top = %p\n", *_top);
+
+       return B_OK;
+}
+
+
+void
+platform_release_heap(stage2_args *args, void *base)
+{
+       if (base != NULL)
+               platform_free_region(base, args->heap_size);
+}
+
diff --git a/src/system/boot/platform/cfe/menu.cpp 
b/src/system/boot/platform/cfe/menu.cpp
new file mode 100644
index 0000000..47f9c6f
--- /dev/null
+++ b/src/system/boot/platform/cfe/menu.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <boot/platform.h>
+#include <boot/menu.h>
+#include <boot/platform/generic/text_menu.h>
+
+
+void
+platform_add_menus(Menu *menu)
+{
+       // ToDo: implement me!
+
+       switch (menu->Type()) {
+               case MAIN_MENU:
+                       break;
+               case SAFE_MODE_MENU:
+                       break;
+               default:
+                       break;
+       }
+}
+
+
+void
+platform_update_menu_item(Menu *menu, MenuItem *item)
+{
+       platform_generic_update_text_menu_item(menu, item);
+}
+
+
+void
+platform_run_menu(Menu *menu)
+{
+       platform_generic_run_text_menu(menu);
+}
+
+
+size_t
+platform_get_user_input_text(Menu *menu, MenuItem *item, char *buffer,
+       size_t bufferSize)
+{
+       return platform_generic_get_user_input_text(menu, item, buffer,
+               bufferSize);
+}
diff --git a/src/system/boot/platform/cfe/mmu.cpp 
b/src/system/boot/platform/cfe/mmu.cpp
new file mode 100644
index 0000000..b9f3143
--- /dev/null
+++ b/src/system/boot/platform/cfe/mmu.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <platform_arch.h>
+#include <boot/platform.h>
+#include <boot/stdio.h>
+#include <boot/platform/cfe/cfe.h>
+#include <stdarg.h>
+
+
+status_t
+platform_allocate_region(void **_address, size_t size, uint8 protection,
+       bool exactAddress)
+{
+       if (size == 0)
+               return B_BAD_VALUE;
+
+       void *address = arch_mmu_allocate(*_address, size, protection,
+               exactAddress);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = address;
+       return B_OK;
+}
+
+
+status_t
+platform_free_region(void *address, size_t size)
+{
+       return arch_mmu_free(address, size);
+}
+
diff --git a/src/system/boot/platform/cfe/start.cpp 
b/src/system/boot/platform/cfe/start.cpp
new file mode 100644
index 0000000..f5df643
--- /dev/null
+++ b/src/system/boot/platform/cfe/start.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Copyright 2003-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Copyright 2011, Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <string.h>
+
+#include <OS.h>
+
+#include <boot/platform.h>
+#include <boot/stage2.h>
+#include <boot/heap.h>
+#include <boot/platform/cfe/cfe.h>
+#include <platform_arch.h>
+
+#include "console.h"
+#include "real_time_clock.h"
+
+
+#define HEAP_SIZE 65536
+
+
+extern "C" void _start(uint64 handle, uint64 entry, uint32 _unused, 
+       uint32 signature);
+extern "C" void start(uint64 cfeHandle, uint64 cfeEntry);
+
+// GCC defined globals
+extern void (*__ctor_list)(void);
+extern void (*__ctor_end)(void);
+extern uint8 __bss_start;
+extern uint8 _end;
+
+#if 0//OF
+uint32 gMachine;
+#endif
+static uint32 sBootOptions;
+
+
+static void
+call_ctors(void)
+{
+       void (**f)(void);
+
+       for (f = &__ctor_list; f < &__ctor_end; f++) {
+               (**f)();
+       }
+}
+
+
+static void
+clear_bss(void)
+{
+       memset(&__bss_start, 0, &_end - &__bss_start);
+}
+
+
+extern "C" void
+platform_start_kernel(void)
+{
+       addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry;
+       addr_t stackTop = gKernelArgs.cpu_kstack[0].start
+               + gKernelArgs.cpu_kstack[0].size;
+
+       printf("kernel entry at %p\n", (void*)kernelEntry);
+       printf("kernel stack top: %p\n", (void*)stackTop);
+
+       /* TODO: ?
+       mmu_init_for_kernel();
+       smp_boot_other_cpus();
+       */
+
+       status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop);
+
+       panic("Kernel returned! Return value: %ld\n", error);
+}
+
+
+extern "C" void
+platform_exit(void)
+{
+       cfe_exit(CFE_FLG_WARMSTART, 0);
+       panic("cfe_exit() failed.");
+}
+
+
+extern "C" uint32
+platform_boot_options(void)
+{
+       return sBootOptions;
+}
+
+
+extern "C" void
+_start(uint64 handle, uint64 entry, uint32 _unused, uint32 signature)
+{
+
+       if (signature != CFE_EPTSEAL)
+               return;//XXX:something?
+
+       clear_bss();
+       call_ctors();
+               // call C++ constructors before doing anything else
+
+       start(handle, entry);
+}
+
+
+extern "C" void
+start(uint64 cfeHandle, uint64 cfeEntry)
+{
+       char bootargs[512];
+
+       // stage2 args - might be set via the command line one day
+       stage2_args args;
+       args.heap_size = HEAP_SIZE;
+       args.arguments = NULL;
+
+       cfe_init(cfeHandle, cfeEntry);
+
+       // check for arguments
+#if 0//OF
+       if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs))
+                       != OF_FAILED) {
+               static const char *sArgs[] = { NULL, NULL };
+               sArgs[0] = (const char *)bootargs;
+               args.arguments = sArgs;
+       }
+#endif
+
+#if 0//OF
+       determine_machine();
+#endif
+       console_init();
+
+#if 0//OF
+       if ((gMachine & MACHINE_QEMU) != 0)
+               dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n");
+       else if ((gMachine & MACHINE_PEGASOS) != 0)
+               dprintf("Pegasos PowerPC machine detected\n");
+       else
+               dprintf("Apple PowerPC machine assumed\n");
+#endif
+
+       // Initialize and take over MMU and set the OpenFirmware callbacks - it
+       // will ask us for memory after that instead of maintaining it itself
+       // (the kernel will need to adjust the callback later on as well)
+       arch_mmu_init();
+
+       if (boot_arch_cpu_init() != B_OK)
+               cfe_exit(CFE_FLG_WARMSTART, 1);
+
+#if 0//OF FIXME
+       if (init_real_time_clock() != B_OK)
+               cfe_exit(CFE_FLG_WARMSTART, 1);
+#endif
+
+       // check for key presses once
+       sBootOptions = 0;
+       int key = console_check_for_key();
+       if (key == 32) {
+               // space bar: option menu
+               sBootOptions |= BOOT_OPTION_MENU;
+       } else if (key == 27) {
+               // ESC: debug output
+               sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT;
+       }
+
+       gKernelArgs.platform_args.cfe_entry = cfeEntry;
+
+       main(&args);
+               // if everything goes fine, main() never returns
+
+       cfe_exit(CFE_FLG_WARMSTART, 1);
+}
diff --git a/src/system/boot/platform/cfe/support.cpp 
b/src/system/boot/platform/cfe/support.cpp
new file mode 100644
index 0000000..93bf0e5
--- /dev/null
+++ b/src/system/boot/platform/cfe/support.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2011, François Revol, revol@xxxxxxxx
+ * Copyright 2005, Ingo Weinhold <bonefish@xxxxxxxxxxxxxxx>.
+ * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold, bonefish@xxxxxxxxxxxxxxx
+ *             Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ */
+
+
+#include "support.h"
+#include <boot/platform/cfe/cfe.h>
+
+
+bigtime_t
+system_time(void)
+{
+       bigtime_t result = cfe_getticks() * 1000000LL / CFE_HZ ;
+       return result;
+}
+
diff --git a/src/system/boot/platform/cfe/support.h 
b/src/system/boot/platform/cfe/support.h
new file mode 100644
index 0000000..f231ab4
--- /dev/null
+++ b/src/system/boot/platform/cfe/support.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *      Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ */
+#ifndef SUPPORT_H
+#define SUPPORT_H
+
+
+#include <OS.h>
+
+
+bigtime_t system_time(void);
+
+#endif
diff --git a/src/system/boot/platform/cfe/video.cpp 
b/src/system/boot/platform/cfe/video.cpp
new file mode 100644
index 0000000..affd6df
--- /dev/null
+++ b/src/system/boot/platform/cfe/video.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Copyright 2010 Andreas Färber <andreas.faerber@xxxxxx>
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <boot/platform.h>
+#include <boot/stage2.h>
+#include <boot/platform/generic/video.h>
+#include <edid.h>
+#include <boot/platform/cfe/cfe.h>
+
+
+//#define TRACE_VIDEO
+
+
+static int sScreen;
+
+
+void
+platform_blit4(addr_t frameBuffer, const uint8 *data,
+       uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
+{
+       panic("platform_blit4(): not implemented\n");
+}
+
+
+extern "C" void
+platform_set_palette(const uint8 *palette)
+{
+       switch (gKernelArgs.frame_buffer.depth) {
+               case 8:
+                       break;
+               default:
+                       break;
+       }
+}
+
+
+extern "C" void
+platform_switch_to_logo(void)
+{
+       // in debug mode, we'll never show the logo
+       if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0)
+               return;
+
+       return;
+}
+
+
+extern "C" void
+platform_switch_to_text_mode(void)
+{
+       // nothing to do if we're in text mode
+       if (!gKernelArgs.frame_buffer.enabled)
+               return;
+
+       // ToDo: implement me
+
+       gKernelArgs.frame_buffer.enabled = false;
+}
+
+
+extern "C" status_t
+platform_init_video(void)
+{
+       gKernelArgs.frame_buffer.enabled = false;
+
+       return B_NO_INIT;
+}
+
diff --git a/src/system/ldscripts/ppc/boot_loader_cfe.ld 
b/src/system/ldscripts/ppc/boot_loader_cfe.ld
new file mode 100644
index 0000000..327e7c4
--- /dev/null
+++ b/src/system/ldscripts/ppc/boot_loader_cfe.ld
@@ -0,0 +1,45 @@
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+OUTPUT_ARCH(powerpc)
+
+ENTRY(_start)
+
+SECTIONS
+{
+       . = 0x102000 + SIZEOF_HEADERS;
+
+       __text_begin = .;
+
+       /* text/read-only data */
+       .text : { *(.text .text.* .gnu.linkonce.t.*) }
+
+       .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+       .sdata2 : { *(.sdata2) }
+
+       /* writable data  */
+       /* align to the same offset in the next page (for performance reasons
+          (not that it really matters in the boot loader)) */
+       . = ALIGN(0x1000) + 0x1000 + (. & (0x1000 - 1));
+
+       __ctor_list = .;
+       .ctors : { *(.ctors) }
+       __ctor_end = .;
+
+       __data_start = .;
+       .data : { *(.data .gnu.linkonce.d.*) }
+       .data.rel.ro : { *(.data.rel.ro.local .data.rel.ro*) }
+       .got : { *(.got .got2) }
+       .sdata : { *(.sdata .sdata.* .gnu.linkonce.s.*) }
+
+       /* uninitialized data (in same segment as writable data) */
+       __bss_start = .;
+       .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) }
+       .bss : {
+               *(.bss .bss.* .gnu.linkonce.b.*)
+               . = ALIGN(0x1000);
+       }
+
+       _end = . ;
+
+       /* Strip unnecessary stuff */
+       /DISCARD/ : { *(.comment .note .eh_frame .dtors .debug_*) }
+}


Other related posts:

  • » [haiku-commits] haiku: hrev43262 - src/system/boot/platform/cfe src/system/boot/platform/cfe/arch/ppc headers/private/kernel/boot/platform/cfe - revol