From d24ddec4e4e5bb2fd466c1b3db7a4fa836fbd4ff Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 25 Jul 2011 22:26:35 +0000 Subject: [PATCH] * Move platform support.cpp into less generic of_support.cpp * Add header file to support of_support.cpp * Add support functions to obtain address and size cell lengths * Small style cleanups * Add support for G5 PowerPC cpus... * Refactor memory region code to be aware of 64-bit OF addresses. As-is the boot loader wouldn't start on G5 systems because OpenFirmware memory base addresses are stored as two 32-bit unsigned int 'cells' vs one 32-bit unsigned int 'cell' on G3/G4. I removed the static struct and replaced it with a template and pass uint32 or uint64 depending on the address cell size. Thanks for the idea DeadYak! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42486 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../platform/openfirmware/openfirmware.h | 12 ++-- src/system/boot/platform/openfirmware/Jamfile | 2 +- .../platform/openfirmware/arch/ppc/mmu.cpp | 68 ++++++++++++++++--- .../boot/platform/openfirmware/of_support.cpp | 48 +++++++++++++ .../boot/platform/openfirmware/of_support.h | 19 ++++++ .../boot/platform/openfirmware/support.cpp | 17 ----- 6 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 src/system/boot/platform/openfirmware/of_support.cpp create mode 100644 src/system/boot/platform/openfirmware/of_support.h delete mode 100644 src/system/boot/platform/openfirmware/support.cpp diff --git a/headers/private/kernel/platform/openfirmware/openfirmware.h b/headers/private/kernel/platform/openfirmware/openfirmware.h index 9e75fc10e6..065f73f49a 100644 --- a/headers/private/kernel/platform/openfirmware/openfirmware.h +++ b/headers/private/kernel/platform/openfirmware/openfirmware.h @@ -15,6 +15,13 @@ extern int gChosen; +template +struct of_region +{ + addressSize base; + uint32 size; +}; + struct of_arguments { const char *name; int num_args; @@ -27,11 +34,6 @@ struct of_arguments { #endif }; -struct of_region { - void *base; - uint32 size; -}; - #ifdef __cplusplus extern "C" { diff --git a/src/system/boot/platform/openfirmware/Jamfile b/src/system/boot/platform/openfirmware/Jamfile index 227df039bf..322ab3bea5 100644 --- a/src/system/boot/platform/openfirmware/Jamfile +++ b/src/system/boot/platform/openfirmware/Jamfile @@ -17,7 +17,7 @@ KernelMergeObject boot_platform_openfirmware.o : network.cpp real_time_clock.cpp start.cpp - support.cpp + of_support.cpp video.cpp openfirmware.cpp diff --git a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp index 7bd8e0b32b..b3111e8176 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp @@ -17,6 +17,7 @@ #include #include +#include "of_support.h" // set protection to WIMGNPP: -----PP // PP: 00 - no access @@ -69,30 +70,81 @@ remove_virtual_range_to_keep(void *start, uint32 size) static status_t find_physical_memory_ranges(size_t &total) { - int memory, package; + int memory; dprintf("checking for memory...\n"); if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED) return B_ERROR; - package = of_instance_to_package(memory); + int package = of_instance_to_package(memory); total = 0; - struct of_region regions[64]; - int count; - count = of_getprop(package, "reg", regions, sizeof(regions)); + /* Memory base addresses are provided in 32 or 64 bit flavors + #address-cells and #size-cells matches the number of 32-bit 'cells' + representing the length of the base address and size fields + */ + int root = of_finddevice("/"); + int regAddressCount = of_address_cells(root); + int regSizeCount = of_size_cells(root); + if (regAddressCount == OF_FAILED || regSizeCount == OF_FAILED) { + dprintf("finding base/size length counts failed, assume 32-bit.\n"); + regAddressCount = 1; + regSizeCount = 1; + } + dprintf("memory range address cells: %d; size cells: %d;\n", + regAddressCount, regSizeCount); + + if (regAddressCount > 2 || regSizeCount > 1) { + dprintf("Unsupported cell size detected. (machine is > 64bit?).\n"); + return B_ERROR; + } + + // On 64-bit PowerPC systems (G5), our mem base range address is larger + if (regAddressCount == 2) { + struct of_region regions[64]; + int count = of_getprop(package, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + count = of_getprop(memory, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + return B_ERROR; + count /= sizeof(regions[0]); + + for (int32 i = 0; i < count; i++) { + if (regions[i].size <= 0) { + dprintf("%ld: empty region\n", i); + continue; + } + dprintf("%" B_PRIu32 ": base = %" B_PRIu64 "," + "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); + + total += regions[i].size; + + if (insert_physical_memory_range((addr_t)regions[i].base, + regions[i].size) != B_OK) { + dprintf("cannot map physical memory range " + "(num ranges = %" B_PRIu32 ")!\n", + gKernelArgs.num_physical_memory_ranges); + return B_ERROR; + } + } + return B_OK; + } + + // Otherwise, normal 32-bit PowerPC G3 or G4 have a smaller 32-bit one + struct of_region regions[64]; + int count = of_getprop(package, "reg", regions, sizeof(regions)); if (count == OF_FAILED) count = of_getprop(memory, "reg", regions, sizeof(regions)); if (count == OF_FAILED) return B_ERROR; - count /= sizeof(of_region); + count /= sizeof(regions[0]); for (int32 i = 0; i < count; i++) { if (regions[i].size <= 0) { dprintf("%ld: empty region\n", i); continue; } - dprintf("%" B_PRIu32 ": base = %p, size = %" B_PRIu32 "\n", i, - regions[i].base, regions[i].size); + dprintf("%" B_PRIu32 ": base = %" B_PRIu32 "," + "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); total += regions[i].size; diff --git a/src/system/boot/platform/openfirmware/of_support.cpp b/src/system/boot/platform/openfirmware/of_support.cpp new file mode 100644 index 0000000000..f1e86ef809 --- /dev/null +++ b/src/system/boot/platform/openfirmware/of_support.cpp @@ -0,0 +1,48 @@ +/* + * 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 "of_support.h" +#include + + +bigtime_t +system_time(void) +{ + int result = of_milliseconds(); + return (result == OF_FAILED ? 0 : bigtime_t(result) * 1000); +} + + +/** given the package provided, get the number of cells ++ in the reg property ++ */ + +uint32 +of_address_cells(int package) { + uint32 address_cells; + if (of_getprop(package, "#address-cells", + &address_cells, sizeof(address_cells)) == OF_FAILED) + return OF_FAILED; + + return address_cells; +} + + +uint32 +of_size_cells(int package) { + uint32 size_cells; + if (of_getprop(package, "#size-cells", + &size_cells, sizeof(size_cells)) == OF_FAILED) + return OF_FAILED; + return size_cells; +} + + diff --git a/src/system/boot/platform/openfirmware/of_support.h b/src/system/boot/platform/openfirmware/of_support.h new file mode 100644 index 0000000000..a7667ec396 --- /dev/null +++ b/src/system/boot/platform/openfirmware/of_support.h @@ -0,0 +1,19 @@ +/* + * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com + */ +#ifndef OF_SUPPORT_H +#define OF_SUPPORT_H + + +#include + + +bigtime_t system_time(void); +uint32 of_address_cells(int package); +uint32 of_size_cells(int package); + +#endif diff --git a/src/system/boot/platform/openfirmware/support.cpp b/src/system/boot/platform/openfirmware/support.cpp deleted file mode 100644 index 2333b8eb24..0000000000 --- a/src/system/boot/platform/openfirmware/support.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2005, Ingo Weinhold . - * All rights reserved. Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -bigtime_t -system_time(void) -{ - int result = of_milliseconds(); - return (result == OF_FAILED ? 0 : bigtime_t(result) * 1000); -}