From 8abaaaf7e523080b4be87cbaacda915ccb5c5525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 3 Sep 2003 02:03:28 +0000 Subject: [PATCH] OpenFirmware bindings for the stage2 boot loader. Not yet complete. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4465 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/boot/platform/Jamfile | 3 + .../boot/platform/openfirmware/Handle.cpp | 64 +++ .../boot/platform/openfirmware/Handle.h | 32 ++ src/kernel/boot/platform/openfirmware/Jamfile | 19 + .../boot/platform/openfirmware/console.cpp | 76 +++ .../boot/platform/openfirmware/console.h | 29 ++ src/kernel/boot/platform/openfirmware/debug.c | 31 ++ .../boot/platform/openfirmware/devices.cpp | 30 ++ .../boot/platform/openfirmware/heap.cpp | 61 +++ .../boot/platform/openfirmware/openfirmware.c | 471 ++++++++++++++++++ .../boot/platform/openfirmware/openfirmware.h | 57 +++ src/kernel/boot/platform/openfirmware/start.c | 71 +++ 12 files changed, 944 insertions(+) create mode 100644 src/kernel/boot/platform/Jamfile create mode 100644 src/kernel/boot/platform/openfirmware/Handle.cpp create mode 100644 src/kernel/boot/platform/openfirmware/Handle.h create mode 100644 src/kernel/boot/platform/openfirmware/Jamfile create mode 100644 src/kernel/boot/platform/openfirmware/console.cpp create mode 100644 src/kernel/boot/platform/openfirmware/console.h create mode 100644 src/kernel/boot/platform/openfirmware/debug.c create mode 100644 src/kernel/boot/platform/openfirmware/devices.cpp create mode 100644 src/kernel/boot/platform/openfirmware/heap.cpp create mode 100644 src/kernel/boot/platform/openfirmware/openfirmware.c create mode 100644 src/kernel/boot/platform/openfirmware/openfirmware.h create mode 100644 src/kernel/boot/platform/openfirmware/start.c diff --git a/src/kernel/boot/platform/Jamfile b/src/kernel/boot/platform/Jamfile new file mode 100644 index 0000000000..4fe018f321 --- /dev/null +++ b/src/kernel/boot/platform/Jamfile @@ -0,0 +1,3 @@ +SubDir OBOS_TOP src kernel boot platform ; + +SubInclude OBOS_TOP src kernel boot platform $(OBOS_BOOT_PLATFORM) ; diff --git a/src/kernel/boot/platform/openfirmware/Handle.cpp b/src/kernel/boot/platform/openfirmware/Handle.cpp new file mode 100644 index 0000000000..21584f6227 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/Handle.cpp @@ -0,0 +1,64 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include + +#include "Handle.h" +#include "openfirmware.h" + + +Handle::Handle(int handle, bool takeOwnership) + : + fHandle(handle), + fOwnHandle(takeOwnership) +{ +} + + +Handle::Handle(void) + : + fHandle(0) +{ +} + + +Handle::~Handle() +{ + if (fOwnHandle) + of_close(fHandle); +} + + +void +Handle::SetHandle(int handle, bool takeOwnership) +{ + if (fHandle && fOwnHandle) + of_close(fHandle); + + fHandle = handle; + fOwnHandle = takeOwnership; +} + + +ssize_t +Handle::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) +{ + if (pos == -1 || of_seek(fHandle, pos) != OF_FAILED) + return of_read(fHandle, buffer, bufferSize); + + return B_ERROR; +} + + +ssize_t +Handle::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize) +{ + if (pos == -1 || of_seek(fHandle, pos) != OF_FAILED) + return of_write(fHandle, buffer, bufferSize); + + return B_ERROR; +} + diff --git a/src/kernel/boot/platform/openfirmware/Handle.h b/src/kernel/boot/platform/openfirmware/Handle.h new file mode 100644 index 0000000000..99df56c467 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/Handle.h @@ -0,0 +1,32 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef HANDLE_H +#define HANDLE_H + + +#include + + +#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); + + protected: + int fHandle; + bool fOwnHandle; +}; + +#endif /* __cplusplus */ + +#endif /* HANDLE_H */ diff --git a/src/kernel/boot/platform/openfirmware/Jamfile b/src/kernel/boot/platform/openfirmware/Jamfile new file mode 100644 index 0000000000..cc687d4597 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/Jamfile @@ -0,0 +1,19 @@ +SubDir OBOS_TOP src kernel boot platform openfirmware ; + +SubDirHdrs $(OBOS_TOP) headers private kernel boot platform $(OBOS_BOOT_PLATFORM) ; + +KernelMergeObject boot_platform_openfirmware.o : +# crt0.S + <$(SOURCE_GRIST)>start.c + <$(SOURCE_GRIST)>openfirmware.c + <$(SOURCE_GRIST)>debug.c + <$(SOURCE_GRIST)>Handle.cpp + <$(SOURCE_GRIST)>devices.cpp + <$(SOURCE_GRIST)>console.cpp + <$(SOURCE_GRIST)>heap.cpp + : + ; + +SEARCH on [ FGristFiles crt0.S ] + = [ FDirName $(OBOS_TOP) src kernel boot arch $(OBOS_ARCH) ] ; + diff --git a/src/kernel/boot/platform/openfirmware/console.cpp b/src/kernel/boot/platform/openfirmware/console.cpp new file mode 100644 index 0000000000..5aeee58e8d --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/console.cpp @@ -0,0 +1,76 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include + +#include "Handle.h" +#include "console.h" +#include "openfirmware.h" + + +class ConsoleHandle : public Handle { + public: + ConsoleHandle(); + + 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); +}; + +static ConsoleHandle sInput, sOutput; +FILE *stdin, *stdout, *stderr; +int gChosen; + + +ConsoleHandle::ConsoleHandle() + : Handle() +{ +} + + +ssize_t +ConsoleHandle::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) +{ + // don't seek in character devices + return of_read(fHandle, buffer, bufferSize); +} + + +ssize_t +ConsoleHandle::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize) +{ + // don't seek in character devices + return of_write(fHandle, buffer, bufferSize); +} + + +// #pragma mark - + + +status_t +console_init(void) +{ + gChosen = of_finddevice("/chosen"); + if (gChosen == OF_FAILED) + return B_ERROR; + + int input, output; + if (of_getprop(gChosen, "stdin", &input, sizeof(int)) == OF_FAILED) + return B_ERROR; + if (of_getprop(gChosen, "stdout", &output, sizeof(int)) == OF_FAILED) + return B_ERROR; + + sInput.SetHandle(input); + sOutput.SetHandle(output); + + // now that we're initialized, enable stdio functionality + stdin = (FILE *)&sInput; + stdout = stderr = (FILE *)&sOutput; + + return B_OK; +} + + diff --git a/src/kernel/boot/platform/openfirmware/console.h b/src/kernel/boot/platform/openfirmware/console.h new file mode 100644 index 0000000000..4af3116284 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/console.h @@ -0,0 +1,29 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef CONSOLE_H +#define CONSOLE_H + + +#include +#include + +#include "Handle.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +extern status_t console_init(void); + +extern status_t set_cursor_pos(FILE *, int x, int y); +extern status_t set_foreground_color(FILE *, int c); +extern status_t set_background_color(FILE *, int c); + +#ifdef __cplusplus +} +#endif + +#endif /* CONSOLE_H */ diff --git a/src/kernel/boot/platform/openfirmware/debug.c b/src/kernel/boot/platform/openfirmware/debug.c new file mode 100644 index 0000000000..c861d155fc --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/debug.c @@ -0,0 +1,31 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + +#include "openfirmware.h" + + +/** ToDo: this works only after console_init() was called. + * But it probably should do something before as well... + */ + +void +panic(const char *format, ...) +{ + va_list list; + + puts("*** PANIC ***"); + + va_start(list, format); + vprintf(format, list); + va_end(list); + + of_exit(); +} + diff --git a/src/kernel/boot/platform/openfirmware/devices.cpp b/src/kernel/boot/platform/openfirmware/devices.cpp new file mode 100644 index 0000000000..452cf00af8 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/devices.cpp @@ -0,0 +1,30 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include +#include + +#include "Handle.h" +#include "openfirmware.h" + + +status_t +platform_get_boot_devices(stage2_args *args, list *devicesList) +{ + int handle; + + if ((handle = of_finddevice("ide0")) != OF_FAILED) { + Handle *device = new Handle(handle, false); + + printf("Found IDE device, handle = %d.\n", handle); + list_add_item(devicesList, device); + } + puts("platform_get_boot_devices() end."); + return B_OK; +} + diff --git a/src/kernel/boot/platform/openfirmware/heap.cpp b/src/kernel/boot/platform/openfirmware/heap.cpp new file mode 100644 index 0000000000..8417a6756b --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/heap.cpp @@ -0,0 +1,61 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include +#include "openfirmware.h" + + +#define TRACE_HEAP 1 +#if TRACE_HEAP +# define TRACE(x) printf x +#else +# define TRACE(x) ; +#endif + + +#define HEAP_SIZE 32768 + + +struct of_address { + void *base; + int size; +}; + + +status_t +platform_init_heap(stage2_args *args, void **_base, void **_top) +{ + TRACE(("platform_init_heap()\n")); + + int memory; + if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED) + return B_ERROR; + + printf("memory = %d\n", memory); + struct of_address available; + int memPackage = of_instance_to_package(memory); + printf("memPackage = %d\n", memPackage); + of_getprop(memPackage, "available", &available, sizeof(struct of_address)); + printf("available: base = %p, size = %d\n", available.base, available.size); + + *_base = of_claim(available.base, HEAP_SIZE); + printf("heap base = %p\n", *_base); + *_top = (void *)((int8 *)*_base + HEAP_SIZE); + printf("heap top = %p\n", *_top); + + return B_OK; +} + + +void +platform_release_heap(void *base) +{ + if (base != NULL) + of_release(base, HEAP_SIZE); +} + diff --git a/src/kernel/boot/platform/openfirmware/openfirmware.c b/src/kernel/boot/platform/openfirmware/openfirmware.c new file mode 100644 index 0000000000..c71d6c36ed --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/openfirmware.c @@ -0,0 +1,471 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include "openfirmware.h" +#include + + +// OpenFirmware entry function +static int (*gCallOpenFirmware)(void *) = 0; + + +void +of_init(int (*openFirmwareEntry)(void *)) +{ + gCallOpenFirmware = openFirmwareEntry; +} + + +int +of_call_method(const char *method, int numArgs, int numReturns, ...) +{ + struct { + const char *name; + int num_args; + int num_returns; + void *args[10]; + } args = {method, numArgs, numReturns}; + va_list list; + int i; + + // iterate over all arguments and copy them into the + // structure passed over to the OpenFirmware + + va_start(list, numReturns); + for (i = 0; i < numArgs; i++) { + // copy args + args.args[i] = (void *)va_arg(list, void *); + } + for (i = numArgs; i < numArgs + numReturns; i++) { + // clear return values + args.args[i] = NULL; + } + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + if (numReturns > 0) { + // copy return values over to the provided location + + for (i = numArgs; i < numArgs + numReturns; i++) { + void **store = va_arg(list, void **); + if (store) + *store = args.args[i]; + } + } + va_end(list); + + return 0; +} + + +int +of_finddevice(const char *device) +{ + struct { + const char *name; + int num_args; + int num_returns; + const char *device; + int handle; + } args = {"finddevice", 1, 1, device, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.handle; +} + + +/** Returns the first child of the given node + */ + +int +of_child(int node) +{ + struct { + const char *name; + int num_args; + int num_returns; + int node; + int child; + } args = {"child", 1, 1, node, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.child; +} + + +/** Returns the next sibling of the given node + */ + +int +of_peer(int node) +{ + struct { + const char *name; + int num_args; + int num_returns; + int node; + int next_sibling; + } args = {"peer", 1, 1, node, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.next_sibling; +} + + +/** Returns the parent of the given node + */ + +int +of_parent(int node) +{ + struct { + const char *name; + int num_args; + int num_returns; + int node; + int parent; + } args = {"parent", 1, 1, node, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.parent; +} + + +int +of_instance_to_path(int instance, char *pathBuffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int instance; + char *path_buffer; + int buffer_size; + int size; + } args = {"instance-to-path", 3, 1, instance, pathBuffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_instance_to_package(int instance) +{ + struct { + const char *name; + int num_args; + int num_returns; + int instance; + int package; + } args = {"instance-to-package", 1, 1, instance, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.package; +} + + +int +of_getprop(int package, const char *property, void *buffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int package; + const char *property; + void *buffer; + int buffer_size; + int size; + } args = {"getprop", 4, 1, package, property, buffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_setprop(int package, const char *property, const void *buffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int package; + const char *property; + const void *buffer; + int buffer_size; + int size; + } args = {"setprop", 4, 1, package, property, buffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_getproplen(int package, const char *property) +{ + struct { + const char *name; + int num_args; + int num_returns; + int package; + const char *property; + int size; + } args = {"getproplen", 2, 1, package, property, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_nextprop(int package, const char *previousProperty, char *nextProperty) +{ + struct { + const char *name; + int num_args; + int num_returns; + int package; + const char *previous_property; + char *next_property; + int flag; + } args = {"nextprop", 3, 1, package, previousProperty, nextProperty, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.flag; +} + + +int +of_package_to_path(int package, char *pathBuffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int package; + char *path_buffer; + int buffer_size; + int size; + } args = {"package-to-path", 3, 1, package, pathBuffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +// I/O functions + + +int +of_open(const char *nodeName) +{ + struct { + const char *name; + int num_args; + int num_returns; + const char *node_name; + int handle; + } args = {"open", 1, 1, nodeName, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED || args.handle == 0) + return OF_FAILED; + + return args.handle; +} + + +void +of_close(int handle) +{ + struct { + const char *name; + int num_args; + int num_returns; + int handle; + } args = {"close", 1, 0, handle}; + + gCallOpenFirmware(&args); +} + + +int +of_read(int handle, void *buffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int handle; + void *buffer; + int buffer_size; + int size; + } args = {"read", 3, 1, handle, buffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_write(int handle, const void *buffer, int bufferSize) +{ + struct { + const char *name; + int num_args; + int num_returns; + int handle; + const void *buffer; + int buffer_size; + int size; + } args = {"write", 3, 1, handle, buffer, bufferSize, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.size; +} + + +int +of_seek(int handle, long long pos) +{ + struct { + const char *name; + int num_args; + int num_returns; + int handle; + int64 pos; + int status; + } args = {"seek", 3, 1, handle, pos, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.status; +} + + +// memory functions + + +int +of_release(void *virtual, int size) +{ + struct { + const char *name; + int num_args; + int num_returns; + void *virtual; + int size; + } args = {"release", 2, 0, virtual, size}; + + return gCallOpenFirmware(&args); +} + + +void * +of_claim(void *virtual, int size) +{ + struct { + const char *name; + int num_args; + int num_returns; + void *virtual; + int size; + int align; + void *address; + } args = {"claim", 3, 1, virtual, size, 64}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return NULL; + + return args.address; +} + + +// misc functions + + +/** tests if the given service is missing + */ + +int +of_test(const char *service) +{ + struct { + const char *name; + int num_args; + int num_returns; + const char *service; + int missing; + } args = {"test", 1, 1, service, 0}; + + if (gCallOpenFirmware(&args) == OF_FAILED) + return OF_FAILED; + + return args.missing; +} + + +/** Returns the millisecond counter + */ + +int +of_milliseconds(void) +{ + struct { + const char *name; + int num_args; + int num_returns; + int milliseconds; + } args = {"milliseconds", 0, 1, 0}; + + gCallOpenFirmware(&args); + + return args.milliseconds; +} + + +void +of_exit(void) +{ + struct { + const char *name; + int num_args; + int num_returns; + } args = {"exit", 0, 0}; + + gCallOpenFirmware(&args); +} + diff --git a/src/kernel/boot/platform/openfirmware/openfirmware.h b/src/kernel/boot/platform/openfirmware/openfirmware.h new file mode 100644 index 0000000000..8feb195e25 --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/openfirmware.h @@ -0,0 +1,57 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef OPEN_FIRMWARE_H +#define OPEN_FIRMWARE_H + + +#include + + +#define OF_FAILED (-1) + +/* global device tree/properties access */ +extern int gChosen; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void of_init(int (*openFirmwareEntry)(void *)); + +/* device tree functions */ +extern int of_finddevice(const char *device); +extern int of_child(int node); +extern int of_peer(int node); +extern int of_parent(int node); +extern int of_instance_to_path(int instance, char *pathBuffer, int bufferSize); +extern int of_instance_to_package(int instance); +extern int of_getprop(int package, const char *property, void *buffer, int bufferSize); +extern int of_setprop(int package, const char *property, const void *buffer, int bufferSize); +extern int of_nextprop(int package, const char *previousProperty, char *nextProperty); +extern int of_getproplen(int package, const char *property); +extern int of_package_to_path(int package, char *pathBuffer, int bufferSize); + +/* I/O functions */ +extern int of_open(const char *nodeName); +extern void of_close(int handle); +extern int of_read(int handle, void *buffer, int bufferSize); +extern int of_write(int handle, const void *buffer, int bufferSize); +extern int of_seek(int handle, off_t pos); + +/* memory functions */ +extern int of_release(void *virtualAddress, int size); +extern void *of_claim(void *virtualAddress, int size); + +/* misc functions */ +extern int of_test(const char *service); +extern int of_milliseconds(void); +extern void of_exit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OPEN_FIRMWARE_H */ diff --git a/src/kernel/boot/platform/openfirmware/start.c b/src/kernel/boot/platform/openfirmware/start.c new file mode 100644 index 0000000000..3eb627ef8f --- /dev/null +++ b/src/kernel/boot/platform/openfirmware/start.c @@ -0,0 +1,71 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include + +#include + +#include "openfirmware.h" +#include "console.h" + + +void _start(uint32 _unused1, uint32 _unused2, void *openFirmwareEntry); +void start(void *openFirmwareEntry); +int boot(stage2_args *args); + +// GCC defined globals +extern void (*__ctor_list)(void); +extern void (*__ctor_end)(void); +extern uint8 __bss_start; +extern uint8 _end; + + +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); +} + + +void +_start(uint32 _unused1, uint32 _unused3, void *openFirmwareEntry) +{ + // According to the PowerPC bindings, OpenFirmware should have created + // a stack of 32kB or higher for us at this point + + clear_bss(); + call_ctors(); + // call C++ constructors before doing anything else + + start(openFirmwareEntry); +} + + +void +start(void *openFirmwareEntry) +{ + of_init(openFirmwareEntry); + console_init(); + + boot(NULL); + // if everything wents fine, boot() never returns + + of_exit(); +} + +