sparc: fix bootloader build
- Add various missing jamfiles - Add required implementation stubs - Update openfirmware jamfiles for multiboot support - Update linker rules for sparc loader Change-Id: I2d06c7a4d33827f58d82946687003f9a0dcb1b7d Reviewed-on: https://review.haiku-os.org/c/1329 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
** Copyright 2019, Adrien Destugues, [email protected]
|
||||||
|
** Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_SPARC_MMU_H
|
||||||
|
#define _KERNEL_ARCH_SPARC_MMU_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arch_cpu.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _KERNEL_ARCH_SPARC_MMU_H */
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel bus_managers config_manager arch $(TARGET_ARCH) ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
|
||||||
|
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] ;
|
||||||
|
|
||||||
|
KernelStaticLibrary config_manager_arch :
|
||||||
|
config_manager_arch.c
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* arch-specific config manager
|
||||||
|
*
|
||||||
|
* Authors (in chronological order):
|
||||||
|
* François Revol ([email protected])
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <config_manager.h>
|
||||||
|
|
||||||
|
int config_manager_scan_hardcoded(struct device_info **info, int32 *count)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel bus_managers pci arch sparc ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ]
|
||||||
|
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) openfirmware ] ;
|
||||||
|
|
||||||
|
KernelStaticLibrary pci_arch_bus_manager :
|
||||||
|
pci_controller.cpp
|
||||||
|
pci_io.c
|
||||||
|
|
||||||
|
# openfirmware
|
||||||
|
# TODO
|
||||||
|
;
|
||||||
|
|
||||||
@@ -1,33 +1,29 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch sparc ;
|
SubDir HAIKU_TOP src system boot arch sparc ;
|
||||||
|
|
||||||
{
|
|
||||||
local defines = _BOOT_MODE ;
|
|
||||||
|
|
||||||
defines = [ FDefines $(defines) ] ;
|
|
||||||
SubDirCcFlags $(defines) ;
|
|
||||||
SubDirC++Flags $(defines) -fno-rtti ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local kernelLibArchObjects =
|
local kernelLibArchObjects =
|
||||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>byteorder.o
|
|
||||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>memcpy.o
|
<src!system!kernel!lib!arch!$(TARGET_ARCH)>memcpy.o
|
||||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>memset.o
|
<src!system!kernel!lib!arch!$(TARGET_ARCH)>memset.o
|
||||||
;
|
;
|
||||||
|
|
||||||
BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
|
local platform ;
|
||||||
debug_uart_8250.cpp
|
for platform in [ MultiBootSubDirSetup openfirmware ] {
|
||||||
#arch_uart_8250.cpp
|
on $(platform) {
|
||||||
arch_elf.cpp
|
DEFINES += _BOOT_MODE ;
|
||||||
: # additional flags
|
|
||||||
:
|
|
||||||
$(kernelArchObjects)
|
|
||||||
$(kernelLibArchObjects)
|
|
||||||
;
|
|
||||||
|
|
||||||
SEARCH on [ FGristFiles arch_elf.cpp arch_uart_8250.cpp ]
|
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
||||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ;
|
debug_uart_8250.cpp
|
||||||
|
#arch_uart_8250.cpp
|
||||||
|
arch_elf.cpp
|
||||||
|
: # additional flags
|
||||||
|
:
|
||||||
|
$(kernelArchObjects)
|
||||||
|
$(kernelLibArchObjects)
|
||||||
|
;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles debug_uart_8250.cpp ]
|
SEARCH on [ FGristFiles arch_elf.cpp arch_uart_8250.cpp ]
|
||||||
= [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ;
|
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ;
|
||||||
|
|
||||||
|
SEARCH on [ FGristFiles debug_uart_8250.cpp ]
|
||||||
|
= [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ SubDirC++Flags -D_BOOT_MODE -fno-rtti ;
|
|||||||
|
|
||||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
|
{
|
||||||
|
local defines = _BOOT_MODE _BOOT_PLATFORM_OPENFIRMWARE ;
|
||||||
|
defines = [ FDefines $(defines) ] ;
|
||||||
|
SubDirCcFlags $(defines) ;
|
||||||
|
SubDirC++Flags $(defines) -fno-rtti ;
|
||||||
|
}
|
||||||
|
|
||||||
BootMergeObject boot_platform_openfirmware.o :
|
local platform_src =
|
||||||
console.cpp
|
console.cpp
|
||||||
debug.cpp
|
debug.cpp
|
||||||
devices.cpp
|
devices.cpp
|
||||||
@@ -19,23 +24,41 @@ BootMergeObject boot_platform_openfirmware.o :
|
|||||||
start.cpp
|
start.cpp
|
||||||
support.cpp
|
support.cpp
|
||||||
video.cpp
|
video.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
local kernel_src =
|
||||||
openfirmware.cpp
|
openfirmware.cpp
|
||||||
openfirmware_devices.cpp
|
openfirmware_devices.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
local vesa_src =
|
||||||
# VESA/DDC EDID
|
# VESA/DDC EDID
|
||||||
decode_edid.c
|
decode_edid.c
|
||||||
dump_edid.c
|
dump_edid.c
|
||||||
|
|
||||||
:
|
|
||||||
:
|
|
||||||
boot_platform_generic.a
|
|
||||||
boot_platform_openfirmware_$(TARGET_ARCH).a
|
|
||||||
;
|
;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles $(genericPlatformSources) ]
|
local platform ;
|
||||||
= [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
|
for platform in [ MultiBootSubDirSetup openfirmware ] {
|
||||||
SEARCH on [ FGristFiles openfirmware.cpp openfirmware_devices.cpp ]
|
on $(platform) {
|
||||||
= [ FDirName $(HAIKU_TOP) src system kernel platform openfirmware ] ;
|
BootMergeObject boot_platform_openfirmware.o :
|
||||||
|
|
||||||
|
$(platform_src)
|
||||||
|
$(kernel_src)
|
||||||
|
$(vesa_src)
|
||||||
|
:
|
||||||
|
:
|
||||||
|
boot_platform_generic_openfirmware.a
|
||||||
|
boot_platform_openfirmware_$(TARGET_ARCH).a
|
||||||
|
;
|
||||||
|
|
||||||
|
# SEARCH on [ FGristFiles $(genericPlatformSources) ]
|
||||||
|
# = [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
|
||||||
|
SEARCH on [ FGristFiles $(kernel_src) ]
|
||||||
|
= [ FDirName $(HAIKU_TOP) src system kernel platform openfirmware ] ;
|
||||||
|
SEARCH on [ FGristFiles $(vesa_src) ]
|
||||||
|
= [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src system boot platform openfirmware arch ;
|
SubInclude HAIKU_TOP src system boot platform openfirmware arch ;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
SubDir HAIKU_TOP src system boot platform openfirmware arch sparc ;
|
SubDir HAIKU_TOP src system boot platform openfirmware arch sparc ;
|
||||||
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ;
|
SubDirHdrs $(HAIKU_TOP) src system boot platform $(HAIKU_BOOT_PLATFORM) ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ]
|
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ]
|
||||||
[ FDirName kernel boot platform $(HAIKU_KERNEL_PLATFORM) ]
|
[ FDirName kernel boot platform $(HAIKU_KERNEL_PLATFORM) ]
|
||||||
@@ -9,6 +9,9 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ]
|
|||||||
SubDirC++Flags -fno-rtti ;
|
SubDirC++Flags -fno-rtti ;
|
||||||
|
|
||||||
BootStaticLibrary boot_platform_openfirmware_sparc :
|
BootStaticLibrary boot_platform_openfirmware_sparc :
|
||||||
|
arch_start_kernel.S
|
||||||
|
cpu.cpp
|
||||||
|
mmu.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ]
|
SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ]
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* 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):
|
||||||
|
return
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boot/platform/openfirmware/platform_arch.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <boot/kernel_args.h>
|
||||||
|
#include <boot/stage2.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <platform/openfirmware/devices.h>
|
||||||
|
#include <platform/openfirmware/openfirmware.h>
|
||||||
|
|
||||||
|
#define TRACE_CPU
|
||||||
|
#ifdef TRACE_CPU
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
boot_arch_cpu_init(void)
|
||||||
|
{
|
||||||
|
int32 busFrequency = 0;
|
||||||
|
|
||||||
|
int root = of_finddevice("/");
|
||||||
|
if (root == OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init(): Failed to open \"/\"!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
of_getprop(root, "clock-frequency", &busFrequency, 4);
|
||||||
|
// we might find it in /cpus instead
|
||||||
|
|
||||||
|
// iterate through the "/cpus" node to find all CPUs
|
||||||
|
int cpus = of_finddevice("/cpus");
|
||||||
|
if (cpus == OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init(): Failed to open \"/cpus\"!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
char cpuPath[256];
|
||||||
|
int cookie = 0;
|
||||||
|
int cpuCount = 0;
|
||||||
|
while (of_get_next_device(&cookie, cpus, "cpu", cpuPath,
|
||||||
|
sizeof(cpuPath)) == B_OK) {
|
||||||
|
TRACE(("found CPU: %s\n", cpuPath));
|
||||||
|
|
||||||
|
// For the first CPU get the frequencies of CPU, bus, and time base.
|
||||||
|
// We assume they are the same for all CPUs.
|
||||||
|
if (cpuCount == 0) {
|
||||||
|
int cpu = of_finddevice(cpuPath);
|
||||||
|
if (cpu == OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init: Failed get CPU device node!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Does encode-int really encode quadlet (32 bit numbers)
|
||||||
|
// only?
|
||||||
|
int32 clockFrequency;
|
||||||
|
if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4)
|
||||||
|
== OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init: Failed to get CPU clock "
|
||||||
|
"frequency!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (busFrequency == 0
|
||||||
|
&& of_getprop(cpu, "bus-frequency", &busFrequency, 4)
|
||||||
|
== OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init: Failed to get bus clock "
|
||||||
|
"frequency!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
int32 timeBaseFrequency;
|
||||||
|
if (of_getprop(cpu, "timebase-frequency", &timeBaseFrequency, 4)
|
||||||
|
== OF_FAILED) {
|
||||||
|
printf("boot_arch_cpu_init: Failed to get time base "
|
||||||
|
"frequency!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
gKernelArgs.arch_args.cpu_frequency = clockFrequency;
|
||||||
|
gKernelArgs.arch_args.bus_frequency = busFrequency;
|
||||||
|
gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency;
|
||||||
|
|
||||||
|
TRACE((" CPU clock frequency: %d\n", clockFrequency));
|
||||||
|
TRACE((" bus clock frequency: %d\n", busFrequency));
|
||||||
|
TRACE((" time base frequency: %d\n", timeBaseFrequency));
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpuCount == 0) {
|
||||||
|
printf("boot_arch_cpu_init(): Found no CPUs!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
gKernelArgs.num_cpus = cpuCount;
|
||||||
|
|
||||||
|
// allocate the kernel stacks (the memory stuff is already initialized
|
||||||
|
// at this point)
|
||||||
|
addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000,
|
||||||
|
cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE),
|
||||||
|
B_READ_AREA | B_WRITE_AREA, false);
|
||||||
|
if (!stack) {
|
||||||
|
printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n");
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < cpuCount; i++) {
|
||||||
|
gKernelArgs.cpu_kstack[i].start = stack;
|
||||||
|
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
|
||||||
|
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
|
||||||
|
stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,457 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Axel Dörfler, [email protected].
|
||||||
|
* Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
* Alexander von Gluck, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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 <platform/openfirmware/openfirmware.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
|
||||||
|
|
||||||
|
|
||||||
|
uint32 sPageTableHashMask;
|
||||||
|
|
||||||
|
|
||||||
|
// begin and end of the boot loader
|
||||||
|
extern "C" uint8 __text_begin;
|
||||||
|
extern "C" uint8 _end;
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
find_physical_memory_ranges(size_t &total)
|
||||||
|
{
|
||||||
|
int memory;
|
||||||
|
dprintf("checking for memory...\n");
|
||||||
|
if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED)
|
||||||
|
return B_ERROR;
|
||||||
|
int package = of_instance_to_package(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 = of_finddevice("/");
|
||||||
|
int32 regAddressCells = of_address_cells(root);
|
||||||
|
int32 regSizeCells = of_size_cells(root);
|
||||||
|
if (regAddressCells == OF_FAILED || regSizeCells == OF_FAILED) {
|
||||||
|
dprintf("finding base/size length counts failed, assume 32-bit.\n");
|
||||||
|
regAddressCells = 1;
|
||||||
|
regSizeCells = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE : Size Cells of 2 is possible in theory... but I haven't seen it yet.
|
||||||
|
if (regAddressCells > 2 || regSizeCells > 1) {
|
||||||
|
panic("%s: Unsupported OpenFirmware cell count detected.\n"
|
||||||
|
"Address Cells: %" B_PRId32 "; Size Cells: %" B_PRId32
|
||||||
|
" (CPU > 64bit?).\n", __func__, regAddressCells, regSizeCells);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On 64-bit PowerPC systems (G5), our mem base range address is larger
|
||||||
|
if (regAddressCells == 2) {
|
||||||
|
struct of_region<uint64> 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("%d: 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<uint32> 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("%d: empty region\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dprintf("%" B_PRIu32 ": base = %" B_PRIu32 ","
|
||||||
|
"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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_virtual_allocated(void *address, size_t size)
|
||||||
|
{
|
||||||
|
uint64 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)
|
||||||
|
{
|
||||||
|
uint64 foundBase;
|
||||||
|
return !get_free_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_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
|
||||||
|
map_page(void *virtualAddress, void *physicalAddress, uint8 mode)
|
||||||
|
{
|
||||||
|
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 *)(intptr_t(virtualAddress) + offset),
|
||||||
|
(void *)(intptr_t(physicalAddress) + offset), mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 *)(addr_t)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 *)(addr_t)(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 *)(addr_t)(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_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - OpenFirmware callbacks and public API
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
map_callback(struct of_arguments *args)
|
||||||
|
{
|
||||||
|
void *physicalAddress = (void *)args->Argument(0);
|
||||||
|
void *virtualAddress = (void *)args->Argument(1);
|
||||||
|
int length = args->Argument(2);
|
||||||
|
int mode = args->Argument(3);
|
||||||
|
intptr_t &error = args->ReturnValue(0);
|
||||||
|
|
||||||
|
// insert range in physical allocated if needed
|
||||||
|
|
||||||
|
if (is_physical_memory(physicalAddress)
|
||||||
|
&& insert_physical_allocated_range((addr_t)physicalAddress, length)
|
||||||
|
!= B_OK) {
|
||||||
|
error = -1;
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert range in virtual allocated
|
||||||
|
|
||||||
|
if (insert_virtual_allocated_range((addr_t)virtualAddress, length)
|
||||||
|
!= B_OK) {
|
||||||
|
error = -2;
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map range into the page table
|
||||||
|
|
||||||
|
map_range(virtualAddress, physicalAddress, length, mode);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
unmap_callback(struct of_arguments *args)
|
||||||
|
{
|
||||||
|
/* void *address = (void *)args->Argument(0);
|
||||||
|
int length = args->Argument(1);
|
||||||
|
int &error = args->ReturnValue(0);
|
||||||
|
*/
|
||||||
|
// TODO: to be implemented
|
||||||
|
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
translate_callback(struct of_arguments *args)
|
||||||
|
{
|
||||||
|
// could not find the translation
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
alloc_real_mem_callback(struct of_arguments *args)
|
||||||
|
{
|
||||||
|
/* addr_t minAddress = (addr_t)args->Argument(0);
|
||||||
|
addr_t maxAddress = (addr_t)args->Argument(1);
|
||||||
|
int length = args->Argument(2);
|
||||||
|
int mode = args->Argument(3);
|
||||||
|
int &error = args->ReturnValue(0);
|
||||||
|
int &physicalAddress = args->ReturnValue(1);
|
||||||
|
*/
|
||||||
|
// ToDo: to be implemented
|
||||||
|
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Dispatches the callback to the responsible function */
|
||||||
|
|
||||||
|
static int
|
||||||
|
callback(struct of_arguments *args)
|
||||||
|
{
|
||||||
|
const char *name = args->name;
|
||||||
|
TRACE("OF CALLBACK: %s\n", name);
|
||||||
|
|
||||||
|
if (!strcmp(name, "map"))
|
||||||
|
return map_callback(args);
|
||||||
|
else if (!strcmp(name, "unmap"))
|
||||||
|
return unmap_callback(args);
|
||||||
|
else if (!strcmp(name, "translate"))
|
||||||
|
return translate_callback(args);
|
||||||
|
else if (!strcmp(name, "alloc-real-mem"))
|
||||||
|
return alloc_real_mem_callback(args);
|
||||||
|
|
||||||
|
return OF_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
arch_set_callback(void)
|
||||||
|
{
|
||||||
|
// set OpenFirmware callbacks - it will ask us for memory after that
|
||||||
|
// instead of maintaining it itself
|
||||||
|
|
||||||
|
void *oldCallback = NULL;
|
||||||
|
if (of_call_client_function("set-callback", 1, 1, &callback, &oldCallback)
|
||||||
|
== OF_FAILED) {
|
||||||
|
dprintf("Error: OpenFirmware set-callback failed\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
TRACE("old callback = %p; new callback = %p\n", oldCallback, callback);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 = %luMB\n", total / (1024 * 1024));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
OUTPUT_FORMAT("elf64-sparc")
|
||||||
|
OUTPUT_ARCH(sparc:v9)
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x202000 + SIZEOF_HEADERS;
|
||||||
|
|
||||||
|
__text_begin = .;
|
||||||
|
|
||||||
|
/* text/read-only data */
|
||||||
|
.text : { *(.text .text.* .gnu.linkonce.t.*)
|
||||||
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
|
*(.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));
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
__ctor_list = .;
|
||||||
|
*(.ctors)
|
||||||
|
__ctor_end = .;
|
||||||
|
|
||||||
|
__data_start = .;
|
||||||
|
*(.data .gnu.linkonce.d.*)
|
||||||
|
*(.data.rel.ro.local .data.rel.ro*)
|
||||||
|
*(.got .got2)
|
||||||
|
*(.sdata .sdata.* .gnu.linkonce.s.* .fixup) }
|
||||||
|
|
||||||
|
/* uninitialized data (in same segment as writable data) */
|
||||||
|
__bss_start = .;
|
||||||
|
.bss : { *(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||||
|
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
. = ALIGN(0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
_end = . ;
|
||||||
|
|
||||||
|
/* Strip unnecessary stuff */
|
||||||
|
/DISCARD/ : { *(.comment .note .eh_frame .dtors .debug_* .gnu.attributes) }
|
||||||
|
}
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
SubDir HAIKU_TOP src system libroot posix string arch sparc ;
|
SubDir HAIKU_TOP src system libroot posix string arch sparc ;
|
||||||
|
|
||||||
UsePrivateSystemHeaders ;
|
local architectureObject ;
|
||||||
|
for architectureObject in [ MultiArchSubDirSetup sparc ] {
|
||||||
|
on $(architectureObject) {
|
||||||
|
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
MergeObject <$(TARGET_ARCH)>posix_string_arch_$(TARGET_ARCH).o :
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||||
memcpy.c
|
|
||||||
memset.c
|
MergeObject <$(TARGET_ARCH)>posix_string_arch_$(TARGET_ARCH).o :
|
||||||
;
|
memcpy.c
|
||||||
|
memset.c
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ if $(TARGET_ARCH) = x86_64
|
|||||||
}
|
}
|
||||||
|
|
||||||
local architectureObject ;
|
local architectureObject ;
|
||||||
for architectureObject in [ MultiArchSubDirSetup ] {
|
for architectureObject in [ MultiArchSubDirSetup sparc ] {
|
||||||
on $(architectureObject) {
|
on $(architectureObject) {
|
||||||
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
SubDir HAIKU_TOP src system runtime_loader arch sparc ;
|
||||||
|
|
||||||
|
local architectureObject ;
|
||||||
|
for architectureObject in [ MultiArchSubDirSetup sparc ] {
|
||||||
|
on $(architectureObject) {
|
||||||
|
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
||||||
|
|
||||||
|
UsePrivateHeaders runtime_loader ;
|
||||||
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
|
||||||
|
StaticLibrary <$(architecture)>libruntime_loader_$(TARGET_ARCH).a :
|
||||||
|
arch_relocate.cpp
|
||||||
|
:
|
||||||
|
<src!system!libroot!os!arch!$(TARGET_ARCH)!$(architecture)>thread.o
|
||||||
|
|
||||||
|
<src!system!libroot!posix!string!arch!$(TARGET_ARCH)!$(architecture)>memset.o
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2018, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ithamar R. Adema <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "runtime_loader_private.h"
|
||||||
|
|
||||||
|
#include <runtime_loader.h>
|
||||||
|
|
||||||
|
//#define TRACE_RLD
|
||||||
|
#ifdef TRACE_RLD
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_relocate_image(image_t *rootImage, image_t *image,
|
||||||
|
SymbolLookupCache* cache)
|
||||||
|
{
|
||||||
|
debugger("arch_relocate_image: Not Yet Implemented!");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user