* Introduced new build system variables

{HAIKU,HOST,TARGET}_KERNEL_PIC_{CC,LINK}FLAGS which define the
  compiler/linker flags specifying the kind of position independence
  the kernel shall have. For x86 we had and still have -fno-pic, but the
  PPC kernel has -fPIE (position independent executable) now, as we
  need to relocate it.
* The boot loader relocates the kernel now. Mostly copied the relocation
  code from the kernel ELF loader. Almost completely rewrote the PPC
  specific relocation code, though. It's more correct and more complete now
  (some things are still missing though).
* Added boot platform awareness to the kernel. Moved the generic
  Open Firmware code (openfirmware.c/h) from the boot loader to the kernel.
* The kernel PPC serial debug output is sent to the console for the time
  being.
* The PPC boot loader counts the CPUs now and allocates the kernel stacks
  (made OF device iteration a bit more flexible on the way -- the search
  can be restricted to subtree). Furthermore we really enter the kernel...
  (Yay! :-) ... and crash in the first dprintf() (in the atomic_set()
  called by acquire_spinlock()). kprintf() works, though.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15756 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2005-12-30 21:20:07 +00:00
parent 456d0d082b
commit 957a1b17eb
49 changed files with 1085 additions and 63 deletions

View File

@ -122,6 +122,16 @@ if $(HAIKU_GCC_VERSION[1]) >= 3 {
HAIKU_KERNEL_C++FLAGS += -fno-use-cxa-atexit ;
}
HAIKU_KERNEL_PIC_CCFLAGS = -fno-pic ;
HAIKU_KERNEL_PIC_LINKFLAGS = ;
if $(HAIKU_ARCH) = ppc {
# Build a position independent PPC kernel. We need to be able to relocate
# the kernel, since the virtual address space layout at boot time is not
# fixed.
HAIKU_KERNEL_PIC_CCFLAGS = -fPIE ;
HAIKU_KERNEL_PIC_LINKFLAGS = -shared -fPIE ;
}
# If the environment variable DEBUG_PRINTF is defined we define an equally
# named macro to the variable value. Some components use the macro to allow
# another function than printf() to print the debug output. The variable should
@ -322,6 +332,16 @@ HOST_KERNEL_CCFLAGS += -finline -fno-builtin
HOST_KERNEL_C++FLAGS += -finline -fno-builtin -fno-exceptions
-DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) -D_KERNEL_MODE ;
HOST_KERNEL_PIC_CCFLAGS = -fno-pic ;
HOST_KERNEL_PIC_LINKFLAGS = ;
if $(HOST_ARCH) = ppc {
# Build a position independent PPC kernel. We need to be able to relocate
# the kernel, since the virtual address space layout at boot time is not
# fixed.
HOST_KERNEL_PIC_CCFLAGS = -fPIE ;
HOST_KERNEL_PIC_LINKFLAGS = -shared -fPIE ;
}
# warning flags
HOST_WARNING_CCFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wcast-align
-Wsign-compare ;
@ -486,6 +506,7 @@ local buildVars =
ARFLAGS UNARFLAGS
KERNEL_CCFLAGS KERNEL_C++FLAGS
KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS
WARNING_CCFLAGS WARNING_C++FLAGS
KERNEL_WARNING_CCFLAGS KERNEL_WARNING_C++FLAGS

View File

@ -95,7 +95,7 @@ rule KernelAddon
Depends $(target) : $(beginGlue) $(endGlue) ;
# compile and link
SetupKernel $(sources) : -fno-pic ;
SetupKernel $(sources) : $(TARGET_KERNEL_PIC_FLAGS) ;
local linkFlags = -nostdlib -Xlinker -soname=\"$(target)\" ;
LINKFLAGS on $(target) = [ on $(target) return $(LINKFLAGS) ] $(linkFlags) ;
Main $(target) : $(sources) ;

View File

@ -0,0 +1,28 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_BOOT_ARCH_H
#define KERNEL_BOOT_ARCH_H
#include <SupportDefs.h>
#include <boot/elf.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ELF support */
extern status_t boot_arch_elf_relocate_rel(struct preloaded_image *image,
struct Elf32_Rel *rel, int rel_len);
extern status_t boot_arch_elf_relocate_rela(struct preloaded_image *image,
struct Elf32_Rela *rel, int rel_len);
#ifdef __cplusplus
}
#endif
#endif /* KERNEL_BOOT_ARCH_H */

View File

@ -19,6 +19,15 @@ struct preloaded_image {
addr_range dynamic_section;
struct Elf32_Ehdr elf_header;
struct Elf32_Sym *syms;
struct Elf32_Rel *rel;
int rel_len;
struct Elf32_Rela *rela;
int rela_len;
struct Elf32_Rel *pltrel;
int pltrel_len;
int pltrel_type;
struct Elf32_Sym *debug_symbols;
const char *debug_string_table;
uint32 num_debug_symbols, debug_string_table_size;
@ -28,4 +37,15 @@ struct preloaded_image {
// the ID field will be filled out in the kernel
};
#ifdef __cplusplus
extern "C" {
#endif
extern status_t boot_elf_resolve_symbol(struct preloaded_image *image,
struct Elf32_Sym *symbol, addr_t *symbolAddress);
#ifdef __cplusplus
}
#endif
#endif /* KERNEL_BOOT_ELF_H */

View File

@ -8,10 +8,13 @@
#include <SupportDefs.h>
struct kernel_args;
#ifdef __cplusplus
extern "C" {
#endif
/* memory management */
extern status_t arch_set_callback(void);
extern void *arch_mmu_allocate(void *address, size_t size, uint8 protection,
@ -19,6 +22,15 @@ extern void *arch_mmu_allocate(void *address, size_t size, uint8 protection,
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

View File

@ -0,0 +1,23 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_PLATFORM_H
#define _KERNEL_PLATFORM_H
#include <SupportDefs.h>
struct kernel_args;
#ifdef __cplusplus
extern "C" {
#endif
status_t platform_init(struct kernel_args *kernelArgs);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _KERNEL_PLATFORM_H

View File

@ -31,6 +31,7 @@ if $(TARGET_ARCH) = x86 {
KernelLd boot_loader :
boot_platform_$(TARGET_BOOT_PLATFORM).o
boot_arch_$(TARGET_ARCH).o
boot_loader.a
boot_net.a
boot_partitions.a
@ -68,5 +69,6 @@ actions BuildZbeos {
BuildZbeos zbeos : boot_loader ;
SubInclude HAIKU_TOP src system boot platform ;
SubInclude HAIKU_TOP src system boot arch $(TARGET_ARCH) ;
SubInclude HAIKU_TOP src system boot loader ;
SubInclude HAIKU_TOP src system boot platform ;

View File

@ -0,0 +1,7 @@
SubDir HAIKU_TOP src system boot arch ppc ;
SubDirC++Flags -fno-rtti ;
KernelMergeObject boot_arch_ppc.o :
elf.cpp
;

View File

@ -0,0 +1,378 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
/*
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <boot/arch.h>
#include <KernelExport.h>
#include <elf_priv.h>
#include <arch/elf.h>
#define CHATTY 0
status_t
boot_arch_elf_relocate_rel(struct preloaded_image *image,
struct Elf32_Rel *rel, int rel_len)
{
// there are no rel entries in PPC elf
return B_NO_ERROR;
}
static inline void
write_word32(addr_t P, Elf32_Word value)
{
*(Elf32_Word*)P = value;
}
static inline void
write_word30(addr_t P, Elf32_Word value)
{
// bits 0:29
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0x3) | (value << 2);
}
static inline bool
write_low24_check(addr_t P, Elf32_Word value)
{
// bits 6:29
// TODO: This check doesn't work, since negative values are allowed, too.
// if (value & 0xff000000)
// return false;
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0xfc000003) | (value << 2);
return true;
}
static inline bool
write_low14_check(addr_t P, Elf32_Word value)
{
// bits 16:29
// if (value & 0xffffc000)
// return false;
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0xffff0003) | (value << 2);
return true;
}
static inline void
write_half16(addr_t P, Elf32_Word value)
{
// bits 16:29
*(Elf32_Half*)P = (Elf32_Half)value;
}
static inline bool
write_half16_check(addr_t P, Elf32_Word value)
{
// bits 16:29
// if (value & 0xffff0000)
// return false;
*(Elf32_Half*)P = (Elf32_Half)value;
return true;
}
static inline Elf32_Word
lo(Elf32_Word value)
{
return (value & 0xffff);
}
static inline Elf32_Word
hi(Elf32_Word value)
{
return ((value >> 16) & 0xffff);
}
static inline Elf32_Word
ha(Elf32_Word value)
{
return (((value >> 16) + (value & 0x8000 ? 1 : 0)) & 0xffff);
}
status_t
boot_arch_elf_relocate_rela(struct preloaded_image *image,
struct Elf32_Rela *rel, int rel_len)
{
int i;
struct Elf32_Sym *sym;
int vlErr;
addr_t S = 0; // symbol address
addr_t R = 0; // section relative symbol address
addr_t G = 0; // GOT address
addr_t L = 0; // PLT address
#define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
#define A ((addr_t)rel[i].r_addend)
#define B (image->text_region.delta)
// TODO: Get the GOT address!
#define REQUIRE_GOT \
if (G == 0) { \
dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
return B_ERROR; \
}
// TODO: Get the PLT address!
#define REQUIRE_PLT \
if (L == 0) { \
dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
return B_ERROR; \
}
for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) {
#if CHATTY
dprintf("looking at rel type %d, offset 0x%x, sym 0x%x, addend 0x%x\n",
ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
#endif
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_PPC_SECTOFF:
case R_PPC_SECTOFF_LO:
case R_PPC_SECTOFF_HI:
case R_PPC_SECTOFF_HA:
dprintf("arch_elf_relocate_rela(): Getting section relative "
"symbol addresses not yet supported!\n");
return B_ERROR;
case R_PPC_ADDR32:
case R_PPC_ADDR24:
case R_PPC_ADDR16:
case R_PPC_ADDR16_LO:
case R_PPC_ADDR16_HI:
case R_PPC_ADDR16_HA:
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_REL24:
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
case R_PPC_GLOB_DAT:
case R_PPC_UADDR32:
case R_PPC_UADDR16:
case R_PPC_REL32:
case R_PPC_SDAREL16:
case R_PPC_ADDR30:
case R_PPC_JMP_SLOT:
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
vlErr = boot_elf_resolve_symbol(image, sym, &S);
if (vlErr<0)
return vlErr;
break;
}
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_PPC_NONE:
break;
case R_PPC_COPY:
// TODO: Implement!
dprintf("arch_elf_relocate_rela(): R_PPC_COPY not yet "
"supported!\n");
return B_ERROR;
case R_PPC_ADDR32:
case R_PPC_GLOB_DAT:
case R_PPC_UADDR32:
write_word32(P, S + A);
break;
case R_PPC_ADDR24:
if (write_low24_check(P, (S + A) >> 2))
break;
dprintf("R_PPC_ADDR24 overflow\n");
return B_BAD_DATA;
case R_PPC_ADDR16:
case R_PPC_UADDR16:
if (write_half16_check(P, S + A))
break;
dprintf("R_PPC_ADDR16 overflow\n");
return B_BAD_DATA;
case R_PPC_ADDR16_LO:
write_half16(P, lo(S + A));
break;
case R_PPC_ADDR16_HI:
write_half16(P, hi(S + A));
break;
case R_PPC_ADDR16_HA:
write_half16(P, ha(S + A));
break;
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
if (write_low14_check(P, (S + A) >> 2))
break;
dprintf("R_PPC_ADDR14 overflow\n");
return B_BAD_DATA;
case R_PPC_REL24:
if (write_low24_check(P, (S + A - P) >> 2))
break;
dprintf("R_PPC_REL24 overflow: 0x%lx\n", (S + A - P) >> 2);
return B_BAD_DATA;
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
if (write_low14_check(P, (S + A - P) >> 2))
break;
dprintf("R_PPC_REL14 overflow\n");
return B_BAD_DATA;
case R_PPC_GOT16:
REQUIRE_GOT;
if (write_half16_check(P, G + A))
break;
dprintf("R_PPC_GOT16 overflow\n");
return B_BAD_DATA;
case R_PPC_GOT16_LO:
REQUIRE_GOT;
write_half16(P, lo(G + A));
break;
case R_PPC_GOT16_HI:
REQUIRE_GOT;
write_half16(P, hi(G + A));
break;
case R_PPC_GOT16_HA:
REQUIRE_GOT;
write_half16(P, ha(G + A));
break;
case R_PPC_JMP_SLOT:
{
// If the relative offset is small enough, we fabricate a
// relative branch instruction ("b <addr>").
addr_t jumpOffset = S - P;
if ((jumpOffset & 0xfc000000) != 0
&& (~jumpOffset & 0xfe000000) != 0) {
// Offset > 24 bit.
// TODO: Implement!
// See System V PPC ABI supplement, p. 5-6!
dprintf("arch_elf_relocate_rela(): R_PPC_JMP_SLOT: "
"Offsets > 24 bit currently not supported!\n");
dprintf("jumpOffset: %p\n", (void*)jumpOffset);
return B_ERROR;
} else {
// Offset <= 24 bit
// 0:5 opcode (= 18), 6:29 address, 30 AA, 31 LK
// "b" instruction: opcode = 18, AA = 0, LK = 0
// address: 24 high-order bits of 26 bit offset
*(uint32*)P = 0x48000000 | ((jumpOffset) & 0x03fffffc);
}
break;
}
case R_PPC_RELATIVE:
write_word32(P, B + A);
break;
case R_PPC_LOCAL24PC:
// TODO: Implement!
// low24*
// if (write_low24_check(P, ?)
// break;
// return B_BAD_DATA;
dprintf("arch_elf_relocate_rela(): R_PPC_LOCAL24PC not yet "
"supported!\n");
return B_ERROR;
case R_PPC_REL32:
write_word32(P, S + A - P);
break;
case R_PPC_PLTREL24:
REQUIRE_PLT;
if (write_low24_check(P, (L + A - P) >> 2))
break;
dprintf("R_PPC_PLTREL24 overflow\n");
return B_BAD_DATA;
case R_PPC_PLT32:
REQUIRE_PLT;
write_word32(P, L + A);
break;
case R_PPC_PLTREL32:
REQUIRE_PLT;
write_word32(P, L + A - P);
break;
case R_PPC_PLT16_LO:
REQUIRE_PLT;
write_half16(P, lo(L + A));
break;
case R_PPC_PLT16_HI:
REQUIRE_PLT;
write_half16(P, hi(L + A));
break;
case R_PPC_PLT16_HA:
write_half16(P, ha(L + A));
break;
case R_PPC_SDAREL16:
// TODO: Implement!
// if (write_half16_check(P, S + A - _SDA_BASE_))
// break;
// return B_BAD_DATA;
dprintf("arch_elf_relocate_rela(): R_PPC_SDAREL16 not yet "
"supported!\n");
return B_ERROR;
case R_PPC_SECTOFF:
if (write_half16_check(P, R + A))
break;
dprintf("R_PPC_SECTOFF overflow\n");
return B_BAD_DATA;
case R_PPC_SECTOFF_LO:
write_half16(P, lo(R + A));
break;
case R_PPC_SECTOFF_HI:
write_half16(P, hi(R + A));
break;
case R_PPC_SECTOFF_HA:
write_half16(P, ha(R + A));
break;
case R_PPC_ADDR30:
write_word30(P, (S + A - P) >> 2);
break;
default:
dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
return B_ERROR;
}
}
return B_NO_ERROR;
}

View File

@ -0,0 +1,7 @@
SubDir HAIKU_TOP src system boot arch x86 ;
SubDirC++Flags -fno-rtti ;
KernelMergeObject boot_arch_x86.o :
elf.cpp
;

View File

@ -0,0 +1,135 @@
/*
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <boot/arch.h>
#include <KernelExport.h>
#include <elf_priv.h>
#include <arch/elf.h>
//#define TRACE_ARCH_ELF
#ifdef TRACE_ARCH_ELF
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
#ifdef TRACE_ARCH_ELF
static const char *kRelocations[] = {
"R_386_NONE",
"R_386_32", /* add symbol value */
"R_386_PC32", /* add PC relative symbol value */
"R_386_GOT32", /* add PC relative GOT offset */
"R_386_PLT32", /* add PC relative PLT offset */
"R_386_COPY", /* copy data from shared object */
"R_386_GLOB_DAT", /* set GOT entry to data address */
"R_386_JMP_SLOT", /* set GOT entry to code address */
"R_386_RELATIVE", /* add load address of shared object */
"R_386_GOTOFF", /* add GOT relative symbol address */
"R_386_GOTPC", /* add PC relative GOT table address */
};
#endif
status_t
boot_arch_elf_relocate_rel(struct preloaded_image *image,
struct Elf32_Rel *rel, int rel_len)
{
struct Elf32_Sym *sym;
addr_t S;
addr_t A;
addr_t P;
addr_t final_val;
int i;
S = A = P = 0;
for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
TRACE(("looking at rel type %s, offset 0x%lx\n", kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset));
// calc S
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_386_32:
case R_386_PC32:
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
case R_386_GOTOFF:
{
int vlErr;
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
vlErr = boot_elf_resolve_symbol(image, sym, &S);
if (vlErr < 0)
return vlErr;
TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, sym)));
}
}
// calc A
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_386_32:
case R_386_PC32:
case R_386_GOT32:
case R_386_PLT32:
case R_386_RELATIVE:
case R_386_GOTOFF:
case R_386_GOTPC:
A = *(addr_t *)(image->text_region.delta + rel[i].r_offset);
TRACE(("A %p\n", (void *)A));
break;
}
// calc P
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_386_PC32:
case R_386_GOT32:
case R_386_PLT32:
case R_386_GOTPC:
P = image->text_region.delta + rel[i].r_offset;
TRACE(("P %p\n", (void *)P));
break;
}
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_386_NONE:
continue;
case R_386_32:
final_val = S + A;
break;
case R_386_PC32:
final_val = S + A - P;
break;
case R_386_RELATIVE:
// B + A;
final_val = image->text_region.delta + A;
break;
case R_386_JMP_SLOT:
case R_386_GLOB_DAT:
final_val = S;
break;
default:
dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
return EPERM;
}
*(addr_t *)(image->text_region.delta + rel[i].r_offset) = final_val;
TRACE(("-> offset %p = %p\n", (void *)(image->text_region.delta + rel[i].r_offset), (void *)final_val));
}
return B_NO_ERROR;
}
status_t
boot_arch_elf_relocate_rela(struct preloaded_image *image,
struct Elf32_Rela *rel, int rel_len)
{
dprintf("arch_elf_relocate_rela: not supported on x86\n");
return B_ERROR;
}

View File

@ -6,6 +6,7 @@
#include "elf.h"
#include <boot/arch.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#include <elf32.h>
@ -37,6 +38,69 @@ verify_elf_header(struct Elf32_Ehdr &header)
}
static status_t
elf_parse_dynamic_section(struct preloaded_image *image)
{
image->syms = 0;
image->rel = 0;
image->rel_len = 0;
image->rela = 0;
image->rela_len = 0;
image->pltrel = 0;
image->pltrel_len = 0;
image->pltrel_type = 0;
struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_section.start;
if (!d)
return B_ERROR;
for (int i = 0; d[i].d_tag != DT_NULL; i++) {
switch (d[i].d_tag) {
case DT_HASH:
// image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_STRTAB:
// image->strtab = (char *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_SYMTAB:
image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_REL:
image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_RELSZ:
image->rel_len = d[i].d_un.d_val;
break;
case DT_RELA:
image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_RELASZ:
image->rela_len = d[i].d_un.d_val;
break;
case DT_JMPREL:
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_PLTRELSZ:
image->pltrel_len = d[i].d_un.d_val;
break;
case DT_PLTREL:
image->pltrel_type = d[i].d_un.d_val;
break;
default:
continue;
}
}
// lets make sure we found all the required sections
// if (!image->symhash || !image->syms || !image->strtab)
if (/* !image->symhash ||*/ !image->syms /*|| !image->strtab*/)
return B_ERROR;
return B_OK;
}
static status_t
load_elf_symbol_table(int fd, preloaded_image *image)
{
@ -288,8 +352,10 @@ elf_load_image(int fd, preloaded_image *image)
memset((void *)(region->start + offset), 0, region->size - offset);
}
// modify the dynamic section by the delta of the regions
// offset dynamic section, and program entry addresses by the delta of the
// regions
image->dynamic_section.start += image->text_region.delta;
image->elf_header.e_entry += image->text_region.delta;
image->num_debug_symbols = 0;
image->debug_symbols = NULL;
@ -361,3 +427,69 @@ elf_load_image(Directory *directory, const char *path)
return status;
}
status_t
elf_relocate_image(struct preloaded_image *image)
{
status_t status = elf_parse_dynamic_section(image);
if (status != B_OK)
return status;
// deal with the rels first
if (image->rel) {
TRACE(("total %i relocs\n",
image->rel_len / (int)sizeof(struct Elf32_Rel)));
status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len);
if (status < B_OK)
return status;
}
if (image->pltrel) {
TRACE(("total %i plt-relocs\n",
image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
if (image->pltrel_type == DT_REL) {
status = boot_arch_elf_relocate_rel(image, image->pltrel,
image->pltrel_len);
} else {
status = boot_arch_elf_relocate_rela(image,
(struct Elf32_Rela *)image->pltrel, image->pltrel_len);
}
if (status < B_OK)
return status;
}
if (image->rela) {
status = boot_arch_elf_relocate_rela(image, image->rela,
image->rela_len);
if (status < B_OK)
return status;
}
return B_OK;
}
status_t
boot_elf_resolve_symbol(struct preloaded_image *image,
struct Elf32_Sym *symbol, addr_t *symbolAddress)
{
switch (symbol->st_shndx) {
case SHN_UNDEF:
// Since we do that only for the kernel, there shouldn't be
// undefined symbols.
return B_MISSING_SYMBOL;
case SHN_ABS:
*symbolAddress = symbol->st_value;
return B_NO_ERROR;
case SHN_COMMON:
// ToDo: finish this
TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
return B_ERROR;
default:
// standard symbol
*symbolAddress = symbol->st_value + image->text_region.delta;
return B_NO_ERROR;
}
}

View File

@ -13,4 +13,6 @@
extern status_t elf_load_image(Directory *directory, const char *path);
extern status_t elf_load_image(int fd, preloaded_image *image);
extern status_t elf_relocate_image(struct preloaded_image *image);
#endif /* LOADER_ELF_H */

View File

@ -65,7 +65,13 @@ load_kernel(stage2_args *args, Directory *volume)
close(fd);
if (status < B_OK) {
dprintf("loading kernel failed: %ld!\n", status);
dprintf("loading kernel failed: %lx!\n", status);
return status;
}
status = elf_relocate_image(&gKernelArgs.kernel_image);
if (status < B_OK) {
dprintf("relocating kernel failed: %lx!\n", status);
return status;
}

View File

@ -5,10 +5,10 @@
#include <SupportDefs.h>
#include <platform/openfirmware/openfirmware.h>
#include <util/kernel_cpp.h>
#include "Handle.h"
#include "openfirmware.h"
Handle::Handle(int handle, bool takeOwnership)

View File

@ -11,11 +11,12 @@ KernelMergeObject boot_platform_openfirmware.o :
menu.cpp
mmu.cpp
network.cpp
openfirmware.c
start.c
support.cpp
video.cpp
openfirmware.c
# generic
text_menu.cpp
:
@ -24,5 +25,7 @@ KernelMergeObject boot_platform_openfirmware.o :
SEARCH on [ FGristFiles text_menu.cpp ]
= [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
SEARCH on [ FGristFiles openfirmware.c ]
= [ FDirName $(HAIKU_TOP) src system kernel platform openfirmware ] ;
SubInclude HAIKU_TOP src system boot platform openfirmware arch ;

View File

@ -7,9 +7,10 @@ SubDirC++Flags -fno-rtti ;
KernelStaticLibrary boot_platform_openfirmware_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) ] ;

View File

@ -0,0 +1,44 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#define FUNCTION(x) .global x; .type x,@function; x
/* status_t arch_start_kernel(struct kernel_args *kernelArgs,
addr_t kernelEntry, addr_t kernelStackTop);
r3 - kernelArgs
r4 - kernelEntry
r5 - kernelStackTop
*/
FUNCTION(arch_start_kernel):
// push a stack frame
stwu %r1, -32(%r1)
mflr %r0
stw %r0, 36(%r1)
// save the old stack pointer in r29
stw %r29, 20(%r1)
mr %r29, %r1
// set up the kernel stack
subi %r1, %r5, 16
// enter the kernel
mtlr %r4
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

View File

@ -0,0 +1,71 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* 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/openfirmware.h>
#include "devices.h"
#define TRACE_CPU
#ifdef TRACE_CPU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
status_t
boot_arch_cpu_init(void)
{
// iterate through the "/cpus" node to find all CPUs
int cpus = of_finddevice("/cpus");
if (cpus == OF_FAILED) {
printf("arch_cpu_init(): Failed to open \"/cpus\"!\n");
return B_ERROR;
}
char cpuPath[256];
int cookie = 0;
int cpuCount = 0;
while (platform_get_next_device(&cookie, cpus, "cpu", cpuPath,
sizeof(cpuPath)) == B_OK) {
TRACE(("found CPU: %s\n", cpuPath));
cpuCount++;
}
if (cpuCount == 0) {
printf("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, B_READ_AREA | B_WRITE_AREA, false);
if (!stack) {
printf("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;
stack += KERNEL_STACK_SIZE;
}
return B_OK;
}

View File

@ -4,12 +4,11 @@
*/
#include "openfirmware.h"
#include <platform_arch.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>
@ -352,7 +351,6 @@ find_allocated_ranges(void *pageTable, page_table_entry_group **_physicalPageTab
for (int i = 0; i < length; i++) {
struct translation_map *map = &translations[i];
//printf("%i: map: %p, length %d -> physical: %p, mode %d\n", i, map->virtual_address, map->length, map->physical_address, map->mode);
printf("%i: map: %p, length %d -> physical: %p, mode %d\n", i, map->virtual_address, map->length, map->physical_address, map->mode);
// insert range in physical allocated, if it points to physical memory
@ -476,18 +474,19 @@ find_free_virtual_range(void *base, size_t size)
extern "C" void *
arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 protection,
arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 _protection,
bool exactAddress)
{
// we only know page sizes
size = ROUNDUP(size, B_PAGE_SIZE);
// set protection to WIMGxPP: -I--xPP
// set protection to WIMGNPP: -I---PP
// PP: 00 - no access
// 01 - read only
// 10 - read/write
// 11 - read only
if (protection & B_WRITE_AREA)
uint8 protection = 0;
if (_protection & B_WRITE_AREA)
protection = 0x22;
else
protection = 0x21;

View File

@ -6,11 +6,11 @@
#include <SupportDefs.h>
#include <string.h>
#include <platform/openfirmware/openfirmware.h>
#include <util/kernel_cpp.h>
#include "Handle.h"
#include "console.h"
#include "openfirmware.h"
class ConsoleHandle : public Handle {

View File

@ -6,10 +6,9 @@
#include <boot/platform.h>
#include <boot/stdio.h>
#include <platform/openfirmware/openfirmware.h>
#include <stdarg.h>
#include "openfirmware.h"
/** ToDo: this works only after console_init() was called.
* But it probably should do something before as well...

View File

@ -3,9 +3,8 @@
* Distributed under the terms of the MIT License.
*/
#include "devices.h"
#include "Handle.h"
#include "openfirmware.h"
#include "machine.h"
#include <boot/platform.h>
@ -14,6 +13,7 @@
#include <boot/stage2.h>
#include <boot/net/NetStack.h>
#include <boot/net/RemoteDisk.h>
#include <platform/openfirmware/openfirmware.h>
#include <util/kernel_cpp.h>
#include <string.h>
@ -23,21 +23,41 @@ char sBootPath[192];
/** Gets all device types of the specified type by doing a
* depth-first searchi of the OpenFirmware device tree.
* depth-first search of the OpenFirmware device tree.
* If a root != 0 is given, the function only traverses the subtree spanned
* by the root (inclusively). Otherwise the whole device tree is searched.
*
* The cookie has to be initialized to zero.
*/
static status_t
get_next_device(int *_cookie, const char *type, char *path, size_t pathSize)
status_t
platform_get_next_device(int *_cookie, int root, const char *type, char *path,
size_t pathSize)
{
int node = *_cookie;
if (node == 0)
node = of_peer(0);
while (true) {
int next = of_child(node);
int next;
if (node == 0) {
// node is NULL, meaning that this is the initial function call.
// If a root was supplied, we take that, otherwise the device tree
// root.
if (root != 0)
node = root;
else
node = of_peer(0);
if (node == OF_FAILED)
return B_ERROR;
if (node == 0)
return B_ENTRY_NOT_FOUND;
// We want to visit the root first.
next = node;
} else
next = of_child(node);
if (next == OF_FAILED)
return B_ERROR;
@ -55,7 +75,7 @@ get_next_device(int *_cookie, const char *type, char *path, size_t pathSize)
if (next == OF_FAILED)
return B_ERROR;
if (next == 0) {
if (next == root || next == 0) {
// We have searched the whole device tree
return B_ENTRY_NOT_FOUND;
}
@ -209,7 +229,8 @@ platform_add_block_devices(stage2_args *args, NodeList *devicesList)
int cookie = 0;
char path[256];
status_t status;
while ((status = get_next_device(&cookie, "block", path, sizeof(path))) == B_OK) {
while ((status = platform_get_next_device(&cookie, 0, "block", path,
sizeof(path))) == B_OK) {
if (!strcmp(path, sBootPath)) {
// don't add the boot device twice
continue;

View File

@ -0,0 +1,22 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef OPENFIRMWARE_DEVICES_H
#define OPENFIRMWARE_DEVICES_H
#include <SupportDefs.h>
#ifdef __cplusplus
extern "C" {
#endif
status_t platform_get_next_device(int *_cookie, int root, const char *type,
char *path, size_t pathSize);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OPENFIRMWARE_DEVICES_H */

View File

@ -8,7 +8,7 @@
#include <boot/platform.h>
#include <boot/heap.h>
#include <boot/stdio.h>
#include "openfirmware.h"
#include <platform/openfirmware/openfirmware.h>
#define TRACE_HEAP 1

View File

@ -7,10 +7,9 @@
#include <platform_arch.h>
#include <boot/platform.h>
#include <boot/stdio.h>
#include <platform/openfirmware/openfirmware.h>
#include <stdarg.h>
#include "openfirmware.h"
status_t
platform_allocate_region(void **_address, size_t size, uint8 protection,

View File

@ -13,8 +13,7 @@
#include <boot/net/Ethernet.h>
#include <boot/net/NetStack.h>
#include "openfirmware.h"
#include <platform/openfirmware/openfirmware.h>
//#define TRACE_NETWORK

View File

@ -8,11 +8,11 @@
#include <boot/platform.h>
#include <boot/stage2.h>
#include <boot/heap.h>
#include <platform/openfirmware/openfirmware.h>
#include <platform_arch.h>
#include <string.h>
#include "openfirmware.h"
#include "console.h"
#include "machine.h"
@ -81,8 +81,21 @@ determine_machine(void)
void
platform_start_kernel(void)
{
printf("kernel entry at %p\n", (void *)gKernelArgs.kernel_image.elf_header.e_entry);
of_exit();
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);
}
@ -130,11 +143,16 @@ start(void *openFirmwareEntry)
// 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();
arch_set_callback();
arch_mmu_init();
if (boot_arch_cpu_init() != B_OK)
platform_exit();
gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry;
main(&args);
// if everything wents fine, main() never returns
// if everything goes fine, main() never returns
of_exit();
}

View File

@ -5,7 +5,7 @@
#include <OS.h>
#include "openfirmware.h"
#include <platform/openfirmware/openfirmware.h>
bigtime_t
system_time(void)

View File

@ -37,7 +37,7 @@ KernelMergeObject kernel_core.o :
thread.c
timer.c
: -fno-pic
: $(TARGET_KERNEL_PIC_CCFLAGS)
;
# We need to specify the dependency on the generated syscalls files explicitly.
@ -63,6 +63,7 @@ KernelLd kernel_$(TARGET_ARCH) :
kernel_debug.o
lib$(TARGET_ARCH).a
lib$(TARGET_BOOT_PLATFORM).a
linkhack.so
@ -75,6 +76,7 @@ KernelLd kernel_$(TARGET_ARCH) :
: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/kernel.ld
: -Bdynamic -export-dynamic -dynamic-linker /foo/bar
$(TARGET_KERNEL_PIC_LINKFLAGS)
:
;
@ -90,6 +92,7 @@ KernelLd kernel.so :
kernel_debug.o
lib$(TARGET_ARCH).a
lib$(TARGET_BOOT_PLATFORM).a
linkhack.so
@ -102,6 +105,7 @@ KernelLd kernel.so :
: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/kernel.ld
: -Bdynamic -shared -export-dynamic -dynamic-linker /foo/bar
$(TARGET_KERNEL_PIC_LINKFLAGS)
;
NotFile kernel ;
@ -120,3 +124,7 @@ SubInclude HAIKU_TOP src system kernel lib ;
SubInclude HAIKU_TOP src system kernel messaging ;
SubInclude HAIKU_TOP src system kernel util ;
SubInclude HAIKU_TOP src system kernel vm ;
if $(TARGET_BOOT_PLATFORM) {
SubInclude HAIKU_TOP src system kernel platform $(TARGET_BOOT_PLATFORM) ;
}

View File

@ -20,5 +20,5 @@ KernelStaticLibrary libppc :
arch_vm_translation_map.cpp
arch_asm.S
:
-fno-pic -Wno-unused
;
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -11,10 +11,15 @@
#include <vm.h>
#include <boot/kernel_args.h>
#include <arch/debug_console.h>
#include <platform/openfirmware/openfirmware.h>
#include <string.h>
static int sInput = -1;
static int sOutput = -1;
char
arch_debug_blue_screen_getchar(void)
{
@ -22,7 +27,6 @@ arch_debug_blue_screen_getchar(void)
}
char
arch_debug_serial_getchar(void)
{
@ -33,6 +37,10 @@ arch_debug_serial_getchar(void)
void
arch_debug_serial_putchar(const char c)
{
if (c == '\n')
of_write(sOutput, "\r\n", 2);
else
of_write(sOutput, &c, 1);
}
@ -56,6 +64,11 @@ arch_debug_serial_early_boot_message(const char *string)
status_t
arch_debug_console_init(kernel_args *args)
{
if (of_getprop(gChosen, "stdin", &sInput, sizeof(int)) == OF_FAILED)
return B_ERROR;
if (of_getprop(gChosen, "stdout", &sOutput, sizeof(int)) == OF_FAILED)
return B_ERROR;
return B_OK;
}
@ -63,5 +76,6 @@ arch_debug_console_init(kernel_args *args)
status_t
arch_debug_console_init_settings(kernel_args *args)
{
return B_OK;
}

View File

@ -24,8 +24,8 @@ KernelStaticLibrary libx86 :
bios.cpp
cpuid.S
:
-fno-pic -Wno-unused
;
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;
# We need to specify the dependency on the generated syscalls file explicitly.
Includes [ FGristFiles arch_x86.S arch_interrupts.S ]

View File

@ -6,5 +6,5 @@ KernelMergeObject kernel_cache.o :
file_cache.cpp
vnode_store.cpp
: -fno-pic -Wno-unused
;
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -9,5 +9,5 @@ KernelMergeObject kernel_debug.o :
gdb.c
user_debugger.cpp
: -fno-pic -Wno-unused
;
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -18,5 +18,5 @@ KernelMergeObject kernel_device_manager.o :
scan.c
settings.cpp
:
-fno-pic -Wno-unused
;
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -52,7 +52,7 @@ KernelMergeObject kernel_disk_device_manager.o :
# disk device types
DiskDeviceTypes.cpp
: -fno-pic -Wno-unused
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;
# KFileDiskDevice.cpp needs the virtualdrive.h Header. Add it here to not

View File

@ -18,5 +18,5 @@ KernelMergeObject kernel_fs.o :
IOScheduler.cpp
KPath.cpp
: -fno-pic -Wno-unused
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -5,7 +5,7 @@ SubDir HAIKU_TOP src system kernel lib ;
KernelMergeObject kernel_os_main.o :
driver_settings.c
fs_info.c
: -fno-pic
: $(TARGET_KERNEL_PIC_CCFLAGS)
;
SEARCH on [ FGristFiles driver_settings.c fs_info.c ]
@ -103,7 +103,7 @@ KernelMergeObject kernel_posix.o :
strstr.c
strtok.c
: -fno-pic
: $(TARGET_KERNEL_PIC_CCFLAGS)
;
SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ;
@ -113,5 +113,5 @@ KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o :
byteorder.S
system_time.S
: -fno-pic
: $(TARGET_KERNEL_PIC_CCFLAGS)
;

View File

@ -24,6 +24,7 @@
#include <kscheduler.h>
#include <ksyscalls.h>
#include <messaging.h>
#include <platform.h>
#include <port.h>
#include <real_time_clock.h>
#include <sem.h>
@ -80,6 +81,9 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
if (smp_trap_non_boot_cpus(currentCPU)) {
thread_id thread;
// init platform
platform_init(&sKernelArgs);
// setup debug output
debug_init(&sKernelArgs);
set_dprintf_enabled(true);

View File

@ -12,5 +12,5 @@ KernelMergeObject kernel_messaging.o :
KMessage.cpp
MessagingService.cpp
: -fno-pic -Wno-unused
;
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;

View File

@ -0,0 +1,8 @@
SubDir HAIKU_TOP src system kernel platform bios_ia32 ;
SubDirCcFlags $(TARGET_KERNEL_PIC_CCFLAGS) ;
SubDirC++Flags $(TARGET_KERNEL_PIC_CCFLAGS) ;
KernelStaticLibrary libbios_ia32.a :
platform.cpp
;

View File

@ -0,0 +1,14 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <platform.h>
#include <boot/kernel_args.h>
status_t
platform_init(struct kernel_args *kernelArgs)
{
return B_OK;
}

View File

@ -0,0 +1,9 @@
SubDir HAIKU_TOP src system kernel platform openfirmware ;
SubDirCcFlags $(TARGET_KERNEL_PIC_CCFLAGS) ;
SubDirC++Flags $(TARGET_KERNEL_PIC_CCFLAGS) ;
KernelStaticLibrary libopenfirmware.a :
openfirmware.c
platform.cpp
;

View File

@ -3,8 +3,8 @@
* Distributed under the terms of the MIT License.
*/
#include <platform/openfirmware/openfirmware.h>
#include "openfirmware.h"
#include <stdarg.h>

View File

@ -0,0 +1,16 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <platform.h>
#include <boot/kernel_args.h>
#include <platform/openfirmware/openfirmware.h>
status_t
platform_init(struct kernel_args *kernelArgs)
{
return of_init(
(int(*)(void*))kernelArgs->platform_args.openfirmware_entry);
}

View File

@ -10,5 +10,5 @@ KernelMergeObject kernel_util.o :
queue.c
ring_buffer.cpp
: -fno-pic -Wno-unused -DUSING_LIBGCC
;
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused -DUSING_LIBGCC
;

View File

@ -12,5 +12,5 @@ KernelMergeObject kernel_vm.o :
vm_store_null.c
#vm_tests.c
: -fno-pic -Wno-unused
;
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
;