Skip to content
Snippets Groups Projects
Commit 74081fd8 authored by Armin Luntzer's avatar Armin Luntzer
Browse files

merge application loader

parents 054c8801 e28d308b
No related branches found
No related tags found
No related merge requests found
Showing
with 822 additions and 35 deletions
......@@ -16,11 +16,12 @@
* @param m an ELF module
* @param rel an ELF relocation entry
* @param sym the address of the target symbol
* @param sec_name the name of the section to apply the relocation in
*
* return 0 on success
*/
int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym)
int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym, const char *sec_name)
{
Elf_Addr rsym;
......@@ -40,9 +41,13 @@ int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym)
if (!sym)
return -EINVAL;
if (!sec_name) {
pr_err("\tsec_name empty!\n");
return -EINVAL;
}
text = find_mod_sec(m, ".text");
text = find_mod_sec(m, sec_name);
loc8 = (uint8_t *) (text->addr + rel->r_offset);
loc32 = (uint32_t *) loc8;
......
......@@ -145,8 +145,6 @@ hw_div0_trap_handler:
nmi_entry:
.global reg_access_trap_handler
reg_access_trap_handler:
.global strchr
strchr:
.global syscall_tbl
syscall_tbl:
.global syscall_trap
......@@ -159,4 +157,4 @@ syscall_trap:
unimpl_flush_trap_handler:
.global watchpoint_det_trap_handler
watchpoint_det_trap_handler:
ta 0
ta 3
......@@ -568,6 +568,9 @@ int elf_header_check(Elf_Ehdr *ehdr);
Elf_Shdr *elf_get_shdr(const Elf_Ehdr *ehdr);
size_t elf_find_shdr_alloc_idx(const Elf_Ehdr *ehdr, const size_t offset);
size_t elf_get_common_size(const Elf_Ehdr *ehdr);
size_t elf_get_common_objects(const Elf_Ehdr *ehdr, char **objname);
Elf_Shdr *elf_get_sec_by_idx(const Elf_Ehdr *ehdr, const size_t idx);
Elf_Shdr *elf_get_sec_shstrtab(const Elf_Ehdr *ehdr);
char *elf_get_shstrtab_str(const Elf_Ehdr *ehdr, size_t idx);
......@@ -586,6 +589,7 @@ unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr,
const char *name, unsigned long *value);
unsigned long elf_get_symbol_type(const Elf_Ehdr *ehdr, const char *name);
size_t elf_get_symbol_size(const Elf_Ehdr *ehdr, const char *name);
size_t elf_find_sec_idx_by_type(const Elf_Ehdr *ehdr,
const uint32_t sh_type,
......@@ -606,4 +610,6 @@ void elf_dump_symtab(const Elf_Ehdr *ehdr);
void elf_dump_sections(const Elf_Ehdr *ehdr);
unsigned short elf_get_symbol_shndx(const Elf_Ehdr *ehdr,
const char *name);
#endif /* _KERNEL_ELF_H_ */
......@@ -62,7 +62,8 @@ struct elf_module {
/* implemented in architecture code */
int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym);
int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym,
const char *sec_name);
struct module_section *find_mod_sec(const struct elf_module *m,
......
......@@ -20,12 +20,16 @@ char *strpbrk(const char *s, const char *accept);
char *strsep(char **stringp, const char *delim);
char *strdup(const char *s);
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
size_t strlen(const char *s);
int memcmp(const void *s1, const void *s2, size_t n);
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
char *strcpy(char *dest, const char *src);
void bzero(void *s, size_t n);
......@@ -46,5 +50,7 @@ int vprintf(const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
int puts(const char *s);
int putchar(int c);
#endif /* _KERNEL_STRING_H_ */
......@@ -105,6 +105,16 @@ config EMBED_MODULES_IMAGE
generated modules into the final kernel binary.
This is a convenience option, if unsure, say Y.
config EMBED_APPLICATION
string "Embed an application image"
depends on EMBED_MODULES_IMAGE
default ""
help
Specify a path to an executable to embed or leave it empty.
Note: in the current implementation, the executable is treated as a
kernel module, so it requires to be relocatible and have a init/exit
call.
endif # MODULES
......@@ -178,4 +188,5 @@ config DEBUG_INFO_REDUCED
DEBUG_INFO build and compile times are reduced too.
Only works with newer gcc versions.
endmenu
......@@ -163,6 +163,27 @@ int kernel_main(void)
modules_list_loaded();
#endif
#ifdef CONFIG_EMBED_APPLICATION
/* dummy demonstrator */
{
void *addr;
struct elf_module m;
addr = module_read_embedded("CrApp1");
pr_debug(MSG "test executable address is %p\n", addr);
if (addr)
module_load(&m, addr);
#if 0
modules_list_loaded();
#endif
}
#endif
#ifdef CONFIG_MPPB
/* The mppbv2 LEON's cache would really benefit from cache sniffing...
* Interactions with DMA or Xentiums are a pain when using the lower
......
......@@ -69,6 +69,28 @@ struct module_section *find_mod_sec(const struct elf_module *m,
}
/**
* @brief find module section by index
*
* @param m a struct elf_module
*
* @param idx the index of the module section
*
* @return module section structure pointer or NULL if not found
*/
struct module_section *find_mod_idx(const struct elf_module *m,
size_t idx)
{
if (idx >= m->num_sec)
return NULL;
return &m->sec[idx];
}
/**
* @brief setup the module structure
*
......@@ -178,8 +200,13 @@ static int module_load_mem(struct elf_module *m)
sec = elf_get_sec_by_idx(m->ehdr, idx);
#if 0
if (!sec->sh_size) /* don't need those */
continue;
#else
if (!(sec->sh_flags & SHF_ALLOC))
continue;
#endif
s->size = sec->sh_size;
......@@ -193,24 +220,27 @@ static int module_load_mem(struct elf_module *m)
goto error;
strcpy(s->name, src);
pr_err(MOD "section %s index %d max %d\n", s->name, s, m->num_sec);
if (sec->sh_type & SHT_NOBITS) {
pr_debug(MOD "\tZero segment %10s at %p size %ld\n",
pr_info(MOD "\tZero segment %10s at %p size %ld\n",
s->name, (char *) va_load,
sec->sh_size);
bzero((void *) va_load, s->size);
} else {
pr_debug(MOD "\tCopy segment %10s from %p to %p size %ld\n",
pr_info(MOD "\tCopy segment %10s from %p to %p size %ld\n",
s->name,
(char *) m->ehdr + sec->sh_offset,
(char *) va_load,
sec->sh_size);
memcpy((void *) va_load,
(char *) m->ehdr + sec->sh_offset,
sec->sh_size);
if (sec->sh_size)
memcpy((void *) va_load,
(char *) m->ehdr + sec->sh_offset,
sec->sh_size);
}
s->addr = va_load;
......@@ -219,10 +249,84 @@ static int module_load_mem(struct elf_module *m)
s++;
if (s > &m->sec[m->num_sec]) {
pr_debug(MOD "Error out of section memory\n");
pr_err(MOD "Error out of section memory\n");
goto error;
}
}
#if 0
if (elf_get_common_size(m->ehdr)) {
m->num_sec++;
m->sec = (struct module_section *)
krealloc(m->sec, sizeof(struct module_section) * m->num_sec);
if (!m->sec)
goto error;
s = &m->sec[m->num_sec - 1];
s->size = elf_get_common_size(m->ehdr);
s->addr = (unsigned long) kzalloc(s->size);
if (!s->addr)
goto error;
pr_info(MOD "\tcreating .alloc section of %d bytes at %x\n", s->size, s->addr);
s->name = kmalloc(strlen(".alloc"));
if (!s->name)
goto error;
strcpy(s->name, ".alloc");
}
#else
/* yes, yes, fixup like everything else here */
if (elf_get_common_objects(m->ehdr, NULL)) {
size_t cnt = elf_get_common_objects(m->ehdr, NULL);
char **obj;
m->sec = (struct module_section *)
krealloc(m->sec, sizeof(struct module_section) * (m->num_sec + cnt));
if (!m->sec)
goto error;
/* point to last */
s = &m->sec[m->num_sec];
/* and update */
m->num_sec += cnt;
obj = kmalloc(cnt * sizeof(char **));
if (!obj)
goto error;
/* load names */
elf_get_common_objects(m->ehdr, obj);
/* Allocate one section entry for each object, this is not
* that efficient, but what the heck. Better not to have
* uninitialised non-static globals at all!
*/
for (idx = 0; idx < cnt; idx++) {
s->size = elf_get_symbol_size(m->ehdr, obj[idx]);
s->addr = (unsigned long) kzalloc(s->size);
if (!s->addr)
goto error;
pr_debug(MOD "\tcreating \"%s\" section of %d bytes at %x\n", obj[idx], s->size, s->addr);
s->name = kmalloc(strlen(obj[idx]));
if (!s->name)
goto error;
strcpy(s->name, obj[idx]);
s++;
}
kfree(obj);
}
#endif
return 0;
......@@ -264,11 +368,12 @@ static int module_relocate(struct elf_module *m)
if (m->ehdr->e_type != ET_DYN)
return 0;
/* we only need RELA type relocations */
while (1) {
char *rel_sec;
idx = elf_find_sec_idx_by_type(m->ehdr, SHT_RELA, idx + 1);
if (!idx)
......@@ -276,8 +381,16 @@ static int module_relocate(struct elf_module *m)
sec = elf_get_sec_by_idx(m->ehdr, idx);
pr_debug(MOD "\n"
MOD "Section Header info: %ld\n", sec->sh_info);
pr_info(MOD "\n"
MOD "Section Header info: %ld %s\n", sec->sh_info, elf_get_shstrtab_str(m->ehdr, idx));
if (!strcmp(elf_get_shstrtab_str(m->ehdr, idx), ".rela.text"))
rel_sec = ".text";
else if (!strcmp(elf_get_shstrtab_str(m->ehdr, idx), ".rela.data"))
rel_sec = ".data";
else
BUG();
if (sec) {
......@@ -295,8 +408,8 @@ static int module_relocate(struct elf_module *m)
unsigned int symsec = ELF_R_SYM(relatab[i].r_info);
char *symstr = elf_get_symbol_str(m->ehdr, symsec);
struct module_section *s;
struct module_section *text = find_mod_sec(m, ".text");
struct module_section *text = find_mod_sec(m, ".text"); /* ?? rel_sec ?? */
pr_debug(MOD "OFF: %08lx INF: %8lx ADD: %3ld LNK: %ld SEC: %d NAME: %s\n",
relatab[i].r_offset,
relatab[i].r_info,
......@@ -308,23 +421,63 @@ static int module_relocate(struct elf_module *m)
if (strlen(symstr)) {
Elf_Addr sym = (Elf_Addr) lookup_symbol(symstr);
unsigned long symval;
Elf_Addr sym = (Elf_Addr) lookup_symbol(symstr);
if (!sym) {
if (!sym) {
pr_debug(MOD "\tSymbol %s not found in library, trying to resolving in module\n",
symstr);
unsigned long symval;
pr_info(MOD "\tSymbol %s not found in library, trying to resolving in module\n",
symstr);
if ((elf_get_symbol_type(m->ehdr, symstr) & STT_OBJECT)) {
char *secstr;
if (!(elf_get_symbol_type(m->ehdr, symstr) & STT_OBJECT)) {
pr_debug(MOD "\tERROR, object data resolution not yet implemented, symbol %s may not function as intended. If it is a variable, declare it static as a workaround\n", symstr);
}
s = find_mod_sec(m, elf_get_shstrtab_str(m->ehdr, elf_get_symbol_shndx(m->ehdr, symstr)));
switch (elf_get_symbol_shndx(m->ehdr, symstr)) {
case SHN_UNDEF:
pr_debug(MOD "\tundefined section index\n");
break;
case SHN_ABS:
pr_debug(MOD "\tabsolute value section index\n");
case SHN_COMMON:
pr_debug(MOD "\t %s common symbol index (must allocate) add: %d\n", symstr,
relatab[i].r_addend);
s = find_mod_sec(m, symstr);
if (!s) {
pr_err("no suitable section found");
return -1;
}
break;
default:
break;
}
if (!s) {
pr_debug(MOD "Error cannot locate section %s for symbol\n", secstr);
continue;
}
secstr = s->name;
/* target address to insert at location */
reladdr = (long) s->addr;
pr_debug(MOD "\tRelative symbol address: %x, entry at %08lx, section %s\n", reladdr, s->addr, secstr);
/* needed ?? */
//elf_get_symbol_value(m->ehdr, symstr, (unsigned long *) &relatab[i].r_addend);
apply_relocate_add(m, &relatab[i], reladdr, rel_sec);
continue;
}
#if 0
if (!(elf_get_symbol_type(m->ehdr, symstr) & (STT_FUNC | STT_OBJECT))) {
pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr);
return -1;
}
#endif
if (!elf_get_symbol_value(m->ehdr, symstr, &symval)) {
pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr);
return -1;
......@@ -334,25 +487,26 @@ static int module_relocate(struct elf_module *m)
}
pr_debug(MOD "\tSymbol %s at %lx\n", symstr, sym);
pr_debug(MOD "\tSymbol %s at %lx val %lx sec %d\n", symstr, sym, symval, symsec);
apply_relocate_add(m, &relatab[i], sym);
apply_relocate_add(m, &relatab[i], sym, rel_sec);
} else { /* no string, symtab entry is probably a section, try to identify it */
char *secstr = elf_get_shstrtab_str(m->ehdr, symsec);
s = find_mod_sec(m, secstr);
s = find_mod_idx(m, symsec-1);
if (!s) {
pr_debug(MOD "Error cannot locate section %s for symbol\n", secstr);
continue;
}
secstr = s->name;
/* target address to insert at location */
reladdr = (long) s->addr;
pr_debug(MOD "\tRelative symbol address: %x, entry at %08lx\n", reladdr, s->addr);
pr_debug(MOD "\tRelative symbol address: %x, entry at %08lx, section %s\n", reladdr, s->addr, secstr);
apply_relocate_add(m, &relatab[i], reladdr);
apply_relocate_add(m, &relatab[i], reladdr, rel_sec);
}
pr_debug(MOD "\n");
......
......@@ -510,6 +510,102 @@ unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr,
}
/**
* @brief get the value of a symbol
*
* @param ehdr an Elf_Ehdr
*
* @param name the name of the symbol
*
* @return the size of the symbol (0 if not found or simply size 0)
* -1 on error
*/
size_t elf_get_symbol_size(const Elf_Ehdr *ehdr, const char *name)
{
unsigned int i;
size_t sym_cnt;
Elf_Shdr *symtab;
Elf_Sym *symbols;
symtab = elf_find_sec(ehdr, ".symtab");
if (!symtab) {
pr_debug(MSG "WARN: no .symtab section found\n");
return -1;
}
if (symtab->sh_entsize != sizeof(Elf_Sym)) {
pr_debug(MSG "Error %d != %ld\n",
sizeof(Elf_Sym), symtab->sh_entsize);
return -1;
}
symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
sym_cnt = symtab->sh_size / symtab->sh_entsize;
for (i = 0; i < sym_cnt; i++) {
if(!strcmp(elf_get_symbol_str(ehdr, i), name))
return (size_t) symbols[i].st_size;
}
return 0;
}
/**
* @brief get the section index of a symbol
*
* @param ehdr an Elf_Ehdr
*
* @param name the name of the symbol
*
* @return the section index of the symbol or -1 if not found
*/
unsigned short elf_get_symbol_shndx(const Elf_Ehdr *ehdr,
const char *name)
{
unsigned int i;
size_t sym_cnt;
Elf_Shdr *symtab;
Elf_Sym *symbols;
symtab = elf_find_sec(ehdr, ".symtab");
if (!symtab) {
pr_debug(MSG "WARN: no .symtab section found\n");
return -1;
}
if (symtab->sh_entsize != sizeof(Elf_Sym)) {
pr_debug(MSG "Error %d != %ld\n",
sizeof(Elf_Sym), symtab->sh_entsize);
return -1;
}
symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
sym_cnt = symtab->sh_size / symtab->sh_entsize;
for (i = 0; i < sym_cnt; i++) {
if(!strcmp(elf_get_symbol_str(ehdr, i), name)) {
return symbols[i].st_shndx;
}
}
return -1;
}
/**
* @brief get the ELF type of a symbol
*
......@@ -607,14 +703,114 @@ size_t elf_get_num_alloc_sections(const Elf_Ehdr *ehdr)
for (i = 0; i <ehdr->e_shnum; i++) {
shdr = elf_get_sec_by_idx(ehdr, i);
if ((shdr->sh_flags & SHF_ALLOC))
if (shdr->sh_size)
cnt++;
cnt++;
}
return cnt;
}
/* @brief get the total byte size of unallocated uninitialised common objects
*
* @param ehdr an Elf_Ehdr
*
* @return the number of bytes to be occupied by common (unallocated) objects
*/
size_t elf_get_common_size(const Elf_Ehdr *ehdr)
{
unsigned int i;
size_t sym_cnt;
Elf_Shdr *symtab;
Elf_Sym *symbols;
size_t bytes = 0;
symtab = elf_find_sec(ehdr, ".symtab");
if (!symtab) {
pr_debug(MSG "WARN: no .symtab section found\n");
return 0;
}
if (symtab->sh_entsize != sizeof(Elf_Sym)) {
pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
return 0;
}
symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
sym_cnt = symtab->sh_size / symtab->sh_entsize;
for (i = 0; i < sym_cnt; i++) {
if (symbols[i].st_shndx == SHN_COMMON)
bytes += symbols[i].st_size;
}
return bytes;
}
/* @brief get the total count of unallocated uninitialised common objects
*
* @param ehdr an Elf_Ehdr
* @param[out] an index array
*
* @note set idx to NULL to determine the number of elements needed for the
* array
*
* @return the number of common objects
*/
size_t elf_get_common_objects(const Elf_Ehdr *ehdr, char **objname)
{
unsigned int i;
size_t sym_cnt;
Elf_Shdr *symtab;
Elf_Sym *symbols;
size_t common = 0;
symtab = elf_find_sec(ehdr, ".symtab");
if (!symtab) {
pr_debug(MSG "WARN: no .symtab section found\n");
return 0;
}
if (symtab->sh_entsize != sizeof(Elf_Sym)) {
pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
return 0;
}
symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
sym_cnt = symtab->sh_size / symtab->sh_entsize;
for (i = 0; i < sym_cnt; i++) {
if (symbols[i].st_shndx == SHN_COMMON) {
if (objname)
objname[common] = elf_get_symbol_str(ehdr, i);
common++;
}
}
return common;
}
/**
* @brief get the number of entries in a dynamic section
*
......@@ -727,7 +923,8 @@ void elf_dump_symtab(const Elf_Ehdr *ehdr)
printk(MSG "\n"
MSG ".symtab contains %d entries\n"
MSG "============================\n"
MSG "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\n", sym_cnt);
MSG "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\t\t[SHIDX]\n",
sym_cnt);
for (i = 0; i < sym_cnt; i++) {
......@@ -756,7 +953,9 @@ void elf_dump_symtab(const Elf_Ehdr *ehdr)
printk("\tUNKNOWN"); break;
}
printk("\t%-10s\n", elf_get_symbol_str(ehdr, i));
printk("\t%-10s", elf_get_symbol_str(ehdr, i));
printk("\t%4ld\n", symbols[i].st_shndx);
}
}
......
......@@ -173,6 +173,33 @@ char *strdup(const char *s)
EXPORT_SYMBOL(strdup);
/**
* @brief locate a character in string
*
* @param s the string to search in
* @param c the character to search for
*
* @returns a pointer to the first matched character or NULL if not found
*
* @note the terminating null byte is considered part of the string, so that if
* c is given as '\0', the function returns a pointer to the terminator
*/
char *strchr(const char *s, int c)
{
while ((*s) != (char) c) {
if ((*s) == '\0')
return NULL;
s++;
}
return (char *) s;
}
EXPORT_SYMBOL(strchr);
/**
* @brief calculate the length of a string
*
......@@ -300,6 +327,53 @@ void *memcpy(void *dest, const void *src, size_t n)
EXPORT_SYMBOL(memcpy);
/**
* @brief copy a memory area src that may overlap with area dest
*
* @param dest the destination memory area
* @param src the source memory area
* @param n the number of bytes to copy
*
* @returns a pointer to dest
*/
void *memmove(void *dest, const void *src, size_t n)
{
char *d;
const char *s;
if (dest <= src) {
d = dest;
s = src;
while (n--) {
(*d) = (*s);
d++;
s++;
}
} else {
d = dest;
d += n;
s = src;
s += n;
while (n--) {
d--;
s--;
(*d) = (*s);
}
}
return dest;
}
EXPORT_SYMBOL(memmove);
/**
* @brief copy a '\0' terminated string
*
......@@ -352,6 +426,58 @@ void bzero(void *s, size_t n)
EXPORT_SYMBOL(bzero);
/**
* @brief writes the string s and a trailing newline to stdout
*
* @param str the destination buffer
* @param format the format string buffer
* @param ... arguments to the format string
*
* @return the number of characters written to buf
*/
int puts(const char *s)
{
int n;
n = vsnprintf(NULL, INT_MAX, s, NULL);
n+= vsnprintf(NULL, INT_MAX, "\n", NULL);
return n;
}
EXPORT_SYMBOL(puts);
/**
* @brief writes the character c, cast to an unsigned char, to stdout
*
* @param c the character to write
*
* @return the number of characters written to buf
*
* FIXME: this must be replaced by a different mechanic, e.g. provided
* by the architecture or a driver
*/
int putchar(int c)
{
#define TREADY 4
static volatile int *console = (int *)0x80000100;
while (!(console[1] & TREADY));
console[0] = 0x0ff & c;
if (c == '\n') {
while (!(console[1] & TREADY));
console[0] = (int) '\r';
}
return c;
}
/**
* @brief print a string into a buffer
......
......@@ -309,7 +309,9 @@ if [ "$1" = "embed" ]; then
rm -f modules.image
${AR} rcs ${srctree}/modules.image \
$(tr '\n' ' ' < ${srctree}/modules.order) \
$(find dsp/xentium -name *.xen)
$(find dsp/xentium -name *.xen) \
"${CONFIG_EMBED_APPLICATION}"
leanos_link "${kallsymso}" leanos "${embedflags}"
exit
......
CC = sparc-elf-gcc
SOURCEDIR = ./
INCLUDEDIR = ./
BUILDDIR = ./
PATH +=
CPPFLAGS :=
CFLAGS := -r -mv8 -mhard-float -mfix-gr712rc -O2 -std=gnu89 -W -Wall \
-Wextra -Werror -pedantic -Wshadow -Wuninitialized \
-fdiagnostics-show-option -Wcast-qual -Wformat=2 \
-nostartfiles -nostdlib
LDFLAGS :=
SOURCES := $(wildcard *.c)
OBJECTS := $(patsubst %.c, $(BUILDDIR)/%.o, $(subst $(SOURCEDIR)/,, $(SOURCES)))
TARGET := executable_demo
DEBUG?=1
ifeq "$(shell expr $(DEBUG) \> 1)" "1"
CFLAGS += -DDEBUGLEVEL=$(DEBUG)
else
CFLAGS += -DDEBUGLEVEL=1
endif
all: $(SOURCES)
$(CC) $(CPPFLAGS) $(CFLAGS) $^ -o $(TARGET)
Description:
============
This test configures and executes an embedded application demonstrator.
Press Ctrl+C to quit the demonstration.
Pass/Fail Criterea:
===================
None
Prerequisites:
==============
* connected GR712 board
* grmon v2.x
Notes:
======
The current .config of LeanOS will be overwritten and the image will
be rebuilt.
#
# Automatically generated file; DO NOT EDIT.
# LeanOS Configuration
#
#
# SPARC Configuration
#
# CONFIG_LEON2 is not set
CONFIG_LEON3=y
# CONFIG_MMU is not set
CONFIG_CPU_CLOCK_FREQ=80000000
CONFIG_EXTRA_SPARC_PHYS_BANKS=0
CONFIG_SPARC_CPU_REG_WINDOWS=8
CONFIG_SPARC_TEXT_START=0x40000000
CONFIG_SPARC_FP_START=0x40100000
#
# Memory Management Settings
#
CONFIG_SPARC_MM_BLOCK_ORDER_MAX=26
CONFIG_SPARC_MM_BLOCK_ORDER_MIN=12
CONFIG_SPARC_INIT_PAGE_MAP_MAX_ENTRIES=8
CONFIG_SPARC_BOOTMEM_RESERVE_CHUNK_ORDER=20
CONFIG_SPARC_BOOTMEM_REQUEST_NEW_ON_DEMAND=y
CONFIG_SPARC_NESTED_IRQ=y
#
# General Setup
#
CONFIG_KALLSYMS=y
CONFIG_CROSS_PLATFORM_TARGET=y
CONFIG_CROSS_COMPILE="sparc-elf-"
# CONFIG_TARGET_COMPILER_BOOT_CODE is not set
CONFIG_ARCH_CUSTOM_BOOT_CODE=y
CONFIG_MODULES=y
CONFIG_EMBED_MODULES_IMAGE=y
# CONFIG_BUILD_XEN_KERNELS is not set
#
# Compile-time checks and compiler options
#
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_OPTIMIZE_NONE is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_KERNEL_PRINTK=y
CONFIG_KERNEL_LEVEL=7
# CONFIG_IRQ_STATS_COLLECT is not set
# CONFIG_TASK_PREEMPTION_DISABLE is not set
# CONFIG_SOC is not set
#
# Core Components
#
CONFIG_SYSCTL=y
CONFIG_MM=y
#
# Memory Management Debug Options
#
# CONFIG_MM_DEBUG_DUMP is not set
CONFIG_PAGE_MAP=y
#
# Page Map Options
#
# CONFIG_PAGE_MAP_CHECK_PAGE_ALIGNMENT is not set
CONFIG_PAGE_MAP_MOVE_NODE_AVAIL_THRESH=1
CONFIG_CHUNK=y
CONFIG_AR=y
# CONFIG_SAMPLES is not set
/* This demonstrates a basic configuration for and "embedded application"
*
* Note that at this point, we do not distinguish between an application
* payload and a module, this will be changed in the future.
*/
#include "glue.h"
/* some random function we use in our executable */
static void print0r(int i)
{
printk("print0r %d\n", i);
}
/* this is the equivalent of "main()" in our application
* (can actually be main I guess)
*/
static int iasw(void *data)
{
int i;
(void) data;
/* print a little */
for (i = 0; i < 10; i++)
print0r(i);
/* then print a single "z" in a loop and "pause" until the function
* is re-scheduled by issuing sched_yield()
*/
while (1) {
printk("z");
sched_yield();
}
return 0;
}
/*
* This is our startup call, it will be executed once when the application is
* loaded. Here we create at thread in which our actual application code
* will run in.
*/
int init_iasw(void)
{
struct task_struct *t;
t = kthread_create(iasw, (void *) 0, KTHREAD_CPU_AFFINITY_NONE, "IASW");
kthread_wake_up(t);
return 0;
}
/**
* this is our optional exit call, it will be called when the module/application
* is removed by the kernel
*/
int exit_iasw(void)
{
printk("%s leaving\n", __func__);
/* kthread_destroy() */
return 0;
}
/* here we declare our init and exit functions */
module_init(init_iasw)
module_exit(exit_iasw)
#ifndef GLUE_H
#define GLUE_H
/*
* prototypes and declarations needed to build this demo
*/
#define module_init(initfunc) \
int _module_init(void) __attribute__((alias(#initfunc)));
#define module_exit(exitfunc) \
int _module_exit(void) __attribute__((alias(#exitfunc)));
#define KTHREAD_CPU_AFFINITY_NONE (-1)
int printk(const char *format, ...);
struct task_struct *kthread_create(int (*thread_fn)(void *data),
void *data, int cpu,
const char *namefmt,
...);
void kthread_wake_up(struct task_struct *task);
void sched_yield(void);
#endif /* GLUE_H */
load leanos
run
quit
#!/bin/bash
# grmon must be in path!
#build application
make || exit 1
mydir=$PWD
srcdir=../../../../
cp config ${srcdir}/.config || exit 1
echo -e "CONFIG_EMBED_APPLICATION=\"$PWD/executable_demo\"" >> ${srcdir}/.config
cd ${srcdir} || exit 1
make clean || exit 1
make || exit 1
grmon -ftdi -u -ftdifreq 0 -jtagcable 3 -nb -c $mydir/grmon_cmds
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment