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
This commit is contained in:
Axel Dörfler 2003-09-03 02:03:28 +00:00
parent ededd6e07f
commit 8abaaaf7e5
12 changed files with 944 additions and 0 deletions

View File

@ -0,0 +1,3 @@
SubDir OBOS_TOP src kernel boot platform ;
SubInclude OBOS_TOP src kernel boot platform $(OBOS_BOOT_PLATFORM) ;

View File

@ -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 <SupportDefs.h>
#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;
}

View File

@ -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 <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);
protected:
int fHandle;
bool fOwnHandle;
};
#endif /* __cplusplus */
#endif /* HANDLE_H */

View File

@ -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) ] ;

View File

@ -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 <SupportDefs.h>
#include <string.h>
#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;
}

View File

@ -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 <boot/vfs.h>
#include <boot/stdio.h>
#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 */

View File

@ -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 <boot/platform.h>
#include <boot/stdio.h>
#include <stdarg.h>
#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();
}

View File

@ -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 <boot/platform.h>
#include <boot/vfs.h>
#include <boot/stdio.h>
#include <util/kernel_cpp.h>
#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;
}

View File

@ -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 <boot/platform.h>
#include <boot/heap.h>
#include <boot/stdio.h>
#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);
}

View File

@ -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 <stdarg.h>
// 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);
}

View File

@ -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 <SupportDefs.h>
#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 */

View File

@ -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 <SupportDefs.h>
#include <boot/heap.h>
#include <string.h>
#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();
}