diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index 2c667b3eba..31c6be11df 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src system boot arch arm ; #XXX: should not be needed here UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UseLibraryHeaders [ FDirName libfdt ] ; { local defines = _BOOT_MODE ; diff --git a/src/system/boot/arch/arm/arch_mmu.cpp b/src/system/boot/arch/arm/arch_mmu.cpp index c26893c100..890526e9c1 100644 --- a/src/system/boot/arch/arm/arch_mmu.cpp +++ b/src/system/boot/arch/arm/arch_mmu.cpp @@ -23,6 +23,12 @@ #include +extern "C" { +#include +#include +#include +}; + //#define TRACE_MMU #ifdef TRACE_MMU @@ -37,6 +43,8 @@ // You also need to define ENABLE_SERIAL in serial.cpp // for output to work. +extern void *gFDT; + /* TODO: @@ -551,11 +559,113 @@ mmu_init_for_kernel(void) } +//TODO:move this to generic/ ? +static status_t +find_physical_memory_ranges(uint64 &total) +{ + int node; + const void *prop; + int len; + + dprintf("checking for memory...\n"); + // let's just skip the OF way (prop memory on /chosen) + //node = fdt_path_offset(gFDT, "/chosen"); + node = fdt_path_offset(gFDT, "/memory"); + // TODO: check devicetype=="memory" ? + + total = 0; + + // 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 = fdt_path_offset(gFDT, "/"); + int32 regAddressCells = 1; + int32 regSizeCells = 1; + prop = fdt_getprop(gFDT, root, "#address-cells", &len); + if (prop && len == sizeof(uint32)) + regAddressCells = fdt32_to_cpu(*(uint32_t *)prop); + prop = fdt_getprop(gFDT, root, "#size-cells", &len); + if (prop && len == sizeof(uint32)) + regSizeCells = fdt32_to_cpu(*(uint32_t *)prop); + + + // NOTE : Size Cells of 2 is possible in theory... but I haven't seen it yet. + if (regAddressCells > 2 || regSizeCells > 1) { + panic("%s: Unsupported FDT cell count detected.\n" + "Address Cells: %" B_PRId32 "; Size Cells: %" B_PRId32 + " (CPU > 64bit?).\n", __func__, regAddressCells, regSizeCells); + return B_ERROR; + } + + prop = fdt_getprop(gFDT, node, "reg", &len); + if (prop == NULL) { + panic("FDT /memory reg property not set"); + return B_ERROR; + } + + const uint32 *p = (const uint32 *)prop; + for (int32 i = 0; len; i++) { + uint64 base; + uint64 size; + if (regAddressCells == 2) + base = fdt64_to_cpu(*(uint64_t *)p); + else + base = fdt32_to_cpu(*(uint32_t *)p); + p += regAddressCells; + if (regSizeCells == 2) + size = fdt64_to_cpu(*(uint64_t *)p); + else + size = fdt32_to_cpu(*(uint32_t *)p); + p += regAddressCells; + len -= sizeof(uint32) * (regAddressCells + regSizeCells); + + if (size <= 0) { + dprintf("%ld: empty region\n", i); + continue; + } + dprintf("%" B_PRIu32 ": base = %" B_PRIu64 "," + "size = %" B_PRIu64 "\n", i, base, size); + + total += size; + + if (insert_physical_memory_range(base, 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; +} + + extern "C" void mmu_init(void) { TRACE(("mmu_init\n")); + // skip RAM check if already done (rPi) + if (gKernelArgs.num_physical_memory_ranges == 0) { + // get map of physical memory (fill in kernel_args structure) + + uint64 total; + if (find_physical_memory_ranges(total) != B_OK) { + dprintf("Error: could not find physical memory ranges!\n"); + +#ifdef SDRAM_BASE + dprintf("Defaulting to 32MB at %" B_PRIx64 "\n", (uint64)SDRAM_BASE); + // specify available physical memory, using 32MB for now, since our + // ARMv5 targets have very little by default. + total = 32 * 1024 * 1024; + insert_physical_memory_range(SDRAM_BASE, total); +#else + return /*B_ERROR*/; +#endif + } + dprintf("total physical memory = %" B_PRId64 "MB\n", total / (1024 * 1024)); + } + // see if subpages are disabled if (mmu_read_C1() & (1 << 23)) sSmallPageType = ARM_MMU_L2_TYPE_SMALLNEW; diff --git a/src/system/boot/platform/u-boot/start.cpp b/src/system/boot/platform/u-boot/start.cpp index 1481e41190..655667579c 100644 --- a/src/system/boot/platform/u-boot/start.cpp +++ b/src/system/boot/platform/u-boot/start.cpp @@ -277,10 +277,6 @@ start_gen(int argc, const char **argv, struct image_header *uimage, void *fdt) args.platform.boot_tgz_size); } - // specify available physical memory, using 32MB for now, since our - // ARMv5 targets have very little by default. TODO get from FDT! - insert_physical_memory_range(SDRAM_BASE, 32 * 1024 * 1024); - // save the size of the FDT so we can map it easily after mmu_init size_t fdtSize = gFDT ? fdt_totalsize(gFDT) : 0;