diff --git a/SConscript b/SConscript
index 9444732..3582fb3 100644
--- a/SConscript
+++ b/SConscript
@@ -35,8 +35,7 @@ import os
import GenApps
# imports from SConstruct
-Import('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped test')
-
+Import('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped test dynApp dynamicAppName')
# returns the list of .c and .s files in dir, prefixed by dstDir
def getAllSourceFiles(dir, dstDir):
sourceFiles = []
@@ -53,9 +52,9 @@ def getAllSourceFiles(dir, dstDir):
# used to generate both static and dynamic resources
def generateResource(target, source, env):
if propsFilesMap.has_key(str(source[0])):
- GenApps.generateResource(str(source[0]),str(target[0]),chuncksNbits,gzipped,propsFilesMap[str(source[0])])
+ GenApps.generateResource(str(source[0]),str(target[0]), chuncksNbits,gzipped,propsFilesMap[str(source[0])])
else:
- GenApps.generateResource(str(source[0]),str(target[0]),chuncksNbits,gzipped,None)
+ GenApps.generateResource(str(source[0]),str(target[0]), chuncksNbits,gzipped,None)
return None
# builder used to generate the file index, with the URLs tree
@@ -102,10 +101,13 @@ VariantDir(os.path.join(binDir,'drivers'), driversDir, duplicate=0)
# applications files index and channel files settings
resourcesIndexO = os.path.join(binDir,'gen','resources_index')
resourcesIndexC = os.path.join(genDir,'resources_index.c')
+elfEnvironmentO = os.path.join(binDir,'gen','elf_environment')
+elfEnvironmentC = os.path.join(genDir,'elf_environment.c')
channelsH = os.path.join(genDir,'channels.h')
appListName = os.path.join(genDir,'appList')
definesH = os.path.join(genDir,'defines.h')
blobsH = os.path.join(genDir,'blobs.h')
+
# loop on each web resource in order to generate associated c files
# static resources generate pre-computed c files
# dynamic resources are enriched with new declarations (from their XML)
@@ -156,16 +158,47 @@ env.GenChannelsH(channelsH,propsFilesList)
env.Depends(channelsH,toolsList)
env.GenDefinesH(definesH,[])
env.GenBlobsH(blobsH,[])
-# engine source code dependencies
-coreFiles = getAllSourceFiles(coreDir, os.path.join(binDir,'core'))
-# target drivers source code dependencies
-targetFiles = getAllSourceFiles(driversDir, os.path.join(binDir,'drivers'))
-# create a library from all sources
-lib = env.Library(libFileName, targetFiles + coreFiles + genObjects)
-# link the library into a elf file
-if env['BUILDERS']['Program'] is not None:
- final = env.Program(elfFileName, targetFiles + coreFiles + genObjects)
+if dynApp :
+
+ installList = []
+ removeList = []
+ for file in sourcesMap.keys():
+ if file.endswith('.h') or file.endswith('.c'):
+ GenApps.extractXMLElfApplicationLifeCycle(file, installList, removeList)
+
+ # elf application environment generation
+ GenApps.generateElfApplication(elfEnvironmentC, installList, removeList)
+ # elf application environment object file
+ genObjects.append(env.Object(elfEnvironmentO, elfEnvironmentC))
+
+ linkerCommand = env.subst('$LINK')
+ linkerCommand += ' -r '
+
+ pathes = []
+ for elt in genObjects :
+ for inner_elt in elt.data :
+ pathes.append(inner_elt.path)
+ linkerCommand += ' '.join(pathes)
+ linkerCommand += ' -o $TARGET'
+
+ finalDynamicAppName = os.path.join(binDir, dynamicAppName + '.o')
+
+ env.Command(finalDynamicAppName, None, linkerCommand)
+
+ for elt in genObjects :
+ for inner_elt in elt.data :
+ env.Depends(finalDynamicAppName, inner_elt.path)
else:
- final = None
-# clean
-Clean([lib,final],[binDir,genDir])
+ # engine source code dependencies
+ coreFiles = getAllSourceFiles(coreDir, os.path.join(binDir,'core'))
+ # target drivers source code dependencies
+ targetFiles = getAllSourceFiles(driversDir, os.path.join(binDir,'drivers'))
+ # create a library from all sources
+ lib = env.Library(libFileName, targetFiles + coreFiles + genObjects)
+ # link the library into a elf file
+ if env['BUILDERS']['Program'] is not None:
+ final = env.Program(elfFileName, targetFiles + coreFiles + genObjects)
+ else:
+ final = None
+ # clean
+ Clean([lib,final],[binDir,genDir])
diff --git a/SConstruct b/SConstruct
index 2040869..1bf6cd1 100644
--- a/SConstruct
+++ b/SConstruct
@@ -79,6 +79,7 @@ opts.Add(BoolVariable('gzip', 'Set to 1 to gzip (at compile time) static Web res
opts.Add(BoolVariable('debug', 'Set to 1 to build for debug', False))
opts.Add(BoolVariable('sdump', 'Set to 1 to include stack dump', False))
opts.Add(BoolVariable('test', 'Set to 1 to test the test apps', False))
+opts.Add(BoolVariable('dynApp', 'Set to 1 to build an uploadable application', False))
opts.Add('ipaddr', 'Set the IP address of Smews', None)
# the list of disableable options
disabledHash = {}
@@ -97,6 +98,7 @@ globalEnv = Environment(tools = ['gcc','as','ar','gnulink'], ENV = os.environ, o
Help(opts.GenerateHelpText(globalEnv))
# arguments are stored into variables
+dynApp = globalEnv['dynApp']
gzipped = globalEnv['gzip']
debug = globalEnv['debug']
sdump = globalEnv['sdump']
@@ -159,6 +161,7 @@ if len(targets) == 0:
# will generate :
# / -> smews, myApp/ -> myApplication, test/ -> test
appDirs = originalAppDirs.split(',')
+
dirsMap = {}
for appDir in set(appDirs + [httpCodesDir]):
if appDir != '':
@@ -168,6 +171,18 @@ for appDir in set(appDirs + [httpCodesDir]):
else:
dirsMap[appDir] = '/' + appDir
+dynamicAppName = ''
+if dynApp :
+ appDirNames = []
+ for appDir in appDirs:
+ if appDir != '':
+ idx = appDir.find(':')
+ if idx != -1:
+ appDirNames.append(appDir[idx+1:])
+ else:
+ appDirNames.append(appDir)
+ dynamicAppName = '_'.join(appDirNames)
+
# association between web applicative resources and their final URLs
# appDir did only contain association of embedded applications
# here, we retrieve all the files of each application
@@ -185,14 +200,18 @@ for appDir in dirsMap.keys():
globalEnv.Replace(CC = 'gcc')
globalEnv.Replace(AS = 'as')
globalEnv.Replace(AR = 'ar')
+globalEnv.Replace(LINK = 'ld')
globalEnv.Append(CCFLAGS = '-Wall')
if sdump:
globalEnv.Append(CCFLAGS = '-DSTACK_DUMP')
if debug:
globalEnv.Append(CCFLAGS = '-O0 -g')
else:
- globalEnv.Append(CCFLAGS = '-Os -ffunction-sections -fdata-sections -fno-strict-aliasing')
- globalEnv.Append(LINKFLAGS = '-Wl,--gc-sections -Wl,--print-gc-sections')
+ if dynApp :
+ globalEnv.Append(CCFLAGS = '-Os -fno-strict-aliasing')
+ else :
+ globalEnv.Append(CCFLAGS = '-Os -ffunction-sections -fdata-sections -fno-strict-aliasing')
+ globalEnv.Append(LINKFLAGS = '--gc-sections --print-gc-sections')
globalEnv.Append(CPPDEFINES = {'CHUNCKS_NBITS' : str(chuncksNbits)})
for func in toDisable:
globalEnv.Append(CPPDEFINES = { disabledHash[func] : '1'})
@@ -224,7 +243,7 @@ for target in targets:
os.mkdir(dir)
# export variables for external SConscript files
- Export('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped test')
+ Export('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped test dynApp dynamicAppName')
Export('env targetDir binDir projectName elfName')
Export('dirsMap sourcesMap target sconsBasePath httpCodesDir tmpBase')
# target dependent SConscript call
diff --git a/apps/connectionsStats/stats.c b/apps/connectionsStats/stats.c
index 938e042..679d3cf 100644
--- a/apps/connectionsStats/stats.c
+++ b/apps/connectionsStats/stats.c
@@ -65,5 +65,6 @@ static char doGet(struct args_t *args) {
out_str("NULL\n");
out_str("\tsomething to send: "); out_uint(something_to_send(conn)); out_str("\n");
})
+
return 1;
}
diff --git a/apps/contactsBook/cb_add.c b/apps/contactsBook/cb_add.c
index e788d96..ec129af 100755
--- a/apps/contactsBook/cb_add.c
+++ b/apps/contactsBook/cb_add.c
@@ -35,7 +35,7 @@
/*
-
+
@@ -47,7 +47,7 @@
#include "cb_shared.h"
-static char doGet(struct args_t *args) {
+static char doGetAdd(struct args_t *args) {
unsigned char id = 0;
uint16_t n = CONST_UI16(n_contacts);
if(args && args->num < 5) {
diff --git a/apps/contactsBook/cb_get.c b/apps/contactsBook/cb_get.c
index e82d75c..4f1c00a 100755
--- a/apps/contactsBook/cb_get.c
+++ b/apps/contactsBook/cb_get.c
@@ -35,7 +35,7 @@
/*
-
+
*/
@@ -65,10 +65,9 @@ static void out_const_str(const unsigned char /*CONST_VAR*/ *str) {
}
}
-static char doGet(struct args_t *args) {
+static char doGetContacts(struct args_t *args) {
uint16_t i = 0;
uint16_t n = CONST_UI16(n_contacts);
-
out_const_str(str0);
for(i=0; i
+
+
+
+
+
+
+*/
+
+#include "elf_allocator.h"
+
+#include "elfloader-otf.h"
+#include "codeprop-otf.h"
+#include "RamFileSystem.h"
+
+#include "application.h"
+
+struct file_t {
+ char *filename;
+ uint16_t size;
+};
+
+/* elf loader*/
+const char *elf_loader_return_labels[] = {
+ "ok", "Bad Elf Header", "No Symbol Table", "No String Table", "No Text section", "Symbol not found", "Segment not found", "No StartPoint",
+ "Unhandled Relocation", "Out Of Range", "Relocation Not Sorted", "Input Error", "Output Error"
+};
+
+
+/* Storage buffer */
+#define STORAGE_BUFFER_SIZE 512
+
+static uint8_t storage_buffer[STORAGE_BUFFER_SIZE];
+
+void flash_dump() {
+ int i, index, maxInfosPerLine;
+ int allocatorSize = 256;
+ char *flash = (char *)elf_allocator_storage;
+
+ maxInfosPerLine = 16;
+
+ printf("\r\nFlash Dump:\r\n");
+ printf("---------\r\n");
+
+ index = 0;
+ while(allocatorSize > maxInfosPerLine) {
+
+ printf("%p ", flash + index);
+
+ for(i = 0; i < maxInfosPerLine; i++, index++)
+ printf("%02X, ", flash[index]);
+
+ printf("\r\n");
+ allocatorSize -= maxInfosPerLine;
+ }
+
+ if(allocatorSize>0) {
+ printf("%p ", flash + index);
+ for(i = 0; i < allocatorSize; i++, index++)
+ printf("%02X, ", flash[index]);
+ printf("\r\n");
+ }
+
+ printf("\r\n");
+}
+extern char _text_end;
+/*-----------------------------------------------------------------------------*/
+static char initElfLoader() {
+
+ elf_applications_init(elf_allocator_flash_alloc, NULL);
+ printf("text end %p\r\n", &_text_end);
+ return 1;
+}
+
+/*-----------------------------------------------------------------------------*/
+static char doPostIn(uint8_t content_type, /*uint16_t content_length,*/ uint8_t call_number,
+ char *filename, void **post_data) {
+ uint16_t i = 0;
+ uint16_t j = 0;
+ uint16_t k = 0;
+ short value;
+ printf("%s IN\r\n", __FUNCTION__);
+
+ if(!filename) return 1;
+
+ // Leave when data is already available..
+ if(*post_data) return 1;
+
+ struct file_t *file = mem_alloc(sizeof(struct file_t));
+ if(!file)
+ return 1;
+
+ /* Filename */
+ while(filename[i++] != '\0');
+
+ file->filename = mem_alloc(i * sizeof(char));
+ if(!file->filename) {
+ mem_free(file, sizeof(struct file_t));
+ return 1;
+ }
+
+ i = 0;
+ do {
+ file->filename[i] = filename[i];
+ }while(filename[i++] != '\0');
+
+ /* Size + storage */
+ i = 0;
+ while((value = in()) != -1) {
+ /*printf("%d\r\n", i);*/
+
+ if(j < STORAGE_BUFFER_SIZE) {
+ storage_buffer[j] = value;
+ j++;
+ } else {
+
+ /* Commit buffer */
+ if(APPLICATION_WRITE(((uint8_t *)elf_allocator_storage) + k, storage_buffer, STORAGE_BUFFER_SIZE) != 0) {
+ printf("An error happened while flashing elf to storage\r\n");
+ return 1;
+ }
+
+ k += STORAGE_BUFFER_SIZE;
+ printf("%d\r\n", k);
+ storage_buffer[0] = value;
+ j = 1;
+ }
+
+ i++;
+ }
+
+ if(j > 0) {
+ if(APPLICATION_WRITE(((uint8_t *)elf_allocator_storage) + k, storage_buffer, j) != 0) {
+ printf("An error happened while flashing elf to storage\r\n");
+ return 1;
+ }
+ }
+ file->size = i;
+
+ //printf("File Size is %d\r\n", file->size);
+
+
+ *post_data = file;
+ printf("%s OUT\r\n", __FUNCTION__);
+ return 1;
+}
+
+void clean_up(struct file_t *file) {
+ uint16_t i = 0;
+ while(file->filename[i++] != '\0');
+
+ mem_free(file->filename, i * sizeof(char));
+ mem_free(file, sizeof(struct file_t));
+}
+
+/*-----------------------------------------------------------------------------*/
+static char doPostOut(uint8_t content_type, void *data) {
+
+ printf("%s IN\r\n", __FUNCTION__);
+ if(data) {
+
+ uint16_t i;
+ struct file_t *file = (struct file_t*)data;
+ void *storage_handle;
+ int loading;
+
+ storage_handle = rfs_open((void *)elf_allocator_storage);
+
+ if(storage_handle == NULL) {
+ out_str("Unable to open elf storage");
+ clean_up(file);
+ return 1;
+ }
+
+ elfloader_init();
+ printf("ElfLoader loading...\r\n");
+ loading = elfloader_load(storage_handle, codeprop_output);
+
+ printf("Loading = %d\r\n", loading);
+ if(loading == ELFLOADER_OK) {
+ /*flash_dump();*/
+ printf("Elf Application Environment is %p\r\n", elf_application_environment);
+
+ printf("Install function is %p\r\n", elf_application_environment->install);
+ printf("Remove function is %p\r\n", elf_application_environment->remove);
+ printf("URLS Tree is %p\r\n", elf_application_environment->urls_tree);
+ printf("Resources index is %p\r\n", elf_application_environment->resources_index);
+
+ printf("Resources index[0] %p\r\n", elf_application_environment->resources_index[0]);
+ printf("Resources index[1] %p\r\n", elf_application_environment->resources_index[1]);
+ printf("Resources index[2] %p\r\n", elf_application_environment->resources_index[2]);
+ printf("Resources index[3] %p\r\n", elf_application_environment->resources_index[3]);
+
+ if(!application_add(file->filename, file->size, data_address, data_size, elf_application_environment)) {
+ out_str("Failed to add application ");
+ out_str(file->filename);
+ out_str(".");
+ printf("Failed to add application %s.\r\n", file->filename);
+ clean_up(file);
+ return 1;
+ }
+
+ out_str("The file \"");
+ out_str(file->filename);
+ out_str("\" has been uploaded successfully (");
+ out_uint(file->size);
+ out_str(" bytes)\n");
+
+ } else {
+
+ if(loading < 0) {
+ out_str("An internal error happened\r\n");
+ } else {
+ out_str("An error happened while loading ");
+ out_str(file->filename);
+ out_str(" : ");
+ out_str(elf_loader_return_labels[loading]);
+ }
+
+ rfs_close(storage_handle);
+ clean_up(file);
+
+ }
+
+ } else
+ out_str("Please provide a file");
+
+ printf("%s OUT\r\n", __FUNCTION__);
+ return 1;
+}
diff --git a/apps/elfloader/ElfMonitor.c b/apps/elfloader/ElfMonitor.c
new file mode 100644
index 0000000..f82d3ad
--- /dev/null
+++ b/apps/elfloader/ElfMonitor.c
@@ -0,0 +1,52 @@
+/*
+
+
+
+
+*/
+
+#include "../../core/elf_application.h"
+
+static CONST_VAR(unsigned char, fields_names[5][16]) = {
+ {"name"},
+ {"size"},
+};
+
+static CONST_VAR(unsigned char, str0[]) = "[";
+static CONST_VAR(unsigned char, str1[]) = "{";
+static CONST_VAR(unsigned char, str2[]) = ":\"";
+static CONST_VAR(unsigned char, str3[]) = "\",";
+static CONST_VAR(unsigned char, str4[]) = "},";
+static CONST_VAR(unsigned char, str5[]) = "]";
+
+static void out_const_str(const unsigned char /*CONST_VAR*/ *str) {
+ const unsigned char *c = str;
+ unsigned char tmp;
+ while((tmp = CONST_READ_UI8(c++))!='\0'){
+ out_c(tmp);
+ }
+}
+
+static char doGetApplis(struct args_t *args) {
+ out_const_str(str0);
+
+ FOR_EACH_APPLICATION(appli,
+
+ out_const_str(str1);
+
+ out_const_str(fields_names[0]);
+ out_const_str(str2);
+ out_const_str(appli->filename);
+ out_const_str(str3);
+
+ out_const_str(fields_names[1]);
+ out_const_str(str2);
+ out_uint(appli->size);
+ out_const_str(str3);
+
+ out_const_str(str4);
+ )
+
+ out_const_str(str5);
+ return 1;
+}
diff --git a/apps/elfloader/RamFileSystem.c b/apps/elfloader/RamFileSystem.c
new file mode 100644
index 0000000..7fbe9cc
--- /dev/null
+++ b/apps/elfloader/RamFileSystem.c
@@ -0,0 +1,53 @@
+
+#ifdef LINUX
+#include
+#include
+#else
+#include
+#endif
+
+#include "tinyLibC.h"
+
+struct RamFileSystem {
+ const char *base;
+ const char *current;
+};
+
+struct RamFileSystem RFS = {
+ NULL, NULL
+};
+
+void *rfs_open(const char *aMemoryBank) {
+ RFS.base = aMemoryBank;
+ RFS.current = aMemoryBank;
+ return &RFS;
+}
+
+void rfs_close(void *aHandle) {
+ RFS.base = 0;
+ RFS.current = 0;
+}
+
+int rfs_tell(const void *aHandle) {
+ const struct RamFileSystem *rfs = (struct RamFileSystem *)aHandle;
+ return (rfs->current - rfs->base);
+}
+
+int rfs_seek(void *aHandle, int anOffset) {
+ struct RamFileSystem *rfs = (struct RamFileSystem *)aHandle;
+ rfs->current = rfs->base + anOffset;
+
+ return anOffset;
+}
+
+int rfs_write(const void *aBuffer, int aLength, int aCount, void *aHandle) {
+ return -1;
+}
+
+int rfs_read(void *aBuffer, int aLength, int aCount, void *aHandle) {
+ struct RamFileSystem *rfs = (struct RamFileSystem *)aHandle;
+
+ memcpy(aBuffer, rfs->current, aLength * aCount);
+ rfs->current += aLength * aCount;
+ return (aLength * aCount);
+}
diff --git a/apps/elfloader/RamFileSystem.h b/apps/elfloader/RamFileSystem.h
new file mode 100644
index 0000000..d9ba0ad
--- /dev/null
+++ b/apps/elfloader/RamFileSystem.h
@@ -0,0 +1,12 @@
+#ifndef __RAM_FILE_SYSTEM_H__
+#define __RAM_FILE_SYSTEM_H__
+
+extern void *rfs_open(const char *aMemoryBank);
+extern void rfs_close(void *aHandle);
+
+extern int rfs_tell(const void *aHandle);
+extern int rfs_seek(void *handle, int anOffset);
+extern int rfs_write(const void *aBuffer, int aLength, int aCount, void *aHandle);
+extern int rfs_read(void *aBuffer, int aLength, int aCount, void *aHandle);
+
+#endif
diff --git a/apps/elfloader/application.c b/apps/elfloader/application.c
new file mode 100644
index 0000000..79e96eb
--- /dev/null
+++ b/apps/elfloader/application.c
@@ -0,0 +1,88 @@
+#include "application.h"
+#include "elf_allocator.h"
+#include "tinyLibC.h"
+
+static struct elf_application_t application_buffer;
+
+char application_add(const char *filename, uint16_t size,
+ char *data_address, unsigned int data_size,
+ struct elf_application_environment_t *environment) {
+ struct elf_application_t *applicationInFlash;
+ char res;
+ int filenameLength;
+ char *data_source;
+
+ if((filename == NULL) || (size == 0) || (environment == NULL))
+ return 0;
+
+ data_source = NULL;
+ if(data_size > 0) {
+ data_source = (char *)elf_allocator_flash_alloc(data_size);
+ if(APPLICATION_WRITE(data_source, data_address, data_size) != 0) {
+ printf("FAILED to allocate data storage\r\n");
+ return 0;
+ }
+ }
+
+ if(environment->install) {
+ int i = 0;
+ while(environment->install[i] != NULL) {
+ res = environment->install[i]();
+ if(res != 0) {
+ printf("Application %s failed to install (%d).\r\n", filename, res);
+ return 0;
+ }
+ i++;
+ }
+ }
+
+ /* Fill the application structure */
+ /* +1 to keep the '\0' character */
+ filenameLength = strlen(filename) + 1;
+ application_buffer.filename = elf_allocator_flash_alloc(filenameLength);
+ if(APPLICATION_WRITE(application_buffer.filename, filename, filenameLength) != 0) {
+ printf("FAILED TO WRITE application filename\r\n");
+ return 0;
+ }
+
+ printf("Application name is %s\r\n", application_buffer.filename);
+
+ application_buffer.size = size;
+ application_buffer.environment = environment;
+ application_buffer.parsing = NULL;
+ application_buffer.data_destination = data_address;
+ application_buffer.data_source = data_source;
+ application_buffer.data_size = data_size;
+
+ applicationInFlash = (struct elf_application_t *)elf_allocator_flash_alloc(sizeof(struct elf_application_t));
+
+ res = APPLICATION_WRITE(applicationInFlash, &application_buffer, sizeof(struct elf_application_t));
+
+ printf("Application In Flash : name %s, size %d, environment %p, parsing : %p\r\n",
+ applicationInFlash->filename, applicationInFlash->size, applicationInFlash->environment, applicationInFlash->parsing);
+
+ return elf_application_add(applicationInFlash);
+}
+
+void application_remove(const char *filename) {
+ if(all_applications != NULL) {
+ struct elf_application_t *application = all_applications;
+ while(application) {
+ if(strcmp(filename, application->filename) == 0) {
+
+ elf_application_remove(application);
+
+ if(application->environment->remove) {
+ int i = 0;
+ while(application->environment->remove[i] != NULL) {
+ application->environment->remove[i]();
+ i++;
+ }
+ }
+ // @WARNING We should deallocate memory here but doesn't have any free function in elf_allocator.
+ return;
+ }
+ application = application->next;
+ }
+ }
+}
diff --git a/apps/elfloader/application.h b/apps/elfloader/application.h
new file mode 100644
index 0000000..f8b7638
--- /dev/null
+++ b/apps/elfloader/application.h
@@ -0,0 +1,9 @@
+#ifndef __APPLICATION_H__
+#define __APPLICATION_H__
+
+#include "../../core/elf_application.h"
+
+extern char application_add(const char *filename, uint16_t size,char *data_address, unsigned int data_size, struct elf_application_environment_t *environment);
+extern void application_remove(const char *filename);
+
+#endif
diff --git a/apps/elfloader/codeprop-otf.h b/apps/elfloader/codeprop-otf.h
new file mode 100644
index 0000000..4fbe14c
--- /dev/null
+++ b/apps/elfloader/codeprop-otf.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: codeprop-otf.h,v 1.1 2009/07/11 14:18:50 ksb Exp $
+ */
+#ifndef __CODEPROP_H__
+#define __CODEPROP_H__
+
+/* Segment writing object */
+extern struct elfloader_output *codeprop_output;
+
+#endif /* __CODEPROP_H__ */
diff --git a/apps/elfloader/elfScript.js b/apps/elfloader/elfScript.js
new file mode 100644
index 0000000..60479d8
--- /dev/null
+++ b/apps/elfloader/elfScript.js
@@ -0,0 +1,57 @@
+var applications = null;
+var fields = ["name","size"];
+var table = null;
+
+function setCellText(cell,cellValue) {
+ if(cellValue != "") {
+ var aText = document.createTextNode(cellValue);
+ cell.appendChild(aText);
+ } else {
+ cell.innerHTML = " ";
+ }
+}
+
+function addTableLine(i) {
+ var tr = document.createElement("tr");
+ tr.id = "application_" + i;
+ table.appendChild(tr);
+ for (j in fields) {
+ var td = document.createElement("td");
+ td.id = "td_" + i + "_" + j;
+ var str = eval("applications[i]." + fields[j]);
+ str = unescape(str);
+ setCellText(td,str);
+ tr.appendChild(td);
+ }
+}
+
+function updateApplications() {
+ table = document.getElementById("applicationsTable");
+ for(var i in applications) {
+ addTableLine(i);
+ }
+}
+
+function initFields(xhr) {
+ if(xhr.readyState == 4 && xhr.status == 200) {
+ applications = eval('(' + xhr.responseText + ')');
+ updateApplications();
+ }
+}
+
+function ajaxGet(url,callBack,arg) {
+ var xhr;
+ var chart = this;
+ var xhrTimer;
+ try{ xhr = new XMLHttpRequest(); }
+ catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); }
+ xhr.onreadystatechange = function(){
+ if(callBack) callBack(xhr,arg);
+ };
+ xhr.open("GET", url, true);
+ xhr.send(null);
+}
+
+function init() {
+ ajaxGet('ElfMonitor',initFields);
+}
diff --git a/apps/elfloader/elf_allocator.c b/apps/elfloader/elf_allocator.c
new file mode 100644
index 0000000..7096217
--- /dev/null
+++ b/apps/elfloader/elf_allocator.c
@@ -0,0 +1,47 @@
+#include "elf_allocator.h"
+
+/* RAM */
+#ifndef ELF_ALLOCATOR_RAM_SIZE
+#define ELF_ALLOCATOR_RAM_SIZE 1024*10
+#endif
+
+/* FLASH */
+#ifndef ELF_ALLOCATOR_FLASH_ADDRESS
+#define ELF_ALLOCATOR_FLASH_ADDRESS ((char *)0x00001000)
+#endif
+
+#ifndef ELF_ALLOCATOR_FLASH_STORAGE_ADDRESS
+#define ELF_ALLOCATOR_FLASH_STORAGE_ADDRESS ((char *)0x0000C000)
+#endif
+
+
+static char elf_allocator_ram_buffer[ELF_ALLOCATOR_RAM_SIZE];
+static char *elf_allocator_last_ram_used = 0;
+
+const char *elf_allocator_flash_buffer = ELF_ALLOCATOR_FLASH_ADDRESS;
+static char *elf_allocator_last_flash_used = 0;
+
+
+const void * elf_allocator_storage = ELF_ALLOCATOR_FLASH_STORAGE_ADDRESS;
+
+void *elf_allocator_ram_alloc(unsigned int size) {
+ char *result;
+ if(elf_allocator_last_ram_used == 0)
+ elf_allocator_last_ram_used = elf_allocator_ram_buffer;
+
+ result = elf_allocator_last_ram_used;
+ elf_allocator_last_ram_used += size;
+
+ return result;
+}
+
+void *elf_allocator_flash_alloc(unsigned int size) {
+ char *result;
+ if(elf_allocator_last_flash_used == 0)
+ elf_allocator_last_flash_used = (char *)elf_allocator_flash_buffer;
+
+ result = elf_allocator_last_flash_used;
+ elf_allocator_last_flash_used += ((size & 1) == 0) ? size : size + 1; // align on an even address
+
+ return result;
+}
diff --git a/apps/elfloader/elf_allocator.h b/apps/elfloader/elf_allocator.h
new file mode 100644
index 0000000..450f38e
--- /dev/null
+++ b/apps/elfloader/elf_allocator.h
@@ -0,0 +1,10 @@
+#ifndef __ELF_ALLOCATOR_H__
+#define __ELF_ALLOCATOR_H__
+
+extern const void * elf_allocator_storage;
+
+extern void *elf_allocator_ram_alloc(unsigned int size);
+
+extern void *elf_allocator_flash_alloc(unsigned int size);
+
+#endif
diff --git a/apps/elfloader/elfloader-arch-otf.h b/apps/elfloader/elfloader-arch-otf.h
new file mode 100644
index 0000000..f072264
--- /dev/null
+++ b/apps/elfloader/elfloader-arch-otf.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * Copyright (c) 2007, Simon Berg
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: elfloader-arch-otf.h,v 1.1 2009/07/11 14:18:50 ksb Exp $
+ */
+/**
+ * \addtogroup elfloader
+ * @{
+ */
+
+/**
+ * \defgroup elfloaderarch Architecture specific functionality for the ELF loader.
+ *
+ * The architecture specific functionality for the Contiki ELF loader
+ * has to be implemented for each processor type Contiki runs on.
+ *
+ * Since the ELF format is slightly different for different processor
+ * types, the Contiki ELF loader is divided into two parts: the
+ * generic ELF loader module (\ref elfloader) and the architecture
+ * specific part (this module). The architecture specific part deals
+ * with memory allocation, code and data relocation, and writing the
+ * relocated ELF code into program memory.
+ *
+ * To port the Contiki ELF loader to a new processor type, this module
+ * has to be implemented for the new processor type.
+ *
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the architecture specific parts of the Contiki ELF loader.
+ *
+ * \author
+ * Adam Dunkels
+ *
+ */
+
+#ifndef __ELFLOADER_ARCH_H__
+#define __ELFLOADER_ARCH_H__
+
+#include "elfloader-otf.h"
+
+
+/**
+ * \brief Perform a relocation.
+ * \param output The output object for the segment.
+ * \param sectionoffset The file offset at which the relocation can be found.
+ * \param sectionaddr The section start address (absolute runtime).
+ * \param rela A pointer to an ELF32 rela structure (struct elf32_rela).
+ * \param addr The relocated address.
+ *
+ * This function is called from the Contiki ELF loader to
+ * perform a relocation on a piece of code or data. The
+ * relocated address is calculated by the Contiki ELF
+ * loader, based on information in the ELF file, and it is
+ * the responsibility of this function to patch the
+ * executable code. The Contiki ELF loader passes a
+ * pointer to an ELF32 rela structure (struct elf32_rela)
+ * that contains information about how to patch the
+ * code. This information is different from processor to
+ * processor.
+ */
+int elfloader_arch_relocate(void *input_fd,
+ struct elfloader_output *output,
+ unsigned int sectionoffset,
+ char *sectionaddr,
+ struct elf32_rela *rela, char *addr,
+ struct elf32_sym *symbol);
+
+#endif /* __ELFLOADER_ARCH_H__ */
+
+/** @} */
+/** @} */
diff --git a/apps/elfloader/elfloader-arm.c b/apps/elfloader/elfloader-arm.c
new file mode 100644
index 0000000..627bd50
--- /dev/null
+++ b/apps/elfloader/elfloader-arm.c
@@ -0,0 +1,181 @@
+#include
+#include "elfloader-arch-otf.h"
+
+#include "RamFileSystem.h"
+
+#if 1
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...) do {} while (0)
+#endif
+
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+
+
+/*Elf32_ST_TYPE*/
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+#define STT_LOPROC 13
+#define STT_HIPROC 15
+
+#define ELF32_ST_TYPE(i) ((i)&0xf)
+
+
+/* Supported relocations */
+#define R_ARM_ABS32 2
+#define R_ARM_THM_CALL 10
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+
+struct mov_relocation_data {
+ int offsets[4];
+ int mask;
+};
+
+const struct mov_relocation_data movw_relocation_data = {
+ {12, 11, 8, 0}, 0xFFFF
+};
+
+const struct mov_relocation_data movt_relocation_data = {
+ {28, 27, 24, 16}, 0xFFFF0000
+};
+
+/* Adapted from elfloader-avr.c */
+int
+elfloader_arch_relocate(void *input_fd,
+ struct elfloader_output *output,
+ unsigned int sectionoffset,
+ char *sectionaddr,
+ struct elf32_rela *rela, char *addr,
+ struct elf32_sym *symbol)
+{
+ unsigned int type;
+
+ type = ELF32_R_TYPE(rela->r_info);
+ rfs_seek(input_fd, sectionoffset + rela->r_offset);
+
+/* PRINTF("elfloader_arch_relocate: type %d\n", type);
+ PRINTF("Addr: %p, Addend: %ld\n", addr, rela->r_addend); */
+ switch(type) {
+ case R_ARM_ABS32:
+ {
+ int32_t addend;
+ rfs_read((char*)&addend, 4, 1, input_fd);
+ addr += addend;
+ elfloader_output_write_segment(output,(char*) &addr, 4);
+ /*printf("%p: addr: %p addend %p\r\n", sectionaddr +rela->r_offset,
+ addr, addend);*/
+ }
+ break;
+
+ case R_ARM_THM_CALL: {
+ uint16_t instr[2];
+ int32_t offset;
+ int32_t addend;
+
+ rfs_read((char *)instr, 4, 1, input_fd);
+
+ // Build the addend from the instructions
+ addend = (instr[0] & 0x7FF) << 12 | (instr[1] & 0x7FF) << 1;
+
+ // Sign extent, when we have a negative number, we preserve it through shifting.
+ if(addend & (1<<22))
+ {
+ //printf("%x\r\n", addend);
+ addend |= 0xFF8<<20;
+ //printf("%x\r\n", addend);
+ }
+
+ //printf("R_ARM_THM_CALL addend : %x %d\r\n",addend, addend);
+ // S + A
+ offset = addend + (uint32_t)addr;
+
+ //printf("R_ARM_THM_CALL S + A : %x\r\n",offset);
+
+ if(ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) {
+ // (S + A) | T
+ offset |= 0x1;
+ //PRINTF("elfloader-arm.c: R_ARM_THM_CALL Symbol is STT_FUNC\r\n");
+ }
+
+ //printf("R_ARM_THM_CALL OFFSET (S + A) | T : %x\r\n",offset);
+
+ // ((S+A) | T) - P
+ offset = offset - ((uint32_t)sectionaddr + (rela->r_offset));
+
+ //printf("R_ARM_THM_CALL ((S+A) | T) - P: %x\r\n",offset);
+
+ instr[0] = ((offset >> 12) & 0x7FF) | 0xF000;
+ instr[1] = ((offset >> 1) & 0x7FF) | 0xF800;
+
+ /*printf("R_ARM_THM_CALL after relocation: %04x %04x\r\n",instr[0], instr[1]);*/
+ elfloader_output_write_segment(output, (char*)instr, 4);
+ }
+ break;
+
+
+ case R_ARM_THM_MOVW_ABS_NC :
+ case R_ARM_THM_MOVT_ABS : {
+ uint16_t instr[2];
+ uint32_t mask;
+ int16_t addend = 0;
+ uint32_t val;
+ const struct mov_relocation_data *mov_relocation_data =
+ ( type == R_ARM_THM_MOVW_ABS_NC ) ?
+ &movw_relocation_data : &movt_relocation_data;
+
+ rfs_read((char*)instr, 4, 1, input_fd);
+
+ /*PRINTF("elfloader-arm.c: relocation %d\r\n", type);
+ PRINTF("elfloader-arm.c: R_ARM_THM_MOV before relocation %x %x\r\n", instr[0], instr[1]);*/
+
+ // Build the 16 bit addend from the instructions
+ addend |= (instr[0] & 0xF) << 12;
+ addend |= ((instr[0] >> 10) & 0x1) << 11;
+ addend |= ((instr[1] >> 12) & 0x7) << 8;
+ addend |= instr[1] & 0xF;
+
+ /*printf("A: %x %d\r\n", addend, addend);
+ printf("S: %x %d\r\n", addr, addr);*/
+
+ // S + A
+ val = (uint32_t) addr + addend;
+ //printf("S+A %d %x\r\n", val, val);
+
+ if(type == R_ARM_THM_MOVW_ABS_NC) {
+ // We are in thumb mode, we just have to check whether the symbol type is STT_FUNC
+ if(ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) {
+ // (S + A) | T
+ val = val | 0x1;
+ //PRINTF("elfloader-arm.c: R_ARM_THM_MOVW_ABS_NC Symbol is STT_FUNC\r\n");
+ }
+ }
+
+ // Result_Mask
+ mask = val & mov_relocation_data->mask;
+
+ instr[0] &= ~0xF;
+ instr[0] |= (mask >> mov_relocation_data->offsets[0]) & 0xF;
+ instr[0] &= ~(1<<10);
+ instr[0] |= ((mask >> mov_relocation_data->offsets[1]) & 0x1)<<10;
+
+ instr[1] &= ~(0x7<<12);
+ instr[1] |= ((mask >> mov_relocation_data->offsets[2]) & 0x7)<<12;
+ instr[1] &= ~0xFF;
+ instr[1] |= (mask >> mov_relocation_data->offsets[3]) & 0xFF;
+
+ //PRINTF("elfloader-arm.c: R_ARM_THM_MOV after relocation %x %x\r\n", instr[0], instr[1]);
+ elfloader_output_write_segment(output, (char*)instr, 4);
+ }
+ break;
+
+ default:
+ printf("elfloader-arm.c: unsupported relocation type %d\n", type);
+ return ELFLOADER_UNHANDLED_RELOC;
+ }
+
+ return ELFLOADER_OK;
+}
diff --git a/apps/elfloader/elfloader-otf.c b/apps/elfloader/elfloader-otf.c
new file mode 100644
index 0000000..40b2128
--- /dev/null
+++ b/apps/elfloader/elfloader-otf.c
@@ -0,0 +1,848 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * Copyright (c) 2007, Simon Berg
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: elfloader-otf.c,v 1.1 2009/07/11 14:18:50 ksb Exp $
+ */
+
+#ifdef LINUX
+
+#include
+#include
+#include
+#include
+
+#else
+
+#include
+
+#endif
+
+#include "elfloader-otf.h"
+#include "elfloader-arch-otf.h"
+
+//#include "cfs/cfs.h"
+#include "RamFileSystem.h"
+#include "symtab.h"
+#include "tinyLibC.h"
+
+// For rodata linked list.
+#include "../../core/memory.h"
+
+/*#include
+#include
+#include */
+
+#if 0
+#include
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...) do {} while (0)
+//#define PRINTF(...) printf(__VA_ARGS__)
+#endif
+
+
+
+#define EI_NIDENT 16
+
+
+struct elf32_ehdr {
+ unsigned char e_ident[EI_NIDENT]; /* ident bytes */
+ elf32_half e_type; /* file type */
+ elf32_half e_machine; /* target machine */
+ elf32_word e_version; /* file version */
+ elf32_addr e_entry; /* start address */
+ elf32_off e_phoff; /* phdr file offset */
+ elf32_off e_shoff; /* shdr file offset */
+ elf32_word e_flags; /* file flags */
+ elf32_half e_ehsize; /* sizeof ehdr */
+ elf32_half e_phentsize; /* sizeof phdr */
+ elf32_half e_phnum; /* number phdrs */
+ elf32_half e_shentsize; /* sizeof shdr */
+ elf32_half e_shnum; /* number shdrs */
+ elf32_half e_shstrndx; /* shdr string index */
+};
+
+/* Values for e_type. */
+#define ET_NONE 0 /* Unknown type. */
+#define ET_REL 1 /* Relocatable. */
+#define ET_EXEC 2 /* Executable. */
+#define ET_DYN 3 /* Shared object. */
+#define ET_CORE 4 /* Core file. */
+
+struct elf32_shdr {
+ elf32_word sh_name; /* section name */
+ elf32_word sh_type; /* SHT_... */
+ elf32_word sh_flags; /* SHF_... */
+ elf32_addr sh_addr; /* virtual address */
+ elf32_off sh_offset; /* file offset */
+ elf32_word sh_size; /* section size */
+ elf32_word sh_link; /* misc info */
+ elf32_word sh_info; /* misc info */
+ elf32_word sh_addralign; /* memory alignment */
+ elf32_word sh_entsize; /* entry size if table */
+};
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends*/
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relation section without addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+struct elf32_rel {
+ elf32_addr r_offset; /* Location to be relocated. */
+ elf32_word r_info; /* Relocation type and symbol index. */
+};
+
+#define ELF32_R_SYM(info) ((info) >> 8)
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+
+
+struct relevant_section {
+ unsigned char number;
+ unsigned int offset;
+ char *address;
+};
+
+struct relevant_rodata_section {
+ unsigned char number;
+ unsigned int offset;
+ char *address;
+ struct relevant_rodata_section *next;
+};
+
+char elfloader_unknown[MAX_SYMBOL_SIZE]; /* Name that caused link error. */
+
+static struct relevant_section bss, data, rodata, text;
+
+const static unsigned char elf_magic_header[] =
+ {0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
+ 0x01, /* Only 32-bit objects. */
+ 0x01, /* Only LSB data. */
+ 0x01, /* Only ELF version 1. */
+ };
+
+#define COPY_SEGMENT_DATA_BUFFER_SIZE 128
+
+static char copy_segment_data_buffer[COPY_SEGMENT_DATA_BUFFER_SIZE];
+/* Copy data from the elf file to a segment */
+static int
+copy_segment_data(void *input_fd, unsigned int offset,
+ struct elfloader_output *output, unsigned int len)
+{
+ int res;
+
+ /*printf("Copy Segment Data IN input %p output %p buffer %p, len : %d\r\n", input_fd, output, buffer, len);*/
+
+ if (rfs_seek(input_fd, offset) != offset) return ELFLOADER_INPUT_ERROR;
+ while(len > sizeof(copy_segment_data_buffer)) {
+
+ res = rfs_read(copy_segment_data_buffer, sizeof(copy_segment_data_buffer), 1, input_fd);
+ if (res != sizeof(copy_segment_data_buffer)) return ELFLOADER_INPUT_ERROR;
+
+ res = elfloader_output_write_segment(output, copy_segment_data_buffer, sizeof(copy_segment_data_buffer));
+
+ if (res != sizeof(copy_segment_data_buffer)) return ELFLOADER_OUTPUT_ERROR;
+ len -= sizeof(copy_segment_data_buffer);
+
+ }
+
+ if (len)
+ {
+ res = rfs_read(copy_segment_data_buffer, len, 1, input_fd);
+ if (res != len) return ELFLOADER_INPUT_ERROR;
+ res = elfloader_output_write_segment(output, copy_segment_data_buffer, len);
+ if (res != len) return ELFLOADER_OUTPUT_ERROR;
+ }
+ /*printf("Copy Segment Data OUT input %p output %p\r\n", input_fd, output);*/
+
+ return ELFLOADER_OK;
+}
+
+static int
+seek_read(void *fd, unsigned int offset, char *buf, int len)
+{
+ if (rfs_seek(fd, offset) != offset) return -1;
+ return rfs_read(buf, len, 1, fd);
+}
+
+static void *
+find_local_symbol(void *input_fd, const char *symbol,
+ unsigned int symtab, unsigned short symtabsize,
+ unsigned int strtab,
+ struct relevant_rodata_section *rodatas)
+{
+ struct elf32_sym s;
+ unsigned int a;
+ char name[MAX_SYMBOL_SIZE];
+ struct relevant_section *sect;
+ int ret;
+
+ //printf("Symbol : %s\r\n", symbol);
+
+
+ for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
+ ret = seek_read(input_fd, a, (char *)&s, sizeof(s));
+ if (ret < 0) return NULL;
+
+ if(s.st_name != 0) {
+ ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
+ if (ret < 0) return NULL;
+
+ if(strcmp(name, symbol) == 0) {
+ if(s.st_shndx == bss.number) {
+ sect = &bss;
+ } else if(s.st_shndx == data.number) {
+ sect = &data;
+ } else if(s.st_shndx == text.number) {
+ sect = &text;
+ } else if(s.st_shndx == rodata.number){
+ sect = &rodata;
+ } else {
+ struct relevant_rodata_section *rodata = rodatas;
+ while(rodata) {
+ if(rodata->number == s.st_shndx) {
+ return &(rodata->address[s.st_value]);
+ }
+
+ rodata = rodata->next;
+ }
+ return NULL;
+ }
+
+ return &(sect->address[s.st_value]);
+ }
+ }
+ }
+ return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+static int
+relocate_section(void *input_fd,
+ struct elfloader_output *output,
+ unsigned int section, unsigned short size,
+ unsigned int sectionaddr,
+ char *sectionbase,
+ unsigned int strs,
+ unsigned int strtab,
+ unsigned int symtab, unsigned short symtabsize,
+ unsigned char using_relas,
+ struct relevant_rodata_section *rodatas)
+{
+ /* sectionbase added; runtime start address of current section */
+ struct elf32_rela rela; /* Now used both for rel and rela data! */
+ int rel_size = 0;
+ struct elf32_sym s;
+ unsigned int a;
+ char *addr;
+ struct relevant_section *sect;
+ int ret;
+ char name[MAX_SYMBOL_SIZE];
+
+ /* determine correct relocation entry sizes */
+ if(using_relas) {
+ rel_size = sizeof(struct elf32_rela);
+ } else {
+ rel_size = sizeof(struct elf32_rel);
+ }
+
+ addr = NULL;
+
+// printf("elfloader : Section %x size :%d relsize %d\r\n", section, size, rel_size);
+
+ for(a = section; a < section + size; a += rel_size) {
+ ret = seek_read(input_fd, a, (char *)&rela, rel_size);
+ if (ret < 0) return ELFLOADER_INPUT_ERROR;
+
+ ret = seek_read(input_fd,
+ (symtab +
+ sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
+ (char *)&s, sizeof(struct elf32_sym));
+
+ if (ret < 0) return ELFLOADER_INPUT_ERROR;
+
+ if(s.st_name != 0) {
+ char c;
+ int offset = 0;
+ rfs_seek(input_fd, strtab + s.st_name);
+
+ do {
+ rfs_read(&c, 1, 1, input_fd);
+ name[offset++] = c;
+ } while(c != '\0' && offset < sizeof(name));
+
+ /*ret = seek_read(input_fd, offset, name, sizeof(name));
+ if (ret < 0) return ELFLOADER_INPUT_ERROR;*/
+ if (offset >= sizeof(name)) return ELFLOADER_INPUT_ERROR;
+
+
+ addr = (char *)symtab_lookup(name);
+
+ /* ADDED */
+ if(addr == NULL) {
+ addr = find_local_symbol(input_fd, name, symtab, symtabsize, strtab, rodatas);
+ }
+
+ if(addr == NULL) {
+ if(s.st_shndx == bss.number) {
+ sect = &bss;
+ } else if(s.st_shndx == data.number) {
+ sect = &data;
+ } else if(s.st_shndx == rodata.number) {
+ sect = &rodata;
+ } else if(s.st_shndx == text.number ) {
+ sect = &text;
+ } else {
+ printf("elfloader unknown name: '%s'\n", name);
+ memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
+ elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
+ return ELFLOADER_SYMBOL_NOT_FOUND;
+ }
+ addr = sect->address;
+ }
+ } else {
+ if(s.st_shndx == bss.number) {
+ addr = bss.address;
+ } else if(s.st_shndx == data.number) {
+ addr = data.address;
+ } else if(s.st_shndx == rodata.number) {
+ addr = rodata.address;
+ } else if(s.st_shndx == text.number) {
+ addr = text.address;
+ } else {
+ struct relevant_rodata_section *rodata = rodatas;
+ while(rodata) {
+ if(rodata->number == s.st_shndx) {
+ addr = rodata->address;
+ break;
+ }
+
+ rodata = rodata->next;
+ }
+ }
+
+ if(addr == NULL) {
+ return ELFLOADER_SEGMENT_NOT_FOUND;
+ }
+ }
+
+#if 0 /* We don't know how big the relocation is or even if we need to read it.
+ Let the architecture dependant code decide */
+ if (!using_relas) {
+ /* copy addend to rela structure */
+ ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
+ if (ret < 0) return ELFLOADER_INPUT_ERROR;
+ }
+#endif
+ {
+ /* Copy data up to the next relocation */
+ unsigned int offset = elfloader_output_segment_offset(output);
+ if (rela.r_offset < offset) {
+ PRINTF("elfloader relocation out of offset order\r\n");
+
+ }
+ if (rela.r_offset > offset) {
+ ret = copy_segment_data(input_fd, offset+sectionaddr, output,
+ rela.r_offset - offset);
+
+ if (ret != ELFLOADER_OK) return ret;
+ }
+ }
+
+ ret = elfloader_arch_relocate(input_fd, output, sectionaddr, sectionbase,
+ &rela, addr, &s);
+
+
+ if (ret != ELFLOADER_OK) return ret;
+ }
+
+ return ELFLOADER_OK;
+}
+
+/*---------------------------------------------------------------------------*/
+void
+elfloader_init(void)
+{
+}
+/*---------------------------------------------------------------------------*/
+#if 0
+static void
+print_chars(unsigned char *ptr, int num)
+{
+ int i;
+ for(i = 0; i < num; ++i) {
+ PRINTF("%d", ptr[i]);
+ if(i == num - 1) {
+ PRINTF("\n");
+ } else {
+ PRINTF(", ");
+ }
+ }
+}
+#endif /* 0 */
+
+static int
+copy_segment(void *input_fd,
+ struct elfloader_output *output,
+ unsigned int section, unsigned short size,
+ unsigned int sectionaddr,
+ char *sectionbase,
+ unsigned int strs,
+ unsigned int strtab,
+ unsigned int symtab, unsigned short symtabsize,
+ unsigned char using_relas,
+ unsigned int seg_size, unsigned int seg_type,
+ struct relevant_rodata_section *rodatas)
+{
+ unsigned int offset;
+ int ret;
+
+ ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
+ if (ret != ELFLOADER_OK) return ret;
+
+ ret = relocate_section(input_fd, output,
+ section, size,
+ sectionaddr,
+ sectionbase,
+ strs,
+ strtab,
+ symtab, symtabsize, using_relas, rodatas);
+
+ if (ret != ELFLOADER_OK) return ret;
+
+ offset = elfloader_output_segment_offset(output);
+ ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
+
+ if (ret != ELFLOADER_OK) return ret;
+
+ return elfloader_output_end_segment(output);
+}
+
+static void cleanup_rodatas(struct relevant_rodata_section *rodatas) {
+ struct relevant_rodata_section *next_rodata;
+ struct relevant_rodata_section *temp_rodata;
+ temp_rodata = rodatas;
+ while(temp_rodata) {
+ next_rodata = temp_rodata->next;
+ mem_free(temp_rodata, sizeof(struct relevant_rodata_section));
+ temp_rodata = next_rodata;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+struct elf_application_environment_t *elf_application_environment;
+char *data_address;
+unsigned int data_size;
+
+
+int
+elfloader_load(void *input_fd, struct elfloader_output *output)
+{
+ struct elf32_ehdr ehdr;
+ struct elf32_shdr shdr;
+ struct elf32_shdr strtable;
+ unsigned int strs;
+ unsigned int shdrptr;
+ unsigned int nameptr;
+ char name[12];
+
+ int i;
+ unsigned short shdrnum, shdrsize;
+
+ unsigned char using_relas = -1;
+ unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
+ unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
+ unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
+ unsigned short symtaboff = 0, symtabsize;
+ unsigned short strtaboff = 0, strtabsize;
+ unsigned short bsssize = 0;
+
+ struct relevant_rodata_section *rodatas = NULL;
+ struct relevant_rodata_section *temp_rodata = NULL;
+
+ void *localSymbol;
+ int ret;
+
+ elfloader_unknown[0] = 0;
+
+ /* The ELF header is located at the start of the buffer. */
+ ret = seek_read(input_fd, 0, (char *)&ehdr, sizeof(ehdr));
+ if (ret != sizeof(ehdr)) return ELFLOADER_INPUT_ERROR;
+
+ /* print_chars(ehdr.e_ident, sizeof(elf_magic_header));
+ print_chars(elf_magic_header, sizeof(elf_magic_header));*/
+ /* Make sure that we have a correct and compatible ELF header. */
+ if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
+ PRINTF("ELF header problems\n");
+ return ELFLOADER_BAD_ELF_HEADER;
+ }
+
+ /* Grab the section header. */
+ shdrptr = ehdr.e_shoff;
+ ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
+ if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
+
+ /* Get the size and number of entries of the section header. */
+ shdrsize = ehdr.e_shentsize;
+ shdrnum = ehdr.e_shnum;
+
+ /* The string table section: holds the names of the sections. */
+ ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
+ (char *)&strtable, sizeof(strtable));
+ if (ret != sizeof(strtable)) return ELFLOADER_INPUT_ERROR;
+ /* Get a pointer to the actual table of strings. This table holds
+ the names of the sections, not the names of other symbols in the
+ file (these are in the sybtam section). */
+ strs = strtable.sh_offset;
+
+ /* Go through all sections and pick out the relevant ones. The
+ ".text" segment holds the actual code from the ELF file, the
+ ".data" segment contains initialized data, the ".rodata" segment
+ contains read-only data, the ".bss" segment holds the size of the
+ unitialized data segment. The ".rel[a].text" and ".rel[a].data"
+ segments contains relocation information for the contents of the
+ ".text" and ".data" segments, respectively. The ".symtab" segment
+ contains the symbol table for this file. The ".strtab" segment
+ points to the actual string names used by the symbol table.
+
+ In addition to grabbing pointers to the relevant sections, we
+ also save the section number for resolving addresses in the
+ relocator code.
+ */
+
+
+ /* Initialize the segment sizes to zero so that we can check if
+ their sections was found in the file or not. */
+ textsize = textrelasize = datasize = datarelasize =
+ rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
+
+ bss.number = data.number = rodata.number = text.number = -1;
+
+ bss.address = data.address = rodata.address = text.address = NULL;
+ bss.offset = data.offset = rodata.offset = text.offset = 0;
+
+ shdrptr = ehdr.e_shoff;
+
+ // first, find all .rodata.* sections
+ for(i = 0; i < shdrnum; ++i) {
+
+ ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
+ if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
+
+ /* The name of the section is contained in the strings table. */
+ nameptr = strs + shdr.sh_name;
+ ret = seek_read(input_fd, nameptr, name, sizeof(name));
+ if (ret != sizeof(name)) return ELFLOADER_INPUT_ERROR;
+
+ if(strncmp(name, ".rodata.str", 11) == 0) {
+
+ temp_rodata = mem_alloc(sizeof(struct relevant_rodata_section));
+ if(!temp_rodata) {
+ PRINTF("Unable to allocate relevant rodata section.\r\n");
+ return ELFLOADER_OUTPUT_ERROR;
+ }
+
+ temp_rodata->number = i;
+ temp_rodata->offset = shdr.sh_offset;
+
+ temp_rodata->address = (char *)
+ elfloader_output_alloc_segment(output, ELFLOADER_SEG_RODATA, shdr.sh_size);
+ if (!temp_rodata->address) {
+ PRINTF("Unable to allocate relevant rodata section space.\r\n");
+ return ELFLOADER_OUTPUT_ERROR;
+ }
+
+ printf("rodata.str allocated \r\n");
+
+ ret = elfloader_output_start_segment(output, ELFLOADER_SEG_RODATA,
+ temp_rodata->address, shdr.sh_size);
+ if(ret != ELFLOADER_OK) return ret;
+
+ copy_segment_data(input_fd, shdr.sh_offset, output, shdr.sh_size);
+
+ // Head insert
+ temp_rodata->next = rodatas;
+ rodatas = temp_rodata;
+ }
+
+ /* Move on to the next section header. */
+ shdrptr += shdrsize;
+ }
+
+ /*temp_rodata = rodatas;
+ while(temp_rodata) {
+ printf("Loaded RODATA %d\r\n", temp_rodata->number);
+
+ temp_rodata = temp_rodata->next;
+ }*/
+
+
+ // NOW the bss, data, text sections.
+ shdrptr = ehdr.e_shoff;
+
+ for(i = 0; i < shdrnum; ++i) {
+
+ ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
+ if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
+
+ /* The name of the section is contained in the strings table. */
+ nameptr = strs + shdr.sh_name;
+ ret = seek_read(input_fd, nameptr, name, sizeof(name));
+ if (ret != sizeof(name)) return ELFLOADER_INPUT_ERROR;
+
+ /* Match the name of the section with a predefined set of names
+ (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
+ .strtab). */
+ /* added support for .rodata, .rel.text and .rel.data). */
+
+
+ if(strcmp(name, ".text") == 0) {
+ textoff = shdr.sh_offset;
+ textsize = shdr.sh_size;
+ text.number = i;
+ text.offset = textoff;
+ } else if(strcmp(name, ".rel.text") == 0) {
+ using_relas = 0;
+ textrelaoff = shdr.sh_offset;
+ textrelasize = shdr.sh_size;
+ } else if(strcmp(name, ".rela.text") == 0) {
+ using_relas = 1;
+ textrelaoff = shdr.sh_offset;
+ textrelasize = shdr.sh_size;
+ } else if(strcmp(name, ".data") == 0) {
+ dataoff = shdr.sh_offset;
+ datasize = shdr.sh_size;
+ data.number = i;
+ data.offset = dataoff;
+ } else if(strcmp(name, ".rodata") == 0) {
+ /* read-only data handled the same way as regular text section */
+ rodataoff = shdr.sh_offset;
+ rodatasize = shdr.sh_size;
+ rodata.number = i;
+ rodata.offset = rodataoff;
+ } else if(strcmp(name, ".rel.rodata") == 0) {
+ /* using elf32_rel instead of rela */
+ using_relas = 0;
+ rodatarelaoff = shdr.sh_offset;
+ rodatarelasize = shdr.sh_size;
+ } else if(strcmp(name, ".rela.rodata") == 0) {
+ using_relas = 1;
+ rodatarelaoff = shdr.sh_offset;
+ rodatarelasize = shdr.sh_size;
+ } else if(strcmp(name, ".rel.data") == 0) {
+ /* using elf32_rel instead of rela */
+ using_relas = 0;
+ datarelaoff = shdr.sh_offset;
+ datarelasize = shdr.sh_size;
+ } else if(strcmp(name, ".rela.data") == 0) {
+ using_relas = 1;
+ datarelaoff = shdr.sh_offset;
+ datarelasize = shdr.sh_size;
+ } else if(strcmp(name, ".symtab") == 0) {
+ symtaboff = shdr.sh_offset;
+ symtabsize = shdr.sh_size;
+ } else if(strcmp(name, ".strtab") == 0) {
+ strtaboff = shdr.sh_offset;
+ strtabsize = shdr.sh_size;
+ } else if(strcmp(name, ".bss") == 0) {
+ bsssize = shdr.sh_size;
+ bss.number = i;
+ bss.offset = 0;
+ }
+
+ /* Move on to the next section header. */
+ shdrptr += shdrsize;
+ }
+
+ if(symtabsize == 0) {
+ return ELFLOADER_NO_SYMTAB;
+ }
+ if(strtabsize == 0) {
+ return ELFLOADER_NO_STRTAB;
+ }
+ if(textsize == 0) {
+ return ELFLOADER_NO_TEXT;
+ }
+
+
+ if (bsssize) {
+ bss.address = (char *)
+ elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
+ if (!bss.address) return ELFLOADER_OUTPUT_ERROR;
+ }
+
+
+ data_address = NULL;
+ data_size = 0;
+ if (datasize) {
+ data.address = (char *)
+ elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
+ if (!data.address) return ELFLOADER_OUTPUT_ERROR;
+
+ data_address = data.address;
+ data_size = datasize;
+ }
+ if (textsize) {
+ text.address = (char *)
+ elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
+ if (!text.address) return ELFLOADER_OUTPUT_ERROR;
+ }
+ if (rodatasize) {
+ rodata.address = (char *)
+ elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
+ /*printf("RODATA ADDRESS IS %p\r\n", rodata.address);*/
+ if (!rodata.address) return ELFLOADER_OUTPUT_ERROR;
+ }
+
+/* If we have text segment relocations, we process them. */
+ if(textrelasize > 0) {
+ PRINTF("elfloader: relocate text\r\n");
+ ret = copy_segment(input_fd, output,
+ textrelaoff, textrelasize,
+ textoff,
+ text.address,
+ strs,
+ strtaboff,
+ symtaboff, symtabsize, using_relas,
+ textsize, ELFLOADER_SEG_TEXT, rodatas);
+ if(ret != ELFLOADER_OK) {
+ PRINTF("elfloader: text failed\r\n");
+ return ret;
+ }
+ }
+
+ /* If we have any rodata segment relocations, we process them too. */
+ if(rodatarelasize > 0) {
+ PRINTF("elfloader: relocate rodata %d %d %d\r\n", rodatarelaoff, rodatarelasize, rodataoff);
+ ret = copy_segment(input_fd, output,
+ rodatarelaoff, rodatarelasize,
+ rodataoff,
+ rodata.address,
+ strs,
+ strtaboff,
+ symtaboff, symtabsize, using_relas,
+ rodatasize, ELFLOADER_SEG_RODATA, rodatas);
+ if(ret != ELFLOADER_OK) {
+ PRINTF("elfloader: data failed\r\n");
+ return ret;
+ }
+ } else {
+ // When no relocation is performed, we still have to copy the rodata values.
+ if(rodatasize) {
+ ret = elfloader_output_start_segment(output, ELFLOADER_SEG_RODATA,
+ rodata.address, rodatasize);
+ if(ret != ELFLOADER_OK) return ret;
+
+ copy_segment_data(input_fd, rodataoff, output, rodatasize);
+ }
+ }
+
+ /* If we have any data segment relocations, we process them too. */
+ if(datarelasize > 0) {
+ PRINTF("elfloader: relocate data\r\n");
+ ret = copy_segment(input_fd, output,
+ datarelaoff, datarelasize,
+ dataoff,
+ data.address,
+ strs,
+ strtaboff,
+ symtaboff, symtabsize, using_relas,
+ datasize, ELFLOADER_SEG_DATA, rodatas);
+ if(ret != ELFLOADER_OK) {
+ PRINTF("elfloader: data failed\n");
+ return ret;
+ }
+ ret = elfloader_output_end_segment(output);
+ if (ret != ELFLOADER_OK) return ret;
+ } else {
+ if(datasize) {
+ ret = elfloader_output_start_segment(output, ELFLOADER_SEG_DATA,
+ data.address, datasize);
+ if(ret != ELFLOADER_OK) return ret;
+
+ copy_segment_data(input_fd, dataoff, output, datasize);
+ }
+ }
+
+ /* Write text and rodata segment into flash and data segment into RAM. */
+/* elfloader_arch_write_rom(fd, textoff, textsize, text.address); */
+/* elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address); */
+
+ {
+ /* Write zeros to bss segment */
+ unsigned int len = bsssize;
+ static const char zeros[16] = {0};
+ ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
+ bss.address,bsssize);
+ if (ret != ELFLOADER_OK) return ret;
+ while(len > sizeof(zeros)) {
+ ret = elfloader_output_write_segment(output, zeros, sizeof(zeros));
+ if (ret != sizeof(zeros)) return ELFLOADER_OUTPUT_ERROR;
+ len -= sizeof(zeros);
+ }
+ ret = elfloader_output_write_segment(output, zeros, len);
+ if (ret != len) return ELFLOADER_OUTPUT_ERROR;
+ }
+
+ PRINTF("elfloader: elf application environment search\r\n");
+
+ localSymbol = find_local_symbol(input_fd, ELF_APPLICATION_ENVIRONMENT_NAME, symtaboff, symtabsize, strtaboff, rodatas);
+
+ cleanup_rodatas(rodatas);
+
+ if(localSymbol != NULL) {
+ PRINTF("elfloader: elf application environment %p\r\n", localSymbol);
+ elf_application_environment = (struct elf_application_environment_t *)localSymbol;
+
+ return ELFLOADER_OK;
+ }
+/*
+ PRINTF("elfloader: no autostart\n");
+ process = (struct process **) find_program_processes(fd, symtaboff, symtabsize, strtaboff);
+ if(process != NULL) {
+ PRINTF("elfloader: FOUND PRG\n");
+ }*/
+ PRINTF("elfloader: elf application environment not found\r\n");
+ return ELFLOADER_NO_STARTPOINT;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/apps/elfloader/elfloader-otf.h b/apps/elfloader/elfloader-otf.h
new file mode 100644
index 0000000..1339bdc
--- /dev/null
+++ b/apps/elfloader/elfloader-otf.h
@@ -0,0 +1,339 @@
+/**
+ * \addtogroup loader
+ * @{
+ */
+
+/**
+ * \defgroup elfloader The Contiki ELF loader
+ *
+ * The Contiki ELF loader links, relocates, and loads ELF
+ * (Executable Linkable Format) object files into a running Contiki
+ * system.
+ *
+ * ELF is a standard format for relocatable object code and executable
+ * files. ELF is the standard program format for Linux, Solaris, and
+ * other operating systems.
+ *
+ * An ELF file contains either a standalone executable program or a
+ * program module. The file contains both the program code, the
+ * program data, as well as information about how to link, relocate,
+ * and load the program into a running system.
+ *
+ * The ELF file is composed of a set of sections. The sections contain
+ * program code, data, or relocation information, but can also contain
+ * debugging information.
+ *
+ * To link and relocate an ELF file, the Contiki ELF loader first
+ * parses the ELF file structure to find the appropriate ELF
+ * sections. It then allocates memory for the program code and data in
+ * ROM and RAM, respectively. After allocating memory, the Contiki ELF
+ * loader starts relocating the code found in the ELF file.
+ *
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the Contiki ELF loader.
+ * \author
+ * Adam Dunkels
+ * Simon Berg
+ *
+ */
+
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * Copyright (c) 2007, Simon Berg
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ */
+
+#ifndef __ELFLOADER_H__
+#define __ELFLOADER_H__
+
+#include "../../core/elf_application.h"
+
+/**
+ * Return value from elfloader_load() indicating that loading worked.
+ */
+#define ELFLOADER_OK 0
+/**
+ * Return value from elfloader_load() indicating that the ELF file had
+ * a bad header.
+ */
+#define ELFLOADER_BAD_ELF_HEADER 1
+/**
+ * Return value from elfloader_load() indicating that no symbol table
+ * could be find in the ELF file.
+ */
+#define ELFLOADER_NO_SYMTAB 2
+/**
+ * Return value from elfloader_load() indicating that no string table
+ * could be find in the ELF file.
+ */
+#define ELFLOADER_NO_STRTAB 3
+/**
+ * Return value from elfloader_load() indicating that the size of the
+ * .text segment was zero.
+ */
+#define ELFLOADER_NO_TEXT 4
+/**
+ * Return value from elfloader_load() indicating that a symbol
+ * specific symbol could not be found.
+ *
+ * If this value is returned from elfloader_load(), the symbol has
+ * been copied into the elfloader_unknown[] array.
+ */
+#define ELFLOADER_SYMBOL_NOT_FOUND 5
+/**
+ * Return value from elfloader_load() indicating that one of the
+ * required segments (.data, .bss, or .text) could not be found.
+ */
+#define ELFLOADER_SEGMENT_NOT_FOUND 6
+/**
+ * Return value from elfloader_load() indicating that no starting
+ * point could be found in the loaded module.
+ */
+#define ELFLOADER_NO_STARTPOINT 7
+
+/**
+ * Return value from elfloader_load() indicating that the ELF file contained
+ * a relocation type that the implementation can't handle.
+ */
+#define ELFLOADER_UNHANDLED_RELOC 8
+
+/**
+ * Return value from elfloader_load() indicating that the offset for
+ * a relative addressing mode was too big.
+ */
+#define ELFLOADER_OUTOF_RANGE 9
+
+/**
+ * Return value from elfloader_load() indicating that the relocations
+ * where not sorted by offset
+ */
+#define ELFLOADER_RELOC_NOT_SORTED 10
+
+/**
+ * Return value from elfloader_load() indicating that reading from the
+ * ELF file failed in some way.
+ */
+#define ELFLOADER_INPUT_ERROR 11
+
+/**
+ * Return value from elfloader_load() indicating that writing to a segment
+ * failed.
+ */
+#define ELFLOADER_OUTPUT_ERROR 12
+
+
+#define ELFLOADER_SEG_TEXT 1
+#define ELFLOADER_SEG_RODATA 2
+#define ELFLOADER_SEG_DATA 3
+#define ELFLOADER_SEG_BSS 4
+
+#define MAX_SYMBOL_SIZE 128
+
+/**
+ * elfloader output object
+ *
+ * This object defines methods (callbacks) for writing the segments to memory.
+ * It can be extended by the user to include any necessary state.
+ */
+
+struct elfloader_output {
+ const struct elfloader_output_ops *ops;
+};
+/**
+ * \brief Allocate a new segment
+ * \param input The output object
+ * \param type Type of segment
+ * \param size Size of segment in bytes
+ * \return A pointer to the start of the segment.
+ *
+ * The returned address doesn't need to correspond to any real memory,
+ * since it's only used for calculating the relocations.
+ */
+
+void *elfloader_allocate_segment(struct elfloader_output *output,
+ unsigned int type, int size);
+
+/**
+ * \brief Start writing to a new segment
+ * \param input The output object
+ * \param type Type of segment
+ * \param addr Address of segment from elfloader_allocate_segment
+ * \param size Size of segment in bytes
+ * \return Returns ELFLOADER_OK if successful, otherwise an error code
+ *
+ */
+
+int elfloader_start_segment(struct elfloader_output *output,
+ unsigned int type, void *addr, int size);
+/**
+ * \brief Mark end of segment
+ * \param input The output object
+ * \return Zero if successful
+ */
+
+int elfloader_end_segment(struct elfloader_output *output);
+
+/**
+ * \brief Write data to a segment
+ * \param input The output object
+ * \param buf Data to be written
+ * \param len Length of data
+ * \return The number of bytes actually written, or negative if failed.
+ */
+
+int elfloader_write_segment(struct elfloader_output *output, const char *buf,
+ unsigned int len);
+
+/**
+ * \brief Get the current offset in the file where the next data will
+ * be written.
+ * \param input The output object
+ * \return The current offset.
+ */
+
+unsigned int elfloader_segment_offset(struct elfloader_output *output);
+
+#define elfloader_output_alloc_segment(output, type, size) \
+((output)->ops->allocate_segment(output, type, size))
+
+#define elfloader_output_start_segment(output, type, addr, size) \
+((output)->ops->start_segment(output, type, addr, size))
+
+#define elfloader_output_end_segment(output) \
+((output)->ops->end_segment(output))
+
+#define elfloader_output_write_segment(output, buf, len) \
+((output)->ops->write_segment(output, buf, len))
+
+/*
+#define elfloader_output_write_segment(output, buf, len) \
+(printf("%p %p %d\r\n", output, buf, len),((output)->ops->write_segment(output, buf, len)))
+*/
+
+#define elfloader_output_segment_offset(output) \
+((output)->ops->segment_offset(output))
+
+
+struct elfloader_output_ops {
+ void * (*allocate_segment)(struct elfloader_output *output,
+ unsigned int type, int size);
+ int (*start_segment)(struct elfloader_output *output,
+ unsigned int type, void *addr, int size);
+ int (*end_segment)(struct elfloader_output *output);
+ int (*write_segment)(struct elfloader_output *output, const char *buf,
+ unsigned int len);
+ unsigned int (*segment_offset)(struct elfloader_output *output);
+};
+
+
+/**
+ * elfloader initialization function.
+ *
+ * This function should be called at boot up to initilize the elfloader.
+ */
+void elfloader_init(void);
+
+/**
+ * \brief Load and relocate an ELF file.
+ * \param input Input object defining how to read from the ELF file
+ * \param output Output object defining how to create and write to seegments.
+ * \return ELFLOADER_OK if loading and relocation worked.
+ * Otherwise an error value.
+ *
+ * If the function is able to load the ELF file, a pointer
+ * to the process structure in the model is stored in the
+ * elfloader_loaded_process variable.
+ *
+ */
+int elfloader_load(void *input_fd,
+ struct elfloader_output *output);
+
+/**
+ * A pointer to the processes loaded with elfloader_load().
+ */
+/*extern struct process **elfloader_autostart_processes;*/
+#ifdef ELF_APPLICATION_ENVIRONMENT_NAME
+#undef ELF_APPLICATION_ENVIRONMENT_NAME
+#endif
+
+#define ELF_APPLICATION_ENVIRONMENT_NAME "elf_application_environment"
+
+extern struct elf_application_environment_t *elf_application_environment;
+extern char *data_address;
+extern unsigned int data_size;
+
+/**
+ * If elfloader_load() could not find a specific symbol, it is copied
+ * into this array.
+ */
+extern char elfloader_unknown[MAX_SYMBOL_SIZE];
+
+#ifdef ELFLOADER_CONF_DATAMEMORY_SIZE
+#define ELFLOADER_DATAMEMORY_SIZE ELFLOADER_CONF_DATAMEMORY_SIZE
+#else
+#define ELFLOADER_DATAMEMORY_SIZE 0x100
+#endif
+
+#ifdef ELFLOADER_CONF_TEXTMEMORY_SIZE
+#define ELFLOADER_TEXTMEMORY_SIZE ELFLOADER_CONF_TEXTMEMORY_SIZE
+#else
+#define ELFLOADER_TEXTMEMORY_SIZE 0x100
+#endif
+
+typedef unsigned long elf32_word;
+typedef signed long elf32_sword;
+typedef unsigned short elf32_half;
+typedef unsigned long elf32_off;
+typedef unsigned long elf32_addr;
+
+struct elf32_rela {
+ elf32_addr r_offset; /* Location to be relocated. */
+ elf32_word r_info; /* Relocation type and symbol index. */
+ elf32_sword r_addend; /* Addend. */
+};
+
+struct elf32_sym {
+ elf32_word st_name; /* String table index of name. */
+ elf32_addr st_value; /* Symbol value. */
+ elf32_word st_size; /* Size of associated object. */
+ unsigned char st_info; /* Type and binding information. */
+ unsigned char st_other; /* Reserved (not used). */
+ elf32_half st_shndx; /* Section index of symbol. */
+};
+
+
+#endif /* __ELFLOADER_H__ */
+
+/** @} */
+/** @} */
diff --git a/apps/elfloader/index.html b/apps/elfloader/index.html
new file mode 100644
index 0000000..772ef51
--- /dev/null
+++ b/apps/elfloader/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+ Smews Elf Loader
+
+
+
+
+
+ Welcome to the elf applications manager
+ Uploaded applications
+
+ Upload a file
+
+
+
+
diff --git a/apps/elfloader/ram-segments.c b/apps/elfloader/ram-segments.c
new file mode 100644
index 0000000..40aa0e0
--- /dev/null
+++ b/apps/elfloader/ram-segments.c
@@ -0,0 +1,139 @@
+#ifndef __RAM_SEGMENTS_C__1POIF5E8U4__
+#define __RAM_SEGMENTS_C__1POIF5E8U4__
+
+#include "elfloader-otf.h"
+#include "codeprop-otf.h"
+
+
+#include "elf_allocator.h"
+
+#include "tinyLibC.h"
+
+struct ram_output
+{
+ struct elfloader_output output;
+ char *base;
+ unsigned int offset, type;
+ void *text;
+ void *rodata;
+ void *data;
+ void *bss;
+ void *flashLimit;
+};
+
+static void *
+allocate_segment(struct elfloader_output * const output,
+ unsigned int type, int size)
+{
+ struct ram_output * const ram = (struct ram_output *)output;
+
+ switch(type) {
+ case ELFLOADER_SEG_TEXT:
+ /*if (ram->text) mem_free(ram->text, ram->textSize);*/
+ ram->text = elf_allocator_flash_alloc(size);
+ return ram->text;
+
+ case ELFLOADER_SEG_RODATA:
+ /*if (ram->rodata) free(ram->rodata, ram->rodataSize);*/
+ ram->rodata = elf_allocator_flash_alloc(size);
+ return ram->rodata;
+
+ case ELFLOADER_SEG_DATA:
+ /*if (ram->data) free(ram->data, ram->dataSize);*/
+ ram->data = elf_allocator_ram_alloc(size);
+ return ram->data;
+
+ case ELFLOADER_SEG_BSS:
+ /*if (ram->bss) free(ram->bss, ram->bssSize);*/
+ ram->bss = elf_allocator_ram_alloc(size);
+ return ram->bss;
+ }
+ return 0;
+}
+
+static int
+start_segment(struct elfloader_output *output,
+ unsigned int type, void *addr, int size)
+{
+ ((struct ram_output*)output)->base = addr;
+ ((struct ram_output*)output)->offset = 0;
+ ((struct ram_output*)output)->type = type;
+ return ELFLOADER_OK;
+}
+
+static int
+end_segment(struct elfloader_output *output)
+{
+ return ELFLOADER_OK;
+}
+
+static int
+write_segment(struct elfloader_output *output, const char *buf,
+ unsigned int len)
+{
+ struct ram_output * const memory = (struct ram_output *)output;
+ printf("ram-segments.write Base %p + Ram Offset %x = %p (%d bytes)\r\n", memory->base, memory->offset, memory->base + memory->offset,len);
+ printf("Output->ops %p 0\r\n", output->ops);
+ switch(memory->type) {
+ case ELFLOADER_SEG_TEXT :
+ case ELFLOADER_SEG_RODATA : {
+ int ret;
+
+ if(memory->flashLimit) {
+ if( ((memory->base + memory->offset) <= (char *)memory->flashLimit) &&
+ ((memory->base + memory->offset + len) >= (char *)memory->flashLimit)) {
+ printf("No more available flash memory\r\n");
+ return -2;
+ }
+ }
+
+ printf("Output->ops %p 1 Memory %p\r\n", output->ops, memory->base + memory->offset);
+ ret = APPLICATION_WRITE(memory->base + memory->offset, buf, len);
+ printf("Output->ops %p 2\r\n", output->ops);
+ if(ret != 0) {
+ printf("An error happened while writing to flash %d\r\n", ret);
+ return ret;
+ }
+ }
+
+ break;
+ default :
+ fake_memcpy(memory->base + memory->offset, buf, len);
+ break;
+
+ }
+
+ memory->offset += len;
+
+ return len;
+}
+
+static unsigned int
+segment_offset(struct elfloader_output *output)
+{
+ return ((struct ram_output*)output)->offset;
+}
+
+static const struct elfloader_output_ops elf_output_ops =
+ {
+ allocate_segment,
+ start_segment,
+ end_segment,
+ write_segment,
+ segment_offset
+ };
+
+static struct ram_output seg_output = {
+ {&elf_output_ops},
+ 0, 0,
+ 0,
+ 0, 0, 0, 0, 0
+};
+
+struct elfloader_output *codeprop_output = &seg_output.output;
+
+void ram_segments_set_flash_limit(void *aLimit) {
+ seg_output.flashLimit = aLimit;
+}
+
+#endif /* __RAM_SEGMENTS_C__1POIF5E8U4__ */
diff --git a/apps/elfloader/ram-segments.h b/apps/elfloader/ram-segments.h
new file mode 100644
index 0000000..ef7f342
--- /dev/null
+++ b/apps/elfloader/ram-segments.h
@@ -0,0 +1,6 @@
+#ifndef __RAM_SEGMENTS_H__
+#define __RAM_SEGMENTS_H__
+
+extern void ram_segments_set_flash_limit(void *aLimit);
+
+#endif
diff --git a/apps/elfloader/style.css b/apps/elfloader/style.css
new file mode 100755
index 0000000..6ddb865
--- /dev/null
+++ b/apps/elfloader/style.css
@@ -0,0 +1,19 @@
+body {fill: #333333; color: #333333; font-family: sans-serif; font-size: 12pt; }
+h1 {text-align: center; font-weight: normal; font-size: 2em; }
+
+img { border: 0px; }
+a { color: #000000; text-decoration: none; }
+a:hover { color: #444466; text-decoration: underline; }
+
+#smewsLogo { display: block; text-align: center; }
+#contactsTable { position: relative; margin: 0 auto; border: 3px solid #444466; border-collapse: collapse; }
+#contactsTable td, #contactsTable th { padding: 5px; text-align: center; font-size: 0.9em; }
+#contactsTable th { border: 3px solid #444466; }
+#contactsTable td { border: 1px solid #666688; width: 10em; }
+#contactsTable tr { height: 2.4em; }
+#googleFrame { width: 450px; height: 250px; }
+#googleLink { font-size: 0.8em; float: right; }
+#smewsContact { position: absolute; background-color: #dddddd; padding: 6px; border: 2px solid black; }
+.fieldInput { width: 97%; }
+.busyCell { background-color: #bbffbb; }
+#adddel { color: #444466; font-weight: bold; font-size: 18px; text-align: center; }
diff --git a/apps/elfloader/symbols.c b/apps/elfloader/symbols.c
new file mode 100644
index 0000000..d897657
--- /dev/null
+++ b/apps/elfloader/symbols.c
@@ -0,0 +1,52 @@
+#include
+#include "symbols.h"
+#include "../../core/generators.h"
+#include "../../core/connections.h"
+#include "../../core/timers.h"
+#include "../../core/memory.h"
+
+
+const struct symbols symbols[] = {
+ {"get_all_connections", get_all_connections },
+ {"get_current_remote_ip", get_current_remote_ip },
+ {"get_local_ip", get_local_ip },
+#ifndef DISABLE_GP_IP_HANDLER
+ {"get_payload_size", get_payload_size },
+ {"get_protocol", get_protocol },
+#endif
+ {"get_remote_ip", get_remote_ip },
+
+#ifndef DISABLE_GP_IP_HANDLER
+ {"get_send_code", get_send_code },
+#endif
+
+#if !defined(DISABLE_POST) || !defined(DISABLE_GP_IP_HANDLER)
+ {"in", in },
+#endif
+ {"mem_alloc", mem_alloc },
+ {"mem_free", mem_free },
+ {"out_c", out_c },
+ {"out_str", out_str },
+ {"out_uint", out_uint },
+ {"printf", printf},
+
+ {"rand", rand },
+
+#ifndef DISABLE_GP_IP_HANDLER
+ {"request_packet_out_call", request_packet_out_call },
+#endif
+
+ {"rflpc_timer_get_counter", rflpc_timer_get_counter },
+
+#ifndef DISABLE_COMET
+ {"server_push", server_push},
+#endif
+#ifndef DISABLE_TIMERS
+ {"set_timer", set_timer},
+#endif
+ {"something_to_send", something_to_send },
+
+ {"srand", srand }
+};
+
+const int symbols_nelts = sizeof(symbols)/sizeof(struct symbols);
diff --git a/apps/elfloader/symbols.h b/apps/elfloader/symbols.h
new file mode 100644
index 0000000..e1e811e
--- /dev/null
+++ b/apps/elfloader/symbols.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: symbols.h,v 1.5 2007/01/30 18:04:59 bg- Exp $
+ */
+#ifndef __SYMBOLS_H__
+#define __SYMBOLS_H__
+
+struct symbols {
+ const char *name;
+ void *value;
+};
+
+extern const int symbols_nelts;
+
+extern const struct symbols symbols[/* symbols_nelts */];
+
+#endif /* __SYMBOLS_H__ */
diff --git a/apps/elfloader/symtab.c b/apps/elfloader/symtab.c
new file mode 100644
index 0000000..ce06a6c
--- /dev/null
+++ b/apps/elfloader/symtab.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: symtab.c,v 1.7 2007/01/24 16:13:50 adamdunkels Exp $
+ */
+
+#include "symtab.h"
+
+#include "symbols.h"
+
+#include "tinyLibC.h"
+
+/* Binary search is twice as large but still small. */
+#ifndef SYMTAB_CONF_BINARY_SEARCH
+#define SYMTAB_CONF_BINARY_SEARCH 1
+#endif
+
+/*---------------------------------------------------------------------------*/
+#if SYMTAB_CONF_BINARY_SEARCH
+void *
+symtab_lookup(const char *name)
+{
+ int start, middle, end;
+ int r;
+
+ start = 0;
+ end = symbols_nelts - 1; /* Last entry is { 0, 0 }. */
+ while(start <= end) {
+ /* Check middle, divide */
+ middle = (start + end) / 2;
+ r = strcmp(name, symbols[middle].name);
+ if(r < 0) {
+ end = middle - 1;
+ } else if(r > 0) {
+ start = middle + 1;
+ } else {
+ return symbols[middle].value;
+ }
+ }
+ return 0;
+}
+#else * SYMTAB_CONF_BINARY_SEARCH */
+void *
+symtab_lookup(const char *name)
+{
+ const struct symbols *s;
+
+ for(s = symbols; s->name != NULL; ++s) {
+ if(strcmp(name, s->name) == 0) {
+ return s->value;
+ }
+ }
+ return 0;
+}
+#endif /* SYMTAB_CONF_BINARY_SEARCH */
+/*---------------------------------------------------------------------------*/
diff --git a/apps/elfloader/symtab.h b/apps/elfloader/symtab.h
new file mode 100644
index 0000000..f01eb6b
--- /dev/null
+++ b/apps/elfloader/symtab.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * 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 Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * @(#)$Id: symtab.h,v 1.4 2007/01/12 13:55:05 bg- Exp $
+ */
+#ifndef __SYMTAB_H__
+#define __SYMTAB_H__
+
+void *symtab_lookup(const char *name);
+
+#endif /* __SYMTAB_H__ */
diff --git a/apps/elfloader/tinyLibC.c b/apps/elfloader/tinyLibC.c
new file mode 100644
index 0000000..9f77f68
--- /dev/null
+++ b/apps/elfloader/tinyLibC.c
@@ -0,0 +1,63 @@
+#include "tinyLibC.h"
+
+/* not written for speed*/
+int memcmp(const void *aPointer, const void *anotherPointer, int aSize) {
+ const char *pointer = (const char *) aPointer;
+ const char *nother = (const char *) aPointer;
+ int i = 0;
+ for(i = 0; i < aSize; i++) {
+ if(pointer[i] != nother[i])
+ return pointer[i] - nother[i];
+ }
+ return 0;
+}
+
+int strlen(const char *aString) {
+ int i = 0;
+ while(aString[i] != '\0')
+ i++;
+ return i;
+}
+
+int strcmp(const char *aString, const char *anotherString) {
+ while (*aString == *anotherString && *aString != '\0')
+ {
+ aString++;anotherString++;
+ }
+ return *aString - *anotherString;
+/*
+
+ int length = strlen(aString);
+ int diff = length - strlen(anotherString);
+ if(diff == 0)
+ return memcmp(aString, anotherString, length);
+ return diff;*/
+}
+
+char toLower(char aChar) {
+ if(aChar>= 'a' && (aChar <= 'z'))
+ return aChar;
+ return (aChar>= 'A' && (aChar <= 'Z')) ? aChar - 'A' + 'a' : aChar;
+}
+
+int strncmp(const char *aString, const char *anotherString, int aSize) {
+ while (*aString == *anotherString && *aString != '\0' && --aSize) {
+ aString++;anotherString++;
+ }
+ return *aString - *anotherString;
+/* int diff, i;
+ for(i = 0; i < aSize; i++) {
+ diff = toLower(aString[i]) - toLower(anotherString[i]);
+ if(diff != 0)
+ return diff;
+ }
+ return 0;*/
+}
+
+void fake_memcpy(void *dest, const void *source, int len) {
+ int i;
+ char * dst = (char *)dest;
+ const char *src = (const char *)source;
+ for(i = 0; i < len; i++)
+ dst[i] = src[i];
+}
diff --git a/apps/elfloader/tinyLibC.h b/apps/elfloader/tinyLibC.h
new file mode 100644
index 0000000..4d95840
--- /dev/null
+++ b/apps/elfloader/tinyLibC.h
@@ -0,0 +1,13 @@
+#ifndef __TINY_LIB_C_H__
+#define __TINY_LIB_C_H__
+
+#ifndef LINUX
+extern int memcmp(const void *aPointer, const void *anotherPointer, int aSize);
+extern int strlen(const char *aString);
+extern int strcmp(const char *aString, const char *anotherString);
+extern int strncmp(const char *aString, const char *anotherString, int aSize);
+extern char toLower(char aChar);
+extern void fake_memcpy(void *dest, const void *source, int len);
+#endif
+
+#endif
diff --git a/apps/kernel_console/kernel_console.c b/apps/kernel_console/kernel_console.c
index f8e571b..ff3ac0e 100644
--- a/apps/kernel_console/kernel_console.c
+++ b/apps/kernel_console/kernel_console.c
@@ -99,7 +99,8 @@ static char kernel_console_init()
}
-extern CONST_VAR(const struct output_handler_t *, resources_index[]);
+extern struct output_handler_t * resources_index[];
+/*extern CONST_VAR(const struct output_handler_t *, resources_index[]);*/
extern CONST_VAR(unsigned char, urls_tree[]);
void kernel_console_ressource_index(const char *args)
{
diff --git a/core/connections.c b/core/connections.c
index e4b937d..afdf516 100644
--- a/core/connections.c
+++ b/core/connections.c
@@ -36,6 +36,8 @@
#include "connections.h"
#include "memory.h"
+#include "elf_application.h"
+
/* Local IP address */
#ifdef IPV6
@@ -57,6 +59,10 @@ unsigned char local_ip_addr[4] = { IP_ADDR };
struct connection *all_connections;
struct http_rst_connection rst_connection;
+struct connection *get_all_connections() {
+ return all_connections;
+}
+
#ifdef IPV6
/*-----------------------------------------------------------------------------------*/
@@ -158,12 +164,15 @@ struct connection *add_connection(const struct connection *from
#else
connection = mem_alloc(sizeof(struct connection)); /* test NULL: done */
#endif
+
if (connection == NULL)
return NULL;
/* copy the connection */
- if (from != NULL)
+ if (from != NULL) {
*connection = *from;
+ }
+
/* insert the new connection */
if(all_connections == NULL) {
connection->next = connection;
@@ -175,6 +184,11 @@ struct connection *add_connection(const struct connection *from
connection->next = all_connections;
all_connections->prev = connection;
}
+
+#ifndef DISABLE_ELF
+ elf_application_add_connection(connection);
+#endif
+
return connection;
}
@@ -198,8 +212,15 @@ void free_connection(const struct connection *connection) {
#endif
if(connection->protocol.http.generator_service) {
clean_service(connection->protocol.http.generator_service, NULL);
+#ifndef DISABLE_COROUTINES
+ cr_clean(&connection->protocol.http.generator_service->coroutine);
+#endif
mem_free(connection->protocol.http.generator_service, sizeof(struct generator_service_t));
}
+#ifndef DISABLE_ELF
+ elf_application_remove_connection(connection);
+#endif
+
}
#ifdef IPV6
diff --git a/core/connections.h b/core/connections.h
index ef09b51..2a49a49 100644
--- a/core/connections.h
+++ b/core/connections.h
@@ -178,12 +178,12 @@ struct connection {
/* Loop on each connection */
#define FOR_EACH_CONN(item, code) \
- if(all_connections) { \
- struct connection *(item) = all_connections; \
+ if(get_all_connections()) { \
+ struct connection *(item) = get_all_connections(); \
do { \
{code} \
(item) = (item)->next; \
- } while((item) != all_connections); \
+ } while((item) != get_all_connections()); \
} \
#define NEXT_CONN(item) (item) = (item)->next
@@ -204,6 +204,7 @@ struct http_rst_connection {
extern struct connection *all_connections;
extern struct http_rst_connection rst_connection;
+extern struct connection *get_all_connections();
diff --git a/core/coroutines.c b/core/coroutines.c
index ec453f4..a285d0e 100644
--- a/core/coroutines.c
+++ b/core/coroutines.c
@@ -53,6 +53,15 @@ static struct coroutine_t *cr_in_stack = NULL;
/* Currently running coroutine. Null when the main program is running. */
static volatile struct coroutine_t *current_cr = NULL;
+void dumpCRInStack() {
+ if(cr_in_stack == NULL) {
+ printf("No cr in stack\r\n");
+ return;
+ }
+
+ printf("CR in stack %p, sp %p\r\n", cr_in_stack, cr_in_stack->curr_context.sp[0]);
+}
+
/* initialize a coroutine structure */
void cr_init(struct coroutine_t *coroutine) {
coroutine->curr_context.status = cr_ready;
@@ -73,31 +82,38 @@ void cr_run(struct coroutine_t *coroutine
) {
/* push all working registers */
PUSHREGS;
+
/* backup current context stack pointer(s) */
if(current_cr) {
BACKUP_CTX(current_cr->curr_context.sp);
} else {
BACKUP_CTX(main_sp);
}
+
/* set new current context */
current_cr = coroutine;
+
if(current_cr) {
RESTORE_CTX(current_cr->curr_context.sp);
/* test if this is the first time we run this context */
if(current_cr->curr_context.status == cr_ready) {
current_cr->curr_context.status = cr_active;
+
+
#ifndef DISABLE_POST
if(type == cor_type_post_out)
current_cr->func.func_post_out(current_cr->params.out.content_type,current_cr->params.out.post_data);
else if(type == cor_type_post_in)
- current_cr->func.func_post_in(current_cr->params.in.content_type,current_cr->params.in.part_number,current_cr->params.in.filename,(void**)¤t_cr->params.in.post_data);
+ current_cr->func.func_post_in(current_cr->params.in.content_type,/* current_cr->params.in.content_length,*/ current_cr->params.in.part_number,current_cr->params.in.filename,(void**)¤t_cr->params.in.post_data);
else
#endif
current_cr->func.func_get(current_cr->params.args);
+
current_cr->curr_context.status = cr_terminated;
current_cr = NULL;
}
}
+
if(current_cr == NULL) {
/* restore the main program stack pointer if needed */
RESTORE_CTX(main_sp);
@@ -112,16 +128,23 @@ void cr_run(struct coroutine_t *coroutine
struct coroutine_t *cr_prepare(struct coroutine_t *coroutine) {
if(cr_in_stack != coroutine) {
if(cr_in_stack != NULL) { /* is there a coroutine currently using the shared stack? */
+
/* backup its context in a freshly allocated buffer of the exact needed size */
char *sp = cr_in_stack->curr_context.sp[0];
uint16_t stack_size = shared_stack + STACK_SIZE - sp;
- cr_in_stack->curr_context.stack = mem_alloc(stack_size); /* test NULL: done */
- if(cr_in_stack->curr_context.stack == NULL) {
- return NULL;
+
+ if(stack_size>0) {
+
+ cr_in_stack->curr_context.stack = mem_alloc(stack_size); /* test NULL: done */
+
+ if(cr_in_stack->curr_context.stack == NULL) {
+ return NULL;
+ }
+
+ cr_in_stack->curr_context.stack_size = stack_size;
+ /* process the copy from (big) shared stack to the new (small) buffer */
+ memcpy(cr_in_stack->curr_context.stack, sp, stack_size);
}
- cr_in_stack->curr_context.stack_size = stack_size;
- /* process the copy from (big) shared stack to the new (small) buffer */
- memcpy(cr_in_stack->curr_context.stack, sp, stack_size);
}
if(coroutine->curr_context.stack != NULL) { /* does the new coroutine already has an allocated stack? */
/* restore its context to the (big) shared stack */
@@ -133,6 +156,7 @@ struct coroutine_t *cr_prepare(struct coroutine_t *coroutine) {
/* update the cr_in_stack pointer */
cr_in_stack = coroutine;
}
+
return cr_in_stack;
}
diff --git a/core/coroutines.h b/core/coroutines.h
index 4346d05..ac9dfa3 100644
--- a/core/coroutines.h
+++ b/core/coroutines.h
@@ -53,7 +53,7 @@
typedef char (cr_func_get)(struct args_t *args);
#ifndef DISABLE_POST
typedef char (cr_func_post_out)(uint8_t content_type,void *post_data);
-typedef char (cr_func_post_in)(uint8_t content_type, uint8_t part_number, char *filename, void **post_data);
+typedef char (cr_func_post_in)(uint8_t content_type, /*uint16_t content_length,*/ uint8_t part_number, char *filename, void **post_data);
#endif
/* A context (possibly several per coroutine) */
@@ -82,6 +82,7 @@ struct coroutine_t {
#ifndef DISABLE_POST
struct in_t { /* used with dopostin function */
uint8_t content_type;
+ /*uint16_t content_length;*/
uint8_t part_number; /* number of part with multipart data (0 if one part) */
char *filename; /* filename of current file */
void *post_data; /* data flowing between dopostin and dopostout functions */
@@ -116,6 +117,8 @@ enum coroutine_type_e { cor_type_get, cor_type_post_in, cor_type_post_out } coro
/* Functions and variables for coroutines */
+extern void dumpCRInStack();
+
/* initialize a coroutine structure */
extern void cr_init(struct coroutine_t *coroutine);
/* prepare a coroutine for usage: the context is copied in the shared stack
diff --git a/core/elf_application.c b/core/elf_application.c
new file mode 100644
index 0000000..cd8ed01
--- /dev/null
+++ b/core/elf_application.c
@@ -0,0 +1,389 @@
+#ifndef DISABLE_ELF
+
+#include "elf_application.h"
+#include "memory.h"
+
+unsigned int elf_applications_count __attribute__ ((section(".persistent_data"))) = 0;
+
+struct elf_application_t *all_applications __attribute__ ((section(".persistent_data"))) = 0;
+
+/* Post Url termination character */
+#define URL_POST_END 255
+
+/* "404 Not found" handler */
+#define http_404_handler apps_httpCodes_404_html_handler
+extern CONST_VAR(struct output_handler_t, apps_httpCodes_404_html_handler);
+
+static elf_application_allocate_t elf_application_allocate;
+static elf_application_free_t elf_application_free;
+
+void elf_applications_init(elf_application_allocate_t allocate, elf_application_free_t free) {
+ elf_application_allocate = allocate;
+ elf_application_free = free;
+}
+
+int elf_application_get_count() { return elf_applications_count; }
+
+
+char elf_application_add(struct elf_application_t *application) {
+ struct elf_application_parsing_t *parsing;
+ /* Head insert */
+ struct elf_application_t *buf[1];
+ unsigned int i;
+ const struct output_handler_t * /*CONST_VAR*/ output_handler;
+
+ /*application->previous = NULL; */
+ buf[0] = NULL;
+ APPLICATION_WRITE(&application->previous, buf, sizeof(struct elf_application_t *));
+
+ if(all_applications == NULL) {
+ /* application->next = NULL; */
+ APPLICATION_WRITE(&application->next, buf, sizeof(struct elf_application_t *));
+ } else {
+ /* application->next = all_applications; */
+ APPLICATION_WRITE(&application->next, &all_applications, sizeof(struct elf_application_t *));
+ /* all_applications->previous = application; */
+ APPLICATION_WRITE(&all_applications->previous, application, sizeof(struct elf_application_t *));
+ }
+
+ /* all_applications = application; */
+ APPLICATION_WRITE(&all_applications, &application, sizeof(struct elf_application_t *));
+
+ {
+ unsigned int elfApplicationsCount = elf_applications_count + 1;
+ APPLICATION_WRITE((void *)&elf_applications_count, &elfApplicationsCount, sizeof(unsigned int));
+ }
+
+ i = 0;
+ while((output_handler = CONST_ADDR(application->environment->resources_index[i])) != NULL) {
+
+ if(CONST_UI8(output_handler->handler_type) == type_generator
+ #ifndef DISABLE_GP_IP_HANDLER
+ || CONST_UI8(output_handler->handler_type) == type_general_ip_handler
+ #endif
+ ) {
+ generator_init_func_t * init_handler = CONST_ADDR(GET_GENERATOR(output_handler).init);
+ if(init_handler)
+ init_handler();
+ }
+
+ i++;
+ }
+
+ /* Add all existing connections to the application's parsing */
+ FOR_EACH_CONN(conn, {
+ if(!IS_HTTP(conn)) {
+ NEXT_CONN(conn);
+ continue;
+ }
+
+ parsing = (struct elf_application_parsing_t *)mem_alloc(sizeof(struct elf_application_parsing_t));
+ parsing->connection = conn;
+ parsing->blob = application->environment->urls_tree;
+ parsing->previous = NULL;
+ parsing->next = application->parsing;
+
+ if(application->parsing != NULL) {
+ application->parsing->previous = parsing;
+ }
+
+ APPLICATION_WRITE(&application->parsing, &parsing, sizeof(struct elf_application_parsing_t *));
+ })
+
+ return 1;
+}
+
+void elf_application_remove(const struct elf_application_t *application) {
+ if(elf_application_get_count() > 0 ) {
+ struct elf_application_t *appli = all_applications;
+
+ while(appli) {
+ if(application == appli) {
+
+ /* remove the parsing data */
+ {
+ struct elf_application_parsing_t *parsing = appli->parsing;
+ struct elf_application_parsing_t *parsingNext;
+ while(parsing) {
+ parsingNext = parsing->next;
+ mem_free(parsing, sizeof(struct elf_application_parsing_t));
+ parsing = parsingNext;
+ }
+ }
+
+ /* Now remove the application by itself */
+ if(application == all_applications) {
+
+ /* all_applications = application->next; */
+ APPLICATION_WRITE(all_applications, application->next, sizeof(struct elf_application_t *));
+
+ if(all_applications != NULL) {
+ /* all_applications->previous = NULL; */
+ struct elf_application_t *buf[1];
+ buf[0] = NULL;
+ APPLICATION_WRITE(all_applications->previous, buf, sizeof(struct elf_application_t *));
+ }
+
+ } else {
+ /* application->previous->next = application->next; */
+ APPLICATION_WRITE(application->previous->next, application->next, sizeof(struct elf_application_t *));
+
+ /* application->next->previous = application->previous; */
+ APPLICATION_WRITE(application->next->previous, application->previous, sizeof(struct elf_application_t *));
+ }
+
+ {
+ unsigned int elfApplicationsCount = elf_applications_count - 1;
+ APPLICATION_WRITE((void *)&elf_applications_count, &elfApplicationsCount, sizeof(unsigned int));
+ }
+ return;
+ }
+ appli = appli->next;
+ }
+ }
+}
+
+/* When the device resets, init all dynamic applications*/
+void elf_application_init() {
+
+ if(elf_application_get_count() > 0) {
+ struct elf_application_t *appli = all_applications;
+ const struct output_handler_t * /*CONST_VAR*/ output_handler;
+ int i;
+
+ while(appli) {
+
+
+ if(appli->data_size>0) {
+ memcpy(appli->data_destination, appli->data_source, appli->data_size);
+ }
+
+
+ i = 0;
+ while((output_handler = CONST_ADDR(appli->environment->resources_index[i])) != NULL) {
+
+ if(CONST_UI8(output_handler->handler_type) == type_generator
+#ifndef DISABLE_GP_IP_HANDLER
+ || CONST_UI8(output_handler->handler_type) == type_general_ip_handler
+#endif
+ ) {
+ generator_init_func_t * init_handler = CONST_ADDR(GET_GENERATOR(output_handler).init);
+ if(init_handler)
+ init_handler();
+ }
+
+ i++;
+ }
+
+ appli = appli->next;
+ }
+
+ }
+}
+
+/* When a connection has been created */
+void elf_application_add_connection(struct connection *connection) {
+ if(connection) {
+
+ if(!IS_HTTP(connection))
+ return;
+
+ if(elf_application_get_count() > 0 ) {
+ struct elf_application_parsing_t *parsing;
+ struct elf_application_t * appli = all_applications;
+
+
+ while(appli) {
+
+ parsing = (struct elf_application_parsing_t *)mem_alloc(sizeof(struct elf_application_parsing_t));
+ /* Head insert */
+ parsing->connection = connection;
+ parsing->blob = appli->environment->urls_tree;
+ parsing->previous = NULL;
+ parsing->next = appli->parsing;
+
+ if(appli->parsing != NULL)
+ appli->parsing->previous = parsing;
+
+ APPLICATION_WRITE(&appli->parsing, &parsing, sizeof(struct elf_application_parsing_t *));
+
+ appli = appli->next;
+ }
+ }
+ }
+}
+/* When a connection has been terminated */
+void elf_application_remove_connection(const struct connection *connection) {
+ if(connection) {
+ if(elf_application_get_count() > 0 ) {
+ struct elf_application_parsing_t *parsing;
+ struct elf_application_t * appli = all_applications;
+
+ while(appli) {
+ parsing = appli->parsing;
+
+ while(parsing) {
+
+ if(parsing->connection == connection) {
+ if(parsing->previous)
+ parsing->previous->next = parsing->next;
+
+ if(parsing->next)
+ parsing->next->previous = parsing->previous;
+
+ if(parsing == appli->parsing) {
+ APPLICATION_WRITE(&appli->parsing, &parsing->next, sizeof(struct elf_application_parsing_t *));
+ }
+
+ mem_free(parsing, sizeof(struct elf_application_parsing_t));
+ break;
+ }
+
+ parsing = parsing->next;
+ }
+
+ appli = appli->next;
+ }
+ }
+ }
+}
+
+struct output_handler_t *url_parse_step(uint8_t byte, unsigned char **url_blob, const struct output_handler_t **resources_index) {
+ unsigned char *blob;
+ unsigned char blob_curr;
+
+ blob = *url_blob;
+ blob_curr = CONST_READ_UI8(blob);
+
+ if(blob_curr == URL_POST_END) {
+ blob++;
+ blob_curr = CONST_READ_UI8(blob);
+ }
+
+ if(blob_curr >= 128) {
+ if (byte == ' ') {
+ printf("======> OUTPUT HANDLER FOUND %p %d<=====\r\n", CONST_ADDR(resources_index[blob_curr - 128]), blob_curr - 128);
+ return (struct output_handler_t*)CONST_ADDR(resources_index[blob_curr - 128]);
+ }
+
+ blob++;
+ blob_curr = CONST_READ_UI8(blob);
+ }
+
+ do {
+ unsigned char offsetInf = 0;
+ unsigned char offsetEq = 0;
+ unsigned char blob_next;
+
+ blob_curr = CONST_READ_UI8(blob);
+ blob_next = CONST_READ_UI8(++blob);
+ if (byte != blob_curr && blob_next >= 128) {
+ blob_next = CONST_READ_UI8(++blob);
+ }
+
+ if (blob_next < 32) {
+ offsetInf +=
+ ((blob_next>>2) & 1) + ((blob_next>>1) & 1) + (blob_next & 1);
+
+ offsetEq = offsetInf + ((blob_next & 2)?CONST_READ_UI8(blob+1):0);
+ }
+ if (byte == blob_curr) {
+ if (blob_next < 32) {
+ if (blob_next & 2)
+ blob += offsetEq;
+ else {
+ *url_blob = blob;
+ return &http_404_handler;
+ }
+ }
+
+ *url_blob = blob;
+ return NULL;
+ }
+ else if (byte < blob_curr) {
+ if (blob_next < 32 && blob_next & 1) {
+ blob += offsetInf;
+ }
+ else {
+ *url_blob = blob;
+ return &http_404_handler;
+ }
+ }
+ else {
+ if (blob_next < 32 && blob_next & 4) {
+ unsigned char offsetSup = offsetEq + ((blob_next & 3) ? CONST_READ_UI8(blob + (offsetInf - 1)) : 0);
+
+ blob += offsetSup;
+ }
+ else {
+ *url_blob = blob;
+ return &http_404_handler;
+ }
+ }
+ } while(1);
+
+ return NULL;
+}
+
+void elf_application_parsing_start(const struct connection *connection) {
+ if(elf_application_get_count() > 0) {
+ struct elf_application_parsing_t *parsing;
+ struct elf_application_t *appli = all_applications;
+ while(appli) {
+
+ parsing = appli->parsing;
+
+ while(parsing) {
+
+ if(parsing->connection == connection) {
+ parsing->blob = appli->environment->urls_tree;
+ break;
+ }
+
+ parsing = parsing->next;
+ }
+
+ appli = appli->next;
+ }
+ }
+}
+
+struct output_handler_t *elf_application_parse_step(const struct connection *connection, uint8_t byte) {
+ if(elf_application_get_count() > 0) {
+ struct elf_application_parsing_t *parsing;
+ struct output_handler_t *output_handler = NULL;
+ struct elf_application_t *appli = all_applications;
+ char still_parsing = 0;
+
+ while(appli) {
+
+ parsing = appli->parsing;
+
+ while(parsing) {
+
+ if(parsing->connection == connection) {
+ output_handler = url_parse_step(byte, &parsing->blob, appli->environment->resources_index);
+
+ if(output_handler == NULL)
+ still_parsing = 1;
+ else {
+ if(output_handler != &http_404_handler)
+ return output_handler;
+ }
+
+ break;
+ }
+
+ parsing = parsing->next;
+ }
+
+ appli = appli->next;
+ }
+
+ if(still_parsing == 1)
+ return NULL;
+ }
+ return &http_404_handler;
+}
+
+#endif
diff --git a/core/elf_application.h b/core/elf_application.h
new file mode 100644
index 0000000..7a18992
--- /dev/null
+++ b/core/elf_application.h
@@ -0,0 +1,115 @@
+/*
+* Copyright or © or Copr. 2008, Simon Duquennoy
+*
+* Author e-mail: simon.duquennoy@lifl.fr
+*
+* This software is a computer program whose purpose is to design an
+* efficient Web server for very-constrained embedded system.
+*
+* This software is governed by the CeCILL license under French law and
+* abiding by the rules of distribution of free software. You can use,
+* modify and/ or redistribute the software under the terms of the CeCILL
+* license as circulated by CEA, CNRS and INRIA at the following URL
+* "http://www.cecill.info".
+*
+* As a counterpart to the access to the source code and rights to copy,
+* modify and redistribute granted by the license, users are provided only
+* with a limited warranty and the software's author, the holder of the
+* economic rights, and the successive licensors have only limited
+* liability.
+*
+* In this respect, the user's attention is drawn to the risks associated
+* with loading, using, modifying and/or developing or reproducing the
+* software by the user in light of its specific status of free software,
+* that may mean that it is complicated to manipulate, and that also
+* therefore means that it is reserved for developers and experienced
+* professionals having in-depth computer knowledge. Users are therefore
+* encouraged to load and test the software's suitability as regards their
+* requirements in conditions enabling the security of their systems and/or
+* data to be ensured and, more generally, to use and operate it in the
+* same conditions as regards security.
+*
+* The fact that you are presently reading this means that you have had
+* knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef DISABLE_ELF
+
+#ifndef __ELF_APPLICATION_H__
+#define __ELF_APPLICATION_H__
+
+#include "handlers.h"
+#include "connections.h"
+
+typedef void *(*elf_application_allocate_t)(unsigned int size);
+typedef void (*elf_application_free_t)(void *memory);
+
+/* Callbacks */
+typedef char (*elf_application_install_t)();
+typedef void (*elf_application_remove_t)();
+
+struct elf_application_environment_t {
+ elf_application_install_t *install;
+ elf_application_remove_t *remove;
+ unsigned char * urls_tree;
+ struct output_handler_t ** resources_index;
+};
+
+/* Stores parsing information per connection*/
+struct elf_application_parsing_t {
+ struct connection *connection;
+ unsigned char * blob;
+
+ struct elf_application_parsing_t *previous;
+ struct elf_application_parsing_t *next;
+};
+
+struct elf_application_t {
+ char * filename;
+ uint16_t size;
+
+ char * data_source;
+ char * data_destination;
+ unsigned int data_size;
+
+ struct elf_application_parsing_t * parsing;
+
+ struct elf_application_environment_t *environment;
+
+ struct elf_application_t * previous;
+ struct elf_application_t * next;
+};
+
+
+#define FOR_EACH_APPLICATION(item, code) \
+ if(elf_application_get_count() > 0) { \
+ struct elf_application_t *(item) = all_applications; \
+ do { \
+ {code} \
+ (item) = (item)->next; \
+ } while(item); \
+ }
+
+extern struct elf_application_t * all_applications;
+
+extern void elf_applications_init(elf_application_allocate_t allocate, elf_application_free_t free);
+
+extern int elf_application_get_count();
+extern char elf_application_add(struct elf_application_t *application);
+extern void elf_application_remove(const struct elf_application_t *application);
+
+/* When the device resets, init all dynamic applications*/
+extern void elf_application_init();
+
+/* When a connection has been created */
+extern void elf_application_add_connection(struct connection *connection);
+/* When a connection has been terminated */
+extern void elf_application_remove_connection(const struct connection *connection);
+
+/* Resets the parsing internals*/
+extern void elf_application_parsing_start(const struct connection *connection);
+extern struct output_handler_t *elf_application_parse_step(const struct connection *connection, uint8_t byte);
+
+#endif
+
+#endif
diff --git a/core/handlers.h b/core/handlers.h
index 91140c4..6b3b18c 100644
--- a/core/handlers.h
+++ b/core/handlers.h
@@ -53,7 +53,7 @@ typedef char (generator_dopacket_out_func_t)(const void *connection_info);
#endif
#ifndef DISABLE_POST
-typedef char (generator_dopost_in_func_t)(uint8_t,uint8_t,char *,void **);
+typedef char (generator_dopost_in_func_t)(uint8_t, /*uint16_t,*/ uint8_t,char *,void **);
typedef char (generator_dopost_out_func_t)(uint8_t,void *);
#endif
@@ -164,7 +164,7 @@ struct output_handler_t {
#define GET_FLAGS(r) (CONST_UI8((r)->handler_type) == type_control ? CONST_UI8(GET_CONTROL(r).flags) : (TCP_ACK | TCP_PSH))
/* Global output_handler table */
-extern CONST_VAR(const struct output_handler_t *, resources_index[]);
+extern CONST_VAR(struct output_handler_t * const, resources_index[]);
/* URL tree: parsing an URL to retrieve an output_handler */
extern CONST_VAR(unsigned char, urls_tree[]);
diff --git a/core/input.c b/core/input.c
index b718c54..dabad39 100644
--- a/core/input.c
+++ b/core/input.c
@@ -42,6 +42,9 @@
#include "coroutines.h"
#include "blobs.h"
#include "defines.h"
+#include "elf_application.h"
+
+#include
/* Used to dump the runtime stack */
#ifdef STACK_DUMP
@@ -192,7 +195,7 @@ short in()
#ifndef DISABLE_POST
/* called from dopostin or dopacketin */
short in(){
- unsigned char tmp;
+ unsigned char tmp, last_position_in_boundary;
#ifndef DISABLE_GP_IP_HANDLER
/* If post AND general purpose ip, then check if the connection is null
@@ -206,12 +209,16 @@ short in(){
if(coroutine_state.state == cor_out)
return -1;
+
if(!curr_input.connection->protocol.http.post_data->content_length)
return -1;
+
if(curr_input.connection->protocol.http.post_data->boundary && (curr_input.connection->protocol.http.post_data->boundary->index == (uint8_t)-1)) /* index = -1 => boundary found */
return -1;
+
if(!curr_input.length)
cr_run(NULL,cor_type_get); /* input buffer is empty, changing context */
+
if(curr_input.connection->protocol.http.post_data->boundary){
/* getting next value in input buffer */
tmp = curr_input.connection->protocol.http.post_data->boundary->boundary_buffer[curr_input.connection->protocol.http.post_data->boundary->index];
@@ -221,7 +228,12 @@ short in(){
if(curr_input.connection->protocol.http.post_data->boundary->index == curr_input.connection->protocol.http.post_data->boundary->boundary_size)
curr_input.connection->protocol.http.post_data->boundary->index = 0;
/* comparing first and last characters of buffer with boundary, then all characters */
- if(curr_input.connection->protocol.http.post_data->boundary->boundary_buffer[(unsigned char)(curr_input.connection->protocol.http.post_data->boundary->index - 1) % curr_input.connection->protocol.http.post_data->boundary->boundary_size]
+ if(curr_input.connection->protocol.http.post_data->boundary->index == 0)
+ last_position_in_boundary = curr_input.connection->protocol.http.post_data->boundary->boundary_size - 1;
+ else
+ last_position_in_boundary = (unsigned char)(curr_input.connection->protocol.http.post_data->boundary->index - 1);
+
+ if(curr_input.connection->protocol.http.post_data->boundary->boundary_buffer[last_position_in_boundary]
== curr_input.connection->protocol.http.post_data->boundary->boundary_ref[curr_input.connection->protocol.http.post_data->boundary->boundary_size-1]
&& curr_input.connection->protocol.http.post_data->boundary->boundary_buffer[curr_input.connection->protocol.http.post_data->boundary->index]
== curr_input.connection->protocol.http.post_data->boundary->boundary_ref[0]){
@@ -230,6 +242,7 @@ short in(){
for(i = 1 ; i < curr_input.connection->protocol.http.post_data->boundary->boundary_size-1 ; i++){
if(index == curr_input.connection->protocol.http.post_data->boundary->boundary_size)
index = 0;
+
if(curr_input.connection->protocol.http.post_data->boundary->boundary_ref[i] != curr_input.connection->protocol.http.post_data->boundary->boundary_buffer[index])
break;
index++;
@@ -240,6 +253,7 @@ short in(){
}
else
DEV_GETC(tmp);
+
/* updating counters */
if(curr_input.connection->protocol.http.post_data->content_length != (uint16_t)-1)
curr_input.connection->protocol.http.post_data->content_length--;
@@ -316,7 +330,7 @@ char smews_receive(void) {
/* tmp connection used to store the current state until checksums are checked */
struct connection tmp_connection;
- if(!DEV_DATA_TO_READ)
+ if(!DEV_DATA_TO_READ)
return 0;
#ifdef IPV6
@@ -329,7 +343,6 @@ char smews_receive(void) {
DEV_GETC(tmp_char);
#endif
-
#ifdef SMEWS_RECEIVING
SMEWS_RECEIVING;
#endif
@@ -361,7 +374,6 @@ char smews_receive(void) {
return 1;
#endif
-
/* We don't care about the Hop Limit (TTL) */
DEV_GET(tmp_char);
@@ -422,6 +434,7 @@ char smews_receive(void) {
if(UI16(current_checksum) != 0xffff)
return 1;
+
#endif
#ifndef DISABLE_GP_IP_HANDLER
@@ -467,6 +480,7 @@ char smews_receive(void) {
return 1;
}
#endif
+
/* End of IP, starting TCP */
checksum_init();
@@ -541,7 +555,6 @@ char smews_receive(void) {
/* get TCP ack */
DEV_GETC32(current_inack);
-
/* duplicate ACK: set nextoutseqno for retransmission */
if(UI32(tmp_connection.protocol.http.next_outseqno) - UI16(tmp_connection.protocol.http.inflight) == UI32(current_inack)) {
UI32(tmp_connection.protocol.http.next_outseqno) = UI32(current_inack);
@@ -663,7 +676,7 @@ char smews_receive(void) {
x = 0;
if(segment_length && tmp_connection.protocol.http.tcp_state == tcp_established && (new_tcp_data || tmp_connection.output_handler == NULL)) {
const struct output_handler_t * /*CONST_VAR*/ output_handler = NULL;
-
+ struct output_handler_t * elf_application_output_handler = NULL;
/* parse the eventual GET request */
unsigned const char * /*CONST_VAR*/ blob;
unsigned char blob_curr;
@@ -705,6 +718,7 @@ char smews_receive(void) {
&& output_handler != &http_505_handler
#endif
) {
+
blob_curr = CONST_READ_UI8(blob);
#ifndef DISABLE_POST
/* testing end multipart */
@@ -720,6 +734,7 @@ char smews_receive(void) {
#endif
x++;
DEV_GETC(tmp_char);
+
#ifndef DISABLE_POST
/* updating content length */
if((tmp_connection.protocol.http.parsing_state == parsing_init_buffer
@@ -727,8 +742,11 @@ char smews_receive(void) {
||(tmp_connection.protocol.http.post_data
&& tmp_connection.protocol.http.post_data->boundary
&& tmp_connection.protocol.http.post_data->boundary->ready_to_count))
- && tmp_connection.protocol.http.post_data->content_length != (uint16_t)-1)
+ && tmp_connection.protocol.http.post_data->content_length != (uint16_t)-1) {
+
tmp_connection.protocol.http.post_data->content_length--;
+
+ }
}
/* initializing buffer before parsing data */
if(tmp_connection.protocol.http.parsing_state == parsing_init_buffer){
@@ -857,6 +875,9 @@ char smews_receive(void) {
cr_init(&(tmp_connection.protocol.http.post_data->coroutine));
tmp_connection.protocol.http.post_data->coroutine.func.func_post_in = CONST_ADDR(GET_GENERATOR(output_handler).handlers.post.dopostin);
tmp_connection.protocol.http.post_data->coroutine.params.in.content_type = tmp_connection.protocol.http.post_data->content_type;
+
+ /*tmp_connection.protocol.http.post_data->coroutine.params.in.content_length = tmp_connection.protocol.http.post_data->content_length;*/
+
tmp_connection.protocol.http.post_data->coroutine.params.in.filename = tmp_connection.protocol.http.post_data->filename;
tmp_connection.protocol.http.post_data->coroutine.params.in.post_data = tmp_connection.protocol.http.post_data->post_data;
if(tmp_connection.protocol.http.post_data->boundary){
@@ -914,6 +935,7 @@ char smews_receive(void) {
continue;
break;
}
+
/* searching end character of post url detection */
if(tmp_connection.protocol.http.parsing_state == parsing_url && blob_curr == URL_POST_END){
if(tmp_connection.protocol.http.post_data){
@@ -998,24 +1020,25 @@ char smews_receive(void) {
else{
/* final reallocation */
uint8_t i = 0;
- char *new_tab = mem_alloc((tmp_connection.protocol.http.post_data->boundary->index+5)*sizeof(char));
+ char *new_tab = mem_alloc((tmp_connection.protocol.http.post_data->boundary->index+4)*sizeof(char));
if(!new_tab){
output_handler = &http_404_handler;
break;
}
- new_tab[0] = '\n';
- new_tab[1] = '\r';
- new_tab[2] = '\n';
+
+ new_tab[0] = '\r';
+ new_tab[1] = '\n';
+ new_tab[2] = '-';
new_tab[3] = '-';
- new_tab[4] = '-';
/* copying boundary */
for(i = 0 ; i < tmp_connection.protocol.http.post_data->boundary->index ; i++)
- new_tab[i+5] = tmp_connection.protocol.http.post_data->boundary->boundary_ref[i];
+ new_tab[i+4] = tmp_connection.protocol.http.post_data->boundary->boundary_ref[i];
mem_free(tmp_connection.protocol.http.post_data->boundary->boundary_ref,(tmp_connection.protocol.http.post_data->boundary->boundary_size)*sizeof(char));
- tmp_connection.protocol.http.post_data->boundary->boundary_size = tmp_connection.protocol.http.post_data->boundary->index + 5;
+ tmp_connection.protocol.http.post_data->boundary->boundary_size = tmp_connection.protocol.http.post_data->boundary->index + 4;
tmp_connection.protocol.http.post_data->boundary->boundary_ref = new_tab;
tmp_connection.protocol.http.post_data->boundary->index = -1;
tmp_connection.protocol.http.post_data->boundary->boundary_buffer = mem_alloc(tmp_connection.protocol.http.post_data->boundary->boundary_size*sizeof(char));
+
if(!tmp_connection.protocol.http.post_data->boundary->boundary_buffer){
/* If no space for boundary_ref, free boundary */
mem_free(tmp_connection.protocol.http.post_data->boundary, sizeof(struct boundary_t));
@@ -1025,6 +1048,7 @@ char smews_receive(void) {
}
}
}
+
/* parsing content-type */
else if(tmp_connection.protocol.http.parsing_state == parsing_post_content_type){
if(blob_curr - 128 == CONTENT_TYPE_MULTIPART_47_FORM_45_DATA){ /* multipart */
@@ -1086,6 +1110,7 @@ char smews_receive(void) {
#endif
tmp_connection.protocol.http.parsing_state = parsing_url;
blob = urls_tree;
+ elf_application_parsing_start(connection);
} else {
if(tmp_char == ' ') {
#ifndef DISABLE_POST
@@ -1095,8 +1120,14 @@ char smews_receive(void) {
}
else{
#endif
- if(!output_handler)
+
+ elf_application_output_handler = elf_application_parse_step(connection, tmp_char);
+ if((elf_application_output_handler != NULL) && (elf_application_output_handler != &http_404_handler))
+ output_handler = elf_application_output_handler;
+
+ if(!output_handler) {
output_handler = (struct output_handler_t*)CONST_ADDR(resources_index[blob_curr - 128]);
+ }
#ifndef DISABLE_POST
if(tmp_connection.protocol.http.post_data){
tmp_connection.protocol.http.parsing_state = parsing_post_attributes;
@@ -1160,6 +1191,7 @@ char smews_receive(void) {
}
blob_curr = CONST_READ_UI8(blob);
}
+
#ifndef DISABLE_POST
/* end header detection */
if(tmp_connection.protocol.http.parsing_state == parsing_post_attributes && tmp_char == 13){
@@ -1231,6 +1263,7 @@ char smews_receive(void) {
if (tmp_char != blob_curr && blob_next >= 128) {
blob_next = CONST_READ_UI8(++blob);
}
+
if (blob_next < 32) {
offsetInf += ((blob_next>>2) & 1) + ((blob_next>>1) & 1) + (blob_next & 1);
offsetEq = offsetInf + ((blob_next & 2)?CONST_READ_UI8(blob+1):0);
@@ -1277,8 +1310,19 @@ char smews_receive(void) {
}
}
} while(1);
+
+ elf_application_output_handler = elf_application_parse_step(connection, tmp_char);
+ if(output_handler == &http_404_handler) {
+ output_handler = elf_application_output_handler;
+
+ if((tmp_char == ' ') && (output_handler != &http_404_handler) && (output_handler != NULL)){
+ tmp_connection.protocol.http.parsing_state = parsing_end;
+ break;
+ }
+ }
}
}
+
/* detecting parsing_end */
if(
#ifndef DISABLE_POST
@@ -1289,9 +1333,11 @@ char smews_receive(void) {
|| output_handler == &http_505_handler
#endif
) && tmp_connection.protocol.http.parsing_state != parsing_cmd)){
+
tmp_connection.protocol.http.parsing_state = parsing_end;
tmp_connection.protocol.http.ready_to_send = 1;
}
+
if(!output_handler)
tmp_connection.protocol.http.blob = blob;
else {
@@ -1357,6 +1403,7 @@ char smews_receive(void) {
tmp_connection.protocol.http.blob = blob;
}
}
+
/* drop remaining TCP data */
while(x++ < segment_length)
DEV_GETC(tmp_char);
@@ -1397,13 +1444,14 @@ char smews_receive(void) {
#endif
}
}
-
+
if(!connection && tmp_connection.protocol.http.tcp_state == tcp_syn_rcvd) {
connection = add_connection(&tmp_connection
#ifdef IPV6
, compressed_ip_size(comp_ipv6_addr)
#endif
);
+
/* update the pointer in the tmp_connection because
* it will be copied later so if the pointers do not have the right value, the list
* will be screwed */
@@ -1413,7 +1461,7 @@ char smews_receive(void) {
tmp_connection.next = connection->next;
}
}
-
+
if(!connection) {
/* no valid connection has been found for this packet, send a reset */
UI32(tmp_connection.protocol.http.next_outseqno) = UI32(current_inack);
@@ -1449,5 +1497,6 @@ char smews_receive(void) {
}
}
}
+
return 1;
}
diff --git a/core/memory.c b/core/memory.c
index 8b31ee4..82983ab 100644
--- a/core/memory.c
+++ b/core/memory.c
@@ -110,6 +110,7 @@ void *mem_alloc(uint16_t size) {
return NULL;
}
+
return curr_free;
}
diff --git a/core/output.c b/core/output.c
index 74b064c..4b01d48 100644
--- a/core/output.c
+++ b/core/output.c
@@ -309,6 +309,7 @@ void smews_send_packet (struct connection *connection)
{
uint16_t max_out_size;
uint32_t file_remaining_bytes;
+
max_out_size = MAX_OUT_SIZE (connection->protocol.http.tcp_mss);
file_remaining_bytes = UI32 (connection->protocol.http.final_outseqno) - UI32 (next_outseqno);
segment_length = file_remaining_bytes > max_out_size ? max_out_size : file_remaining_bytes;
@@ -316,6 +317,7 @@ void smews_send_packet (struct connection *connection)
break;
}
case type_generator:
+
segment_length = curr_output.content_length;
segment_length += _service_headers_size (curr_output.service_header);
break;
@@ -680,7 +682,6 @@ char smews_send (void)
struct connection *active_connection = NULL;
const struct output_handler_t * /*CONST_VAR */ old_output_handler = NULL;
-
/* sending reset has the highest priority */
if (UI16 (rst_connection.port))
{
@@ -730,7 +731,7 @@ char smews_send (void)
}
#endif
- if (!active_connection->protocol.http.ready_to_send)
+ if(!active_connection->protocol.http.ready_to_send)
{
old_output_handler = active_connection->output_handler;
active_connection->output_handler = &ref_ack;
@@ -743,13 +744,21 @@ char smews_send (void)
active_connection->output_handler = &ref_ack;
}
#endif
-
+
/* get the type of web applicative resource */
switch (CONST_UI8 (active_connection->output_handler->handler_type))
{
case type_control:
/* preparing to send TCP control data */
- smews_send_packet (active_connection);
+#ifndef DISABLE_POST
+ /* Added to prevent from duplicate ack generation while dealing with post requests
+ * When dealing with post requests, it happens that smews has to handle packets acknowlegment while the post data
+ * are still not fully received :
+ * in the meantime, smews acknowledges multiple times (read dozens) the same packet, till post data reception completes.
+ */
+ //if(!active_connection->protocol.http.post_data)
+#endif
+ smews_send_packet (active_connection);
active_connection->output_handler = NULL;
if (active_connection->protocol.http.tcp_state == tcp_closing)
{
@@ -798,6 +807,7 @@ char smews_send (void)
{
return 1;
}
+
curr_output.service = active_connection->protocol.http.generator_service;
/* if we create the service, it is the first segment of the answer stream, we need
* to reduce its size to fit the mss if the segment is not the last.
@@ -808,6 +818,7 @@ char smews_send (void)
curr_output.service->in_flight_infos = NULL;
curr_output.service->is_persistent = CONST_UI8 (GET_GENERATOR (active_connection->output_handler).prop) == prop_persistent;
UI32 (curr_output.service->curr_outseqno) = UI32 (active_connection->protocol.http.next_outseqno);
+
#ifndef DISABLE_COROUTINES
/* init coroutine */
cr_init (&curr_output.service->coroutine);
@@ -827,6 +838,7 @@ char smews_send (void)
else
{
#endif
+
#ifndef DISABLE_COROUTINES
curr_output.service->coroutine.func.func_get = CONST_ADDR(GET_GENERATOR(active_connection->output_handler).handlers.get.doget);
#ifndef DISABLE_ARGS
@@ -837,9 +849,11 @@ char smews_send (void)
#ifndef DISABLE_POST
}
#endif
+
/* we don't know yet the final output sequence number for this service */
UI32 (active_connection->protocol.http.final_outseqno) = UI32 (active_connection->protocol.http.next_outseqno) - 1;
#ifndef DISABLE_COMET
+
/* if this is a comet generator, manage all listenning clients */
if (CONST_UI8 (active_connection->output_handler->handler_comet))
{
@@ -854,6 +868,7 @@ char smews_send (void)
}
)
}
+
/* manage streamed comet data */
if (CONST_UI8 (active_connection->output_handler->handler_stream))
{
@@ -923,7 +938,6 @@ char smews_send (void)
{
curr_output.service_header = curr_output.service->service_header;
}
-
/* initializations before generating the segment */
curr_output.content_length = 0;
checksum_init ();
diff --git a/core/smews.c b/core/smews.c
index 91856d2..09c516c 100644
--- a/core/smews.c
+++ b/core/smews.c
@@ -42,7 +42,6 @@
/*-----------------------------------------------------------------------------------*/
void smews_retransmit(void) {
last_transmission_time++;
-
FOR_EACH_CONN(conn, {
if(conn->output_handler
&& IS_HTTP(conn)
diff --git a/core/smews.h b/core/smews.h
index d58cef9..018c2a8 100644
--- a/core/smews.h
+++ b/core/smews.h
@@ -42,6 +42,7 @@
#include "coroutines.h"
#include "timers.h"
#include "memory.h"
+#include "elf_application.h"
extern void smews_retransmit(void);
@@ -99,6 +100,9 @@ static inline void smews_init(void) {
}
x++;
}
+
+ elf_application_init();
+
#ifndef DISABLE_TIMERS
set_timer(&smews_retransmit,1000);
#endif
diff --git a/doc/elf_screenshot.png b/doc/elf_screenshot.png
new file mode 100644
index 0000000..6ab181b
Binary files /dev/null and b/doc/elf_screenshot.png differ
diff --git a/doc/userguide.pdf b/doc/userguide.pdf
index 8e8ff28..a1a5875 100644
Binary files a/doc/userguide.pdf and b/doc/userguide.pdf differ
diff --git a/doc/userguide.tex b/doc/userguide.tex
index a66056c..70c9968 100755
--- a/doc/userguide.tex
+++ b/doc/userguide.tex
@@ -1269,6 +1269,72 @@ \section{Synthesis of the features}
\label{tab:gpip-appssyscalls}
\end{table}
+\chapter{Uploading new applications into an embedded Smews}
+\label{ch:uploadingapp}
+
+In a standard behaviour, only applications crafted with Smews are accessible, but there's another way to deploy applications for the MBED device, without having to modify the embedded server, called post-issuance.
+
+\section{Preparing Smews for post-issuance.}
+Post-issuance in Smews is available thanks to an application called ElfLoader, shipped with the server, that will handle the file upload through a POST request and relocation of elf files onto the device. To build such a configuration :
+
+\begin{verbatim}
+$ scons target=mbed_ethernet apps=:elfloader ipaddr=192.168.100.2
+\end{verbatim}
+
+Then, flash the resulting image onto the MBED :
+\begin{verbatim}
+$ cp ./bin/mbed_ethernet/smews.bin /media/MBED/ && sync
+\end{verbatim}
+
+From now on, Smews is able to deploy new applications with no need to rebuild the Smews image.
+
+\section{Building your own elf application}
+
+Building an elf application uploadable to Smews is nothing more complicated than the regular process.
+For example, to build the connections stats application :
+\begin{verbatim}
+$ scons target=mbed_ethernet apps=constat:connectionsStats dynApp=1
+\end{verbatim}
+
+The \verb+dynApp+ option tells SCons to build an uploadable elf file, and the result will be outputted into \verb+bin/mbed_ethernet+ directory.
+
+Though not used here, programmers can handle several application lifecycle steps by declaring XML metadata either in a separate C file and/or directly into their applications.
+\begin{itemize}
+\item \verb+install+ -- function executed during application installation;
+\item \verb+remove+ -- function executed when an application is removed;
+\end{itemize}
+
+The XML metadata should look as the following, and be declared into one single file, or as many times needed into applications' files :
+\begin{lstlisting}
+/*
+
+
+
+ */
+\end{lstlisting}
+
+\section{Uploading elf applications.}
+Open up your browser and enter the Smews' ip; a Post form should appear. Then, select the \verb+*.o+ file into \verb+bin/mbed_ethernet+ folder and press the submit button.
+\begin{center}
+\includegraphics[width=15cm]{elf_screenshot}
+\end{center}
+
+
+
+Wait until the process completion, then finally, to access to the newly deployed application, open a new tab and enter the application URL as in the application SCons command line, here \url{http://192.168.100.2/constat/}
+
+\section{Summary}
+ To deploy applications onto Smews for an MBED device :
+\begin{itemize}
+\item 1) Prepare a Smews image : \begin{verbatim} $ scons target=mbed_ethernet apps=:elfloader ipaddr=192.168.100.2\end{verbatim}
+\item 2) Flash it down to the device : \begin{verbatim}$ cp ./bin/mbed_ethernet/smews.bin /media/MBED/ && sync\end{verbatim}
+\item 3) Build your elf application : \begin{verbatim}$ scons target=mbed_ethernet apps=constat:connectionsStats dynApp=1\end{verbatim}
+\item 4) Open your browser and enter the Smews' ip address, here \url{http://192.168.100.2}.
+\item 5) Choose the \verb+*.o+ file into \verb+bin/mbed_ethernet+ directory, then press the Submit button. Wait until the process completes.
+\item 6) Enter in a new tab the application's url. Here, \url{http://192.168.100.2/constat/}
+\end{itemize}
+
+ To add a new application, start again at step 3).
\chapter{Credits}
diff --git a/targets/linux/drivers/target.h b/targets/linux/drivers/target.h
index 34fe141..90cc181 100644
--- a/targets/linux/drivers/target.h
+++ b/targets/linux/drivers/target.h
@@ -107,6 +107,14 @@ extern fd_set fdset;
#define CONST_WRITE_NBYTES(dst,src,len) memcpy(dst,src,len)
+/* Application */
+#define APPLICATION_READ_UI8(x) CONST_READ_UI8(x)
+#define APPLICATION_READ_UI16(x) CONST_READ_UI16(x)
+#define APPLICATION_READ_UI32(x) CONST_READ_UI32(x)
+#define APPLICATION_READ_ADDR(x) CONST_READ_ADDR(x)
+
+#define APPLICATION_WRITE(dst, src, len) CONST_WRITE_NBYTES(dst,src,len)
+
/* Endianness */
#define ENDIANNESS LITTLE_ENDIAN
diff --git a/targets/mbed_ethernet/SConscript b/targets/mbed_ethernet/SConscript
index 4f6592a..d176ce8 100644
--- a/targets/mbed_ethernet/SConscript
+++ b/targets/mbed_ethernet/SConscript
@@ -35,7 +35,6 @@
import os
import sys,subprocess
-
def check_output(args):
str = ""
try:
@@ -58,7 +57,7 @@ def execute(args):
except OSError as e:
sys.stderr.write("failed to execute process: {}\n".format(args))
-Import('env binDir projectName elfName targetDir')
+Import('env binDir projectName elfName targetDir dynApp')
# Clone rflpc if needed
@@ -71,6 +70,7 @@ cflags = check_output(args)
args[1] = '--ldflags'
ldflags = check_output(args)
+ldflags = ("-L" + os.path.join(targetDir) + " " + ldflags).replace("rflpc17xx.ld", "smews.ld")
args[1] = '--lib'
lib = check_output(args)
@@ -79,11 +79,13 @@ env.Replace(CC = 'arm-none-eabi-gcc')
env.Replace(AS = 'arm-none-eabi-as')
env.Replace(AR = 'arm-none-eabi-ar')
env.Replace(RANLIB = 'arm-none-eabi-ranlib')
+env.Replace(LINK = 'arm-none-eabi-ld')
env.Append(CCFLAGS = cflags)
env.Append(CCFLAGS = '-DENABLE_LL_CACHE')
env.Append(CCFLAGS = '-DMBED_USE_LCD_DISPLAY')
env.Append(LIBS = lib)
env.Append(LINKFLAGS = ldflags)
-binaryName = projectName + '.bin'
-env.Command(binaryName, elfName, ['arm-none-eabi-objcopy -O binary -j .text -j .data $SOURCE $TARGET'])
+if not dynApp :
+ binaryName = projectName + '.bin'
+ env.Command(binaryName, elfName, ['arm-none-eabi-objcopy -O binary -j .text -j .data $SOURCE $TARGET'])
diff --git a/targets/mbed_ethernet/drivers/hardware.c b/targets/mbed_ethernet/drivers/hardware.c
index bab92e8..16eacc6 100644
--- a/targets/mbed_ethernet/drivers/hardware.c
+++ b/targets/mbed_ethernet/drivers/hardware.c
@@ -261,6 +261,8 @@ void mbed_print_configuration(void)
printf("\r\n");
}
+extern char _stack_end;
+
void mbed_print_motd(void)
{
printf("\r\n ______\r\n");
diff --git a/targets/mbed_ethernet/drivers/target.h b/targets/mbed_ethernet/drivers/target.h
index 0379851..89e046e 100644
--- a/targets/mbed_ethernet/drivers/target.h
+++ b/targets/mbed_ethernet/drivers/target.h
@@ -120,6 +120,18 @@
/* Writes len bytes from src to dst, where dst targets a persistent variable */
#define CONST_WRITE_NBYTES(dst,src,len)
+/* Application */
+/* Gets a byte from address x */
+#define APPLICATION_READ_UI8(x) CONST_READ_UI8(x)
+/* Gets two bytes from address x */
+#define APPLICATION_READ_UI16(x) CONST_READ_UI16(x)
+/* Gets four bytes from address x */
+#define APPLICATION_READ_UI32(x) CONST_READ_UI32(x)
+/* Gets an address from address x */
+#define APPLICATION_READ_ADDR(x) CONST_READ_ADDR(x)
+
+#define APPLICATION_WRITE(dst, src, len) rflpc_iap_write_buffer(dst, src, len)
+
/* Endianness: define ENDIANNESS as LITTLE_ENDIAN or BIG_ENDIAN */
#ifndef ENDIANNESS
#define ENDIANNESS LITTLE_ENDIAN
diff --git a/targets/mbed_ethernet/smews.ld b/targets/mbed_ethernet/smews.ld
new file mode 100644
index 0000000..82456c2
--- /dev/null
+++ b/targets/mbed_ethernet/smews.ld
@@ -0,0 +1,121 @@
+/* This file is part of rflpc. Copyright 2010-2011 Michael Hauspie
+ *
+ * rflpc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * rflpc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with rflpc. If not, see .
+ */
+
+/*
+ Linker script for lpc1768 mbed platform (http://www.mbed.org).
+
+ Author: Michael Hauspie
+ Created: Nov. 12 2010
+ Time-stamp: <2011-09-28 10:11:51 (mickey)>
+*/
+
+/* output format of the file.
+ default, big endian, little endian
+ Arm cortex M3 is little endian so use that as default
+*/
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+/* Architecture, obviously arm */
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+
+/* Memory map, give names and properties to the mbed different memories */
+MEMORY
+{
+ /* Flash: starting at 0x00000000 512kB available.
+ rx stands for read only executable.
+ Writing to flash must use algorithms included in boot rom so read
+ only from ld point of view
+ */
+ flash(rx) : ORIGIN = 0, LENGTH = 512K
+/* on chip sram: starting at 0x10000000, 32kB available */
+ ram(rwx): ORIGIN = 0x10000000, LENGTH = 32K
+/* outside chip sram (accessible via AHB matrix: starting at 0x2007C000, 32kB available */
+ out_ram(rwx): ORIGIN = 0x2007C000, LENGTH = 32K
+}
+
+
+SECTIONS
+{
+ /* .text sections starts at address 0 */
+ . = 0x0;
+ /* output .text section is the concatenation of all .text section of all object files
+ However, the special sections defined in init.c which contains interrupt vector
+ need to be put first
+ */
+ .text : {
+ /* The interrupt vector will be remapped in RAM so that it can be easily modified
+ and the one in flash will be copied at startup before performing the actual remap
+ by modifying the VTOR register (p. 75, user manual)
+ */
+ _interrupt_start = .;
+ *(.interrupt_vector) ;
+ _interrupt_end = .;
+
+ . = 0x10000;
+
+ *(.text*) ;
+ /* Constant data is also put in flash */
+ *(.rodata*) ;
+ _persistent_data_start = .;
+ *(.persistent_data);
+ _persistent_data_end = .;
+ }
+ /* this declares a global constant which contains the address of the end of section text.
+ This will be used by the startup code to copy data from flash to ram */
+ _text_end = .;
+
+ /* This will enforce the relocated interrupt vector to be located at the start of the RAM */
+ .relocated_interrupt_vector(NOLOAD) : {
+ *(.ram_int_vector);
+ } > ram
+
+ /* bss has to be located in ram */
+ .bss (NOLOAD): {
+ /* stores the start address of the bss so that the startup code can 0 it */
+ _bss_start = .;
+ _ram_start = .;
+ *(.bss*);
+ } > ram
+ /* stores the end address of the bss so that the startup code can 0 it */
+ _bss_end = .;
+
+
+ /* Data section is put in flash and will be copied in ram by startup script */
+
+ /* the > ram makes all the symbol referencing section .data to be relocated in
+ ram (i.e. addresses used in code are in ram) the AT>flash makes the section
+ to be located in flash. Thus, the startup script will just have to copy
+ the data section from flash to ram */
+
+ /* this declares a global constant _data_start which contains the address of
+ the section in ram */
+ .data : {
+ _data_start = .;
+ *(.data*) ;
+} > ram AT>flash
+ _data_end = .;
+ /* declares a global constant _data_end which contains the address of the end of the section in ram */
+
+
+
+ /* Stack must be located in ram*/
+ .stack(NOLOAD) : { *(.stack) } > ram
+
+
+
+ /* outram section must be located in out_ram */
+ .out_ram(NOLOAD) : { *(.out_ram) } > out_ram
+}
diff --git a/tools/GenApps.py b/tools/GenApps.py
index 83ca98b..138b323 100755
--- a/tools/GenApps.py
+++ b/tools/GenApps.py
@@ -192,6 +192,91 @@ def getAppFilesRec(appPath,path):
def getAppFiles(path):
return getAppFilesRec(path,path)
+def extractXMLElfApplicationLifeCycle(sourceFile, installList, removeList) :
+ # open the source file in order to parse the XML and return the file data
+ file = open(sourceFile,'r')
+ lines = file.readlines()
+ if len(lines) > 1:
+ fileData = reduce(lambda x,y: x + y,lines)
+ else:
+ fileData = ''
+ def start_element(name, attrs):
+ global elfInfos
+ if name == 'lifeCycle':
+ elfInfos = attrs
+ def end_element(name):
+ return
+ def char_data(data):
+ return
+
+ # select the XML part of the c file
+ xmlRoot = 'elf'
+ xmlData = fileData[fileData.rfind('<' + xmlRoot + '>'):]
+ xmlData = xmlData[:xmlData.rfind('' + xmlRoot + '>') + len(xmlRoot) + 3]
+ if len(xmlData) > 1:
+ global elfInfos
+ # init globals used for parsing
+ elfInfos = {}
+
+ # parse the XML
+ p = xml.parsers.expat.ParserCreate()
+ p.StartElementHandler = start_element
+ p.EndElementHandler = end_element
+ p.CharacterDataHandler = char_data
+ p.Parse(xmlData, 0)
+
+ if elfInfos.has_key('onInstall'):
+ installList.append(elfInfos['onInstall'])
+ if elfInfos.has_key('onRemove'):
+ removeList.append(elfInfos['onRemove'])
+
+def generateElfApplication(dstFile, installList, removeList) :
+ generatedHeader = '#include "elf_application.h"\n\n'
+ forwardDeclarations = ''
+ generatedDynApp = ''
+
+ #install
+ if(len(installList)>0):
+ for install in installList :
+ forwardDeclarations += 'extern elf_application_install_t ' + install + ';\n'
+ generatedDynApp += 'static elf_application_install_t elf_application_installs[] = {'
+ generatedDynApp += '&' + ',&'.join(installList) + ", NULL};\n\n"
+
+ #remove
+ if(len(removeList)>0):
+ for remove in removeList :
+ forwardDeclarations += 'extern elf_application_remove_t ' + remove + ';\n'
+ generatedDynApp += 'static elf_application_remove_t elf_application_removes[] = {'
+ generatedDynApp += '&' + ',&'.join(removeList) + ", NULL};\n\n"
+
+ # elf application environment
+
+ generatedDynApp += 'CONST_VAR(struct elf_application_environment_t const, elf_application_environment) = {\n'
+
+ forwardDeclarations += 'extern CONST_VAR(struct output_handler_t * const, resources_index[]);\n'
+ forwardDeclarations += 'extern CONST_VAR(unsigned char, urls_tree[]);\n'
+
+ if(len(installList)>0):
+ generatedDynApp += '\t.install = elf_application_installs,\n'
+ else :
+ generatedDynApp += '\t.install = NULL,\n'
+
+ if(len(removeList)>0):
+ generatedDynApp += '\t.remove = elf_application_removes,\n'
+ else :
+ generatedDynApp += '\t.remove = NULL,\n'
+
+ generatedDynApp += '\t.urls_tree = urls_tree,\n';
+ generatedDynApp += '\t.resources_index = resources_index,\n'
+ generatedDynApp = generatedHeader + forwardDeclarations + '\n' + generatedDynApp + '};\n'
+
+ cOut = open(dstFile,'w')
+ writeHeader(cOut, 0)
+ cOut.write(generatedDynApp)
+ cOut.close()
+
+
+
# Web resource type from original applicative file
def getResourceType(path):
if path.endswith('.c') or path.endswith('.h'):
@@ -310,7 +395,7 @@ def char_data(data):
if (controlByte == 128):
exit('Error: the file ' + srcFile + ' only defines a doPacketOut without a doPacketIn handler')
- exit('Error: the file ' + srcFile + 'has an incompatible decription (' +
+ exit('Error: the file ' + srcFile + 'has an incompatible description (' +
((controlByte & 1 == 1 and 'doGet,') or '') +
((controlByte & 2 == 2 and 'doPost,') or '') +
((controlByte & 4 == 4 and 'doPostIn,') or '') +
@@ -327,6 +412,13 @@ def char_data(data):
# initGet handler
if handlerInfos.has_key('initGet'):
dstFileInfos['initGet'] = handlerInfos['initGet']
+ # install handler
+ if handlerInfos.has_key('install'):
+ dstFileInfos['install'] = handlerInfos['install']
+ # shutdown handler
+ if handlerInfos.has_key('shutdown'):
+ dstFileInfos['shutdown'] = handlerInfos['shutdown']
+
# generator arguments
dstFileInfos['argsList'] = argsList
dstFileInfos['contentTypeList'] = contentTypeList
@@ -367,7 +459,7 @@ def generateResourceProps(srcFile,dstFileInfos):
pOut.close()
# launches a Web applicative resource file generation
-def generateResource(srcFile,dstFile,chuncksNbits,gzipped,dstFileInfos):
+def generateResource(srcFile,dstFile, chuncksNbits,gzipped,dstFileInfos):
if getResourceType(srcFile) == DynamicResource:
generateDynamicResource(srcFile,dstFile,dstFileInfos)
else:
@@ -415,6 +507,7 @@ def generateDynamicResource(srcFile,dstFile,dstFileInfos):
generatedOutputHandler += '#endif\n'
# output_handler structure creation
+# generatedOutputHandler += 'struct output_handler_t ' + cFuncName + ' = {\n'
generatedOutputHandler += 'CONST_VAR(struct output_handler_t, ' + cFuncName + ') = {\n'
# handler type
if dstFileInfos.has_key('doPacketIn'):
@@ -663,6 +756,7 @@ def generateStaticResource(srcFile,dstFile,chuncksNbits,gzipped):
# we fill the output handler structure
cOut.write('\n/********** File handler **********/\n')
+# cOut.write('struct output_handler_t ' + cName + '_handler = {\n')
cOut.write('CONST_VAR(struct output_handler_t, ' + cName + '_handler) = {\n')
cOut.write('\t.handler_type = type_file,\n'
+ '\t.handler_data = {\n'
@@ -703,6 +797,7 @@ def generateChannelsH(dstFile,propsFilesMap):
# for each channel: external structure declaration, macro for the channel name
if propsFilesMap[fileName]['channel'] != '':
cStructName = getCName(fileName[:fileName.rfind('.c')])
+# hOut.write('extern struct output_handler_t ' + cStructName + ';\n')
hOut.write('extern CONST_VAR(struct output_handler_t, ' + cStructName + ');\n')
hOut.write('#define ' + propsFilesMap[fileName]['channel'] + ' ' + cStructName + '\n')
hOut.write('\n#endif\n')
@@ -733,9 +828,11 @@ def generateIndex(dstDir,sourcesMap,target,chuncksNbits,appBase,propsFilesMap):
cOut.write('\n/********** External references **********/\n')
for fileName in staticFilesNames:
cName = getCName(fileName)
+# cOut.write('extern struct output_handler_t ' + cName + '_handler;\n')
cOut.write('extern CONST_VAR(struct output_handler_t, ' + cName + '_handler);\n')
for fileName in generatorFilesNames:
cFuncName = getCName(fileName[:fileName.rfind('.c')])
+# cOut.write('extern struct output_handler_t ' + cFuncName + ';\n')
cOut.write('extern CONST_VAR(struct output_handler_t, ' + cFuncName + ');\n')
# filesRef is a map used to associate URLs to output_handlers
@@ -788,7 +885,7 @@ def generateIndex(dstDir,sourcesMap,target,chuncksNbits,appBase,propsFilesMap):
# files index creation (table of ordered output_handlers)
cOut.write('\n/********** Files index **********/\n')
- cOut.write('CONST_VAR(const struct output_handler_t /*CONST_VAR*/ *, resources_index[]) = {\n')
+ cOut.write('CONST_VAR(struct output_handler_t /*CONST_VAR*/ * const, resources_index[]) = {\n')
# insert each handler
for file in filesList:
cOut.write('\t&' + filesRefs[file] + ',\n')
diff --git a/tools/mimeListPost b/tools/mimeListPost
index 7e39761..8f8b900 100644
--- a/tools/mimeListPost
+++ b/tools/mimeListPost
@@ -15,7 +15,7 @@
#application/mspowerpoint
#application/msword
#application/mswordf
-#application/octet-stream
+application/octet-stream
#application/oda
#application/pdf
#application/postscript
@@ -41,6 +41,7 @@ application/x-latex
#application/x-mif
#application/x-netcdf
#application/x-nschat
+application/x-object
application/x-sh
#application/x-shar
#application/x-shockwave-flash