Updated ELF loader to use preloaded_image struct for the kernel.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7712 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -60,8 +60,8 @@ static uint32 *pgtable = 0;
|
|||||||
// function decls for this module
|
// function decls for this module
|
||||||
static void sort_addr_range(addr_range *range, int count);
|
static void sort_addr_range(addr_range *range, int count);
|
||||||
static void calculate_cpu_conversion_factor(void);
|
static void calculate_cpu_conversion_factor(void);
|
||||||
static void load_elf_image(void *data, uint32 *next_paddr, addr_range *ar0,
|
static void load_elf_image(void *data, uint32 *next_paddr, struct preloaded_image *image,
|
||||||
addr_range *ar1, uint32 *start_addr, addr_range *dynamic_section);
|
uint32 *start_addr);
|
||||||
static int mmu_init(kernel_args *ka, uint32 *next_paddr);
|
static int mmu_init(kernel_args *ka, uint32 *next_paddr);
|
||||||
static void mmu_map_page(uint32 vaddr, uint32 paddr);
|
static void mmu_map_page(uint32 vaddr, uint32 paddr);
|
||||||
static int check_cpu(void);
|
static int check_cpu(void);
|
||||||
@@ -157,12 +157,15 @@ _start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
|||||||
|
|
||||||
// load the kernel (3rd entry in the bootdir)
|
// load the kernel (3rd entry in the bootdir)
|
||||||
load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR_ADDR), &next_paddr,
|
load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR_ADDR), &next_paddr,
|
||||||
&ka->kernel_seg0_addr, &ka->kernel_seg1_addr, &kernel_entry, &ka->kernel_dynamic_section_addr);
|
&ka->kernel_image, &kernel_entry);
|
||||||
|
|
||||||
if (ka->kernel_seg1_addr.size > 0)
|
if (ka->kernel_image.data_region.size > 0) {
|
||||||
next_vaddr = ROUNDUP(ka->kernel_seg1_addr.start + ka->kernel_seg1_addr.size, PAGE_SIZE);
|
next_vaddr = ROUNDUP(ka->kernel_image.data_region.start
|
||||||
else
|
+ ka->kernel_image.data_region.size, PAGE_SIZE);
|
||||||
next_vaddr = ROUNDUP(ka->kernel_seg0_addr.start + ka->kernel_seg0_addr.size, PAGE_SIZE);
|
} else {
|
||||||
|
next_vaddr = ROUNDUP(ka->kernel_image.text_region.start
|
||||||
|
+ ka->kernel_image.text_region.size, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
// map in a kernel stack
|
// map in a kernel stack
|
||||||
ka->cpu_kstack[0].start = next_vaddr;
|
ka->cpu_kstack[0].start = next_vaddr;
|
||||||
@@ -388,28 +391,29 @@ _start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_elf_image(void *data, uint32 *next_paddr, addr_range *ar0, addr_range *ar1,
|
load_elf_image(void *data, uint32 *next_paddr, struct preloaded_image *image,
|
||||||
uint32 *start_addr, addr_range *dynamic_section)
|
uint32 *start_addr)
|
||||||
{
|
{
|
||||||
struct Elf32_Ehdr *imageHeader = (struct Elf32_Ehdr*) data;
|
struct Elf32_Ehdr *imageHeader = (struct Elf32_Ehdr *)data;
|
||||||
struct Elf32_Phdr *segments = (struct Elf32_Phdr*)(imageHeader->e_phoff + (unsigned) imageHeader);
|
struct Elf32_Phdr *segments = (struct Elf32_Phdr *)(imageHeader->e_phoff + (unsigned) imageHeader);
|
||||||
int segmentIndex;
|
int segmentIndex;
|
||||||
int foundSegmentIndex = 0;
|
int foundSegmentIndex = 0;
|
||||||
|
|
||||||
ar0->size = 0;
|
memset(image, 0, sizeof(struct preloaded_image));
|
||||||
ar1->size = 0;
|
memcpy(&image->elf_header, imageHeader, sizeof(struct Elf32_Ehdr));
|
||||||
dynamic_section->size = 0;
|
|
||||||
|
|
||||||
for (segmentIndex = 0; segmentIndex < imageHeader->e_phnum; segmentIndex++) {
|
for (segmentIndex = 0; segmentIndex < imageHeader->e_phnum; segmentIndex++) {
|
||||||
struct Elf32_Phdr *segment = &segments[segmentIndex];
|
struct Elf32_Phdr *segment = &segments[segmentIndex];
|
||||||
|
struct elf_region *region;
|
||||||
|
uint32 size, virtualAddress;
|
||||||
uint32 segmentOffset;
|
uint32 segmentOffset;
|
||||||
|
|
||||||
switch (segment->p_type) {
|
switch (segment->p_type) {
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
break;
|
break;
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
dynamic_section->start = segment->p_vaddr;
|
image->dynamic_section.start = segment->p_vaddr;
|
||||||
dynamic_section->size = segment->p_memsz;
|
image->dynamic_section.size = segment->p_memsz;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -418,46 +422,54 @@ load_elf_image(void *data, uint32 *next_paddr, addr_range *ar0, addr_range *ar1,
|
|||||||
PRINT(("p_vaddr 0x%x p_paddr 0x%x p_filesz 0x%x p_memsz 0x%x\n",
|
PRINT(("p_vaddr 0x%x p_paddr 0x%x p_filesz 0x%x p_memsz 0x%x\n",
|
||||||
segment->p_vaddr, segment->p_paddr, segment->p_filesz, segment->p_memsz));
|
segment->p_vaddr, segment->p_paddr, segment->p_filesz, segment->p_memsz));
|
||||||
|
|
||||||
/* Map initialized portion */
|
size = ROUNDUP(segment->p_filesz, PAGE_SIZE);
|
||||||
for (segmentOffset = 0;
|
virtualAddress = ROUNDOWN(segment->p_vaddr, PAGE_SIZE);
|
||||||
segmentOffset < ROUNDUP(segment->p_filesz, PAGE_SIZE);
|
|
||||||
segmentOffset += PAGE_SIZE) {
|
|
||||||
|
|
||||||
mmu_map_page(segment->p_vaddr + segmentOffset, *next_paddr);
|
/* Map initialized portion */
|
||||||
memcpy((void *)ROUNDOWN(segment->p_vaddr + segmentOffset, PAGE_SIZE),
|
for (segmentOffset = 0; segmentOffset < size; segmentOffset += PAGE_SIZE) {
|
||||||
(void *)ROUNDOWN((unsigned)data + segment->p_offset + segmentOffset, PAGE_SIZE), PAGE_SIZE);
|
mmu_map_page(virtualAddress + segmentOffset, *next_paddr);
|
||||||
|
memcpy((void *)(virtualAddress + segmentOffset),
|
||||||
|
(void *)ROUNDOWN((uint32)data + segment->p_offset + segmentOffset, PAGE_SIZE),
|
||||||
|
PAGE_SIZE);
|
||||||
(*next_paddr) += PAGE_SIZE;
|
(*next_paddr) += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean out the leftover part of the last page */
|
/* Clean out the leftover part of the last page */
|
||||||
if (segment->p_filesz % PAGE_SIZE > 0) {
|
if (segment->p_filesz % PAGE_SIZE > 0) {
|
||||||
PRINT(("memsetting 0 to va 0x%x, size %d\n", (void*)((unsigned)segment->p_vaddr + segment->p_filesz), PAGE_SIZE - (segment->p_filesz % PAGE_SIZE)));
|
PRINT(("memsetting 0 to va 0x%x, size %d\n", (void *)((unsigned)segment->p_vaddr + segment->p_filesz), PAGE_SIZE - (segment->p_filesz % PAGE_SIZE)));
|
||||||
memset((void*)((unsigned)segment->p_vaddr + segment->p_filesz), 0, PAGE_SIZE
|
memset((void *)((unsigned)segment->p_vaddr + segment->p_filesz), 0, PAGE_SIZE
|
||||||
- (segment->p_filesz % PAGE_SIZE));
|
- (segment->p_filesz % PAGE_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = ROUNDUP(segment->p_memsz, PAGE_SIZE);
|
||||||
|
|
||||||
/* Map uninitialized portion */
|
/* Map uninitialized portion */
|
||||||
for (; segmentOffset < ROUNDUP(segment->p_memsz, PAGE_SIZE); segmentOffset += PAGE_SIZE) {
|
for (; segmentOffset < size; segmentOffset += PAGE_SIZE) {
|
||||||
PRINT(("mapping zero page at va 0x%x\n", segment->p_vaddr + segmentOffset));
|
PRINT(("mapping zero page at va 0x%x\n", segment->p_vaddr + segmentOffset));
|
||||||
mmu_map_page(segment->p_vaddr + segmentOffset, *next_paddr);
|
mmu_map_page(virtualAddress + segmentOffset, *next_paddr);
|
||||||
memset((void *)(segment->p_vaddr + segmentOffset), 0, PAGE_SIZE);
|
memset((void *)(virtualAddress + segmentOffset), 0, PAGE_SIZE);
|
||||||
(*next_paddr) += PAGE_SIZE;
|
(*next_paddr) += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (foundSegmentIndex) {
|
if (foundSegmentIndex == 0)
|
||||||
case 0:
|
region = &image->text_region;
|
||||||
ar0->start = segment->p_vaddr;
|
else
|
||||||
ar0->size = segment->p_memsz;
|
region = &image->data_region;
|
||||||
break;
|
|
||||||
case 1:
|
region->start = segment->p_vaddr;
|
||||||
ar1->start = segment->p_vaddr;
|
region->size = size;
|
||||||
ar1->size = segment->p_memsz;
|
region->delta = -region->start;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
foundSegmentIndex++;
|
foundSegmentIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize the region pointers to the allocated region
|
||||||
|
// (text region comes first)
|
||||||
|
image->data_region.start = image->text_region.start + image->text_region.size;
|
||||||
|
|
||||||
|
image->data_region.delta += image->data_region.start;
|
||||||
|
image->text_region.delta += image->text_region.start;
|
||||||
|
|
||||||
*start_addr = imageHeader->e_entry;
|
*start_addr = imageHeader->e_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user