Merge branch 'master' of ssh://git.haiku-os.org/haiku

This commit is contained in:
Philippe Saint-Pierre 2011-11-13 22:21:17 -05:00
commit 8458b41ba6
31 changed files with 2130 additions and 25 deletions

View File

@ -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

View File

@ -0,0 +1,54 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* 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 */

View File

@ -0,0 +1,38 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 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 */

View File

@ -0,0 +1,24 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 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 */

View File

@ -0,0 +1,15 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 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 */

View File

@ -1,5 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
@ -152,7 +153,7 @@ public:
// parent already located -- locate the entry in the parent
BString locatedDirectoryPath;
if (directory->GetLocatedPath(locatedDirectoryPath))
_LocateEntryInParentDir(file, locatedDirectoryPath);
_LocateEntryInParentDir(file, locatedDirectoryPath, true);
}
}
@ -200,17 +201,17 @@ private:
}
bool _LocateDirectory(LocatableDirectory* directory,
const BString& locatedPath)
const BString& locatedPath, bool implicit)
{
if (directory == NULL
|| directory->State() != LOCATABLE_ENTRY_UNLOCATED) {
return false;
}
if (!_LocateEntry(directory, locatedPath, true, true))
if (!_LocateEntry(directory, locatedPath, implicit, true))
return false;
_LocateEntries(directory, locatedPath);
_LocateEntries(directory, locatedPath, implicit);
return true;
}
@ -244,14 +245,14 @@ private:
BString locatedName;
_SplitPath(locatedPath, locatedDirectory, locatedName);
if (locatedName == entry->Name())
_LocateDirectory(entry->Parent(), locatedDirectory);
_LocateDirectory(entry->Parent(), locatedDirectory, implicit);
}
return true;
}
bool _LocateEntryInParentDir(LocatableEntry* entry,
const BString& locatedDirectoryPath)
const BString& locatedDirectoryPath, bool implicit)
{
// construct the located entry path
BString locatedEntryPath(locatedDirectoryPath);
@ -260,11 +261,11 @@ private:
locatedEntryPath << '/';
locatedEntryPath << entry->Name();
return _LocateEntry(entry, locatedEntryPath, true, false);
return _LocateEntry(entry, locatedEntryPath, implicit, false);
}
void _LocateEntries(LocatableDirectory* directory,
const BString& locatedPath)
const BString& locatedPath, bool implicit)
{
for (LocatableEntryList::ConstIterator it
= directory->Entries().GetIterator();
@ -272,13 +273,13 @@ private:
if (entry->State() == LOCATABLE_ENTRY_LOCATED_EXPLICITLY)
continue;
if (_LocateEntryInParentDir(entry, locatedPath)) {
if (_LocateEntryInParentDir(entry, locatedPath, implicit)) {
// recurse for directories
if (LocatableDirectory* subDir
= dynamic_cast<LocatableDirectory*>(entry)) {
BString locatedEntryPath;
if (subDir->GetLocatedPath(locatedEntryPath))
_LocateEntries(subDir, locatedEntryPath);
_LocateEntries(subDir, locatedEntryPath, implicit);
}
}
}
@ -313,6 +314,8 @@ private:
directory->ReleaseReference();
return NULL;
}
directory->AddEntry(file);
fEntries.Insert(file);
return file;
@ -361,8 +364,11 @@ private:
&& parentDirectory->State() != LOCATABLE_ENTRY_UNLOCATED) {
BString locatedDirectoryPath;
if (parentDirectory->GetLocatedPath(locatedDirectoryPath))
_LocateEntryInParentDir(directory, locatedDirectoryPath);
_LocateEntryInParentDir(directory, locatedDirectoryPath, true);
}
if (parentDirectory != NULL)
parentDirectory->AddEntry(directory);
fEntries.Insert(directory);
return directory;

View File

@ -1,6 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2010, Rene Gollent, rene@gollent.com.
* Copyright 2010-2011, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
@ -107,7 +107,8 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener)
fRunButton(NULL),
fStepOverButton(NULL),
fStepIntoButton(NULL),
fStepOutButton(NULL)
fStepOutButton(NULL),
fSourceLocatePanel(NULL)
{
fTeam->Lock();
BString name = fTeam->Name();
@ -138,6 +139,8 @@ TeamWindow::~TeamWindow()
_SetActiveStackTrace(NULL);
_SetActiveImage(NULL);
_SetActiveThread(NULL);
delete fSourceLocatePanel;
}
@ -247,13 +250,15 @@ TeamWindow::MessageReceived(BMessage* message)
&& fActiveFunction->GetFunctionDebugInfo()
->SourceFile() != NULL && fActiveSourceCode != NULL
&& fActiveSourceCode->GetSourceFile() == NULL) {
BFilePanel* panel = NULL;
try {
panel = new BFilePanel(B_OPEN_PANEL,
new BMessenger(this));
panel->Show();
if (fSourceLocatePanel == NULL) {
fSourceLocatePanel = new BFilePanel(B_OPEN_PANEL,
new BMessenger(this));
}
fSourceLocatePanel->Show();
} catch (...) {
delete panel;
delete fSourceLocatePanel;
fSourceLocatePanel = NULL;
}
}
break;

View File

@ -1,6 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2010, Rene Gollent, rene@gollent.com.
* Copyright 2010-2011, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_WINDOW_H
@ -24,6 +24,7 @@
class BButton;
class BFilePanel;
class BMenuBar;
class BSplitView;
class BStringView;
@ -185,6 +186,7 @@ private:
BSplitView* fThreadSplitView;
InspectorWindow* fInspectorWindow;
GUITeamUISettings fUISettings;
BFilePanel* fSourceLocatePanel;
};

View File

@ -0,0 +1,86 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de.
* 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
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 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 */

View File

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

View File

@ -0,0 +1,3 @@
SubDir HAIKU_TOP src system boot platform cfe arch ;
SubInclude HAIKU_TOP src system boot platform cfe arch $(TARGET_ARCH) ;

View File

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

View File

@ -0,0 +1,49 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* 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

View File

@ -0,0 +1,32 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* 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;
}

View File

@ -0,0 +1,588 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de.
* Alexander von Gluck, kallisti5@unixzen.com
*/
#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;
}

View File

@ -0,0 +1,264 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* 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;
}

View File

@ -0,0 +1,170 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. 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;
}

View File

@ -0,0 +1,21 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de. 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 */

View File

@ -0,0 +1,46 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de.
* 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;
}

View File

@ -0,0 +1,138 @@
/*
* Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2010, Andreas Färber <andreas.faerber@web.de>
* 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;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de.
* 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);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de.
* 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);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de.
* 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);
}

View File

@ -0,0 +1,177 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2011, Alexander von Gluck, kallisti5@unixzen.com
* 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);
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2011, François Revol, revol@free.fr.
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold, bonefish@cs.tu-berlin.de
* Alexander von Gluck, kallisti5@unixzen.com
*/
#include "support.h"
#include <boot/platform/cfe/cfe.h>
bigtime_t
system_time(void)
{
bigtime_t result = cfe_getticks() * 1000000LL / CFE_HZ ;
return result;
}

View File

@ -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@unixzen.com
*/
#ifndef SUPPORT_H
#define SUPPORT_H
#include <OS.h>
bigtime_t system_time(void);
#endif

View File

@ -0,0 +1,72 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2010 Andreas Färber <andreas.faerber@web.de>
* 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;
}

View File

@ -199,7 +199,7 @@ void
ObjectCache::ReturnObjectToSlab(slab* source, void* object, uint32 flags)
{
if (source == NULL) {
panic("object_cache: free'd object has no slab");
panic("object_cache: free'd object %p has no slab", object);
return;
}
@ -210,7 +210,7 @@ ObjectCache::ReturnObjectToSlab(slab* source, void* object, uint32 flags)
if (object < objectsStart
|| object >= objectsStart + source->size * object_size
|| ((uint8*)object - objectsStart) % object_size != 0) {
panic("object_cache: tried to free invalid object pointer");
panic("object_cache: tried to free invalid object pointer %p", object);
return;
}
#endif // KDEBUG
@ -261,7 +261,8 @@ ObjectCache::AssertObjectNotFreed(void* object)
slab* source = ObjectSlab(object);
if (!partial.Contains(source) && !full.Contains(source)) {
panic("object_cache: to be freed object slab not part of cache!");
panic("object_cache: to be freed object %p: slab not part of cache!",
object);
return false;
}

View File

@ -3664,6 +3664,9 @@ vm_init(kernel_args* args)
vm_page_init_num_pages(args);
sAvailableMemory = vm_page_num_pages() * B_PAGE_SIZE;
slab_init(args);
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
size_t heapSize = INITIAL_HEAP_SIZE;
// try to accomodate low memory systems
while (heapSize > sAvailableMemory / 8)
@ -3671,9 +3674,6 @@ vm_init(kernel_args* args)
if (heapSize < 1024 * 1024)
panic("vm_init: go buy some RAM please.");
slab_init(args);
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
// map in the new heap and initialize it
addr_t heapBase = vm_allocate_early(args, heapSize, heapSize,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0);

View File

@ -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_*) }
}