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:
Axel Dörfler
2004-05-31 23:52:01 +00:00
parent a8061da698
commit 8b33111039
+52 -40
View File
@@ -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;
} }