mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
sparc32 merge
git-svn-id: svn://coreboot.org/openbios/openbios-devel@18 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
133
arch/sparc32/aoutload.c
Normal file
133
arch/sparc32/aoutload.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* a.out boot loader
|
||||
* As we have seek, this implementation can be straightforward.
|
||||
* 2003-07 by SONE Takeshi
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "a.out.h"
|
||||
#include "sys_info.h"
|
||||
#include "loadfs.h"
|
||||
#define printf printk
|
||||
#define debug printk
|
||||
|
||||
#define addr_fixup(addr) ((addr) & 0x00ffffff)
|
||||
|
||||
static char *image_name, *image_version;
|
||||
const char *program_name, *program_version;
|
||||
|
||||
static int check_mem_ranges(struct sys_info *info,
|
||||
unsigned long start,
|
||||
unsigned long size)
|
||||
{
|
||||
int j;
|
||||
unsigned long end;
|
||||
unsigned long prog_start, prog_end;
|
||||
struct memrange *mem;
|
||||
|
||||
prog_start = virt_to_phys(&_start);
|
||||
prog_end = virt_to_phys(&_end);
|
||||
|
||||
end = start + size;
|
||||
|
||||
if (start < prog_start && end > prog_start)
|
||||
goto conflict;
|
||||
if (start < prog_end && end > prog_end)
|
||||
goto conflict;
|
||||
mem = info->memrange;
|
||||
for (j = 0; j < info->n_memranges; j++) {
|
||||
if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
|
||||
break;
|
||||
}
|
||||
if (j >= info->n_memranges)
|
||||
goto badseg;
|
||||
return 1;
|
||||
|
||||
conflict:
|
||||
printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
|
||||
|
||||
badseg:
|
||||
printf("A.out file [%#lx-%#lx] doesn't fit into memory\n", start, end - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aout_load(struct sys_info *info, const char *filename, const char *cmdline)
|
||||
{
|
||||
int retval = -1;
|
||||
int image_retval;
|
||||
struct exec ehdr;
|
||||
unsigned long start, size;
|
||||
|
||||
image_name = image_version = 0;
|
||||
|
||||
if (!file_open(filename))
|
||||
goto out;
|
||||
|
||||
if (lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) {
|
||||
debug("Can't read a.out header\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (N_BADMAG(ehdr)) {
|
||||
debug("Not a bootable a.out image\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (N_MAGIC(ehdr) == NMAGIC) {
|
||||
size = N_DATADDR(ehdr) + ehdr.a_data;
|
||||
} else {
|
||||
size = ehdr.a_text + ehdr.a_data;
|
||||
}
|
||||
|
||||
start = 0x4000; // N_TXTADDR(ehdr);
|
||||
|
||||
if (!check_mem_ranges(info, start, size))
|
||||
goto out;
|
||||
|
||||
printf("Loading a.out %s...\n", image_name ? image_name : "image");
|
||||
|
||||
file_seek(N_TXTOFF(ehdr));
|
||||
|
||||
if (N_MAGIC(ehdr) == NMAGIC) {
|
||||
if (lfile_read(start, ehdr.a_text) != ehdr.a_text) {
|
||||
printf("Can't read program text segment (size 0x%x)\n", ehdr.a_text);
|
||||
goto out;
|
||||
}
|
||||
if (lfile_read(start + N_DATADDR(ehdr), ehdr.a_data) != ehdr.a_data) {
|
||||
printf("Can't read program data segment (size 0x%x)\n", ehdr.a_data);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (lfile_read(start, size) != size) {
|
||||
printf("Can't read program (size 0x%x)\n", size);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
debug("Loaded %lu bytes\n", size);
|
||||
|
||||
debug("entry point is %#x\n", start);
|
||||
printf("Jumping to entry point...\n");
|
||||
|
||||
#if 1
|
||||
{
|
||||
extern unsigned int qemu_mem_size;
|
||||
void *init_openprom(unsigned long memsize, const char *cmdline, char boot_device);
|
||||
|
||||
int (*entry)(const void *romvec, int p2, int p3, int p4, int p5);
|
||||
const void *romvec;
|
||||
|
||||
romvec = init_openprom(qemu_mem_size, cmdline, 'c');
|
||||
entry = (void *) addr_fixup(start);
|
||||
image_retval = entry(romvec, 0, 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("Image returned with return value %#x\n", image_retval);
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
Reference in New Issue
Block a user