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