[haiku-commits] BRANCH xyzzy-github.x86_64 - src/system/boot/loader src/system/boot/platform/bios_ia32 headers/private/kernel/boot src/system/kernel/arch/x86_64 src/system/boot/platform/openfirmware

  • From: xyzzy-github.x86_64 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 25 Jun 2012 00:48:54 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64'
old head: f6a3444449c452a63e0e0d91e8480f39bca81aed
new head: 8846189866301c85683151a54ec88e809333ca7a

----------------------------------------------------------------------------

8846189: Handle 64-bit load addresses for ELF64 images in the bootloader.
  
  The ELF loader now uses a new platform function, platform_allocate_elf_region,
  which returns 2 addresses: the real load address and an address where the
  region is mapped in the loader's address space. All of the ELF loading code
  has been changed to access the load region through the mapped address rather
  than the addresses contained in the ELF image. The ELF64 version of
  platform_allocate_elf_region on x86 uses the existing MMU code, which maps
  everything at 0x80000000, but returns the correct 64-bit address. The long
  mode switch code will just set up the 64-bit address space with everything
  remapped at the correct address.

                                      [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      8846189866301c85683151a54ec88e809333ca7a

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Sun Jun 24 21:57:48 2012 UTC

----------------------------------------------------------------------------

13 files changed, 243 insertions(+), 40 deletions(-)
headers/private/kernel/boot/elf.h                  |   22 ++++-
headers/private/kernel/boot/platform.h             |    7 ++
src/system/boot/arch/x86_64/Jamfile                |   10 +-
src/system/boot/loader/elf.cpp                     |   81 +++++++++++-----
src/system/boot/platform/amiga_m68k/mmu.cpp        |   14 +++
src/system/boot/platform/atari_m68k/mmu.cpp        |   14 +++
src/system/boot/platform/bios_ia32/mmu.cpp         |   37 +++++++
src/system/boot/platform/cfe/mmu.cpp               |   18 ++++
src/system/boot/platform/openfirmware/mmu.cpp      |   18 ++++
src/system/boot/platform/raspberrypi_arm/mmu.cpp   |   14 +++
.../boot/platform/routerboard_mipsel/mmu.cpp       |    9 ++
src/system/boot/platform/u-boot/mmu.cpp            |   18 ++++
src/system/kernel/arch/x86_64/arch_elf.cpp         |   21 ++--

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/boot/elf.h 
b/headers/private/kernel/boot/elf.h
index 88514d9..46bbfc1 100644
--- a/headers/private/kernel/boot/elf.h
+++ b/headers/private/kernel/boot/elf.h
@@ -1,7 +1,7 @@
 /*
  * Copyright 2003-2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights 
reserved.
  * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
- * Distributed under the terms of the OpenBeOS License.
+ * Distributed under the terms of the MIT License.
  */
 #ifndef KERNEL_BOOT_ELF_H
 #define KERNEL_BOOT_ELF_H
@@ -44,9 +44,10 @@ struct preloaded_image {
 } _PACKED;
 
 struct preloaded_elf32_image : public preloaded_image {
-       Elf32_Ehdr elf_header;
+       Elf32_Ehdr      elf_header;
        elf32_region text_region;
        elf32_region data_region;
+       uint32          mapped_delta;
 
        FixedWidthPointer<Elf32_Sym> syms;
        FixedWidthPointer<Elf32_Rel> rel;
@@ -61,9 +62,10 @@ struct preloaded_elf32_image : public preloaded_image {
 } _PACKED;
 
 struct preloaded_elf64_image : public preloaded_image {
-       Elf64_Ehdr elf_header;
+       Elf64_Ehdr      elf_header;
        elf64_region text_region;
        elf64_region data_region;
+       uint64          mapped_delta;
 
        FixedWidthPointer<Elf64_Sym> syms;
        FixedWidthPointer<Elf64_Rel> rel;
@@ -77,11 +79,23 @@ struct preloaded_elf64_image : public preloaded_image {
        FixedWidthPointer<Elf64_Sym> debug_symbols;
 } _PACKED;
 
-
+#ifdef _BOOT_MODE
 extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image,
        struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress);
 extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image,
        struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress);
 
 
+// Helper method to set a relocation at the mapped address in the loader's
+// address space.
+template<typename ImageType, typename AddrType>
+inline void
+boot_elf_set_relocation(ImageType* image, AddrType resolveAddress,
+       AddrType finalAddress)
+{
+       AddrType* dest = (AddrType*)(addr_t)(resolveAddress + 
image->mapped_delta);
+       *dest = finalAddress;
+}
+#endif
+
 #endif /* KERNEL_BOOT_ELF_H */
diff --git a/headers/private/kernel/boot/platform.h 
b/headers/private/kernel/boot/platform.h
index 9f3c8eb..c251488 100644
--- a/headers/private/kernel/boot/platform.h
+++ b/headers/private/kernel/boot/platform.h
@@ -72,6 +72,13 @@ extern size_t platform_get_user_input_text(Menu *menu, 
MenuItem *item,
        char *buffer, size_t bufferSize);
 extern char* platform_debug_get_log_buffer(size_t* _size);
 
+/* ELF functions */
+
+extern status_t platform_allocate_elf_region(uint32 *_address, uint32 size,
+       uint8 protection, void **_mappedAddress);
+extern status_t platform_allocate_elf_region(uint64 *_address, uint64 size,
+       uint8 protection, void **_mappedAddress);
+
 #endif
 
 #endif /* KERNEL_BOOT_PLATFORM_H */
diff --git a/src/system/boot/arch/x86_64/Jamfile 
b/src/system/boot/arch/x86_64/Jamfile
index 3dd0418..f81c3f1 100644
--- a/src/system/boot/arch/x86_64/Jamfile
+++ b/src/system/boot/arch/x86_64/Jamfile
@@ -2,6 +2,10 @@ SubDir HAIKU_TOP src system boot arch x86_64 ;
 
 DEFINES += _BOOT_MODE ;
 
+local bootArchSources =
+       arch_elf64.cpp
+;
+
 local kernelArchSources =
        arch_elf.cpp
        cpuid.S
@@ -16,18 +20,18 @@ local librootOsArchSources =
 ;
 
 BootMergeObject boot_arch_$(TARGET_ARCH).o :
-       arch_elf64.cpp
+       $(bootArchSources)
        $(kernelArchSources)
        $(kernelLibArchSources)
        $(librootOsArchSources)
        : # additional flags
 ;
 
+SEARCH on [ FGristFiles $(bootArchSources) ]
+    = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ;
 SEARCH on [ FGristFiles $(kernelArchSources) ]
     = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ;
 SEARCH on [ FGristFiles $(kernelLibArchSources) ]
     = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ;
 SEARCH on [ FGristFiles $(librootOsArchSources) ]
     = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ;
-SEARCH on [ FGristFiles $(kernelArchSources) ]
-    = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ;
diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp
index 1e1d7a4..cf780c3 100644
--- a/src/system/boot/loader/elf.cpp
+++ b/src/system/boot/loader/elf.cpp
@@ -38,6 +38,7 @@ class ELFLoader {
 private:
        typedef typename Class::ImageType       ImageType;
        typedef typename Class::RegionType      RegionType;
+       typedef typename Class::AddrType        AddrType;
        typedef typename Class::EhdrType        EhdrType;
        typedef typename Class::PhdrType        PhdrType;
        typedef typename Class::ShdrType        ShdrType;
@@ -53,7 +54,7 @@ public:
 
 private:
        static  status_t        _LoadSymbolTable(int fd, ImageType* image);
-       static  status_t        _ParseDynamicSection(ImageType* image);
+       static  status_t        _ParseDynamicSection(ImageType* image, AddrType 
delta);
 };
 
 
@@ -62,6 +63,7 @@ struct ELF32Class {
 
        typedef preloaded_elf32_image   ImageType;
        typedef elf32_region                    RegionType;
+       typedef Elf32_Addr                              AddrType;
        typedef Elf32_Ehdr                              EhdrType;
        typedef Elf32_Phdr                              PhdrType;
        typedef Elf32_Shdr                              ShdrType;
@@ -80,6 +82,7 @@ struct ELF64Class {
 
        typedef preloaded_elf64_image   ImageType;
        typedef elf64_region                    RegionType;
+       typedef Elf64_Addr                              AddrType;
        typedef Elf64_Ehdr                              EhdrType;
        typedef Elf64_Phdr                              PhdrType;
        typedef Elf64_Shdr                              ShdrType;
@@ -132,6 +135,7 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
        size_t totalSize;
        ssize_t length;
        status_t status;
+       void* mappedRegion = NULL;
 
        ImageType* image = static_cast<ImageType*>(_image);
        EhdrType& elfHeader = image->elf_header;
@@ -196,8 +200,9 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
                        B_PAGE_SIZE);
                region->delta = -region->start;
 
-               TRACE(("segment %ld: start = 0x%lx, size = %lu, delta = %lx\n", 
i,
-                       region->start, region->size, region->delta));
+               TRACE(("segment %ld: start = 0x%llx, size = %llu, delta = 
%llx\n", i,
+                       (uint64)region->start, (uint64)region->size,
+                       (int64)(AddrType)region->delta));
        }
 
        // found both, text and data?
@@ -228,10 +233,10 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
        }
 
        // The kernel and the modules are relocatable, thus
-       // platform_allocate_region() can automatically allocate an address,
+       // platform_allocate_elf_region() can automatically allocate an address,
        // but shall prefer the specified base address.
-       if (platform_allocate_region((void **)&firstRegion->start, totalSize,
-                       B_READ_AREA | B_WRITE_AREA, false) < B_OK) {
+       if (platform_allocate_elf_region(&firstRegion->start, totalSize,
+                       B_READ_AREA | B_WRITE_AREA, &mappedRegion) < B_OK) {
                status = B_NO_MEMORY;
                goto error1;
        }
@@ -242,6 +247,16 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
        image->data_region.delta += image->data_region.start;
        image->text_region.delta += image->text_region.start;
 
+       TRACE(("text: start 0x%llx, size 0x%llx, delta 0x%llx\n",
+               (uint64)image->text_region.start, 
(uint64)image->text_region.size,
+               (int64)(AddrType)image->text_region.delta));
+       TRACE(("data: start 0x%llx, size 0x%llx, delta 0x%llx\n",
+               (uint64)image->data_region.start, 
(uint64)image->data_region.size,
+               (int64)(AddrType)image->data_region.delta));
+
+       // Calculate the delta from a real load address to the mapped address
+       image->mapped_delta = (AddrType)(addr_t)mappedRegion - 
firstRegion->start;
+
        // load program data
 
        for (int32 i = 0; i < elfHeader.e_phnum; i++) {
@@ -258,10 +273,14 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
                else
                        continue;
 
-               TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz));
+               // Calculate where to load the data to.
+               addr_t dest = region->start + image->mapped_delta;
+
+               TRACE(("load segment %ld (%llu bytes) mapped at 0x%lx...\n", i,
+                       (uint64)header.p_filesz, dest));
 
                length = read_pos(fd, header.p_offset,
-                       (void*)(region->start + (header.p_vaddr % B_PAGE_SIZE)),
+                       (void*)(dest + (header.p_vaddr % B_PAGE_SIZE)),
                        header.p_filesz);
                if (length < (ssize_t)header.p_filesz) {
                        status = B_BAD_DATA;
@@ -274,7 +293,7 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
 
                uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + 
header.p_filesz;
                if (offset < region->size)
-                       memset((void*)(region->start + offset), 0, region->size 
- offset);
+                       memset((void*)(dest + offset), 0, region->size - 
offset);
        }
 
        // offset dynamic section, and program entry addresses by the delta of 
the
@@ -294,8 +313,8 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
        return B_OK;
 
 error2:
-       if (image->text_region.start != 0)
-               platform_free_region((void*)image->text_region.start, 
totalSize);
+       if (mappedRegion != NULL)
+               platform_free_region(mappedRegion, totalSize);
 error1:
        free(programHeaders);
        kernel_args_free(image);
@@ -310,13 +329,16 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
 {
        ImageType* image = static_cast<ImageType*>(_image);
 
-       status_t status = _ParseDynamicSection(image);
+       // Pull information out of the dynamic section. First pass through we 
set
+       // the addresses we want in our address space.
+       status_t status = _ParseDynamicSection(image, image->mapped_delta);
        if (status != B_OK)
                return status;
 
        // deal with the rels first
        if (image->rel) {
-               TRACE(("total %i relocs\n", image->rel_len / 
(int)sizeof(RelType)));
+               TRACE(("total %i relocs\n",
+                       (int)image->rel_len / (int)sizeof(RelType)));
 
                status = boot_arch_elf_relocate_rel(image, image->rel, 
image->rel_len);
                if (status < B_OK)
@@ -324,15 +346,18 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
        }
 
        if (image->pltrel) {
-               TRACE(("total %i plt-relocs\n",
-                       image->pltrel_len / (int)sizeof(RelType)));
-
                RelType* pltrel = image->pltrel;
                if (image->pltrel_type == DT_REL) {
+                       TRACE(("total %i plt-relocs\n",
+                               (int)image->pltrel_len / (int)sizeof(RelType)));
+
                        status = boot_arch_elf_relocate_rel(image, pltrel,
                                image->pltrel_len);
                } else {
-                       status = boot_arch_elf_relocate_rela(image, (RelaType 
*)pltrel,
+                       TRACE(("total %i plt-relocs\n",
+                               (int)image->pltrel_len / 
(int)sizeof(RelaType)));
+
+                       status = boot_arch_elf_relocate_rela(image, 
(RelaType*)pltrel,
                                image->pltrel_len);
                }
                if (status < B_OK)
@@ -341,13 +366,17 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
 
        if (image->rela) {
                TRACE(("total %i rela relocs\n",
-                       image->rela_len / (int)sizeof(RelaType)));
+                       (int)image->rela_len / (int)sizeof(RelaType)));
                status = boot_arch_elf_relocate_rela(image, image->rela,
                        image->rela_len);
                if (status < B_OK)
                        return status;
        }
 
+       // Make a second pass through the dynamic section, storing the correct
+       // virtual addresses for the kernel.
+       _ParseDynamicSection(image, 0);
+
        return B_OK;
 }
 
@@ -458,7 +487,7 @@ error1:
 
 template<typename Class>
 /*static*/ status_t
-ELFLoader<Class>::_ParseDynamicSection(ImageType* image)
+ELFLoader<Class>::_ParseDynamicSection(ImageType* image, AddrType delta)
 {
        image->syms = 0;
        image->rel = 0;
@@ -469,10 +498,12 @@ ELFLoader<Class>::_ParseDynamicSection(ImageType* image)
        image->pltrel_len = 0;
        image->pltrel_type = 0;
 
-       DynType* d = (DynType*)image->dynamic_section.start;
-       if (!d)
+       if(image->dynamic_section.start == 0)
                return B_ERROR;
 
+       DynType* d = (DynType*)(addr_t)(image->dynamic_section.start
+               + image->mapped_delta);
+
        for (int i = 0; d[i].d_tag != DT_NULL; i++) {
                switch (d[i].d_tag) {
                        case DT_HASH:
@@ -480,25 +511,25 @@ ELFLoader<Class>::_ParseDynamicSection(ImageType* image)
                                break;
                        case DT_SYMTAB:
                                image->syms = (SymType*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
+                                       + image->text_region.delta + delta);
                                break;
                        case DT_REL:
                                image->rel = (RelType*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
+                                       + image->text_region.delta + delta);
                                break;
                        case DT_RELSZ:
                                image->rel_len = d[i].d_un.d_val;
                                break;
                        case DT_RELA:
                                image->rela = (RelaType*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
+                                       + image->text_region.delta + delta);
                                break;
                        case DT_RELASZ:
                                image->rela_len = d[i].d_un.d_val;
                                break;
                        case DT_JMPREL:
                                image->pltrel = (RelType*)(d[i].d_un.d_ptr
-                                       + image->text_region.delta);
+                                       + image->text_region.delta  + delta);
                                break;
                        case DT_PLTRELSZ:
                                image->pltrel_len = d[i].d_un.d_val;
diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp 
b/src/system/boot/platform/amiga_m68k/mmu.cpp
index 03f56b9..040c34a 100644
--- a/src/system/boot/platform/amiga_m68k/mmu.cpp
+++ b/src/system/boot/platform/amiga_m68k/mmu.cpp
@@ -662,6 +662,20 @@ platform_free_region(void *address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       void *address = mmu_allocate((void *)*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
+
 void
 platform_release_heap(struct stage2_args *args, void *base)
 {
diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp 
b/src/system/boot/platform/atari_m68k/mmu.cpp
index 7132119..77759cd 100644
--- a/src/system/boot/platform/atari_m68k/mmu.cpp
+++ b/src/system/boot/platform/atari_m68k/mmu.cpp
@@ -666,6 +666,20 @@ platform_free_region(void *address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       void *address = mmu_allocate((void *)*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
+
 void
 platform_release_heap(struct stage2_args *args, void *base)
 {
diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp 
b/src/system/boot/platform/bios_ia32/mmu.cpp
index cfed3de..344abf7 100644
--- a/src/system/boot/platform/bios_ia32/mmu.cpp
+++ b/src/system/boot/platform/bios_ia32/mmu.cpp
@@ -769,6 +769,43 @@ platform_free_region(void *address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       void *address = mmu_allocate((void *)*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
+
+status_t
+platform_allocate_elf_region(uint64 *_address, uint64 size, uint8 protection,
+       void **_mappedAddress)
+{
+       // The 64-bit kernel is loaded to 0xFFFFFFFF80000000. You'll notice that
+       // the low 32 bits of this address are the same as the 32-bit 
KERNEL_BASE
+       // (0x80000000). Therefore, the way this function is implemented is to 
use
+       // mmu_allocate() and then set the upper 32 bits to all 1s. The long 
mode
+       // switch code will remap everything to the correct addresses.
+
+       void *address = mmu_allocate((void *)(addr_t)(*_address & 0xFFFFFFFF), 
size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       // This is the address that the ELF loading code will access the mapping
+       // through.
+       *_mappedAddress = address;
+
+       *_address = (uint64)(uint32)address | 0xFFFFFFFF00000000LL;
+       return B_OK;
+}
+
+
 void
 platform_release_heap(struct stage2_args *args, void *base)
 {
diff --git a/src/system/boot/platform/cfe/mmu.cpp 
b/src/system/boot/platform/cfe/mmu.cpp
index b9f3143..e33ebe7 100644
--- a/src/system/boot/platform/cfe/mmu.cpp
+++ b/src/system/boot/platform/cfe/mmu.cpp
@@ -34,3 +34,21 @@ platform_free_region(void *address, size_t size)
        return arch_mmu_free(address, size);
 }
 
+
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       if (size == 0)
+               return B_BAD_VALUE;
+
+       void *address = arch_mmu_allocate((void *)*_address, size, protection,
+               exactAddress);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
diff --git a/src/system/boot/platform/openfirmware/mmu.cpp 
b/src/system/boot/platform/openfirmware/mmu.cpp
index b765e8d..f284dae 100644
--- a/src/system/boot/platform/openfirmware/mmu.cpp
+++ b/src/system/boot/platform/openfirmware/mmu.cpp
@@ -34,3 +34,21 @@ platform_free_region(void *address, size_t size)
        return arch_mmu_free(address, size);
 }
 
+
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       if (size == 0)
+               return B_BAD_VALUE;
+
+       void *address = arch_mmu_allocate((void *)*_address, size, protection,
+               exactAddress);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.cpp 
b/src/system/boot/platform/raspberrypi_arm/mmu.cpp
index 18c39f5..3b52275 100644
--- a/src/system/boot/platform/raspberrypi_arm/mmu.cpp
+++ b/src/system/boot/platform/raspberrypi_arm/mmu.cpp
@@ -678,6 +678,20 @@ platform_free_region(void *address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+       void *address = mmu_allocate((void *)*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+}
+
+
 void
 platform_release_heap(struct stage2_args *args, void *base)
 {
diff --git a/src/system/boot/platform/routerboard_mipsel/mmu.cpp 
b/src/system/boot/platform/routerboard_mipsel/mmu.cpp
index cb46119..744cac4 100644
--- a/src/system/boot/platform/routerboard_mipsel/mmu.cpp
+++ b/src/system/boot/platform/routerboard_mipsel/mmu.cpp
@@ -79,6 +79,15 @@ platform_free_region(void* address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+#warning IMPLEMENT platform_allocate_elf_region
+       return B_ERROR;
+}
+
+
 void
 platform_release_heap(struct stage2_args* args, void* base)
 {
diff --git a/src/system/boot/platform/u-boot/mmu.cpp 
b/src/system/boot/platform/u-boot/mmu.cpp
index e38d931..a1d001c 100644
--- a/src/system/boot/platform/u-boot/mmu.cpp
+++ b/src/system/boot/platform/u-boot/mmu.cpp
@@ -681,6 +681,24 @@ platform_free_region(void *address, size_t size)
 }
 
 
+status_t
+platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection,
+       void **_mappedAddress)
+{
+#ifdef __ARM__
+       void *address = mmu_allocate((void *)*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = (uint32)address;
+       *_mappedAddress = address;
+       return B_OK;
+#else
+       return B_ERROR;
+#endif
+}
+
+
 void
 platform_release_heap(struct stage2_args *args, void *base)
 {
diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp 
b/src/system/kernel/arch/x86_64/arch_elf.cpp
index b0cbe9d..09d2f34 100644
--- a/src/system/kernel/arch/x86_64/arch_elf.cpp
+++ b/src/system/kernel/arch/x86_64/arch_elf.cpp
@@ -136,31 +136,36 @@ boot_arch_elf_relocate_rela(preloaded_elf64_image* image, 
Elf64_Rela* rel,
                }
 
                // Address of the relocation.
-               Elf64_Addr* resolveAddr = (Elf64_Addr 
*)(image->text_region.delta
-                       + rel[i].r_offset);
+               Elf64_Addr relocAddr = image->text_region.delta + 
rel[i].r_offset;
 
-               // Perform the relocation.
+               // Calculate the relocation value.
+               Elf64_Addr relocValue;
                switch(type) {
                        case R_X86_64_NONE:
-                               break;
+                               continue;
                        case R_X86_64_64:
-                               *resolveAddr = symAddr + rel[i].r_addend;
+                               relocValue = symAddr + rel[i].r_addend;
                                break;
                        case R_X86_64_PC32:
-                               *resolveAddr = symAddr + rel[i].r_addend - 
rel[i].r_offset;
+                               relocValue = symAddr + rel[i].r_addend - 
rel[i].r_offset;
                                break;
                        case R_X86_64_GLOB_DAT:
                        case R_X86_64_JUMP_SLOT:
-                               *resolveAddr = symAddr + rel[i].r_addend;
+                               relocValue = symAddr + rel[i].r_addend;
                                break;
                        case R_X86_64_RELATIVE:
-                               *resolveAddr = image->text_region.delta + 
rel[i].r_addend;
+                               relocValue = image->text_region.delta + 
rel[i].r_addend;
                                break;
                        default:
                                dprintf("arch_elf_relocate_rel: unhandled 
relocation type %d\n",
                                        type);
                                return B_BAD_DATA;
                }
+#ifdef _BOOT_MODE
+               boot_elf_set_relocation(image, relocAddr, relocValue);
+#else
+               *(Elf64_Addr *)relocAddr = relocValue;
+#endif
        }
 
        return B_OK;


Other related posts: