Merge branch 'master' of ssh://git.haiku-os.org/haiku
This commit is contained in:
commit
8458b41ba6
7
docs/develop/ports/ppc/cfe.txt
Normal file
7
docs/develop/ports/ppc/cfe.txt
Normal 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
|
||||
|
54
headers/private/kernel/boot/platform/cfe/cfe.h
Normal file
54
headers/private/kernel/boot/platform/cfe/cfe.h
Normal 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 */
|
38
headers/private/kernel/boot/platform/cfe/platform_arch.h
Normal file
38
headers/private/kernel/boot/platform/cfe/platform_arch.h
Normal 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 */
|
@ -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 */
|
@ -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 */
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
86
src/system/boot/platform/cfe/Handle.cpp
Normal file
86
src/system/boot/platform/cfe/Handle.cpp
Normal 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
|
||||
}
|
||||
|
34
src/system/boot/platform/cfe/Handle.h
Normal file
34
src/system/boot/platform/cfe/Handle.h
Normal 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 */
|
37
src/system/boot/platform/cfe/Jamfile
Normal file
37
src/system/boot/platform/cfe/Jamfile
Normal 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 ;
|
3
src/system/boot/platform/cfe/arch/Jamfile
Normal file
3
src/system/boot/platform/cfe/arch/Jamfile
Normal 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) ;
|
19
src/system/boot/platform/cfe/arch/ppc/Jamfile
Normal file
19
src/system/boot/platform/cfe/arch/ppc/Jamfile
Normal 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) ] ;
|
49
src/system/boot/platform/cfe/arch/ppc/arch_start_kernel.S
Normal file
49
src/system/boot/platform/cfe/arch/ppc/arch_start_kernel.S
Normal 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
|
||||
|
32
src/system/boot/platform/cfe/arch/ppc/cpu.cpp
Normal file
32
src/system/boot/platform/cfe/arch/ppc/cpu.cpp
Normal 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;
|
||||
}
|
||||
|
588
src/system/boot/platform/cfe/arch/ppc/mmu.cpp
Normal file
588
src/system/boot/platform/cfe/arch/ppc/mmu.cpp
Normal 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;
|
||||
}
|
||||
|
264
src/system/boot/platform/cfe/cfe.cpp
Normal file
264
src/system/boot/platform/cfe/cfe.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
170
src/system/boot/platform/cfe/console.cpp
Normal file
170
src/system/boot/platform/cfe/console.cpp
Normal 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;
|
||||
}
|
||||
|
21
src/system/boot/platform/cfe/console.h
Normal file
21
src/system/boot/platform/cfe/console.h
Normal 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 */
|
46
src/system/boot/platform/cfe/debug.cpp
Normal file
46
src/system/boot/platform/cfe/debug.cpp
Normal 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;
|
||||
}
|
138
src/system/boot/platform/cfe/devices.cpp
Normal file
138
src/system/boot/platform/cfe/devices.cpp
Normal 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;
|
||||
}
|
||||
|
48
src/system/boot/platform/cfe/heap.cpp
Normal file
48
src/system/boot/platform/cfe/heap.cpp
Normal 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);
|
||||
}
|
||||
|
48
src/system/boot/platform/cfe/menu.cpp
Normal file
48
src/system/boot/platform/cfe/menu.cpp
Normal 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);
|
||||
}
|
36
src/system/boot/platform/cfe/mmu.cpp
Normal file
36
src/system/boot/platform/cfe/mmu.cpp
Normal 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);
|
||||
}
|
||||
|
177
src/system/boot/platform/cfe/start.cpp
Normal file
177
src/system/boot/platform/cfe/start.cpp
Normal 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);
|
||||
}
|
23
src/system/boot/platform/cfe/support.cpp
Normal file
23
src/system/boot/platform/cfe/support.cpp
Normal 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;
|
||||
}
|
||||
|
17
src/system/boot/platform/cfe/support.h
Normal file
17
src/system/boot/platform/cfe/support.h
Normal 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
|
72
src/system/boot/platform/cfe/video.cpp
Normal file
72
src/system/boot/platform/cfe/video.cpp
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
45
src/system/ldscripts/ppc/boot_loader_cfe.ld
Normal file
45
src/system/ldscripts/ppc/boot_loader_cfe.ld
Normal 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_*) }
|
||||
}
|
Loading…
Reference in New Issue
Block a user