File: [local] / prex / boot / common / main.c (download)
Revision 1.1.1.1 (vendor branch), Tue Aug 19 12:46:47 2008 UTC (16 years, 1 month ago) by nbrk
Branch: MAIN, KOHSUKE
CVS Tags: PREX_0_8_BASE, HEAD Changes since 1.1: +0 -0 lines
Initial import of Prex, Portable Real-time Embedded POSIX microkernel system.
I have totally new directions in my development (more focused on real hardware, not virtual one).
Old hacks are available in prex-old module. They will be carefully re-designed and merged soon.
|
/*-
* Copyright (c) 2005-2006, Kohsuke Ohtani
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* main.c - Prex boot loader main module
*/
#include <prex/bootinfo.h>
#include <platform.h>
#include <boot.h>
#include <ar.h>
#ifdef DEBUG
#define DPRINTF(a) printf a
#else
#define DPRINTF(a)
#endif
paddr_t load_base; /* current load address */
paddr_t load_start; /* start address for loading */
int nr_img; /* number of module images */
struct boot_info *boot_info; /* pointer to boot information. */
/*
* Define memory block as reserved area.
*/
void
reserve_memory(paddr_t start, size_t size)
{
int i;
paddr_t mem_end;
DPRINTF(("reserved memory: start=%x size=%x\n", start, size));
if (boot_info->main_mem.size == 0)
panic("bad mem size");
mem_end = boot_info->main_mem.start + boot_info->main_mem.size;
if (start > mem_end)
return;
if (start + size > mem_end)
size = (size_t)(mem_end - start);
for (i = 0; i < NRESMEM; i++) {
if (boot_info->reserved[i].size == 0) {
boot_info->reserved[i].start = start;
boot_info->reserved[i].size = size;
break;
}
}
if (i == NRESMEM)
panic("No memory slot to reserve");
}
/*
* Load all images.
* Return 0 on success, -1 on failure.
*/
static int
load_image(struct ar_hdr *hdr, struct module *m)
{
char *c;
if (strncmp((char *)&hdr->ar_fmag, ARFMAG, 2))
return -1;
strncpy((char *)&m->name, (char *)&hdr->ar_name, 16);
c = (char *)&m->name;
while (*c != '/' && *c != ' ')
c++;
*c = '\0';
DPRINTF(("loading: hdr=%x module=%x name=%s\n",
(int)hdr, (int)m, (char *)&m->name));
if (elf_load((char *)hdr + sizeof(struct ar_hdr), m))
panic("Load error");
return 0;
}
#ifdef CONFIG_RAMDISK
/*
* Setup for RAMDISK
*/
static void
setup_ramdisk(struct ar_hdr *hdr)
{
struct mem_map *ram_disk;
size_t size;
if (strncmp((char *)&hdr->ar_fmag, ARFMAG, 2))
return;
size = (size_t)atol((char *)&hdr->ar_size);
if (size == 0)
return;
ram_disk = (struct mem_map *)&boot_info->ram_disk;
ram_disk->start = (paddr_t)hdr + sizeof(struct ar_hdr);
ram_disk->size = size;
reserve_memory(ram_disk->start, ram_disk->size);
DPRINTF(("RAM disk base=%x size=%x\n", ram_disk->start,
ram_disk->size));
}
#endif /* CONFIG_RAMDISK */
/*
* Setup OS images - kernel, driver and boot tasks.
*
* It reads each module file image and copy it to the appropriate
* memory area. The image is built as generic archive (.a) file.
*
* The image information is stored into the boot information area.
*/
static void
setup_image(void)
{
char *hdr;
struct module *m;
char *magic;
int i;
long len;
/*
* Validate archive image
*/
magic = (char *)boot_info->archive;
if (strncmp(magic, ARMAG, 8))
panic("Invalid OS image");
/*
* Load kernel image
*/
hdr = (char *)((paddr_t)magic + 8);
if (load_image((struct ar_hdr *)hdr, &boot_info->kernel))
panic("Can not load kernel");
/*
* Load driver module
*/
len = atol((char *)&((struct ar_hdr *)hdr)->ar_size);
if (len == 0)
panic("Invalid OS image");
hdr = (char *)((paddr_t)hdr + sizeof(struct ar_hdr) + len);
if (load_image((struct ar_hdr *)hdr, &boot_info->driver))
panic("Can not load driver");
/*
* Load boot tasks
*/
i = 0;
m = (struct module *)&boot_info->tasks[0];
while (1) {
/* Proceed to next archive header */
len = atol((char *)&((struct ar_hdr *)hdr)->ar_size);
if (len == 0)
break;
hdr = (char *)((paddr_t)hdr + sizeof(struct ar_hdr) + len);
/* Pad to even boundary */
hdr += ((paddr_t)hdr % 2);
/* Check archive header */
if (strncmp((char *)&((struct ar_hdr *)hdr)->ar_fmag,
ARFMAG, 2))
break;
#ifdef CONFIG_RAMDISK
/* Load RAM disk image */
if (!strncmp((char *)&((struct ar_hdr *)hdr)->ar_name,
"ramdisk.a", 9)) {
setup_ramdisk((struct ar_hdr *)hdr);
continue;
}
#endif /* CONFIG_RAMDISK */
/* Load task */
if (load_image((struct ar_hdr *)hdr, m))
break;
i++;
m++;
}
boot_info->nr_tasks = i;
if (boot_info->nr_tasks == 0)
panic("No boot task found!");
/*
* Save information for boot modules.
* This includes kernel, driver, and boot tasks.
*/
boot_info->modules.start = load_start;
boot_info->modules.size = (size_t)(load_base - load_start);
}
#ifdef DEBUG_BOOTINFO
static void
dump_image(struct module *m)
{
printf("%s: entry=%x phys=%x size=%x text=%x data=%x textsz=%x datasz=%x bss=%x\n",
m->name, (int)m->entry, (int)m->phys, (int)m->size,
(int)m->text, (int)m->data, (int)m->textsz,
(int)m->datasz, (int)m->bsssz);
}
static void
dump_bootinfo(void)
{
struct module *m;
int i;
printf("main memory start=%x size=%x\n",
(int)boot_info->main_mem.start,
(int)boot_info->main_mem.size);
for (i = 0; i < NRESMEM; i++) {
if (boot_info->reserved[i].size != 0) {
printf("reserved mem start=%x size=%x\n",
(int)boot_info->reserved[i].start,
(int)boot_info->reserved[i].size);
}
}
printf("ramdisk start=%x size=%x\n",
(int)boot_info->ram_disk.start,
(int)boot_info->ram_disk.size);
dump_image(&boot_info->kernel);
dump_image(&boot_info->driver);
m = (struct module *)&boot_info->tasks[0];
for (i = 0; i < boot_info->nr_tasks; i++, m++)
dump_image(m);
}
#endif
/*
* C entry point
*/
void
loader_main(void)
{
paddr_t kernel_entry;
DPRINTF(("Prex Boot Loader V1.00\n"));
load_base = 0;
load_start = 0;
nr_img = 0;
/*
* Get machine-dependent information.
*/
setup_bootinfo(&boot_info);
/*
* Load program image.
*/
setup_image();
#ifdef DEBUG_BOOTINFO
dump_bootinfo();
#endif
/*
* Jump to the kernel entry point
* via machine-dependent code.
*/
kernel_entry = (paddr_t)phys_to_virt(boot_info->kernel.entry);
DPRINTF(("kernel_entry=%x\n", kernel_entry));
DPRINTF(("Entering kernel...\n\n"));
start_kernel(kernel_entry, (paddr_t)boot_info);
/* NOTREACHED */
}